diff --git a/.devcontainer/devcontainer-lock.json b/.devcontainer/devcontainer-lock.json new file mode 100644 index 000000000..cb770df4f --- /dev/null +++ b/.devcontainer/devcontainer-lock.json @@ -0,0 +1,14 @@ +{ + "features": { + "ghcr.io/devcontainers/features/git:1": { + "version": "1.3.5", + "resolved": "ghcr.io/devcontainers/features/git@sha256:27905dc196c01f77d6ba8709cb82eeaf330b3b108772e2f02d1cd0d826de1251", + "integrity": "sha256:27905dc196c01f77d6ba8709cb82eeaf330b3b108772e2f02d1cd0d826de1251" + }, + "ghcr.io/devcontainers/features/node:1": { + "version": "1.7.1", + "resolved": "ghcr.io/devcontainers/features/node@sha256:8c0de46939b61958041700ee89e3493f3b2e4131a06dc46b4d9423427d06e5f6", + "integrity": "sha256:8c0de46939b61958041700ee89e3493f3b2e4131a06dc46b4d9423427d06e5f6" + } + } +} diff --git a/package-lock.json b/package-lock.json index d772ac029..005606ebe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -80,255 +80,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@angular/common": { - "version": "20.3.19", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-20.3.19.tgz", - "integrity": "sha512-hcB1eUEN8LGcKGc4DlRJ+abS6AYfbEHDZKg8LnXNugkbwI6Ebyh2AUYTDhzZL2S4aH+C8biHKgSYHFCqieCRhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@angular/core": "20.3.19", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@angular/compiler": { - "version": "20.3.19", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-20.3.19.tgz", - "integrity": "sha512-ETkgDKm0l2PuaBubgPJe0ccy8kE75DFu6/zKcz7TUuk3KrKF2OZAopbbjftsUSZGeCNvCdqHzjmcL6hQ6oAOwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - } - }, - "node_modules/@angular/compiler-cli": { - "version": "20.3.19", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-20.3.19.tgz", - "integrity": "sha512-ET/JjO8s62kAHfgIsGXlvW5VUwLqHm03q1y/2yD7aQW/WdDvssMsvZv7Knl440989vdOFemIGTMwVPakmWqRmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "7.28.3", - "@jridgewell/sourcemap-codec": "^1.4.14", - "chokidar": "^4.0.0", - "convert-source-map": "^1.5.1", - "reflect-metadata": "^0.2.0", - "semver": "^7.0.0", - "tslib": "^2.3.0", - "yargs": "^18.0.0" - }, - "bin": { - "ng-xi18n": "bundles/src/bin/ng_xi18n.js", - "ngc": "bundles/src/bin/ngc.js" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@angular/compiler": "20.3.19", - "typescript": ">=5.8 <6.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz", - "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.3", - "@babel/parser": "^7.28.3", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.3", - "@babel/types": "^7.28.2", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@angular/compiler-cli/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular/compiler-cli/node_modules/cliui": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", - "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@angular/compiler-cli/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular/compiler-cli/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular/compiler-cli/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/@angular/compiler-cli/node_modules/yargs": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", - "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^9.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "string-width": "^7.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^22.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/@angular/compiler-cli/node_modules/yargs-parser": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", - "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/@angular/core": { - "version": "20.3.19", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-20.3.19.tgz", - "integrity": "sha512-SYnwW+q51bQoPtGFoGovm1P5GK9fMEXsG0lGaEAUapjskblAYyX7hLlM/jgueSojv2SjhqNF8aXR+gjHLhZVNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@angular/compiler": "20.3.19", - "rxjs": "^6.5.3 || ^7.4.0", - "zone.js": "~0.15.0" - }, - "peerDependenciesMeta": { - "@angular/compiler": { - "optional": true - }, - "zone.js": { - "optional": true - } - } - }, "node_modules/@apidevtools/json-schema-ref-parser": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", @@ -5236,6 +4987,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@lit/react/-/react-1.0.8.tgz", "integrity": "sha512-p2+YcF+JE67SRX3mMlJ1TKCSTsgyOVdAwd/nxp3NuV1+Cb6MWALbN6nT7Ld4tpmYofcE5kcaSY1YBB9erY+6fw==", + "dev": true, "license": "BSD-3-Clause", "peerDependencies": { "@types/react": "17 || 18 || 19" @@ -5866,329 +5618,6 @@ "node": ">= 0.6" } }, - "node_modules/@napi-rs/nice": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.1.1.tgz", - "integrity": "sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "optionalDependencies": { - "@napi-rs/nice-android-arm-eabi": "1.1.1", - "@napi-rs/nice-android-arm64": "1.1.1", - "@napi-rs/nice-darwin-arm64": "1.1.1", - "@napi-rs/nice-darwin-x64": "1.1.1", - "@napi-rs/nice-freebsd-x64": "1.1.1", - "@napi-rs/nice-linux-arm-gnueabihf": "1.1.1", - "@napi-rs/nice-linux-arm64-gnu": "1.1.1", - "@napi-rs/nice-linux-arm64-musl": "1.1.1", - "@napi-rs/nice-linux-ppc64-gnu": "1.1.1", - "@napi-rs/nice-linux-riscv64-gnu": "1.1.1", - "@napi-rs/nice-linux-s390x-gnu": "1.1.1", - "@napi-rs/nice-linux-x64-gnu": "1.1.1", - "@napi-rs/nice-linux-x64-musl": "1.1.1", - "@napi-rs/nice-openharmony-arm64": "1.1.1", - "@napi-rs/nice-win32-arm64-msvc": "1.1.1", - "@napi-rs/nice-win32-ia32-msvc": "1.1.1", - "@napi-rs/nice-win32-x64-msvc": "1.1.1" - } - }, - "node_modules/@napi-rs/nice-android-arm-eabi": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.1.1.tgz", - "integrity": "sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-android-arm64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.1.1.tgz", - "integrity": "sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-darwin-arm64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.1.1.tgz", - "integrity": "sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-darwin-x64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.1.1.tgz", - "integrity": "sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-freebsd-x64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.1.1.tgz", - "integrity": "sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-arm-gnueabihf": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.1.1.tgz", - "integrity": "sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-arm64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.1.1.tgz", - "integrity": "sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-arm64-musl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.1.1.tgz", - "integrity": "sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-ppc64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.1.1.tgz", - "integrity": "sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-riscv64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.1.1.tgz", - "integrity": "sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-s390x-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.1.1.tgz", - "integrity": "sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-x64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.1.1.tgz", - "integrity": "sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-x64-musl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.1.1.tgz", - "integrity": "sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-openharmony-arm64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-openharmony-arm64/-/nice-openharmony-arm64-1.1.1.tgz", - "integrity": "sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-win32-arm64-msvc": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.1.1.tgz", - "integrity": "sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-win32-ia32-msvc": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.1.1.tgz", - "integrity": "sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-win32-x64-msvc": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.1.1.tgz", - "integrity": "sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", @@ -6472,18 +5901,10 @@ "resolved": "packages/openbridge-webcomponents", "link": true }, - "node_modules/@oicl/openbridge-webcomponents-ng": { - "resolved": "packages/openbridge-webcomponents-ng", - "link": true - }, "node_modules/@oicl/openbridge-webcomponents-react": { "resolved": "packages/openbridge-webcomponents-react", "link": true }, - "node_modules/@oicl/openbridge-webcomponents-svelte": { - "resolved": "packages/openbridge-webcomponents-svelte", - "link": true - }, "node_modules/@oicl/openbridge-webcomponents-vue": { "resolved": "packages/openbridge-webcomponents-vue", "link": true @@ -6834,316 +6255,6 @@ "win32" ] }, - "node_modules/@parcel/watcher": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", - "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.3", - "is-glob": "^4.0.3", - "node-addon-api": "^7.0.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.6", - "@parcel/watcher-darwin-arm64": "2.5.6", - "@parcel/watcher-darwin-x64": "2.5.6", - "@parcel/watcher-freebsd-x64": "2.5.6", - "@parcel/watcher-linux-arm-glibc": "2.5.6", - "@parcel/watcher-linux-arm-musl": "2.5.6", - "@parcel/watcher-linux-arm64-glibc": "2.5.6", - "@parcel/watcher-linux-arm64-musl": "2.5.6", - "@parcel/watcher-linux-x64-glibc": "2.5.6", - "@parcel/watcher-linux-x64-musl": "2.5.6", - "@parcel/watcher-win32-arm64": "2.5.6", - "@parcel/watcher-win32-ia32": "2.5.6", - "@parcel/watcher-win32-x64": "2.5.6" - } - }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", - "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", - "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", - "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", - "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", - "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", - "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", - "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", - "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", - "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", - "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", - "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", - "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", - "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/@parse5/tools": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@parse5/tools/-/tools-0.3.0.tgz", @@ -7310,19 +6421,6 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", "license": "BSD-3-Clause" }, - "node_modules/@publint/pack": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@publint/pack/-/pack-0.1.4.tgz", - "integrity": "sha512-HDVTWq3H0uTXiU0eeSQntcVUTPP3GamzeXI41+x7uU9J65JgWQh3qWZHblR1i0npXfFtF+mxBiU2nJH8znxWnQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://bjornlu.com/sponsor" - } - }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-rc.3", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", @@ -7330,27 +6428,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@rollup/plugin-json": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", - "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.1.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, "node_modules/@rollup/plugin-node-resolve": { "version": "15.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz", @@ -7799,26 +6876,6 @@ "win32" ] }, - "node_modules/@rollup/wasm-node": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/wasm-node/-/wasm-node-4.60.3.tgz", - "integrity": "sha512-SVhQ4TJk0BvnJKwceVsCWHtmquucfjU0eu+Bonrjb6W3zombkA/tqw1efaqT2BONX/TJniqkzumF6Sz/sXMJ2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, "node_modules/@rushstack/node-core-library": { "version": "5.21.0", "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.21.0.tgz", @@ -9081,170 +8138,6 @@ "sourcemap-codec": "^1.4.8" } }, - "node_modules/@sveltejs/acorn-typescript": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.9.tgz", - "integrity": "sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^8.9.0" - } - }, - "node_modules/@sveltejs/adapter-auto": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-7.0.1.tgz", - "integrity": "sha512-dvuPm1E7M9NI/+canIQ6KKQDU2AkEefEZ2Dp7cY6uKoPq9Z/PhOXABe526UdW2mN986gjVkuSLkOYIBnS/M2LQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@sveltejs/kit": "^2.0.0" - } - }, - "node_modules/@sveltejs/kit": { - "version": "2.59.1", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.59.1.tgz", - "integrity": "sha512-d8OON70AphLdDesuTIl//M2O6fRTIicX8aYv8vhCiYEhTTI2OboKqey0Hu1A4VFhqwgqtq0vKDmPFGkw8kKmgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@sveltejs/acorn-typescript": "^1.0.5", - "@types/cookie": "^0.6.0", - "acorn": "^8.14.1", - "cookie": "^0.6.0", - "devalue": "^5.6.4", - "esm-env": "^1.2.2", - "kleur": "^4.1.5", - "magic-string": "^0.30.5", - "mrmime": "^2.0.0", - "set-cookie-parser": "^3.0.0", - "sirv": "^3.0.0" - }, - "bin": { - "svelte-kit": "svelte-kit.js" - }, - "engines": { - "node": ">=18.13" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0", - "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0", - "svelte": "^4.0.0 || ^5.0.0-next.0", - "typescript": "^5.3.3 || ^6.0.0", - "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/@sveltejs/kit/node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@sveltejs/package": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/@sveltejs/package/-/package-2.5.7.tgz", - "integrity": "sha512-qqD9xa9H7TDiGFrF6rz7AirOR8k15qDK/9i4MIE8te4vWsv5GEogPks61rrZcLy+yWph+aI6pIj2MdoK3YI8AQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^5.0.0", - "kleur": "^4.1.5", - "sade": "^1.8.1", - "semver": "^7.5.4", - "svelte2tsx": "~0.7.33" - }, - "bin": { - "svelte-package": "svelte-package.js" - }, - "engines": { - "node": "^16.14 || >=18" - }, - "peerDependencies": { - "svelte": "^3.44.0 || ^4.0.0 || ^5.0.0-next.1" - } - }, - "node_modules/@sveltejs/package/node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@sveltejs/package/node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-6.2.4.tgz", - "integrity": "sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", - "deepmerge": "^4.3.1", - "magic-string": "^0.30.21", - "obug": "^2.1.0", - "vitefu": "^1.1.1" - }, - "engines": { - "node": "^20.19 || ^22.12 || >=24" - }, - "peerDependencies": { - "svelte": "^5.0.0", - "vite": "^6.3.0 || ^7.0.0" - } - }, - "node_modules/@sveltejs/vite-plugin-svelte-inspector": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-5.0.2.tgz", - "integrity": "sha512-TZzRTcEtZffICSAoZGkPSl6Etsj2torOVrx6Uw0KpXxrec9Gg6jFWQ60Q3+LmNGfZSxHRCZL7vXVZIWmuV50Ig==", - "dev": true, - "license": "MIT", - "dependencies": { - "obug": "^2.1.0" - }, - "engines": { - "node": "^20.19 || ^22.12 || >=24" - }, - "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", - "svelte": "^5.0.0", - "vite": "^6.3.0 || ^7.0.0" - } - }, "node_modules/@testing-library/dom": { "version": "10.4.1", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", @@ -9490,13 +8383,6 @@ "assertion-error": "^2.0.1" } }, - "node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/deep-eql": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", @@ -9646,12 +8532,14 @@ "version": "15.7.15", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "dev": true, "license": "MIT" }, "node_modules/@types/react": { "version": "18.3.28", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", + "dev": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -11192,16 +10080,6 @@ "node": ">=8" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-escapes": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", @@ -11672,16 +10550,6 @@ "node": ">=10" } }, - "node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.17", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", @@ -13122,16 +11990,6 @@ "node": ">=0.8" } }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/color": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", @@ -13375,13 +12233,6 @@ "node": ">= 12.0.0" } }, - "node_modules/common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true, - "license": "ISC" - }, "node_modules/common-tags": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", @@ -14160,13 +13011,6 @@ } } }, - "node_modules/dedent-js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz", - "integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==", - "dev": true, - "license": "MIT" - }, "node_modules/deep-eql": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", @@ -14379,24 +13223,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/devalue": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.8.0.tgz", - "integrity": "sha512-2zA9pFEsnp7vWBZbXF5JAgAq0fsUIt/1XPbRiAmRV3lp/2C3upzH+sADiyy66aFCihoLEsrQHxNM5w1gIDfsBg==", - "dev": true, - "license": "MIT" - }, "node_modules/didyoumean2": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/didyoumean2/-/didyoumean2-7.0.4.tgz", @@ -14904,20 +13730,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, "node_modules/error-ex": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", @@ -15448,13 +14260,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/esm-env": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", - "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", - "dev": true, - "license": "MIT" - }, "node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -15513,24 +14318,6 @@ "node": ">=0.10" } }, - "node_modules/esrap": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.6.tgz", - "integrity": "sha512-WN0clHt0a4mzC780UBVVBpsj4vSSjOFNRd2WjYtduB9HeKxm1sjHMNUwLEHVjI3FdCQD/Hurgz9ftbKEzP79Ow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "peerDependencies": { - "@typescript-eslint/types": "^8.2.0" - }, - "peerDependenciesMeta": { - "@typescript-eslint/types": { - "optional": true - } - } - }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -16342,23 +15129,6 @@ "dev": true, "license": "MIT" }, - "node_modules/find-cache-directory": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/find-cache-directory/-/find-cache-directory-6.0.0.tgz", - "integrity": "sha512-CvFd5ivA6HcSHbD+59P7CyzINHXzwhuQK8RY7CxJZtgDSAtRlHiCaQpZQ2lMR/WRyUIEmzUvL6G2AGurMfegZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "common-path-prefix": "^3.0.0", - "pkg-dir": "^8.0.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/find-replace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", @@ -18346,27 +17116,6 @@ "dev": true, "license": "ISC" }, - "node_modules/image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", - "dev": true, - "license": "MIT", - "optional": true, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/immutable": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", - "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", - "dev": true, - "license": "MIT" - }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -18473,16 +17222,6 @@ "dev": true, "license": "ISC" }, - "node_modules/injection-js": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/injection-js/-/injection-js-2.6.1.tgz", - "integrity": "sha512-dbR5bdhi7TWDoCye9cByZqeg/gAfamm8Vu3G1KZOTYkOif8WkuM8CD0oeDPtZYMzT5YH76JAFB7bkmyY9OJi2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - } - }, "node_modules/install-artifact-from-github": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/install-artifact-from-github/-/install-artifact-from-github-1.4.0.tgz", @@ -19017,16 +17756,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-reference": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", - "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.6" - } - }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -20221,13 +18950,6 @@ "node": ">=6" } }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true, - "license": "MIT" - }, "node_modules/jsonfile": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", @@ -20336,16 +19058,6 @@ "node": ">=0.10.0" } }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/kolorist": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", @@ -20419,112 +19131,6 @@ "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", "license": "BSD-2-Clause" }, - "node_modules/less": { - "version": "4.6.4", - "resolved": "https://registry.npmjs.org/less/-/less-4.6.4.tgz", - "integrity": "sha512-OJmO5+HxZLLw0RLzkqaNHzcgEAQG7C0y3aMbwtCzIUFZsLMNNq/1IdAdHEycQ58CwUO3jPTHmoN+tE5I7FQxNg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "copy-anything": "^3.0.5", - "parse-node-version": "^1.0.1" - }, - "bin": { - "lessc": "bin/lessc" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "source-map": "~0.6.0" - } - }, - "node_modules/less/node_modules/copy-anything": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", - "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-what": "^4.1.8" - }, - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/less/node_modules/is-what": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", - "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/less/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/less/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "license": "MIT", - "optional": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/less/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/less/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "optional": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -20884,13 +19490,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/locate-character": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", - "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", - "dev": true, - "license": "MIT" - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -22003,16 +20602,6 @@ "mpd-to-m3u8-json": "bin/parse.js" } }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", @@ -22241,38 +20830,6 @@ "dev": true, "license": "MIT" }, - "node_modules/needle": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.5.0.tgz", - "integrity": "sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 4.4.x" - } - }, - "node_modules/needle/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -22307,700 +20864,6 @@ "node": ">= 0.4.0" } }, - "node_modules/ng-packagr": { - "version": "20.3.2", - "resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-20.3.2.tgz", - "integrity": "sha512-yW5ME0hqTz38r/th/7zVwX5oSIw1FviSA2PUlGZdVjghDme/KX6iiwmOBmlt9E9whNmwijEC6Gn3KKbrsBx8ig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@rollup/plugin-json": "^6.1.0", - "@rollup/wasm-node": "^4.24.0", - "ajv": "^8.17.1", - "ansi-colors": "^4.1.3", - "browserslist": "^4.22.1", - "chokidar": "^4.0.1", - "commander": "^14.0.0", - "dependency-graph": "^1.0.0", - "esbuild": "^0.25.0", - "find-cache-directory": "^6.0.0", - "injection-js": "^2.4.0", - "jsonc-parser": "^3.3.1", - "less": "^4.2.0", - "ora": "^8.2.0", - "piscina": "^5.0.0", - "postcss": "^8.4.47", - "rollup-plugin-dts": "^6.2.0", - "rxjs": "^7.8.1", - "sass": "^1.81.0", - "tinyglobby": "^0.2.12" - }, - "bin": { - "ng-packagr": "src/cli/main.js" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "optionalDependencies": { - "rollup": "^4.24.0" - }, - "peerDependencies": { - "@angular/compiler-cli": "^20.0.0", - "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", - "tslib": "^2.3.0", - "typescript": ">=5.8 <6.0" - }, - "peerDependenciesMeta": { - "tailwindcss": { - "optional": true - } - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/ng-packagr/node_modules/ajv": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", - "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ng-packagr/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/ng-packagr/node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "node_modules/ng-packagr/node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ng-packagr/node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ng-packagr/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/ng-packagr/node_modules/log-symbols": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", - "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "is-unicode-supported": "^1.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ng-packagr/node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ng-packagr/node_modules/ora": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", - "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "cli-cursor": "^5.0.0", - "cli-spinners": "^2.9.2", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.0.0", - "log-symbols": "^6.0.0", - "stdin-discarder": "^0.2.2", - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ng-packagr/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/ng-packagr/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/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -26013,13 +23876,6 @@ "dev": true, "license": "MIT" }, - "node_modules/package-manager-detector": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", - "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", - "dev": true, - "license": "MIT" - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -26077,16 +23933,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, "node_modules/parse5": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", @@ -26452,19 +24298,6 @@ "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", "license": "MIT" }, - "node_modules/piscina": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.1.4.tgz", - "integrity": "sha512-7uU4ZnKeQq22t9AsmHGD2w4OYQGonwFnTypDypaWi7Qr2EvQIFVtG8J5D/3bE7W123Wdc9+v4CZDu5hJXVCtBg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.x" - }, - "optionalDependencies": { - "@napi-rs/nice": "^1.0.4" - } - }, "node_modules/pixelmatch": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.3.0.tgz", @@ -26587,22 +24420,6 @@ "node": ">=4" } }, - "node_modules/pkg-dir": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-8.0.0.tgz", - "integrity": "sha512-4peoBq4Wks0riS0z8741NVv+/8IiTvqnZAr8QGgtdifrtpdXbNw/FxRS1l6NFqm4EMzuS0EDqNNx4XGaz8cuyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up-simple": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/pkg-types": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", @@ -27070,17 +24887,6 @@ "node": ">=6.0.0" } }, - "node_modules/prettier-plugin-svelte": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.5.1.tgz", - "integrity": "sha512-65+fr5+cgIKWKiqM1Doum4uX6bY8iFCdztvvp2RcF+AJoieaw9kJOFMNcJo/bkmKYsxFaM9OsVZK/gWauG/5mg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "prettier": "^3.0.0", - "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" - } - }, "node_modules/pretty-bytes": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", @@ -27314,14 +25120,6 @@ "dev": true, "license": "MIT" }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -27329,28 +25127,6 @@ "dev": true, "license": "MIT" }, - "node_modules/publint": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/publint/-/publint-0.3.18.tgz", - "integrity": "sha512-JRJFeBTrfx4qLwEuGFPk+haJOJN97KnPuK01yj+4k/Wj5BgoOK5uNsivporiqBjk2JDaslg7qJOhGRnpltGeog==", - "dev": true, - "license": "MIT", - "dependencies": { - "@publint/pack": "^0.1.4", - "package-manager-detector": "^1.6.0", - "picocolors": "^1.1.1", - "sade": "^1.8.1" - }, - "bin": { - "publint": "src/cli.js" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://bjornlu.com/sponsor" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -27887,13 +25663,6 @@ "node": ">=6" } }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -28299,32 +26068,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/rollup-plugin-dts": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.4.1.tgz", - "integrity": "sha512-l//F3Zf7ID5GoOfLfD8kroBjQKEKpy1qfhtAdnpibFZMffPaylrg1CoDC2vGkPeTeyxUe4bVFCln2EFuL7IGGg==", - "dev": true, - "license": "LGPL-3.0-only", - "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "@jridgewell/sourcemap-codec": "^1.5.5", - "convert-source-map": "^2.0.0", - "magic-string": "^0.30.21" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/Swatinem" - }, - "optionalDependencies": { - "@babel/code-frame": "^7.29.0" - }, - "peerDependencies": { - "rollup": "^3.29.4 || ^4", - "typescript": "^4.5 || ^5.0 || ^6.0" - } - }, "node_modules/rollup-plugin-postcss-lit": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/rollup-plugin-postcss-lit/-/rollup-plugin-postcss-lit-2.2.0.tgz", @@ -28429,29 +26172,6 @@ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", "license": "BSD-3-Clause" }, - "node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/sade": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "mri": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/safe-array-concat": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", @@ -28544,68 +26264,6 @@ "dev": true, "license": "MIT" }, - "node_modules/sass": { - "version": "1.99.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.99.0.tgz", - "integrity": "sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.1.5", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" - } - }, - "node_modules/sass/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/sass/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/sax": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", - "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", - "dev": true, - "license": "BlueOak-1.0.0", - "optional": true, - "engines": { - "node": ">=11.0.0" - } - }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -29172,13 +26830,6 @@ "node": ">= 0.8.0" } }, - "node_modules/set-cookie-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.1.0.tgz", - "integrity": "sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==", - "dev": true, - "license": "MIT" - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -29804,19 +27455,6 @@ "dev": true, "license": "MIT" }, - "node_modules/stdin-discarder": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", - "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/stop-iteration-iterator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", @@ -30535,113 +28173,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/svelte": { - "version": "5.55.5", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.55.5.tgz", - "integrity": "sha512-2uCs/LZ9us+AktdzYJM8OcxQ8qnPS1kpaO7syGT/MgO+6Qr1Ybl+TqPq+97u7PHqmmMlye5ZkoyXONy5mjjAbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.4", - "@jridgewell/sourcemap-codec": "^1.5.0", - "@sveltejs/acorn-typescript": "^1.0.5", - "@types/estree": "^1.0.5", - "@types/trusted-types": "^2.0.7", - "acorn": "^8.12.1", - "aria-query": "5.3.1", - "axobject-query": "^4.1.0", - "clsx": "^2.1.1", - "devalue": "^5.6.4", - "esm-env": "^1.2.1", - "esrap": "^2.2.4", - "is-reference": "^3.0.3", - "locate-character": "^3.0.0", - "magic-string": "^0.30.11", - "zimmerframe": "^1.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/svelte-check": { - "version": "4.4.8", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.4.8.tgz", - "integrity": "sha512-67adfgBox5eNSNIvIIwgFizKGdcRrGpiMoNO2obHcYuLz7iTa8Xgm/NGU3ntMFnNm8K1grFOIG6HhMLX/vcN8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "chokidar": "^4.0.1", - "fdir": "^6.2.0", - "picocolors": "^1.0.0", - "sade": "^1.7.4" - }, - "bin": { - "svelte-check": "bin/svelte-check" - }, - "engines": { - "node": ">= 18.0.0" - }, - "peerDependencies": { - "svelte": "^4.0.0 || ^5.0.0-next.0", - "typescript": ">=5.0.0" - } - }, - "node_modules/svelte-check/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/svelte-check/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/svelte/node_modules/aria-query": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz", - "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/svelte2tsx": { - "version": "0.7.55", - "resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.7.55.tgz", - "integrity": "sha512-JWzgeM3lqySRNfqcsesvVEh8LhTWBxQJ9RMjzJ+VepdmXtVnNd0SbtGctG6+/fbHq0N6mhwSd823gszw9JHeGQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "dedent-js": "^1.0.1", - "scule": "^1.3.0" - }, - "peerDependencies": { - "svelte": "^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0", - "typescript": "^4.9.4 || ^5.0.0 || ^6.0.0" - } - }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -32377,26 +29908,6 @@ } } }, - "node_modules/vitefu": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz", - "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==", - "dev": true, - "license": "MIT", - "workspaces": [ - "tests/deps/*", - "tests/projects/*", - "tests/projects/workspace/packages/*" - ], - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } - } - }, "node_modules/vitest": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.0.tgz", @@ -34288,13 +31799,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/zimmerframe": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz", - "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==", - "dev": true, - "license": "MIT" - }, "node_modules/zip-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", @@ -34426,6 +31930,7 @@ "packages/openbridge-webcomponents-ng": { "name": "@oicl/openbridge-webcomponents-ng", "version": "2.0.0-next.29", + "extraneous": true, "license": "Apache-2.0", "dependencies": { "@oicl/openbridge-webcomponents": "^2.0.0-next.28", @@ -34444,23 +31949,10 @@ "@angular/core": "^20.0.1" } }, - "packages/openbridge-webcomponents-ng/node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "packages/openbridge-webcomponents-react": { "name": "@oicl/openbridge-webcomponents-react", "version": "2.0.0-next.29", + "dev": true, "license": "Apache-2.0", "dependencies": { "@lit/react": "^1.0.0", @@ -34477,6 +31969,7 @@ "packages/openbridge-webcomponents-svelte": { "name": "@oicl/openbridge-webcomponents-svelte", "version": "2.0.0-next.29", + "extraneous": true, "license": "Apache-2.0", "dependencies": { "@oicl/openbridge-webcomponents": "^2.0.0-next.28" diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/bars-graphs/area-graph/area-graph.stories.ts/no-labels-ticks-area-graph--but-yes-32px-padding-for-optional-points--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/bars-graphs/area-graph/area-graph.stories.ts/no-labels-ticks-area-graph--but-yes-32px-padding-for-optional-points--auto.png deleted file mode 100644 index 351c8f15d..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/bars-graphs/area-graph/area-graph.stories.ts/no-labels-ticks-area-graph--but-yes-32px-padding-for-optional-points--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/bars-graphs/line-graph/line-graph.stories.ts/no-labels-ticks-line-graph--but-yes-32px-padding-for-optional-points--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/bars-graphs/line-graph/line-graph.stories.ts/no-labels-ticks-line-graph--but-yes-32px-padding-for-optional-points--auto.png deleted file mode 100644 index 5c994e9b2..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/bars-graphs/line-graph/line-graph.stories.ts/no-labels-ticks-line-graph--but-yes-32px-padding-for-optional-points--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/bar-horizontal/bar-horizontal.stories.ts/chart-integration--as-external-bottom-axis--scalebackground--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/bar-horizontal/bar-horizontal.stories.ts/chart-integration--as-external-bottom-axis--scalebackground--auto.png deleted file mode 100644 index 1fae2ddc7..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/bar-horizontal/bar-horizontal.stories.ts/chart-integration--as-external-bottom-axis--scalebackground--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/bar-horizontal/bar-horizontal.stories.ts/component-size-comparison--regular-medium-large-xl--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/bar-horizontal/bar-horizontal.stories.ts/component-size-comparison--regular-medium-large-xl--auto.png deleted file mode 100644 index bca526b31..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/bar-horizontal/bar-horizontal.stories.ts/component-size-comparison--regular-medium-large-xl--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/bar-horizontal/bar-horizontal.stories.ts/state-comparison--incommand-active-loading-off-focus--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/bar-horizontal/bar-horizontal.stories.ts/state-comparison--incommand-active-loading-off-focus--auto.png deleted file mode 100644 index b10bfd9e9..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/bar-horizontal/bar-horizontal.stories.ts/state-comparison--incommand-active-loading-off-focus--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/bar-vertical/bar-vertical.stories.ts/chart-integration--as-external-right-axis--scalebackground--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/bar-vertical/bar-vertical.stories.ts/chart-integration--as-external-right-axis--scalebackground--auto.png deleted file mode 100644 index cc73c464b..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/bar-vertical/bar-vertical.stories.ts/chart-integration--as-external-right-axis--scalebackground--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/chart-line/chart-line-base.stories.ts/no-labels-ticks-line-graph--but-yes-32px-padding-for-optional-points--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/chart-line/chart-line-base.stories.ts/no-labels-ticks-line-graph--but-yes-32px-padding-for-optional-points--auto.png deleted file mode 100644 index 351c8f15d..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/chart-line/chart-line-base.stories.ts/no-labels-ticks-line-graph--but-yes-32px-padding-for-optional-points--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/chart-line/chart-line-base.stories.ts/threshold-height-line-graph--192px--where-labels-appear--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/chart-line/chart-line-base.stories.ts/threshold-height-line-graph--192px--where-labels-appear--auto.png deleted file mode 100644 index 9a8b0b210..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/chart-line/chart-line-base.stories.ts/threshold-height-line-graph--192px--where-labels-appear--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/external-scale/external-scale.stories.ts/horizontal--bottom-side--hasbar--advices--setpoint--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/external-scale/external-scale.stories.ts/horizontal--bottom-side--hasbar--advices--setpoint--auto.png deleted file mode 100644 index 2728284ea..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/external-scale/external-scale.stories.ts/horizontal--bottom-side--hasbar--advices--setpoint--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/external-scale/external-scale.stories.ts/horizontal--top-side--hasbar--advices--setpoint--fillmode-tint--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/external-scale/external-scale.stories.ts/horizontal--top-side--hasbar--advices--setpoint--fillmode-tint--auto.png deleted file mode 100644 index 03b79bfd3..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/external-scale/external-scale.stories.ts/horizontal--top-side--hasbar--advices--setpoint--fillmode-tint--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/external-scale/external-scale.stories.ts/vertical--left-side--hasbar--advices--setpoint--fillmode-tint--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/external-scale/external-scale.stories.ts/vertical--left-side--hasbar--advices--setpoint--fillmode-tint--auto.png deleted file mode 100644 index f5acc0444..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/building-blocks/external-scale/external-scale.stories.ts/vertical--left-side--hasbar--advices--setpoint--fillmode-tint--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/automation-button-readout-stack/automation-button-readout-stack.stories.ts/mixed-value-and-button-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/automation-button-readout-stack/automation-button-readout-stack.stories.ts/mixed-value-and-button-auto.png deleted file mode 100644 index db35b47a1..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/automation-button-readout-stack/automation-button-readout-stack.stories.ts/mixed-value-and-button-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/automation-button-readout-stack/automation-button-readout-stack.stories.ts/mixed-value-and-state-off-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/automation-button-readout-stack/automation-button-readout-stack.stories.ts/mixed-value-and-state-off-auto.png deleted file mode 100644 index 72f85f98f..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/automation-button-readout-stack/automation-button-readout-stack.stories.ts/mixed-value-and-state-off-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/automation-button-readout-stack/automation-button-readout-stack.stories.ts/mixed-value-and-state-on-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/automation-button-readout-stack/automation-button-readout-stack.stories.ts/mixed-value-and-state-on-auto.png deleted file mode 100644 index 918204f6d..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/automation-button-readout-stack/automation-button-readout-stack.stories.ts/mixed-value-and-state-on-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/automation-button-readout-stack/automation-button-readout-stack.stories.ts/state-off-without-icon-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/automation-button-readout-stack/automation-button-readout-stack.stories.ts/state-off-without-icon-auto.png deleted file mode 100644 index cc721baf3..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/automation-button-readout-stack/automation-button-readout-stack.stories.ts/state-off-without-icon-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-horizontal-multi-application-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-horizontal-multi-application-auto.png deleted file mode 100644 index d102fe70f..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-horizontal-multi-application-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-horizontal-multi-regular-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-horizontal-multi-regular-auto.png deleted file mode 100644 index f629d4b76..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-horizontal-multi-regular-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-horizontal-single-application-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-horizontal-single-application-auto.png deleted file mode 100644 index d102fe70f..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-horizontal-single-application-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-horizontal-single-regular-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-horizontal-single-regular-auto.png deleted file mode 100644 index f629d4b76..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-horizontal-single-regular-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-vertical-multi-application-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-vertical-multi-application-auto.png deleted file mode 100644 index 372ca0cbe..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-vertical-multi-application-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-vertical-multi-regular-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-vertical-multi-regular-auto.png deleted file mode 100644 index 07c06308f..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-vertical-multi-regular-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-vertical-single-application-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-vertical-single-application-auto.png deleted file mode 100644 index dd6b35d22..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-vertical-single-application-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-vertical-single-regular-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-vertical-single-regular-auto.png deleted file mode 100644 index 9deefe16d..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/notification-floating-item/notification-floating-item.stories.ts/notification-vertical-single-regular-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/toggle-button-vertical-group/toggle-button-vertical-group.stories.ts/initially-disabled-selection-falls-back-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/toggle-button-vertical-group/toggle-button-vertical-group.stories.ts/initially-disabled-selection-falls-back-auto.png deleted file mode 100644 index 50e6f2fc7..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/toggle-button-vertical-group/toggle-button-vertical-group.stories.ts/initially-disabled-selection-falls-back-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/toggle-button-vertical-group/toggle-button-vertical-group.stories.ts/label-under-regular-disabled-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/toggle-button-vertical-group/toggle-button-vertical-group.stories.ts/label-under-regular-disabled-auto.png deleted file mode 100644 index f97d7ce1b..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/toggle-button-vertical-group/toggle-button-vertical-group.stories.ts/label-under-regular-disabled-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/topbar-message-item/topbar-message-item.stories.ts/large-with-long-text-and-description-and-both-timestamps-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/topbar-message-item/topbar-message-item.stories.ts/large-with-long-text-and-description-and-both-timestamps-auto.png deleted file mode 100644 index 4b89f9b0f..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/components/topbar-message-item/topbar-message-item.stories.ts/large-with-long-text-and-description-and-both-timestamps-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/azimuth-thruster/azimuth-thruster.stories.ts/in-command-at-setpoint-disable-auto-setpoint-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/azimuth-thruster/azimuth-thruster.stories.ts/in-command-at-setpoint-disable-auto-setpoint-auto.png deleted file mode 100644 index 0e8df0a68..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/azimuth-thruster/azimuth-thruster.stories.ts/in-command-at-setpoint-disable-auto-setpoint-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/component-size-comparison--regular-medium-large-xl--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/component-size-comparison--regular-medium-large-xl--auto.png deleted file mode 100644 index 1013d70f3..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/component-size-comparison--regular-medium-large-xl--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/fill-mode-comparison--enhanced--fill-vs-tint--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/fill-mode-comparison--enhanced--fill-vs-tint--auto.png deleted file mode 100644 index 25de8ce02..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/fill-mode-comparison--enhanced--fill-vs-tint--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/state-comparison--incommand-active-loading-off--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/state-comparison--incommand-active-loading-off--auto.png deleted file mode 100644 index 793d0231a..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/state-comparison--incommand-active-loading-off--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/state-comparison--incommand-active-loading-off-focus--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/state-comparison--incommand-active-loading-off-focus--auto.png deleted file mode 100644 index 7905c93b9..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/state-comparison--incommand-active-loading-off-focus--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/with-setpoint--value-away-from-setpoint--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/with-setpoint--value-away-from-setpoint--auto.png deleted file mode 100644 index 01b664a48..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-horizontal/gauge-horizontal.stories.ts/with-setpoint--value-away-from-setpoint--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/component-size-comparison--regular-medium-large-xl--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/component-size-comparison--regular-medium-large-xl--auto.png deleted file mode 100644 index 813a5badd..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/component-size-comparison--regular-medium-large-xl--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/enhanced-mode-comparison--regular-vs-enhanced--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/enhanced-mode-comparison--regular-vs-enhanced--auto.png deleted file mode 100644 index 1bdd00428..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/enhanced-mode-comparison--regular-vs-enhanced--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/fill-mode-comparison--enhanced--fill-vs-tint--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/fill-mode-comparison--enhanced--fill-vs-tint--auto.png deleted file mode 100644 index 045faefe8..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/fill-mode-comparison--enhanced--fill-vs-tint--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/state-comparison--incommand-active-loading-off--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/state-comparison--incommand-active-loading-off--auto.png deleted file mode 100644 index d5b34cc80..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/state-comparison--incommand-active-loading-off--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/state-comparison--incommand-active-loading-off-focus--auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/state-comparison--incommand-active-loading-off-focus--auto.png deleted file mode 100644 index 0e88469f9..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/gauge-vertical/gauge-vertical.stories.ts/state-comparison--incommand-active-loading-off-focus--auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/main-engine-indicator/propulsion-main-engine-indicator.stories.ts/in-command---silhouette-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/main-engine-indicator/propulsion-main-engine-indicator.stories.ts/in-command---silhouette-auto.png deleted file mode 100644 index f88708a18..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/main-engine-indicator/propulsion-main-engine-indicator.stories.ts/in-command---silhouette-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/main-engine-indicator/propulsion-main-engine-indicator.stories.ts/not-in-command---silhouette-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/main-engine-indicator/propulsion-main-engine-indicator.stories.ts/not-in-command---silhouette-auto.png deleted file mode 100644 index d635360bf..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/main-engine-indicator/propulsion-main-engine-indicator.stories.ts/not-in-command---silhouette-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/propulsion-tunnel-thruster/propulsion-tunnel-thruster.stories.ts/not-in-command---silhouette-auto.png b/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/propulsion-tunnel-thruster/propulsion-tunnel-thruster.stories.ts/not-in-command---silhouette-auto.png deleted file mode 100644 index 9e5b17e9c..000000000 Binary files a/packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/propulsion-tunnel-thruster/propulsion-tunnel-thruster.stories.ts/not-in-command---silhouette-auto.png and /dev/null differ diff --git a/packages/openbridge-webcomponents/oicl-openbridge-webcomponents-2.0.0-next.29.tgz b/packages/openbridge-webcomponents/oicl-openbridge-webcomponents-2.0.0-next.29.tgz new file mode 100644 index 000000000..ea1224e1a Binary files /dev/null and b/packages/openbridge-webcomponents/oicl-openbridge-webcomponents-2.0.0-next.29.tgz differ diff --git a/packages/openbridge-webcomponents/src/components/accordion-card/accordion-card.css b/packages/openbridge-webcomponents/src/components/accordion-card/accordion-card.css index 8d1ef3b5a..0851867f6 100644 --- a/packages/openbridge-webcomponents/src/components/accordion-card/accordion-card.css +++ b/packages/openbridge-webcomponents/src/components/accordion-card/accordion-card.css @@ -8,7 +8,7 @@ width: auto; flex-direction: column; align-items: center; - width: 320px; + width: 100%; .card-container { display: flex; @@ -117,7 +117,7 @@ flex: 1 0 0; align-self: stretch; height: 100%; - padding: 0 16px 16px 16px; + padding: 0 8px 8px 8px; } & .card-container { diff --git a/packages/openbridge-webcomponents/src/skipper/advice.ts b/packages/openbridge-webcomponents/src/skipper/advice.ts new file mode 100644 index 000000000..e8d8db2d9 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/advice.ts @@ -0,0 +1,195 @@ +import {SVGTemplateResult, nothing, svg} from 'lit'; +import { TickmarkStyle, TickmarkType, tickmark } from './tickmark'; + +export enum AdviceType { + advice = 'advice', + caution = 'caution', + warning = 'warning', + alarm = 'alarm' +} + +export enum AdviceState { + regular = 'regular', + hinted = 'hinted', + triggered = 'triggered', +} + +export interface AngleAdviceRaw { + minAngle: number; + maxAngle: number; + type: AdviceType; + state: AdviceState; + hideMinTickmark?: boolean; + hideMaxTickmark?: boolean; +} + +export interface AngleAdvice { + minAngle: number; + maxAngle: number; + type: AdviceType; + hinted: boolean; +} + +const margin = (344 - 328) / 2 + 8; +const deltaAngle = Math.atan2(margin, (344 + 328) / 2); + +export function adviceMask( + minAngle: number, + maxAngle: number, + fill: string, + stroke: string +): SVGTemplateResult { + const radl = (minAngle * Math.PI) / 180 + deltaAngle; + const radh = (maxAngle * Math.PI) / 180 - deltaAngle; + const r1 = 546 / 2; + const r2 = 572 / 2; + const R = (r2 - r1) / 2; + const x1l = Math.sin(radl) * r1; + const y1l = -Math.cos(radl) * r1; + const x2l = Math.sin(radl) * r2; + const y2l = -Math.cos(radl) * r2; + + const x1h = Math.sin(radh) * r1; + const y1h = -Math.cos(radh) * r1; + const x2h = Math.sin(radh) * r2; + const y2h = -Math.cos(radh) * r2; + + const path = `M ${x1l} ${y1l} + A ${r1} ${r1} 0 0 1 ${x1h} ${y1h} + A ${R} ${R} 0 0 0 ${x2h} ${y2h} + A ${r2} ${r2} 0 0 0 ${x2l} ${y2l} + A ${R} ${R} 0 0 0 ${x1l} ${y1l} + Z`; + return svg``; +} + +// mainColor = advice.type == AdviceType.caution ? 'var(--on-caution-active-color)' : advice.type == AdviceType.warning ? 'var(--on-warning-active-color)' : advice.type == AdviceType.alarm ? 'var(--on-alarm-active-color)' : ''; +// fillColor = advice.type == AdviceType.caution ? 'var(--on-caution-active-color)' : advice.type == AdviceType.warning ? 'var(--on-warning-active-color)' : advice.type == AdviceType.alarm ? 'var(--on-alarm-active-color)' : ''; + +export function renderAdvice(advice: AngleAdviceRaw): SVGTemplateResult { + if ((Math.abs(advice.maxAngle - advice.minAngle)) < 4.5) { + return svg``; + } + if (advice.type === AdviceType.caution || advice.type === AdviceType.warning || advice.type === AdviceType.alarm) { + let mainColor; + let fillColor: string | null = null; + + if (advice.state === AdviceState.hinted) { + mainColor = 'var(--instrument-frame-tertiary-color)'; + if (advice.type != AdviceType.caution) { + fillColor = 'var(--instrument-frame-tertiary-color)'; + } + } else if (advice.state === AdviceState.regular) { + mainColor = 'var(--instrument-tick-mark-tertiary-color)'; + } else { + // mainColor = 'var(--on-caution-active-color)'; + // fillColor = 'var(--alert-caution-color)'; + + mainColor = advice.type == AdviceType.caution ? 'var(--on-caution-active-color)' : advice.type == AdviceType.warning ? 'var(--on-warning-active-color)' : advice.type == AdviceType.alarm ? 'var(--on-alarm-active-color)' : ''; + fillColor = advice.type == AdviceType.caution ? 'var(--alert-caution-color)' : advice.type == AdviceType.warning ? 'var(--alert-warning-color)' : advice.type == AdviceType.alarm ? 'var(--alert-alarm-color)' : ''; + } + + const radialPattern = []; + if (advice.type == AdviceType.caution) { + for (let i = 0; i < 360; i += 4) { + radialPattern.push( + svg` + + + + ` + ); + } + } + const maskId = `adviceMask-${advice.minAngle}-${advice.maxAngle}`; + let tickmarkStyle = TickmarkStyle.hinted; + if (advice.state === AdviceState.regular) { + tickmarkStyle = TickmarkStyle.regular; + } else if (advice.state === AdviceState.triggered) { + tickmarkStyle = TickmarkStyle.enhanced; + } + + return svg` + + ${adviceMask(advice.minAngle, advice.maxAngle, 'white', 'black')} + + + ${fillColor ? svg`` : nothing} + ${advice.type == AdviceType.caution ? radialPattern : nothing} + + ${adviceMask(advice.minAngle, advice.maxAngle, 'none', mainColor)} + ${ + advice.hideMinTickmark + ? nothing + : tickmark(advice.minAngle, { + size: TickmarkType.primary, + style: tickmarkStyle, + scale: 1, + inside: false, + textRadius: 0, + maxDigits: 0, + }) + } + ${ + advice.hideMaxTickmark + ? nothing + : tickmark(advice.maxAngle, { + size: TickmarkType.primary, + style: tickmarkStyle, + scale: 1, + inside: false, + textRadius: 0, + maxDigits: 0, + }) + } + `; + } + else { + let mainColor; + let tickmarkStyle; + /* + if (advice.state === AdviceState.hinted) { + mainColor = 'var(--instrument-frame-tertiary-color)'; + tickmarkStyle = TickmarkStyle.hinted; + } else if (advice.state === AdviceState.regular) { + mainColor = 'var(--instrument-regular-secondary-color)'; + tickmarkStyle = TickmarkStyle.regular; + } else { + mainColor = 'var(--instrument-enhanced-secondary-color)'; + tickmarkStyle = TickmarkStyle.regular; + }*/ + if (advice.state === AdviceState.hinted) { + mainColor = 'var(--instrument-frame-tertiary-color)'; + tickmarkStyle = TickmarkStyle.hinted; + } + else if (advice.state === AdviceState.regular) { + mainColor = 'var(--instrument-tick-mark-tertiary-color)'; + tickmarkStyle = TickmarkStyle.regular; + } + else { + mainColor = 'var(--on-caution-active-color)'; + // fillColor = 'var(--alert-caution-color)'; + // mainColor = advice.type == AdviceType.warning ? 'var(--on-warning-active-color)' : advice.type == AdviceType.alarm ? 'var(--on-alarm-active-color)' : ''; + tickmarkStyle = TickmarkStyle.hinted; + } + return svg` + ${adviceMask(advice.minAngle, advice.maxAngle, advice.state === AdviceState.regular ? mainColor : 'none', mainColor)} + ${tickmark(advice.minAngle, { + size: TickmarkType.primary, + style: tickmarkStyle, + scale: 1, + inside: false, + textRadius: 0, + maxDigits: 0, + })} + ${tickmark(advice.maxAngle, { + size: TickmarkType.primary, + style: tickmarkStyle, + scale: 1, + inside: false, + textRadius: 0, + maxDigits: 0, + })} + `; + } +} diff --git a/packages/openbridge-webcomponents/src/skipper/current-icons.ts b/packages/openbridge-webcomponents/src/skipper/current-icons.ts new file mode 100644 index 000000000..f53a21206 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/current-icons.ts @@ -0,0 +1,53 @@ +import { nothing, svg } from "lit"; +import { Colors } from "./interfaces"; + +export function getCurrentIcon(currentSpeed: number) { + // TODO - check this icon + if (currentSpeed < 0.2) { + return svg` + + + + `; + } + else if (currentSpeed >= 0.2 && currentSpeed < 0.5) { + return svg` + + + + + `; + } + else if (currentSpeed >= 0.5 && currentSpeed < 1.0) { + return svg` + + + + + + `; + } + else if (currentSpeed >= 1.0 && currentSpeed < 2) { + return svg` + + + + + + + `; + } + else if (currentSpeed >= 2) { + return svg` + + + + + + + `; + } + else { + return nothing; + } +} \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/gnss-skyplot/gnss-skyplot-styles.ts b/packages/openbridge-webcomponents/src/skipper/gnss-skyplot/gnss-skyplot-styles.ts new file mode 100644 index 000000000..7b2e03964 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/gnss-skyplot/gnss-skyplot-styles.ts @@ -0,0 +1,63 @@ +import { css } from 'lit'; +export const skyplotStyles = css` + .container { + height: 100%; + width: 100%; + } + + .container > svg { + height: 100%; + width: 100%; + } + + .satellite-label { + fill: var(--element-active-inverted-color); + font-size: 16px; + font-family: sans-serif; + text-anchor: middle; + dominant-baseline: middle; + pointer-events: none; + } + + .ring { + fill: var(--instrument-enhanced-secondary-color); + } + + .ring-dark { + fill-opacity: 0.75; + } + + .ring-mid { + fill-opacity: 0.55; + } + + .ring-light { + fill-opacity: 0.35; + } + + .circle-dashed { + fill: none; + stroke: var(--instrument-frame-primary-color); + stroke-width: 1.2; + stroke-dasharray: 6 6; + } + + .circle-solid { + fill: none; + stroke: var(--element-active-color); + stroke-width: 2; + } + + .axis { + stroke: var(--instrument-frame-primary-color); + stroke-width: 1.4; + } + + .label { + fill: var(--element-active-color); + font-size: 14px; + font-family: sans-serif; + text-anchor: middle; + dominant-baseline: middle; + } +`; \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/gnss-skyplot/gnss-skyplot.stories.ts b/packages/openbridge-webcomponents/src/skipper/gnss-skyplot/gnss-skyplot.stories.ts new file mode 100644 index 000000000..1d799d6dc --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/gnss-skyplot/gnss-skyplot.stories.ts @@ -0,0 +1,35 @@ +import type {Meta, StoryObj} from '@storybook/web-components'; +import {widthDecorator} from '../../storybook-util.js'; +import { GnssSkyplot } from './gnss-skyplot.js'; +import './gnss-skyplot.js'; + +const meta: Meta = { + title: 'INSTRUMENT/Gnss-Skyplot', + tags: ['alpha'], + component: 'ob-gnss-skyplot', + parameters: { + actions: { + handles: ['click'], + }, + }, + args: { + width: 512, + showGpsSatellites: true, + showGlonassSatellites: true, + showGalileioSatellites: true, + showBeiDouSatellites: true + }, + argTypes: { + width: {control: {type: 'range', min: 32, max: 1028, step: 1}}, + }, + decorators: [widthDecorator], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Skyplot: Story = { + args: { + width: 512, + }, +}; \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/gnss-skyplot/gnss-skyplot.ts b/packages/openbridge-webcomponents/src/skipper/gnss-skyplot/gnss-skyplot.ts new file mode 100644 index 000000000..7f929982b --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/gnss-skyplot/gnss-skyplot.ts @@ -0,0 +1,460 @@ +import {LitElement, svg, html, nothing} from 'lit'; +import {property} from 'lit/decorators.js'; +import { customElement } from '../../decorator.js'; + +import { skyplotStyles } from './gnss-skyplot-styles.js'; +import { Colors } from '../interfaces.js'; + +export interface SatelliteData { + id: number; + type: SatelliteType; + strength: number; + azimuth: number; // 0–360°, clockwise from North + elevation: number; // 0°-90° - relative to the horizon + spoofing: boolean; + jamming: boolean; + spoJamConfirmed: boolean; +} + +export enum SatelliteType { + GPS = 'GPS', + GLONASS = 'GLONASS', + Galileio = 'Galileio', + BeiDou = 'BeiDou' +} + +export enum Strength { + None = 0, + Weak = 1, + Medium = 2, + Strong = 3 +} + +export interface Satellite { + id: number; + azimuth: number; + elevation: number; + type: SatelliteType; + strength: number; + spoofing: boolean; + jamming: boolean; + spoJamConfirmed: boolean; +} + +@customElement('ob-gnss-skyplot') +export class GnssSkyplot extends LitElement { + @property({type: Array}) satellites: SatelliteData[] = [ // this is just for test + {id: 13, type: SatelliteType.GPS, strength: 0.8, azimuth: 90, elevation: 45, spoofing: true, jamming: false, spoJamConfirmed: false}, + {id: 1, type: SatelliteType.GLONASS, strength: 137, azimuth: 205, elevation: 34, spoofing: false, jamming: false, spoJamConfirmed: false}, + {id: 5, type: SatelliteType.Galileio, strength: 22, azimuth: 88, elevation: 56, spoofing: false, jamming: false, spoJamConfirmed: false}, + {id: 7, type: SatelliteType.BeiDou, strength: 11, azimuth: 310, elevation: 22, spoofing: true, jamming: false, spoJamConfirmed: false}, + {id: 11, type: SatelliteType.GLONASS, strength: 0, azimuth: 145, elevation: 10, spoofing: false, jamming: false, spoJamConfirmed: false}, + {id: 21, type: SatelliteType.GLONASS, strength: 25, azimuth: 67, elevation: 44, spoofing: false, jamming: true, spoJamConfirmed: false}, + {id: 22, type: SatelliteType.Galileio, strength: 65, azimuth: 250, elevation: 66, spoofing: false, jamming: true, spoJamConfirmed: true}, + {id: 23, type: SatelliteType.BeiDou, strength: 57, azimuth: 178, elevation: 39, spoofing: false, jamming: false, spoJamConfirmed: false}, + {id: 24, type: SatelliteType.GPS, strength: 35, azimuth: 99, elevation: 72, spoofing: false, jamming: false, spoJamConfirmed: false}, + {id: 6, type: SatelliteType.Galileio, strength: 75, azimuth: 33, elevation: 18, spoofing: false, jamming: false, spoJamConfirmed: false}, + {id: 8, type: SatelliteType.GPS, strength: 35, azimuth: 277, elevation: 81, spoofing: false, jamming: false, spoJamConfirmed: false}, + {id: 9, type: SatelliteType.GLONASS, strength: 25, azimuth: 190, elevation: 29, spoofing: false, jamming: false, spoJamConfirmed: false}, + {id: 10, type: SatelliteType.Galileio, strength: 85, azimuth: 44, elevation: 61, spoofing: false, jamming: false, spoJamConfirmed: false}, + {id: 12, type: SatelliteType.GPS, strength: 35, azimuth: 320, elevation: 47, spoofing: false, jamming: false, spoJamConfirmed: false}, + {id: 14, type: SatelliteType.Galileio, strength: 15, azimuth: 130, elevation: 53, spoofing: false, jamming: false, spoJamConfirmed: false}, + {id: 15, type: SatelliteType.BeiDou, strength: 45, azimuth: 260, elevation: 14, spoofing: false, jamming: false, spoJamConfirmed: false} + ]; + + @property({type: Boolean}) showGpsSatellites: boolean = false; + @property({type: Boolean}) showGlonassSatellites: boolean = false; + @property({type: Boolean}) showGalileioSatellites: boolean = false; + @property({type: Boolean}) showBeiDouSatellites: boolean = false; + + override render() { + // this.satellites = this.mapSatellitesToCircle(this.generateRandomSatellites()); + this.satellites = this.mapSatellitesToCircle(this.satellites); + return html` +
+ ${this.getGnssSkylot()} +
+ `; + } + + static override styles = [ + skyplotStyles + ]; + + private mapSatellitesToCircle( + input: SatelliteData[] + ): (SatelliteData & { x: number; y: number })[] { + + const centerX = -58; + const centerY = 168; + + const maxRadius = 227.84; // outer ring + + return input.map(s => { + + const angle = (s.azimuth * Math.PI) / 180; + + const clamped = Math.max(0, Math.min(90, s.elevation)); + + const radius = maxRadius * Math.cos((clamped * Math.PI) / 180); + + const x = Math.round(centerX + Math.sin(angle) * radius); + const y = Math.round(centerY - Math.cos(angle) * radius); + + s.strength = this.mapStrength(s.strength); + + return { + ...s, + x, + y + }; + }); + } + + // TODO check the right satellite strength + private mapStrength(value: number): Strength { + if (value <= 0) return Strength.None; + if (value < 30) return Strength.Weak; + if (value < 70) return Strength.Medium; + return Strength.Strong; + } + + private handleClickOnSatellite(id: number) { + const clickedSatellite = this.satellites.find(s => s.id === id); + + if (!clickedSatellite) return; + + window.dispatchEvent( + new CustomEvent('satellite', { + detail: clickedSatellite + }) + ); + + // TODO: remove + console.log(clickedSatellite); + } + + getGnssSkylot() { + return svg` + + + + ${this.getLabels()} + ${this.getOuterRing()} + ${this.getTickmarks()} + ${this.getRings()} + ${this.getRingsAngle()} + + + ${this.getSatellites()} + + + `; + } + + private getLabels() { + return svg` + + + + + `; + } + + private getTickmarks() { + return svg` + + + + + + + + + + + `; + } + + private getOuterRing() { + return svg` + + + + `; + } + + private getRings() { + return svg` + + + + + + `; + } + + private getRingsAngle() { + return svg` + + + + + + `; + } + + private renderSignalIcon({ + id = 0, + x = 0, + y = 0, + strength = 1, + spoofing = false, + jamming = false, + spoJamConfirmed = false + }) + { + const spoofingStroke = spoofing ? Colors.alertAlarmColor : Colors.instrumentEnhancedTertiary; + const jammingStroke = jamming ? Colors.alertCautionColor : Colors.instrumentEnhancedTertiary; + const slashVisible = spoJamConfirmed; + + return svg` + this.handleClickOnSatellite(id)}> + + ${this.getStrengthFeature(strength)} + + ${id !== undefined ? this.getText(id, strength) : ''} + + ${this.getSpoofing(spoofing, spoofingStroke)} + ${this.getJamming(jamming, jammingStroke)} + ${this.getSlash(slashVisible)} + + `; + } + + private getSpoofing(spoofing: boolean, spoofingStroke: string) { + if (spoofing) { + return svg` + + + + + + `; + } + else { + return nothing; + } + } + + private getJamming(jamming: boolean, jammingStroke: string) { + if (jamming) { + return svg` + + + + + + `; + } + else { + return nothing; + } + } + + private getSlash(slashVisible: boolean) { + if (slashVisible) { + return svg` + + + + + + ` + } + else { + return nothing; + } + } + + private getText(id: number, strength: number) { + return svg` + + ${id} + + `; + } + + private getTextFillColor(strength: number) { + if (strength == Strength.Strong) { + return Colors.elementActiveInvertedColor; + } + else if (strength == Strength.Medium) { + return Colors.elementActiveColor; + } + else if (strength == Strength.Weak) { + return Colors.elementNeutralColor; + } + else { // strength == Strength.None + return Colors.elementDisabledColor; + } + } + + private getStrengthFeature(strength: Strength) { + const fillColor = this.getSectorStrengthFillColor(strength); + const strokeColor = this.getSectorStrengthStrokeColor(strength); + + return svg` + + + + + + + + + + + + + + `; + } + + private getFrameStrengthColor(strength: Strength) { + if (strength == Strength.Strong) { + return Colors.dataScalesMonochrome060; + } + else if (strength == Strength.Medium) { + return Colors.dataScalesMonochrome020; + } + else if (strength == Strength.Weak || strength == Strength.None) { + return Colors.overlayContainerBackground; + } + else { + return Colors.overlayContainerBackground; + } + } + + private getSectorStrengthFillColor(strength: Strength) { + if (strength == Strength.Strong) { + return Colors.instrumentEnhancedSecondary; + } + else if (strength == Strength.Medium) { + return Colors.instrumentEnhancedSecondaryDif; + } + else if (strength == Strength.Weak) { + return Colors.instrumentEnhancedTertiary; + } + else { // strength == Strength.None + return Colors.instrumentFrameTertiary; + } + } + + private getSectorStrengthStrokeColor(strength: Strength) { + if (strength == Strength.Strong) { + return Colors.instrumentEnhancedPrimary; + } + else if (strength == Strength.Medium) { + return Colors.instrumentEnhancedSecondary; + } + else if (strength == Strength.Weak) { + return Colors.instrumentEnhancedSecondaryDif; // TODO change + } + else { // strength == Strength.None + return Colors.borderSilhouetteColor; + } + } + + private getSatellites() { + return svg` + ${this.satellites.map(s => { + if (s.type == SatelliteType.GPS && this.showGpsSatellites == true) { + return this.renderSignalIcon(s); + } + else if (s.type == SatelliteType.GLONASS && this.showGlonassSatellites == true) { + return this.renderSignalIcon(s); + } + else if (s.type == SatelliteType.Galileio && this.showGalileioSatellites == true) { + return this.renderSignalIcon(s); + } + else if (s.type == SatelliteType.BeiDou && this.showBeiDouSatellites == true) { + return this.renderSignalIcon(s); + } + return nothing; + }) + } + `; + } + + /* + private generateRandomSatellites(count = 30): SatelliteData[] { + const types = [ + SatelliteType.GPS, + SatelliteType.GLONASS, + SatelliteType.Galileio, + SatelliteType.BeiDou + ]; + + return Array.from({ length: count }, (_, i) => { + const type = types[Math.floor(Math.random() * types.length)]; + + return { + id: i + 1, + type, + strength: this.mapStrength(Math.round(Math.random() * 100)), // 0–100 + + azimuth: Math.floor(Math.random() * 360), // 0–360° + elevation: Math.floor(Math.random() * 91), // 0–90° + + spoofing: Math.random() < 0.1, // 10% + jamming: Math.random() < 0.1, // 10% + spoJamConfirmed: false + }; + }); + } + */ + +} + +declare global { + interface HTMLElementTagNameMap { + 'ob-gnss-skyplot': GnssSkyplot; + } +} \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/index.ts b/packages/openbridge-webcomponents/src/skipper/index.ts new file mode 100644 index 000000000..2cf1e9555 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/index.ts @@ -0,0 +1,5 @@ +export * from './long-lat/long-lat.js'; +export * from './long-lat/long-lat-environmental.js'; +export * from './speedometer/speedometer.js'; +export * from './true-relative/true-relative.js'; +export * from './gnss-skyplot/gnss-skyplot.js'; \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/interfaces.ts b/packages/openbridge-webcomponents/src/skipper/interfaces.ts new file mode 100644 index 000000000..901d8b7de --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/interfaces.ts @@ -0,0 +1,85 @@ +import {InstrumentFieldSize} from '../navigation-instruments/instrument-field/instrument-field.js'; + +export enum SpeedType { + SOG = 'SOG', + STW = 'STW', +} + +export enum SensorPosition { + bow = 'bow', + middle = 'middle', + aft = 'aft', +} + +export enum MeasurementPosition { + Sensor = 'Sensor', + CCRP = 'CCRP', + Bow = 'Bow', +} + +export interface InstrumentField { + size: InstrumentFieldSize; + neutralColor: boolean; + value: number | undefined; + fractionDigits: number; + unit: string; + tag: string; + horizontal: boolean; +} + +export enum AlertTypes { + caution = 'caution', + warning = 'warning', + alarm = 'alarm', + none = 'none', +} + +export enum AlertColor { + cautionColor = 'var(--caution-enabled-background-color)', + warningColor = 'var(--warning-enabled-background-color)', + alarmColor = 'var(--alarm-enabled-background-color)', +} + +export enum Colors { + instrumentEnhancedPrimary = 'var(--instrument-enhanced-primary-color)', + instrumentEnhancedSecondary = 'var(--instrument-enhanced-secondary-color)', + instrumentEnhancedSecondaryDif = 'var(--instrument-enhanced-secondary-dif-color)', + instrumentEnhancedTertiary = 'var(--instrument-enhanced-tertiary-color)', + instrumentFramePrimary = 'var(--instrument-frame-primary-color)', + instrumentFrameSecondary = 'var(--instrument-frame-secondary-color)', + instrumentFrameTertiary = 'var(--instrument-frame-tertiary-color)', + instrumentTickMarkSecondary = 'var(--instrument-tick-mark-secondary-color)', + instrumentTickMarkLabelSecondary = 'var(--instrument-tick-mark-label-secondary-color)', + instrumentTickmarkTertiary = 'var(--instrument-tick-mark-tertiary-color)', + instrumentRegularTertiary = 'var(--instrument-regular-tertiary-color)', + instrumentRegularSecondary = 'var(--instrument-regular-secondary-color)', + instrumentRegularSecondaryDif = 'var(--instrument-regular-secondary-dif-color)', + colorBorderDivider = 'var(--border-divider-color)', + containerSection = 'var(--container-section-color)', + containerBackdrop = 'var(--container-backdrop-color)', + containerBackground = 'var(--container-background-color)', + overlayContainerBackground = 'var(--overlay-container-background-color)', + overlayBorderOutlineColor = 'var(--overlay-border-outline-color)', + elementNeutralColor = 'var(--element-neutral-color)', + elementDisabledColor = 'var(--element-disabled-color)', + elementSymbolColor = 'var(--element-symbol-color)', + alertAlarmColor = 'var(--alert-alarm-color)', + alertCautionColor = 'var(--alert-caution-color)', + alertAlarmOutlineColor = 'var(--alert-alarm-outline-color)', + alertCautionOutlineColor = 'var(--alert-caution-outline-color)', + alertLowIntegrity = 'var(--alert-low-integrity-background-color)', + elementActiveColor = 'var(--element-active-color)', + elementActiveInvertedColor = 'var(--element-active-inverted-color)', + borderSilhouetteColor = 'var(--border-silhouette-color)', + baseBlue100 = 'var(--base-blue-100)', + baseBlue200 = 'var(--base-blue-200)', + baseBlue400 = 'var(--base-blue-400)', + dataScalesMonochrome020 = 'var(--data-scales-monochrome-020)', + dataScalesMonochrome060 = 'var(--data-scales-monochrome-060)', +} + +export interface WatchBarArea { + startAngle: number; + endAngle: number; + fillColor: string; +} diff --git a/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat-environmental.stories.ts b/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat-environmental.stories.ts new file mode 100644 index 000000000..7f30f6c4a --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat-environmental.stories.ts @@ -0,0 +1,80 @@ +import type {Meta, StoryObj} from '@storybook/web-components-vite'; +import {widthDecorator} from '../../storybook-util.js'; +import './long-lat-environmental.js'; +import { MeasurementPosition, SensorPosition, SpeedType } from '../interfaces.js'; + +const meta: Meta = { + title: 'INSTRUMENT/LongLatEnvironmental', + tags: ['alpha'], + component: 'ob-long-lat-environmental', + parameters: { + actions: { + handles: ['click'], + }, + }, + args: { + width: 512 + }, + argTypes: { + width: {control: {type: 'range', min: 32, max: 1028, step: 1}}, + speedType: { + options: [ + SpeedType.SOG, + SpeedType.STW + ], + control: {type: 'select'}, + }, + measurementPosition: { + options: [ + MeasurementPosition.CCRP, + MeasurementPosition.Sensor, + MeasurementPosition.Bow + ], + control: {type: 'select'}, + }, + bowToCCRP: {control: {type: 'range', min: 0, max: 100, step: 0.5}}, + sternToCCRP: {control: {type: 'range', min: 0, max: 100, step: 0.5}}, + sensorToCCRP: {control: {type: 'range', min: -100, max: 100, step: 0.5}}, + longSpeed: {control: {type: 'range', min: -25, max: 100, step: 0.5}}, + latFrontSpeed: {control: {type: 'range', min: -5, max: 5, step: 0.5}}, + latMiddleSpeed: {control: {type: 'range', min: -5, max: 5, step: 0.5}}, + latAftSpeed: {control: {type: 'range', min: -5, max: 5, step: 0.5}}, + longMaxSpeed: {control: {type: 'range', min: 1, max: 50, step: 1}}, + latMaxSpeed: {control: {type: 'range', min: 1, max: 50, step: 1}}, + windSpeed: {control: {type: 'range', min: 0, max: 100, step: 1}}, + windAngle: {control: {type: 'range', min: 0, max: 360, step: 0.5}}, + currentSpeed: {control: {type: 'range', min: 0, max: 3, step: 0.1}}, + currentAngle: {control: {type: 'range', min: 0, max: 360, step: 0.5}}, + heading: {control: {type: 'range', min: 0, max: 360, step: 1}}, + rotationsPerMinute: {control: {type: 'range', min: -10, max: 10, step: 1}} + }, + decorators: [widthDecorator], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LongLatEnvironmental: Story = { + args: { + width: 512, + speedType: SpeedType.SOG, + longMaxSpeed: 25, + latMaxSpeed: 5, + longSpeed: 23.7, + latFrontSpeed: 2.5, + latMiddleSpeed: 4, + latAftSpeed: 4, + windSpeed: 17, + windAngle: 17, + currentSpeed: 0.15, + currentAngle: 5, + heading: 10, + rotationsPerMinute: 5, + showVesselTrail: false, + showSensorIcon: true, + measurementPosition: MeasurementPosition.CCRP, + bowToCCRP: 100, + sternToCCRP: 100, + sensorToCCRP: 25 + }, +}; \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat-environmental.ts b/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat-environmental.ts new file mode 100644 index 000000000..6ec915572 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat-environmental.ts @@ -0,0 +1,1105 @@ +import {LitElement, svg, html, SVGTemplateResult, nothing} from 'lit'; +import {property, state} from 'lit/decorators.js'; +import {customElement} from '../../decorator.js'; +import { longLatStyles } from './long-lat-styles.js'; +import { Colors, MeasurementPosition, SpeedType, WatchBarArea } from '../interfaces.js'; +import { getWindIcon } from '../wind-icons.js'; +import { getCurrentIcon } from '../current-icons.js'; + +@customElement('ob-long-lat-environmental') +export class LongLatEnvironmental extends LitElement { + @property({type: Number}) longMaxSpeed = 25; + @property({type: Number}) latMaxSpeed = 5; + @property({type: Number}) longSpeed = 5; + @property({type: Number}) latFrontSpeed = 5; + @property({type: Number}) latMiddleSpeed = 5; + @property({type: Number}) latAftSpeed = 5; + @property({type: String}) speedType = SpeedType.SOG; + + @property({type: Number}) windSpeed = 5; + @property({type: Number}) windAngle = 5; + @property({type: Number}) currentSpeed = 5; + @property({type: Number}) currentAngle = 5; + @property({type: Number}) heading = 0; + @property({type: Number}) rotationsPerMinute: number = 1; + @property({type: Boolean}) showVesselTrail = false; + + @property({type: Boolean}) showSensorIcon = false; + @property({type: String}) measurementPosition = MeasurementPosition.CCRP; + @property({type: Number}) bowToCCRP = 25; + @property({type: Number}) sternToCCRP = 25; + @property({type: Number}) sensorToCCRP = 15; + + longSpeedRatio = 1; + latFrontSpeedRatio = 1; + latMiddleSpeedRatio = 1; + latAftSpeedRatio = 1; + + private lowIntegrity = false; + + @state() + private rot = 0; + + rotSpeed = 10; // brzina u °/min + endAngle = 0; + + _lastTime = 0; + _animId?: number; + + override firstUpdated() { + this._lastTime = performance.now(); + this._animId = requestAnimationFrame(this._animate); + } + + override connectedCallback() { + super.connectedCallback(); + this._lastTime = performance.now(); + this._animate(this._lastTime); + } + + override disconnectedCallback() { + super.disconnectedCallback(); + cancelAnimationFrame(this._animId!); + } + + + _animate = (time: number) => { + const deltaTime = time - this._lastTime; + this._lastTime = time; + + const rotDegPerMs = this.rotSpeed / 60000; + + this.rot = (this.rot + rotDegPerMs * deltaTime) % 360; + + this._animId = requestAnimationFrame(this._animate); + }; + + override render() { + // this.setMaxSpeed(); + this.setLongSpeedRatio(); + this.setLatFrontSpeedRatio(); + this.setLatMiddleSpeedRatio(); + this.setLatAftSpeedRatio(); + this.setRotationsPerMinute(); + + return html` +
+ ${this.getLongLat()} +
+ `; + } + + static override styles = [ + longLatStyles + ]; + + private get isWindValid() { + return this.isValidNumber(this.windSpeed) && this.isValidNumber(this.windAngle); + } + + private get isCurrentValid() { + return this.isValidNumber(this.currentSpeed) && this.isValidNumber(this.currentAngle); + } + + /* + private setMaxSpeed(): void { + if (this.longMaxSpeed < 25) { + this.longMaxSpeed = 25; + } + else if (this.longMaxSpeed > 25) { + this.longMaxSpeed = 50; + } + } + */ + + setLongSpeedRatio() { + this.longSpeedRatio = Math.abs(this.longSpeed / this.longMaxSpeed); + } + + setLatFrontSpeedRatio() { + this.latFrontSpeedRatio = Math.abs(this.latFrontSpeed / this.latMaxSpeed); + } + + setLatMiddleSpeedRatio() { + this.latMiddleSpeedRatio = Math.abs(this.latMiddleSpeed / this.latMaxSpeed); + } + + setLatAftSpeedRatio() { + this.latAftSpeedRatio = Math.abs(this.latAftSpeed / this.latMaxSpeed); + } + + setRotationsPerMinute() { + if (this.rotationsPerMinute > 10) { + this.rotationsPerMinute = 10; + } + else if (this.rotationsPerMinute <-10) { + this.rotationsPerMinute = -10; + } + } + + setLowIntegrity(state: boolean): void { + this.lowIntegrity = state; + } + + getLowIntegrity(): boolean { + return this.lowIntegrity; + } + + private isValidNumber(value: number | undefined): boolean { + return typeof value === 'number' && !isNaN(value); + } + + private get isRotationsPerMinuteValid() { + return this.isValidNumber(this.rotationsPerMinute); + } + + private get isHeadingValid() { + return this.isValidNumber(this.heading); + } + + private getLongLat() { + return svg` + + + ${this.getWatchFace()} + + ${this.getVesselAndVesselSpeeds()} + + ${this.getLabels()} + + ${this.getCurrent()} + + ${this.getWind()} + + ${this.getRotContainer()} + + ${this.getVesselTrail()} + + ${this.getSensorIcon()} + + + `; + } + + private getRotContainer() { + if (this.isRotationsPerMinuteValid && this.isHeadingValid && this.rotationsPerMinute != 0) { + return svg` + + ${this.getRot()} + + `; + } + else { + return nothing; + } + } + + private getWatchFace() { + return svg` + + + + + + + + + + + + + + + + + + + + + + `; + } + + private getLabels() { + return svg` + + + + + + + + + + + + + `; + } + + private getVesselAndVesselSpeeds() { + return svg` + + + + + + + + + ${this.getMiddleSpeedContainer()} + + ${this.getLatSpeedArrow(this.latFrontSpeed, this.latFrontSpeedRatio)} + + + ${this.getLatSpeedArrow(this.latAftSpeed, this.latAftSpeedRatio)} + + + ${this.getLongSpeedArrow()} + + ${this.getVessel()} + + + `; + } + + private getVessel() { + return svg` + + + + + + + `; + } + + private getCurrent() { + if (this.isCurrentValid) { + return svg` + + + ${this.renderCurrentIcon()} + + + `; + } + else { + return nothing; + } + } + + renderCurrentIcon() { + const cx = 355.66; + const cy = 360.66; + const radius = 225; + + return svg` + + ${getCurrentIcon(this.currentSpeed)} + + `; + } + + renderWindIcon() { + const cx = 357.66; + const cy = 360.66; + const radius = 225; + + return svg` + + ${getWindIcon(this.windSpeed)} + + `; + } + + private getWind() { + if (this.isWindValid) { + return svg` + + + ${this.renderWindIcon()} + + + `; + } + else { + return nothing; + } + } + + private getRot() { + this.rotSpeed = this.rotationsPerMinute * 360; + this.endAngle = this.rotationsPerMinute * 18; + + const clipId = "rot-bar-mask"; + + const CX = 360.60; + const CY = 360.66; + + return svg` + + + + + ${this.renderPrimaryBarAreaMask([ + { + startAngle: 0, + endAngle: this.endAngle + (this.rotationsPerMinute > 0 ? 1.5 : -1.5), + fillColor: "white", + } + ])} + + + + + ${this.renderPrimaryBarArea([ + { + startAngle: 0, + endAngle: this.endAngle, + fillColor: Colors.instrumentRegularTertiary, + } + ])} + + + + + + + + + ${[0, 72, 144, 216, 288].map(a => { + const r = 176; + const rad = (a - 90) * Math.PI / 180; + const x = r * Math.cos(rad); + const y = r * Math.sin(rad); + + return svg` + + `; + })} + + + + + + `; + } + + private renderPrimaryBarArea(barAreas: WatchBarArea[]): SVGTemplateResult[] | typeof nothing { + if (!barAreas.length) return nothing; + + return barAreas.map(bar => { + const start = Math.min(bar.startAngle, bar.endAngle); + const end = Math.max(bar.startAngle, bar.endAngle); + + const d = this.describeArc(168, 184, start, end); + + return svg` + + `; + }); + } + + private renderPrimaryBarAreaMask(barAreas: WatchBarArea[]): SVGTemplateResult[] | typeof nothing { + if (!barAreas.length) return nothing; + + return barAreas.map(bar => { + const start = Math.min(bar.startAngle, bar.endAngle); + const end = Math.max(bar.startAngle, bar.endAngle); + + const d = this.describeArc(164, 180, start, end); // malo veći kao OpenBridge + + return svg` + + `; + }); + } + + private describeArc(r: number, R: number, startAngle: number, endAngle: number) { + const toRad = (a: number) => (a - 90) * Math.PI / 180; + + const largeArc = endAngle - startAngle > 180 ? 1 : 0; + + const x1 = R * Math.cos(toRad(startAngle)); + const y1 = R * Math.sin(toRad(startAngle)); + + const x2 = R * Math.cos(toRad(endAngle)); + const y2 = R * Math.sin(toRad(endAngle)); + + const x3 = r * Math.cos(toRad(endAngle)); + const y3 = r * Math.sin(toRad(endAngle)); + + const x4 = r * Math.cos(toRad(startAngle)); + const y4 = r * Math.sin(toRad(startAngle)); + + return ` + M ${x1} ${y1} + A ${R} ${R} 0 ${largeArc} 1 ${x2} ${y2} + L ${x3} ${y3} + A ${r} ${r} 0 ${largeArc} 0 ${x4} ${y4} + Z + `; + } + + private getSensorIcon() { + if (this.showSensorIcon) { + return svg` + + + + `; + } + else { + return nothing; + } + } + + private getSensorPosition() { + const vesselLength = this.bowToCCRP + this.sternToCCRP; + const unitOfVesselLength = (95 / vesselLength); // 1m of vessel length - mapping real vessel length to svg length + const ccrpPosition = -15 + this.bowToCCRP * unitOfVesselLength; + + if (this.measurementPosition == MeasurementPosition.CCRP) { + return ccrpPosition; + } + else if (this.measurementPosition == MeasurementPosition.Sensor) { + const sensorToCCRP = ccrpPosition - this.sensorToCCRP * unitOfVesselLength; + if (this.sensorToCCRP > this.bowToCCRP) { + return ccrpPosition - this.bowToCCRP * unitOfVesselLength; + } + else if (Math.abs(this.sensorToCCRP) > this.sternToCCRP) { + return ccrpPosition + this.sternToCCRP * unitOfVesselLength; + } + return sensorToCCRP; + } + else { // measurementPosition == MeasurementPosition.Bow + return -15; + } + } + + private getLongSpeedArrow() { + if (this.longSpeed > 0) { + return svg` + + ${this.getForwardArrows()} + + `; + } + else if (this.longSpeed < 0) { + return svg` + + ${this.getBackwardArrows()} + + `; + } + else { + return nothing; + } + } + + private getForwardArrows() { + if (this.longSpeedRatio < 1/3) { + return svg` + + `; + } + else if (this.longSpeedRatio < 2/3) { + return svg` + + + `; + } + else { + return svg` + + + + `; + } + } + + private getBackwardArrows() { + if (this.longSpeedRatio < 1/3) { + return svg` + + `; + } + else if (this.longSpeedRatio < 2/3) { + return svg` + + + `; + } + else { + return svg` + + + + `; + } + } + + private getMiddleSpeedContainer() { + if (this.measurementPosition == MeasurementPosition.Sensor && this.isValidNumber(this.latMiddleSpeed)) { + return svg` + + + ${this.getLatSpeedArrow(this.latMiddleSpeed, this.latMiddleSpeedRatio)} + + `; + } + else { + return nothing; + } + } + + private getLatSpeedArrow(speed: number, speedRatio: number) { + if (speed < 0) { + return svg` + + ${this.getLatLeftArrow(speedRatio)} + + `; + } + else if (speed > 0) { + return svg` + + ${this.getLatRightArrow(speedRatio)} + + `; + } + else { + return nothing; + } + } + + private getLatLeftArrow(speedRatio: number) { + if (speedRatio < 1/3) { + return svg` + + `; + } + else if (speedRatio < 2/3) { + return svg` + + + `; + } + else { + return svg` + + + + `; + } + } + + private getLatRightArrow(speedRatio: number) { + if (speedRatio < 1/3) { + return svg` + + `; + } + else if (speedRatio < 2/3) { + return svg` + + + `; + } + else { + return svg` + + + + `; + } + } + + private getVesselTrail() { + if (this.showVesselTrail) { + if (this.longSpeed > 0) { + if (this.latFrontSpeed > 0 && this.latAftSpeed > 0) { + return svg`${this.renderVesselTrail()}`; + } + else if (this.latFrontSpeed < 0 && this.latAftSpeed < 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed > 0 && this.latAftSpeed < 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed < 0 && this.latAftSpeed > 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed == 0 && this.latAftSpeed == 0) { + return svg` + + ${this.renderVesselTrail(0)} + + `; + } + else if (this.latFrontSpeed == 0 && this.latAftSpeed < 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed == 0 && this.latAftSpeed > 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed < 0 && this.latAftSpeed == 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed > 0 && this.latAftSpeed == 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else { + return nothing; + } + } + else if (this.longSpeed < 0) { + if (this.latFrontSpeed > 0 && this.latAftSpeed > 0) { + return svg` + + ${this.renderVesselTrail()} + `; + } + else if (this.latFrontSpeed < 0 && this.latAftSpeed < 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed > 0 && this.latAftSpeed < 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed < 0 && this.latAftSpeed > 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed == 0 && this.latAftSpeed == 0) { + return svg` + + ${this.renderVesselTrail(0)} + + `; + } + else if (this.latFrontSpeed == 0 && this.latAftSpeed < 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed == 0 && this.latAftSpeed > 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed < 0 && this.latAftSpeed == 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed > 0 && this.latAftSpeed == 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else { + return nothing; + } + } + else if (this.longSpeed == 0) { + if (this.latFrontSpeed > 0 && this.latAftSpeed > 0) { + return svg`${this.renderVesselTrail()}`; + } + else if (this.latFrontSpeed < 0 && this.latAftSpeed < 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed > 0 && this.latAftSpeed < 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed < 0 && this.latAftSpeed > 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed == 0 && this.latAftSpeed < 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed == 0 && this.latAftSpeed > 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed < 0 && this.latAftSpeed == 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else if (this.latFrontSpeed > 0 && this.latAftSpeed == 0) { + return svg` + + ${this.renderVesselTrail()} + + `; + } + else { + return nothing; + } + } + else { + return nothing; + } + } + else { + return nothing; + } + } + + private getLatSpeed(): number { + return Math.max( + Math.abs(this.latFrontSpeed) ?? 0, + Math.abs(this.latMiddleSpeed) ?? 0, + Math.abs(this.latAftSpeed) ?? 0 + ); + } + + private getHotizontalPosition(angle: number, i: number) { + if (this.longSpeed != 0) { + return (angle == 0 ? 0 : 0 - i * 1.5); + } + else { + if (Math.abs(this.getLatSpeed()/this.latMaxSpeed) > 2/3) { + return 0 - i * 8; + } + else if (Math.abs(this.getLatSpeed()/this.latMaxSpeed) > 1/3) { + return 0 - i * 6; + } + else { + return 0 - i * 3; + } + // 0 - i * ((Math.abs(this.latSpeed/this.latMaxSpeed) > 2/3 ? 6 : Math.abs(this.latSpeed/this.latMaxSpeed) > 1/3 ? 8 : 3)) + } + } + + private getVerticalPosition(i: number) { + if(this.longSpeed != 0) { + if (Math.abs(this.longSpeed/this.longMaxSpeed) > 2/3) { + return i * 8; + } + else if (Math.abs(this.longSpeed/this.longMaxSpeed) > 1/3) { + return i * 6; + } + else { + return i * 3; + } + } + else { + return 0; + } + //(i * (Math.abs(this.longSpeed/this.longMaxSpeed) > 2/3 ? 8 : Math.abs(this.longSpeed/this.longMaxSpeed) > 1/3 ? 6 : 3)) : 0 + } + + private getVesselTrailRotation(angle: number, i: number) { + if (this.longSpeed == 0) { + if (Math.abs(this.latFrontSpeed) > Math.abs(this.latAftSpeed)) { + return -i; + } + else if (Math.abs(this.latFrontSpeed) < Math.abs(this.latAftSpeed)) { + return i; + } + else if ((this.latFrontSpeed < 0 && this.latAftSpeed > 0) || (this.latFrontSpeed > 0 && this.latAftSpeed < 0)) { + return i * 2; + } + else { + return 0; + } + } + else { + if (angle == 0) { + return 0; + } + else if ((this.latFrontSpeed < 0 && this.latAftSpeed > 0) || (this.latFrontSpeed > 0 && this.latAftSpeed < 0)) { + return i * 3; + } + else { + return i; + } + } + // this.longSpeed == 0 ? Math.abs(this.latFrontSpeed) > Math.abs(this.latAftSpeed) ? -i : Math.abs(this.latFrontSpeed) < Math.abs(this.latAftSpeed) ? i : 0 : (angle == 0 ? 0 : i) + } + + private renderVesselTrail(angle = 1) { + return svg` + ${Array.from({ length: 10 }, (_, i) => + this.renderVesselPath({ + x: this.getHotizontalPosition(angle, i), + y: this.getVerticalPosition(i), // based on speed + width: 22, + height: 180, + rotation: this.getVesselTrailRotation(angle, i), //*5), + opacity: 1 - i * 0.1 + }) + )} + `; + } + + private renderVesselPath(options: { + x: number; + y: number; + width: number; + height: number; + rotation?: number; + opacity?: number; + }) { + const { + x, + y, + // width, + // height, + rotation = 0, + opacity = 1 + } = options; + + const cx = x; // + width / 2; + const cy = y; // + height / 2; + + return svg` + + ${this.getTrail()} + + `; + } + + private getTrail() { + if (this.longSpeed == 0) { + return svg` + + + + + `; + } + else if (this.latFrontSpeed == 0 && this.latMiddleSpeed == 0 && this.latAftSpeed == 0) { + return svg` + + + + + `; + } + else { + return svg` + + + + + + `; + } + } + +} + +declare global { + interface HTMLElementTagNameMap { + 'ob-long-lat-environmental': LongLatEnvironmental; + } +} \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat-styles.ts b/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat-styles.ts new file mode 100644 index 000000000..9f3ddb451 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat-styles.ts @@ -0,0 +1,75 @@ +import { css } from 'lit'; +export const longLatStyles = css` + + .container { + height: 100%; + width: 100%; + } + + .container > svg { + height: 100%; + width: 100%; + } + + .instrument-field-angle { + grid-area: angle; + padding-top: 11px; + padding-bottom: 4px; + } + + .speed-gauge-value { + position: relative; + font-size: 64; + } + + .satellite-label { + fill: var(--element-active-inverted-color); + font-size: 16px; + font-family: sans-serif; + text-anchor: middle; + dominant-baseline: middle; + pointer-events: none; + } + + .ring { + fill: var(--instrument-enhanced-secondary-color); + } + + .ring-dark { + fill-opacity: 0.75; + } + + .ring-mid { + fill-opacity: 0.55; + } + + .ring-light { + fill-opacity: 0.35; + } + + .circle-dashed { + fill: none; + stroke: var(--instrument-frame-primary-color); + stroke-width: 1.2; + stroke-dasharray: 6 6; + } + + .circle-solid { + fill: none; + stroke: var(--element-active-color); + stroke-width: 2; + } + + .axis { + stroke: var(--instrument-frame-primary-color); + stroke-width: 1.4; + } + + .label { + fill: var(--element-active-color); + font-size: 14px; + font-family: sans-serif; + text-anchor: middle; + dominant-baseline: middle; + } +`; \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat.stories.ts b/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat.stories.ts new file mode 100644 index 000000000..8c5488a06 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat.stories.ts @@ -0,0 +1,82 @@ +import type {Meta, StoryObj} from '@storybook/web-components-vite'; +import {widthDecorator} from '../../storybook-util.js'; +import './long-lat.js'; +import { MeasurementPosition, SpeedType } from '../interfaces.js'; + +const meta: Meta = { + title: 'INSTRUMENT/LongLat', + tags: ['alpha'], + component: 'ob-long-lat', + parameters: { + actions: { + handles: ['click'], + }, + }, + args: { + width: 512 + }, + argTypes: { + width: {control: {type: 'range', min: 32, max: 1028, step: 1}}, + speedType: { + options: [ + SpeedType.SOG, + SpeedType.STW + ], + control: {type: 'select'}, + }, + longSpeed: {control: {type: 'range', min: -25, max: 100, step: 0.1}}, + latFrontSpeed: {control: {type: 'range', min: -5, max: 5, step: 0.1}}, + latMiddleSpeed: {control: {type: 'range', min: -5, max: 5, step: 0.1}}, + latAftSpeed: {control: {type: 'range', min: -5, max: 5, step: 0.1}}, + longMaxSpeed: {control: {type: 'range', min: 1, max: 50, step: 1}}, + latMaxSpeed: {control: {type: 'range', min: 1, max: 50, step: 1}}, + measurementPosition: { + options: [ + MeasurementPosition.CCRP, + MeasurementPosition.Sensor, + MeasurementPosition.Bow + ], + control: {type: 'select'}, + }, + bowToCCRP: {control: {type: 'range', min: 0, max: 100, step: 0.5}}, + sternToCCRP: {control: {type: 'range', min: 0, max: 100, step: 0.5}}, + sensorToCCRP: {control: {type: 'range', min: -100, max: 100, step: 0.5}}, + }, + decorators: [widthDecorator], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LongLat: Story = { + args: { + width: 512, + speedType: SpeedType.SOG, + longMaxSpeed: 25, + latMaxSpeed: 5, + longSpeed: 23.7, + latFrontSpeed: 2.5, + latAftSpeed: -4, + measurementPosition: MeasurementPosition.Sensor, + bowToCCRP: 100, + sternToCCRP: 100, + sensorToCCRP: 50 + }, +}; + +export const LongLatWithoutLatFrontSpeed: Story = { + args: { + width: 512, + speedType: SpeedType.SOG, + longMaxSpeed: 25, + latMaxSpeed: 5, + longSpeed: 23.7, + latFrontSpeed: undefined, + latMiddleSpeed: 2.5, + latAftSpeed: -4, + measurementPosition: MeasurementPosition.Sensor, + bowToCCRP: 100, + sternToCCRP: 100, + sensorToCCRP: 100 + }, +}; \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat.ts b/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat.ts new file mode 100644 index 000000000..ac09b1bf1 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/long-lat/long-lat.ts @@ -0,0 +1,529 @@ +import {LitElement, svg, html, nothing} from 'lit'; +import {property} from 'lit/decorators.js'; +import {customElement} from '../../decorator.js'; +import { longLatStyles } from './long-lat-styles.js'; +import { Colors, MeasurementPosition, SpeedType } from '../interfaces.js'; +import { InstrumentFieldSize } from '../../navigation-instruments/instrument-field/instrument-field.js'; + +@customElement('ob-long-lat') +export class LongLat extends LitElement { + @property({type: Number}) longMaxSpeed = 25; + @property({type: Number}) latMaxSpeed = 5; + @property({type: Number}) longSpeed = 5; + @property({type: Number}) latFrontSpeed = undefined; + @property({type: Number}) latMiddleSpeed = undefined; + @property({type: Number}) latAftSpeed = undefined; + @property({type: String}) speedType = SpeedType.SOG; + + @property({type: String}) measurementPosition = MeasurementPosition.Sensor; + @property({type: Number}) bowToCCRP = 25; + @property({type: Number}) sternToCCRP = 25; + @property({type: Number}) sensorToCCRP = 15; + + longSpeedRatio = 1; + latFrontSpeedRatio = 1; + latMiddleSpeedRatio = 1; + latAftSpeedRatio = 1; + + private lowIntegrity = false; + + override render() { + this.setLongSpeedRatio(); + this.setLatFrontSpeedRatio(); + this.setLatMiddleSpeedRatio(); + this.setLatAftSpeedRatio(); + + return html` +
+ ${this.getLongLat()} +
+ `; + } + + static override styles = [ + longLatStyles + ]; + + private isValidNumber(value: number | undefined): boolean { + return typeof value === 'number' && !isNaN(value); + } + + setLongSpeedRatio() { + this.longSpeedRatio = Math.abs(this.longSpeed / this.longMaxSpeed); + } + + setLatFrontSpeedRatio() { + if (this.latFrontSpeed != undefined) + this.latFrontSpeedRatio = Math.abs(this.latFrontSpeed / this.latMaxSpeed); + } + + setLatMiddleSpeedRatio() { + if (this.latMiddleSpeed != undefined) + this.latMiddleSpeedRatio = Math.abs(this.latMiddleSpeed / this.latMaxSpeed); + } + + setLatAftSpeedRatio() { + if (this.latAftSpeed != undefined) + this.latAftSpeedRatio = Math.abs(this.latAftSpeed / this.latMaxSpeed); + } + + setLowIntegrity(state: boolean): void { + this.lowIntegrity = state; + } + + getLowIntegrity(): boolean { + return this.lowIntegrity; + } + + private get isLongSpeedValid() { + return this.isValidNumber(this.longSpeed); + } + + private get isLatFrontSpeedValid() { + return this.isValidNumber(this.latFrontSpeed); + } + + private get isLatMiddleSpeedValid() { + return this.isValidNumber(this.latMiddleSpeed); + } + + private get isLatAftSpeedValid() { + return this.isValidNumber(this.latAftSpeed); + } + + private getLongLat() { + return svg` + + + ${this.getVessel()} + + ${this.getMiddleSpeedContainer()} + + ${this.getLatFrontSpeedContainer()} + + ${this.getLatAftSpeedContainer()} + + ${this.getLongSpeedContainer()} + + ${this.getSpeedLabel()} + + `; + } + + private getLongSpeedContainer() { + if (this.isLongSpeedValid) { + return svg` + ${this.getLongSpeedArrow()} + ${this.getLongSpeedField()} + `; + } + else { + return nothing; + } + } + + private getSensorPosition() { + const vesselLength = this.bowToCCRP + this.sternToCCRP; + const unitOfVesselLength = (343 / vesselLength); // 1m of vessel length - mapping real vessel length to svg length + const ccrpPosition = -15 + this.bowToCCRP * unitOfVesselLength; + + if (this.measurementPosition == MeasurementPosition.CCRP) { + return ccrpPosition; + } + else if (this.measurementPosition == MeasurementPosition.Sensor) { + const sensorToCCRP = ccrpPosition - this.sensorToCCRP * unitOfVesselLength; + if (this.sensorToCCRP > this.bowToCCRP) { + return ccrpPosition - this.bowToCCRP * unitOfVesselLength; + } + else if (Math.abs(this.sensorToCCRP) > this.sternToCCRP) { + return ccrpPosition + this.sternToCCRP * unitOfVesselLength; + } + return sensorToCCRP; + } + else { // measurementPosition == MeasurementPosition.Bow + return -15; + } + } + + private getLatSpeedArrow(speed: number, speedRatio: number) { + if (speed < 0) { + return svg` + + + + + + + + + ${this.getLatLeftArrow(speedRatio)} + + `; + } + else if (speed > 0) { + return svg` + + + + + + + + + ${this.getLatRightArrow(speedRatio)} + + `; + } + else { + return nothing; + } + } + + private getLatLeftArrow(speedRatio: number) { + if (speedRatio < 1/3) { + return svg` + + `; + } + else if (speedRatio < 2/3) { + return svg` + + + `; + } + else { + return svg` + + + + `; + } + } + + private getLatRightArrow(speedRatio: number) { + if (speedRatio < 1/3) { + return svg` + + `; + } + else if (speedRatio < 2/3) { + return svg` + + + `; + } + else { + return svg` + + + + `; + } + } + + private getLatFrontSpeedContainer() { + if (this.isLatFrontSpeedValid && this.latFrontSpeed != undefined) { + return svg` + ${this.getLatSpeedArrow(this.latFrontSpeed, this.latFrontSpeedRatio)} + ${this.getLatFrontSpeedField()} + `; + } + else { + return nothing; + } + } + + private getMiddleSpeedContainer() { + if (this.isLatMiddleSpeedValid && this.latMiddleSpeed != undefined) { + if (this.measurementPosition == MeasurementPosition.Sensor) { + return svg` + + ${this.getLatSpeedArrow(this.latMiddleSpeed, this.latMiddleSpeedRatio)} + ${this.getLatMiddleSpeedField()} + + `; + } + else { + return nothing; + } + } + else { + return nothing; + } + } + + private getLatAftSpeedContainer() { + if (this.isLatAftSpeedValid && this.latAftSpeed != undefined) { + return svg` + + ${this.getLatSpeedArrow(this.latAftSpeed, this.latAftSpeedRatio)} + + ${this.getLatAftSpeedField()} + `; + } + else { + return nothing; + } + } + + private getSpeedLabel() { + if (this.speedType == SpeedType.SOG) { + return svg` + + + + + + + + + + `; + } + else if (this.speedType == SpeedType.STW) { + return svg` + + + + + + + + `; + } + else { + return nothing; + } + } + + private getLongSpeedArrow() { + if (this.longSpeed > 0) { + return svg` + + + + + + + + + ${this.getForwardArrows()} + + `; + } + else if (this.longSpeed < 0) { + return svg` + + + + + + + + + ${this.getBackwardArrow()} + + `; + } + else { + return nothing; + } + } + + private getForwardArrows() { + if (this.longSpeedRatio < 1/3) { + return svg` + + `; + } + else if (this.longSpeedRatio < 2/3) { + return svg` + + + `; + } + else { + return svg` + + + + `; + } + } + + private getBackwardArrow() { + if (this.longSpeedRatio < 1/3) { + return svg` + + `; + } + else if (this.longSpeedRatio < 2/3) { + return svg` + + + `; + } + else { + return svg` + + + + `; + } + } + + private getVessel() { + return svg` + + + + + + + `; + } + + private getLongSpeedField() { + return svg` + + + + + ${this.getSpeed(408, 410, this.longSpeed)} + + + + + + + + + `; + } + + private getLatFrontSpeedField() { + if (this.latFrontSpeed != undefined) { + return svg` + + + + + ${this.getSpeed(408, 238, this.latFrontSpeed)} + + + + + + + + `; + } + else { + return nothing; + } + } + + private getSpeed(x: number, y: number, speed: number) { + return svg` + + ${Math.abs(speed).toFixed(1)} + + `; + } + + private getLatMiddleSpeedField() { + if (this.latMiddleSpeed != undefined) { + return svg` + + + ${this.getSpeed(408, 238, this.latMiddleSpeed)} + + + + + + + + `; + } + else { + return nothing; + } + } + + private getLatAftSpeedField() { + if (this.latAftSpeed != undefined) { + return svg` + + + + + ${this.getSpeed(408, 578, this.latAftSpeed)} + + + + + + + + `; + } + else { + return nothing; + } + } + +} + +declare global { + interface HTMLElementTagNameMap { + 'ob-long-lat': LongLat; + } +} \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/models.ts b/packages/openbridge-webcomponents/src/skipper/models.ts new file mode 100644 index 000000000..079a87f16 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/models.ts @@ -0,0 +1,14 @@ +export enum InnerWatchFaceType { + REGULAR = "REGULAR", + PORT_STARBOARD = "PORT_STARBOARD", + POSITIVE_NEGATIVE = "POSITIVE_NEGATIVE" +} + +export type InnerWatchFaceTypeString = keyof typeof InnerWatchFaceType; + +export enum WidthSize { + MIN = "MIN", + REGULAR = "REGULAR", + MAX = "MAX" +} +export type WidthSizeStrings = keyof typeof WidthSize; diff --git a/packages/openbridge-webcomponents/src/skipper/speedometer/speedometer-styles.ts b/packages/openbridge-webcomponents/src/skipper/speedometer/speedometer-styles.ts new file mode 100644 index 000000000..e130bd762 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/speedometer/speedometer-styles.ts @@ -0,0 +1,100 @@ +import { css } from 'lit'; +export const speedometerStyles = css` + + .container { + height: 100%; + width: 100%; + } + + .container > svg { + height: 100%; + width: 100%; + } + + .speed-gauge-value { + position: relative; + display: flex; + flex-direction: column; + font-size: 64; + align-items: center; + justify-content: center; + + // border: 1px solid var(--element-inactive-color); + // border-radius: 6px; + } + + .ob-main-value { + position: relative; + transform: scale(2.25); + transform-origin: top; + display: flex; + align-items: center; + justify-content: center; + width: 350px; + + // border: 1px solid var(--element-inactive-color); + // border-radius: 6px; + + } + + .ob-secondary-value { + position: relative; + display: flex; + align-items: center; + justify-content: center; + + transform: scale(1.5); + transform-origin: top; + } + + .satellite-label { + fill: var(--element-active-inverted-color); + font-size: 16px; + font-family: sans-serif; + text-anchor: middle; + dominant-baseline: middle; + pointer-events: none; + } + + .ring { + fill: var(--instrument-enhanced-secondary-color); + } + + .ring-dark { + fill-opacity: 0.75; + } + + .ring-mid { + fill-opacity: 0.55; + } + + .ring-light { + fill-opacity: 0.35; + } + + .circle-dashed { + fill: none; + stroke: var(--instrument-frame-primary-color); + stroke-width: 1.2; + stroke-dasharray: 6 6; + } + + .circle-solid { + fill: none; + stroke: var(--element-active-color); + stroke-width: 2; + } + + .axis { + stroke: var(--instrument-frame-primary-color); + stroke-width: 1.4; + } + + .label { + fill: var(--element-active-color); + font-size: 14px; + font-family: sans-serif; + text-anchor: middle; + dominant-baseline: middle; + } +`; \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/speedometer/speedometer.stories.ts b/packages/openbridge-webcomponents/src/skipper/speedometer/speedometer.stories.ts new file mode 100644 index 000000000..557416ec9 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/speedometer/speedometer.stories.ts @@ -0,0 +1,112 @@ +import type {Meta, StoryObj} from '@storybook/web-components-vite'; +import {widthDecorator} from '../../storybook-util.js'; +import { AlertTypes, SpeedType } from '../interfaces.js'; +import './speedometer.js'; + +const meta: Meta = { + title: 'INSTRUMENT/Speedometer', + tags: ['autodocs', '6.0'], + component: 'ob-speedometer', + parameters: { + actions: { + handles: ['click'], + }, + }, + args: { + width: 512 + }, + argTypes: { + width: {control: {type: 'range', min: 32, max: 1028, step: 1}}, + mainSpeedType: { + options: [ + SpeedType.SOG, + SpeedType.STW + ], + control: {type: 'select'}, + }, + sogSpeed: {control: {type: 'range', min: -15, max: 100, step: 0.5}}, + stwSpeed: {control: {type: 'range', min: -15, max: 100, step: 0.5}}, + alertLow: {control: {type: 'range', min: -10, max: 50, step: 0.5}}, + alertHigh: {control: {type: 'range', min: -10, max: 50, step: 0.5}}, + alertLowType: { + options: [ + AlertTypes.caution, + AlertTypes.warning, + AlertTypes.alarm, + AlertTypes.none + ], + control: {type: 'select'}, + }, + alertHighType: { + options: [ + AlertTypes.caution, + AlertTypes.warning, + AlertTypes.alarm, + AlertTypes.none + ], + control: {type: 'select'} + }, + maxSpeed: {control: {type: 'range', min: 1, max: 50, step: 1}}, + useAlerts: { + options: [ + false, + true + ], + control: {type: 'select'}, + }, + }, + decorators: [widthDecorator], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Speedometer: Story = { + args: { + width: 512, + maxSpeed: 27, + mainSpeedType: SpeedType.SOG, + sogSpeed: 22.7, + stwSpeed: 23.7, + alertLow: -2, + alertHigh: 24, + alertLowType: AlertTypes.none, + alertHighType: AlertTypes.caution, + showSog: true, + showStw: true, + useAlerts: true, + showSpeedAsNumber: false + }, +}; + +export const SpeedometerSogOnly: Story = { + args: { + width: 512, + maxSpeed: 27, + mainSpeedType: SpeedType.SOG, + sogSpeed: 5.49, + alertLow: -2, + alertHigh: 22, + alertLowType: AlertTypes.alarm, + alertHighType: AlertTypes.caution, + showSog: true, + showStw: false, + useAlerts: true + }, +}; + +export const SpeedometerStwOnly: Story = { + args: { + width: 512, + maxSpeed: 27, + mainSpeedType: SpeedType.STW, + stwSpeed: 5.49, + alertLow: -2, + alertHigh: 22, + alertLowType: AlertTypes.alarm, + alertHighType: AlertTypes.caution, + showSog: false, + showStw: true, + useAlerts: true + }, +}; \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/speedometer/speedometer.ts b/packages/openbridge-webcomponents/src/skipper/speedometer/speedometer.ts new file mode 100644 index 000000000..0dd12cf4d --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/speedometer/speedometer.ts @@ -0,0 +1,1021 @@ +import {LitElement, svg, html, SVGTemplateResult, nothing} from 'lit'; +import {property} from 'lit/decorators.js'; +import {customElement} from '../../decorator.js'; +import { speedometerStyles } from './speedometer-styles.js'; +import { roundedArch } from '../../svghelpers/roundedArch.js'; +import { AdviceState, AdviceType, renderAdvice } from '../advice.js'; +import { InstrumentFieldSize } from '../../navigation-instruments/instrument-field/instrument-field.js'; +import { AlertColor, AlertTypes, Colors, InstrumentField, SpeedType, WatchBarArea } from '../interfaces.js'; + +export const OUTER_RING_RADIUS = 368 / 2; +const RING2_RADIUS = 528.25 / 2; +const RING3_RADIUS = 373.25 / 2; + +@customElement('ob-speedometer') +export class Speedometer extends LitElement { + @property({type: Number}) maxSpeed = 25; + @property({type: String}) mainSpeedType = SpeedType.SOG; + @property({type: Number}) sogSpeed = 5; + @property({type: Number}) fractionDigits = 2; + @property({type: Number}) stwSpeed = 5; + @property({type: Boolean}) useAlerts = false; + @property({type: Number}) alertLow = 5; + @property({type: String}) alertLowType: AlertTypes = AlertTypes.alarm; + @property({type: Number}) alertHigh = 22; + @property({type: String}) alertHighType: AlertTypes = AlertTypes.caution; + @property({type: Boolean}) showSog = false; + @property({type: Boolean}) showStw = false; + @property({type: Boolean}) showSpeedAsNumber = false; + + private rotateStw = 0; + + private rotate = 0; + private rotationAngle = 9; + + private minSpeed = -5; + private lowIntegrity = false; + + private viewBox = "130 80 712 712"; + + override render() { + this.setViewBox(); + this.setMaxSpeed(); + this.setRotate(); + this.setStwRotate(); + + return html` +
+ ${this.getSpeedometer()} +
+ `; + } + + setViewBox() { + if (this.showSog && this.showStw) { + this.viewBox = "130 80 712 712"; + } + else { + this.viewBox = "130 80 712 612"; + } + } + + static override styles = [ + speedometerStyles + ]; + + getSogSpeed(): number { + if (this.sogSpeed <= this.maxSpeed && this.sogSpeed >= this.minSpeed) { + return this.sogSpeed; + } + else if (this.sogSpeed > this.maxSpeed) { + return this.maxSpeed; + } + else if (this.sogSpeed < this.minSpeed) { + return this.minSpeed; + } + else { + return this.minSpeed; + } + } + + getStwSpeed(): number { + if (this.stwSpeed <= this.maxSpeed && this.stwSpeed >= this.minSpeed) { + return this.stwSpeed; + } + else if (this.stwSpeed > this.maxSpeed) { + return this.maxSpeed; + } + else if (this.stwSpeed < this.minSpeed) { + return this.minSpeed; + } + else { + return this.minSpeed; + } + } + + private getAngle(v: number): number { + return (v / this.maxSpeed) * (180 + 45) - 90; + } + + private setMaxSpeed(): void { + if (this.maxSpeed <= 25) { + this.maxSpeed = 25; + this.minSpeed = -5; + this.rotationAngle = 9; + } + else if (this.maxSpeed > 25) { + this.maxSpeed = 50; + this.minSpeed = -10; + this.rotationAngle = 4.5; + } + } + + setRotate(): void { + if (this.sogSpeed > this.maxSpeed) { + this.rotate = this.maxSpeed * this.rotationAngle; + this.setLowIntegrity(true); + } + else if (this.sogSpeed < this.minSpeed) { + this.rotate = this.minSpeed * this.rotationAngle; + this.setLowIntegrity(true); + } + else { + this.rotate = isNaN(this.sogSpeed) ? 0 : this.sogSpeed * this.rotationAngle; + this.setLowIntegrity(false); + } + } + + setStwRotate(): void { + if (this.stwSpeed > this.maxSpeed) { + this.rotateStw = this.maxSpeed * this.rotationAngle; + this.setLowIntegrity(true); + } + else if (this.stwSpeed < this.minSpeed) { + this.rotateStw = this.minSpeed * this.rotationAngle; + this.setLowIntegrity(true); + } + else { + this.rotateStw = isNaN(this.stwSpeed) ? 0 : this.stwSpeed * this.rotationAngle; + this.setLowIntegrity(false); + } + } + + setLowIntegrity(state: boolean): void { + this.lowIntegrity = state; + } + + getLowIntegrity(): boolean { + return this.lowIntegrity; + } + + private renderPrimaryBarArea(barAreas: WatchBarArea[]): SVGTemplateResult[] | typeof nothing { + if (barAreas.length === 0) { + return nothing; + } + return barAreas.map((bar, index) => { + const startAngle = Math.min(bar.startAngle, bar.endAngle); + const endAngle = Math.max(bar.startAngle, bar.endAngle); + const arc = roundedArch({ + r: RING3_RADIUS, + R: RING2_RADIUS, + startAngle: startAngle, + endAngle: endAngle, + roundInsideCut: false, + roundOutsideCut: false, + }); + // The mask is a sector to cut out the stroke on the start and end of the bar + const mask = svg` + + + + `; + return svg` + ${mask} + + + + `; + }); + } + + private renderSecondaryBarArea(barAreas: WatchBarArea[]): SVGTemplateResult[] | typeof nothing { + if (barAreas.length === 0) { + return nothing; + } + return barAreas.map((bar, index) => { + const startAngle = Math.min(bar.startAngle, bar.endAngle); + const endAngle = Math.max(bar.startAngle, bar.endAngle); + const arc = roundedArch({ + r: 154, + R: 179, + startAngle: startAngle, + endAngle: endAngle, + roundInsideCut: false, + roundOutsideCut: false, + }); + // The mask is a sector to cut out the stroke on the start and end of the bar + const mask = svg` + + + + `; + return svg` + ${mask} + + + + `; + }); + } + + private getSpeedometer() { + return svg` + + + ${this.getWatchFace()} + ${this.getTickmarks()} + ${this.getLabels()} + + ${this.getSpeedValue()} + + ${this.getSecondaryContainer()} + ${this.getPrimaryContainer()} + + ${this.getAlerts()} + + ${this.getPrimaryNeedle()} + + + `; + } + + private getWatchFace() { + return svg` + + + + + + + + + + + + + + + + + + + + + + + + `; + } + + private getAlerts() { + if (this.useAlerts) { + return svg` + ${this.getAdviceContainerLow()} + ${this.getAdviceContainerHigh()} + `; + } + else { + return nothing; + } + } + + private getAlertLowMask() { + if (this.alertLowType != AlertTypes.none && this.useAlerts && this.alertLow > -this.maxSpeed/5) { + return svg` + + + + + + + + ${this.alertLowType != AlertTypes.caution ? svg` + + + + + + + ` + : svg` + + + + + + + + + ` + } + + + + + `; + } + else { + return nothing; + } + } + + private getAlertHighMask() { + if (this.alertHighType != AlertTypes.none && this.useAlerts && this.alertHigh < this.maxSpeed) { + return svg` + + + + + + + + + + + ${(this.stwSpeed >= this.alertHigh || this.sogSpeed >= this.alertHigh) ? + this.renderPathMaskOfHighAdvice( + [ + { + startAngle: this.getAngle(this.alertHigh), + endAngle: this.getAngle(this.maxSpeed), + fillColor: this.getHighAdviceColor(), + } + ] + ) + : nothing} + + + + + ${this.alertHighType != AlertTypes.caution ? + svg` + + ` : + svg` + + ` + } + + + + ${this.alertHighType != AlertTypes.caution ? + svg` + + + + + + + ` : + svg` + + + + + + + + + ` + } + + + + + `; + } + else { + return nothing; + } + } + + private getSpeedValue() { + if (this.showSpeedAsNumber) { + if (this.showSog && this.showStw) { + if (this.mainSpeedType == SpeedType.SOG) { + return svg` + +
+ ${this.getSpeedField({size: InstrumentFieldSize.enhanced, neutralColor: false, horizontal: true, value: this.sogSpeed, fractionDigits: this.fractionDigits, unit: 'kn', tag: 'SOG-R'})} +
+
+ + + + +
+ ${this.getSpeedField({size: InstrumentFieldSize.enhanced, neutralColor: true, horizontal: true, value: this.stwSpeed, fractionDigits: this.fractionDigits, unit: 'kn', tag: 'STW-R'})} +
+
+ `; + } + else { + return svg` + +
+ ${this.getSpeedField({size: InstrumentFieldSize.enhanced, neutralColor: false, horizontal: true, value: this.stwSpeed, fractionDigits: this.fractionDigits, unit: 'kn', tag: 'STW-R'})} +
+
+ + + + +
+ ${this.getSpeedField({size: InstrumentFieldSize.enhanced, neutralColor: true, horizontal: true, value: this.sogSpeed, fractionDigits: this.fractionDigits, unit: 'kn', tag: 'SOG-R'})} +
+
+ `; + } + } + else if (this.showSog && !this.showStw) { + return svg` + +
+ ${this.getSpeedField({size: InstrumentFieldSize.enhanced, neutralColor: false, horizontal: false, value: this.sogSpeed, fractionDigits: this.fractionDigits, unit: 'kn', tag: 'SOG-R'})} +
+
+ ` + } + else if (this.showStw && !this.showSog) { + return svg` + +
+ ${this.getSpeedField({size: InstrumentFieldSize.enhanced, neutralColor: false, horizontal: false, value: this.stwSpeed, fractionDigits: this.fractionDigits, unit: 'kn', tag: 'STW-R'})} +
+
+ ` + } + else { + return nothing; + } + } + else { + return nothing; + } + } + + private getPrimaryContainer() { + if (this.showSog && this.mainSpeedType == SpeedType.SOG && this.sogSpeed != undefined) { + return svg` + + ${this.renderPrimaryBarArea([ + { + startAngle: this.getAngle(0), + endAngle: this.getAngle(this.getSogSpeed()), + fillColor: Colors.instrumentEnhancedTertiary, + }]) + } + + + + ${this.getMainNeedle(SpeedType.SOG)} + + ` + } + else if (this.showStw && this.mainSpeedType == SpeedType.STW && this.stwSpeed != undefined) { + return svg` + + ${this.renderPrimaryBarArea([ + { + startAngle: this.getAngle(0), + endAngle: this.getAngle(this.getStwSpeed()), + fillColor: Colors.instrumentEnhancedTertiary, + }]) + } + + + + ${this.getMainNeedle(SpeedType.STW)} + + ` + } + else { + return nothing; + } + } + + private getPrimaryNeedle() { + if (this.showSog && this.mainSpeedType == SpeedType.SOG && this.sogSpeed != undefined) { + return svg` + + ${this.getMainNeedle(SpeedType.SOG)} + + ` + } + else if (this.showStw && this.mainSpeedType == SpeedType.STW && this.stwSpeed != undefined) { + return svg` + + ${this.getMainNeedle(SpeedType.STW)} + + ` + } + else { + return nothing; + } + } + + private getSecondaryContainer() { + if ((this.showStw && (this.mainSpeedType == SpeedType.SOG && this.stwSpeed != undefined) || this.showSog && (this.mainSpeedType == SpeedType.STW && this.sogSpeed != undefined))) { + return svg` + + ${this.renderSecondaryBarArea([ + { + startAngle: this.getAngle(0), + endAngle: this.getAngle(this.mainSpeedType == SpeedType.SOG ? this.getStwSpeed() : this.getSogSpeed()), + fillColor: Colors.instrumentRegularTertiary, + }, + ])} + + + ${this.mainSpeedType == SpeedType.SOG ? this.getSecondaryNeedle(SpeedType.STW) : this.getSecondaryNeedle(SpeedType.SOG)} + `; + } + else { + return nothing; + } + } + + private getSpeedField(instrumentField: InstrumentField) { + return html` + + `; + } + + private getAdviceContainerHigh() { + if (this.useAlerts && this.alertHighType != AlertTypes.none && this.alertHigh < this.maxSpeed) { + return svg` + ${ + this.getAlertHighMask() + } + + + + + + + + + + + + + + + + + + + + + + ${renderAdvice( + { + minAngle: this.getAngle(this.alertHigh), + maxAngle: this.getAngle(this.maxSpeed), + type: this.getAdviceType(this.alertHighType), + state: this.getHighState(), + hideMaxTickmark: true, + hideMinTickmark: true + } + )} + + `; + } + else { + return nothing; + } + } + + private getAdviceContainerLow() { + if (this.useAlerts && this.alertLowType != AlertTypes.none && this.alertLow > -this.maxSpeed/5) { + return svg` + ${ + this.getAlertLowMask() + } + + ${renderAdvice( + { + minAngle: this.getAngle(this.minSpeed), + maxAngle: this.getAngle(this.alertLow), + type: this.getAdviceType(this.alertLowType), + state: this.getLowState(), + hideMaxTickmark: true, + hideMinTickmark: true + } + )} + + `; + } + else { + return nothing; + } + } + + private getMainNeedleFillColor(speedType: SpeedType) { + if (speedType == SpeedType.SOG) { + if (this.sogSpeed > this.maxSpeed || this.sogSpeed < this.minSpeed) { + return Colors.alertCautionColor; + } + else { + return Colors.instrumentFramePrimary; + } + } + else { + if (this.stwSpeed > this.maxSpeed || this.stwSpeed < this.minSpeed) { + return Colors.alertCautionColor; + } + else { + return Colors.instrumentEnhancedSecondary; + } + } + } + + // add yellow color for needle for low integrity + private getMainNeedle(speedType: SpeedType) { + return svg` + + + + `; + } + + private getSecondaryNeedleFillColor(speedType: SpeedType) { + if (speedType == SpeedType.SOG) { + if (this.sogSpeed > this.maxSpeed || this.sogSpeed < this.minSpeed) { + return Colors.alertCautionColor; + } + else { + return Colors.instrumentFrameSecondary; + } + } + else { + if (this.stwSpeed > this.maxSpeed || this.stwSpeed < this.minSpeed) { + return Colors.alertCautionColor; + } + else { + return Colors.instrumentRegularSecondary; + } + } + } + + private getSecondaryNeedle(speedType: SpeedType) { + if (speedType == SpeedType.STW) { + return svg` + + + + + `; + } + else { + return svg` + + + + + `; + } + } + + private getLabels() { + if (this.maxSpeed == 25) { + return this.getLabels25(); + } + else { + return this.getLabels50(); + } + } + + private getLabels25() { + return svg` + + + + + + + + + + + + `; + } + + private getLabels50() { + return svg` + + + + + + + + + + `; + } + + private getTickmarks() { + if (this.maxSpeed == 50) { + return this.getTickmarks50(); + } + else { + return this.getTickmarks25(); + } + } + + // maybe remove + getTickmarks25() { + return svg` + + + + + + + + + + + + + `; + } + + getTickmarks50() { + return svg` + + + + + + + + + + + + + + `; + } + + getRadiusMask() { + return svg` + + + + + + `; + } + + private getHighState() { + if (this.showSog && this.sogSpeed >= this.alertHigh) { + return AdviceState.triggered; + } + else if (this.showStw && this.stwSpeed >= this.alertHigh) { + return AdviceState.triggered; + } + else { + return AdviceState.hinted; + } + } + + private getLowState() { + if (this.showSog && this.sogSpeed <= this.alertLow) { + return AdviceState.triggered; + } + else if (this.showStw && this.stwSpeed <= this.alertLow) { + return AdviceState.triggered; + } + else { + return AdviceState.hinted; + } + } + + private getAdviceType(alertType: AlertTypes) { + if (alertType == AlertTypes.caution) { + return AdviceType.caution; + } + else if(alertType == AlertTypes.warning) { + return AdviceType.warning; + } + else if (alertType == AlertTypes.alarm) { + return AdviceType.alarm + } + else { + return AdviceType.advice; + } + } + + private getHighAdviceColor() { + if ((this.sogSpeed < this.alertHigh || !this.showSog) && (this.stwSpeed < this.alertHigh || !this.showStw)) { + return Colors.instrumentTickmarkTertiary; + } + else { + if (this.alertHighType == AlertTypes.alarm) { + return AlertColor.alarmColor; + } + else if (this.alertHighType == AlertTypes.warning) { + return AlertColor.warningColor; + } + else if (this.alertHighType == AlertTypes.caution) { + return AlertColor.cautionColor; + } + else { + return Colors.instrumentTickmarkTertiary; + } + } + } + + getHighAlertColor() { + if (this.sogSpeed >= this.alertHigh) { + return this.getAlertColor(this.alertHighType) + } + else if (this.alertHighType == AlertTypes.none) { + return ''; + } + else { + return Colors.containerBackdrop; + } + } + + private getAlertColor(color: AlertTypes) { + if (color == AlertTypes.caution) { + return AlertColor.cautionColor; + } + else if (color == AlertTypes.warning) { + return AlertColor.warningColor; + } + else if (color == AlertTypes.alarm) { + return AlertColor.alarmColor; + } + return ''; + } + + private renderPathMaskOfHighAdvice(barAreas: WatchBarArea[]): SVGTemplateResult[] | typeof nothing { + if (barAreas.length === 0 || (Math.abs(barAreas[0].endAngle - barAreas[0].startAngle)) < 4.5) { + return nothing; + } + + const CX = 477.284; + const CY = 429; + const RADIUS = 264; + + return barAreas.map((bar) => { + + const startAngle = Math.min(bar.startAngle, bar.endAngle); + const endAngle = Math.max(bar.startAngle, bar.endAngle); + + const path = this.describeSector( + CX, + CY, + RADIUS, + startAngle, + endAngle + ); + + return svg` + + `; + }); + } + + private describeSector( + cx: number, + cy: number, + r: number, + startAngle: number, + endAngle: number + ): string { + + const toRad = (a: number) => (a - 90) * Math.PI / 180; + + const polar = (angle: number) => ({ + x: cx + r * Math.cos(toRad(angle)), + y: cy + r * Math.sin(toRad(angle)), + }); + + const start = polar(startAngle); + const end = polar(endAngle); + + const largeArc = Math.abs(endAngle - startAngle) > 180 ? 1 : 0; + + return ` + M ${cx} ${cy} + L ${start.x} ${start.y} + A ${r} ${r} 0 ${largeArc} 1 ${end.x} ${end.y} + Z + `; + } + + cutTickmarks(startAngle: number, endAngle: number) { + const CX = 477.284; + const CY = 429; + + const OUTER = 289; + const INNER = 265; + + const path = this.describeDonutSector( + CX, + CY, + OUTER, + INNER, + startAngle, + endAngle + ); + + return path; + } + + private describeDonutSector( + cx: number, + cy: number, + rOuter: number, + rInner: number, + startAngle: number, + endAngle: number + ): string { + + const toRad = (a: number) => (a - 90) * Math.PI / 180; + + const polar = (r: number, angle: number) => ({ + x: cx + r * Math.cos(toRad(angle)), + y: cy + r * Math.sin(toRad(angle)), + }); + + const p1 = polar(rOuter, startAngle); + const p2 = polar(rOuter, endAngle); + const p3 = polar(rInner, endAngle); + const p4 = polar(rInner, startAngle); + + const largeArc = Math.abs(endAngle - startAngle) > 180 ? 1 : 0; + + return ` + M ${p1.x} ${p1.y} + A ${rOuter} ${rOuter} 0 ${largeArc} 1 ${p2.x} ${p2.y} + L ${p3.x} ${p3.y} + A ${rInner} ${rInner} 0 ${largeArc} 0 ${p4.x} ${p4.y} + Z + `; + } + +} + +declare global { + interface HTMLElementTagNameMap { + 'ob-speedometer': Speedometer; + } +} \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/tickmark.ts b/packages/openbridge-webcomponents/src/skipper/tickmark.ts new file mode 100644 index 000000000..e11ca542d --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/tickmark.ts @@ -0,0 +1,154 @@ +import {SVGTemplateResult, svg} from 'lit'; + +export interface Tickmark { + angle: number; + type: TickmarkType; + text?: string; + color?: string; +} + +export enum TickmarkType { + zeroLineThick = 'zeroLineThick', + zeroLine = 'zeroLine', + main = 'main', + primary = 'primary', + secondary = 'secondary', + tertiary = 'tertiary', + textOnly = 'textOnly', +} + +export enum TickmarkStyle { + hinted = 'hinted', + regular = 'regular', + enhanced = 'enhanced', + warning = 'warning', + alarm = 'alarm', +} + +export function tickmarkColor(style: TickmarkStyle): string { + if (style === TickmarkStyle.hinted) { + return 'var(--instrument-frame-tertiary-color)'; + } + else if (style === TickmarkStyle.regular) { + return 'var(--instrument-tick-mark-tertiary-color)'; + } + else if (style === TickmarkStyle.warning) { + return 'var(--on-warning-active-color)'; + } + else if (style === TickmarkStyle.alarm) { + return 'var(--on-alarm-active-color)'; + } + else { + return 'var(--instrument-tick-mark-primary-color)'; + } +} + +export function tickmark( + angle: number, + { + size, + style, + scale, + text, + inside, + textRadius, + rotation, + maxDigits, + color, + }: { + size: TickmarkType; + style: TickmarkStyle; + scale: number; + text?: string; + inside: boolean; + textRadius: number; + rotation?: number; + maxDigits: number; + color?: string; + } +): SVGTemplateResult | SVGTemplateResult[] { + // check if scale is not infinite + if (scale === Infinity || scale <= 0) { + throw new Error('Scale is not valid'); + } + let innerRadius: number; + let outerRadius: number; + textRadius = textRadius + (3 / scale + 3) * (inside ? -1 : 1); + const rad = (angle * Math.PI) / 180; + if (size === TickmarkType.primary) { + innerRadius = 328 / 2; + outerRadius = 368 / 2; + } else if (size === TickmarkType.secondary) { + innerRadius = 328 / 2; + outerRadius = 344 / 2; + } else if (size === TickmarkType.main || size === TickmarkType.zeroLine) { + innerRadius = 320 / 2; + outerRadius = 368 / 2; + } else if (size === TickmarkType.zeroLineThick) { + innerRadius = 224 / 2; + outerRadius = 368 / 2; + } else if (size === TickmarkType.tertiary) { + innerRadius = 328 / 2; + outerRadius = 336 / 2; + } else { + return [textSvg(text ?? '', angle, inside, scale, textRadius)]; + } + const colorName = color ?? tickmarkColor(style); + + const x1 = Math.sin(rad) * innerRadius; + const y1 = -Math.cos(rad) * innerRadius; + const x2 = Math.sin(rad) * outerRadius; + const y2 = -Math.cos(rad) * outerRadius; + const strokeWidth = + size === TickmarkType.zeroLine || size === TickmarkType.zeroLineThick + ? 4 + : 1; + const tick = svg``; + if (text) { + if (rotation === undefined) { + return [tick, textSvg(text, angle, inside, scale, textRadius)]; + } else { + const newRadius = + textRadius + ((4 / scale + 5) * (inside ? -1 : 1) * maxDigits) / 2; + const textX = Math.sin(rad) * newRadius; + const textY = -Math.cos(rad) * newRadius; + return [ + tick, + svg`${text}`, + ]; + } + } + return tick; +} + +function textSvg( + text: string, + angle: number, + inside: boolean, + scale: number, + textRadius: number +) { + let positionClass = 'top'; + if (angle === 0) { + positionClass = 'top'; + } else if (angle < 180 && angle > 0) { + positionClass = 'right'; + } else if (angle === 180) { + positionClass = 'bottom'; + } else { + positionClass = 'left'; + } + const rad = (angle * Math.PI) / 180; + const insideGain = inside ? -1 : 1; + const yOffset = (7 / scale) * insideGain; + const xOffset = (6 / scale) * insideGain; + + let textX = Math.sin(rad) * (textRadius + xOffset); + if (angle > 180) { + textX += (4 / scale) * insideGain; + } else if (angle < 180 && angle > 0) { + textX -= (4 / scale) * insideGain; + } + const textY = -Math.cos(rad) * (textRadius + yOffset); + return svg`${text}`; +} diff --git a/packages/openbridge-webcomponents/src/skipper/true-relative/true-relative-styles.ts b/packages/openbridge-webcomponents/src/skipper/true-relative/true-relative-styles.ts new file mode 100644 index 000000000..30aed6107 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/true-relative/true-relative-styles.ts @@ -0,0 +1,75 @@ +import { css } from 'lit'; +export const trueRelativeStyles = css` + + .container { + height: 100%; + width: 100%; + } + + .container > svg { + height: 100%; + width: 100%; + } + + .instrument-field-angle { + grid-area: angle; + padding-top: 11px; + padding-bottom: 4px; + } + + .speed-gauge-value { + position: relative; + font-size: 64; + } + + .satellite-label { + fill: var(--element-active-inverted-color); + font-size: 16px; + font-family: sans-serif; + text-anchor: middle; + dominant-baseline: middle; + pointer-events: none; + } + + .ring { + fill: var(--instrument-enhanced-secondary-color); + } + + .ring-dark { + fill-opacity: 0.75; + } + + .ring-mid { + fill-opacity: 0.55; + } + + .ring-light { + fill-opacity: 0.35; + } + + .circle-dashed { + fill: none; + stroke: var(--instrument-frame-primary-color); + stroke-width: 1.2; + stroke-dasharray: 6 6; + } + + .circle-solid { + fill: none; + stroke: var(--element-active-color); + stroke-width: 2; + } + + .axis { + stroke: var(--instrument-frame-primary-color); + stroke-width: 1.4; + } + + .label { + fill: var(--element-active-color); + font-size: 14px; + font-family: sans-serif; + text-anchor: middle; + dominant-baseline: middle; + } +`; \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/true-relative/true-relative.stories.ts b/packages/openbridge-webcomponents/src/skipper/true-relative/true-relative.stories.ts new file mode 100644 index 000000000..7fd5e94d1 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/true-relative/true-relative.stories.ts @@ -0,0 +1,146 @@ +import type {Meta, StoryObj} from '@storybook/web-components-vite'; +import {widthDecorator} from '../../storybook-util.js'; +import './true-relative.js'; +import { SensorPosition, SpeedType } from '../interfaces.js'; +import { TrueRelativeDirection } from './true-relative.js'; + +const meta: Meta = { + title: 'INSTRUMENT/TrueRelative', + tags: ['alpha'], + component: 'ob-true-relative', + parameters: { + actions: { + handles: ['click'], + }, + }, + args: { + width: 512 + }, + argTypes: { + width: {control: {type: 'range', min: 32, max: 1028, step: 1}}, + speedType: { + options: [ + SpeedType.SOG, + SpeedType.STW + ], + control: {type: 'select'}, + }, + sensorPosition: { + options: [ + SensorPosition.bow, + SensorPosition.middle, + SensorPosition.aft, + ], + control: {type: 'select'}, + }, + maxSpeed: {control: {type: 'range', min: 1, max: 50, step: 1}}, + hdgSpeed: {control: {type: 'range', min: 0, max: 100, step: 0.5}}, + hdgDirection: {control: {type: 'range', min: 0, max: 360, step: 0.5}}, + cogSpeed: {control: {type: 'range', min: 0, max: 100, step: 0.5}}, + cogDirection: {control: {type: 'range', min: 0, max: 360, step: 0.5}}, + windSpeed: {control: {type: 'range', min: 0, max: 100, step: 1}}, + windAngle: {control: {type: 'range', min: 0, max: 360, step: 0.5}}, + currentSpeed: {control: {type: 'range', min: 0, max: 3, step: 0.1}}, + currentAngle: {control: {type: 'range', min: 0, max: 360, step: 0.5}}, + rotationsPerMinute: {control: {type: 'range', min: -10, max: 10, step: 1}}, + direction: { + control: {type: 'select'}, + options: Object.values(TrueRelativeDirection), + }, + }, + decorators: [widthDecorator], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const TrueRelative: Story = { + args: { + width: 512, + speedType: SpeedType.SOG, + maxSpeed: 25, + hdgSpeed: 23.7, + hdgDirection: 0, + cogSpeed: 19.7, + cogDirection: 25, + windSpeed: 17, + windAngle: 30, + currentSpeed: 0.65, + currentAngle: 60, + rotationsPerMinute: 5, + direction: TrueRelativeDirection.NorthUp, + hasNorthArrow: false + }, +}; + +export const NoRot: Story = { + args: { + width: 512, + speedType: SpeedType.SOG, + maxSpeed: 25, + hdgSpeed: 23.7, + hdgDirection: 0, + cogSpeed: 19.7, + cogDirection: 25, + windSpeed: 17, + windAngle: 30, + currentSpeed: 0.65, + currentAngle: 60, + rotationsPerMinute: undefined, + direction: TrueRelativeDirection.NorthUp, + }, +}; + +export const NoHdg: Story = { + args: { + width: 512, + speedType: SpeedType.SOG, + maxSpeed: 25, + hdgSpeed: undefined, + hdgDirection: 0, + cogSpeed: 19.7, + cogDirection: 25, + windSpeed: 17, + windAngle: 30, + currentSpeed: 0.65, + currentAngle: 60, + rotationsPerMinute: undefined, + direction: TrueRelativeDirection.NorthUp, + }, +}; + +export const NoCog: Story = { + args: { + width: 512, + speedType: SpeedType.SOG, + maxSpeed: 25, + hdgSpeed: 23.7, + hdgDirection: 0, + cogSpeed: 19.7, + cogDirection: undefined, + windSpeed: 17, + windAngle: 30, + currentSpeed: 0.65, + currentAngle: 60, + rotationsPerMinute: undefined, + direction: TrueRelativeDirection.NorthUp + }, +}; + +export const NoWindAndCurrent: Story = { + args: { + width: 512, + speedType: SpeedType.SOG, + maxSpeed: 25, + hdgSpeed: 23.7, + hdgDirection: 0, + cogSpeed: 19.7, + cogDirection: 20.67, + windSpeed: undefined, + windAngle: 30, + currentSpeed: undefined, + currentAngle: 60, + rotationsPerMinute: 5, + direction: TrueRelativeDirection.NorthUp + }, +}; \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/true-relative/true-relative.ts b/packages/openbridge-webcomponents/src/skipper/true-relative/true-relative.ts new file mode 100644 index 000000000..5c697147f --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/true-relative/true-relative.ts @@ -0,0 +1,661 @@ +import {LitElement, svg, html, SVGTemplateResult, nothing} from 'lit'; +import {property, state} from 'lit/decorators.js'; +import {customElement} from '../../decorator.js'; +import { trueRelativeStyles } from './true-relative-styles.js'; +import { Colors, SensorPosition, SpeedType, WatchBarArea } from '../interfaces.js'; +import { getWindIcon } from '../wind-icons.js'; +import { getCurrentIcon } from '../current-icons.js'; + +export enum TrueRelativeDirection { + NorthUp = 'northUp', + HeadingUp = 'headingUp', + CourseUp = 'courseUp', +} + +@customElement('ob-true-relative') +export class TrueRelative extends LitElement { + @property({type: Number}) maxSpeed = 25; + + @property({type: Number}) hdgSpeed = 5; + @property({type: Number}) hdgDirection = 0; + + @property({type: Number}) cogSpeed = 5; + @property({type: Number}) cogDirection = 25; + + @property({type: String}) speedType = SpeedType.SOG; // TODO: remove + + @property({type: Number}) windSpeed = 5; + @property({type: Number}) windAngle = 5; + @property({type: Number}) currentSpeed = 5; + @property({type: Number}) currentAngle = 5; + @property({type: Number}) rotationsPerMinute = 1; + + @property({type: String}) direction: TrueRelativeDirection = TrueRelativeDirection.NorthUp; + @property({type: Boolean}) sensorPosition = SensorPosition.bow; + @property({type: Boolean}) hasNorthArrow = false; + + center = {x: 362.039, y: 362.039}; + // 362.039 362.039 + + speedRatio = 1; + + private lowIntegrity = false; + + @state() + private rot = 0; + + rotSpeed = 10; // °/min + endAngle = 0; + + _lastTime = 0; + _animId?: number; + + override firstUpdated() { + this._lastTime = performance.now(); + this._animId = requestAnimationFrame(this._animate); + } + + override connectedCallback() { + super.connectedCallback(); + this._lastTime = performance.now(); + this._animate(this._lastTime); + } + + override disconnectedCallback() { + super.disconnectedCallback(); + cancelAnimationFrame(this._animId!); + } + + _animate = (time: number) => { + const deltaTime = time - this._lastTime; + this._lastTime = time; + + const rotDegPerMs = this.rotSpeed / 60000; + + this.rot = (this.rot + rotDegPerMs * deltaTime) % 360; + + this._animId = requestAnimationFrame(this._animate); + }; + + override render() { + this.setMaxSpeed(); + this.setSpeedRatio(); + this.setRotationsPerMinute(); + + return html` +
+ ${this.getTrueRelative()} +
+ `; + } + + static override styles = [ + trueRelativeStyles + ]; + + private isValidNumber(value: number | undefined): boolean { + return typeof value === 'number' && !isNaN(value); + } + + private get isHdgValid() { + return this.isValidNumber(this.hdgSpeed) && this.isValidNumber(this.hdgDirection); + } + + private get isCogValid() { + return this.isValidNumber(this.cogSpeed) && this.isValidNumber(this.cogDirection); + } + + private get isRotationsPerMinuteValid() { + return this.isValidNumber(this.rotationsPerMinute); + } + + private get isWindValid() { + return this.isValidNumber(this.windSpeed) && this.isValidNumber(this.windAngle); + } + + private get isCurrentValid() { + return this.isValidNumber(this.currentSpeed) && this.isValidNumber(this.currentAngle); + } + + private getRotation(): number { + if (this.direction === TrueRelativeDirection.NorthUp) { + return 0; + } + else if (this.direction === TrueRelativeDirection.HeadingUp) { + return -this.hdgDirection; + } + else if (this.direction === TrueRelativeDirection.CourseUp) { + return -this.cogDirection; + } + else { + return 0; + } + } + + private setMaxSpeed(): void { + if (this.maxSpeed < 25) { + this.maxSpeed = 25; + } + else if (this.maxSpeed > 25) { + this.maxSpeed = 50; + } + } + + setSpeedRatio() { + this.speedRatio = Math.abs(this.hdgSpeed / this.maxSpeed); + } + + setRotationsPerMinute() { + if (this.rotationsPerMinute > 10) { + this.rotationsPerMinute = 10; + } + else if (this.rotationsPerMinute <-10) { + this.rotationsPerMinute = -10; + } + } + + setLowIntegrity(state: boolean): void { + this.lowIntegrity = state; + } + + getLowIntegrity(): boolean { + return this.lowIntegrity; + } + + private getTrueRelative() { + return svg` + + + + ${this.getWatchFace()} + + ${this.getTickmarks()} + + ${this.getLabels()} + + ${this.getCurrent()} + + ${this.getWind()} + + + ${this.getClipPaths()} + + ${this.getVessel()} + + ${this.getCogContainer()} + + ${this.getHdgContainer()} + + ${this.getRotContainer()} + + + `; + } + + private getCogContainer() { + if (this.isCogValid && this.cogSpeed != 0) { + return svg` + + ${this.renderSogContainer()} + + `; + } + else { + return nothing; + } + } + + private getHdgContainer() { + if (this.isHdgValid && this.hdgSpeed != 0) { + return svg` + + ${this.getStwArrowMask()} + ${this.getStwContainer()} + + `; + } + else { + return nothing; + } + + } + + private getRotContainer() { + if (this.isRotationsPerMinuteValid && this.rotationsPerMinute != 0) { + return svg` + + ${this.getRot()} + + `; + } + else { + return nothing; + } + } + + private getWatchFace() { + return svg` + + + `; + } + + getTickmarks() { + return svg` + + + + + + + + + `; + } + + private getLabels() { + return svg` + + + + + + + + + + + + + + ${this.getNorthArrow()} + `; + } + + private getNorthArrow() { + if (this.hasNorthArrow) { + return svg` + + + + + `; + } + else { + return nothing; + } + } + + private getClipPaths() { + return svg` + + + + + `; + } + + private getVessel() { + if (this.isHdgValid) { + return svg` + + ${this.getVesselIcon()} + + `; + } + else { + return nothing; + } + } + + private getVesselIcon() { + return svg` + + + + + + + `; + } + + private getSensorPosition() { + if (this.sensorPosition == SensorPosition.aft) { + return -60; + } + else if (this.sensorPosition == SensorPosition.middle) { + return -20; + } + else { + return 0; // -15; + } + } + + private getStwArrowMask() { + return svg` + + + + + `; + } + + private getHdgDirection(stroke: string, strokeWidth: number, dashed = true) { + return svg` + + + `; + } + + private getStwArrow(stroke: string, strokeWidth: number, fill?: string) { + const cx = 362.039; + const cy = 362.039; + + const intensity = Math.min(Math.max(this.hdgSpeed / this.maxSpeed, 0), 1); + + const minY = cy - 10; + const maxY = 219; + const y = minY - (minY - maxY) * intensity; + + return svg` + + + + + + + + `; + } + + + private getStwContainer() { + return svg` + + + ${this.getHdgDirection(Colors.borderSilhouetteColor, 3, false)} + ${this.getStwArrow(Colors.borderSilhouetteColor, 3)} + + + + + + + ${this.getHdgDirection(Colors.instrumentEnhancedSecondary, 2, true)} + ${this.getStwArrow(Colors.instrumentEnhancedSecondary, 2, Colors.instrumentEnhancedSecondary)} + + + + `; + } + + private renderSogContainer() { + const cx = 362.039; + const cy = 362.039; + + const intensity = Math.min(Math.max(this.cogSpeed / this.maxSpeed, 0), 1); + + const minY = cy - 10; + const maxY = 219; + const y = minY - (minY - maxY) * intensity; + + return svg` + + + + + + + + + + + + + + + + + + + + + + `; + } + + private getCurrent() { + if (this.isCurrentValid) { + return svg` + + ${this.renderCurrentIcon()} + + `; + } + else { + return nothing; + } + } + + renderCurrentIcon() { + const cx = 355.66; + const cy = 360.66; + const radius = 225; + + return svg` + + ${getCurrentIcon(this.currentSpeed)} + + `; + } + + renderWindIcon() { + const cx = 357.66; + const cy = 360.66; + const radius = 225; + + return svg` + + ${getWindIcon(this.windSpeed)} + + `; + } + + private getWind() { + if (this.isWindValid) { + return svg` + + ${this.renderWindIcon()} + + `; + } + else { + return nothing; + } + } + + private getRot() { + this.rotSpeed = this.rotationsPerMinute * 360; + this.endAngle = this.rotationsPerMinute * 18; + + const clipId = "rot-bar-mask"; + + const CX = 361.66; + const CY = 362; + + return svg` + + + + ${this.renderPrimaryBarAreaMask([ + { + startAngle: 0, + endAngle: this.endAngle + (this.rotationsPerMinute > 0 ? 1.5 : -1.5), + fillColor: "white", + } + ])} + + + + + ${this.renderPrimaryBarArea([ + { + startAngle: 0, + endAngle: this.endAngle, + fillColor: Colors.instrumentRegularTertiary, + } + ])} + + + + + + + + + ${[0, 72, 144, 216, 288].map(a => { + const r = 176; + const rad = (a - 90) * Math.PI / 180; + const x = r * Math.cos(rad); + const y = r * Math.sin(rad); + + return svg` + + `; + })} + + + + + + `; + } + + private renderPrimaryBarArea(barAreas: WatchBarArea[]): SVGTemplateResult[] | typeof nothing { + if (!barAreas.length) return nothing; + + return barAreas.map(bar => { + const start = Math.min(bar.startAngle, bar.endAngle); + const end = Math.max(bar.startAngle, bar.endAngle); + + const d = this.describeArc(168, 184, start, end); + + return svg` + + `; + }); + } + + private renderPrimaryBarAreaMask(barAreas: WatchBarArea[]): SVGTemplateResult[] | typeof nothing { + if (!barAreas.length) return nothing; + + return barAreas.map(bar => { + const start = Math.min(bar.startAngle, bar.endAngle); + const end = Math.max(bar.startAngle, bar.endAngle); + + const d = this.describeArc(164, 180, start, end); // malo veći kao OpenBridge + + return svg` + + `; + }); + } + + private describeArc(r: number, R: number, startAngle: number, endAngle: number) { + const toRad = (a: number) => (a - 90) * Math.PI / 180; + + const largeArc = endAngle - startAngle > 180 ? 1 : 0; + + const x1 = R * Math.cos(toRad(startAngle)); + const y1 = R * Math.sin(toRad(startAngle)); + + const x2 = R * Math.cos(toRad(endAngle)); + const y2 = R * Math.sin(toRad(endAngle)); + + const x3 = r * Math.cos(toRad(endAngle)); + const y3 = r * Math.sin(toRad(endAngle)); + + const x4 = r * Math.cos(toRad(startAngle)); + const y4 = r * Math.sin(toRad(startAngle)); + + return ` + M ${x1} ${y1} + A ${R} ${R} 0 ${largeArc} 1 ${x2} ${y2} + L ${x3} ${y3} + A ${r} ${r} 0 ${largeArc} 0 ${x4} ${y4} + Z + `; + } + +} + +declare global { + interface HTMLElementTagNameMap { + 'ob-true-relative': TrueRelative; + } +} \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/utils/storybook-helpers.ts b/packages/openbridge-webcomponents/src/skipper/utils/storybook-helpers.ts new file mode 100644 index 000000000..a2f028665 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/utils/storybook-helpers.ts @@ -0,0 +1,15 @@ +export function mapBooleanArgs(args: any): any { + const out = { ...args }; + Object.entries(args).forEach( + (entry) => { + const k = entry[0]; + let v = entry[1]; + if (v === true) { + v = '' + } else if (v === false) { + v = undefined + } + out[k] = v + }) + return out +} \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/utils/uuid.ts b/packages/openbridge-webcomponents/src/skipper/utils/uuid.ts new file mode 100644 index 000000000..d74b37ad5 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/utils/uuid.ts @@ -0,0 +1,6 @@ +export function uuidv4() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); +} \ No newline at end of file diff --git a/packages/openbridge-webcomponents/src/skipper/vessel-view/vessel-styles.ts b/packages/openbridge-webcomponents/src/skipper/vessel-view/vessel-styles.ts new file mode 100644 index 000000000..ddfdf0ea3 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/vessel-view/vessel-styles.ts @@ -0,0 +1,85 @@ +import {css} from 'lit'; +export const vesselStyles = css` + .container { + height: 100%; + width: 100%; + } + + .container > svg { + height: 100%; + width: 100%; + } + + .satellite-label { + fill: var(--element-active-inverted-color); + font-size: 16px; + font-family: sans-serif; + text-anchor: middle; + dominant-baseline: middle; + pointer-events: none; + } + + .ring { + fill: var(--instrument-enhanced-secondary-color); + } + + .ring-dark { + fill-opacity: 0.75; + } + + .ring-mid { + fill-opacity: 0.55; + } + + .ring-light { + fill-opacity: 0.35; + } + + .circle-dashed { + fill: none; + stroke: var(--instrument-frame-primary-color); + stroke-width: 1.2; + stroke-dasharray: 6 6; + } + + .circle-solid { + fill: none; + stroke: var(--element-active-color); + stroke-width: 2; + } + + .axis { + stroke: var(--instrument-frame-primary-color); + stroke-width: 1.4; + } + + .label { + fill: var(--element-active-color); + font-size: 14px; + font-family: sans-serif; + text-anchor: middle; + dominant-baseline: middle; + } + + .both-views { + width: 400px; + overflow-x: hidden; + + display: flex; + justify-content: center; + align-items: center; + } + + .both-views-inner { + transform: scale(0.69); + transform-origin: center; + + display: flex; + flex-direction: column; + align-items: center; + } + + .top-down-view { + margin-left: 60px; + } +`; diff --git a/packages/openbridge-webcomponents/src/skipper/vessel-view/vessel-types.ts b/packages/openbridge-webcomponents/src/skipper/vessel-view/vessel-types.ts new file mode 100644 index 000000000..b19f9e2bc --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/vessel-view/vessel-types.ts @@ -0,0 +1,827 @@ +import {nothing, svg, type TemplateResult} from 'lit'; +import {Colors} from '../interfaces.js'; +import {VesselTypes, ViewType} from './vessel.js'; + +type VesselTypeData = { + side: TemplateResult; + topDown: TemplateResult; + sideTopY: number; + sideBottomY: number; +}; + +type DimHeightVesselParams = { + vesselHeight: number; + textY: number; + arrowPath: string; + lineStart: number; + lineEnd: number; +}; + +type getSideViewParams = { + sensorX: number; //!!! + sensorY: number; //!!! + mastEndY: number; + verticalGuideStartY: number; + verticalGuideEndY: number; + ARCH_X: number; + ARCH_Y: number; + sensorHeightOverKeel: number; //!!! + sternTextX: number; + sternLine: { + startX: number; + endX: number; + arrowPath: string; + textX: number; + y: number; + }; + + ARCH_BOTTOM_Y: number; + bowTextX: number; + bowLine: { + startX: number; + endX: number; + arrowPath: string; + textX: number; + y: number; + }; + sensorToCCRP: number; + + dim: { + arrowPath: string; + startX: number; + endX: number; + y: number; + textX: number; + }; //!!! + coneLeftX: number; + coneRightX: number; + coneBottomY: number; + toggleSLAndDLSensor: boolean; + textOffset: number; //!!! + ccrpX: number; //!!! + + vesselLengthComputed: number; + sternToCCRP: number; + bowToCCRP: number; + vesselHeight: number; +}; + +type getTopDownViewParams = { + sensorX: number; + ccrpX: number; + sensorHeightOverKeel: number; + toggleSLAndDLSensor: boolean; + vesselLengthComputed: number; + + sensorYTopView: number; + sensorPortStarboardOffset: number; + sensorDim: { + arrowPath: string; + lineStart: number; + lineEnd: number; + textY: number; + }; + DIM_X: number; + showSensorDim: boolean; + yAxisCCRPPos: number; + starboardDimensionLine: {startY: number; endY: number}; + getArrowHalfHeight: () => number; + ARROW_SIZE: number; + getMidY: (start: number, end: number) => number; + starboardToCCRP: number; + portDimensionLine: {startY: number; endY: number}; + portToCCRP: number; + vesselWidthComputed: number; +}; + +type sensorPositionParams = { + sensorX: number; + sensorY: number; + sensorHeightOverKeel: number; + toggleSLAndDLSensor: boolean; + sensorToCCRP: number; + dim: { + arrowPath: string; + startX: number; + endX: number; + y: number; + textX: number; + }; + textOffset: number; + viewMode: ViewType; +}; + +type dimPortToCCRPParams = { + portDimensionLine: {startY: number; endY: number}; + getMidY: (startY: number, endY: number) => number; + portToCCRP: number; + ARROW_SIZE: number; + getArrowHalfHeight: () => number; +}; + +type dimStarboardToCCRPParams = { + starboardDimensionLine: {startY: number; endY: number}; + getMidY: (startY: number, endY: number) => number; + starboardToCCRP: number; + ARROW_SIZE: number; + getArrowHalfHeight: () => number; +}; + +type horizontalCCRPParams = {yAxisCCRPPos: number}; + +type verticalCCRPParams = {xAxisCCRPPos: number}; + +type sensorPosTopDownParams = { + sensorX: number; + sensorYTopView: number; +}; + +export function getVesselType(vesselType: string): VesselTypeData { + if (vesselType === VesselTypes.TANKER) { + const {TANKER_SIDE_VIEW, TANKER_TOP_DOWN_VIEW} = getVesselTanker(); + + return { + side: TANKER_SIDE_VIEW, + topDown: TANKER_TOP_DOWN_VIEW, + sideTopY: 117, + sideBottomY: 261, + }; + } else if (vesselType === VesselTypes.CARGO) { + const {CARGO_SIDE_VIEW, CARGO_TOP_DOWN_VIEW} = getVesselCargo(); + + return { + side: CARGO_SIDE_VIEW, + topDown: CARGO_TOP_DOWN_VIEW, + sideTopY: 117, + sideBottomY: 261, + }; + } else if (vesselType === VesselTypes.CAR_FERRY) { + const {CAR_FERRY_SIDE_VIEW, CAR_FERRY_TOP_DOWN_VIEW} = getVesselCarFerry(); + + return { + side: CAR_FERRY_SIDE_VIEW, + topDown: CAR_FERRY_TOP_DOWN_VIEW, + sideTopY: 180, + sideBottomY: 264, + }; + } else if (vesselType === VesselTypes.FISHING) { + const {FISHING_SIDE_VIEW, FISHING_TOP_DOWN_VIEW} = getVesselFishing(); + + return { + side: FISHING_SIDE_VIEW, + topDown: FISHING_TOP_DOWN_VIEW, + sideTopY: 126, + sideBottomY: 270, + }; + } + + return { + side: svg``, + topDown: svg``, + sideTopY: 117, + sideBottomY: 261, + }; +} + +function sensorPositioning( + sensorPosParams: sensorPositionParams +): TemplateResult { + return svg` + Sensor + ${ + sensorPosParams.sensorToCCRP !== 0 + ? svg` + + + + + + + + ${Math.abs(sensorPosParams.sensorToCCRP)} + + + ` + : nothing + } + `; +} + +function dimLengthLineSideView(totalLength: number): TemplateResult { + return svg` + ${totalLength} + + `; +} + +function dimHeightVesselSide(params: DimHeightVesselParams): TemplateResult { + return svg` + + ${params.vesselHeight} + + + + + + +`; +} + +function dimSternToCCRPSide(sideViewParams: getSideViewParams): TemplateResult { + return svg`${textLabel({ + posX: sideViewParams.sternTextX - 7, + posY: 297.656, + label: sideViewParams.sternToCCRP, + })} + + `; +} + +function dimBowToCCRPSide(sideViewParams: getSideViewParams): TemplateResult { + return svg`${textLabel({ + posX: sideViewParams.bowTextX - 7, + posY: 297.656, + label: sideViewParams.bowToCCRP, + })} + + `; +} + +function dimHeightSensorIndicatorSide( + sideViewParams: getSideViewParams, + keelRefPoint: boolean +): TemplateResult { + return svg` + + + ${textLabel({posX: 6.5, posY: 15.656, label: !keelRefPoint ? sideViewParams.sensorHeightOverKeel : 'Keel'})} + + `; +} + +function getSensorCone(sideViewParams: getSideViewParams): TemplateResult { + return svg` + + + `; +} + +export function getSideView( + vesselType: string, + sideViewParams: getSideViewParams, + sensorPos: sensorPositionParams, + dimHeightVesselParams: DimHeightVesselParams +): TemplateResult { + const VESSEL_TYPE = getVesselType(vesselType); + return svg` + + + + + + ${ + !sideViewParams.toggleSLAndDLSensor + ? svg` + ${dimHeightSensorIndicatorSide(sideViewParams, false)} + ` + : nothing + } + ${VESSEL_TYPE.side} + + ${dimLengthLineSideView(sideViewParams.vesselLengthComputed)} + + + ${dimSternToCCRPSide(sideViewParams)} + ${dimHeightSensorIndicatorSide(sideViewParams, true)} + + ${dimBowToCCRPSide(sideViewParams)} + + + + ${dimHeightVesselSide(dimHeightVesselParams)} + ${sensorPositioning(sensorPos)} + ${ + sideViewParams.toggleSLAndDLSensor + ? svg` + + ${getSensorCone(sideViewParams)} + + ` + : nothing + } + + + + ${textLabel({ + posX: sideViewParams.ccrpX - 16, + posY: 320, + label: 'CCRP', + fontWeight: 'bold', + })} + + + `; +} +/// +// +/* +TOP DOWN VIEW FUNCTIONS +*/ +function dimLengthLineTopView(totalLength: number): TemplateResult { + return svg` + ${textLabel({posX: 230, posY: 314.156, label: totalLength})} + + `; +} + +function dimWidthLineTopView(totalWidth: number): TemplateResult { + return svg` + ${textLabel({posX: 0, posY: 237, label: totalWidth})} + + `; +} + +function dimPortToCCRPLine(dimPortParams: dimPortToCCRPParams): TemplateResult { + return svg` + ${textLabel({ + posX: 448, + posY: dimPortParams.getMidY( + dimPortParams.portDimensionLine.startY, + dimPortParams.portDimensionLine.endY + ), + label: dimPortParams.portToCCRP, + })} + + + + `; +} + +function dimStarboardToCCRPLine( + dimStarboardParams: dimStarboardToCCRPParams +): TemplateResult { + return svg` + ${textLabel({ + posX: 448, + posY: dimStarboardParams.getMidY( + dimStarboardParams.starboardDimensionLine.startY, + dimStarboardParams.starboardDimensionLine.endY + ), + label: dimStarboardParams.starboardToCCRP, + })} + + + `; +} + +function horizontalCCRPTopView( + yAxisCCRPParams: horizontalCCRPParams +): TemplateResult { + return svg` + ${textLabel({posX: 475, posY: yAxisCCRPParams.yAxisCCRPPos, label: 'CCRP'})}`; +} + +function verticalCCRPTopView( + xAxisCCRPParams: verticalCCRPParams +): TemplateResult { + return svg` + ${textLabel({posX: xAxisCCRPParams.xAxisCCRPPos - 15, posY: 296.156, label: 'CCRP'})} + `; +} + +function sensorPositionTopView( + sensorPos: sensorPosTopDownParams +): TemplateResult { + return svg` + + + `; +} + +function textLabel(position: { + posX: number; + posY: number; + label: string | number; + fontWeight?: 'bold'; +}): TemplateResult { + return svg` + ${position.label} + `; +} + +function getSensorHeightIndicator( + topDownViewParams: getTopDownViewParams +): TemplateResult { + return svg` + + + + + + ${textLabel({ + posX: 177, + posY: 165.156, + label: topDownViewParams.toggleSLAndDLSensor + ? 'Keel' + : '+' + topDownViewParams.sensorHeightOverKeel, + })} + + `; +} + +function verticalDimSensorToCCRPLine( + topDownViewParams: getTopDownViewParams +): TemplateResult { + return svg` + + + + `; +} + +export function getTopDownView( + vesselType: string, + topDownViewParams: getTopDownViewParams, + dimPortToCCRPParams: dimPortToCCRPParams, + dimStarboardToCCRPParams: dimStarboardToCCRPParams, + horizontalCCRPParams: horizontalCCRPParams, + verticalCCRPParams: verticalCCRPParams, + sensorPosTopDownParams: sensorPosTopDownParams +): TemplateResult { + const VESSEL_TYPE = getVesselType(vesselType); + return svg` + + ${VESSEL_TYPE.topDown} + + ${dimWidthLineTopView(topDownViewParams.vesselWidthComputed)} + + ${dimPortToCCRPLine({ + portDimensionLine: dimPortToCCRPParams.portDimensionLine, + getMidY: dimPortToCCRPParams.getMidY, + portToCCRP: dimPortToCCRPParams.portToCCRP, + ARROW_SIZE: dimPortToCCRPParams.ARROW_SIZE, + getArrowHalfHeight: dimPortToCCRPParams.getArrowHalfHeight, + })} + + ${dimStarboardToCCRPLine({ + starboardDimensionLine: dimStarboardToCCRPParams.starboardDimensionLine, + getMidY: dimStarboardToCCRPParams.getMidY, + starboardToCCRP: dimStarboardToCCRPParams.starboardToCCRP, + ARROW_SIZE: dimStarboardToCCRPParams.ARROW_SIZE, + getArrowHalfHeight: dimStarboardToCCRPParams.getArrowHalfHeight, + })} + ${dimLengthLineTopView(topDownViewParams.vesselLengthComputed)} + + + + ${horizontalCCRPTopView(horizontalCCRPParams)} + ${verticalCCRPTopView(verticalCCRPParams)} + + ${sensorPositionTopView(sensorPosTopDownParams)} + ${textLabel({ + posX: sensorPosTopDownParams.sensorX - 30, + posY: sensorPosTopDownParams.sensorYTopView + 20, + label: 'Sensor', + })} + ${ + topDownViewParams.showSensorDim + ? svg` + ${verticalDimSensorToCCRPLine(topDownViewParams)} + + ${textLabel({ + posX: topDownViewParams.DIM_X + 5, + posY: topDownViewParams.sensorDim.textY, + label: Math.abs(topDownViewParams.sensorPortStarboardOffset), + })} + + ` + : nothing + } + + ${getSensorHeightIndicator(topDownViewParams)} +
+ `; +} + +export function getVesselIcon( + vesselType: string, + sideViewParams: getSideViewParams, + sensorPositionParams: sensorPositionParams, + topDownViewParams: getTopDownViewParams, + portToCCRPParams: dimPortToCCRPParams, + starboardToCCRPParams: dimStarboardToCCRPParams, + horizontalCCRPParams: horizontalCCRPParams, + verticalCCRPParams: verticalCCRPParams, + sensorPosTopDownParams: sensorPosTopDownParams, + dimHeightVesselParams: DimHeightVesselParams +) { + const SIDE_VIEW = getSideView( + vesselType, + sideViewParams, + sensorPositionParams, + dimHeightVesselParams + ); + const TOP_DOWN_VIEW = getTopDownView( + vesselType, + topDownViewParams, + portToCCRPParams, + starboardToCCRPParams, + horizontalCCRPParams, + verticalCCRPParams, + sensorPosTopDownParams + ); + + return {SIDE_VIEW, TOP_DOWN_VIEW}; +} + +function getVesselTanker(): { + TANKER_SIDE_VIEW: TemplateResult; + TANKER_TOP_DOWN_VIEW: TemplateResult; +} { + const TANKER_SIDE_VIEW = svg` + + + + + + + + + + + + `; + + const TANKER_TOP_DOWN_VIEW = svg` + + + + + + + + `; + + return {TANKER_SIDE_VIEW, TANKER_TOP_DOWN_VIEW}; +} + +function getVesselCargo(): { + CARGO_SIDE_VIEW: TemplateResult; + CARGO_TOP_DOWN_VIEW: TemplateResult; +} { + const CARGO_SIDE_VIEW = svg` + + + + + + + + +`; + + const CARGO_TOP_DOWN_VIEW = svg` + + + + +`; + + return {CARGO_SIDE_VIEW, CARGO_TOP_DOWN_VIEW}; +} + +function getVesselCarFerry(): { + CAR_FERRY_SIDE_VIEW: TemplateResult; + CAR_FERRY_TOP_DOWN_VIEW: TemplateResult; +} { + const CAR_FERRY_SIDE_VIEW = svg` + + + + + `; + + const CAR_FERRY_TOP_DOWN_VIEW = svg` + + + + + + + + +`; + + return {CAR_FERRY_SIDE_VIEW, CAR_FERRY_TOP_DOWN_VIEW}; +} + +function getVesselFishing(): { + FISHING_SIDE_VIEW: TemplateResult; + FISHING_TOP_DOWN_VIEW: TemplateResult; +} { + const FISHING_SIDE_VIEW = svg` + + + + + + + `; + + const FISHING_TOP_DOWN_VIEW = svg` + + + + + + + + + + + + + + + + + `; + + return {FISHING_SIDE_VIEW, FISHING_TOP_DOWN_VIEW}; +} + +/* + + + + + + + + + + + + + + + + + */ diff --git a/packages/openbridge-webcomponents/src/skipper/vessel-view/vessel.stories.ts b/packages/openbridge-webcomponents/src/skipper/vessel-view/vessel.stories.ts new file mode 100644 index 000000000..5e4e8a2f1 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/vessel-view/vessel.stories.ts @@ -0,0 +1,64 @@ +import type {Meta, StoryObj} from '@storybook/web-components-vite'; +import {widthDecorator} from '../../storybook-util.js'; +import {Vessel, VesselTypes, ViewType} from './vessel.js'; +import './vessel.js'; + +const meta: Meta = { + title: 'INSTRUMENT/Vessel', + tags: ['autodocs', '6.0'], + component: 'ob-vessel-view', + + parameters: { + actions: { + handles: ['click'], + }, + }, + args: { + width: 512, + height: 264, + }, + argTypes: { + width: {control: {type: 'range', min: 32, max: 1028, step: 1}}, + vesselType: { + options: [ + VesselTypes.CARGO, + VesselTypes.TANKER, + VesselTypes.FISHING, + VesselTypes.CAR_FERRY, + ], + control: {type: 'select'}, + }, + viewMode: { + options: [ViewType.SIDE, ViewType.TOP, ViewType.BOTH], + control: {type: 'select'}, + }, + }, + decorators: [widthDecorator], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Vessel_tanker: Story = { + args: { + // width: 512, + vesselHeight: 40, + + bowToCCRP: 50, + sternToCCRP: 50, + sensorToCCRP: 0, + sensorHeightOverKeel: 50, + portToCCRP: 15, + starboardToCCRP: 15, + sensorPortStarboardOffset: 0, + vesselType: VesselTypes.CARGO, + viewMode: ViewType.SIDE, + toggleSLAndDLSensor: true, + }, +}; + +export const Vessel_cruiser: Story = { + args: { + width: 512, + }, +}; diff --git a/packages/openbridge-webcomponents/src/skipper/vessel-view/vessel.ts b/packages/openbridge-webcomponents/src/skipper/vessel-view/vessel.ts new file mode 100644 index 000000000..f9e4a4c0a --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/vessel-view/vessel.ts @@ -0,0 +1,447 @@ +import {LitElement, html} from 'lit'; +import {property} from 'lit/decorators.js'; +import {customElement} from '../../decorator.js'; + +import {vesselStyles} from './vessel-styles.js'; +import {getSideView} from './vessel-types.js'; +import {getTopDownView} from './vessel-types.js'; +import {getVesselType} from './vessel-types.js'; + +export enum VesselTypes { + FISHING = 'FISHING', + TANKER = 'TANKER', + CARGO = 'CARGO', + CAR_FERRY = 'CAR_FERRY', +} + +export enum ViewType { + SIDE = 'SIDE', + TOP = 'TOP', + BOTH = 'BOTH', +} + +@customElement('ob-vessel-view') +export class Vessel extends LitElement { + @property({type: Number}) vesselWidth: number = 30; + @property({type: Number}) vesselHeight: number = 50; + @property({type: Number}) bowToCCRP: number = 12; + @property({type: Number}) sternToCCRP: number = 13; + @property({type: Number}) starboardToCCRP: number = 100; + @property({type: Number}) portToCCRP: number = 15; + @property({type: Number}) sensorHeightOverKeel: number = 50; + @property({type: Number}) sensorToCCRP: number = 0; + @property({type: String}) vesselType: VesselTypes = VesselTypes.CARGO; + @property({type: String}) viewMode: ViewType = ViewType.TOP; + @property({type: Number}) sensorPortStarboardOffset: number = 0; + @property({type: Boolean}) toggleSLAndDLSensor: boolean = false; + //values for SIDE_VIEW + private readonly MIN_X = 37; + private readonly MAX_X = 444; + private readonly LINE_Y = 303; + private readonly ARROW_SIZE = 5; + private readonly VESSEL_BOTTOM_Y = 260; + private readonly DIM_TOP_Y = 117; + private readonly ARCH_HEIGHT = 40; + //values for TOP_DOWN_VIEW + private readonly TOP_Y = 193; + private readonly BOTTOM_Y = 271; + + override render() { + return html`
${this.getVessel()}
`; + } + + static override styles = [vesselStyles]; + + private getScaledX(value: number) { + const length = this.vesselLengthComputed; + //fallback logic if both sternToCCRP and bowToCCRP are 0 + if (length === 0) { + return this.MIN_X; // fallback position + } + + const ratio = value / length; + return this.MIN_X + ratio * (this.MAX_X - this.MIN_X); + } + + private buildDimensionLine( + startX: number, + endX: number, + yAxis: number = this.LINE_Y + ) { + const y = yAxis; + const a = this.ARROW_SIZE; + + const arrowPath = ` + M${startX} ${y} + L${startX + a} ${y + 2.887} + L${startX + a} ${y - 2.887} + Z + + M${endX} ${y} + L${endX - a} ${y - 2.887} + L${endX - a} ${y + 2.887} + Z + `; + + return { + startX, + endX, + arrowPath, + textX: (startX + endX) / 2, + y, + }; + } + + private getSternLine() { + const startX = this.MIN_X; + const endX = this.getScaledX(this.sternToCCRP ?? 0); + + return this.buildDimensionLine(startX, endX); + } + + private getBowLine() { + const startX = this.getScaledX(this.sternToCCRP ?? 0); + const endX = this.MAX_X; + + return this.buildDimensionLine(startX, endX); + } + + private getCCRPX() { + return this.getScaledX(this.sternToCCRP); + } + + get vesselLengthComputed() { + return this.sternToCCRP + this.bowToCCRP; + } + + private getOffsetInPixels(value: number) { + const length = this.vesselLengthComputed; + if (length === 0) return 0; + + const ratio = value / length; + return ratio * (this.MAX_X - this.MIN_X); + } + + private getOffsetYInPixels(value: number) { + const total = this.vesselWidthComputed; + + if (total === 0) return 0; + + const ratio = value / total; + + return ratio * (this.BOTTOM_Y - this.TOP_Y); + } + + private getVesselTopY(x: number) { + const t = (x - this.MIN_X) / (this.MAX_X - this.MIN_X); + + // curved ends + flat middle + const baseY = 210; + const curvature = 25; + + const curve = curvature * (Math.pow(t - 0.5, 2) * 4); // parabola + + return baseY + curve; + } + + override updated(changedProps: Map) { + if (changedProps.has('sternToCCRP')) { + if (this.sternToCCRP < 0) { + this.sternToCCRP = 0; + } + } + + if (changedProps.has('bowToCCRP')) { + if (this.bowToCCRP < 0) { + this.bowToCCRP = 0; + } + } + } + //////// + //TOP DOWN VIEW LOGIC + //////// + + get vesselWidthComputed() { + return (this.portToCCRP ?? 0) + (this.starboardToCCRP ?? 0); + } + + get yAxisCCRPPos() { + const width = this.BOTTOM_Y - this.TOP_Y; + + if (this.vesselWidthComputed === 0) return this.TOP_Y; + + const CCRPY = + this.TOP_Y + (this.portToCCRP / this.vesselWidthComputed) * width; + + return Math.max(this.TOP_Y, Math.min(this.BOTTOM_Y, CCRPY)); + } + + get portDimensionLine() { + const startY = this.TOP_Y; + const endY = this.yAxisCCRPPos; + return {startY, endY}; + } + + get starboardDimensionLine() { + const startY = this.yAxisCCRPPos; + const endY = this.BOTTOM_Y; + return {startY, endY}; + } + + private getMidY(start: number, end: number) { + return (start + end) / 2; + } + + private buildVerticalDimensionLine(x: number, startY: number, endY: number) { + const a = this.ARROW_SIZE; + const h = a * 0.577; + + const arrowPath = ` + M${x} ${startY} + L${x - h} ${startY + a} + L${x + h} ${startY + a} + Z + + M${x} ${endY} + L${x - h} ${endY - a} + L${x + h} ${endY - a} + Z + `; + + return { + arrowPath, + lineStart: startY + a, + lineEnd: endY - a, + textY: (startY + endY) / 2, + }; + } + + //////// + //COMMON VIEW LOGIC + //////// + private getArrowHalfHeight(): number { + return this.ARROW_SIZE * 0.577; + } + + toggleVesselViewer(): void { + // this.sideTopDownViewToggle = !this.sideTopDownViewToggle; + } + + getVessel() { + const vesselTypeData = getVesselType(this.vesselType); + + const dimTopY = vesselTypeData.sideTopY; + const dimBottomY = vesselTypeData.sideBottomY; + //vessel height dim line side view + const vesselHeightDim = { + vesselHeight: this.vesselHeight, + ...this.buildVerticalDimensionLine( + 18, // X position (left side) + dimTopY, // dynamic top from vessel type + dimBottomY // dynamic bottom from vessel type + ), + }; + + //stern dimensions + const sternLine = this.getSternLine(); + const sternTextX = (sternLine.startX + sternLine.endX) / 2; + //bow dimensions + const bowLine = this.getBowLine(); + const bowTextX = (bowLine.startX + bowLine.endX) / 2; + //CCRP line position + const ccrpX = this.getCCRPX(); + //sensor Y (mast) line + const sensorX = Math.max( + this.MIN_X, + Math.min(this.MAX_X, ccrpX + this.getOffsetInPixels(this.sensorToCCRP)) + ); + const mastEndY = this.getVesselTopY(sensorX); + //Sensor Y position + // const dimTopY = this.DIM_TOP_Y; + // const dimBottomY = this.VESSEL_BOTTOM_Y; + + const dimHeightPx = dimBottomY - dimTopY; + + const ratio = + this.vesselHeight === 0 + ? 0 + : this.sensorHeightOverKeel / this.vesselHeight; + + // ✅ map directly into dimension scale + + const sensorY = this.toggleSLAndDLSensor + ? dimBottomY // ✅ DL mode → glued to keel + : dimBottomY - ratio * dimHeightPx; + + //CCRP to sensor DIM line + const dimStartX = Math.min(sensorX, ccrpX); + const dimEndX = Math.max(sensorX, ccrpX); + let DIM_Y: number; + + if (this.toggleSLAndDLSensor) { + // halfway between mid-height and bottom dim line + const midY = (this.DIM_TOP_Y + this.VESSEL_BOTTOM_Y) / 2; + + DIM_Y = (midY + this.VESSEL_BOTTOM_Y) * 0.63; + } else { + // original position + DIM_Y = 85; + } + + const dim = this.buildDimensionLine(dimStartX, dimEndX, DIM_Y); + const textOffset = Math.abs(this.sensorToCCRP).toString().length * 3; + //positioning vertical arch dimensions for dynamic usage + const ARCH_X = this.MAX_X; // tweak spacing + const ARCH_Y = sensorY - this.ARCH_HEIGHT; // keep same vertical alignment + + //positioning static keel arch dimension + const keelY = this.VESSEL_BOTTOM_Y; + const ARCH_BOTTOM_Y = keelY - 40; + //vertical dashed indicator line + const verticalGuideStartY = sensorY; + const verticalGuideEndY = DIM_Y; + //cone dimension + const CONE_LENGTH = 40; + const coneLeftX = sensorX - CONE_LENGTH * 0.7; + const coneRightX = sensorX + CONE_LENGTH * 0.7; + + const coneBottomY = sensorY + CONE_LENGTH; + //////// + //TOP DOWN VIEW LOGIC + //////// + const sensorYOffset = this.getOffsetYInPixels( + this.sensorPortStarboardOffset + ); + + const sensorYRaw = this.yAxisCCRPPos + sensorYOffset; + + const sensorYTopView = Math.max( + this.TOP_Y, + Math.min(this.BOTTOM_Y, sensorYRaw) + ); + + //vertical Dim line from CCRP to sensor + const showSensorDim = this.sensorPortStarboardOffset !== 0; + const DIM_X = sensorX + 15; + + const dimStartY = Math.min(sensorYTopView, this.yAxisCCRPPos); + const dimEndY = Math.max(sensorYTopView, this.yAxisCCRPPos); + + const sensorDim = this.buildVerticalDimensionLine( + DIM_X, + dimStartY, + dimEndY + ); + + const SIDE_VIEW = getSideView( + this.vesselType, + { + sensorX, + sensorY, + mastEndY, + verticalGuideStartY, + verticalGuideEndY, + ARCH_X, + ARCH_Y, + sensorHeightOverKeel: this.sensorHeightOverKeel, + sternTextX, + sternLine, + ARCH_BOTTOM_Y, + bowTextX, + bowLine, + sensorToCCRP: this.sensorToCCRP, + dim, + coneLeftX, + coneRightX, + coneBottomY, + toggleSLAndDLSensor: this.toggleSLAndDLSensor, + textOffset, + ccrpX, + vesselLengthComputed: this.vesselLengthComputed, + sternToCCRP: this.sternToCCRP, + bowToCCRP: this.bowToCCRP, + vesselHeight: this.vesselHeight, + }, + { + sensorX, + sensorY, + sensorHeightOverKeel: this.sensorHeightOverKeel, + toggleSLAndDLSensor: this.toggleSLAndDLSensor, + sensorToCCRP: this.sensorToCCRP, + dim, + textOffset, + viewMode: this.viewMode, + }, + vesselHeightDim + ); + + const TOP_DOWN_VIEW = getTopDownView( + this.vesselType, + { + sensorX, + ccrpX, + sensorHeightOverKeel: this.sensorHeightOverKeel, + toggleSLAndDLSensor: this.toggleSLAndDLSensor, + vesselLengthComputed: this.vesselLengthComputed, + sensorYTopView, + sensorPortStarboardOffset: this.sensorPortStarboardOffset, + sensorDim, + DIM_X, + showSensorDim, + yAxisCCRPPos: this.yAxisCCRPPos, + starboardDimensionLine: this.starboardDimensionLine, + getArrowHalfHeight: this.getArrowHalfHeight.bind(this), + ARROW_SIZE: this.ARROW_SIZE, + getMidY: this.getMidY, + starboardToCCRP: this.starboardToCCRP, + portDimensionLine: this.portDimensionLine, + portToCCRP: this.portToCCRP, + vesselWidthComputed: this.vesselWidthComputed, + }, + { + portDimensionLine: this.portDimensionLine, + getMidY: this.getMidY, + portToCCRP: this.portToCCRP, + ARROW_SIZE: this.ARROW_SIZE, + getArrowHalfHeight: this.getArrowHalfHeight, + }, + { + starboardDimensionLine: this.starboardDimensionLine, + getMidY: this.getMidY, + starboardToCCRP: this.starboardToCCRP, + ARROW_SIZE: this.ARROW_SIZE, + getArrowHalfHeight: this.getArrowHalfHeight, + }, + { + yAxisCCRPPos: this.yAxisCCRPPos, + }, + { + xAxisCCRPPos: ccrpX, + }, + { + sensorX, + sensorYTopView, + } + ); + + if (this.viewMode === ViewType.SIDE) { + return SIDE_VIEW; + } + if (this.viewMode === ViewType.TOP) { + return TOP_DOWN_VIEW; + } + + return html`
+
+
${SIDE_VIEW}
+
${TOP_DOWN_VIEW}
+
+
`; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'ob-vessel': Vessel; + } +} diff --git a/packages/openbridge-webcomponents/src/skipper/wind-icons.ts b/packages/openbridge-webcomponents/src/skipper/wind-icons.ts new file mode 100644 index 000000000..defce2ab6 --- /dev/null +++ b/packages/openbridge-webcomponents/src/skipper/wind-icons.ts @@ -0,0 +1,132 @@ +import { nothing, svg } from "lit"; +import { Colors } from "./interfaces"; + +export function getWindIcon(windSpeed: number) { + if (windSpeed < 1) { + return svg` + + + + `; + } + else if (windSpeed >= 1.0 && windSpeed < 5) { + return svg` + + + + `; + } + else if (windSpeed >= 5.0 && windSpeed < 10.0) { + return svg` + + + + `; + } + else if (windSpeed >= 10.0 && windSpeed < 15.0) { + return svg` + + + + `; + } + else if (windSpeed >= 15.0 && windSpeed < 20.0) { + return svg` + + + + `; + } + else if (windSpeed >= 20.0 && windSpeed < 25.0) { + return svg` + + + + `; + } + else if (windSpeed >= 25.0 && windSpeed < 30.0) { + return svg` + + + + `; + } + else if (windSpeed >= 30.0 && windSpeed < 35.0) { + return svg` + + + + `; + } + else if (windSpeed >= 35.0 && windSpeed < 40.0) { + return svg` + + + + `; + } + else if (windSpeed >= 40.0 && windSpeed < 45.0) { + return svg` + + + + `; + } + else if (windSpeed >= 45.0 && windSpeed < 50.0) { + return svg` + + + + `; + } + else if (windSpeed >= 50.0 && windSpeed < 55.0) { + return svg` + + + + `; + } + // TODO add the missing speeds (>= 50.0 && <55.0) + else if (windSpeed >= 60.0 && windSpeed < 65.0) { + return svg` + + + + `; + } + // TODO add the missing speeds (>= 60.0 && <65.0) + else if (windSpeed >= 70.0 && windSpeed < 75.0) { + return svg` + + + + `; + } + // TODO add the missing speeds (>= 70.0 && <74.0) + else if (windSpeed >= 74.0) { + return svg` + + `; + } + else { + return nothing; + } +} + +/* + getWindIcon(): any { + return this.speedWind < 1.0 ? WindLarge0 : + this.speedWind >= 1.0 && this.speedWind < 4.0 ? WindLarge1 : + this.speedWind >= 4.0 && this.speedWind < 8.0 ? WindLarge2 : + this.speedWind >= 8.0 && this.speedWind < 13.0 ? WindLarge3 : + this.speedWind >= 13.0 && this.speedWind < 19.0 ? WindLarge4 : + this.speedWind >= 19.0 && this.speedWind < 25.0 ? WindLarge5 : + this.speedWind >= 25.0 && this.speedWind < 32.0 ? WindLarge6 : + this.speedWind >= 32.0 && this.speedWind < 39.0 ? WindLarge7 : + this.speedWind >= 39.0 && this.speedWind < 47.0 ? WindLarge8 : + this.speedWind >= 47.0 && this.speedWind < 55.0 ? WindLarge9 : + this.speedWind >= 55.0 && this.speedWind < 64.0 ? WindLarge10 : + this.speedWind >= 64.0 && this.speedWind < 74.0 ? WindLarge11 : + this.speedWind >= 74.0 ? WindLarge12 : WindLargeUndefined; + } +*/ \ No newline at end of file