diff --git a/README.md b/README.md index 1fdb778888..de70daa9b0 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ GeoSet bridges the gap between Superset and GIS tooling. This is accomplished by - Point size scaling by value (number or percentile bounds) - Collapsible legend with layer toggling and dynamic iconography - Native dashboard integration +- Lasso select with CSV/Excel export - Text Overlay Formatting

diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 132d28a098..9b5c7da9a7 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -1001,7 +1001,6 @@ "version": "1.4.126", "resolved": "https://registry.npmjs.org/@aw-web-design/x-default-browser/-/x-default-browser-1.4.126.tgz", "integrity": "sha512-Xk1sIhyNC/esHGGVjL/niHLowM0csl/kFO5uawBy4IrWwy0o1G8LGt3jP6nmWGz+USxeeqbihAmp/oVZju6wug==", - "dev": true, "license": "MIT", "dependencies": { "default-browser-id": "3.0.0" @@ -1058,7 +1057,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1068,7 +1066,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.28.6", @@ -1099,7 +1096,6 @@ "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" @@ -1154,7 +1150,6 @@ "version": "7.27.3", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.27.3" @@ -1167,7 +1162,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.28.6", @@ -1184,7 +1178,6 @@ "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" @@ -1194,7 +1187,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -1216,7 +1208,6 @@ "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" @@ -1226,7 +1217,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -1244,7 +1234,6 @@ "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" @@ -1254,7 +1243,6 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.27.2", @@ -1271,7 +1259,6 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1289,7 +1276,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/@babel/helper-globals": { @@ -1305,7 +1291,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.28.5", @@ -1332,7 +1317,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.28.6", @@ -1350,7 +1334,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.27.1" @@ -1363,7 +1346,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1373,7 +1355,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", @@ -1391,7 +1372,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-member-expression-to-functions": "^7.28.5", @@ -1409,7 +1389,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.27.1", @@ -1441,7 +1420,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1451,7 +1429,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.28.6", @@ -1466,7 +1443,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.28.6", @@ -1519,7 +1495,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -1536,7 +1511,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1552,7 +1526,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1568,7 +1541,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -1586,7 +1558,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", @@ -1603,7 +1574,6 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1684,7 +1654,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.28.6.tgz", "integrity": "sha512-D+OrJumc9McXNEBI/JmFnc/0uCM2/Y3PEBG3gfV3QIYkKv5pvnpzFrl1kYCrcHJP8nOeFB/SHi1IHz29pNGuew==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -1700,7 +1669,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -1716,7 +1684,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -1758,7 +1725,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -1884,7 +1850,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -1900,7 +1865,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", @@ -1917,7 +1881,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1933,7 +1896,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.6.tgz", "integrity": "sha512-9knsChgsMzBV5Yh3kkhrZNxH3oCYAfMBkNNaVN4cP2RVlFPe8wYdwwcnOsAbkdDoV9UjFtOXWrWB52M8W4jNeA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", @@ -1951,7 +1913,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.28.6", @@ -1969,7 +1930,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1985,7 +1945,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -2001,7 +1960,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", @@ -2018,7 +1976,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", @@ -2035,7 +1992,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -2056,7 +2012,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", @@ -2073,7 +2028,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -2090,7 +2044,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", @@ -2107,7 +2060,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2123,7 +2075,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.28.6.tgz", "integrity": "sha512-5suVoXjC14lUN6ZL9OLKIHCNVWCrqGqlmEp/ixdXjvgnEl/kauLvvMO/Xw9NyMc95Joj1AeLVPVMvibBgSoFlA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", @@ -2140,7 +2091,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2156,7 +2106,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", @@ -2173,7 +2122,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -2189,7 +2137,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2205,7 +2152,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.27.1.tgz", "integrity": "sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -2222,7 +2168,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -2239,7 +2184,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.27.1", @@ -2257,7 +2201,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -2273,7 +2216,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2289,7 +2231,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -2305,7 +2246,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2321,7 +2261,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.27.1", @@ -2338,7 +2277,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.28.6", @@ -2355,7 +2293,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz", "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.28.3", @@ -2374,7 +2311,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.27.1", @@ -2391,7 +2327,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", @@ -2408,7 +2343,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2424,7 +2358,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -2440,7 +2373,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -2456,7 +2388,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", @@ -2476,7 +2407,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -2493,7 +2423,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -2509,7 +2438,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", @@ -2526,7 +2454,6 @@ "version": "7.27.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2542,7 +2469,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", @@ -2559,7 +2485,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -2577,7 +2502,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2678,7 +2602,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.6.tgz", "integrity": "sha512-eZhoEZHYQLL5uc1gS5e9/oTknS0sSSAtd5TkKMUp3J+S/CaUjagc0kOUPsEbDmMeva0nC3WWl4SxVY6+OBuxfw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" @@ -2694,7 +2617,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", @@ -2711,7 +2633,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2758,7 +2679,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2774,7 +2694,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", @@ -2791,7 +2710,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2807,7 +2725,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2823,7 +2740,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2839,7 +2755,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz", "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -2859,7 +2774,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -2875,7 +2789,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", @@ -2892,7 +2805,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", @@ -2909,7 +2821,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", @@ -2943,7 +2854,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.6.tgz", "integrity": "sha512-GaTI4nXDrs7l0qaJ6Rg06dtOXTBCG6TMDB44zbqofCIC4PqC7SEvmFFtpxzCDw9W5aJ7RKVshgXTLvLdBFV/qw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.28.6", @@ -3028,7 +2938,6 @@ "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" @@ -3038,7 +2947,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.27.1.tgz", "integrity": "sha512-ez3a2it5Fn6P54W8QkbfIyyIbxlXvcxyWHHvno1Wg0Ej5eiJY5hBb8ExttoIOJJk7V2dZE6prP7iby5q2aQ0Lg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -3056,7 +2964,6 @@ "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", @@ -3092,7 +2999,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -3112,7 +3018,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.28.6.tgz", "integrity": "sha512-pgcbbEl/dWQYb6L6Yew6F94rdwygfuv+vJ/tXfwIOYAfPB6TNWpXUMEtEq3YuTeHRdvMIhvz13bkT9CNaS+wqA==", - "dev": true, "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", @@ -3878,25 +3783,25 @@ } }, "node_modules/@deck.gl/core": { - "version": "9.2.5", - "resolved": "https://registry.npmjs.org/@deck.gl/core/-/core-9.2.5.tgz", - "integrity": "sha512-/PGNX4Wd7rEahYi6ivC4WExJ3U6Hqgl42R83guNzTL6gM2+02PUQRoQG9QdFagj5d6kWYVN0LVJME2a5WQmzOg==", - "license": "MIT", - "dependencies": { - "@loaders.gl/core": "^4.2.0", - "@loaders.gl/images": "^4.2.0", - "@luma.gl/constants": "^9.2.4", - "@luma.gl/core": "^9.2.4", - "@luma.gl/engine": "^9.2.4", - "@luma.gl/shadertools": "^9.2.4", - "@luma.gl/webgl": "^9.2.4", + "version": "9.2.11", + "resolved": "https://registry.npmjs.org/@deck.gl/core/-/core-9.2.11.tgz", + "integrity": "sha512-lpdxXQuFSkd6ET7M6QxPI8QMhsLRY6vzLyk83sPGFb7JSb4OhrNHYt9sfIhcA/hxJW7bdBSMWWphf2GvQetVuA==", + "license": "MIT", + "dependencies": { + "@loaders.gl/core": "~4.3.4", + "@loaders.gl/images": "~4.3.4", + "@luma.gl/constants": "~9.2.6", + "@luma.gl/core": "~9.2.6", + "@luma.gl/engine": "~9.2.6", + "@luma.gl/shadertools": "~9.2.6", + "@luma.gl/webgl": "~9.2.6", "@math.gl/core": "^4.1.0", "@math.gl/sun": "^4.1.0", "@math.gl/types": "^4.1.0", "@math.gl/web-mercator": "^4.1.0", - "@probe.gl/env": "^4.1.0", - "@probe.gl/log": "^4.1.0", - "@probe.gl/stats": "^4.1.0", + "@probe.gl/env": "^4.1.1", + "@probe.gl/log": "^4.1.1", + "@probe.gl/stats": "^4.1.1", "@types/offscreencanvas": "^2019.6.4", "gl-matrix": "^3.0.0", "mjolnir.js": "^3.0.0" @@ -3953,14 +3858,14 @@ } }, "node_modules/@deck.gl/layers": { - "version": "9.2.5", - "resolved": "https://registry.npmjs.org/@deck.gl/layers/-/layers-9.2.5.tgz", - "integrity": "sha512-a48zWxeHknSX67ZeIzWeLXuOVJkEnQjnLIC27Uv3zHjKlvaoraWPOgScUNyteB0UIIzhzE+D8lF+ViHeIdkNSA==", + "version": "9.2.11", + "resolved": "https://registry.npmjs.org/@deck.gl/layers/-/layers-9.2.11.tgz", + "integrity": "sha512-2FSb0Qa6YR+Rg6GWhYOGTUug3vtZ4uKcFdnrdiJoVXGyibKJMScKZIsivY0r/yQQZsaBjYqty5QuVJvdtEHxSA==", "license": "MIT", "dependencies": { - "@loaders.gl/images": "^4.2.0", - "@loaders.gl/schema": "^4.2.0", - "@luma.gl/shadertools": "^9.2.4", + "@loaders.gl/images": "~4.3.4", + "@loaders.gl/schema": "~4.3.4", + "@luma.gl/shadertools": "~9.2.6", "@mapbox/tiny-sdf": "^2.0.5", "@math.gl/core": "^4.1.0", "@math.gl/polygon": "^4.1.0", @@ -3969,28 +3874,28 @@ }, "peerDependencies": { "@deck.gl/core": "~9.2.0", - "@loaders.gl/core": "^4.2.0", - "@luma.gl/core": "~9.2.4", - "@luma.gl/engine": "~9.2.4" + "@loaders.gl/core": "~4.3.4", + "@luma.gl/core": "~9.2.6", + "@luma.gl/engine": "~9.2.6" } }, "node_modules/@deck.gl/mesh-layers": { - "version": "9.2.5", - "resolved": "https://registry.npmjs.org/@deck.gl/mesh-layers/-/mesh-layers-9.2.5.tgz", - "integrity": "sha512-OJ7Nx6xhp7+bQ4S4asUUp7PdGwcfmQpQhe5SHDGy1UBZ0yZE+ojOo9uvVfXvGBnqq4Zpg9avV+WRN1/BffBsOw==", + "version": "9.2.11", + "resolved": "https://registry.npmjs.org/@deck.gl/mesh-layers/-/mesh-layers-9.2.11.tgz", + "integrity": "sha512-zPB7TtnPXB3tOEoOfcOkNZo7coIq/ukIQa8HIUQLLiOE8AVSQfz3kbMmMK6rUabXlQbgSw/I/j3kFSYRHg3NGg==", "license": "MIT", "dependencies": { - "@loaders.gl/gltf": "^4.2.0", - "@loaders.gl/schema": "^4.2.0", - "@luma.gl/gltf": "^9.2.4", - "@luma.gl/shadertools": "^9.2.4" + "@loaders.gl/gltf": "~4.3.4", + "@loaders.gl/schema": "~4.3.4", + "@luma.gl/gltf": "~9.2.6", + "@luma.gl/shadertools": "~9.2.6" }, "peerDependencies": { "@deck.gl/core": "~9.2.0", - "@luma.gl/core": "~9.2.4", - "@luma.gl/engine": "~9.2.4", - "@luma.gl/gltf": "~9.2.4", - "@luma.gl/shadertools": "~9.2.4" + "@luma.gl/core": "~9.2.6", + "@luma.gl/engine": "~9.2.6", + "@luma.gl/gltf": "~9.2.6", + "@luma.gl/shadertools": "~9.2.6" } }, "node_modules/@deck.gl/react": { @@ -4022,7 +3927,6 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -5083,7 +4987,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/@fal-works/esbuild-plugin-global-externals/-/esbuild-plugin-global-externals-2.1.2.tgz", "integrity": "sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==", - "dev": true, "license": "MIT" }, "node_modules/@fastify/ajv-compiler": { @@ -5236,7 +5139,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -5246,7 +5149,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@inquirer/ansi": "^1.0.2", @@ -5271,7 +5174,7 @@ "version": "5.1.21", "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@inquirer/core": "^10.3.2", @@ -5293,7 +5196,7 @@ "version": "10.3.2", "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@inquirer/ansi": "^1.0.2", @@ -5321,7 +5224,7 @@ "version": "4.2.23", "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@inquirer/core": "^10.3.2", @@ -5344,7 +5247,7 @@ "version": "4.0.23", "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@inquirer/core": "^10.3.2", @@ -5367,7 +5270,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "chardet": "^2.1.1", @@ -5389,7 +5292,7 @@ "version": "1.0.15", "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -5399,7 +5302,7 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@inquirer/core": "^10.3.2", @@ -5421,7 +5324,7 @@ "version": "3.0.23", "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@inquirer/core": "^10.3.2", @@ -5443,7 +5346,7 @@ "version": "4.0.23", "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@inquirer/ansi": "^1.0.2", @@ -5491,7 +5394,7 @@ "version": "4.1.11", "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@inquirer/core": "^10.3.2", @@ -5514,7 +5417,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@inquirer/core": "^10.3.2", @@ -5538,7 +5441,7 @@ "version": "4.4.2", "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@inquirer/ansi": "^1.0.2", @@ -5563,7 +5466,7 @@ "version": "3.0.10", "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -6709,7 +6612,6 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -7269,23 +7171,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@lerna/create/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@lerna/create/node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -7797,15 +7682,15 @@ } }, "node_modules/@luma.gl/constants": { - "version": "9.2.5", - "resolved": "https://registry.npmjs.org/@luma.gl/constants/-/constants-9.2.5.tgz", - "integrity": "sha512-Z+DC7LIw+kPcIthGJdSoquIc92kkUlTOINMuJtssPsvOgFYtlsRn29h95K9y8ehjh234q2+73ExjfDQFE64f5Q==", + "version": "9.2.6", + "resolved": "https://registry.npmjs.org/@luma.gl/constants/-/constants-9.2.6.tgz", + "integrity": "sha512-rvFFrJuSm5JIWbDHFuR4Q2s4eudO3Ggsv0TsGKn9eqvO7bBiPm/ANugHredvh3KviEyYuMZZxtfJvBdr3kzldg==", "license": "MIT" }, "node_modules/@luma.gl/core": { - "version": "9.2.5", - "resolved": "https://registry.npmjs.org/@luma.gl/core/-/core-9.2.5.tgz", - "integrity": "sha512-7tQ6wTTtQV6iWZxjMr+BDzS2o814EvaNW5efKtdzdvbbNyDWkDQZkyHkPvgGBB1o/+N2cbZS7GWyxOljCCH5uA==", + "version": "9.2.6", + "resolved": "https://registry.npmjs.org/@luma.gl/core/-/core-9.2.6.tgz", + "integrity": "sha512-d8KcH8ZZcjDAodSN/G2nueA9YE2X8kMz7Q0OxDGpCww6to1MZXM3Ydate/Jqsb5DDKVgUF6yD6RL8P5jOki9Yw==", "license": "MIT", "dependencies": { "@math.gl/types": "^4.1.0", @@ -7816,9 +7701,9 @@ } }, "node_modules/@luma.gl/engine": { - "version": "9.2.5", - "resolved": "https://registry.npmjs.org/@luma.gl/engine/-/engine-9.2.5.tgz", - "integrity": "sha512-swM+4VO+ab4DU58TB+cdSdby/MGLLWA9ez6BmaZ0HZwLN1HNdYwbQmT71Frtw+6lJpmBZHr78KOQi66Zx5+SOg==", + "version": "9.2.6", + "resolved": "https://registry.npmjs.org/@luma.gl/engine/-/engine-9.2.6.tgz", + "integrity": "sha512-1AEDs2AUqOWh7Wl4onOhXmQF+Rz1zNdPXF+Kxm4aWl92RQ42Sh2CmTvRt2BJku83VQ91KFIEm/v3qd3Urzf+Uw==", "license": "MIT", "dependencies": { "@math.gl/core": "^4.1.0", @@ -7832,9 +7717,9 @@ } }, "node_modules/@luma.gl/gltf": { - "version": "9.2.5", - "resolved": "https://registry.npmjs.org/@luma.gl/gltf/-/gltf-9.2.5.tgz", - "integrity": "sha512-hQFwtgKK4Vnd6t2bqlKVX+Z+Q5gCimq3V9LCiQmQ6An3t4KbbcXltBaBajSzkL9YEaozszSbcOUaFDXkav8CeQ==", + "version": "9.2.6", + "resolved": "https://registry.npmjs.org/@luma.gl/gltf/-/gltf-9.2.6.tgz", + "integrity": "sha512-is3YkiGsWqWTmwldMz6PRaIUleufQfUKYjJTKpsF5RS1OnN+xdAO0mJq5qJTtOQpppWAU0VrmDFEVZ6R3qvm0A==", "license": "MIT", "dependencies": { "@loaders.gl/core": "^4.2.0", @@ -7850,9 +7735,9 @@ } }, "node_modules/@luma.gl/shadertools": { - "version": "9.2.5", - "resolved": "https://registry.npmjs.org/@luma.gl/shadertools/-/shadertools-9.2.5.tgz", - "integrity": "sha512-9upnT6r5exwotM1atc7Nwa7P69MKx+FavXWlabjk+nrRjeIJwzQ/3sXg9UfdDLavN/cDwGvnWz05UlbyABMmJg==", + "version": "9.2.6", + "resolved": "https://registry.npmjs.org/@luma.gl/shadertools/-/shadertools-9.2.6.tgz", + "integrity": "sha512-4+uUbynqPUra9d/z1nQChyHmhLgmKfSMjS7kOwLB6exSnhKnpHL3+Hu9fv55qyaX50nGH3oHawhGtJ6RRvu65w==", "license": "MIT", "dependencies": { "@math.gl/core": "^4.1.0", @@ -7864,12 +7749,12 @@ } }, "node_modules/@luma.gl/webgl": { - "version": "9.2.5", - "resolved": "https://registry.npmjs.org/@luma.gl/webgl/-/webgl-9.2.5.tgz", - "integrity": "sha512-FW5e+zxPuMI6gOJI6az5UnACrRwitzcghyUCVJBQq6/ZK/Z7bjBP5JQgd287DmFXrhLUrNBJ5NYRLmfbraGdDw==", + "version": "9.2.6", + "resolved": "https://registry.npmjs.org/@luma.gl/webgl/-/webgl-9.2.6.tgz", + "integrity": "sha512-NGBTdxJMk7j8Ygr1zuTyAvr1Tw+EpupMIQo7RelFjEsZXg6pujFqiDMM+rgxex8voCeuhWBJc7Rs+MoSqd46UQ==", "license": "MIT", "dependencies": { - "@luma.gl/constants": "9.2.5", + "@luma.gl/constants": "9.2.6", "@math.gl/types": "^4.1.0", "@probe.gl/env": "^4.0.8" }, @@ -8332,7 +8217,6 @@ "version": "3.0.9", "resolved": "https://registry.npmjs.org/@ndelangen/get-tarball/-/get-tarball-3.0.9.tgz", "integrity": "sha512-9JKTEik4vq+yGosHYhZ1tiH/3WpUS0Nh0kej4Agndhox8pAdWhEx5knFVRcb/ya9knCRCs1rPxNrSXTDdfVqpA==", - "dev": true, "license": "MIT", "dependencies": { "gunzip-maybe": "^1.4.2", @@ -8344,14 +8228,12 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true, "license": "ISC" }, "node_modules/@ndelangen/get-tarball/node_modules/tar-fs": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", - "dev": true, "license": "MIT", "dependencies": { "chownr": "^1.1.1", @@ -9494,24 +9376,24 @@ "license": "MIT" }, "node_modules/@probe.gl/env": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@probe.gl/env/-/env-4.1.0.tgz", - "integrity": "sha512-5ac2Jm2K72VCs4eSMsM7ykVRrV47w32xOGMvcgqn8vQdEMF9PRXyBGYEV9YbqRKWNKpNKmQJVi4AHM/fkCxs9w==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@probe.gl/env/-/env-4.1.1.tgz", + "integrity": "sha512-+68seNDMVsEegRB47pFA/Ws1Fjy8agcFYXxzorKToyPcD6zd+gZ5uhwoLd7TzsSw6Ydns//2KEszWn+EnNHTbA==", "license": "MIT" }, "node_modules/@probe.gl/log": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@probe.gl/log/-/log-4.1.0.tgz", - "integrity": "sha512-r4gRReNY6f+OZEMgfWEXrAE2qJEt8rX0HsDJQXUBMoc+5H47bdB7f/5HBHAmapK8UydwPKL9wCDoS22rJ0yq7Q==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@probe.gl/log/-/log-4.1.1.tgz", + "integrity": "sha512-kcZs9BT44pL7hS1OkRGKYRXI/SN9KejUlPD+BY40DguRLzdC5tLG/28WGMyfKdn/51GT4a0p+0P8xvDn1Ez+Kg==", "license": "MIT", "dependencies": { - "@probe.gl/env": "4.1.0" + "@probe.gl/env": "4.1.1" } }, "node_modules/@probe.gl/stats": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@probe.gl/stats/-/stats-4.1.0.tgz", - "integrity": "sha512-EI413MkWKBDVNIfLdqbeNSJTs7ToBz/KVGkwi3D+dQrSIkRI2IYbWGAU3xX+D6+CI4ls8ehxMhNpUVMaZggDvQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@probe.gl/stats/-/stats-4.1.1.tgz", + "integrity": "sha512-4VpAyMHOqydSvPlEyHwXaE+AkIdR03nX+Qhlxsk2D/IW4OVmDZgIsvJB1cDzyEEtcfKcnaEbfXeiPgejBceT6g==", "license": "MIT" }, "node_modules/@puppeteer/browsers": { @@ -11583,7 +11465,6 @@ "version": "8.1.11", "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-8.1.11.tgz", "integrity": "sha512-U7bmed4Ayg+OlJ8HPmLeGxLTHzDY7rxmxM4aAs4YL01fufYfBcjkIP9kFhJm+GJOvGm+YJEUAPe5mbM1P/bn0Q==", - "dev": true, "license": "MIT", "dependencies": { "@fal-works/esbuild-plugin-global-externals": "^2.1.2", @@ -11914,7 +11795,6 @@ "version": "8.1.11", "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-8.1.11.tgz", "integrity": "sha512-4U48w9C7mVEKrykcPcfHwJkRyCqJ28XipbElACbjIIkQEqaHaOVtP3GeKIrgkoOXe/HK3O4zKWRP2SqlVS0r4A==", - "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.24.4", @@ -11967,7 +11847,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -11980,7 +11859,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -11997,7 +11875,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -12007,7 +11884,6 @@ "version": "14.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", - "dev": true, "license": "MIT", "dependencies": { "@sindresorhus/merge-streams": "^2.1.0", @@ -12028,14 +11904,12 @@ "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, "license": "ISC" }, "node_modules/@storybook/cli/node_modules/ignore": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -12045,7 +11919,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -12058,7 +11931,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "license": "MIT", "dependencies": { "p-locate": "^4.1.0" @@ -12067,28 +11939,10 @@ "node": ">=8" } }, - "node_modules/@storybook/cli/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@storybook/cli/node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^2.1.4", @@ -12101,7 +11955,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver" @@ -12111,7 +11964,6 @@ "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, "license": "MIT", "dependencies": { "bl": "^4.1.0", @@ -12135,7 +11987,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -12151,7 +12002,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "license": "MIT", "dependencies": { "p-limit": "^2.2.0" @@ -12164,7 +12014,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -12177,7 +12026,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, "license": "MIT", "dependencies": { "@types/normalize-package-data": "^2.4.0", @@ -12193,7 +12041,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, "license": "MIT", "dependencies": { "find-up": "^4.1.0", @@ -12211,7 +12058,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "license": "MIT", "dependencies": { "locate-path": "^5.0.0", @@ -12225,7 +12071,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" @@ -12235,7 +12080,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, "license": "MIT", "engines": { "node": ">=14.16" @@ -12248,7 +12092,6 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" @@ -12258,7 +12101,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -12284,7 +12126,6 @@ "version": "8.1.11", "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-8.1.11.tgz", "integrity": "sha512-/LCozjH1IQ1TOs9UQV59BE0X6UZ9q+C0NEUz7qmJZPrwAii3FkW4l7D/fwxblpMExaoxv0oE8NQfUz49U/5Ymg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.24.4", @@ -12312,7 +12153,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -12325,7 +12165,6 @@ "version": "14.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", - "dev": true, "license": "MIT", "dependencies": { "@sindresorhus/merge-streams": "^2.1.0", @@ -12346,7 +12185,6 @@ "version": "7.0.5", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -12356,7 +12194,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -12369,7 +12206,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, "license": "MIT", "engines": { "node": ">=14.16" @@ -12382,7 +12218,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -12417,38 +12252,6 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" } }, - "node_modules/@storybook/core": { - "version": "8.6.15", - "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.6.15.tgz", - "integrity": "sha512-VFpKcphNurJpSC4fpUfKL3GTXVoL53oytghGR30QIw5jKWwaT50HVbTyb41BLOUuZjmMhUQA8weiQEew6RX0gw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@storybook/theming": "8.6.15", - "better-opn": "^3.0.2", - "browser-assert": "^1.2.1", - "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0", - "esbuild-register": "^3.5.0", - "jsdoc-type-pratt-parser": "^4.0.0", - "process": "^0.11.10", - "recast": "^0.23.5", - "semver": "^7.6.2", - "util": "^0.12.5", - "ws": "^8.2.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "prettier": "^2 || ^3" - }, - "peerDependenciesMeta": { - "prettier": { - "optional": true - } - } - }, "node_modules/@storybook/core-common": { "version": "8.1.11", "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-8.1.11.tgz", @@ -12657,7 +12460,6 @@ "version": "8.1.11", "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-8.1.11.tgz", "integrity": "sha512-L6dzQTmR0np/kagNONvvlm6lSvF1FNc9js3vxsEEPnEypLbhx8bDZaHmuhmBpYUzKyUMpRVQTE/WgjHLuBBuxA==", - "dev": true, "license": "MIT", "dependencies": { "@aw-web-design/x-default-browser": "1.4.126", @@ -12715,7 +12517,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -12728,7 +12529,6 @@ "version": "18.19.130", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -12738,7 +12538,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -12755,7 +12554,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "license": "MIT", "dependencies": { "locate-path": "^5.0.0", @@ -12769,7 +12567,6 @@ "version": "14.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", - "dev": true, "license": "MIT", "dependencies": { "@sindresorhus/merge-streams": "^2.1.0", @@ -12790,14 +12587,12 @@ "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, "license": "ISC" }, "node_modules/@storybook/core-server/node_modules/ignore": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -12807,7 +12602,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "license": "MIT", "dependencies": { "p-locate": "^4.1.0" @@ -12820,7 +12614,6 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^2.1.4", @@ -12833,7 +12626,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver" @@ -12843,7 +12635,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -12859,7 +12650,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "license": "MIT", "dependencies": { "p-limit": "^2.2.0" @@ -12872,7 +12662,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -12885,7 +12674,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, "license": "MIT", "dependencies": { "@types/normalize-package-data": "^2.4.0", @@ -12901,7 +12689,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, "license": "MIT", "dependencies": { "find-up": "^4.1.0", @@ -12919,7 +12706,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" @@ -12929,7 +12715,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, "license": "MIT", "engines": { "node": ">=14.16" @@ -12942,7 +12727,6 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" @@ -12952,14 +12736,12 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true, "license": "MIT" }, "node_modules/@storybook/core-server/node_modules/unicorn-magic": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -13003,47 +12785,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@storybook/core/node_modules/@storybook/theming": { - "version": "8.6.15", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.6.15.tgz", - "integrity": "sha512-dAbL0XOekyT6XsF49R6Etj3WxQ/LpdJDIswUUeHgVJ6/yd2opZOGbPxnwA3zlmAh1c0tvpPyhSDXxSG79u8e4Q==", - "license": "MIT", - "peer": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" - } - }, - "node_modules/@storybook/core/node_modules/storybook": { - "version": "8.6.15", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.6.15.tgz", - "integrity": "sha512-Ob7DMlwWx8s7dMvcQ3xPc02TvUeralb+xX3oaPRk9wY9Hc6M1IBC/7cEoITkSmRS2v38DHubC+mtEKNc1u2gQg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@storybook/core": "8.6.15" - }, - "bin": { - "getstorybook": "bin/index.cjs", - "sb": "bin/index.cjs", - "storybook": "bin/index.cjs" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "prettier": "^2 || ^3" - }, - "peerDependenciesMeta": { - "prettier": { - "optional": true - } - } - }, "node_modules/@storybook/csf": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.13.tgz", @@ -13093,7 +12834,6 @@ "version": "3.1.0-next.0", "resolved": "https://registry.npmjs.org/@storybook/docs-mdx/-/docs-mdx-3.1.0-next.0.tgz", "integrity": "sha512-t4syFIeSyufieNovZbLruPt2DmRKpbwL4fERCZ1MifWDRIORCKLc4NCEHy+IqvIqd71/SJV2k4B51nF7vlJfmQ==", - "dev": true, "license": "MIT" }, "node_modules/@storybook/docs-tools": { @@ -13139,7 +12879,6 @@ "version": "8.1.11", "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-8.1.11.tgz", "integrity": "sha512-e02y9dmxowo7cTKYm9am7UO6NOHoHy6Xi7xZf/UA932qLwFZUtk5pnwIEFaZWI3OQsRUCGhP+FL5zizU7uVZeg==", - "dev": true, "license": "MIT", "funding": { "type": "opencollective", @@ -13552,7 +13291,6 @@ "version": "8.1.11", "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-8.1.11.tgz", "integrity": "sha512-Jqvm7HcZismKzPuebhyLECO6KjGiSk4ycbca1WUM/TUvifxCXqgoUPlHHQEEfaRdHS63/MSqtMNjLsQRLC/vNQ==", - "dev": true, "license": "MIT", "dependencies": { "@storybook/client-logger": "8.1.11", @@ -13573,7 +13311,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -13590,14 +13327,12 @@ "version": "5.0.6", "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-5.0.6.tgz", "integrity": "sha512-3yurQZ2hD9VISAhJJP9bpYFNQrHHBXE2JxxjY5aLEcDi46RmAzJE2OC9FAde0yis5ElW0jTTzs0zfg/Cca4XqQ==", - "dev": true, "license": "MIT" }, "node_modules/@storybook/telemetry/node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "license": "MIT", "dependencies": { "locate-path": "^5.0.0", @@ -13611,14 +13346,12 @@ "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, "license": "ISC" }, "node_modules/@storybook/telemetry/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "license": "MIT", "dependencies": { "p-locate": "^4.1.0" @@ -13631,7 +13364,6 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^2.1.4", @@ -13644,7 +13376,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -13660,7 +13391,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "license": "MIT", "dependencies": { "p-limit": "^2.2.0" @@ -13673,7 +13403,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, "license": "MIT", "dependencies": { "@types/normalize-package-data": "^2.4.0", @@ -13689,7 +13418,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, "license": "MIT", "dependencies": { "find-up": "^4.1.0", @@ -13707,7 +13435,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" @@ -13717,7 +13444,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver" @@ -13727,7 +13453,6 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" @@ -14179,263 +13904,2009 @@ "node": ">=12" } }, - "node_modules/@testing-library/dom/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "license": "MIT" + }, + "node_modules/@testing-library/react": { + "version": "12.1.5", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.5.tgz", + "integrity": "sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^8.0.0", + "@types/react-dom": "<18.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": "<18.0.0", + "react-dom": "<18.0.0" + } + }, + "node_modules/@testing-library/react-hooks": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz", + "integrity": "sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "react-error-boundary": "^3.1.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0", + "react": "^16.9.0 || ^17.0.0", + "react-dom": "^16.9.0 || ^17.0.0", + "react-test-renderer": "^16.9.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-test-renderer": { + "optional": true + } + } + }, + "node_modules/@testing-library/react-hooks/node_modules/react-error-boundary": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz", + "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, + "node_modules/@testing-library/user-event": { + "version": "12.8.3", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.8.3.tgz", + "integrity": "sha512-IR0iWbFkgd56Bu5ZI/ej8yQwrkCv8Qydx6RzwbKz9faXazR/+5tvYKsZQgyXJiwgpcva127YO6JcWy7YlCfofQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "license": "MIT" + }, + "node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", + "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.1.tgz", + "integrity": "sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@turf/along": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/along/-/along-7.3.4.tgz", + "integrity": "sha512-PvIoXin0I1t3nRwJz7uqR6fsxDMqdGwJq90qGOeqkNwlZqlF+5o2wKHPwYwi0RXZhLvxRP5qlbNIvV8ADdbWxw==", + "license": "MIT", + "dependencies": { + "@turf/bearing": "7.3.4", + "@turf/destination": "7.3.4", + "@turf/distance": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/along/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/along/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/area": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/area/-/area-7.3.4.tgz", + "integrity": "sha512-UEQQFw2XwHpozSBAMEtZI3jDsAad4NnHL/poF7/S6zeDCjEBCkt3MYd6DSGH/cvgcOozxH/ky3/rIVSMZdx4vA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/area/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/area/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/bbox/-/bbox-7.3.4.tgz", + "integrity": "sha512-D5ErVWtfQbEPh11yzI69uxqrcJmbPU/9Y59f1uTapgwAwQHQztDWgsYpnL3ns8r1GmPWLP8sGJLVTIk2TZSiYA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox-polygon": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/bbox-polygon/-/bbox-polygon-7.3.4.tgz", + "integrity": "sha512-XCDYQwCA41Bum3R1xX0Na1nR4ozoe/pCYy5bxqrzyMs87kPJUIfBrD5IWxjnZyLqFpfEpolMHJz5ed1uA2PanQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox-polygon/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bearing": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/bearing/-/bearing-7.3.4.tgz", + "integrity": "sha512-zvFjapyFaOrM8nBtAND7f4yb0BJV0jyj6cyoXyTYqLY+3Hn0eHgL0M8lwxDLbTom5KfqYDHDVDQC3+VSfypoEA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bearing/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bearing/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-clockwise": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/boolean-clockwise/-/boolean-clockwise-5.1.5.tgz", + "integrity": "sha512-FqbmEEOJ4rU4/2t7FKx0HUWmjFEVqR+NJrFP7ymGSjja2SQ7Q91nnBihGuT+yuHHl6ElMjQ3ttsB/eTmyCycxA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "node_modules/@turf/boolean-disjoint": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/boolean-disjoint/-/boolean-disjoint-7.3.4.tgz", + "integrity": "sha512-Dl4O27ygi2NqskGQuvSlDLJYlJ2SPkHb3A9T/v6eAudjlMiKdEY6bMxKUfU5y+Px1WiCZxd+9rXGXJgGC3WiQg==", + "license": "MIT", + "dependencies": { + "@turf/boolean-point-in-polygon": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/line-intersect": "7.3.4", + "@turf/meta": "7.3.4", + "@turf/polygon-to-line": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-disjoint/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-disjoint/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-intersects": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/boolean-intersects/-/boolean-intersects-7.3.4.tgz", + "integrity": "sha512-sxi41NXkb5hrJgOvpm32hyBLhW8fem0vn2XxR4+jyRg1rM/v3ziF10/VqC9KDZuDNZkt9JjL9B0825Cf7AN6Lg==", + "license": "MIT", + "dependencies": { + "@turf/boolean-disjoint": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-intersects/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-intersects/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-point-in-polygon": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-7.3.4.tgz", + "integrity": "sha512-v/4hfyY90Vz9cDgs2GwjQf+Lft8o7mNCLJOTz/iv8SHAIgMMX0czEoIaNVOJr7tBqPqwin1CGwsncrkf5C9n8Q==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@types/geojson": "^7946.0.10", + "point-in-polygon-hao": "^1.1.0", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-point-in-polygon/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-point-in-polygon/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-point-on-line": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/boolean-point-on-line/-/boolean-point-on-line-7.3.4.tgz", + "integrity": "sha512-70gm5x6YQOZKcw0b/O4jjMwVWnFj+Zb6TXozLgZFDZShc8pgTQtZku7K+HKZ7Eya+7usHIB4IimZauomOMa+iw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-point-on-line/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-point-on-line/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-within": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/boolean-within/-/boolean-within-7.3.4.tgz", + "integrity": "sha512-eLgi803gz0KcYkyxnnqnz9Vd6tw2/0eAExe/Rq8sO0dqypaSiomSumxjqu89d/yo24Qz8gW7c0kJ6YihNbMYxA==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.4", + "@turf/boolean-point-in-polygon": "7.3.4", + "@turf/boolean-point-on-line": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@turf/line-split": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-within/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-within/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/buffer": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/buffer/-/buffer-7.3.4.tgz", + "integrity": "sha512-MVOCBDuOl3KGDsh2stW12RmiFaFeSkVjeUbZ+ADUtIVnv+jlFsmjBpFtsEw8s9YQn5g0667QppOshm0FBHA57Q==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.4", + "@turf/center": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/jsts": "^2.7.1", + "@turf/meta": "7.3.4", + "@turf/projection": "7.3.4", + "@types/geojson": "^7946.0.10", + "d3-geo": "1.7.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/buffer/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/buffer/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/buffer/node_modules/d3-geo": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.7.1.tgz", + "integrity": "sha512-O4AempWAr+P5qbk2bC2FuN/sDW4z+dN2wDf9QV3bxQt4M5HfOEeXLgJ/UKQW0+o1Dj8BE+L5kiDbdWUMjsmQpw==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1" + } + }, + "node_modules/@turf/center": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/center/-/center-7.3.4.tgz", + "integrity": "sha512-4SsLMDHWthXbyIHsczgFCo4fx+8tC8w2+B5HdEuY+P+cSOOL4T+6QQzd7WWjuN/Y3ndowFssUmwRrvXuwVRxQA==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.4", + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/center/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/centroid": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/centroid/-/centroid-7.3.4.tgz", + "integrity": "sha512-6c3kyTSKBrmiPMe75UkHw6MgedroZ6eR5usEvdlDhXgA3MudFPXIZkMFmMd1h9XeJ9xFfkmq+HPCdF0cOzvztA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/centroid/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/centroid/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/circle": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/circle/-/circle-7.3.4.tgz", + "integrity": "sha512-6ccr5iT51/XONF+pbpkqoRxKX4ZVWLubXb1frGCnClv2suo1UIY9SIlINNctVDupXd2P9PpqZCbrXATrcrokPg==", + "license": "MIT", + "dependencies": { + "@turf/destination": "7.3.4", + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/circle/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clone": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-5.1.5.tgz", + "integrity": "sha512-//pITsQ8xUdcQ9pVb4JqXiSqG4dos5Q9N4sYFoWghX21tfOV2dhc5TGqYOhnHrQS7RiKQL1vQ48kIK34gQ5oRg==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "^5.1.5" + } + }, + "node_modules/@turf/destination": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/destination/-/destination-7.3.4.tgz", + "integrity": "sha512-YxoUJwkKmTHiRFQxMQOP0tz8Vy+ga5EXl+C+F/WubjDLwT1AJu5y8CNIjLvWyjPWckj/vZG4u/1js5bx6MLADA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/destination/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/destination/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/difference": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/difference/-/difference-7.3.4.tgz", + "integrity": "sha512-kIxizNQrYLO2rtqUIeed0tPycicrXoipy/g9d4mjv91kzBEbwpyojz9zi8U9G1ISBfCEgA7wsViQD0r+8qzxXw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "polyclip-ts": "^0.16.8", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/difference/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/difference/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/distance": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/distance/-/distance-7.3.4.tgz", + "integrity": "sha512-9drWgd46uHPPyzgrcRQLgSvdS/SjVlQ6ZIBoRQagS5P2kSjUbcOXHIMeOSPwfxwlKhEtobLyr+IiR2ns1TfF8w==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/distance/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/distance/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/ellipse": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/ellipse/-/ellipse-7.3.4.tgz", + "integrity": "sha512-SMgbERZl12j7H8YaIofmnf0NwAvdF5Wly4tjI/eUhj/sFOKrKXOS1lvCSBJ6uSV9tFijl3ecGOVOlTpURdZ30g==", + "license": "MIT", + "dependencies": { + "@turf/destination": "7.3.4", + "@turf/distance": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@turf/transform-rotate": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/ellipse/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/ellipse/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/geojson-rbush": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/geojson-rbush/-/geojson-rbush-7.3.4.tgz", + "integrity": "sha512-aDG/5mMCgKduqBwZ3XpLOdlE2hizV3fM+5dHCWyrBepCQLeM/QRvvpBDCdQKDWKpoIBmrGGYDNiOofnf3QmGhg==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/geojson-rbush/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/geojson-rbush/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/helpers": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-5.1.5.tgz", + "integrity": "sha512-/lF+JR+qNDHZ8bF9d+Cp58nxtZWJ3sqFe6n3u3Vpj+/0cqkjk4nXKYBSY0azm+GIYB5mWKxUXvuP/m0ZnKj1bw==", + "license": "MIT" + }, + "node_modules/@turf/intersect": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/intersect/-/intersect-7.3.4.tgz", + "integrity": "sha512-VsqMEMeRWWs2mjwI7sTlUgH1cEfugTGhQ0nF8ncHG7YKd9HUUTzIKpn9FJeoguPWIYITcy1ar4yJEOU/hteBVw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "polyclip-ts": "^0.16.8", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/intersect/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/intersect/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/invariant": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-5.2.0.tgz", + "integrity": "sha512-28RCBGvCYsajVkw2EydpzLdcYyhSA77LovuOvgCJplJWaNVyJYH6BOR3HR9w50MEkPqb/Vc/jdo6I6ermlRtQA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "^5.1.5" + } + }, + "node_modules/@turf/jsts": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@turf/jsts/-/jsts-2.7.2.tgz", + "integrity": "sha512-zAezGlwWHPyU0zxwcX2wQY3RkRpwuoBmhhNE9HY9kWhFDkCxZ3aWK5URKwa/SWKJbj9aztO+8vtdiBA28KVJFg==", + "license": "(EDL-1.0 OR EPL-1.0)", + "dependencies": { + "jsts": "2.7.1" + } + }, + "node_modules/@turf/kinks": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/kinks/-/kinks-7.3.4.tgz", + "integrity": "sha512-LZTKELWxvXl0vc9ZxVgi0v07fO9+2FrZOam2B10fz/eGjy3oKNazU5gjggbnc499wEIcJS4hN+VyjQZrmsJAdQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/kinks/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-intersect": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/line-intersect/-/line-intersect-7.3.4.tgz", + "integrity": "sha512-XygbTvHa6A+v6l2ZKYtS8AAWxwmrPxKxfBbdH75uED1JvdytSLWYTKGlcU3soxd9sYb4x/g9sDvRIVyU6Lucrg==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "sweepline-intersections": "^1.5.0", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-intersect/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-segment": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/line-segment/-/line-segment-7.3.4.tgz", + "integrity": "sha512-UeISzf/JHoWEY5yeoyvKwA5epWcvJMCpCwbIMolvfTC5pp+IVozjHPVCRvRWuzmbmAvetcW0unL5bjqi0ADmuQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-segment/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-segment/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-segment/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-split": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/line-split/-/line-split-7.3.4.tgz", + "integrity": "sha512-l1zmCSUnGsiN4gf22Aw91a2VnYs5DZS67FdkYqKgr+wPEAL/gpQgIBBWSTmhwY8zb3NEqty+f/gMEe8EJAWYng==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.4", + "@turf/geojson-rbush": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@turf/line-intersect": "7.3.4", + "@turf/line-segment": "7.3.4", + "@turf/meta": "7.3.4", + "@turf/nearest-point-on-line": "7.3.4", + "@turf/truncate": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-split/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-split/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-split/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/meta": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-5.2.0.tgz", + "integrity": "sha512-ZjQ3Ii62X9FjnK4hhdsbT+64AYRpaI8XMBMcyftEOGSmPMUVnkbvuv3C9geuElAXfQU7Zk1oWGOcrGOD9zr78Q==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "^5.1.5" + } + }, + "node_modules/@turf/midpoint": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/midpoint/-/midpoint-7.3.4.tgz", + "integrity": "sha512-/XAeGvsz8l5HaqcP7TUlexzGfibqXozQgBZ8rH7az6op2Dfm3pL/Z7bKLHoVavM0ccBg0Pt7g6j9NM54kZWdKA==", + "license": "MIT", + "dependencies": { + "@turf/bearing": "7.3.4", + "@turf/destination": "7.3.4", + "@turf/distance": "7.3.4", + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/midpoint/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-point-on-line": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/nearest-point-on-line/-/nearest-point-on-line-7.3.4.tgz", + "integrity": "sha512-DQrP3lRju83rIXFN68tUEpc7ki/eRwdwBkK2CTT4RAcyCxbcH2NGJPQv8dYiww/Ar77u1WLVn+aINXZH904dWw==", + "license": "MIT", + "dependencies": { + "@turf/distance": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-point-on-line/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-point-on-line/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-point-on-line/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/point-to-line-distance": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/point-to-line-distance/-/point-to-line-distance-7.3.4.tgz", + "integrity": "sha512-IdPAxlAQZj7FCZg+ObyVHlNdqwLL/oxYoQjpxMNJ511gNxokCtEv0aeRZQjYOYIxr9Ss97v3yo3ILJaF9V2kPw==", + "license": "MIT", + "dependencies": { + "@turf/bearing": "7.3.4", + "@turf/distance": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@turf/meta": "7.3.4", + "@turf/nearest-point-on-line": "7.3.4", + "@turf/projection": "7.3.4", + "@turf/rhumb-bearing": "7.3.4", + "@turf/rhumb-distance": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/point-to-line-distance/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/point-to-line-distance/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/point-to-line-distance/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygon-to-line": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/polygon-to-line/-/polygon-to-line-7.3.4.tgz", + "integrity": "sha512-xhmOZ5rHZAKLUDLeYKWMsX84ip8CCGOcGLBHtPPYOjdIDHddMV6Sxt5kVgkmlZpK6NEWEmOD6lYR4obxHcHlGA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygon-to-line/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygon-to-line/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/projection": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/projection/-/projection-7.3.4.tgz", + "integrity": "sha512-p91zOaLmzoBHzU/2H6Ot1tOhTmAom85n1P7I4Oo0V9xU8hmJXWfNnomLFf/6rnkKDIFZkncLQIBz4iIecZ61sA==", + "license": "MIT", + "dependencies": { + "@turf/clone": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/projection/node_modules/@turf/clone": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-7.3.4.tgz", + "integrity": "sha512-pwQ+RyQw986uu7IulY/18NRAebwZZScb084bvVqVkTrllwLSv4oVBqUxmUMiwtp+PNdiRGRFOvNyZqtRsiD+Jw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/projection/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/projection/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rewind": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/rewind/-/rewind-5.1.5.tgz", + "integrity": "sha512-Gdem7JXNu+G4hMllQHXRFRihJl3+pNl7qY+l4qhQFxq+hiU1cQoVFnyoleIqWKIrdK/i2YubaSwc3SCM7N5mMw==", + "license": "MIT", + "dependencies": { + "@turf/boolean-clockwise": "^5.1.5", + "@turf/clone": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "node_modules/@turf/rhumb-bearing": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/rhumb-bearing/-/rhumb-bearing-7.3.4.tgz", + "integrity": "sha512-tvX1toSo80q0iL0cUMMXpSKsCCfOjRqDGCmOdR6B9shhk6xP1ZM2PLQDr+MFPBFeGyQuyY4CNFkV2+3DF49vYw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-bearing/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-bearing/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-destination": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/rhumb-destination/-/rhumb-destination-7.3.4.tgz", + "integrity": "sha512-6HikEb5nm2A18FQWk6vVLMQkc099I/7c69j47RYM27xQK8J8uBCNk1zLYyMPcZTh24xcNSbZ1iPHDsDOqw6wWQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-destination/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-destination/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-distance": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/rhumb-distance/-/rhumb-distance-7.3.4.tgz", + "integrity": "sha512-phwskeijdgYMsR3qDQmytfsg2iZcp3uWK7UFc76wKTEpxozbDGFI4enX5gXvZPpyI1iD7gsktGqHsO33AjnFDA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-distance/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-distance/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-rotate": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/transform-rotate/-/transform-rotate-7.3.4.tgz", + "integrity": "sha512-pbUG6QLwyJvvitq4aAq4IQH79X8T0NmEPUGDUEEP69yW7t4+UZjDBAVbCKwpOc8gtsK0K5yvxlZ0e2CdtpNmEw==", + "license": "MIT", + "dependencies": { + "@turf/centroid": "7.3.4", + "@turf/clone": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@turf/meta": "7.3.4", + "@turf/rhumb-bearing": "7.3.4", + "@turf/rhumb-destination": "7.3.4", + "@turf/rhumb-distance": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-rotate/node_modules/@turf/clone": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-7.3.4.tgz", + "integrity": "sha512-pwQ+RyQw986uu7IulY/18NRAebwZZScb084bvVqVkTrllwLSv4oVBqUxmUMiwtp+PNdiRGRFOvNyZqtRsiD+Jw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-rotate/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-rotate/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-rotate/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-scale": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/transform-scale/-/transform-scale-7.3.4.tgz", + "integrity": "sha512-7gUIFFHaU3Ewj3rCzIu5Yo7Zjfv4R2ypjh6UWiMJnDavb7RQ8fn0AKKcNMA/vF/yxuncp2l3zoa2gygv4AKM8A==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.4", + "@turf/center": "7.3.4", + "@turf/centroid": "7.3.4", + "@turf/clone": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@turf/meta": "7.3.4", + "@turf/rhumb-bearing": "7.3.4", + "@turf/rhumb-destination": "7.3.4", + "@turf/rhumb-distance": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-scale/node_modules/@turf/clone": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-7.3.4.tgz", + "integrity": "sha512-pwQ+RyQw986uu7IulY/18NRAebwZZScb084bvVqVkTrllwLSv4oVBqUxmUMiwtp+PNdiRGRFOvNyZqtRsiD+Jw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-scale/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-scale/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://opencollective.com/turf" } }, - "node_modules/@testing-library/jest-dom": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", - "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", + "node_modules/@turf/transform-scale/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", "license": "MIT", "dependencies": { - "@adobe/css-tools": "^4.4.0", - "aria-query": "^5.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.6.3", - "picocolors": "^1.1.1", - "redent": "^3.0.0" + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" }, - "engines": { - "node": ">=14", - "npm": ">=6", - "yarn": ">=1" + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", - "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", - "license": "MIT" - }, - "node_modules/@testing-library/react": { - "version": "12.1.5", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.5.tgz", - "integrity": "sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==", + "node_modules/@turf/transform-translate": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/transform-translate/-/transform-translate-7.3.4.tgz", + "integrity": "sha512-qbSIEueOR8mNB7p4EB88vHvUAyuSBM8zxP68UiiTNV3Gh+OZF2VXTFiu3EFYMTaD9sE6Lxmzvv3fjW8N2q82pw==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^8.0.0", - "@types/react-dom": "<18.0.0" - }, - "engines": { - "node": ">=12" + "@turf/clone": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@turf/meta": "7.3.4", + "@turf/rhumb-destination": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" }, - "peerDependencies": { - "react": "<18.0.0", - "react-dom": "<18.0.0" + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@testing-library/react-hooks": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz", - "integrity": "sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==", + "node_modules/@turf/transform-translate/node_modules/@turf/clone": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-7.3.4.tgz", + "integrity": "sha512-pwQ+RyQw986uu7IulY/18NRAebwZZScb084bvVqVkTrllwLSv4oVBqUxmUMiwtp+PNdiRGRFOvNyZqtRsiD+Jw==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.12.5", - "react-error-boundary": "^3.1.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "@types/react": "^16.9.0 || ^17.0.0", - "react": "^16.9.0 || ^17.0.0", - "react-dom": "^16.9.0 || ^17.0.0", - "react-test-renderer": "^16.9.0 || ^17.0.0" + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "react-test-renderer": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@testing-library/react-hooks/node_modules/react-error-boundary": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz", - "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==", + "node_modules/@turf/transform-translate/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "engines": { - "node": ">=10", - "npm": ">=6" + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" }, - "peerDependencies": { - "react": ">=16.13.1" + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@testing-library/user-event": { - "version": "12.8.3", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.8.3.tgz", - "integrity": "sha512-IR0iWbFkgd56Bu5ZI/ej8yQwrkCv8Qydx6RzwbKz9faXazR/+5tvYKsZQgyXJiwgpcva127YO6JcWy7YlCfofQ==", + "node_modules/@turf/transform-translate/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "engines": { - "node": ">=10", - "npm": ">=6" + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" }, - "peerDependencies": { - "@testing-library/dom": ">=7.21.4" + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, + "node_modules/@turf/transform-translate/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", "license": "MIT", - "engines": { - "node": ">= 10" + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10.13.0" + "node_modules/@turf/truncate": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/truncate/-/truncate-7.3.4.tgz", + "integrity": "sha512-VPXdae9+RLLM19FMrJgt7QANBikm7DxPbfp/dXgzE4Ca7v+mJ4T1fYc7gCZDaqOrWMccHKbvv4iSuW7YZWdIIA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", - "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "license": "MIT" - }, - "node_modules/@tufjs/canonical-json": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", - "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", - "dev": true, + "node_modules/@turf/truncate/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", "license": "MIT", - "engines": { - "node": "^16.14.0 || >=18.0.0" + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@tufjs/models": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.1.tgz", - "integrity": "sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==", - "dev": true, + "node_modules/@turf/truncate/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", "license": "MIT", "dependencies": { - "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.4" + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" }, - "engines": { - "node": "^16.14.0 || >=18.0.0" + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@turf/boolean-clockwise": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@turf/boolean-clockwise/-/boolean-clockwise-5.1.5.tgz", - "integrity": "sha512-FqbmEEOJ4rU4/2t7FKx0HUWmjFEVqR+NJrFP7ymGSjja2SQ7Q91nnBihGuT+yuHHl6ElMjQ3ttsB/eTmyCycxA==", + "node_modules/@turf/union": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/union/-/union-7.3.4.tgz", + "integrity": "sha512-JJYyPMmGcrTa9sPv2ief2QU9Hb//cEAU1zgKu/OfoCMa9a8Imp5QVm9UTAkhGlc+4qm/N/X16iJ+cvVWaxPjkg==", "license": "MIT", "dependencies": { - "@turf/helpers": "^5.1.5", - "@turf/invariant": "^5.1.5" + "@turf/helpers": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "polyclip-ts": "^0.16.8", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@turf/clone": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-5.1.5.tgz", - "integrity": "sha512-//pITsQ8xUdcQ9pVb4JqXiSqG4dos5Q9N4sYFoWghX21tfOV2dhc5TGqYOhnHrQS7RiKQL1vQ48kIK34gQ5oRg==", + "node_modules/@turf/union/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", "license": "MIT", "dependencies": { - "@turf/helpers": "^5.1.5" + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@turf/helpers": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-5.1.5.tgz", - "integrity": "sha512-/lF+JR+qNDHZ8bF9d+Cp58nxtZWJ3sqFe6n3u3Vpj+/0cqkjk4nXKYBSY0azm+GIYB5mWKxUXvuP/m0ZnKj1bw==", - "license": "MIT" + "node_modules/@turf/union/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } }, - "node_modules/@turf/invariant": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-5.2.0.tgz", - "integrity": "sha512-28RCBGvCYsajVkw2EydpzLdcYyhSA77LovuOvgCJplJWaNVyJYH6BOR3HR9w50MEkPqb/Vc/jdo6I6ermlRtQA==", + "node_modules/@turf/unkink-polygon": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/unkink-polygon/-/unkink-polygon-7.3.4.tgz", + "integrity": "sha512-dFIqTLAnLL5D3OANPJtRb5OvmOM81GlNCjwgjlLQy0xdpYgKwGdE+gNXjygDrPUUXNc22xnaj3EfAfC3Pq7W4Q==", "license": "MIT", "dependencies": { - "@turf/helpers": "^5.1.5" + "@turf/area": "7.3.4", + "@turf/boolean-point-in-polygon": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@turf/meta": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-5.2.0.tgz", - "integrity": "sha512-ZjQ3Ii62X9FjnK4hhdsbT+64AYRpaI8XMBMcyftEOGSmPMUVnkbvuv3C9geuElAXfQU7Zk1oWGOcrGOD9zr78Q==", + "node_modules/@turf/unkink-polygon/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", "license": "MIT", "dependencies": { - "@turf/helpers": "^5.1.5" + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" } }, - "node_modules/@turf/rewind": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@turf/rewind/-/rewind-5.1.5.tgz", - "integrity": "sha512-Gdem7JXNu+G4hMllQHXRFRihJl3+pNl7qY+l4qhQFxq+hiU1cQoVFnyoleIqWKIrdK/i2YubaSwc3SCM7N5mMw==", + "node_modules/@turf/unkink-polygon/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", "license": "MIT", "dependencies": { - "@turf/boolean-clockwise": "^5.1.5", - "@turf/clone": "^5.1.5", - "@turf/helpers": "^5.1.5", - "@turf/invariant": "^5.1.5", - "@turf/meta": "^5.1.5" + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" } }, "node_modules/@tybys/wasm-util": { @@ -14614,7 +16085,6 @@ "version": "6.0.6", "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", "integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -14752,14 +16222,12 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/detect-port/-/detect-port-1.3.5.tgz", "integrity": "sha512-Rf3/lB9WkDfIL9eEKaSYKc+1L/rNVYBjThk22JTqQw0YozXarX8YljFAz+HCoC6h4B4KwCMsBPZHaFezwT4BNA==", - "dev": true, "license": "MIT" }, "node_modules/@types/diff": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.3.tgz", "integrity": "sha512-K0Oqlrq3kQMaO2RhfrNQX5trmt+XLyom88zS0u84nnIcLvFnRUMRRHmrGny5GSM+kNO9IZLARsdQHDzkhAgmrQ==", - "dev": true, "license": "MIT" }, "node_modules/@types/doctrine": { @@ -14821,13 +16289,6 @@ "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "license": "MIT" }, - "node_modules/@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "license": "MIT", - "peer": true - }, "node_modules/@types/express": { "version": "4.17.25", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", @@ -15266,7 +16727,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", "integrity": "sha512-nj39q0wAIdhwn7DGUyT9irmsKK1tV0bd5WFEhgpqNTMFZ8cE+jieuTphCW0tfdm47S2zVT5mr09B28b1chmQMA==", - "dev": true, "license": "MIT" }, "node_modules/@types/prismjs": { @@ -15522,7 +16982,6 @@ "version": "7.7.1", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", - "dev": true, "license": "MIT" }, "node_modules/@types/send": { @@ -15710,17 +17169,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/vinyl": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.12.tgz", - "integrity": "sha512-Sr2fYMBUVGYq8kj3UthXFAu5UN6ZW+rYr4NACjZQJvHvj+c8lYv0CahmZ2P/r7iUkN44gGUBwqxZkrKXYPb7cw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/expect": "^1.20.4", - "@types/node": "*" - } - }, "node_modules/@types/webpack": { "version": "4.41.40", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.40.tgz", @@ -17187,7 +18635,6 @@ "version": "3.0.0-rc.15", "resolved": "https://registry.npmjs.org/@yarnpkg/esbuild-plugin-pnp/-/esbuild-plugin-pnp-3.0.0-rc.15.tgz", "integrity": "sha512-kYzDJO5CA9sy+on/s2aIW0411AklfCi8Ck/4QDivOqsMKpStZA2SsR+X27VTggGwpStWaLrjJcDcdDMowtG8MA==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "tslib": "^2.4.0" @@ -17258,235 +18705,6 @@ "node": ">=18.12.0" } }, - "node_modules/@yeoman/adapter": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@yeoman/adapter/-/adapter-2.1.1.tgz", - "integrity": "sha512-GJqZ/e+IkgAIaUUqBNngR2Y53eVCiJeMrqx8cLATDauEB6/SdEUIGeyRjaWuXdg+kAJHreFtNdBUDmfHO1lc0w==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@inquirer/core": "^10.0.0", - "chalk": "^5.2.0", - "inquirer": "^12.0.0", - "log-symbols": "^7.0.0", - "ora": "^8.1.0", - "p-queue": "^8.0.1", - "text-table": "^0.2.0" - }, - "engines": { - "node": ">=18.12.0" - } - }, - "node_modules/@yeoman/adapter/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "devOptional": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@yeoman/adapter/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "devOptional": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@yeoman/adapter/node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "restore-cursor": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@yeoman/adapter/node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "devOptional": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@yeoman/adapter/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "devOptional": true, - "license": "MIT", - "peer": true - }, - "node_modules/@yeoman/adapter/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==", - "devOptional": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@yeoman/adapter/node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "mimic-function": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@yeoman/adapter/node_modules/ora": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", - "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", - "devOptional": true, - "license": "MIT", - "peer": true, - "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/@yeoman/adapter/node_modules/ora/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==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "chalk": "^5.3.0", - "is-unicode-supported": "^1.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@yeoman/adapter/node_modules/ora/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==", - "devOptional": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@yeoman/adapter/node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@yeoman/adapter/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==", - "devOptional": true, - "license": "MIT", - "peer": true, - "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/@yeoman/adapter/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/@yeoman/namespace": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@yeoman/namespace/-/namespace-1.0.1.tgz", @@ -17496,33 +18714,6 @@ "node": "^16.13.0 || >=18.12.0" } }, - "node_modules/@yeoman/types": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@yeoman/types/-/types-1.9.1.tgz", - "integrity": "sha512-5BMdA/zMzLv/ahnL1ktaV46nSXorb4sU4kQPQKDhIcK8ERbx9TAbGAE+XAlCXKioNIiOrihYj6gW1d/GEfU9Zw==", - "license": "MIT", - "peer": true, - "engines": { - "node": "^16.13.0 || >=18.12.0" - }, - "peerDependencies": { - "@types/node": ">=16.18.26", - "@yeoman/adapter": "^1.6.0 || ^2.0.0-beta.0 || ^3.0.0 || ^4.0.0", - "mem-fs": "^3.0.0 || ^4.0.0-beta.1", - "mem-fs-editor": "^10.0.2 || >=10.0.2" - }, - "peerDependenciesMeta": { - "@yeoman/adapter": { - "optional": true - }, - "mem-fs": { - "optional": true - }, - "mem-fs-editor": { - "optional": true - } - } - }, "node_modules/@zkochan/js-yaml": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", @@ -17594,7 +18785,6 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, "license": "MIT", "dependencies": { "mime-types": "~2.1.34", @@ -17688,7 +18878,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 10.0.0" @@ -18100,7 +19289,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true, "license": "MIT" }, "node_modules/array-ify": { @@ -18505,7 +19693,6 @@ "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", - "dev": true, "license": "MIT", "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -18688,7 +19875,6 @@ "version": "0.4.14", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.27.7", @@ -18703,7 +19889,6 @@ "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" @@ -18713,7 +19898,6 @@ "version": "0.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.5", @@ -18727,7 +19911,6 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.5" @@ -18946,7 +20129,6 @@ "version": "2.9.14", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz", "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==", - "dev": true, "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.js" @@ -19003,7 +20185,6 @@ "version": "1.6.52", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "dev": true, "license": "Unlicense", "engines": { "node": ">=0.6" @@ -19089,7 +20270,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, "license": "MIT", "dependencies": { "buffer": "^5.5.0", @@ -19101,7 +20281,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -19147,7 +20326,6 @@ "version": "1.20.4", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "dev": true, "license": "MIT", "dependencies": { "bytes": "~3.1.2", @@ -19172,7 +20350,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -19182,7 +20359,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" @@ -19195,7 +20371,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/bonjour-service": { @@ -19275,7 +20450,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, "license": "MIT", "dependencies": { "big-integer": "^1.6.44" @@ -19345,7 +20519,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", - "dev": true, "license": "MIT", "dependencies": { "pako": "~0.2.0" @@ -19355,14 +20528,12 @@ "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", - "dev": true, "license": "MIT" }, "node_modules/browserslist": { "version": "4.28.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -19428,7 +20599,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "funding": [ { "type": "github", @@ -19519,7 +20689,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -19858,7 +21027,6 @@ "version": "1.0.30001764", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz", "integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==", - "dev": true, "funding": [ { "type": "opencollective", @@ -20016,7 +21184,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/charenc": { @@ -20107,7 +21275,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -20180,7 +21347,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", - "dev": true, "license": "MIT", "dependencies": { "consola": "^3.2.3" @@ -20248,7 +21414,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" @@ -20374,7 +21539,6 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -20387,7 +21551,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz", "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==", - "dev": true, "license": "MIT", "dependencies": { "string-width": "^4.2.0" @@ -20421,7 +21584,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "devOptional": true, + "dev": true, "license": "ISC", "engines": { "node": ">= 12" @@ -20483,7 +21646,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4", @@ -20614,7 +21776,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, "license": "MIT", "optional": true, "engines": { @@ -20675,7 +21836,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -20719,7 +21879,6 @@ "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, "license": "MIT", "dependencies": { "mime-db": ">= 1.43.0 < 2" @@ -20732,7 +21891,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", - "dev": true, "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -20751,7 +21909,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -20761,14 +21918,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/compression/node_modules/negotiator": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -20842,7 +21997,6 @@ "version": "0.1.8", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", - "dev": true, "license": "MIT" }, "node_modules/config-chain": { @@ -20882,7 +22036,6 @@ "version": "3.4.2", "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "dev": true, "license": "MIT", "engines": { "node": "^14.18.0 || >=16.10.0" @@ -20906,7 +22059,6 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" @@ -20919,7 +22071,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -21998,14 +23149,12 @@ "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/cookie": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -22015,7 +23164,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "dev": true, "license": "MIT" }, "node_modules/copy-to-clipboard": { @@ -22092,7 +23240,6 @@ "version": "3.47.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz", "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==", - "dev": true, "license": "MIT", "dependencies": { "browserslist": "^4.28.0" @@ -22587,9 +23734,9 @@ "license": "MIT" }, "node_modules/cypress": { - "version": "15.8.2", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-15.8.2.tgz", - "integrity": "sha512-KGpuiE8o9l9eyVLPkig574t8zOXkEDKzI0a+RQwy4cfXzpaLipvTOv0t+QEEkLiw/8HbgMNZ0fbPKakJAB3USA==", + "version": "15.13.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-15.13.0.tgz", + "integrity": "sha512-hJ9sY++TUC/HlUzHVJpIrDyqKMjlhx5PTXl/A7eA91JNEtUWkJAqefQR5mo9AtLra/9+m+JJaMg2U5Qd0a74Fw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -22623,7 +23770,7 @@ "hasha": "5.2.2", "is-installed-globally": "~0.4.0", "listr2": "^3.8.3", - "lodash": "^4.17.21", + "lodash": "^4.17.23", "log-symbols": "^4.0.0", "minimist": "^1.2.8", "ospath": "^1.2.2", @@ -22632,9 +23779,10 @@ "proxy-from-env": "1.0.0", "request-progress": "^3.0.0", "supports-color": "^8.1.1", - "systeminformation": "^5.27.14", + "systeminformation": "^5.31.1", "tmp": "~0.2.4", "tree-kill": "1.2.2", + "tslib": "1.14.1", "untildify": "^4.0.0", "yauzl": "^2.10.0" }, @@ -22755,37 +23903,13 @@ "node": ">=8.12.0" } }, - "node_modules/cypress/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cypress/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/cypress/node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "peer": true }, "node_modules/cypress/node_modules/signal-exit": { "version": "3.0.7", @@ -22812,6 +23936,14 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/cypress/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD", + "peer": true + }, "node_modules/d3": { "version": "3.5.17", "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz", @@ -23459,7 +24591,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dev": true, "license": "MIT", "dependencies": { "bplist-parser": "^0.2.0", @@ -23506,7 +24637,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, "license": "MIT", "dependencies": { "clone": "^1.0.2" @@ -23519,7 +24649,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.8" @@ -23582,7 +24711,6 @@ "version": "6.1.4", "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "dev": true, "license": "MIT" }, "node_modules/degenerator": { @@ -23623,7 +24751,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -23649,7 +24776,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8", @@ -23696,7 +24822,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/detect-package-manager/-/detect-package-manager-2.0.1.tgz", "integrity": "sha512-j/lJHyoLlWi6G1LDdLgvUtz60Zo5GEj+sVYtTVXnYLDPuzgC3llMxonXym9zIwhhUII8vjdw0LXxavpLqTbl1A==", - "dev": true, "license": "MIT", "dependencies": { "execa": "^5.1.1" @@ -23709,7 +24834,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", - "dev": true, "license": "MIT", "dependencies": { "address": "^1.0.1", @@ -23727,7 +24851,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -23737,7 +24860,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/devlop": { @@ -24128,7 +25250,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true, "license": "MIT" }, "node_modules/ejs": { @@ -24150,7 +25271,6 @@ "version": "1.5.267", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", - "dev": true, "license": "ISC" }, "node_modules/email-addresses": { @@ -24311,7 +25431,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -24592,7 +25711,6 @@ "version": "7.13.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", - "dev": true, "license": "MIT", "bin": { "envinfo": "dist/cli.js" @@ -24884,7 +26002,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/esbuild-plugin-alias/-/esbuild-plugin-alias-0.2.1.tgz", "integrity": "sha512-jyfL/pwPqaFXyKnj8lP8iLk6Z0m099uXR45aSN8Av1XD4vhvQutxxPzgA2bTcAwQpa1zCXDcWOlhFgyP3GKqhQ==", - "dev": true, "license": "MIT" }, "node_modules/esbuild-register": { @@ -26355,7 +27472,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -26383,9 +27499,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "devOptional": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/events": { "version": "3.3.0", @@ -26576,7 +27690,6 @@ "version": "4.22.1", "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "dev": true, "license": "MIT", "dependencies": { "accepts": "~1.3.8", @@ -26623,7 +27736,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -26633,7 +27745,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/extend": { @@ -27207,7 +28318,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "dev": true, "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -27226,7 +28336,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -27236,14 +28345,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/find-cache-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, "license": "MIT", "dependencies": { "commondir": "^1.0.1", @@ -27258,7 +28365,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "license": "MIT", "dependencies": { "locate-path": "^3.0.0" @@ -27271,7 +28377,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "license": "MIT", "dependencies": { "p-locate": "^3.0.0", @@ -27285,7 +28390,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -27301,7 +28405,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "license": "MIT", "dependencies": { "p-limit": "^2.0.0" @@ -27314,7 +28417,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -27324,7 +28426,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, "license": "MIT", "dependencies": { "find-up": "^3.0.0" @@ -27440,19 +28541,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/first-chunk-stream": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-5.0.0.tgz", - "integrity": "sha512-WdHo4ejd2cG2Dl+sLkW79SctU7mUQDfr4s1i26ffOZRs5mgv+BRttIM9gwcq0rDbemo0KlpVPaa3LBVLqPXzcQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -27487,7 +28575,6 @@ "version": "0.296.1", "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.296.1.tgz", "integrity": "sha512-dASEzkw6jlgYx1poIqbf8f21OiyD5f0ebEbvwZVohEixE7agpGb+HbAL35BrzAUyb390nfRfFOsG+alNx1Sqww==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -27764,7 +28851,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -27774,7 +28860,6 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -27826,7 +28911,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true, "license": "MIT" }, "node_modules/fs-extra": { @@ -28076,7 +29160,6 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -28619,20 +29702,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", - "devOptional": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -28670,7 +29739,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/get-npm-tarball-url/-/get-npm-tarball-url-2.1.0.tgz", "integrity": "sha512-ro+DiMu5DXgRBabqXupW38h7WPZ9+Ad8UjwhvsmmN8w1sU7ab0nzAXvVZ4kqYg57OrqomRtJvepX5/xvFKNtjA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12.17" @@ -29054,7 +30122,6 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.5.tgz", "integrity": "sha512-r1ekGw/Bgpi3HLV3h1MRBIlSAdHoIMklpaQ3OQLFcRw9PwAj2rqigvIbg+dBUI51OxVI2jsEtDywDBjSiuf7Ug==", - "dev": true, "license": "MIT", "dependencies": { "citty": "^0.1.6", @@ -29738,7 +30805,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/glob/node_modules/brace-expansion": { @@ -30032,7 +31098,6 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", - "dev": true, "license": "MIT", "dependencies": { "browserify-zlib": "^0.1.4", @@ -30965,7 +32030,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "dev": true, "license": "MIT", "dependencies": { "depd": "~2.0.0", @@ -31174,7 +32238,7 @@ "version": "0.7.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -31510,65 +32574,6 @@ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", "license": "MIT" }, - "node_modules/inquirer": { - "version": "12.11.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.11.1.tgz", - "integrity": "sha512-9VF7mrY+3OmsAfjH3yKz/pLbJ5z22E23hENKw3/LNSaA/sAt3v49bDRY+Ygct1xwuKT+U+cBfTzjCPySna69Qw==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/prompts": "^7.10.1", - "@inquirer/type": "^3.0.10", - "mute-stream": "^2.0.0", - "run-async": "^4.0.6", - "rxjs": "^7.8.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/inquirer/node_modules/@inquirer/prompts": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", - "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@inquirer/checkbox": "^4.3.2", - "@inquirer/confirm": "^5.1.21", - "@inquirer/editor": "^4.2.23", - "@inquirer/expand": "^4.0.23", - "@inquirer/input": "^4.3.1", - "@inquirer/number": "^3.0.23", - "@inquirer/password": "^4.0.23", - "@inquirer/rawlist": "^4.1.11", - "@inquirer/search": "^3.2.2", - "@inquirer/select": "^4.4.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -31663,7 +32668,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.10" @@ -31940,7 +32944,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", - "dev": true, "license": "MIT" }, "node_modules/is-docker": { @@ -32042,7 +33045,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -32122,7 +33124,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -32257,7 +33258,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "license": "MIT", "dependencies": { "isobject": "^3.0.1" @@ -32427,13 +33427,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", - "license": "MIT", - "peer": true - }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -32534,7 +33527,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -32606,9 +33598,9 @@ } }, "node_modules/istanbul-lib-processinfo": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", - "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-3.0.0.tgz", + "integrity": "sha512-P7nLXRRlo7Sqinty6lNa7+4o9jBUYGpqtejqCOZKfgXlRoxY/QArflcB86YO500Ahj4pDJEG34JjMRbQgePLnQ==", "dev": true, "license": "ISC", "peer": true, @@ -32617,11 +33609,83 @@ "cross-spawn": "^7.0.3", "istanbul-lib-coverage": "^3.2.0", "p-map": "^3.0.0", - "rimraf": "^3.0.0", + "rimraf": "^6.1.3", "uuid": "^8.3.2" }, "engines": { - "node": ">=8" + "node": "20 || >=22" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/istanbul-lib-processinfo/node_modules/p-map": { @@ -32638,6 +33702,45 @@ "node": ">=8" } }, + "node_modules/istanbul-lib-processinfo/node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/istanbul-lib-processinfo/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -34948,7 +36051,6 @@ "version": "0.15.2", "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.23.0", @@ -34988,7 +36090,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -35005,14 +36106,12 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, "license": "ISC" }, "node_modules/jscodeshift/node_modules/write-file-atomic": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, "license": "ISC", "dependencies": { "graceful-fs": "^4.1.11", @@ -35020,16 +36119,6 @@ "signal-exit": "^3.0.2" } }, - "node_modules/jsdoc-type-pratt-parser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.8.0.tgz", - "integrity": "sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/jsdom": { "version": "26.1.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", @@ -35459,6 +36548,15 @@ "jss": "10.10.0" } }, + "node_modules/jsts": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/jsts/-/jsts-2.7.1.tgz", + "integrity": "sha512-x2wSZHEBK20CY+Wy+BPE7MrFQHW6sIsdaGUMEqmGAio+3gFzQaBYPwLRonUfQf9Ak8pBieqj9tUofX1+WtAEIg==", + "license": "(EDL-1.0 OR EPL-1.0)", + "engines": { + "node": ">= 12" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -35548,7 +36646,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -35558,7 +36655,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -36084,23 +37180,6 @@ "node": ">=8" } }, - "node_modules/lerna/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/lerna/node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -36350,7 +37429,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -36604,7 +37682,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true, "license": "MIT" }, "node_modules/lodash.escaperegexp": { @@ -36679,6 +37756,13 @@ "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", "license": "MIT" }, + "node_modules/lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==", + "deprecated": "This package is deprecated. Use destructuring assignment syntax instead.", + "license": "MIT" + }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -36699,6 +37783,12 @@ "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", "license": "MIT" }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT" + }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -36718,18 +37808,44 @@ "license": "MIT" }, "node_modules/log-symbols": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-7.0.1.tgz", - "integrity": "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==", - "devOptional": true, + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "license": "MIT", - "peer": true, "dependencies": { - "is-unicode-supported": "^2.0.0", - "yoctocolors": "^2.1.1" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "license": "MIT", + "engines": { + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -36864,7 +37980,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^3.0.2" @@ -36950,7 +38065,6 @@ "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", "dependencies": { "pify": "^4.0.1", @@ -36964,7 +38078,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -36974,7 +38087,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver" @@ -37635,28 +38747,11 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/mem-fs": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-4.1.3.tgz", - "integrity": "sha512-+2zSUVKcDWgcF90mPPwyH4J814uRI1PJcVt2RZ4/E8VggPEiIEL7ikMTlPR91P2ZySkyPgD0YGrccwo55SZvnw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": ">=18", - "@types/vinyl": "^2.0.12", - "vinyl": "^3.0.0", - "vinyl-file": "^5.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/mem-fs-editor": { "version": "11.1.4", "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-11.1.4.tgz", @@ -37849,7 +38944,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -37892,7 +38986,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -38499,7 +39592,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -38509,7 +39601,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -38527,20 +39618,6 @@ "node": ">=6" } }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "devOptional": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -38657,10 +39734,10 @@ } }, "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } @@ -38799,7 +39876,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, "license": "MIT", "dependencies": { "minipass": "^3.0.0", @@ -38813,7 +39889,6 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -38826,7 +39901,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, "license": "ISC" }, "node_modules/mitt": { @@ -38845,7 +39919,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" @@ -38858,14 +39931,12 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true, "license": "MIT" }, "node_modules/mlly": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", - "dev": true, "license": "MIT", "dependencies": { "acorn": "^8.15.0", @@ -38878,7 +39949,6 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -38907,16 +39977,6 @@ "node": ">=0.10.0" } }, - "node_modules/moment": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", - "license": "MIT", - "peer": true, - "engines": { - "node": "*" - } - }, "node_modules/monaco-editor": { "version": "0.49.0", "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.49.0.tgz", @@ -39031,7 +40091,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "devOptional": true, + "dev": true, "license": "ISC", "engines": { "node": "^18.17.0 || >=20.5.0" @@ -39102,7 +40162,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -39193,7 +40252,6 @@ "version": "0.1.17", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", - "dev": true, "license": "MIT", "dependencies": { "minimatch": "^3.0.2" @@ -39206,7 +40264,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -39217,7 +40274,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -39306,7 +40362,6 @@ "version": "1.6.7", "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", - "dev": true, "license": "MIT" }, "node_modules/node-fetch/node_modules/tr46": { @@ -39435,7 +40490,6 @@ "version": "2.0.27", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "dev": true, "license": "MIT" }, "node_modules/nomnom": { @@ -42285,36 +43339,6 @@ "node": ">=8.6" } }, - "node_modules/nx/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nx/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/nx/node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -42355,9 +43379,9 @@ } }, "node_modules/nyc": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-17.1.0.tgz", - "integrity": "sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-18.0.0.tgz", + "integrity": "sha512-G5UyHinFkB1BxqGTrmZdB6uIYH0+v7ZnVssuflUDi+J+RhKWyAhRT1RCehBSI6jLFLuUUgFDyLt49mUtdO1XeQ==", "dev": true, "license": "ISC", "peer": true, @@ -42371,11 +43395,11 @@ "find-up": "^4.1.0", "foreground-child": "^3.3.0", "get-package-type": "^0.1.0", - "glob": "^7.1.6", + "glob": "^13.0.6", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-hook": "^3.0.0", "istanbul-lib-instrument": "^6.0.2", - "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-processinfo": "^3.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.2", @@ -42384,17 +43408,42 @@ "p-map": "^3.0.0", "process-on-spawn": "^1.0.0", "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", + "rimraf": "^6.1.3", "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", + "spawn-wrap": "^3.0.0", + "test-exclude": "^8.0.0", "yargs": "^15.0.2" }, "bin": { "nyc": "bin/nyc.js" }, "engines": { - "node": ">=18" + "node": "20 || >=22" + } + }, + "node_modules/nyc/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/nyc/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/nyc/node_modules/camelcase": { @@ -42463,6 +43512,25 @@ "node": ">=8" } }, + "node_modules/nyc/node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/nyc/node_modules/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", @@ -42493,6 +43561,17 @@ "node": ">=8" } }, + "node_modules/nyc/node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/nyc/node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -42510,6 +43589,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/nyc/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/nyc/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -42555,6 +43651,24 @@ "node": ">=8" } }, + "node_modules/nyc/node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/nyc/node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -42569,6 +43683,27 @@ "node": ">=8" } }, + "node_modules/nyc/node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/nyc/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -42599,6 +43734,22 @@ "node": ">=0.10.0" } }, + "node_modules/nyc/node_modules/test-exclude": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-8.0.0.tgz", + "integrity": "sha512-ZOffsNrXYggvU1mDGHk54I96r26P8SyMjO5slMKSc7+IWmtB/MQKnEC2fP51imB3/pT6YK5cT5E8f+Dd9KdyOQ==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^13.0.6", + "minimatch": "^10.2.2" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/nyc/node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", @@ -42650,7 +43801,6 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.5.4.tgz", "integrity": "sha512-X0SNNrZiGU8/e/zAB7sCTtdxWTMSIO73q+xuKgglm2Yvzwlo8UoC5FNySQFCvl84uPaeADkqHUZUkWy4aH4xOA==", - "dev": true, "license": "MIT", "dependencies": { "citty": "^0.1.6", @@ -42671,7 +43821,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true, "license": "MIT" }, "node_modules/object-assign": { @@ -42907,7 +44056,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, "license": "MIT", "dependencies": { "ee-first": "1.1.1" @@ -42920,7 +44068,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -43443,24 +44590,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-queue": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", - "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "eventemitter3": "^5.0.1", - "p-timeout": "^6.1.2" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-reduce": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz", @@ -43878,7 +45007,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -43967,7 +45095,6 @@ "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "dev": true, "license": "MIT" }, "node_modules/path-type": { @@ -43983,7 +45110,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, "license": "MIT" }, "node_modules/pbf": { @@ -44127,7 +45253,6 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -44275,7 +45400,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", - "dev": true, "license": "MIT", "dependencies": { "confbox": "^0.1.8", @@ -44324,6 +45448,15 @@ "node": ">= 0.8.0" } }, + "node_modules/point-in-polygon-hao": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/point-in-polygon-hao/-/point-in-polygon-hao-1.2.4.tgz", + "integrity": "sha512-x2pcvXeqhRHlNRdhLs/tgFapAbSSe86wa/eqmj1G6pWftbEs5aVRJhRGM6FYSUERKu0PjekJzMq0gsI2XyiclQ==", + "license": "MIT", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/polished": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", @@ -44336,6 +45469,16 @@ "node": ">=10" } }, + "node_modules/polyclip-ts": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/polyclip-ts/-/polyclip-ts-0.16.8.tgz", + "integrity": "sha512-JPtKbDRuPEuAjuTdhR62Gph7Is2BS1Szx69CFOO3g71lpJDFo78k4tFyi+qFOMVPePEzdSKkpGU3NBXPHHjvKQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.1.0", + "splaytree-ts": "^1.0.2" + } + }, "node_modules/popper.js": { "version": "1.16.1-lts", "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", @@ -45085,7 +46228,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", - "devOptional": true, "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" @@ -45398,7 +46540,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, "license": "MIT", "dependencies": { "kleur": "^3.0.3", @@ -45471,7 +46612,6 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, "license": "MIT", "dependencies": { "forwarded": "0.2.0", @@ -45591,7 +46731,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", - "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -45602,7 +46741,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, "license": "MIT", "dependencies": { "duplexify": "^3.6.0", @@ -45614,7 +46752,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -45930,7 +47067,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -45940,7 +47076,6 @@ "version": "2.5.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "dev": true, "license": "MIT", "dependencies": { "bytes": "~3.1.2", @@ -45956,7 +47091,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" @@ -48182,14 +49316,12 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true, "license": "MIT" }, "node_modules/regenerate-unicode-properties": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", - "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2" @@ -48238,7 +49370,6 @@ "version": "6.4.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", - "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2", @@ -48283,14 +49414,12 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", - "dev": true, "license": "MIT" }, "node_modules/regjsparser": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "jsesc": "~3.1.0" @@ -49640,7 +50769,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, "license": "MIT", "dependencies": { "onetime": "^5.1.0", @@ -49654,7 +50782,6 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, "license": "ISC" }, "node_modules/ret": { @@ -49752,17 +50879,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/run-async": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-4.0.6.tgz", - "integrity": "sha512-IoDlSLTs3Yq593mb3ZoKWKXMNu3UpObxhgA/Xuid5p4bbfi2jdY1Hj0m1K+0/tEuQTxIGMhQDqGjKb7RuxGpAQ==", - "devOptional": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -49795,7 +50911,7 @@ "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" @@ -49908,7 +51024,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "devOptional": true, "license": "MIT" }, "node_modules/sax": { @@ -50361,7 +51476,6 @@ "version": "0.19.2", "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", - "dev": true, "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -50386,7 +51500,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -50396,14 +51509,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/send/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", "bin": { "mime": "cli.js" @@ -50416,7 +51527,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/serialize-javascript": { @@ -50528,7 +51638,6 @@ "version": "1.16.3", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", - "dev": true, "license": "MIT", "dependencies": { "encodeurl": "~2.0.0", @@ -50610,14 +51719,12 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true, "license": "ISC" }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, "license": "MIT", "dependencies": { "kind-of": "^6.0.2" @@ -51038,7 +52145,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, "license": "MIT" }, "node_modules/skin-tone": { @@ -51315,7 +52421,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", @@ -51326,7 +52431,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -51349,17 +52453,18 @@ "license": "MIT" }, "node_modules/spawn-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-3.0.0.tgz", + "integrity": "sha512-z+s5vv4KzFPJVddGab0xX2n7kQPGMdNUX5l9T8EJqsXdKTWpcxmAqWHpsgHEXoC1taGBCc7b79bi62M5kdbrxQ==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "peer": true, "dependencies": { + "cross-spawn": "^7.0.6", "foreground-child": "^2.0.0", "is-windows": "^1.0.2", "make-dir": "^3.0.0", - "rimraf": "^3.0.0", + "rimraf": "^6.1.3", "signal-exit": "^3.0.2", "which": "^2.0.1" }, @@ -51367,6 +52472,31 @@ "node": ">=8" } }, + "node_modules/spawn-wrap/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/spawn-wrap/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/spawn-wrap/node_modules/foreground-child": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", @@ -51382,6 +52512,36 @@ "node": ">=8.0.0" } }, + "node_modules/spawn-wrap/node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/spawn-wrap/node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/spawn-wrap/node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -51399,6 +52559,62 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/spawn-wrap/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/spawn-wrap/node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/spawn-wrap/node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/spawn-wrap/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -51546,6 +52762,12 @@ "integrity": "sha512-D50hKrjZgBzqD3FT2Ek53f2dcDLAQT8SSGrzj3vidNH5ISRgceeGVJ2dQIthKOuayqFXfFjXheHNo4bbt9LhRQ==", "license": "MIT" }, + "node_modules/splaytree-ts": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/splaytree-ts/-/splaytree-ts-1.0.2.tgz", + "integrity": "sha512-0kGecIZNIReCSiznK3uheYB8sbstLjCZLiwcQwbmLhgHJj2gz6OnSPkVzJQCMnmEz1BQ4gPK59ylhBoEWOhGNA==", + "license": "BDS-3-Clause" + }, "node_modules/split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", @@ -51854,26 +53076,11 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, - "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==", - "devOptional": true, - "license": "MIT", - "peer": true, - "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", @@ -51897,7 +53104,6 @@ "version": "8.1.11", "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.1.11.tgz", "integrity": "sha512-3KjIhF8lczXhKKHyHbOqV30dvuRYJSxc0d1as/C8kybuwE7cLaydhWGma7VBv5bTSPv0rDzucx7KcO+achArPg==", - "dev": true, "license": "MIT", "dependencies": { "@storybook/cli": "8.1.11" @@ -52219,39 +53425,6 @@ "node": ">=8" } }, - "node_modules/strip-bom-buf": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-3.0.1.tgz", - "integrity": "sha512-iJaWw2WroigLHzQysdc5WWeUc99p7ea7AEgB6JkY8CMyiO1yTVAA1gIlJJgORElUIR+lcZJkNl1OGChMhvc2Cw==", - "license": "MIT", - "peer": true, - "dependencies": { - "is-utf8": "^0.2.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-bom-stream": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-5.0.0.tgz", - "integrity": "sha512-Yo472mU+3smhzqeKlIxClre4s4pwtYZEvDNQvY/sJpnChdaxmKuwU28UVx/v1ORKNMxkmj1GBuvxJQyBk6wYMQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "first-chunk-stream": "^5.0.0", - "strip-bom-buf": "^3.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", @@ -52550,6 +53723,21 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/sweepline-intersections": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sweepline-intersections/-/sweepline-intersections-1.5.0.tgz", + "integrity": "sha512-AoVmx72QHpKtItPu72TzFL+kcYjd67BPLDoR0LarIk+xyaRg+pDTMFXndIEvZf9xEKnJv6JdhgRMnocoG0D3AQ==", + "license": "MIT", + "dependencies": { + "tinyqueue": "^2.0.0" + } + }, + "node_modules/sweepline-intersections/node_modules/tinyqueue": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", + "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==", + "license": "ISC" + }, "node_modules/symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", @@ -52584,9 +53772,9 @@ } }, "node_modules/systeminformation": { - "version": "5.30.3", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.30.3.tgz", - "integrity": "sha512-NgHJUpA+y7j4asLQa9jgBt+Eb2piyQIXQ+YjOyd2K0cHNwbNJ6I06F5afOqOiaCuV/wrEyGrb0olg4aFLlJD+A==", + "version": "5.31.5", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.5.tgz", + "integrity": "sha512-5SyLdip4/3alxD4Kh+63bUQTJmu7YMfYQTC+koZy7X73HgNqZSD2P4wOZQWtUncvPvcEmnfIjCoygN4MRoEejQ==", "dev": true, "license": "MIT", "os": [ @@ -52629,7 +53817,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, "license": "ISC", "dependencies": { "chownr": "^2.0.0", @@ -52689,7 +53876,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, "license": "MIT", "dependencies": { "bl": "^4.0.3", @@ -52706,7 +53892,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -52721,7 +53906,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, "license": "ISC", "dependencies": { "minipass": "^3.0.0" @@ -52734,7 +53918,6 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -52747,7 +53930,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, "license": "ISC", "engines": { "node": ">=8" @@ -52757,7 +53939,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, "license": "ISC" }, "node_modules/teen_process": { @@ -52800,7 +53981,6 @@ "version": "0.8.4", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", - "dev": true, "license": "MIT", "dependencies": { "rimraf": "~2.6.2" @@ -52824,7 +54004,6 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -53410,7 +54589,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.6" @@ -54460,7 +55638,6 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, "license": "MIT", "dependencies": { "media-typer": "0.3.0", @@ -54638,7 +55815,6 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.2.tgz", "integrity": "sha512-heMioaxBcG9+Znsda5Q8sQbWnLJSl98AFDXTO80wELWEzX3hordXsTdxrIfMQoO9IY1MEnoGoPjpoKpMj+Yx0Q==", - "dev": true, "license": "MIT" }, "node_modules/uglify-js": { @@ -54721,7 +55897,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -54740,7 +55915,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, "license": "MIT", "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", @@ -54754,7 +55928,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -54764,7 +55937,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -55014,7 +56186,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -55093,7 +56264,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -55114,7 +56284,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, "funding": [ { "type": "opencollective", @@ -55318,7 +56487,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4.0" @@ -55472,7 +56640,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -55676,25 +56843,6 @@ "node": ">=10.13.0" } }, - "node_modules/vinyl-file": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-5.0.0.tgz", - "integrity": "sha512-MvkPF/yA1EX7c6p+juVIvp9+Lxp70YUfNKzEWeHMKpUNVSnTZh2coaOqLxI0pmOe2V9nB+OkgFaMDkodaJUyGw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/vinyl": "^2.0.7", - "strip-bom-buf": "^3.0.1", - "strip-bom-stream": "^5.0.0", - "vinyl": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/vlq": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", @@ -55753,7 +56901,6 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.0.tgz", "integrity": "sha512-e6vZvY6xboSwLz2GD36c16+O/2Z6fKvIf4pOXptw2rY9MVwE/TXc6RGqxD3I3x0a28lwBY7DE+76uTPSsBrrCA==", - "dev": true, "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", @@ -55777,7 +56924,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, "license": "MIT", "dependencies": { "defaults": "^1.0.3" @@ -56832,7 +57978,7 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -57127,7 +58273,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, "license": "ISC" }, "node_modules/yaml": { @@ -57451,7 +58596,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -58382,33 +59527,6 @@ "url": "https://opencollective.com/webpack" } }, - "packages/superset-ui-demo/node_modules/storybook": { - "version": "8.6.15", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.6.15.tgz", - "integrity": "sha512-Ob7DMlwWx8s7dMvcQ3xPc02TvUeralb+xX3oaPRk9wY9Hc6M1IBC/7cEoITkSmRS2v38DHubC+mtEKNc1u2gQg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@storybook/core": "8.6.15" - }, - "bin": { - "getstorybook": "bin/index.cjs", - "sb": "bin/index.cjs", - "storybook": "bin/index.cjs" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "prettier": "^2 || ^3" - }, - "peerDependenciesMeta": { - "prettier": { - "optional": true - } - } - }, "packages/superset-ui-demo/node_modules/style-loader": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", @@ -58475,6 +59593,7 @@ "license": "Apache-2.0", "dependencies": { "@ant-design/icons": "^5.6.1", + "@deck.gl-community/editable-layers": "^9.2.8", "@deck.gl/aggregation-layers": "^9.1.14", "@deck.gl/core": "^9.1.14", "@deck.gl/extensions": "^9.1.14", @@ -58483,6 +59602,13 @@ "@mapbox/geojson-extent": "^1.0.1", "@material-ui/icons": "^4.11.3", "@math.gl/web-mercator": "^4.1.0", + "@turf/area": "^7.2.0", + "@turf/boolean-intersects": "^7.2.0", + "@turf/boolean-point-in-polygon": "^7.2.0", + "@turf/centroid": "^7.2.0", + "@turf/helpers": "^7.2.0", + "@turf/intersect": "^7.2.0", + "@turf/unkink-polygon": "^7.2.0", "@types/d3-array": "^2.0.0", "@types/d3-interpolate": "^3.0.4", "@types/d3-scale-chromatic": "^3.1.0", @@ -58521,6 +59647,171 @@ "react-map-gl": "^6.1.19" } }, + "plugins/geoset-map-chart/node_modules/@deck.gl-community/editable-layers": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@deck.gl-community/editable-layers/-/editable-layers-9.2.8.tgz", + "integrity": "sha512-E9i4LwstJ+d/BqF46afhKVNHZuQt4gwdWL6jqsD4lfzr0IdWJMGmg+r8xtwHYK+nhbraHfX+ddDNUR03bPvswg==", + "license": "MIT", + "dependencies": { + "@math.gl/web-mercator": ">=4.0.1", + "@turf/along": "^7.2.0", + "@turf/area": "^7.2.0", + "@turf/bbox": "^7.2.0", + "@turf/bbox-polygon": "^7.2.0", + "@turf/bearing": "^7.2.0", + "@turf/boolean-point-in-polygon": "^7.2.0", + "@turf/boolean-within": "^7.2.0", + "@turf/buffer": "^7.2.0", + "@turf/center": "^7.2.0", + "@turf/centroid": "^7.2.0", + "@turf/circle": "^7.2.0", + "@turf/clone": "^7.2.0", + "@turf/destination": "^7.2.0", + "@turf/difference": "^7.2.0", + "@turf/distance": "^7.2.0", + "@turf/ellipse": "^7.2.0", + "@turf/helpers": "^7.2.0", + "@turf/intersect": "^7.2.0", + "@turf/invariant": "^7.2.0", + "@turf/kinks": "^7.2.0", + "@turf/line-intersect": "^7.2.0", + "@turf/meta": "^7.2.0", + "@turf/midpoint": "^7.2.0", + "@turf/nearest-point-on-line": "^7.2.0", + "@turf/point-to-line-distance": "^7.2.0", + "@turf/polygon-to-line": "^7.2.0", + "@turf/rewind": "^7.2.0", + "@turf/rhumb-bearing": "^7.2.0", + "@turf/rhumb-destination": "^7.2.0", + "@turf/rhumb-distance": "^7.2.0", + "@turf/transform-rotate": "^7.2.0", + "@turf/transform-scale": "^7.2.0", + "@turf/transform-translate": "^7.2.0", + "@turf/union": "^7.2.0", + "@types/geojson": "^7946.0.16", + "eventemitter3": "^5.0.0", + "lodash.omit": "^4.1.1", + "lodash.throttle": "^4.1.1", + "preact": "^10.17.0", + "uuid": "9.0.0" + }, + "peerDependencies": { + "@deck.gl-community/layers": "^9.2.0-beta", + "@deck.gl/core": "~9.2.8", + "@deck.gl/extensions": "~9.2.8", + "@deck.gl/geo-layers": "~9.2.8", + "@deck.gl/layers": "~9.2.8", + "@deck.gl/mesh-layers": "~9.2.8", + "@luma.gl/constants": "~9.2.6", + "@luma.gl/core": "~9.2.6", + "@luma.gl/engine": "~9.2.6", + "@math.gl/core": ">=4.0.1" + } + }, + "plugins/geoset-map-chart/node_modules/@deck.gl/extensions": { + "version": "9.2.11", + "resolved": "https://registry.npmjs.org/@deck.gl/extensions/-/extensions-9.2.11.tgz", + "integrity": "sha512-zlpM4Bg1ifBziW1Juiii9NY5gyW2rEhyVTWnhagH/bpTCZ2E73OhnToYt1ouqmoxL6lMtIjhRXz6LPb7tJbHHQ==", + "license": "MIT", + "dependencies": { + "@luma.gl/constants": "~9.2.6", + "@luma.gl/shadertools": "~9.2.6", + "@math.gl/core": "^4.1.0" + }, + "peerDependencies": { + "@deck.gl/core": "~9.2.0", + "@luma.gl/core": "~9.2.6", + "@luma.gl/engine": "~9.2.6" + } + }, + "plugins/geoset-map-chart/node_modules/@turf/boolean-clockwise": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/boolean-clockwise/-/boolean-clockwise-7.3.4.tgz", + "integrity": "sha512-X/O+u/OsoJ99mujhlqviuB7HX0tdJ5931TBjNSseps43XtROVuB5PwBDgwKfu5lY1B4DSGAxbbxJ795RmPnguQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "plugins/geoset-map-chart/node_modules/@turf/clone": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-7.3.4.tgz", + "integrity": "sha512-pwQ+RyQw986uu7IulY/18NRAebwZZScb084bvVqVkTrllwLSv4oVBqUxmUMiwtp+PNdiRGRFOvNyZqtRsiD+Jw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "plugins/geoset-map-chart/node_modules/@turf/helpers": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", + "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "plugins/geoset-map-chart/node_modules/@turf/invariant": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", + "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "plugins/geoset-map-chart/node_modules/@turf/meta": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.4.tgz", + "integrity": "sha512-tlmw9/Hs1p2n0uoHVm1w3ugw1I6L8jv9YZrcdQa4SH5FX5UY0ATrKeIvfA55FlL//PGuYppJp+eyg/0eb4goqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "plugins/geoset-map-chart/node_modules/@turf/rewind": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@turf/rewind/-/rewind-7.3.4.tgz", + "integrity": "sha512-4BZ8MHMujl4NAT7XnIs7JoOuDhpR96oDTB0RtqTeIP4onioIedVnw1ZA3Uq08sILGpR0qKLuDsvdz4x9jtbptg==", + "license": "MIT", + "dependencies": { + "@turf/boolean-clockwise": "7.3.4", + "@turf/clone": "7.3.4", + "@turf/helpers": "7.3.4", + "@turf/invariant": "7.3.4", + "@turf/meta": "7.3.4", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, "plugins/geoset-map-chart/node_modules/d3-color": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", @@ -58591,6 +59882,15 @@ "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", "license": "ISC" }, + "plugins/geoset-map-chart/node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "plugins/legacy-plugin-chart-calendar": { "name": "@superset-ui/legacy-plugin-chart-calendar", "version": "0.20.3", @@ -59153,13 +60453,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "plugins/plugin-chart-handlebars/node_modules/currencyformatter.js": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/currencyformatter.js/-/currencyformatter.js-1.0.5.tgz", - "integrity": "sha512-gNhjgPges50sAHOb56BeEOi33w88sED2nSiY0s9niq1S/64IKB8DB1EmJh8wv5PofFXpHWG91yptoDQAj5GI2w==", - "license": "MIT", - "peer": true - }, "plugins/plugin-chart-handlebars/node_modules/expect": { "version": "30.2.0", "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 1a6c2f63b5..521b363c86 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -151,11 +151,11 @@ "immer": "^10.1.1", "interweave": "^13.1.0", "jquery": "^3.7.1", - "jspdf": "^3.0.1", "js-levenshtein": "^1.1.6", "js-yaml-loader": "^1.2.2", "json-bigint": "^1.0.0", "json-stringify-pretty-compact": "^2.0.0", + "jspdf": "^3.0.1", "lodash": "^4.17.21", "luxon": "^3.5.0", "mapbox-gl": "^3.13.0", diff --git a/superset-frontend/plugins/geoset-map-chart/package.json b/superset-frontend/plugins/geoset-map-chart/package.json index c690c51813..ec3c69faba 100644 --- a/superset-frontend/plugins/geoset-map-chart/package.json +++ b/superset-frontend/plugins/geoset-map-chart/package.json @@ -25,6 +25,7 @@ ], "dependencies": { "@ant-design/icons": "^5.6.1", + "@deck.gl-community/editable-layers": "^9.2.8", "@deck.gl/aggregation-layers": "^9.1.14", "@deck.gl/core": "^9.1.14", "@deck.gl/extensions": "^9.1.14", @@ -33,6 +34,13 @@ "@mapbox/geojson-extent": "^1.0.1", "@material-ui/icons": "^4.11.3", "@math.gl/web-mercator": "^4.1.0", + "@turf/area": "^7.2.0", + "@turf/boolean-intersects": "^7.2.0", + "@turf/boolean-point-in-polygon": "^7.2.0", + "@turf/centroid": "^7.2.0", + "@turf/helpers": "^7.2.0", + "@turf/intersect": "^7.2.0", + "@turf/unkink-polygon": "^7.2.0", "@types/d3-array": "^2.0.0", "@types/d3-interpolate": "^3.0.4", "@types/d3-scale-chromatic": "^3.1.0", diff --git a/superset-frontend/plugins/geoset-map-chart/src/DeckGLContainer.tsx b/superset-frontend/plugins/geoset-map-chart/src/DeckGLContainer.tsx index a34eee8388..721d9dd39a 100644 --- a/superset-frontend/plugins/geoset-map-chart/src/DeckGLContainer.tsx +++ b/superset-frontend/plugins/geoset-map-chart/src/DeckGLContainer.tsx @@ -34,6 +34,7 @@ import { import { StaticMap, MapRef } from 'react-map-gl'; import DeckGL from '@deck.gl/react'; import type { Deck, Layer } from '@deck.gl/core'; +import { GeoJsonLayer } from '@deck.gl/layers'; import { JsonObject, JsonValue, styled } from '@superset-ui/core'; import Tooltip, { TooltipProps } from './components/Tooltip'; import 'mapbox-gl/dist/mapbox-gl.css'; @@ -42,8 +43,9 @@ import { isValidViewport, toNumericViewport, } from './utils/fitViewport'; -import { LayerState } from './types'; +import { GeoJsonFeature, LassoDrawMode, LayerState } from './types'; import { MeasureState, useMeasureLayers } from './components/MeasureOverlay'; +import { LASSO_CURSOR, useLassoLayer } from './components/useLassoLayer'; import { Coordinate } from './utils/measureDistance'; const TICK = 250; // milliseconds @@ -65,6 +67,11 @@ export type DeckGLContainerProps = { onMeasureDragStart?: (coordinate: Coordinate) => void; onMeasureDrag?: (coordinate: Coordinate) => void; onMeasureDragEnd?: (coordinate: Coordinate) => void; + lassoIsActive?: boolean; + lassoDrawMode?: LassoDrawMode; + lassoPolygon?: Coordinate[] | null; + onLassoComplete?: (polygon: Coordinate[]) => void; + selectedFeatures?: GeoJsonFeature[]; onEmptyClick?: () => void; }; @@ -106,6 +113,27 @@ const MeasureTooltip = styled.div` } `; +const LASSO_HINT_TEXT: Record = { + freehand: 'Click and drag to draw selection', + polygon: 'Double-click or click first point to close', + circle: 'Click and drag to draw circle', + rectangle: 'Click and drag to draw rectangle', +}; + +const LassoHintTooltip = styled.div` + position: absolute; + background: ${({ theme }) => theme.colorBgElevated}; + color: ${({ theme }) => theme.colorTextSecondary}; + border: 1px solid ${({ theme }) => theme.colorBorder}; + padding: 4px 8px; + border-radius: 4px; + font-size: 11px; + pointer-events: none; + z-index: 100; + white-space: nowrap; + transform: translate(16px, 16px); +`; + // Custom ruler cursor as a data URI SVG // The cursor is a small ruler icon with a crosshair at the click point (top-left) // Uses white fill with black stroke for visibility on any background @@ -186,6 +214,10 @@ export const DeckGLContainer = memo( const currentViewport = useRef(props.viewport); const pendingSaveTime = useRef(null); const [tooltip, setTooltip] = useState(null); + const [lassoMousePos, setLassoMousePos] = useState<{ + x: number; + y: number; + } | null>(null); const [viewState, setViewState] = useState(() => props.viewport); const [mapReady, setMapReady] = useState(false); @@ -369,16 +401,72 @@ export const DeckGLContainer = memo( distance, } = useMeasureLayers(measureState, project); + // Get lasso editable layer (library-based drawing) + const lassoIsActive = props.lassoIsActive ?? false; + const lassoDrawMode = props.lassoDrawMode ?? 'freehand'; + const lassoPolygon = props.lassoPolygon ?? null; + const noopLassoComplete = useCallback(() => {}, []); + const { layers: lassoLayers } = useLassoLayer( + lassoIsActive, + props.onLassoComplete ?? noopLassoComplete, + lassoDrawMode, + lassoPolygon, + ); + + const selectedFeaturesArr = useMemo( + () => props.selectedFeatures ?? [], + [props.selectedFeatures], + ); + const hasSelection = selectedFeaturesArr.length > 0; + + // Build a highlight layer from lasso-selected features + const highlightLayer = useMemo(() => { + if (!hasSelection) return []; + return [ + new GeoJsonLayer({ + id: 'lasso-highlight', + data: { + type: 'FeatureCollection' as const, + features: selectedFeaturesArr, + }, + getFillColor: (f: any) => { + const c = f.color ?? f.properties?.color; + if (!c) return [255, 200, 0, 200]; + return c.length >= 4 ? c : [...c, 200]; + }, + getLineColor: (f: any) => { + const c = f.strokeColor ?? f.properties?.strokeColor; + if (!c) return [40, 40, 40, 220]; + return c.length >= 4 ? c : [...c, 220]; + }, + getPointRadius: (f: any) => f.sizeValue ?? 4, + pointRadiusMinPixels: 4, + lineWidthMinPixels: 1, + pickable: false, + }), + ]; + }, [hasSelection, selectedFeaturesArr]); + const allLayers = useMemo(() => { if (!layerStates || layerStates.length === 0) { - return measureLayers as Layer[]; + return [...measureLayers, ...highlightLayer, ...lassoLayers] as Layer[]; } - const layers = layerStates + let layers = layerStates .map(ls => ls?.layer) .filter(Boolean) as Layer[]; - return [...layers, ...measureLayers] as Layer[]; - }, [layerStates, measureLayers]); + // Dim all data layers when there's an active lasso selection + if (hasSelection) { + layers = layers.map(l => l.clone({ opacity: 0.15 })); + } + + return [ + ...layers, + ...highlightLayer, + ...measureLayers, + ...lassoLayers, + ] as Layer[]; + }, [layerStates, measureLayers, lassoLayers, highlightLayer, hasSelection]); useEffect(() => { if (!props.layerStates) return; @@ -539,6 +627,7 @@ export const DeckGLContainer = memo( // Clear tooltip when mouse leaves the map container const handleMouseLeave = useCallback(() => { setTooltip(null); + setLassoMousePos(null); }, []); // Track drag state for measurement - use refs to avoid stale closure issues @@ -551,6 +640,8 @@ export const DeckGLContainer = memo( (info: any) => { // Don't handle click if a drag was in progress (threshold was exceeded) if (measureDragRef.current) return; + // Suppress normal clicks during lasso mode + if (lassoIsActive) return; if (measureState.isActive && onMeasureClick && info.coordinate) { onMeasureClick(info.coordinate as Coordinate); } @@ -559,13 +650,18 @@ export const DeckGLContainer = memo( onEmptyClick(); } }, - [measureState.isActive, onMeasureClick, onEmptyClick], + [measureState.isActive, lassoIsActive, onMeasureClick, onEmptyClick], ); - // Cursor style for measure mode - use custom ruler cursor + // Cursor style for measure/lasso modes const getCursor = useCallback( - () => (measureState.isActive ? RULER_CURSOR : 'grab'), - [measureState.isActive], + () => + lassoIsActive + ? LASSO_CURSOR + : measureState.isActive + ? RULER_CURSOR + : 'grab', + [measureState.isActive, lassoIsActive], ); // Handle mouse down for drag-to-measure @@ -573,7 +669,6 @@ export const DeckGLContainer = memo( (e: React.MouseEvent) => { if (!measureState.isActive) return; - // Store initial position - don't start drag yet const rect = e.currentTarget.getBoundingClientRect(); mouseDownPosRef.current = { x: e.clientX - rect.left, @@ -584,9 +679,18 @@ export const DeckGLContainer = memo( [measureState.isActive], ); - // Handle mouse move for drag-to-measure + // Handle mouse move for drag-to-measure and lasso hint tooltip const handleMouseMove = useCallback( (e: React.MouseEvent) => { + // Track cursor for lasso hint tooltip + if (lassoIsActive) { + const rect = e.currentTarget.getBoundingClientRect(); + setLassoMousePos({ + x: e.clientX - rect.left, + y: e.clientY - rect.top, + }); + } + if (!measureState.isActive || !mouseDownPosRef.current) return; const map = mapRef.current?.getMap(); @@ -596,14 +700,10 @@ export const DeckGLContainer = memo( const x = e.clientX - rect.left; const y = e.clientY - rect.top; - // Check if we've exceeded drag threshold if (!measureDragRef.current) { const dx = x - mouseDownPosRef.current.x; const dy = y - mouseDownPosRef.current.y; - const distance = Math.sqrt(dx * dx + dy * dy); - - if (distance >= DRAG_THRESHOLD) { - // Start drag from the initial mouse down position + if (Math.sqrt(dx * dx + dy * dy) >= DRAG_THRESHOLD) { measureDragRef.current = true; const startLngLat = map.unproject([ mouseDownPosRef.current.x, @@ -611,15 +711,14 @@ export const DeckGLContainer = memo( ]); props.onMeasureDragStart?.([startLngLat.lng, startLngLat.lat]); } else { - return; // Haven't moved enough yet + return; } } - // Continue drag const lngLat = map.unproject([x, y]); props.onMeasureDrag?.([lngLat.lng, lngLat.lat]); }, - [measureState.isActive, props.onMeasureDragStart, props.onMeasureDrag], + [measureState.isActive, lassoIsActive, props.onMeasureDragStart, props.onMeasureDrag], ); // Handle mouse up for drag-to-measure @@ -627,7 +726,6 @@ export const DeckGLContainer = memo( (e: React.MouseEvent) => { if (!measureState.isActive) return; - // Only finalize drag if we actually started dragging if (measureDragRef.current) { const map = mapRef.current?.getMap(); if (map) { @@ -639,15 +737,17 @@ export const DeckGLContainer = memo( } } - // Reset refs measureDragRef.current = false; mouseDownPosRef.current = null; }, [measureState.isActive, props.onMeasureDragEnd], ); - // Disable map panning when in measure mode - const controllerOptions = measureState.isActive + // Disable map panning when actively drawing (measure or lasso). + // Re-enable after lasso drawing completes so user can pan/zoom the selection. + const isActivelyDrawing = + measureState.isActive || (lassoIsActive && !lassoPolygon); + const controllerOptions = isActivelyDrawing ? { dragPan: false, dragRotate: false } : true; @@ -740,6 +840,13 @@ export const DeckGLContainer = memo( {distance} )} + {lassoIsActive && lassoMousePos && !selectedFeaturesArr.length && ( + + {LASSO_HINT_TEXT[lassoDrawMode]} + + )} {scaleInfo.label} diff --git a/superset-frontend/plugins/geoset-map-chart/src/GeoSetMultiMap/Multi.tsx b/superset-frontend/plugins/geoset-map-chart/src/GeoSetMultiMap/Multi.tsx index 21767a70b5..3222b55014 100644 --- a/superset-frontend/plugins/geoset-map-chart/src/GeoSetMultiMap/Multi.tsx +++ b/superset-frontend/plugins/geoset-map-chart/src/GeoSetMultiMap/Multi.tsx @@ -45,15 +45,22 @@ import { LayerState } from '../types'; import buildGeoSetMapLayerQuery from '../buildQuery'; import transformGeoSetMapLayerProps from '../transformProps'; import MultiLegend from '../components/MultiLegend'; -import type { CategoryEntry, LegendEntry } from '../types'; +import type { CategoryEntry, GeoJsonFeature, LegendEntry } from '../types'; import { useGroupedLegend } from '../utils/hooks'; import MapControls from '../components/MapControls'; +import { useLassoSelection } from '../hooks/useLassoSelection'; +import { + handleLassoPolygonComplete, + normalizeCategoryKey, + projectAnchorToScreen, +} from '../utils/lassoSelection'; +import LassoResultsBar from '../components/LassoResultsBar'; import { CategoryState, MetricLegend, RGBAColor } from '../utils/colors'; import { getGeometryType } from '../utils/dataProcessing'; import { fetchMapboxApiKey, getCachedMapboxApiKey } from '../utils/mapboxApi'; import { multiChartMigration } from '../utils/migrationApi'; import ClickPopupBox, { ClickedFeatureInfo } from '../components/ClickPopupBox'; -import { setLiveViewport } from '../utils/liveViewportStore'; +import { setLiveViewport, getLiveViewport } from '../utils/liveViewportStore'; import { DeckSliceConfig, resolveLayerAutozoom, @@ -132,10 +139,12 @@ type SubsliceLayerEntry = { visualConfig: any; hoverColumnNames: string[]; featureInfoColumnNames: string[]; + exportColumnNames: string[]; }; zoomSliderOptions: { minZoom: number; maxZoom: number }; initiallyHidden: boolean; // Whether this layer starts hidden lazyLoading: boolean; // Whether this layer is configured for lazy loading + lassoSelectable: boolean; // Whether this layer appears in the lasso dropdown }; interface ClickedFeatureWithColumns extends ClickedFeatureInfo { @@ -146,6 +155,8 @@ const DeckMulti = (props: DeckMultiProps) => { const containerRef = useRef(null); // Ref to track measure state for use in callbacks without creating dependencies const measureActiveRef = useRef(false); + const lassoIsActiveRef = useRef(false); + const lassoRequestIdRef = useRef(0); // Generation counter to cancel stale lazy-loading chains const loadGenerationRef = useRef(0); // Store initial autozoom viewport to prevent reset on category toggle @@ -168,7 +179,7 @@ const DeckMulti = (props: DeckMultiProps) => { // Don't show popup when measurement mode is active (uses ref to avoid dependency issues) const handleFeatureClick = useCallback( (info: any, featureInfoColumnNames?: string[]) => { - if (measureActiveRef.current) return; + if (measureActiveRef.current || lassoIsActiveRef.current) return; if (info?.object?.properties) { setClickedFeature({ properties: info.object.properties, @@ -183,6 +194,8 @@ const DeckMulti = (props: DeckMultiProps) => { setClickedFeature(null); }, []); const setTooltip = useCallback((tooltip: TooltipProps['tooltip']) => { + // Suppress hover tooltips while lasso mode is active + if (lassoIsActiveRef.current) return; const { current } = containerRef; if (current) { current.setTooltip(tooltip); @@ -496,10 +509,12 @@ const DeckMulti = (props: DeckMultiProps) => { hoverColumnNames: transformedProps.hoverColumnNames, featureInfoColumnNames: transformedProps.featureInfoColumnNames || [], + exportColumnNames: transformedProps.exportColumnNames || [], }, zoomSliderOptions: newLayerStateOptions, initiallyHidden: sliceInitiallyHidden, lazyLoading: sliceLazyLoading, + lassoSelectable: sliceConfig?.lassoSelectable ?? true, }; }); }) @@ -628,6 +643,7 @@ const DeckMulti = (props: DeckMultiProps) => { ...layer, autozoom: resolveLayerAutozoom(config), lazyLoading: config?.lazyLoading ?? false, + lassoSelectable: config?.lassoSelectable ?? true, }; }); }); @@ -879,6 +895,20 @@ const DeckMulti = (props: DeckMultiProps) => { [sortedLayers, layerVisibility], ); + // Layer list for lasso layer picker dropdown — only lasso-selectable layers + const lassoLayers = useMemo( + () => + sortedLayers + .filter(entry => entry.lassoSelectable !== false) + .map(entry => ({ + id: String(entry.sliceId), + name: + (entry.legendEntry.sliceName as string | undefined) || + entry.legendEntry.legendName, + })), + [sortedLayers], + ); + // Build legendsBySlice for MultiLegend component, with category enabled state applied. // Merges loaded entries with stub entries so the legend shows all layers immediately. const legendsBySlice: Record = useMemo(() => { @@ -998,6 +1028,92 @@ const DeckMulti = (props: DeckMultiProps) => { // Keep ref in sync with measure state for use in callbacks measureActiveRef.current = measureState.isActive; + const { + lassoIsActive, + lassoDrawMode, + setLassoDrawMode, + selectedLassoLayerId, + selectedFeatures, + setSelectedFeatures, + lassoPolygon, + anchorGeoCoord, + setAnchorGeoCoord, + clearSelection, + handleLassoToggle, + handleLassoActivate, + handleLassoComplete, + handleLassoLayerSelect, + deactivateLasso, + } = useLassoSelection({ + availableLayers: lassoLayers, + onPolygonComplete: async polygon => { + const entry = sortedLayers.find( + e => String(e.sliceId) === selectedLassoLayerId, + ); + if (!entry) return; + + const allFeatures = + (entry.transformedProps.payload?.data?.features as GeoJsonFeature[]) || + []; + + // Build hidden-category set from the slice's category visibility map. + // Keys in categoryVisibility are display labels (mixed case), so we + // normalise them to match the lowercased keys used by buildLassoResult. + const sliceVisibility = categoryVisibility[String(entry.sliceId)]; + const hiddenCategoryKeys = sliceVisibility + ? new Set( + Object.entries(sliceVisibility) + .filter(([, v]) => v === false) + .map(([k]) => normalizeCategoryKey(k)), + ) + : undefined; + + await handleLassoPolygonComplete( + polygon, + allFeatures, + { + dimension: entry.transformedProps.visualConfig?.dimension as + | string + | undefined, + hiddenCategoryKeys, + }, + lassoRequestIdRef, + { setSelectedFeatures, setAnchorGeoCoord }, + ); + }, + onActivate: () => { + setMeasureState({ + startPoint: null, + endPoint: null, + isActive: false, + isDragging: false, + }); + // Clear any visible tooltip when entering lasso mode + containerRef.current?.setTooltip(null); + }, + }); + + // Keep ref in sync with lasso state for use in memoized callbacks + lassoIsActiveRef.current = lassoIsActive; + + // Allowlist of query columns for lasso export (from the selected layer). + const exportColumns = useMemo(() => { + const entry = sortedLayers.find( + e => String(e.sliceId) === selectedLassoLayerId, + ); + return entry?.transformedProps?.exportColumnNames; + }, [sortedLayers, selectedLassoLayerId]); + + // Re-project anchor on every render so the results bar tracks pan/zoom. + // Use the live viewport (updated by DeckGLContainer on pan/zoom) instead of + // the initial/autozoom viewport, which goes stale after the user pans. + const anchorPosition = useMemo(() => { + if (!anchorGeoCoord) return null; + const liveVp = getLiveViewport(); + const vp = liveVp ?? viewport; + return projectAnchorToScreen(anchorGeoCoord, vp, width, height); + }, [anchorGeoCoord, viewport, width, height]); + const handleRulerToggle = useCallback(() => { setMeasureState(prev => { if (prev.isActive) { @@ -1008,6 +1124,7 @@ const DeckMulti = (props: DeckMultiProps) => { isDragging: false, }; } + deactivateLasso(); return { startPoint: null, endPoint: null, @@ -1015,7 +1132,7 @@ const DeckMulti = (props: DeckMultiProps) => { isDragging: false, }; }); - }, []); + }, [deactivateLasso]); const handleMeasureClick = useCallback((coordinate: [number, number]) => { setMeasureState(prev => { @@ -1057,7 +1174,7 @@ const DeckMulti = (props: DeckMultiProps) => { }); }, []); - // Handle escape key to exit ruler mode + // Handle escape key to exit ruler mode (lasso escape is handled by useLassoSelection) useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape' && measureState.isActive) { @@ -1124,6 +1241,11 @@ const DeckMulti = (props: DeckMultiProps) => { onMeasureDragStart={handleMeasureDragStart} onMeasureDrag={handleMeasureDrag} onMeasureDragEnd={handleMeasureDragEnd} + lassoIsActive={lassoIsActive} + lassoDrawMode={lassoDrawMode} + lassoPolygon={lassoPolygon} + onLassoComplete={handleLassoComplete} + selectedFeatures={selectedFeatures} onEmptyClick={handleClosePopup} /> { onResetView={handleResetView} onRulerToggle={handleRulerToggle} isRulerActive={measureState.isActive} + onLassoToggle={handleLassoToggle} + onLassoActivate={handleLassoActivate} + isLassoActive={lassoIsActive} + lassoLayers={lassoLayers} + activeLassoLayerId={selectedLassoLayerId} + onLassoLayerSelect={handleLassoLayerSelect} + lassoDrawMode={lassoDrawMode} + onLassoDrawModeChange={setLassoDrawMode} position="top-right" /> + {(selectedFeatures.length > 0 || (lassoPolygon && anchorPosition)) && ( + + )} {clickedFeature && ( void; + drawMode: LassoDrawMode; + onDrawModeChange?: (mode: LassoDrawMode) => void; + onClose: () => void; +}; + +const DropdownPanel = styled.div( + ({ theme }) => ` + position: absolute; + top: calc(100% + 6px); + right: 0; + min-width: 200px; + background: ${theme.colorBgElevated}; + border: 1px solid ${theme.colorBorderSecondary}; + border-radius: 6px; + box-shadow: 0 4px 12px ${theme.colorText}1F; + overflow: hidden; +`, +); + +const DropdownHeader = styled.div( + ({ theme }) => ` + display: flex; + align-items: center; + justify-content: space-between; + padding: 8px 12px 6px; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + color: ${theme.colorTextSecondary}; + border-bottom: 1px solid ${theme.colorBorderSecondary}; +`, +); + +const CloseButton = styled.button( + ({ theme }) => ` + display: flex; + align-items: center; + justify-content: center; + width: 18px; + height: 18px; + padding: 0; + background: transparent; + border: none; + cursor: pointer; + font-size: 14px; + line-height: 1; + color: ${theme.colorTextSecondary}; + + &:hover { + color: ${theme.colorText}; + } +`, +); + +const DropdownItem = styled.button( + ({ theme }) => ` + display: flex; + align-items: center; + gap: 8px; + width: 100%; + padding: 8px 12px; + background: transparent; + border: none; + cursor: pointer; + font-family: inherit; + font-size: 13px; + color: ${theme.colorText}; + text-align: left; + white-space: nowrap; + + &:hover { + background: ${theme.colorBgTextHover}; + } +`, +); + +const CLICK_AND_DRAG_MODES: LassoDrawMode[] = ['freehand', 'circle', 'rectangle']; +const isClickAndDragMode = (mode: LassoDrawMode) => + CLICK_AND_DRAG_MODES.includes(mode); + +const ModeToggleSection = styled.div( + ({ theme }) => ` + display: flex; + gap: 4px; + padding: 8px 12px; + border-top: 1px solid ${theme.colorBorderSecondary}; +`, +); + +const ModeButton = styled.button<{ $isActive?: boolean }>( + ({ theme, $isActive }) => ` + display: flex; + align-items: center; + gap: 4px; + flex: 1; + padding: 4px 8px; + background: ${$isActive ? theme.colorPrimaryBg : 'transparent'}; + border: none; + border-radius: 4px; + cursor: pointer; + font-family: inherit; + font-size: 11px; + color: ${$isActive ? theme.colorPrimary : theme.colorTextSecondary}; + white-space: nowrap; + + &:hover { + background: ${$isActive ? theme.colorPrimaryBgHover : theme.colorBgTextHover}; + } +`, +); + +const ShapeToggleSection = styled.div` + display: flex; + gap: 4px; + padding: 4px 12px 8px; +`; + +const LassoDropdown = ({ + hasMultipleLayers, + layers, + activeLassoLayerId, + onLayerSelect, + drawMode, + onDrawModeChange, + onClose, +}: LassoDropdownProps) => { + const isDragMode = isClickAndDragMode(drawMode); + + return ( + + + {hasMultipleLayers ? 'Select layer' : 'Lasso mode'} + + + + + {hasMultipleLayers && ( +

+ {layers.map(layer => { + const isSelected = layer.id === activeLassoLayerId; + return ( + onLayerSelect?.(layer.id)} + > + + {layer.name} + + ); + })} +
+ )} + + onDrawModeChange?.('freehand')} + > + Click-and-drag + + onDrawModeChange?.('polygon')} + > + Point-to-point + + + {isDragMode && ( + + onDrawModeChange?.('freehand')} + > + Freehand + + onDrawModeChange?.('circle')} + > + Circle + + onDrawModeChange?.('rectangle')} + > + Rectangle + + + )} + + ); +}; + +export default memo(LassoDropdown); diff --git a/superset-frontend/plugins/geoset-map-chart/src/components/LassoResultsBar.tsx b/superset-frontend/plugins/geoset-map-chart/src/components/LassoResultsBar.tsx new file mode 100644 index 0000000000..b243439cd3 --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/src/components/LassoResultsBar.tsx @@ -0,0 +1,294 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { + memo, + useCallback, + useLayoutEffect, + useMemo, + useState, + useRef, +} from 'react'; +import { styled, t } from '@superset-ui/core'; +import { message } from 'antd'; +import type { GeoJsonFeature } from '../types'; +import type { Coordinate } from '../utils/measureDistance'; +import { exportToCSV, exportToExcel } from '../utils/lassoExport'; +import { calculateLassoArea } from '../utils/lassoSelection'; +import { KebabIcon, CloseIcon, DownloadIcon } from './icons'; +import { useClickOutside } from '../hooks/useClickOutside'; + +export interface LassoResultsBarProps { + features: GeoJsonFeature[]; + lassoPolygon?: Coordinate[] | null; + onClear: () => void; + anchorPosition?: { x: number; y: number } | null; + containerWidth?: number; + containerHeight?: number; + exportColumns?: string[]; +} + +const CONTROL_MARGIN = 12; +const TOP_OFFSET = 32 + CONTROL_MARGIN + 8; + +const BarContainer = styled.div<{ $anchorX?: number; $anchorY?: number }>` + position: absolute; + ${({ $anchorX, $anchorY }) => + $anchorX != null && $anchorY != null + ? `left: ${$anchorX}px; top: ${$anchorY}px;` + : `left: ${CONTROL_MARGIN}px; top: ${TOP_OFFSET}px;`} + z-index: 20; + pointer-events: auto; +`; + +const BarContent = styled.div( + ({ theme }) => ` + display: flex; + flex-direction: column; + padding: 10px 8px 10px 16px; + background: ${theme.colorBgElevated}; + border: 1px solid ${theme.colorBorderSecondary}; + border-radius: 6px; + box-shadow: 0 2px 8px ${theme.colorText}1F; + white-space: nowrap; +`, +); + +const TopRow = styled.div` + display: flex; + align-items: center; + gap: 4px; +`; + +const CountLabel = styled.span( + ({ theme }) => ` + font-size: 15px; + font-weight: 700; + color: ${theme.colorText}; + margin-right: 4px; +`, +); + +const AreaLabel = styled.span( + ({ theme }) => ` + font-size: 12px; + font-weight: 400; + color: ${theme.colorTextSecondary}; + padding-top: 2px; +`, +); + +const IconButton = styled.button( + ({ theme }) => ` + display: flex; + align-items: center; + justify-content: center; + width: 28px; + height: 28px; + padding: 0; + background: transparent; + border: none; + border-radius: 4px; + cursor: pointer; + color: ${theme.colorTextSecondary}; + + &:hover { + background: ${theme.colorBgTextHover}; + color: ${theme.colorText}; + } +`, +); + +const MenuPanel = styled.div<{ $flipLeft?: boolean }>( + ({ theme, $flipLeft }) => ` + position: absolute; + top: 0; + ${$flipLeft ? 'right: calc(100% + 6px);' : 'left: calc(100% + 6px);'} + min-width: 170px; + background: ${theme.colorBgElevated}; + border: 1px solid ${theme.colorBorderSecondary}; + border-radius: 6px; + box-shadow: 0 4px 12px ${theme.colorText}1F; + overflow: hidden; +`, +); + +const MenuHeader = styled.div( + ({ theme }) => ` + padding: 8px 12px 6px; + font-size: 11px; + font-weight: 600; + color: ${theme.colorTextSecondary}; + border-bottom: 1px solid ${theme.colorBorderSecondary}; +`, +); + +const MenuItem = styled.button<{ $disabled?: boolean }>( + ({ theme, $disabled }) => ` + display: flex; + align-items: center; + gap: 8px; + width: 100%; + padding: 8px 12px; + background: transparent; + border: none; + cursor: ${$disabled ? 'default' : 'pointer'}; + font-family: inherit; + font-size: 13px; + color: ${$disabled ? theme.colorTextSecondary : theme.colorText}; + opacity: ${$disabled ? 0.5 : 1}; + text-align: left; + white-space: nowrap; + + &:hover { + background: ${$disabled ? 'transparent' : theme.colorBgTextHover}; + } +`, +); + +const LassoResultsBar = ({ + features, + lassoPolygon, + onClear, + anchorPosition, + containerWidth, + containerHeight, + exportColumns, +}: LassoResultsBarProps) => { + const count = features.length; + const areaText = useMemo( + () => (lassoPolygon ? calculateLassoArea(lassoPolygon) : null), + [lassoPolygon], + ); + const [isMenuOpen, setIsMenuOpen] = useState(false); + const [menuFlipLeft, setMenuFlipLeft] = useState(false); + const containerRef = useRef(null); + const [clampedPos, setClampedPos] = useState(anchorPosition); + + // Measure the bar after render and clamp so it stays within the map + useLayoutEffect(() => { + if (!anchorPosition || !containerRef.current) { + setClampedPos(anchorPosition); + return; + } + const el = containerRef.current; + const barW = el.offsetWidth; + const barH = el.offsetHeight; + const maxW = containerWidth ?? Infinity; + const maxH = containerHeight ?? Infinity; + const pad = 8; + const x = Math.max(pad, Math.min(anchorPosition.x, maxW - barW - pad)); + const y = Math.max(pad, Math.min(anchorPosition.y, maxH - barH - pad)); + setClampedPos({ x, y }); + }, [anchorPosition, containerWidth, containerHeight, count]); + + // Determine if menu should flip to the left when it would overflow the container + useLayoutEffect(() => { + if (!isMenuOpen || !containerRef.current || !containerWidth) return; + const el = containerRef.current; + const barRight = (clampedPos?.x ?? 0) + el.offsetWidth; + const MENU_WIDTH = 176; // min-width (170) + gap (6) + setMenuFlipLeft(barRight + MENU_WIDTH > containerWidth); + }, [isMenuOpen, clampedPos, containerWidth]); + + const closeMenu = useCallback(() => setIsMenuOpen(false), []); + useClickOutside(containerRef, closeMenu, isMenuOpen); + + if (count === 0 && !lassoPolygon) return null; + + return ( + + + + {count} Items Selected + {count > 0 && ( + setIsMenuOpen(prev => !prev)} + aria-label="Export options" + aria-expanded={isMenuOpen} + aria-haspopup="menu" + > + + + )} + + + + + {areaText && Area: {areaText}} + + + {isMenuOpen && ( + + Download + { + try { + exportToCSV(features, exportColumns); + message.success({ + content: t('CSV exported successfully'), + duration: 3, + }); + } catch (err) { + message.error({ + content: t('Failed to export CSV'), + duration: 5, + }); + } + setIsMenuOpen(false); + }} + > + Export to .CSV + + { + exportToExcel(features, exportColumns) + .then(() => + message.success({ + content: t('Excel exported successfully'), + duration: 3, + }), + ) + .catch(() => + message.error({ + content: t('Failed to export Excel'), + duration: 5, + }), + ); + setIsMenuOpen(false); + }} + > + Export to Excel + + + )} + + ); +}; + +export default memo(LassoResultsBar); diff --git a/superset-frontend/plugins/geoset-map-chart/src/components/MapControls.tsx b/superset-frontend/plugins/geoset-map-chart/src/components/MapControls.tsx index df540c2886..da7c9dc478 100644 --- a/superset-frontend/plugins/geoset-map-chart/src/components/MapControls.tsx +++ b/superset-frontend/plugins/geoset-map-chart/src/components/MapControls.tsx @@ -16,15 +16,28 @@ * specific language governing permissions and limitations * under the License. */ -import { memo } from 'react'; +import { memo, useCallback, useState, useRef } from 'react'; import { styled } from '@superset-ui/core'; +import type { LassoDrawMode, LassoLayer } from '../types'; +import LassoDropdown from './LassoDropdown'; +import { HomeIcon, RulerIcon, LassoIcon } from './icons'; +import { useClickOutside } from '../hooks/useClickOutside'; + export type MapControlsProps = { onZoomIn: () => void; onZoomOut: () => void; onResetView: () => void; onRulerToggle: () => void; isRulerActive: boolean; + onLassoToggle: () => void; + onLassoActivate?: () => void; + isLassoActive: boolean; + lassoLayers?: LassoLayer[]; + activeLassoLayerId?: string; + onLassoLayerSelect?: (layerId: string) => void; + lassoDrawMode?: LassoDrawMode; + onLassoDrawModeChange?: (mode: LassoDrawMode) => void; position?: 'top-left' | 'top-right'; }; @@ -85,69 +98,87 @@ const ControlButton = styled.button<{ $isActive?: boolean }>( `, ); -const HomeIcon = () => ( - - - - -); - -const RulerIcon = () => ( - - - - - - - -); - const MapControls = ({ onZoomIn, onZoomOut, onResetView, onRulerToggle, isRulerActive, + onLassoToggle, + onLassoActivate, + isLassoActive, + lassoLayers = [], + activeLassoLayerId, + onLassoLayerSelect, + lassoDrawMode = 'freehand', + onLassoDrawModeChange, position = 'top-left', -}: MapControlsProps) => ( - - - - - - - − - - - + - - - - - - -); +}: MapControlsProps) => { + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const containerRef = useRef(null); + const hasMultipleLayers = lassoLayers.length > 1; + + const closeAndActivate = useCallback(() => { + setIsDropdownOpen(false); + if (!hasMultipleLayers || activeLassoLayerId) { + onLassoActivate?.(); + } + }, [hasMultipleLayers, activeLassoLayerId, onLassoActivate]); + + useClickOutside(containerRef, closeAndActivate, isDropdownOpen); + + const handleLassoButtonClick = () => { + if (isLassoActive) { + onLassoToggle(); + setIsDropdownOpen(false); + } else { + setIsDropdownOpen(prev => !prev); + } + }; + + return ( + + + + + + + − + + + + + + + + + + + + + + {isDropdownOpen && ( + + )} + + ); +}; export default memo(MapControls); diff --git a/superset-frontend/plugins/geoset-map-chart/src/components/icons.tsx b/superset-frontend/plugins/geoset-map-chart/src/components/icons.tsx new file mode 100644 index 0000000000..3d5092b0cb --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/src/components/icons.tsx @@ -0,0 +1,184 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* ── Map Controls ────────────────────────────────────────── */ + +export const HomeIcon = () => ( + + + + +); + +export const RulerIcon = () => ( + + + + + + + +); + +export const LassoIcon = () => ( + + + + +); + +/* ── Lasso Results Bar ───────────────────────────────────── */ + +export const KebabIcon = () => ( + + + + + +); + +export const CloseIcon = () => ( + + + + +); + +export const DownloadIcon = () => ( + + + +); + +/* ── Lasso Dropdown ──────────────────────────────────────── */ + +export const FreehandIcon = () => ( + + + +); + +export const PolygonIcon = () => ( + + + + + + + +); + +export const CircleIcon = () => ( + + + +); + +export const RectangleIcon = () => ( + + + +); + +export const RadioIcon = ({ selected }: { selected: boolean }) => ( + + + {selected && } + +); diff --git a/superset-frontend/plugins/geoset-map-chart/src/components/useLassoLayer.ts b/superset-frontend/plugins/geoset-map-chart/src/components/useLassoLayer.ts new file mode 100644 index 0000000000..c2d924c98d --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/src/components/useLassoLayer.ts @@ -0,0 +1,227 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { + EditableGeoJsonLayer, + DrawPolygonByDraggingMode, + DrawPolygonMode, + DrawCircleFromCenterMode, + DrawRectangleMode, + ViewMode, +} from '@deck.gl-community/editable-layers'; +import { PathLayer, SolidPolygonLayer } from '@deck.gl/layers'; +import { PathStyleExtension } from '@deck.gl/extensions'; +import type { Coordinate } from '../utils/measureDistance'; +import type { LassoDrawMode } from '../types'; +import { closeRing } from '../utils/lassoSelection'; + +type EditModeConstructor = + | typeof DrawPolygonByDraggingMode + | typeof DrawPolygonMode + | typeof DrawCircleFromCenterMode + | typeof DrawRectangleMode + | typeof ViewMode; + +const EMPTY_FEATURE_COLLECTION = { + type: 'FeatureCollection' as const, + features: [] as any[], +}; + +// Custom crosshair cursor for lasso drawing mode +export const LASSO_CURSOR = `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Ccircle cx='16' cy='16' r='5' fill='none' stroke='%23000' stroke-width='1.5'/%3E%3Cline x1='16' y1='8' x2='16' y2='13' stroke='%23000' stroke-width='1.5'/%3E%3Cline x1='16' y1='19' x2='16' y2='24' stroke='%23000' stroke-width='1.5'/%3E%3Cline x1='8' y1='16' x2='13' y2='16' stroke='%23000' stroke-width='1.5'/%3E%3Cline x1='19' y1='16' x2='24' y2='16' stroke='%23000' stroke-width='1.5'/%3E%3C/svg%3E") 16 16, crosshair`; + +const DRAW_MODES: Record = { + freehand: DrawPolygonByDraggingMode, + polygon: DrawPolygonMode, + circle: DrawCircleFromCenterMode, + rectangle: DrawRectangleMode, +}; + +const DRAG_TO_DRAW_MODES: Set = new Set(['circle', 'rectangle']); + +// Shared color constants for lasso fill/stroke across drawing and completed layers +const LASSO_FILL_COLOR: [number, number, number, number] = [66, 133, 244, 30]; +const LASSO_TENTATIVE_FILL_COLOR: [number, number, number, number] = [ + 66, 133, 244, 15, +]; +const LASSO_LINE_COLOR: [number, number, number, number] = [40, 40, 40, 220]; +const LASSO_TENTATIVE_LINE_COLOR: [number, number, number, number] = [ + 40, 40, 40, 200, +]; + +// Delay before enabling draw mode after activation, so the dropdown-close click +// doesn't register as the first vertex +const ACTIVATION_DELAY_MS = 450; + +const DASH_EXTENSION = new PathStyleExtension({ dash: true }); +const DASH_PROPS = { + getDashArray: [8, 4], + dashJustified: true, + extensions: [DASH_EXTENSION], +}; + +/** + * Hook to create layers for lasso drawing and completed polygon display. + * + * - While drawing: EditableGeoJsonLayer handles mouse interaction + * - After completion: separate SolidPolygonLayer (fill) + PathLayer (dashed outline) + * keep the polygon visible regardless of what the editable layer does + */ +export function useLassoLayer( + isActive: boolean, + onPolygonComplete: (polygon: Coordinate[]) => void, + drawMode: LassoDrawMode = 'freehand', + completedPolygon: Coordinate[] | null = null, +): { layers: any[] } { + const [data, setData] = useState(EMPTY_FEATURE_COLLECTION); + const [mode, setMode] = useState( + () => DRAW_MODES[drawMode], + ); + + // Use refs so effects/callbacks always see the latest values without + // needing them in dependency arrays (avoids stale closures and races) + const onPolygonCompleteRef = useRef(onPolygonComplete); + onPolygonCompleteRef.current = onPolygonComplete; + const drawModeRef = useRef(drawMode); + drawModeRef.current = drawMode; + + // Reset when lasso is activated — brief delay before enabling draw mode + // so the click that closed the dropdown doesn't register as the first vertex. + // Uses drawModeRef so a mode change during the delay window is respected. + useEffect(() => { + if (isActive) { + setData(EMPTY_FEATURE_COLLECTION); + setMode(() => ViewMode); + const timer = setTimeout(() => { + setMode(() => DRAW_MODES[drawModeRef.current]); + }, ACTIVATION_DELAY_MS); + return () => clearTimeout(timer); + } + return undefined; + }, [isActive]); // eslint-disable-line react-hooks/exhaustive-deps + + // Reset drawing state when completed polygon is cleared (user dismissed results) + // so the editable layer returns to draw mode for a new lasso + useEffect(() => { + if (isActive && !completedPolygon) { + setData(EMPTY_FEATURE_COLLECTION); + setMode(() => DRAW_MODES[drawModeRef.current]); + } + }, [completedPolygon]); // eslint-disable-line react-hooks/exhaustive-deps + + // Switch draw mode while active (without resetting polygon data) + useEffect(() => { + if (isActive) { + setMode(() => DRAW_MODES[drawMode]); + } + }, [drawMode, isActive]); + + const handleEdit = useCallback( + ({ updatedData, editType }: { updatedData: any; editType: string }) => { + setData(updatedData); + if (editType === 'addFeature') { + const lastFeature = + updatedData.features[updatedData.features.length - 1]; + const coords: number[][] = lastFeature.geometry.coordinates[0]; + setMode(() => ViewMode); + onPolygonCompleteRef.current( + coords.map(c => [c[0], c[1]] as Coordinate), + ); + } + }, + [], + ); + + // Editable layer for drawing phase + const editableLayer = useMemo(() => { + if (!isActive) return []; + + return [ + new EditableGeoJsonLayer({ + id: 'lasso-editable-layer', + data, + mode, + modeConfig: DRAG_TO_DRAW_MODES.has(drawMode) + ? { dragToDraw: true } + : undefined, + selectedFeatureIndexes: [], + onEdit: handleEdit, + + getFillColor: LASSO_FILL_COLOR, + getLineColor: LASSO_LINE_COLOR, + lineWidthMinPixels: 2, + + getTentativeFillColor: LASSO_TENTATIVE_FILL_COLOR, + getTentativeLineColor: LASSO_TENTATIVE_LINE_COLOR, + + // Dashed outline on both the main geojson and guides (tentative) sub-layers + _subLayerProps: { + geojson: { + _subLayerProps: { + linestrings: DASH_PROPS, + 'polygons-stroke': DASH_PROPS, + }, + }, + guides: { + _subLayerProps: { + linestrings: DASH_PROPS, + 'polygons-stroke': DASH_PROPS, + }, + }, + tooltips: { visible: false }, + }, + + pickable: true, + }), + ]; + }, [isActive, data, mode, drawMode, handleEdit]); + + // Static layers for the completed polygon — persists after drawing finishes + const completedLayers = useMemo(() => { + if (!completedPolygon || completedPolygon.length < 3) return []; + + const ring = closeRing(completedPolygon); + + return [ + new SolidPolygonLayer({ + id: 'lasso-completed-fill', + data: [{ polygon: ring }], + getPolygon: (d: any) => d.polygon, + getFillColor: LASSO_FILL_COLOR, + pickable: false, + }), + new PathLayer({ + id: 'lasso-completed-outline', + data: [{ path: ring }], + getPath: (d: any) => d.path, + getColor: LASSO_LINE_COLOR, + widthMinPixels: 2, + ...DASH_PROPS, + pickable: false, + }), + ]; + }, [completedPolygon]); + + const layers = useMemo( + () => [...editableLayer, ...completedLayers], + [editableLayer, completedLayers], + ); + + return { layers }; +} diff --git a/superset-frontend/plugins/geoset-map-chart/src/declarations.d.ts b/superset-frontend/plugins/geoset-map-chart/src/declarations.d.ts index 2b57d8cf1e..432437514a 100644 --- a/superset-frontend/plugins/geoset-map-chart/src/declarations.d.ts +++ b/superset-frontend/plugins/geoset-map-chart/src/declarations.d.ts @@ -4,3 +4,15 @@ declare module '*.svg' { const content: string; export default content; } + +// Turf packages — types are available at runtime but not resolved by the plugin tsconfig +declare module '@turf/area'; +declare module '@turf/boolean-intersects'; +declare module '@turf/boolean-point-in-polygon'; +declare module '@turf/centroid'; +declare module '@turf/helpers'; +declare module '@turf/intersect'; +declare module '@turf/unkink-polygon'; + +// deck.gl community editable layers +declare module '@deck.gl-community/editable-layers'; diff --git a/superset-frontend/plugins/geoset-map-chart/src/hooks/useClickOutside.ts b/superset-frontend/plugins/geoset-map-chart/src/hooks/useClickOutside.ts new file mode 100644 index 0000000000..02a41b1840 --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/src/hooks/useClickOutside.ts @@ -0,0 +1,48 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { useEffect, useRef as useReactRef, type RefObject } from 'react'; + +/** + * Calls `onClickOutside` when a mousedown event occurs outside the given ref element. + * The listener is only attached when `isActive` is true. + * + * The callback is stored in a ref internally, so callers do not need to + * stabilise it with `useCallback` — an unstable reference will not cause + * the listener to be re-attached on every render. + */ +export function useClickOutside( + ref: RefObject, + onClickOutside: () => void, + isActive: boolean, +): void { + const callbackRef = useReactRef(onClickOutside); + callbackRef.current = onClickOutside; + + useEffect(() => { + if (!isActive) return undefined; + + const handler = (e: MouseEvent) => { + if (ref.current && !ref.current.contains(e.target as Node)) { + callbackRef.current(); + } + }; + document.addEventListener('mousedown', handler); + return () => document.removeEventListener('mousedown', handler); + }, [isActive, ref]); // callbackRef is a stable useRef — no need to list it +} diff --git a/superset-frontend/plugins/geoset-map-chart/src/hooks/useLassoActivation.ts b/superset-frontend/plugins/geoset-map-chart/src/hooks/useLassoActivation.ts new file mode 100644 index 0000000000..adfe601340 --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/src/hooks/useLassoActivation.ts @@ -0,0 +1,123 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { useCallback, useEffect, useRef, useState } from 'react'; +import type { LassoDrawMode, LassoLayer } from '../types'; + +const DRAW_MODE_STORAGE_KEY = 'geoset-lasso-draw-mode'; +const VALID_DRAW_MODES: readonly LassoDrawMode[] = ['freehand', 'polygon', 'circle', 'rectangle']; + +function getPersistedDrawMode(): LassoDrawMode { + try { + const stored = sessionStorage.getItem(DRAW_MODE_STORAGE_KEY); + if (stored && (VALID_DRAW_MODES as readonly string[]).includes(stored)) { + return stored as LassoDrawMode; + } + } catch { + // sessionStorage may be unavailable (SSR, security restrictions) + } + return 'freehand'; +} + +export type UseLassoActivationOptions = { + availableLayers?: LassoLayer[]; + onActivate?: () => void; +}; + +export type UseLassoActivationResult = { + lassoIsActive: boolean; + lassoDrawMode: LassoDrawMode; + setLassoDrawMode: (mode: LassoDrawMode) => void; + selectedLassoLayerId: string | undefined; + handleLassoActivate: () => void; + handleLassoLayerSelect: (layerId: string) => void; + deactivateLasso: () => void; + /** Full reset: deactivate + clear layer selection. Call `onFullReset` too. */ + resetActivation: () => void; +}; + +export function useLassoActivation( + options: UseLassoActivationOptions = {}, +): UseLassoActivationResult { + const { availableLayers = [] } = options; + + const onActivateRef = useRef(options.onActivate); + onActivateRef.current = options.onActivate; + + const [lassoIsActive, setLassoIsActive] = useState(false); + const [lassoDrawMode, setLassoDrawModeState] = useState(getPersistedDrawMode); + + const setLassoDrawMode = useCallback((mode: LassoDrawMode) => { + setLassoDrawModeState(mode); + try { + sessionStorage.setItem(DRAW_MODE_STORAGE_KEY, mode); + } catch { + // sessionStorage may be unavailable + } + }, []); + const [selectedLassoLayerId, setSelectedLassoLayerId] = useState< + string | undefined + >(); + + // Counter bumped on reset so the auto-select effect re-fires even when + // availableLayerIds hasn't changed. + const [resetCount, setResetCount] = useState(0); + + // Auto-select the first available layer when none is selected. + const availableLayerIds = availableLayers.map(l => l.id).join(','); + useEffect(() => { + if (availableLayers.length > 0 && !selectedLassoLayerId) { + setSelectedLassoLayerId(availableLayers[0].id); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + // Deps use `availableLayerIds` (a derived string) instead of the `availableLayers` + // array to avoid re-running when the array reference changes but contents don't. + // `selectedLassoLayerId` is read inside but intentionally excluded — including it + // would prevent re-selection after a reset clears it. + }, [availableLayerIds, resetCount]); + + const resetActivation = useCallback(() => { + setLassoIsActive(false); + setSelectedLassoLayerId(undefined); + setResetCount(c => c + 1); + }, []); + + const deactivateLasso = useCallback(() => { + setLassoIsActive(false); + }, []); + + const handleLassoActivate = useCallback(() => { + onActivateRef.current?.(); + setLassoIsActive(true); + }, []); + + const handleLassoLayerSelect = useCallback((layerId: string) => { + setSelectedLassoLayerId(layerId); + }, []); + + return { + lassoIsActive, + lassoDrawMode, + setLassoDrawMode, + selectedLassoLayerId, + handleLassoActivate, + handleLassoLayerSelect, + deactivateLasso, + resetActivation, + }; +} diff --git a/superset-frontend/plugins/geoset-map-chart/src/hooks/useLassoResults.ts b/superset-frontend/plugins/geoset-map-chart/src/hooks/useLassoResults.ts new file mode 100644 index 0000000000..d104e42750 --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/src/hooks/useLassoResults.ts @@ -0,0 +1,71 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { useCallback, useRef, useState } from 'react'; +import type { Coordinate } from '../utils/measureDistance'; +import type { GeoJsonFeature } from '../types'; + +export type UseLassoResultsOptions = { + onPolygonComplete?: (polygon: Coordinate[]) => void; +}; + +export type UseLassoResultsResult = { + selectedFeatures: GeoJsonFeature[]; + setSelectedFeatures: (features: GeoJsonFeature[]) => void; + lassoPolygon: Coordinate[] | null; + anchorGeoCoord: Coordinate | null; + setAnchorGeoCoord: (coord: Coordinate | null) => void; + clearSelection: () => void; + handleLassoComplete: (polygon: Coordinate[]) => void; +}; + +export function useLassoResults( + options: UseLassoResultsOptions = {}, +): UseLassoResultsResult { + const onPolygonCompleteRef = useRef(options.onPolygonComplete); + onPolygonCompleteRef.current = options.onPolygonComplete; + + const [selectedFeatures, setSelectedFeatures] = useState( + [], + ); + const [lassoPolygon, setLassoPolygon] = useState(null); + const [anchorGeoCoord, setAnchorGeoCoord] = useState( + null, + ); + + const clearSelection = useCallback(() => { + setSelectedFeatures([]); + setLassoPolygon(null); + setAnchorGeoCoord(null); + }, []); + + const handleLassoComplete = useCallback((polygon: Coordinate[]) => { + setLassoPolygon(polygon); + onPolygonCompleteRef.current?.(polygon); + }, []); + + return { + selectedFeatures, + setSelectedFeatures, + lassoPolygon, + anchorGeoCoord, + setAnchorGeoCoord, + clearSelection, + handleLassoComplete, + }; +} diff --git a/superset-frontend/plugins/geoset-map-chart/src/hooks/useLassoSelection.ts b/superset-frontend/plugins/geoset-map-chart/src/hooks/useLassoSelection.ts new file mode 100644 index 0000000000..a069faa123 --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/src/hooks/useLassoSelection.ts @@ -0,0 +1,113 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { useCallback, useEffect } from 'react'; +import type { Coordinate } from '../utils/measureDistance'; +import type { GeoJsonFeature, LassoDrawMode, LassoLayer } from '../types'; +import { useLassoActivation } from './useLassoActivation'; +import { useLassoResults } from './useLassoResults'; + +export type UseLassoSelectionOptions = { + /** Available layers for lasso selection. Omit or pass empty for single-layer. */ + availableLayers?: LassoLayer[]; + /** Called when lasso polygon drawing completes. */ + onPolygonComplete?: (polygon: Coordinate[]) => void; + /** Called when lasso is activated (useful for deactivating other modes like ruler). */ + onActivate?: () => void; +}; + +export type UseLassoSelectionResult = { + lassoIsActive: boolean; + lassoDrawMode: LassoDrawMode; + setLassoDrawMode: (mode: LassoDrawMode) => void; + selectedLassoLayerId: string | undefined; + selectedFeatures: GeoJsonFeature[]; + setSelectedFeatures: (features: GeoJsonFeature[]) => void; + lassoPolygon: Coordinate[] | null; + anchorGeoCoord: Coordinate | null; + setAnchorGeoCoord: (coord: Coordinate | null) => void; + clearSelection: () => void; + handleLassoToggle: () => void; + handleLassoActivate: () => void; + handleLassoComplete: (polygon: Coordinate[]) => void; + handleLassoLayerSelect: (layerId: string) => void; + deactivateLasso: () => void; +}; + +/** + * Composes `useLassoActivation` and `useLassoResults` into a single hook + * managing the full lasso lifecycle: activation, drawing, selection, and reset. + */ +export function useLassoSelection( + options: UseLassoSelectionOptions = {}, +): UseLassoSelectionResult { + const activation = useLassoActivation({ + availableLayers: options.availableLayers, + onActivate: options.onActivate, + }); + + const results = useLassoResults({ + onPolygonComplete: options.onPolygonComplete, + }); + + // Full reset: deactivate lasso and clear any selection results + const fullReset = useCallback(() => { + activation.resetActivation(); + results.clearSelection(); + }, [activation.resetActivation, results.clearSelection]); + + // Toggle lasso off — deactivate and clear results, but keep layer selection + const handleLassoToggle = useCallback(() => { + activation.deactivateLasso(); + results.clearSelection(); + }, [activation.deactivateLasso, results.clearSelection]); + + // Escape key exits lasso mode + useEffect(() => { + if (!activation.lassoIsActive) return undefined; + + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Escape') fullReset(); + }; + document.addEventListener('keydown', handleKeyDown); + return () => document.removeEventListener('keydown', handleKeyDown); + }, [activation.lassoIsActive, fullReset]); + + return { + // Activation state + lassoIsActive: activation.lassoIsActive, + lassoDrawMode: activation.lassoDrawMode, + setLassoDrawMode: activation.setLassoDrawMode, + selectedLassoLayerId: activation.selectedLassoLayerId, + handleLassoActivate: activation.handleLassoActivate, + handleLassoLayerSelect: activation.handleLassoLayerSelect, + deactivateLasso: activation.deactivateLasso, + + // Results state + selectedFeatures: results.selectedFeatures, + setSelectedFeatures: results.setSelectedFeatures, + lassoPolygon: results.lassoPolygon, + anchorGeoCoord: results.anchorGeoCoord, + setAnchorGeoCoord: results.setAnchorGeoCoord, + clearSelection: results.clearSelection, + handleLassoComplete: results.handleLassoComplete, + + // Combined + handleLassoToggle, + }; +} diff --git a/superset-frontend/plugins/geoset-map-chart/src/layers/GeoSetLayer/GeoSetLayer.tsx b/superset-frontend/plugins/geoset-map-chart/src/layers/GeoSetLayer/GeoSetLayer.tsx index 9753e7fd15..6de39f5cf8 100644 --- a/superset-frontend/plugins/geoset-map-chart/src/layers/GeoSetLayer/GeoSetLayer.tsx +++ b/superset-frontend/plugins/geoset-map-chart/src/layers/GeoSetLayer/GeoSetLayer.tsx @@ -39,6 +39,7 @@ import { } from '@superset-ui/core'; import { Alert } from 'antd'; import Layer from '@deck.gl/core/dist/lib/layer'; +import { useLassoSelection } from '../../hooks/useLassoSelection'; import { DeckGLContainerHandle, DeckGLContainerStyledWrapper, @@ -56,6 +57,11 @@ import { calculateAutozoomViewport, Viewport } from '../../utils/fitViewport'; import { TooltipProps } from '../../components/Tooltip'; import Legend, { SizeLegend } from '../../components/Legend'; import MapControls from '../../components/MapControls'; +import LassoResultsBar from '../../components/LassoResultsBar'; +import { + handleLassoPolygonComplete, + projectAnchorToScreen, +} from '../../utils/lassoSelection'; import { GeoJsonFeature, LayerState } from '../../types'; import { useDebouncedValue } from '../../utils/hooks'; import { normalizeRGBA } from '../../utils/colorsFallback'; @@ -78,7 +84,10 @@ import { import { handleSchemaCheck } from '../../utils/migrationApi'; import MeasureOverlay, { MeasureState } from '../../components/MeasureOverlay'; import { Coordinate } from '../../utils/measureDistance'; -import { setLiveViewport } from '../../utils/liveViewportStore'; +import { + setLiveViewport, + getLiveViewport, +} from '../../utils/liveViewportStore'; import ClickPopupBox, { ClickedFeatureInfo, } from '../../components/ClickPopupBox'; @@ -175,7 +184,7 @@ const recurseGeoJson = ( }; // save dimension/category so we don't lose it in metric mode if (propOverrides.dimensionColumn) { - (enrichedFeature as any).categoryName = + enrichedFeature.categoryName = alteredProps[propOverrides.dimensionColumn]; } @@ -340,8 +349,7 @@ export function getLayer( } else { // Helper to normalize category keys for lookup const getCategoryKey = (f: GeoJsonFeature): string | null => { - const categoryRaw = - (f as any).categoryName ?? f.properties?.[dimension as string]; + const categoryRaw = f.categoryName ?? f.properties?.[dimension as string]; if (categoryRaw == null) return null; return typeof categoryRaw === 'string' ? categoryRaw.trim().toLowerCase() @@ -705,6 +713,7 @@ export type DeckGLGeoJsonProps = { mapStyle: string; hoverColumnNames?: string[]; featureInfoColumnNames?: string[]; + exportColumnNames?: string[]; limitReached?: boolean; visualConfig?: { dimension?: string; @@ -738,11 +747,16 @@ const DeckGLGeoJson = (props: DeckGLGeoJsonProps) => { visualConfig: propVisualConfig, hoverColumnNames, featureInfoColumnNames, + exportColumnNames, limitReached, } = props; const containerRef = useRef(); + const lassoRequestIdRef = useRef(0); + const lassoIsActiveRef = useRef(false); const setTooltip = useCallback((tooltip: TooltipProps['tooltip']) => { + // Suppress hover tooltips while lasso mode is active + if (lassoIsActiveRef.current) return; const { current } = containerRef; if (current) { current.setTooltip(tooltip); @@ -947,21 +961,70 @@ const DeckGLGeoJson = (props: DeckGLGeoJsonProps) => { isDragging: false, }); + const { + lassoIsActive, + lassoDrawMode, + setLassoDrawMode, + selectedFeatures, + setSelectedFeatures, + lassoPolygon, + anchorGeoCoord, + setAnchorGeoCoord, + clearSelection, + handleLassoToggle, + handleLassoActivate, + handleLassoComplete, + deactivateLasso, + } = useLassoSelection({ + onPolygonComplete: async polygon => { + const allFeatures = (payload?.data?.features as GeoJsonFeature[]) || []; + + const hiddenCategoryKeys = new Set( + Object.entries(categories) + .filter(([, cat]) => cat.enabled === false) + .map(([key]) => key), + ); + + await handleLassoPolygonComplete( + polygon, + allFeatures, + { + dimension: propVisualConfig?.dimension as string | undefined, + hiddenCategoryKeys, + }, + lassoRequestIdRef, + { setSelectedFeatures, setAnchorGeoCoord }, + ); + }, + onActivate: () => { + setMeasureState({ + startPoint: null, + endPoint: null, + isActive: false, + isDragging: false, + }); + // Clear any visible tooltip when entering lasso mode + containerRef.current?.setTooltip(null); + }, + }); + + // Keep ref in sync with lasso state for use in memoized callbacks + lassoIsActiveRef.current = lassoIsActive; + // Don't show popup when measurement mode is active const handleFeatureClick = useCallback( (info: any) => { - if (measureState.isActive) return; + if (measureState.isActive || lassoIsActive) return; if (info?.object?.properties) { setClickedFeature({ properties: info.object.properties }); } }, - [measureState.isActive], + [measureState.isActive, lassoIsActive], ); const handleRulerToggle = useCallback(() => { setMeasureState(prev => { if (prev.isActive) { - // Exiting ruler mode - clear points return { startPoint: null, endPoint: null, @@ -969,7 +1032,7 @@ const DeckGLGeoJson = (props: DeckGLGeoJsonProps) => { isDragging: false, }; } - // Entering ruler mode + deactivateLasso(); return { startPoint: null, endPoint: null, @@ -977,7 +1040,7 @@ const DeckGLGeoJson = (props: DeckGLGeoJsonProps) => { isDragging: false, }; }); - }, []); + }, [deactivateLasso]); const handleMeasureClick = useCallback((coordinate: Coordinate) => { setMeasureState(prev => { @@ -1063,6 +1126,15 @@ const DeckGLGeoJson = (props: DeckGLGeoJsonProps) => { width, ]); + // Re-project anchor on every render so the results bar tracks pan/zoom. + // Use the live viewport instead of the initial/autozoom viewport. + const anchorPosition = useMemo(() => { + if (!anchorGeoCoord) return null; + const liveVp = getLiveViewport(); + const vp = liveVp ?? viewport; + return projectAnchorToScreen(anchorGeoCoord, vp, width, height); + }, [anchorGeoCoord, viewport, width, height]); + // Write live viewport to module-level store (outside Redux) so the actual // viewport control value is only changed by explicit user Save actions. // ViewportControl reads the store on-demand via getLiveViewport. @@ -1204,6 +1276,11 @@ const DeckGLGeoJson = (props: DeckGLGeoJsonProps) => { onMeasureDragStart={handleMeasureDragStart} onMeasureDrag={handleMeasureDrag} onMeasureDragEnd={handleMeasureDragEnd} + lassoIsActive={lassoIsActive} + lassoDrawMode={lassoDrawMode} + lassoPolygon={lassoPolygon} + onLassoComplete={handleLassoComplete} + selectedFeatures={selectedFeatures} onEmptyClick={handleClosePopup} /> { onResetView={handleResetView} onRulerToggle={handleRulerToggle} isRulerActive={measureState.isActive} + onLassoToggle={handleLassoToggle} + onLassoActivate={handleLassoActivate} + isLassoActive={lassoIsActive} + lassoDrawMode={lassoDrawMode} + onLassoDrawModeChange={setLassoDrawMode} position="top-right" /> + {(selectedFeatures.length > 0 || (lassoPolygon && anchorPosition)) && ( + + )} col.column_name || col.label || col, ); + // Allowlist for lasso export: only hover and additional details columns. + // Styling inputs (colorByValue, pointSize, textLabel, dimension) are + // excluded — users care about data columns, not rendering config. + const exportColumnNames = [ + ...hoverColumnNames, + ...featureInfoColumnNames, + ].filter((v, i, a) => a.indexOf(v) === i); + if (!Array.isArray(rawFeatures) || rawFeatures.length === 0) { console.warn('🚨 No valid GeoJSON features found'); } @@ -529,6 +537,7 @@ export default function transformProps(chartProps: ChartProps) { legend, hoverColumnNames, featureInfoColumnNames, + exportColumnNames, limitReached, visualConfig: { dimension, diff --git a/superset-frontend/plugins/geoset-map-chart/src/types.ts b/superset-frontend/plugins/geoset-map-chart/src/types.ts index 3a5ab44edd..1dbf88156a 100644 --- a/superset-frontend/plugins/geoset-map-chart/src/types.ts +++ b/superset-frontend/plugins/geoset-map-chart/src/types.ts @@ -38,7 +38,9 @@ export interface GeoJsonFeature { properties: { [key: string]: any }; extraProps?: { [key: string]: any }; color?: number[]; // optionally added by addColor + strokeColor?: number[]; // optionally added by addColor sizeValue?: number; // pre-computed pixel size for dynamic point sizing + categoryName?: string; // set during feature enrichment from dimensionColumn } export function toHex(color: ColorType): string { @@ -111,3 +113,7 @@ export type LegendGroup = { entries: { sliceId: string; legendEntry: LegendEntry }[]; initialCollapsed: boolean; // true only if ALL entries have initialCollapsed }; + +// ── Lasso types ───────────────────────────────────────────── +export type LassoDrawMode = 'freehand' | 'polygon' | 'circle' | 'rectangle'; +export type LassoLayer = { id: string; name: string }; diff --git a/superset-frontend/plugins/geoset-map-chart/src/utils/lassoExport.ts b/superset-frontend/plugins/geoset-map-chart/src/utils/lassoExport.ts new file mode 100644 index 0000000000..8824d99602 --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/src/utils/lassoExport.ts @@ -0,0 +1,177 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import type { GeoJsonFeature } from '../types'; +import { getRepresentativePoint } from './lassoSelection'; + +/** + * Flatten feature properties into tabular rows for export. + * + * Uses an allowlist approach: only columns the user explicitly configured + * (dimension, metric, size, hover-over data, additional details, text label) + * are included. Any computed/styling properties injected during layer + * processing (fillColor, color_*, sizeValue, etc.) are excluded by default. + * + * When no allowlist is provided, falls back to including all properties. + */ +export function featuresToRows( + features: GeoJsonFeature[], + allowedColumns?: string[], +): { + headers: string[]; + rows: Record[]; +} { + let propHeaders: string[]; + + if (allowedColumns && allowedColumns.length > 0) { + const allowed = new Set(allowedColumns); + // Only include allowed keys that actually exist on at least one feature + const present = new Set(); + features.forEach(f => { + if (f.properties) { + Object.keys(f.properties).forEach(k => { + if (allowed.has(k)) present.add(k); + }); + } + }); + // Preserve the caller's column order + propHeaders = allowedColumns.filter(k => present.has(k)); + } else { + // No allowlist — include all properties (fallback) + const keySet = new Set(); + features.forEach(f => { + if (f.properties) { + Object.keys(f.properties).forEach(k => keySet.add(k)); + } + }); + propHeaders = Array.from(keySet).sort(); + } + + const headers = ['_geometry_type', '_longitude', '_latitude', ...propHeaders]; + + const rows = features.map(f => { + const pt = getRepresentativePoint(f); + const row: Record = { + _geometry_type: f.geometry?.type ?? '', + _longitude: pt?.[0] ?? '', + _latitude: pt?.[1] ?? '', + }; + propHeaders.forEach(key => { + row[key] = f.properties?.[key] ?? ''; + }); + return row; + }); + + return { headers, rows }; +} + +function timestamp(): string { + return new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); +} + +function triggerDownload(blob: Blob, filename: string) { + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = filename; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); +} + +/** + * Sanitize a cell value for Excel export. + * Prefixes formula-trigger characters with a single quote so they are treated + * as literal text, matching the CSV injection protection in escapeCSV. + */ +export function sanitizeExcelValue(value: any): any { + if (typeof value === 'string' && /^[=+\-@]/.test(value)) { + return `'${value}`; + } + return value; +} + +export function escapeCSV(value: any): string { + let str = String(value ?? ''); + // Guard against spreadsheet formula injection — only for non-numeric values + // so legitimate negative numbers like -5.2 aren't prefixed with a quote + if (typeof value === 'string' && /^[=+\-@]/.test(str)) { + str = `'${str}`; + } + if ( + str.includes(',') || + str.includes('"') || + str.includes('\n') || + str.includes('\t') + ) { + return `"${str.replace(/"/g, '""')}"`; + } + return str; +} + +/** + * Download selected features as a CSV file. + */ +export function exportToCSV( + features: GeoJsonFeature[], + allowedColumns?: string[], + filename?: string, +): void { + const { headers, rows } = featuresToRows(features, allowedColumns); + const csvLines = [ + headers.map(escapeCSV).join(','), + ...rows.map(row => headers.map(h => escapeCSV(row[h])).join(',')), + ]; + const blob = new Blob([csvLines.join('\n')], { type: 'text/csv' }); + triggerDownload(blob, filename ?? `lasso-selection-${timestamp()}.csv`); +} + +// Cache the dynamic import so subsequent exports don't re-fetch the library +let xlsxModule: typeof import('xlsx') | null = null; + +/** + * Download selected features as an Excel (.xlsx) file. + * xlsx is lazy-loaded to avoid adding to the initial bundle. + */ +export async function exportToExcel( + features: GeoJsonFeature[], + allowedColumns?: string[], + filename?: string, +): Promise { + if (!xlsxModule) { + xlsxModule = await import('xlsx'); + } + const XLSX = xlsxModule; + const { headers, rows } = featuresToRows(features, allowedColumns); + const sanitizedRows = rows.map(row => { + const sanitized: Record = {}; + for (const key of headers) { + sanitized[key] = sanitizeExcelValue(row[key]); + } + return sanitized; + }); + const ws = XLSX.utils.json_to_sheet(sanitizedRows, { header: headers }); + const wb = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(wb, ws, 'Lasso Selection'); + const buffer = XLSX.write(wb, { type: 'array', bookType: 'xlsx' }); + const blob = new Blob([buffer], { + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + }); + triggerDownload(blob, filename ?? `lasso-selection-${timestamp()}.xlsx`); +} diff --git a/superset-frontend/plugins/geoset-map-chart/src/utils/lassoSelection.ts b/superset-frontend/plugins/geoset-map-chart/src/utils/lassoSelection.ts new file mode 100644 index 0000000000..becdd55093 --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/src/utils/lassoSelection.ts @@ -0,0 +1,329 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import area from '@turf/area'; +import booleanIntersects from '@turf/boolean-intersects'; +import booleanPointInPolygon from '@turf/boolean-point-in-polygon'; +import centroid from '@turf/centroid'; +import intersect from '@turf/intersect'; +import { polygon as turfPolygon, point as turfPoint } from '@turf/helpers'; +import unkinkPolygon from '@turf/unkink-polygon'; +import { WebMercatorViewport } from '@math.gl/web-mercator'; +import type { Coordinate } from './measureDistance'; +import type { GeoJsonFeature } from '../types'; + +/** Minimum overlap ratio (0–1) for a polygon to be captured by the lasso. */ +const POLYGON_OVERLAP_THRESHOLD = 0.5; + +/** Vertical pixel offset applied to the results-bar anchor position. */ +const ANCHOR_VERTICAL_OFFSET = 12; + +/** + * Normalize a category value to a consistent string key. + * Used for matching category visibility across single- and multi-layer views. + */ +export function normalizeCategoryKey(raw: unknown): string { + if (raw == null) return ''; + const str = typeof raw === 'string' ? raw : String(raw); + return str.trim().toLowerCase(); +} + +/** + * Get a representative [lng, lat] for any GeoJSON geometry type. + * Used for point features and as a fallback for export coordinates. + */ +export function getRepresentativePoint( + feature: GeoJsonFeature, +): [number, number] | null { + const { geometry } = feature; + if (!geometry || !geometry.type) return null; + + switch (geometry.type) { + case 'Point': + return geometry.coordinates as [number, number]; + case 'MultiPoint': + return (geometry.coordinates?.[0] as [number, number]) ?? null; + default: { + try { + const c = centroid(feature as any); + return c.geometry.coordinates as [number, number]; + } catch (err) { + // eslint-disable-next-line no-console + console.warn('getRepresentativePoint: centroid failed', err); + return null; + } + } + } +} + +/** + * Ensure a polygon coordinate ring is closed (first point == last point). + */ +export function closeRing(coords: Coordinate[]): Coordinate[] { + if (coords.length < 3) return coords; + const first = coords[0]; + const last = coords[coords.length - 1]; + if (first[0] === last[0] && first[1] === last[1]) return coords; + return [...coords, first]; +} + +const SQ_METERS_PER_ACRE = 4046.86; +const SQ_METERS_PER_SQ_MILE = 2_589_988; +const SQ_METERS_PER_SQ_KM = 1_000_000; + +/** + * Calculate the area of a lasso polygon and return a human-readable string. + * Returns `null` when the polygon has fewer than 3 coordinates. + * + * - < 1 km²: displayed in acres + * - >= 1 km²: displayed in square miles + */ +export function calculateLassoArea( + coords: Coordinate[], +): string | null { + if (coords.length < 3) return null; + + const closed = closeRing(coords); + const poly = turfPolygon([closed]); + const sqMeters = area(poly); + + if (sqMeters < SQ_METERS_PER_SQ_KM) { + const acres = sqMeters / SQ_METERS_PER_ACRE; + return `${acres < 0.1 ? acres.toFixed(2) : acres.toFixed(1)} acres`; + } + const sqMiles = sqMeters / SQ_METERS_PER_SQ_MILE; + return `${sqMiles.toFixed(1)} sq mi`; +} + +/** + * Test whether a feature intersects the lasso polygon. + * + * - Point / MultiPoint: direct point-in-polygon test (fast) + * - Polygon / MultiPolygon: selected if >= 50% area overlap + * - LineString / MultiLineString: selected if any vertex is inside + */ +function isFeatureInLasso( + feature: GeoJsonFeature, + lassoPoly: ReturnType, +): boolean { + const { geometry } = feature; + if (!geometry || !geometry.type) return false; + + try { + switch (geometry.type) { + case 'Point': { + const pt = geometry.coordinates as [number, number]; + return booleanPointInPolygon(turfPoint(pt), lassoPoly); + } + case 'MultiPoint': { + // Selected if any point in the multi-point is inside + return (geometry.coordinates as [number, number][]).some(pt => + booleanPointInPolygon(turfPoint(pt), lassoPoly), + ); + } + case 'Polygon': + case 'MultiPolygon': { + // Selected if >= 50% of the polygon's area is inside the lasso + const featureArea = area(feature as any); + if (featureArea === 0) return false; + const overlap = intersect({ + type: 'FeatureCollection', + features: [feature as any, lassoPoly], + }); + if (!overlap) return false; + return area(overlap) / featureArea >= POLYGON_OVERLAP_THRESHOLD; + } + case 'LineString': + case 'MultiLineString': { + // Use full geometric intersection — catches lines that pass through + // the lasso even when no vertex lies inside the polygon. + return booleanIntersects( + { type: 'Feature', geometry, properties: {} } as any, + lassoPoly, + ); + } + default: + // eslint-disable-next-line no-console + console.warn( + `isFeatureInLasso: unsupported geometry type "${geometry.type}"`, + ); + return false; + } + } catch (err) { + // eslint-disable-next-line no-console + console.warn('isFeatureInLasso: geometry test failed', err); + return false; + } +} + +/** Number of features to process before yielding to the main thread. */ +const FILTER_BATCH_SIZE = 2000; + +/** Datasets at or below this size run synchronously (no yield overhead). */ +const SYNC_THRESHOLD = 5000; + +/** + * Yield to the main thread so long-running spatial filtering doesn't freeze + * the UI. Uses `setTimeout(0)` as a universal fallback. + */ +function yieldToMain(): Promise { + return new Promise(resolve => setTimeout(resolve, 0)); +} + +/** + * Prepare lasso polygon(s) for spatial testing. + * Handles closing the ring and splitting self-intersecting polygons. + */ +function prepareLassoPolygons( + lassoCoords: Coordinate[], +): ReturnType[] { + const closed = closeRing(lassoCoords); + const rawPoly = turfPolygon([closed]); + + // Split self-intersecting polygons into valid parts so turf.js spatial + // operations produce correct results. For valid polygons this returns a + // single-element collection, so the overhead is negligible. + try { + const unkinked = unkinkPolygon(rawPoly); + return unkinked.features as ReturnType[]; + } catch { + // If unkinking fails (degenerate geometry), fall back to the raw polygon + return [rawPoly]; + } +} + +/** + * Filter features that intersect the lasso polygon. + * + * Self-intersecting polygons (common with freehand drawing) are automatically + * split into valid parts via `unkinkPolygon`. Small datasets run synchronously + * for instant results; large datasets are batched to avoid blocking the UI. + */ +export async function filterFeaturesInLasso( + features: GeoJsonFeature[], + lassoCoords: Coordinate[], +): Promise { + if (!features.length || lassoCoords.length < 3) return []; + + const polys = prepareLassoPolygons(lassoCoords); + if (polys.length === 0) return []; + + const results: GeoJsonFeature[] = []; + + // Run synchronously for small-to-medium datasets to avoid async overhead + if (features.length <= SYNC_THRESHOLD) { + for (let i = 0; i < features.length; i++) { + if (polys.some(p => isFeatureInLasso(features[i], p))) { + results.push(features[i]); + } + } + return results; + } + + // Batch with yields for large datasets to keep the UI responsive + for (let i = 0; i < features.length; i++) { + if (polys.some(p => isFeatureInLasso(features[i], p))) { + results.push(features[i]); + } + if ((i + 1) % FILTER_BATCH_SIZE === 0 && i + 1 < features.length) { + await yieldToMain(); + } + } + + return results; +} + +/** + * Filter features by category visibility, run lasso spatial selection, + * and compute an anchor position for the results bar. + * + * Shared between Multi.tsx and GeoSetLayer.tsx to avoid duplication. + */ +/** + * Project a geo coordinate to screen pixel position for the results bar anchor. + * Call on every render so the bar tracks the polygon through pan/zoom. + */ +export function projectAnchorToScreen( + geoCoord: Coordinate, + viewport: { longitude: number; latitude: number; zoom: number }, + width: number, + height: number, +): { x: number; y: number } { + const wmv = new WebMercatorViewport({ ...viewport, width, height }); + const [px, py] = wmv.project(geoCoord); + return { x: px, y: py + ANCHOR_VERTICAL_OFFSET }; +} + +export async function buildLassoResult( + allFeatures: GeoJsonFeature[], + polygon: Coordinate[], + opts: { + dimension?: string; + hiddenCategoryKeys?: Set; + }, +): Promise<{ selected: GeoJsonFeature[]; anchorGeoCoord: Coordinate | null }> { + const { dimension, hiddenCategoryKeys } = opts; + + // Filter out features whose category is hidden in the legend + const visibleFeatures = + hiddenCategoryKeys && hiddenCategoryKeys.size > 0 && dimension + ? allFeatures.filter(f => { + const raw = f.categoryName ?? f.properties?.[dimension]; + if (raw == null) return true; + return !hiddenCategoryKeys.has(normalizeCategoryKey(raw)); + }) + : allFeatures; + + const selected = await filterFeaturesInLasso(visibleFeatures, polygon); + + // Return the last polygon coordinate as the anchor — callers project it + // to screen space on every render so the bar tracks pan/zoom. + const anchorGeoCoord: Coordinate | null = polygon[polygon.length - 1] ?? null; + + return { selected, anchorGeoCoord }; +} + +/** + * Shared handler for the onPolygonComplete callback used by both Multi.tsx + * and GeoSetLayer.tsx. Runs `buildLassoResult` with staleness protection + * so a reset during async filtering is safe. + */ +export async function handleLassoPolygonComplete( + polygon: Coordinate[], + features: GeoJsonFeature[], + opts: { dimension?: string; hiddenCategoryKeys?: Set }, + requestIdRef: { current: number }, + callbacks: { + setSelectedFeatures: (features: GeoJsonFeature[]) => void; + setAnchorGeoCoord: (coord: Coordinate | null) => void; + }, +): Promise { + const requestId = ++requestIdRef.current; + + const { selected, anchorGeoCoord } = await buildLassoResult( + features, + polygon, + opts, + ); + + // Discard if the user reset the lasso while filtering was in progress + if (requestIdRef.current !== requestId) return; + + callbacks.setSelectedFeatures(selected); + if (anchorGeoCoord) callbacks.setAnchorGeoCoord(anchorGeoCoord); +} diff --git a/superset-frontend/plugins/geoset-map-chart/test/GeoSetMultiMap/multiUtils.test.ts b/superset-frontend/plugins/geoset-map-chart/test/GeoSetMultiMap/multiUtils.test.ts index 1b6c06cc8f..6cf3524705 100644 --- a/superset-frontend/plugins/geoset-map-chart/test/GeoSetMultiMap/multiUtils.test.ts +++ b/superset-frontend/plugins/geoset-map-chart/test/GeoSetMultiMap/multiUtils.test.ts @@ -34,6 +34,7 @@ const makeConfig = ( legendCollapsed: false, initiallyHidden: false, lazyLoading: false, + lassoSelectable: true, ...overrides, }); @@ -46,6 +47,7 @@ describe('resolveLayerAutozoom', () => { legendCollapsed: false, initiallyHidden: false, lazyLoading: true, + lassoSelectable: true, }), ).toBe(false); }); @@ -58,6 +60,7 @@ describe('resolveLayerAutozoom', () => { legendCollapsed: false, initiallyHidden: false, lazyLoading: true, + lassoSelectable: true, }), ).toBe(false); }); @@ -70,6 +73,7 @@ describe('resolveLayerAutozoom', () => { legendCollapsed: false, initiallyHidden: false, lazyLoading: false, + lassoSelectable: true, }), ).toBe(true); }); @@ -82,6 +86,7 @@ describe('resolveLayerAutozoom', () => { legendCollapsed: false, initiallyHidden: false, lazyLoading: false, + lassoSelectable: true, }), ).toBe(false); }); @@ -107,6 +112,7 @@ describe('normalizeDeckSlices', () => { legendCollapsed: false, initiallyHidden: false, lazyLoading: true, + lassoSelectable: true, }, ]); expect(result[0].lazyLoading).toBe(true); @@ -120,6 +126,7 @@ describe('normalizeDeckSlices', () => { legendCollapsed: false, initiallyHidden: false, lazyLoading: true, + lassoSelectable: true, }, ]); expect(resolveLayerAutozoom(result[0])).toBe(false); @@ -128,6 +135,32 @@ describe('normalizeDeckSlices', () => { it('returns empty array when input is undefined', () => { expect(normalizeDeckSlices(undefined)).toEqual([]); }); + + it('sets lassoSelectable to true by default for legacy number entries', () => { + const result = normalizeDeckSlices([1, 2]); + result.forEach(slice => { + expect(slice.lassoSelectable).toBe(true); + }); + }); + + it('preserves lassoSelectable: false from config objects', () => { + const result = normalizeDeckSlices([ + makeConfig(1, { lassoSelectable: false }), + ]); + expect(result[0].lassoSelectable).toBe(false); + }); + + it('defaults lassoSelectable to true when field is missing from config object', () => { + const configWithoutLasso = { + sliceId: 1, + autozoom: true, + legendCollapsed: false, + initiallyHidden: false, + lazyLoading: false, + } as any; + const result = normalizeDeckSlices([configWithoutLasso]); + expect(result[0].lassoSelectable).toBe(true); + }); }); describe('loadLayersOrchestrated', () => { diff --git a/superset-frontend/plugins/geoset-map-chart/test/components/LassoDropdown.test.tsx b/superset-frontend/plugins/geoset-map-chart/test/components/LassoDropdown.test.tsx new file mode 100644 index 0000000000..ab53cbaedc --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/test/components/LassoDropdown.test.tsx @@ -0,0 +1,130 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import LassoDropdown, { + LassoDropdownProps, +} from '../../src/components/LassoDropdown'; +import { renderWithTheme } from '../testHelpers'; + +const layers = [ + { id: '1', name: 'Points' }, + { id: '2', name: 'Polygons' }, +]; + +const defaultProps: LassoDropdownProps = { + hasMultipleLayers: true, + layers, + activeLassoLayerId: '1', + onLayerSelect: jest.fn(), + drawMode: 'freehand', + onDrawModeChange: jest.fn(), + onClose: jest.fn(), +}; + +function renderDropdown(overrides: Partial = {}) { + return renderWithTheme(); +} + +beforeEach(() => jest.clearAllMocks()); + +describe('LassoDropdown', () => { + it('renders a dialog with the correct label', () => { + renderDropdown(); + expect(screen.getByRole('dialog')).toHaveAttribute( + 'aria-label', + 'Lasso options', + ); + }); + + it('shows "Select layer" header when hasMultipleLayers is true', () => { + renderDropdown(); + expect(screen.getByText('Select layer')).toBeInTheDocument(); + }); + + it('shows "Lasso mode" header when hasMultipleLayers is false', () => { + renderDropdown({ hasMultipleLayers: false }); + expect(screen.getByText('Lasso mode')).toBeInTheDocument(); + }); + + it('renders layer radio items with correct aria-checked state', () => { + renderDropdown(); + const radios = screen.getAllByRole('radio'); + expect(radios).toHaveLength(2); + expect(radios[0]).toHaveAttribute('aria-checked', 'true'); + expect(radios[1]).toHaveAttribute('aria-checked', 'false'); + }); + + it('does not render layer list when hasMultipleLayers is false', () => { + renderDropdown({ hasMultipleLayers: false }); + expect(screen.queryAllByRole('radio')).toHaveLength(0); + }); + + it('calls onLayerSelect when a layer is clicked', () => { + const onLayerSelect = jest.fn(); + renderDropdown({ onLayerSelect }); + userEvent.click(screen.getByText('Polygons')); + expect(onLayerSelect).toHaveBeenCalledWith('2'); + }); + + it('calls onClose when close button is clicked', () => { + const onClose = jest.fn(); + renderDropdown({ onClose }); + userEvent.click(screen.getByLabelText('Close lasso options')); + expect(onClose).toHaveBeenCalledTimes(1); + }); + + it('renders draw method toggle buttons with correct aria-pressed', () => { + renderDropdown({ drawMode: 'polygon' }); + expect(screen.getByText('Click-and-drag')).toHaveAttribute( + 'aria-pressed', + 'false', + ); + expect(screen.getByText('Point-to-point')).toHaveAttribute( + 'aria-pressed', + 'true', + ); + }); + + it('calls onDrawModeChange when Point-to-point is clicked', () => { + const onDrawModeChange = jest.fn(); + renderDropdown({ onDrawModeChange }); + userEvent.click(screen.getByText('Point-to-point')); + expect(onDrawModeChange).toHaveBeenCalledWith('polygon'); + }); + + it('shows shape sub-buttons when in a click-and-drag mode', () => { + renderDropdown({ drawMode: 'freehand' }); + expect(screen.getByText('Freehand')).toBeInTheDocument(); + expect(screen.getByText('Circle')).toBeInTheDocument(); + expect(screen.getByText('Rectangle')).toBeInTheDocument(); + }); + + it('hides shape sub-buttons when in polygon mode', () => { + renderDropdown({ drawMode: 'polygon' }); + expect(screen.queryByText('Freehand')).not.toBeInTheDocument(); + expect(screen.queryByText('Circle')).not.toBeInTheDocument(); + expect(screen.queryByText('Rectangle')).not.toBeInTheDocument(); + }); + + it('calls onDrawModeChange with circle when Circle is clicked', () => { + const onDrawModeChange = jest.fn(); + renderDropdown({ onDrawModeChange, drawMode: 'freehand' }); + userEvent.click(screen.getByText('Circle')); + expect(onDrawModeChange).toHaveBeenCalledWith('circle'); + }); + + it('calls onDrawModeChange with rectangle when Rectangle is clicked', () => { + const onDrawModeChange = jest.fn(); + renderDropdown({ onDrawModeChange, drawMode: 'freehand' }); + userEvent.click(screen.getByText('Rectangle')); + expect(onDrawModeChange).toHaveBeenCalledWith('rectangle'); + }); + + it('marks circle shape button as pressed when drawMode is circle', () => { + renderDropdown({ drawMode: 'circle' }); + expect(screen.getByText('Circle')).toHaveAttribute('aria-pressed', 'true'); + expect(screen.getByText('Freehand')).toHaveAttribute( + 'aria-pressed', + 'false', + ); + }); +}); diff --git a/superset-frontend/plugins/geoset-map-chart/test/components/LassoResultsBar.test.tsx b/superset-frontend/plugins/geoset-map-chart/test/components/LassoResultsBar.test.tsx new file mode 100644 index 0000000000..d85aead19a --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/test/components/LassoResultsBar.test.tsx @@ -0,0 +1,213 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { message } from 'antd'; +import LassoResultsBar, { + LassoResultsBarProps, +} from '../../src/components/LassoResultsBar'; +import { renderWithTheme } from '../testHelpers'; +import { GeoJsonFeature } from '../../src/types'; +import { Coordinate } from '../../src/utils/measureDistance'; + +// Mock the export module so we can verify calls without triggering downloads +jest.mock('../../src/utils/lassoExport', () => ({ + exportToCSV: jest.fn(), + exportToExcel: jest.fn(() => Promise.resolve()), +})); + +jest.mock('antd', () => ({ + ...jest.requireActual('antd'), + message: { + success: jest.fn(), + error: jest.fn(), + }, +})); + +import { exportToCSV, exportToExcel } from '../../src/utils/lassoExport'; + +const sampleFeatures: GeoJsonFeature[] = [ + { + type: 'Feature', + geometry: { type: 'Point', coordinates: [0, 0] }, + properties: { name: 'A' }, + }, + { + type: 'Feature', + geometry: { type: 'Point', coordinates: [1, 1] }, + properties: { name: 'B' }, + }, + { + type: 'Feature', + geometry: { type: 'Point', coordinates: [2, 2] }, + properties: { name: 'C' }, + }, +]; + +const defaultProps: LassoResultsBarProps = { + features: sampleFeatures, + onClear: jest.fn(), + anchorPosition: { x: 100, y: 200 }, +}; + +function renderBar(overrides: Partial = {}) { + return renderWithTheme( + , + ); +} + +beforeEach(() => jest.clearAllMocks()); + +describe('LassoResultsBar', () => { + it('renders the item count', () => { + renderBar(); + expect(screen.getByText('3 Items Selected')).toBeInTheDocument(); + }); + + it('renders nothing when features is empty and no polygon', () => { + const { container } = renderBar({ features: [] }); + expect(container.innerHTML).toBe(''); + }); + + it('renders when features is empty but lassoPolygon is provided', () => { + const polygon: Coordinate[] = [ + [-77.0, 38.9], + [-77.0, 38.91], + [-76.99, 38.91], + [-76.99, 38.9], + ]; + renderBar({ features: [], lassoPolygon: polygon }); + expect(screen.getByText('0 Items Selected')).toBeInTheDocument(); + }); + + it('calls onClear when close button is clicked', () => { + const onClear = jest.fn(); + renderBar({ onClear }); + userEvent.click(screen.getByLabelText('Clear selection')); + expect(onClear).toHaveBeenCalledTimes(1); + }); + + it('opens export menu when kebab button is clicked', () => { + renderBar(); + expect(screen.queryByRole('menu')).not.toBeInTheDocument(); + userEvent.click(screen.getByLabelText('Export options')); + expect(screen.getByRole('menu')).toBeInTheDocument(); + }); + + it('sets aria-expanded on the export button when menu is open', () => { + renderBar(); + const btn = screen.getByLabelText('Export options'); + expect(btn).toHaveAttribute('aria-expanded', 'false'); + userEvent.click(btn); + expect(btn).toHaveAttribute('aria-expanded', 'true'); + }); + + it('renders CSV and Excel menu items', () => { + renderBar(); + userEvent.click(screen.getByLabelText('Export options')); + const items = screen.getAllByRole('menuitem'); + expect(items).toHaveLength(2); + expect(items[0]).toHaveTextContent('Export to .CSV'); + expect(items[1]).toHaveTextContent('Export to Excel'); + }); + + it('calls exportToCSV and closes menu when CSV is clicked', () => { + renderBar(); + userEvent.click(screen.getByLabelText('Export options')); + userEvent.click(screen.getByText('Export to .CSV')); + expect(exportToCSV).toHaveBeenCalledWith(sampleFeatures, undefined); + // Menu should close + expect(screen.queryByRole('menu')).not.toBeInTheDocument(); + }); + + it('calls exportToExcel and closes menu when Excel is clicked', () => { + renderBar(); + userEvent.click(screen.getByLabelText('Export options')); + userEvent.click(screen.getByText('Export to Excel')); + expect(exportToExcel).toHaveBeenCalledWith(sampleFeatures, undefined); + expect(screen.queryByRole('menu')).not.toBeInTheDocument(); + }); + + it('does not call onClear after export (user dismisses explicitly)', () => { + const onClear = jest.fn(); + renderBar({ onClear }); + userEvent.click(screen.getByLabelText('Export options')); + userEvent.click(screen.getByText('Export to .CSV')); + expect(onClear).not.toHaveBeenCalled(); + }); + + it('positions at anchor when anchorPosition is provided', () => { + const { container } = renderBar({ + anchorPosition: { x: 50, y: 75 }, + }); + const bar = container.firstChild as HTMLElement; + // Styled-component applies left/top from the anchor + expect(bar).toHaveStyle('left: 50px'); + expect(bar).toHaveStyle('top: 75px'); + }); + + it('shows success message after CSV export', () => { + renderBar(); + userEvent.click(screen.getByLabelText('Export options')); + userEvent.click(screen.getByText('Export to .CSV')); + expect(message.success).toHaveBeenCalledWith({ + content: 'CSV exported successfully', + duration: 3, + }); + }); + + it('shows error message when CSV export fails', () => { + (exportToCSV as jest.Mock).mockImplementationOnce(() => { + throw new Error('write error'); + }); + renderBar(); + userEvent.click(screen.getByLabelText('Export options')); + userEvent.click(screen.getByText('Export to .CSV')); + expect(message.error).toHaveBeenCalledWith({ + content: 'Failed to export CSV', + duration: 5, + }); + }); + + it('shows success message after Excel export', async () => { + renderBar(); + userEvent.click(screen.getByLabelText('Export options')); + userEvent.click(screen.getByText('Export to Excel')); + // exportToExcel is async — wait for the promise to resolve + await screen.findByText('3 Items Selected'); + expect(message.success).toHaveBeenCalledWith({ + content: 'Excel exported successfully', + duration: 3, + }); + }); + + it('shows error message when Excel export fails', async () => { + (exportToExcel as jest.Mock).mockImplementationOnce(() => + Promise.reject(new Error('network error')), + ); + renderBar(); + userEvent.click(screen.getByLabelText('Export options')); + userEvent.click(screen.getByText('Export to Excel')); + // Wait for the rejected promise to settle + await screen.findByText('3 Items Selected'); + expect(message.error).toHaveBeenCalledWith({ + content: 'Failed to export Excel', + duration: 5, + }); + }); + + it('displays area text when lassoPolygon is provided', () => { + // ~1 km × 1 km square near the equator → should show acres + const polygon: Coordinate[] = [ + [0, 0], + [0.01, 0], + [0.01, 0.01], + [0, 0.01], + ]; + renderBar({ lassoPolygon: polygon }); + expect(screen.getByText(/Area:/)).toBeInTheDocument(); + }); + + it('does not display area text when lassoPolygon is null', () => { + renderBar({ lassoPolygon: null }); + expect(screen.queryByText(/Area:/)).not.toBeInTheDocument(); + }); +}); diff --git a/superset-frontend/plugins/geoset-map-chart/test/components/MapControls.test.tsx b/superset-frontend/plugins/geoset-map-chart/test/components/MapControls.test.tsx new file mode 100644 index 0000000000..ea298afd14 --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/test/components/MapControls.test.tsx @@ -0,0 +1,197 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import MapControls, { + MapControlsProps, +} from '../../src/components/MapControls'; +import { renderWithTheme } from '../testHelpers'; + +const defaultProps: MapControlsProps = { + onZoomIn: jest.fn(), + onZoomOut: jest.fn(), + onResetView: jest.fn(), + onRulerToggle: jest.fn(), + isRulerActive: false, + onLassoToggle: jest.fn(), + isLassoActive: false, +}; + +function renderMapControls(overrides: Partial = {}) { + return renderWithTheme(); +} + +beforeEach(() => { + jest.clearAllMocks(); +}); + +describe('MapControls', () => { + it('renders all toolbar buttons', () => { + renderMapControls(); + expect(screen.getByTitle('Reset view')).toBeInTheDocument(); + expect(screen.getByTitle('Zoom out')).toBeInTheDocument(); + expect(screen.getByTitle('Zoom in')).toBeInTheDocument(); + expect(screen.getByTitle('Measure distance')).toBeInTheDocument(); + expect( + screen.getByTitle('Lasso select features'), + ).toBeInTheDocument(); + }); + + it('calls onZoomIn, onZoomOut, onResetView on click', () => { + const onZoomIn = jest.fn(); + const onZoomOut = jest.fn(); + const onResetView = jest.fn(); + renderMapControls({ onZoomIn, onZoomOut, onResetView }); + + userEvent.click(screen.getByTitle('Zoom in')); + expect(onZoomIn).toHaveBeenCalledTimes(1); + + userEvent.click(screen.getByTitle('Zoom out')); + expect(onZoomOut).toHaveBeenCalledTimes(1); + + userEvent.click(screen.getByTitle('Reset view')); + expect(onResetView).toHaveBeenCalledTimes(1); + }); + + it('calls onRulerToggle on ruler button click', () => { + const onRulerToggle = jest.fn(); + renderMapControls({ onRulerToggle }); + + userEvent.click(screen.getByTitle('Measure distance')); + expect(onRulerToggle).toHaveBeenCalledTimes(1); + }); + + it('shows "Exit measure mode" title when ruler is active', () => { + renderMapControls({ isRulerActive: true }); + expect( + screen.getByTitle('Exit measure mode (Esc)'), + ).toBeInTheDocument(); + }); +}); + +describe('Lasso — single-layer (no lassoLayers)', () => { + it('opens dropdown with "Lasso mode" header on click', () => { + renderMapControls(); + + expect(screen.queryByText('Lasso mode')).not.toBeInTheDocument(); + + userEvent.click(screen.getByTitle('Lasso select features')); + expect(screen.getByText('Lasso mode')).toBeInTheDocument(); + }); + + it('shows mode toggle buttons in dropdown', () => { + renderMapControls(); + + userEvent.click(screen.getByTitle('Lasso select features')); + expect(screen.getByText('Click-and-drag')).toBeInTheDocument(); + expect(screen.getByText('Point-to-point')).toBeInTheDocument(); + }); + + it('does not show layer checkboxes', () => { + renderMapControls(); + + userEvent.click(screen.getByTitle('Lasso select features')); + expect(screen.queryByText('Select layers')).not.toBeInTheDocument(); + }); + + it('calls onLassoActivate when close button clicked', () => { + const onLassoActivate = jest.fn(); + renderMapControls({ onLassoActivate }); + + userEvent.click(screen.getByTitle('Lasso select features')); + userEvent.click(screen.getByLabelText('Close lasso options')); + expect(onLassoActivate).toHaveBeenCalledTimes(1); + }); + + it('calls onLassoDrawModeChange when mode button clicked', () => { + const onLassoDrawModeChange = jest.fn(); + renderMapControls({ onLassoDrawModeChange, lassoDrawMode: 'freehand' }); + + userEvent.click(screen.getByTitle('Lasso select features')); + userEvent.click(screen.getByText('Point-to-point')); + expect(onLassoDrawModeChange).toHaveBeenCalledWith('polygon'); + }); +}); + +describe('Lasso — multi-layer', () => { + const layers = [ + { id: '1', name: 'Burn Areas' }, + { id: '2', name: 'Program Offices' }, + { id: '3', name: 'Air Quality' }, + ]; + + it('opens dropdown with "Select layer" header and layer list', () => { + renderMapControls({ lassoLayers: layers }); + + userEvent.click(screen.getByTitle('Lasso select features')); + expect(screen.getByText('Select layer')).toBeInTheDocument(); + expect(screen.getByText('Burn Areas')).toBeInTheDocument(); + expect(screen.getByText('Program Offices')).toBeInTheDocument(); + expect(screen.getByText('Air Quality')).toBeInTheDocument(); + }); + + it('calls onLassoLayerSelect when a layer is clicked', () => { + const onLassoLayerSelect = jest.fn(); + renderMapControls({ lassoLayers: layers, onLassoLayerSelect }); + + userEvent.click(screen.getByTitle('Lasso select features')); + userEvent.click(screen.getByText('Program Offices')); + expect(onLassoLayerSelect).toHaveBeenCalledWith('2'); + }); + + it('calls onLassoActivate on close when a layer is selected', () => { + const onLassoActivate = jest.fn(); + renderMapControls({ + lassoLayers: layers, + activeLassoLayerId: '2', + onLassoActivate, + }); + + userEvent.click(screen.getByTitle('Lasso select features')); + userEvent.click(screen.getByLabelText('Close lasso options')); + expect(onLassoActivate).toHaveBeenCalledTimes(1); + }); + + it('does NOT call onLassoActivate on close when no layer selected', () => { + const onLassoActivate = jest.fn(); + renderMapControls({ + lassoLayers: layers, + onLassoActivate, + }); + + userEvent.click(screen.getByTitle('Lasso select features')); + userEvent.click(screen.getByLabelText('Close lasso options')); + expect(onLassoActivate).not.toHaveBeenCalled(); + }); + + it('shows mode toggle alongside layer list', () => { + renderMapControls({ lassoLayers: layers }); + + userEvent.click(screen.getByTitle('Lasso select features')); + expect(screen.getByText('Click-and-drag')).toBeInTheDocument(); + expect(screen.getByText('Point-to-point')).toBeInTheDocument(); + }); +}); + +describe('Lasso — active state', () => { + it('shows "Exit lasso mode" title when active', () => { + renderMapControls({ isLassoActive: true }); + expect( + screen.getByTitle('Exit lasso mode (Esc)'), + ).toBeInTheDocument(); + }); + + it('calls onLassoToggle (deactivate) when button clicked while active', () => { + const onLassoToggle = jest.fn(); + renderMapControls({ isLassoActive: true, onLassoToggle }); + + userEvent.click(screen.getByTitle('Exit lasso mode (Esc)')); + expect(onLassoToggle).toHaveBeenCalledTimes(1); + }); + + it('does not open dropdown when clicking to deactivate', () => { + renderMapControls({ isLassoActive: true }); + + userEvent.click(screen.getByTitle('Exit lasso mode (Esc)')); + expect(screen.queryByText('Lasso mode')).not.toBeInTheDocument(); + expect(screen.queryByText('Select layers')).not.toBeInTheDocument(); + }); +}); diff --git a/superset-frontend/plugins/geoset-map-chart/test/components/useLassoLayer.test.ts b/superset-frontend/plugins/geoset-map-chart/test/components/useLassoLayer.test.ts new file mode 100644 index 0000000000..b31d62a14f --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/test/components/useLassoLayer.test.ts @@ -0,0 +1,187 @@ +import { renderHook, act } from '@testing-library/react-hooks'; + +// Mock the editable-layers library — EditableGeoJsonLayer requires WebGL. +// Use a global ref so the mock factory (which is hoisted) can access it. +let mockLayerCalls: any[] = []; + +jest.mock('@deck.gl-community/editable-layers', () => { + class FakeDrawPolygonByDraggingMode {} + class FakeDrawPolygonMode {} + class FakeDrawCircleFromCenterMode {} + class FakeDrawRectangleMode {} + class FakeViewMode {} + + function MockEditableGeoJsonLayer(props: any) { + mockLayerCalls.push(props); + return { id: props.id, props }; + } + + return { + EditableGeoJsonLayer: MockEditableGeoJsonLayer, + DrawPolygonByDraggingMode: FakeDrawPolygonByDraggingMode, + DrawPolygonMode: FakeDrawPolygonMode, + DrawCircleFromCenterMode: FakeDrawCircleFromCenterMode, + DrawRectangleMode: FakeDrawRectangleMode, + ViewMode: FakeViewMode, + }; +}); + +import { useLassoLayer } from '../../src/components/useLassoLayer'; + +beforeEach(() => { + mockLayerCalls = []; +}); + +describe('useLassoLayer', () => { + it('returns empty layers when inactive', () => { + const onComplete = jest.fn(); + const { result } = renderHook(() => useLassoLayer(false, onComplete)); + expect(result.current.layers).toEqual([]); + }); + + it('returns one layer when active', () => { + const onComplete = jest.fn(); + const { result } = renderHook(() => useLassoLayer(true, onComplete)); + expect(result.current.layers).toHaveLength(1); + expect(mockLayerCalls.length).toBeGreaterThan(0); + }); + + it('creates layer with correct id', () => { + const onComplete = jest.fn(); + renderHook(() => useLassoLayer(true, onComplete)); + expect(mockLayerCalls[0]).toEqual( + expect.objectContaining({ id: 'lasso-editable-layer' }), + ); + }); + + it('calls onPolygonComplete when addFeature edit occurs', () => { + const onComplete = jest.fn(); + renderHook(() => useLassoLayer(true, onComplete)); + + const { onEdit } = mockLayerCalls[0]; + + const fakePolygon = { + type: 'FeatureCollection', + features: [ + { + geometry: { + coordinates: [ + [ + [10, 20], + [30, 40], + [50, 60], + [10, 20], + ], + ], + }, + }, + ], + }; + + act(() => { + onEdit({ updatedData: fakePolygon, editType: 'addFeature' }); + }); + + expect(onComplete).toHaveBeenCalledWith([ + [10, 20], + [30, 40], + [50, 60], + [10, 20], + ]); + }); + + it('does not call onPolygonComplete for non-addFeature edits', () => { + const onComplete = jest.fn(); + renderHook(() => useLassoLayer(true, onComplete)); + + const { onEdit } = mockLayerCalls[0]; + + act(() => { + onEdit({ + updatedData: { type: 'FeatureCollection', features: [] }, + editType: 'movePosition', + }); + }); + + expect(onComplete).not.toHaveBeenCalled(); + }); + + it('resets data when transitioning from inactive to active', () => { + const onComplete = jest.fn(); + const { rerender } = renderHook( + ({ active }) => useLassoLayer(active, onComplete), + { initialProps: { active: false } }, + ); + + mockLayerCalls = []; + rerender({ active: true }); + + expect(mockLayerCalls[0]).toEqual( + expect.objectContaining({ + data: expect.objectContaining({ + type: 'FeatureCollection', + features: [], + }), + }), + ); + }); + + it('returns empty layers when transitioning from active to inactive', () => { + const onComplete = jest.fn(); + const { result, rerender } = renderHook( + ({ active }) => useLassoLayer(active, onComplete), + { initialProps: { active: true } }, + ); + + expect(result.current.layers).toHaveLength(1); + + rerender({ active: false }); + expect(result.current.layers).toEqual([]); + }); + + it('creates a layer for circle draw mode with dragToDraw config', () => { + const onComplete = jest.fn(); + renderHook(() => useLassoLayer(true, onComplete, 'circle')); + const lastCall = mockLayerCalls[mockLayerCalls.length - 1]; + expect(lastCall).toEqual( + expect.objectContaining({ + id: 'lasso-editable-layer', + modeConfig: { dragToDraw: true }, + }), + ); + }); + + it('creates a layer for rectangle draw mode with dragToDraw config', () => { + const onComplete = jest.fn(); + renderHook(() => useLassoLayer(true, onComplete, 'rectangle')); + const lastCall = mockLayerCalls[mockLayerCalls.length - 1]; + expect(lastCall).toEqual( + expect.objectContaining({ + id: 'lasso-editable-layer', + modeConfig: { dragToDraw: true }, + }), + ); + }); + + it('does not set dragToDraw for polygon mode', () => { + const onComplete = jest.fn(); + renderHook(() => useLassoLayer(true, onComplete, 'polygon')); + const lastCall = mockLayerCalls[mockLayerCalls.length - 1]; + expect(lastCall.modeConfig).toBeUndefined(); + }); + + it('renders completed polygon layers when completedPolygon is provided', () => { + const onComplete = jest.fn(); + const completedPolygon = [ + [0, 0], + [1, 0], + [1, 1], + [0, 0], + ]; + const { result } = renderHook(() => + useLassoLayer(true, onComplete, 'freehand', completedPolygon as any), + ); + // Should have the editable layer + 2 completed layers (fill + outline) + expect(result.current.layers.length).toBeGreaterThanOrEqual(3); + }); +}); diff --git a/superset-frontend/plugins/geoset-map-chart/test/hooks/useLassoActivation.test.ts b/superset-frontend/plugins/geoset-map-chart/test/hooks/useLassoActivation.test.ts new file mode 100644 index 0000000000..e947bd5683 --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/test/hooks/useLassoActivation.test.ts @@ -0,0 +1,109 @@ +import { renderHook, act } from '@testing-library/react-hooks'; +import { useLassoActivation } from '../../src/hooks/useLassoActivation'; + +describe('useLassoActivation', () => { + beforeEach(() => { + sessionStorage.clear(); + }); + + it('returns correct initial state', () => { + const { result } = renderHook(() => useLassoActivation()); + expect(result.current.lassoIsActive).toBe(false); + expect(result.current.lassoDrawMode).toBe('freehand'); + expect(result.current.selectedLassoLayerId).toBeUndefined(); + }); + + it('activates lasso and calls onActivate', () => { + const onActivate = jest.fn(); + const { result } = renderHook(() => + useLassoActivation({ onActivate }), + ); + act(() => result.current.handleLassoActivate()); + expect(result.current.lassoIsActive).toBe(true); + expect(onActivate).toHaveBeenCalledTimes(1); + }); + + it('deactivateLasso preserves layer selection', () => { + const { result } = renderHook(() => + useLassoActivation({ + availableLayers: [{ id: '1', name: 'Layer 1' }], + }), + ); + act(() => result.current.handleLassoActivate()); + expect(result.current.selectedLassoLayerId).toBe('1'); + + act(() => result.current.deactivateLasso()); + expect(result.current.lassoIsActive).toBe(false); + expect(result.current.selectedLassoLayerId).toBe('1'); + }); + + it('resetActivation clears active state and re-auto-selects the first layer', () => { + const { result } = renderHook(() => + useLassoActivation({ + availableLayers: [{ id: '1', name: 'Layer 1' }], + }), + ); + act(() => result.current.handleLassoActivate()); + act(() => result.current.resetActivation()); + expect(result.current.lassoIsActive).toBe(false); + // Auto-select re-fires after reset so the first layer is ready for next activation + expect(result.current.selectedLassoLayerId).toBe('1'); + }); + + it('auto-selects first layer when availableLayers provided', () => { + const { result } = renderHook(() => + useLassoActivation({ + availableLayers: [ + { id: 'x', name: 'X' }, + { id: 'y', name: 'Y' }, + ], + }), + ); + expect(result.current.selectedLassoLayerId).toBe('x'); + }); + + it('changes draw mode via setLassoDrawMode', () => { + const { result } = renderHook(() => useLassoActivation()); + act(() => result.current.setLassoDrawMode('polygon')); + expect(result.current.lassoDrawMode).toBe('polygon'); + }); + + it('selects a layer via handleLassoLayerSelect', () => { + const { result } = renderHook(() => useLassoActivation()); + act(() => result.current.handleLassoLayerSelect('a')); + expect(result.current.selectedLassoLayerId).toBe('a'); + }); + + it('persists draw mode to sessionStorage', () => { + const { result } = renderHook(() => useLassoActivation()); + act(() => result.current.setLassoDrawMode('circle')); + expect(sessionStorage.getItem('geoset-lasso-draw-mode')).toBe('circle'); + }); + + it('restores draw mode from sessionStorage on mount', () => { + sessionStorage.setItem('geoset-lasso-draw-mode', 'rectangle'); + const { result } = renderHook(() => useLassoActivation()); + expect(result.current.lassoDrawMode).toBe('rectangle'); + }); + + it('falls back to freehand for invalid sessionStorage value', () => { + sessionStorage.setItem('geoset-lasso-draw-mode', 'invalid'); + const { result } = renderHook(() => useLassoActivation()); + expect(result.current.lassoDrawMode).toBe('freehand'); + }); + + it('uses latest onActivate callback without stale closures', () => { + const first = jest.fn(); + const second = jest.fn(); + const { result, rerender } = renderHook( + ({ cb }) => useLassoActivation({ onActivate: cb }), + { initialProps: { cb: first } }, + ); + + rerender({ cb: second }); + act(() => result.current.handleLassoActivate()); + + expect(first).not.toHaveBeenCalled(); + expect(second).toHaveBeenCalledTimes(1); + }); +}); diff --git a/superset-frontend/plugins/geoset-map-chart/test/hooks/useLassoResults.test.ts b/superset-frontend/plugins/geoset-map-chart/test/hooks/useLassoResults.test.ts new file mode 100644 index 0000000000..d8e593020b --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/test/hooks/useLassoResults.test.ts @@ -0,0 +1,77 @@ +import { renderHook, act } from '@testing-library/react-hooks'; +import { useLassoResults } from '../../src/hooks/useLassoResults'; +import type { Coordinate } from '../../src/utils/measureDistance'; + +describe('useLassoResults', () => { + it('returns correct initial state', () => { + const { result } = renderHook(() => useLassoResults()); + expect(result.current.selectedFeatures).toEqual([]); + expect(result.current.lassoPolygon).toBeNull(); + expect(result.current.anchorGeoCoord).toBeNull(); + }); + + it('stores polygon and calls onPolygonComplete when handleLassoComplete fires', () => { + const onPolygonComplete = jest.fn(); + const { result } = renderHook(() => + useLassoResults({ onPolygonComplete }), + ); + + const polygon: Coordinate[] = [ + [0, 0], + [1, 0], + [1, 1], + [0, 0], + ]; + act(() => result.current.handleLassoComplete(polygon)); + + expect(result.current.lassoPolygon).toEqual(polygon); + expect(onPolygonComplete).toHaveBeenCalledWith(polygon); + }); + + it('clearSelection resets features, polygon, and anchor', () => { + const { result } = renderHook(() => useLassoResults()); + + act(() => { + result.current.handleLassoComplete([ + [0, 0], + [1, 0], + [1, 1], + ]); + result.current.setSelectedFeatures([ + { + type: 'Feature', + geometry: { type: 'Point', coordinates: [0, 0] }, + properties: {}, + }, + ]); + result.current.setAnchorGeoCoord([10, 20]); + }); + + expect(result.current.selectedFeatures).toHaveLength(1); + expect(result.current.lassoPolygon).not.toBeNull(); + expect(result.current.anchorGeoCoord).not.toBeNull(); + + act(() => result.current.clearSelection()); + + expect(result.current.selectedFeatures).toEqual([]); + expect(result.current.lassoPolygon).toBeNull(); + expect(result.current.anchorGeoCoord).toBeNull(); + }); + + it('uses latest onPolygonComplete callback without stale closures', () => { + const first = jest.fn(); + const second = jest.fn(); + const { result, rerender } = renderHook( + ({ cb }) => useLassoResults({ onPolygonComplete: cb }), + { initialProps: { cb: first } }, + ); + + rerender({ cb: second }); + + const polygon: Coordinate[] = [[0, 0]]; + act(() => result.current.handleLassoComplete(polygon)); + + expect(first).not.toHaveBeenCalled(); + expect(second).toHaveBeenCalledWith(polygon); + }); +}); diff --git a/superset-frontend/plugins/geoset-map-chart/test/hooks/useLassoSelection.test.ts b/superset-frontend/plugins/geoset-map-chart/test/hooks/useLassoSelection.test.ts new file mode 100644 index 0000000000..f596c68efb --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/test/hooks/useLassoSelection.test.ts @@ -0,0 +1,174 @@ +import { renderHook, act } from '@testing-library/react-hooks'; +import { useLassoSelection } from '../../src/hooks/useLassoSelection'; +import type { Coordinate } from '../../src/utils/measureDistance'; + +describe('useLassoSelection', () => { + it('returns correct initial state', () => { + const { result } = renderHook(() => useLassoSelection()); + expect(result.current.lassoIsActive).toBe(false); + expect(result.current.lassoDrawMode).toBe('freehand'); + expect(result.current.selectedLassoLayerId).toBeUndefined(); + }); + + it('activates lasso on handleLassoActivate', () => { + const { result } = renderHook(() => useLassoSelection()); + act(() => result.current.handleLassoActivate()); + expect(result.current.lassoIsActive).toBe(true); + }); + + it('calls onActivate callback when activated', () => { + const onActivate = jest.fn(); + const { result } = renderHook(() => useLassoSelection({ onActivate })); + act(() => result.current.handleLassoActivate()); + expect(onActivate).toHaveBeenCalledTimes(1); + }); + + it('deactivates and re-auto-selects first layer on handleLassoToggle', () => { + const { result } = renderHook(() => + useLassoSelection({ + availableLayers: [ + { id: '1', name: 'Layer 1' }, + { id: '2', name: 'Layer 2' }, + ], + }), + ); + + // Activate and verify layer is auto-selected + act(() => result.current.handleLassoActivate()); + expect(result.current.lassoIsActive).toBe(true); + expect(result.current.selectedLassoLayerId).toBe('1'); + + // Toggle off — deactivates but auto-select re-fires for next activation + act(() => result.current.handleLassoToggle()); + expect(result.current.lassoIsActive).toBe(false); + expect(result.current.selectedLassoLayerId).toBe('1'); + }); + + it('deactivates without clearing layer on deactivateLasso', () => { + const { result } = renderHook(() => + useLassoSelection({ + availableLayers: [{ id: '1', name: 'Layer 1' }], + }), + ); + + act(() => result.current.handleLassoActivate()); + expect(result.current.selectedLassoLayerId).toBe('1'); + + // Soft deactivation — layer preserved + act(() => result.current.deactivateLasso()); + expect(result.current.lassoIsActive).toBe(false); + expect(result.current.selectedLassoLayerId).toBe('1'); + }); + + it('changes draw mode via setLassoDrawMode', () => { + const { result } = renderHook(() => useLassoSelection()); + act(() => result.current.setLassoDrawMode('polygon')); + expect(result.current.lassoDrawMode).toBe('polygon'); + }); + + it('selects a layer via handleLassoLayerSelect', () => { + const { result } = renderHook(() => useLassoSelection()); + + act(() => result.current.handleLassoLayerSelect('a')); + expect(result.current.selectedLassoLayerId).toBe('a'); + + act(() => result.current.handleLassoLayerSelect('b')); + expect(result.current.selectedLassoLayerId).toBe('b'); + }); + + it('auto-selects first layer when availableLayers provided', () => { + const { result } = renderHook(() => + useLassoSelection({ + availableLayers: [ + { id: 'x', name: 'X' }, + { id: 'y', name: 'Y' }, + ], + }), + ); + expect(result.current.selectedLassoLayerId).toBe('x'); + }); + + it('does not auto-select when a layer is already selected', () => { + const { result } = renderHook(() => + useLassoSelection({ + availableLayers: [{ id: 'x', name: 'X' }], + }), + ); + + // Manually select 'y', then verify auto-select did not override + act(() => result.current.handleLassoLayerSelect('y')); + expect(result.current.selectedLassoLayerId).toBe('y'); + }); + + it('calls onPolygonComplete when handleLassoComplete is called', () => { + const onPolygonComplete = jest.fn(); + const { result } = renderHook(() => + useLassoSelection({ onPolygonComplete }), + ); + const polygon: Coordinate[] = [ + [0, 0], + [1, 0], + [1, 1], + [0, 0], + ]; + act(() => result.current.handleLassoComplete(polygon)); + expect(onPolygonComplete).toHaveBeenCalledWith(polygon); + }); + + it('deactivates lasso on Escape key', () => { + const { result } = renderHook(() => useLassoSelection()); + + act(() => result.current.handleLassoActivate()); + expect(result.current.lassoIsActive).toBe(true); + + act(() => { + document.dispatchEvent( + new KeyboardEvent('keydown', { key: 'Escape' }), + ); + }); + expect(result.current.lassoIsActive).toBe(false); + }); + + it('does not deactivate on Escape when lasso is inactive', () => { + const { result } = renderHook(() => useLassoSelection()); + expect(result.current.lassoIsActive).toBe(false); + + act(() => { + document.dispatchEvent( + new KeyboardEvent('keydown', { key: 'Escape' }), + ); + }); + // Should still be false, no errors + expect(result.current.lassoIsActive).toBe(false); + }); + + it('does not fire Escape listener after unmount', () => { + const { result, unmount } = renderHook(() => useLassoSelection()); + + act(() => result.current.handleLassoActivate()); + unmount(); + + // Should not throw + document.dispatchEvent( + new KeyboardEvent('keydown', { key: 'Escape' }), + ); + }); + + it('uses latest onPolygonComplete callback without stale closures', () => { + const first = jest.fn(); + const second = jest.fn(); + + const { result, rerender } = renderHook( + ({ cb }) => useLassoSelection({ onPolygonComplete: cb }), + { initialProps: { cb: first } }, + ); + + rerender({ cb: second }); + + const polygon: Coordinate[] = [[0, 0]]; + act(() => result.current.handleLassoComplete(polygon)); + + expect(first).not.toHaveBeenCalled(); + expect(second).toHaveBeenCalledWith(polygon); + }); +}); diff --git a/superset-frontend/plugins/geoset-map-chart/test/utils/lassoExport.test.ts b/superset-frontend/plugins/geoset-map-chart/test/utils/lassoExport.test.ts new file mode 100644 index 0000000000..a5f1f2452d --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/test/utils/lassoExport.test.ts @@ -0,0 +1,138 @@ +import { + featuresToRows, + escapeCSV, + sanitizeExcelValue, +} from '../../src/utils/lassoExport'; +import type { GeoJsonFeature } from '../../src/types'; + +describe('escapeCSV', () => { + it('returns plain strings unchanged', () => { + expect(escapeCSV('hello')).toBe('hello'); + }); + + it('wraps strings with commas in quotes', () => { + expect(escapeCSV('a,b')).toBe('"a,b"'); + }); + + it('escapes embedded double quotes', () => { + expect(escapeCSV('say "hi"')).toBe('"say ""hi"""'); + }); + + it('wraps strings with newlines', () => { + expect(escapeCSV('line1\nline2')).toBe('"line1\nline2"'); + }); + + it('converts null/undefined to empty string', () => { + expect(escapeCSV(null)).toBe(''); + expect(escapeCSV(undefined)).toBe(''); + }); + + it('converts numbers to strings', () => { + expect(escapeCSV(42)).toBe('42'); + }); + + it('does not prefix negative numbers with a quote', () => { + expect(escapeCSV(-5.2)).toBe('-5.2'); + expect(escapeCSV(-100)).toBe('-100'); + }); + + it('prepends single quote for formula injection characters in strings', () => { + expect(escapeCSV('=SUM(A1)')).toBe("'=SUM(A1)"); + expect(escapeCSV('+cmd')).toBe("'+cmd"); + expect(escapeCSV('-exec')).toBe("'-exec"); + expect(escapeCSV('@import')).toBe("'@import"); + }); + + it('wraps strings with tabs in quotes', () => { + expect(escapeCSV('col1\tcol2')).toBe('"col1\tcol2"'); + }); + + it('handles formula characters combined with commas', () => { + // Should both prepend quote AND wrap in double quotes + expect(escapeCSV('=SUM(A1),B2')).toBe("\"'=SUM(A1),B2\""); + }); +}); + +describe('sanitizeExcelValue', () => { + it('returns non-string values unchanged', () => { + expect(sanitizeExcelValue(42)).toBe(42); + expect(sanitizeExcelValue(null)).toBe(null); + expect(sanitizeExcelValue(undefined)).toBe(undefined); + expect(sanitizeExcelValue(true)).toBe(true); + }); + + it('returns safe strings unchanged', () => { + expect(sanitizeExcelValue('hello')).toBe('hello'); + expect(sanitizeExcelValue('123')).toBe('123'); + }); + + it('prefixes formula-trigger characters with a single quote', () => { + expect(sanitizeExcelValue('=SUM(A1)')).toBe("'=SUM(A1)"); + expect(sanitizeExcelValue('+cmd')).toBe("'+cmd"); + expect(sanitizeExcelValue('-exec')).toBe("'-exec"); + expect(sanitizeExcelValue('@import')).toBe("'@import"); + }); + + it('does not prefix negative numbers', () => { + expect(sanitizeExcelValue(-5.2)).toBe(-5.2); + expect(sanitizeExcelValue(-100)).toBe(-100); + }); +}); + +describe('featuresToRows', () => { + const features: GeoJsonFeature[] = [ + { + type: 'Feature', + geometry: { type: 'Point', coordinates: [-77.0, 38.9] }, + properties: { name: 'DC', population: 700000 }, + }, + { + type: 'Feature', + geometry: { type: 'Point', coordinates: [-122.4, 37.8] }, + properties: { name: 'SF', elevation: 16 }, + }, + ]; + + it('returns sorted union of all property keys as headers', () => { + const { headers } = featuresToRows(features); + expect(headers).toEqual([ + '_geometry_type', + '_longitude', + '_latitude', + 'elevation', + 'name', + 'population', + ]); + }); + + it('fills missing properties with empty string', () => { + const { rows } = featuresToRows(features); + expect(rows[0].elevation).toBe(''); + expect(rows[1].population).toBe(''); + }); + + it('includes geometry metadata columns', () => { + const { rows } = featuresToRows(features); + expect(rows[0]._geometry_type).toBe('Point'); + expect(rows[0]._longitude).toBe(-77.0); + expect(rows[0]._latitude).toBe(38.9); + }); + + it('returns empty headers (except meta) for features with no properties', () => { + const bare: GeoJsonFeature[] = [ + { + type: 'Feature', + geometry: { type: 'Point', coordinates: [0, 0] }, + properties: {}, + }, + ]; + const { headers } = featuresToRows(bare); + expect(headers).toEqual(['_geometry_type', '_longitude', '_latitude']); + }); + + it('returns empty rows for empty input', () => { + const { rows, headers } = featuresToRows([]); + expect(rows).toEqual([]); + expect(headers).toEqual(['_geometry_type', '_longitude', '_latitude']); + }); +}); diff --git a/superset-frontend/plugins/geoset-map-chart/test/utils/lassoSelection.test.ts b/superset-frontend/plugins/geoset-map-chart/test/utils/lassoSelection.test.ts new file mode 100644 index 0000000000..8c6071dcc0 --- /dev/null +++ b/superset-frontend/plugins/geoset-map-chart/test/utils/lassoSelection.test.ts @@ -0,0 +1,277 @@ +import { + closeRing, + filterFeaturesInLasso, + normalizeCategoryKey, +} from '../../src/utils/lassoSelection'; +import type { GeoJsonFeature } from '../../src/types'; +import type { Coordinate } from '../../src/utils/measureDistance'; + +// Small square lasso polygon around [0,0] +const LASSO_SQUARE: Coordinate[] = [ + [-1, -1], + [1, -1], + [1, 1], + [-1, 1], +]; + +function makePoint(lng: number, lat: number): GeoJsonFeature { + return { + type: 'Feature', + geometry: { type: 'Point', coordinates: [lng, lat] }, + properties: {}, + }; +} + +function makeMultiPoint(coords: [number, number][]): GeoJsonFeature { + return { + type: 'Feature', + geometry: { type: 'MultiPoint', coordinates: coords }, + properties: {}, + }; +} + +function makeLine(coords: [number, number][]): GeoJsonFeature { + return { + type: 'Feature', + geometry: { type: 'LineString', coordinates: coords }, + properties: {}, + }; +} + +function makeMultiLine(lines: [number, number][][]): GeoJsonFeature { + return { + type: 'Feature', + geometry: { type: 'MultiLineString', coordinates: lines }, + properties: {}, + }; +} + +function makePolygon(ring: [number, number][]): GeoJsonFeature { + return { + type: 'Feature', + geometry: { type: 'Polygon', coordinates: [ring] }, + properties: {}, + }; +} + +function makeMultiPolygon(rings: [number, number][][]): GeoJsonFeature { + return { + type: 'Feature', + geometry: { + type: 'MultiPolygon', + coordinates: rings.map(r => [r]), + }, + properties: {}, + }; +} + +describe('closeRing', () => { + it('returns input unchanged if already closed', () => { + const ring: Coordinate[] = [ + [0, 0], + [1, 0], + [1, 1], + [0, 0], + ]; + expect(closeRing(ring)).toBe(ring); + }); + + it('appends first point if ring is not closed', () => { + const ring: Coordinate[] = [ + [0, 0], + [1, 0], + [1, 1], + ]; + const closed = closeRing(ring); + expect(closed).toHaveLength(4); + expect(closed[3]).toEqual([0, 0]); + }); + + it('returns input unchanged if fewer than 3 points', () => { + const ring: Coordinate[] = [[0, 0]]; + expect(closeRing(ring)).toBe(ring); + }); +}); + +describe('normalizeCategoryKey', () => { + it('trims and lowercases strings', () => { + expect(normalizeCategoryKey(' Hello World ')).toBe('hello world'); + }); + + it('converts numbers to strings', () => { + expect(normalizeCategoryKey(42)).toBe('42'); + }); + + it('returns empty string for null/undefined', () => { + expect(normalizeCategoryKey(null)).toBe(''); + expect(normalizeCategoryKey(undefined)).toBe(''); + }); +}); + +describe('filterFeaturesInLasso', () => { + it('returns empty array when no features provided', async () => { + expect(await filterFeaturesInLasso([], LASSO_SQUARE)).toEqual([]); + }); + + it('returns empty array when polygon has fewer than 3 coords', async () => { + const features = [makePoint(0, 0)]; + expect( + await filterFeaturesInLasso(features, [ + [0, 0], + [1, 1], + ]), + ).toEqual([]); + }); + + it('selects Point features inside the lasso', async () => { + const inside = makePoint(0, 0); + const outside = makePoint(5, 5); + const result = await filterFeaturesInLasso( + [inside, outside], + LASSO_SQUARE, + ); + expect(result).toEqual([inside]); + }); + + it('selects MultiPoint features if any point is inside', async () => { + const mp = makeMultiPoint([ + [0, 0], + [10, 10], + ]); + const result = await filterFeaturesInLasso([mp], LASSO_SQUARE); + expect(result).toEqual([mp]); + }); + + it('rejects MultiPoint features if no point is inside', async () => { + const mp = makeMultiPoint([ + [10, 10], + [20, 20], + ]); + const result = await filterFeaturesInLasso([mp], LASSO_SQUARE); + expect(result).toEqual([]); + }); + + it('selects LineString features if any vertex is inside', async () => { + const line = makeLine([ + [0, 0], + [10, 10], + ]); + const result = await filterFeaturesInLasso([line], LASSO_SQUARE); + expect(result).toEqual([line]); + }); + + it('selects LineString features that pass through the lasso without a vertex inside', async () => { + // Line from well outside on the left to well outside on the right, + // passing through the [-1,1] x [-1,1] lasso square at y=0 + const line = makeLine([ + [-10, 0], + [10, 0], + ]); + const result = await filterFeaturesInLasso([line], LASSO_SQUARE); + expect(result).toEqual([line]); + }); + + it('rejects LineString features fully outside the lasso', async () => { + const line = makeLine([ + [10, 10], + [20, 20], + ]); + const result = await filterFeaturesInLasso([line], LASSO_SQUARE); + expect(result).toEqual([]); + }); + + it('selects Polygon features with >= 50% overlap', async () => { + // Small polygon fully inside the lasso square + const inside = makePolygon([ + [-0.5, -0.5], + [0.5, -0.5], + [0.5, 0.5], + [-0.5, 0.5], + [-0.5, -0.5], + ]); + const result = await filterFeaturesInLasso([inside], LASSO_SQUARE); + expect(result).toEqual([inside]); + }); + + it('rejects Polygon features with < 50% overlap', async () => { + // Polygon mostly outside: only a small sliver overlaps the lasso + const mostlyOutside = makePolygon([ + [0.5, 0.5], + [5, 0.5], + [5, 5], + [0.5, 5], + [0.5, 0.5], + ]); + const result = await filterFeaturesInLasso([mostlyOutside], LASSO_SQUARE); + expect(result).toEqual([]); + }); + + it('selects MultiPolygon features with sufficient overlap', async () => { + // One ring fully inside the lasso + const mp = makeMultiPolygon([ + [ + [-0.5, -0.5], + [0.5, -0.5], + [0.5, 0.5], + [-0.5, 0.5], + [-0.5, -0.5], + ], + ]); + const result = await filterFeaturesInLasso([mp], LASSO_SQUARE); + expect(result).toEqual([mp]); + }); + + it('selects MultiLineString features if any vertex is inside', async () => { + const ml = makeMultiLine([ + [ + [10, 10], + [20, 20], + ], + [ + [0, 0], + [10, 10], + ], + ]); + const result = await filterFeaturesInLasso([ml], LASSO_SQUARE); + expect(result).toEqual([ml]); + }); + + it('rejects MultiLineString features if no vertex is inside', async () => { + const ml = makeMultiLine([ + [ + [10, 10], + [20, 20], + ], + [ + [30, 30], + [40, 40], + ], + ]); + const result = await filterFeaturesInLasso([ml], LASSO_SQUARE); + expect(result).toEqual([]); + }); + + it('handles self-intersecting lasso polygons', async () => { + // Bowtie / figure-eight polygon that crosses itself at the origin. + // The valid parts should still select the point at (0.5, 0.5). + const bowtie: Coordinate[] = [ + [-1, -1], + [1, 1], + [1, -1], + [-1, 1], + ]; + const inside = makePoint(0.5, 0.5); + const outside = makePoint(5, 5); + const result = await filterFeaturesInLasso([inside, outside], bowtie); + expect(result).toEqual([inside]); + }); + + it('handles features with missing geometry gracefully', async () => { + const broken = { + type: 'Feature', + geometry: null, + properties: {}, + } as unknown as GeoJsonFeature; + expect(await filterFeaturesInLasso([broken], LASSO_SQUARE)).toEqual([]); + }); +}); diff --git a/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/Contour.tsx b/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/Contour.tsx index 18cad10d87..bee8379d53 100644 --- a/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/Contour.tsx +++ b/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/Contour.tsx @@ -96,7 +96,7 @@ export const getLayer: GetLayerType = function ({ cellSize: Number(cellSize || '200'), aggregation: aggregation.toUpperCase(), getPosition: (d: { position: number[]; weight: number }) => - d.position as Position, + d.position as unknown as Position, getWeight: (d: { weight: number }) => d.weight || 0, ...commonLayerProps({ formData: fd, diff --git a/superset-frontend/src/explore/components/controls/DeckSlicesControl/index.tsx b/superset-frontend/src/explore/components/controls/DeckSlicesControl/index.tsx index 743fd93b6f..1189327890 100644 --- a/superset-frontend/src/explore/components/controls/DeckSlicesControl/index.tsx +++ b/superset-frontend/src/explore/components/controls/DeckSlicesControl/index.tsx @@ -95,6 +95,7 @@ interface SliceSettings { legendCollapsed: boolean; initiallyHidden: boolean; lazyLoading: boolean; + lassoSelectable: boolean; } interface SelectedSliceRowProps { @@ -104,6 +105,7 @@ interface SelectedSliceRowProps { legendCollapsed: boolean; initiallyHidden: boolean; lazyLoading: boolean; + lassoSelectable: boolean; index: number; onRemove: (sliceId: number) => void; onMoveLabel: (dragIndex: number, hoverIndex: number) => void; @@ -167,6 +169,7 @@ const SelectedSliceRow = ({ legendCollapsed, initiallyHidden, lazyLoading, + lassoSelectable, index, onRemove, onMoveLabel, @@ -185,6 +188,8 @@ const SelectedSliceRow = ({ const [draftInitiallyHidden, setDraftInitiallyHidden] = useState(initiallyHidden); const [draftLazyLoading, setDraftLazyLoading] = useState(lazyLoading); + const [draftLassoSelectable, setDraftLassoSelectable] = + useState(lassoSelectable); // Reset draft state when popover opens const handleOpenChange = (open: boolean) => { @@ -193,6 +198,7 @@ const SelectedSliceRow = ({ setDraftLegendCollapsed(legendCollapsed); setDraftInitiallyHidden(initiallyHidden); setDraftLazyLoading(lazyLoading); + setDraftLassoSelectable(lassoSelectable); autozoomBeforeLazyRef.current = autozoom; } setSettingsOpen(open); @@ -220,18 +226,21 @@ const SelectedSliceRow = ({ const legendCollapsedChanged = draftLegendCollapsed !== legendCollapsed; const initiallyHiddenChanged = draftInitiallyHidden !== initiallyHidden; const lazyLoadingChanged = draftLazyLoading !== lazyLoading; + const lassoSelectableChanged = draftLassoSelectable !== lassoSelectable; if ( autozoomChanged || legendCollapsedChanged || initiallyHiddenChanged || - lazyLoadingChanged + lazyLoadingChanged || + lassoSelectableChanged ) { onUpdateSliceSettings(sliceId, { autozoom: draftAutozoom, legendCollapsed: draftLegendCollapsed, initiallyHidden: draftInitiallyHidden, lazyLoading: draftLazyLoading, + lassoSelectable: draftLassoSelectable, }); } setSettingsOpen(false); @@ -354,6 +363,26 @@ const SelectedSliceRow = ({ + + setDraftLassoSelectable(!draftLassoSelectable)} + /> + {t('Lasso Selectable')} + + + + + +