commit ffbdb093a93a51f708df791fbb355f4d92f27039 Author: Ubuntu Date: Mon Jun 15 20:46:11 2026 +0800 feat: project scaffold + bridge + maplibre engine - Vite + Vue 3 + TypeScript strict - @yuto-water/js-bridge (types, detector, browser provider) - MapLibre engine (MapManager singleton, MapFactory, LayerFactory) - Map composables (useMap, useLayer, usePopup) - Tianditu tile source, 6 layer type factory - SCSS design tokens (water-blue theme, dark mode) - Vant 4, maplibre-gl, axios, pinia, echarts deps - Build passes (vue-tsc + vite) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6cd502f --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +dist/ +.env.local +*.log +.DS_Store +tsconfig.tsbuildinfo diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..a7cea0b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar"] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..33895ab --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Vue 3 + TypeScript + Vite + +This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..4b95b16 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5069 @@ +{ + "name": "yuto-water-h5", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "yuto-water-h5", + "version": "0.0.0", + "dependencies": { + "@turf/turf": "^7.3.5", + "axios": "^1.18.0", + "crypto-js": "^4.2.0", + "dayjs": "^1.11.21", + "echarts": "^6.1.0", + "encryptlong": "^3.1.4", + "maplibre-gl": "^5.24.0", + "mitt": "^3.0.1", + "pinia": "^3.0.4", + "supercluster": "^8.0.1", + "uuid": "^14.0.0", + "vant": "^4.9.24", + "vue": "^3.5.34" + }, + "devDependencies": { + "@types/node": "^24.12.3", + "@vitejs/plugin-vue": "^6.0.6", + "@vue/tsconfig": "^0.9.1", + "sass-embedded": "^1.100.0", + "typescript": "~6.0.2", + "vite": "^8.0.12", + "vue-tsc": "^3.2.8" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.12.0", + "resolved": "http://mirrors.tencentyun.com/npm/@bufbuild/protobuf/-/protobuf-2.12.0.tgz", + "integrity": "sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA==", + "dev": true, + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "license": "MIT" + }, + "node_modules/@mapbox/jsonlint-lines-primitives": { + "version": "2.0.2", + "resolved": "http://mirrors.tencentyun.com/npm/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz", + "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@mapbox/point-geometry": { + "version": "1.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz", + "integrity": "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==", + "license": "ISC" + }, + "node_modules/@mapbox/tiny-sdf": { + "version": "2.2.0", + "resolved": "http://mirrors.tencentyun.com/npm/@mapbox/tiny-sdf/-/tiny-sdf-2.2.0.tgz", + "integrity": "sha512-LVL4wgI9YAum5V+LNVQO6QgFBPw7/MIIY4XJPNsPDMrjEwcE+JfKk1LuIl8GnF197ejVdC9QdPaxrx5gfgdGXg==", + "license": "BSD-2-Clause" + }, + "node_modules/@mapbox/unitbezier": { + "version": "0.0.1", + "resolved": "http://mirrors.tencentyun.com/npm/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz", + "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==", + "license": "BSD-2-Clause" + }, + "node_modules/@mapbox/vector-tile": { + "version": "2.0.5", + "resolved": "http://mirrors.tencentyun.com/npm/@mapbox/vector-tile/-/vector-tile-2.0.5.tgz", + "integrity": "sha512-pXj8m7KTsqZt+1jsE0xIpGvqTSbblfkuEJL/NJmNePMtEwxO8V3XMDo9WMSfDeqHvCtBI9Lmt4mGcGR10zecmw==", + "license": "BSD-3-Clause", + "dependencies": { + "@mapbox/point-geometry": "~1.1.0", + "@types/geojson": "^7946.0.16", + "pbf": "^4.0.2" + } + }, + "node_modules/@mapbox/whoots-js": { + "version": "3.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz", + "integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==", + "license": "ISC", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@maplibre/geojson-vt": { + "version": "6.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/@maplibre/geojson-vt/-/geojson-vt-6.1.0.tgz", + "integrity": "sha512-2eIY4gZxeKIVOZVNkAMb+5NgXhgsMQpOveTQAvnp53LYqHGJZDidk7Ew0Tged9PThidpbS+NFTh0g4zivhPDzQ==", + "license": "ISC", + "dependencies": { + "kdbush": "^4.0.2" + } + }, + "node_modules/@maplibre/maplibre-gl-style-spec": { + "version": "24.10.0", + "resolved": "http://mirrors.tencentyun.com/npm/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-24.10.0.tgz", + "integrity": "sha512-lichxSiagMEBBrqHF0trtMQH9RKh+9jUlIJl0qW0QHvt2H/tbvUWdE+ZzI2Jd0/pT7j/iavLonlPu7EQ/ixTOw==", + "license": "ISC", + "dependencies": { + "@mapbox/jsonlint-lines-primitives": "~2.0.2", + "@mapbox/unitbezier": "^1.0.0", + "json-stringify-pretty-compact": "^4.0.0", + "minimist": "^1.2.8", + "quickselect": "^3.0.0", + "tinyqueue": "^3.0.0" + }, + "bin": { + "gl-style-format": "dist/gl-style-format.mjs", + "gl-style-migrate": "dist/gl-style-migrate.mjs", + "gl-style-validate": "dist/gl-style-validate.mjs" + } + }, + "node_modules/@maplibre/maplibre-gl-style-spec/node_modules/@mapbox/unitbezier": { + "version": "1.0.0", + "resolved": "http://mirrors.tencentyun.com/npm/@mapbox/unitbezier/-/unitbezier-1.0.0.tgz", + "integrity": "sha512-fqd515fjBmANKGGsQ286E2Wvj/XvDFpGzwJxq4CI6jMQue6Oy04uCKp+JWKF00xRTmk6cEu1jPJ9p3xqH8YWqQ==", + "license": "BSD-2-Clause" + }, + "node_modules/@maplibre/mlt": { + "version": "1.1.11", + "resolved": "http://mirrors.tencentyun.com/npm/@maplibre/mlt/-/mlt-1.1.11.tgz", + "integrity": "sha512-dKvjKdITw9d0y3ndGkSqLUEpWCizMtdq8NB06cHohH/JZ2sJoM7dClR9wzJLUWykjbw9RXDFmhjjNBnNW27mzw==", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "@mapbox/point-geometry": "^1.1.0" + } + }, + "node_modules/@maplibre/vt-pbf": { + "version": "4.3.2", + "resolved": "http://mirrors.tencentyun.com/npm/@maplibre/vt-pbf/-/vt-pbf-4.3.2.tgz", + "integrity": "sha512-j6p0AdjvAR19Z3XaCysle7A4ZSo08tYOzxD0Y9NQylwPAkwJJeYub5b2eVucdeDh7erhv69DahoLOevDRERRUw==", + "license": "MIT", + "dependencies": { + "@mapbox/point-geometry": "^1.1.0", + "@types/geojson": "^7946.0.16", + "pbf": "^5.1.0" + } + }, + "node_modules/@maplibre/vt-pbf/node_modules/pbf": { + "version": "5.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/pbf/-/pbf-5.1.0.tgz", + "integrity": "sha512-Wv0yo0+uZepnoNEKsquhar1F18LogB8oeEikIhUXG16udbiXG7JecHGySwoo6kuMgjmbQYzdrTZlO+/K9t8eZg==", + "license": "BSD-3-Clause", + "dependencies": { + "resolve-protobuf-schema": "^2.1.0" + }, + "bin": { + "pbf": "bin/pbf" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.5", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.133.0", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "http://mirrors.tencentyun.com/npm/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.3", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@turf/along": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/along/-/along-7.3.5.tgz", + "integrity": "sha512-Ee4AHV9j2Bnlm/5nm4ChY7nkwpaaMffSez9nsJ9HcMbzG+GgTkt0F5pn9d02U7YvuWqckM5lfr3kBI+w2uTz+g==", + "license": "MIT", + "dependencies": { + "@turf/bearing": "7.3.5", + "@turf/destination": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/angle": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/angle/-/angle-7.3.5.tgz", + "integrity": "sha512-+c3UZfkL1nNacfpLkj89rRreIlKM5UALeeWpcw7hCEK4MycXCBmITkyLLXOzoQaRBc/7ua4PV0Ov13Y6Ck9PzQ==", + "license": "MIT", + "dependencies": { + "@turf/bearing": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/rhumb-bearing": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/area": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/area/-/area-7.3.5.tgz", + "integrity": "sha512-sSn80wPT7XfBIDN3vurCPxhk9W4U8ozS/XImSqeLN8qveTICOxzZkhsGDMp0CuncaN+plWut4a2TdNM7mzZB6Q==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/bbox/-/bbox-7.3.5.tgz", + "integrity": "sha512-oG1ya/HtBjAIg4TimbWx+nOYPbY0bCvt82Bq8tm6sBw3qqtbOyRSfDz79Sq90TnH7DXJprJ1qnVGKNtZ6jemfw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox-clip": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/bbox-clip/-/bbox-clip-7.3.5.tgz", + "integrity": "sha512-FuADTCBfRwdzJb2gFawDGnD1jKlUOfsWcu5Uv8iyEgu9JLuLAIYtI/l9xVF76BAoAvSkLgMfUvrPQ4SXCSUrVA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox-polygon": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/bbox-polygon/-/bbox-polygon-7.3.5.tgz", + "integrity": "sha512-Cs9Laej8zfSY51kORM9UcbY4Uf/7X3OIZr/LydbrmmARFSpYH/FZsEQjAGi1S1Q0aYbibVqjEUReHN3ZVsV5eA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bearing": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/bearing/-/bearing-7.3.5.tgz", + "integrity": "sha512-/qabIt/IuPsGlE6RukJ0zOirc6afNxoK7fK1WBNVnHuJjeOpSkW+7q1QW5XQGXBMv3odcD0ZgRR+MBiAHduYSA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bezier-spline": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/bezier-spline/-/bezier-spline-7.3.5.tgz", + "integrity": "sha512-54qnreNRvV9BeTGz2YXJyma+m8HMusuXWw3AkG0bIJGtqJMHqFKC/rWOcYxVj1VM2ScoTgglFxvq7GtSna+KMw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-clockwise": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-clockwise/-/boolean-clockwise-7.3.5.tgz", + "integrity": "sha512-VpDIpTKBjH4oPbzx1ns18TWcosi+qCRtgU1HIJHLj4NWyLNr7TX86DvomCvZRPfsFxkYYgkFlqHBG1a29dcyqQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-concave": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-concave/-/boolean-concave-7.3.5.tgz", + "integrity": "sha512-CHrmnEww43CAwEPszrKtLjM13hWDmsFZe0eCocxOtXLMspj+LCheB0bjMfcoBYfoTsvOPXxnoLTK9n4xuWBRSA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-contains": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-contains/-/boolean-contains-7.3.5.tgz", + "integrity": "sha512-P4JUAHgvJkD+8ybQ6d1OHp9TBsGsjJxF5lWeXJgp0k4+Hd/D0CVy4/mhLkZdNa6QdljVdwNcfU0CTqy1WsSQig==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/boolean-point-on-line": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/line-split": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-crosses": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-crosses/-/boolean-crosses-7.3.5.tgz", + "integrity": "sha512-o4Gmb2gbPl4j7810ZrT9GZsGigY+HRwcOI9pkkKH6BJ4ewSlQCPzP4JFruZp0+mIXS6NnPv7+Lw3J8LN3kYw1g==", + "license": "MIT", + "dependencies": { + "@turf/boolean-equal": "7.3.5", + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/line-intersect": "7.3.5", + "@turf/polygon-to-line": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-disjoint": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-disjoint/-/boolean-disjoint-7.3.5.tgz", + "integrity": "sha512-Pz1GGUC6iL6xGVqhyo+fYg35kl4j/HONMEoC1voN3DcBOCcVlzq+ljvMpvE+oQiR7Q38xLhIxZneLCqMp5YrQA==", + "license": "MIT", + "dependencies": { + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/line-intersect": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/polygon-to-line": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-equal": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-equal/-/boolean-equal-7.3.5.tgz", + "integrity": "sha512-xjSFi/BpxBY5tDDuSbixIRVq2AnDGcdLL8XOHzZtJWZjSa6tAi6afxSiMbQTGIhYfwwcB/sJcIUUffBaIQ2BiA==", + "license": "MIT", + "dependencies": { + "@turf/clean-coords": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "geojson-equality-ts": "^1.0.2", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-intersects": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-intersects/-/boolean-intersects-7.3.5.tgz", + "integrity": "sha512-Z6GPYjozrmTuzWQD0x7o8RPm+4HC7hz9q23hdB3U1+Qahesv8Mtc+wo82tO4CG6/NRnJ9u79DlEhmR1DxUU4iQ==", + "license": "MIT", + "dependencies": { + "@turf/boolean-disjoint": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-overlap": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-overlap/-/boolean-overlap-7.3.5.tgz", + "integrity": "sha512-DUeiPVqFSTjW79erPbo780pRcKCRad59NcscVsTYkZD/92peF/4rQvHbvAUpUDPZaQCxe+mvfeDHfUFmfVKCGA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/line-intersect": "7.3.5", + "@turf/line-overlap": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "geojson-equality-ts": "^1.0.2", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-parallel": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-parallel/-/boolean-parallel-7.3.5.tgz", + "integrity": "sha512-+shvGYFUx1vPQRPNeKiJcHtLAf9fl3mzAl9tBx2z+dU0IZDKz76/MAaDYSrMya/BYilFZ0E4RCEVq1X3s+AfkA==", + "license": "MIT", + "dependencies": { + "@turf/clean-coords": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/line-segment": "7.3.5", + "@turf/rhumb-bearing": "7.3.5", + "@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.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-7.3.5.tgz", + "integrity": "sha512-ba7+B0wzaS9GtERZOoXUZ6oW8IcIJHNQZf3c+tiD9ESjcsPO1Q/4qIJGTKl92nBLhhracHJxMWBM/U6hAVkaRg==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@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-on-line": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-point-on-line/-/boolean-point-on-line-7.3.5.tgz", + "integrity": "sha512-TuWfrAT63W43BDzgYc94UzQ5/PjF1aTnh4AIzmQwez1YnimShYcOTwo8OIHzDaB6gbbvFsfxYMuOA5JOp942Kg==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-touches": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-touches/-/boolean-touches-7.3.5.tgz", + "integrity": "sha512-GwD0gmbV1p+EFHojBjaa1cwGMybayOZUDLj562RlAAoexC8ownrW7W6oMAlM2VCxk4gq6CLx3hss9pONuQcKjQ==", + "license": "MIT", + "dependencies": { + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/boolean-point-on-line": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-valid": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-valid/-/boolean-valid-7.3.5.tgz", + "integrity": "sha512-ZezJCgFJS0JRJfj6fVSI1idcifTaWFW70NYRCUur9926DHLvSkfbtEF5i63yPQt2Zxx00FTUJPcHRzdgOiwECA==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/boolean-crosses": "7.3.5", + "@turf/boolean-disjoint": "7.3.5", + "@turf/boolean-overlap": "7.3.5", + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/boolean-point-on-line": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/line-intersect": "7.3.5", + "@types/geojson": "^7946.0.10", + "geojson-polygon-self-intersections": "^1.2.1", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-within": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/boolean-within/-/boolean-within-7.3.5.tgz", + "integrity": "sha512-FsZhkAoi9KU2F0D5dyOQ38A7y9Bk8XTmUfLKAJa12xHN0QtXZEYH86YdVlrI1XgfFB9gmUddJPFX+bJATy6rxw==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/boolean-point-on-line": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/line-split": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/buffer": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/buffer/-/buffer-7.3.5.tgz", + "integrity": "sha512-TGls3nYtWzviKHT00XVBfHKa7Z2oIZKqiHN7R0xErGwMSAR7YhxVROhxq/iyIsWZjl1SlPwweZZIxWILQuxpZA==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/center": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/jsts": "^2.7.1", + "@turf/meta": "7.3.5", + "@turf/projection": "7.3.5", + "@types/geojson": "^7946.0.10", + "d3-geo": "1.7.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/center": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/center/-/center-7.3.5.tgz", + "integrity": "sha512-eub5/Kfdmn89ZqwCONHI7astmTDEtN5M6+JfOkgoSyhKKFhUJYNxUyH1F/vCtIP7j1K369Vs4L9TYiuGapvIKQ==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/center-mean": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/center-mean/-/center-mean-7.3.5.tgz", + "integrity": "sha512-8IpS7zUZg0fuUpN9ViqT4gR6YMjSR1R1kHysaDxhP1zMrTJ84U5lGG+VQC7HpHqybOnuwkXZrV970h9Ni78n6g==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/center-median": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/center-median/-/center-median-7.3.5.tgz", + "integrity": "sha512-e+NeDKyZzIzSTA0qd9cwIuguCnDQSc6TLd1MjkHKTd37PCaPSc40TMEIBX1x+kJRwOxzmUgpubfHUG9zfjdtyA==", + "license": "MIT", + "dependencies": { + "@turf/center-mean": "7.3.5", + "@turf/centroid": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/center-of-mass": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/center-of-mass/-/center-of-mass-7.3.5.tgz", + "integrity": "sha512-eEzx4YKxUP55Apdjt7XXuQ906KKx4uSQWLxJw5OHE0rKOSN/qYTSdu0s7nQBAmGgAqeSC2538vuN7wEqMfYMvQ==", + "license": "MIT", + "dependencies": { + "@turf/centroid": "7.3.5", + "@turf/convex": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/centroid": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/centroid/-/centroid-7.3.5.tgz", + "integrity": "sha512-hkWaqwGFdOn6Tf0EWfn2yn1XZ1FWE1h2C5ZWstDMu/FxYO5DB+YjlmOFPl4K6SmSOEgdV07eK2vDCyPeTHqKGA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/circle": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/circle/-/circle-7.3.5.tgz", + "integrity": "sha512-Tse7GJrx0rxaQ5BdY6pHZ9HFPrZwRMry2yaqq94UsUyonhy1m7U2icB3Zp4M8o4XjHIGTCq9i2BYcGJram51Sw==", + "license": "MIT", + "dependencies": { + "@turf/destination": "7.3.5", + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clean-coords": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/clean-coords/-/clean-coords-7.3.5.tgz", + "integrity": "sha512-e0ZTqVWiQaCI/b8EFb+HAS8lCDomWafAKxQuIv0IYks0GwOlVTDWTwsY2RX2685j2Y+QssqOsyHsPZCtAjc3YQ==", + "license": "MIT", + "dependencies": { + "@turf/boolean-point-on-line": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clone": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/clone/-/clone-7.3.5.tgz", + "integrity": "sha512-qfIaHj3410QEcTpiCRnTzhq8YrUp2gWrUIPLBAEFykopNxJkq1du1VrRzvuAo36ap2UV7KppkS6wGNypbcxswQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clusters": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/clusters/-/clusters-7.3.5.tgz", + "integrity": "sha512-ZYQSCxElarAaG4azNieZ0ylX1sietkHIVAZv6H5JfSz/EXbAekQIom/isoynfDl/jVyNonDT7UrDZdCIjKQ2Gg==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clusters-dbscan": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/clusters-dbscan/-/clusters-dbscan-7.3.5.tgz", + "integrity": "sha512-xdc0ccv2fyiUSWrJYJFE6RTluf8oVCB0/aCOdUD/ZvtG3eyqGIXMRMzAR1PujQHjBWtI+ndD4Eq+DqiGukGK+g==", + "license": "MIT", + "dependencies": { + "@turf/clone": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clusters-kmeans": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/clusters-kmeans/-/clusters-kmeans-7.3.5.tgz", + "integrity": "sha512-MnKymdmL7vy4TR5CLkcNkNgsJP8ZBEiWkqnRYBJLq/hFoppTvXxKvkRzftWtLfkIWb5oQ2XMvBh8BgALN22d5A==", + "license": "MIT", + "dependencies": { + "@turf/clone": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "skmeans": "0.9.7", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/collect": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/collect/-/collect-7.3.5.tgz", + "integrity": "sha512-ddcBDdnM2Rwjfedxsbjvb7Zhoqo6uCTcnaHvu3ej/g+Z9iJ/K2wkRWhEUVAg/wppso5io6qEPmmPpNlefePt+w==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/combine": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/combine/-/combine-7.3.5.tgz", + "integrity": "sha512-olQH6WmLl3XAalbpiz7RSRr4/mogan38gvgDlo37ypW1ckeBUi+2TX5HgJUZq4wxa2gMlny72QYkqY9zW4Jw+A==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/concave": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/concave/-/concave-7.3.5.tgz", + "integrity": "sha512-T496U4K5mXsJXTKjnf7eW+4SYoDP0bXWhpcfpWuCAaDJy8n1Q8Dbslj7wqrWd2lqIhulVRF+3zWAh0bJS34L5g==", + "license": "MIT", + "dependencies": { + "@turf/clone": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/tin": "7.3.5", + "@types/geojson": "^7946.0.10", + "topojson-client": "3.x", + "topojson-server": "3.x", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/convex": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/convex/-/convex-7.3.5.tgz", + "integrity": "sha512-d/pq86he+/GB/2ObuBHapeT15QFsCPhhGab3uE4YjogLMbD8qtu0sRGF+cvvPRDNuCLycOBL/xgFLnf9SteYlA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "concaveman": "^1.2.1", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/destination": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/destination/-/destination-7.3.5.tgz", + "integrity": "sha512-x6ylChhOlIbucRSw7wF6z2gSEqqQl+dE0nSH5AL/ojZkqqGYahiw+2P4A8ZMuDM6rzH+FIqRYDes0o4nSArZCw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/difference": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/difference/-/difference-7.3.5.tgz", + "integrity": "sha512-iDyWYCvgS3vgB8W1ai2cvfJaTq9bOt1QghiVkCNIyccF97CgtYJzenREVVUlp8qU9lJlbQ/ameyKvXPA1uOAlA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "polyclip-ts": "^0.16.8", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/directional-mean": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/directional-mean/-/directional-mean-7.3.5.tgz", + "integrity": "sha512-Fm3rVgX7xiCL8Ed68dZpUl5NEAgEpaUdkAaZLvhedfUmKcuXcfBwX8RebHwNWctxcvKVOhoAMSlogpV33JnKdQ==", + "license": "MIT", + "dependencies": { + "@turf/bearing": "7.3.5", + "@turf/centroid": "7.3.5", + "@turf/destination": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/length": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/dissolve": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/dissolve/-/dissolve-7.3.5.tgz", + "integrity": "sha512-6kZTc8rbGuBqxWW8iK1sJZC8r7vr5uWdv7nsMJ0eX8/g0mTKNgSGXo14hYqp2GN4bE7JzpAgpFeSX8Xu1psxlQ==", + "license": "MIT", + "dependencies": { + "@turf/flatten": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "polyclip-ts": "^0.16.8", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/distance": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/distance/-/distance-7.3.5.tgz", + "integrity": "sha512-uQAC63zg/l91KUxzfhqio7Ii3+UXTrPOVJScIdRj6EO6+9XHI4kC+AdyIS4cPAv14sZfJLIBxzMnzcGrss+kEA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/distance-weight": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/distance-weight/-/distance-weight-7.3.5.tgz", + "integrity": "sha512-GpV2h5ZkbWMdUFe5BWm9lfeLFMnYR8CRj6HiguZBLesarSub6I0UNO1u8UhkRGi26YLGnFlBh7c4KyaakNx1Gg==", + "license": "MIT", + "dependencies": { + "@turf/centroid": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/ellipse": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/ellipse/-/ellipse-7.3.5.tgz", + "integrity": "sha512-C478LrdvUkjwIVGN6PoYsFp27PuT+W2IH4ZOVt9sd4359hRPFhJ2m+f8jSPfS6rdamdvc/O+h7vNmOIBRP/TeA==", + "license": "MIT", + "dependencies": { + "@turf/destination": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/transform-rotate": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/envelope": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/envelope/-/envelope-7.3.5.tgz", + "integrity": "sha512-0Sc2AVx0JZ3MaQ0k6+khplU3wO7bwc1qAQ6Fd+Q4RhIVPY2JKstBdq5ftU1T/BHNf8KK+9y4qbSV2u8hnw/PqA==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/bbox-polygon": "7.3.5", + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/explode": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/explode/-/explode-7.3.5.tgz", + "integrity": "sha512-Qdd7ehX5AF0DdpJl+JJyxws7jEmsZBRV35wTm+Lyhapuc3yLHU7tN5EqJ+2lVV7RkUgBXEFQV+34pmPLPGQn+w==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/flatten": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/flatten/-/flatten-7.3.5.tgz", + "integrity": "sha512-4dDAyoY8wf4UCIJ2lH3JbypmEeqyuRFExHEPu6eJeaOybdpOV9kn3LqB0lsWArizFjJWQNS+0qpv08jD85jSPg==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/flip": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/flip/-/flip-7.3.5.tgz", + "integrity": "sha512-qDSBFqo5+8yE5gfBCsQZxgj0bGRx6abQg6TgYvg1wvYYHtUJL/0VS+QdDTmxZiYm8N46uNAv9pKvun9MGK+elA==", + "license": "MIT", + "dependencies": { + "@turf/clone": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/geojson-rbush": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/geojson-rbush/-/geojson-rbush-7.3.5.tgz", + "integrity": "sha512-30/hQqc+ErnlcavvDdxGfgm8VtsJDEzSYpf3mPqYxOyI976l49T6+1jCQD5xKswml6o8zZAaTSe6ZcSKF+SCNw==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/great-circle": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/great-circle/-/great-circle-7.3.5.tgz", + "integrity": "sha512-VAio6hwPJIheSzrvsMkLDMHkCfHyOi4H4r1Y2ynb2oMiGiqZjkQ7jIFlRYBcTyO2RnwEOgwM/d3kwRImAwMVBA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "arc": "^0.2.0", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/helpers": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/helpers/-/helpers-7.3.5.tgz", + "integrity": "sha512-E/NMGV5MwbjjP7AJXBtsanC3yY8N2MQ87IGdIgkB2ji5AtBpwnH4L3gEqpYN4RlCJJWbLbzO91BbKv2waUd0eg==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/hex-grid": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/hex-grid/-/hex-grid-7.3.5.tgz", + "integrity": "sha512-sPtYXqbNvUxt8h4NzspcoFAVotd/75LgrLxxI84LGIVPCN+fsK1uWwr4a6MAlzfSbWbOYOq7OSWMSSXzHoQzJg==", + "license": "MIT", + "dependencies": { + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/intersect": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/interpolate": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/interpolate/-/interpolate-7.3.5.tgz", + "integrity": "sha512-rl5LwK85etpvbSW1VEXp/I85kzgiGviXInrvvhQxzEF9xGKvs1ed/6dc1uy1LsczSr4wUnbdGATzZTF9lFYjIw==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/centroid": "7.3.5", + "@turf/clone": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/hex-grid": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/point-grid": "7.3.5", + "@turf/square-grid": "7.3.5", + "@turf/triangle-grid": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/intersect": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/intersect/-/intersect-7.3.5.tgz", + "integrity": "sha512-v11Do9ySbsE08ffiwboQeFKvYByyxzvAz0ls837A9T3rSC+8vKMmK815S+C5v8CBMLNhuBCSgqnOIV3zonNICQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "polyclip-ts": "^0.16.8", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/invariant": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/invariant/-/invariant-7.3.5.tgz", + "integrity": "sha512-ZVIvsBvjr8lO7WxC5zYNjRsjSDvyGvWkJMjuWaJjTU8x+1tmfNnw3gDX/TI2Sit83gcRYLYkNo23lB/udqx/Hg==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/isobands": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/isobands/-/isobands-7.3.5.tgz", + "integrity": "sha512-WX6vpPkM8O8SY7hsijOtj4owVXP24nU33Q0eMhWdZ+YiDmAHgEOQcDhPJLvp0mIbyYj81mU73hdnilf3q9tk/A==", + "license": "MIT", + "dependencies": { + "@turf/area": "7.3.5", + "@turf/bbox": "7.3.5", + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/explode": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/isolines": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/isolines/-/isolines-7.3.5.tgz", + "integrity": "sha512-n5QUX1/Z/PuPVpTUrKhYcKF95L5+nKF8hWznYtG/GsiMXfRqMeAEjTCqgKIgF8T65H4LrvcpLyq8VPQSi7aISw==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/jsts": { + "version": "2.7.2", + "resolved": "http://mirrors.tencentyun.com/npm/@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.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/kinks/-/kinks-7.3.5.tgz", + "integrity": "sha512-dPW8d4vs1v8WMobjyq/TVqajjPwkMsl94IF58yp1UYlmJDQrW4iNRUmI9fFzww+fl7epCKNwY+jZhXf1DRi93w==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/length": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/length/-/length-7.3.5.tgz", + "integrity": "sha512-Bi+vEP54wt1ly3BRcCOP0nd2kGTYEhGk6haQxTpkrqr3XtmqDh8c3NowSgseN2cegIZRjwCOEC8eSsZ0JemJdA==", + "license": "MIT", + "dependencies": { + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-arc": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/line-arc/-/line-arc-7.3.5.tgz", + "integrity": "sha512-XrPicIoN7XCtiJ7e7ELje7GjMZrBw/nuJnz0mQoCwwHwmX8Oz9oRfb6uaiS8NeR4WBzUVdkmVR/ro0kW4lypog==", + "license": "MIT", + "dependencies": { + "@turf/circle": "7.3.5", + "@turf/destination": "7.3.5", + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-chunk": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/line-chunk/-/line-chunk-7.3.5.tgz", + "integrity": "sha512-z5/EBv79oyNXMYFpFIsA9gw/7TAKoJ9a/Ijo/jBeO47Fr1mV3JLtE3aB2i/nqLTYZWMU7K3Lnzwqt2Rn5Gri/Q==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/length": "7.3.5", + "@turf/line-slice-along": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-intersect": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/line-intersect/-/line-intersect-7.3.5.tgz", + "integrity": "sha512-2Cl4oPsjaDdfIwz/5IRDdG2fNdfp3W6atICm81vnzl/GwURoVP+CLjXJ64QWWzpzIbgX2XprJQTmamByDt5MDw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "sweepline-intersections": "^1.5.0", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-offset": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/line-offset/-/line-offset-7.3.5.tgz", + "integrity": "sha512-7tNI+4xKFOTQj720aJI7vuRMyTC+4hAqd7N8AnnZ0EpzH+sBfyrt8rNI/Vf3+d/iY0c9ZNbhU9Qhyb0ckJUdsA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-overlap": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/line-overlap/-/line-overlap-7.3.5.tgz", + "integrity": "sha512-7lZMWYHuzM6EMlL5pIIi/Nh7GLsM7ilW8/jVyHP1yGfQ0c0YAUoJd/Xy3J2+9v8OkYiZW/t2LdwVoTmCEJLWxg==", + "license": "MIT", + "dependencies": { + "@turf/boolean-point-on-line": "7.3.5", + "@turf/geojson-rbush": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/line-segment": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/nearest-point-on-line": "7.3.5", + "@types/geojson": "^7946.0.10", + "fast-deep-equal": "^3.1.3", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-segment": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/line-segment/-/line-segment-7.3.5.tgz", + "integrity": "sha512-TM1aCu7utM6fllAEHO8PNqBJZ/uoFJVNp2A0YI7FyWN928hPbacsvNtLeVz/Kq1ZbeqQ1ZIKRxo9FdVjaj8hGg==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-slice": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/line-slice/-/line-slice-7.3.5.tgz", + "integrity": "sha512-BGw5N4UvjH691J/z1P2S+hWBgCcvbl2/HXaqGvKTijXw5i1vzsZ9m07wLl/qH+i38OJDRMJ/+FkNZnrKpsoXLw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/nearest-point-on-line": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-slice-along": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/line-slice-along/-/line-slice-along-7.3.5.tgz", + "integrity": "sha512-zLOU9mGFXJdbPvA3/zXpDsBmXY2paA7eD6/p0iYiP9OASYO0GDcarwY5K/E0uuEdLrMf8G8YA2cJDcEl9gRgFw==", + "license": "MIT", + "dependencies": { + "@turf/bearing": "7.3.5", + "@turf/destination": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-split": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/line-split/-/line-split-7.3.5.tgz", + "integrity": "sha512-GEuy+LdbbaqtYjHk/i1G8sK51wfCdPqTO8uH0dJZ6WlcIcZQfRcKKI4ksFm7NkVyfmw8gXWbpMJD8lO380GFBQ==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/geojson-rbush": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/line-intersect": "7.3.5", + "@turf/line-segment": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/nearest-point-on-line": "7.3.5", + "@turf/truncate": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-to-polygon": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/line-to-polygon/-/line-to-polygon-7.3.5.tgz", + "integrity": "sha512-PNWDN1B0nJRlgA4DAXeYEf53OZSWwsu/rtDB4wxe/1NwfM9zlDVElQ/mtgDPtZpwC2aDKV5+B0vTXfKR/MMIfg==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/clone": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/mask": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/mask/-/mask-7.3.5.tgz", + "integrity": "sha512-zs9bBtdANOsSkG7xiLFYforeI2nszXu0QwPv3vkaX747oEVdcyd0nSW81aQRmSWw/fvhXja++8duIVXOIYr4ng==", + "license": "MIT", + "dependencies": { + "@turf/clone": "7.3.5", + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "polyclip-ts": "^0.16.8", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/meta": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/meta/-/meta-7.3.5.tgz", + "integrity": "sha512-r+ohqxoyqeigFB0oFrQx/YEHIkOKqcKpCjvZkvZs7Tkv+IFco5MezAd2zd4rzK+0DfFgDP3KpJc7HqrYjvEjhg==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/midpoint": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/midpoint/-/midpoint-7.3.5.tgz", + "integrity": "sha512-y92O2YDDBkZp7jAUuUPgof/HiXHjJSkKjEtQRjWXZcjTlzHd/Fqg6/twarY2wNkENK2EuaaiV9MDy74FeRG2Ow==", + "license": "MIT", + "dependencies": { + "@turf/bearing": "7.3.5", + "@turf/destination": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/moran-index": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/moran-index/-/moran-index-7.3.5.tgz", + "integrity": "sha512-l/FgZkgPzwAsdj7rtKYWv2rxeTy+Tv8NMk6qSEwKqB4eHqn1TYHcTASWRcZIyipH4LtOJJOl77n7FmKcaDBtSg==", + "license": "MIT", + "dependencies": { + "@turf/distance-weight": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-neighbor-analysis": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/nearest-neighbor-analysis/-/nearest-neighbor-analysis-7.3.5.tgz", + "integrity": "sha512-6vnSqt7OH8zTPdvUxCYnnN86Ci8VS5G3q2G1UrAcrnjTH7DbJ4KvIkRQlv4y6hj53G+bm9cA6TjeJuyP2jAOcg==", + "license": "MIT", + "dependencies": { + "@turf/area": "7.3.5", + "@turf/bbox": "7.3.5", + "@turf/bbox-polygon": "7.3.5", + "@turf/centroid": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/nearest-point": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-point": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/nearest-point/-/nearest-point-7.3.5.tgz", + "integrity": "sha512-qcsbj9fo5CYhGeIDaJORoqiZyjNGu2+Te31MVaFoTTxqqkXypxp9e6HJGvUi2zPd1Zk3oAWXhvm1a+UXw2G56w==", + "license": "MIT", + "dependencies": { + "@turf/clone": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@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.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/nearest-point-on-line/-/nearest-point-on-line-7.3.5.tgz", + "integrity": "sha512-MZn6OkEFZpjS6BNUANfqiHMIbQSivu7TNji3a+OAIrnPJ71vp8cbz0N2aVEa5M7I8ipvxoxAPIV3eqg3h280Vg==", + "license": "MIT", + "dependencies": { + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-point-to-line": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/nearest-point-to-line/-/nearest-point-to-line-7.3.5.tgz", + "integrity": "sha512-O27A9dFAqDYBRPhhoLP82Da7Q6rd0fXRR/jwQcBiycjTGdsXJmzxywuR08aDvWiARbJAmohEzdYzk4f9/eWXhA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/point-to-line-distance": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/planepoint": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/planepoint/-/planepoint-7.3.5.tgz", + "integrity": "sha512-+hjECX1hDbol8psuG6iYSwcZHQ+RPJqFIBh3pXKc/pa0cdjZyB/L6q1d8ahnFrQBEpuoO3XVvo2hHN49VOEPjw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/point-grid": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/point-grid/-/point-grid-7.3.5.tgz", + "integrity": "sha512-aEPnqj/4C9ejNz4uCJKgk6Flux6SxnqxjQHAYPIP5C7ooAB1xRAT1NMnCzxUjjUq1SMtgdZ6skoNfvKNK4Rzrw==", + "license": "MIT", + "dependencies": { + "@turf/boolean-within": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/point-on-feature": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/point-on-feature/-/point-on-feature-7.3.5.tgz", + "integrity": "sha512-Y7W+JZJCmm9Qq93NHpk4dVhzAtAk2Uyau2Uk1ttCJ2Jsnuu4dwSjOurpmgDmMUe7yPmzihAUYhMFDumpAja8ZA==", + "license": "MIT", + "dependencies": { + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/center": "7.3.5", + "@turf/explode": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/nearest-point": "7.3.5", + "@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.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/point-to-line-distance/-/point-to-line-distance-7.3.5.tgz", + "integrity": "sha512-mR1NAIX+JfpYAJQ9u3gpIV37QzYvBOefDP+/16uBCAOM8Fp12goT8l7WdenT0dvB4wPibbqM2+2kyEl5u9XJog==", + "license": "MIT", + "dependencies": { + "@turf/bearing": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/nearest-point-on-line": "7.3.5", + "@turf/projection": "7.3.5", + "@turf/rhumb-bearing": "7.3.5", + "@turf/rhumb-distance": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/point-to-polygon-distance": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/point-to-polygon-distance/-/point-to-polygon-distance-7.3.5.tgz", + "integrity": "sha512-SQPhAlfiuCkIIFos/OPCxtt8iR3BlZqGKzKXLYqt6z8iaICaf2SjMyn4Zsr1oFO+Gy2K1rqandR+kuLTIo8Eqg==", + "license": "MIT", + "dependencies": { + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/point-to-line-distance": "7.3.5", + "@turf/polygon-to-line": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/points-within-polygon": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/points-within-polygon/-/points-within-polygon-7.3.5.tgz", + "integrity": "sha512-TRyVY5Xlx6j72sNIyBaHZNgTbILs2iUDevX5lnCFTiThkzp25BIBBQ77tv2VPilYH+v7+9/0T/pLO37SaVhsQw==", + "license": "MIT", + "dependencies": { + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygon-smooth": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/polygon-smooth/-/polygon-smooth-7.3.5.tgz", + "integrity": "sha512-dc/dlYFqVBcel6d5HM5tBANh1HfWbJ89lSVLR7YhRX+Y/UABTvbtJCWwxBBiFxFBeRmW7B45nv3jytHUYxQUOA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygon-tangents": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/polygon-tangents/-/polygon-tangents-7.3.5.tgz", + "integrity": "sha512-3/TtCQlXc2Lrgzb+LjwqbtILWan7lRD6P9Nn3edm2xGAZw5WY17+yZfpeySJPfcZhOWten9dXkOwDvSZF5uyWQ==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/boolean-within": "7.3.5", + "@turf/explode": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/nearest-point": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygon-to-line": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/polygon-to-line/-/polygon-to-line-7.3.5.tgz", + "integrity": "sha512-Mat5tvJcW3grpXCNFcMvjHL3d8hO4eoIgF3qYpXj25BHx/S7SJUOgyCV5x3arC0rCfM/cB71VmNDm9k57ec7bw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygonize": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/polygonize/-/polygonize-7.3.5.tgz", + "integrity": "sha512-pD3Zv/392sLlZVKRGUrJ4CKLN/Im+TO6wMCOfm/uiq4F9pEL5R+HPvXTcwEyxbhEPKYn3cylGKt21Wq0OfNQDQ==", + "license": "MIT", + "dependencies": { + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/envelope": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/projection": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/projection/-/projection-7.3.5.tgz", + "integrity": "sha512-G4bejYKT0vCQZryMhEoS9aLmP7ThDg6nb3zi3wPzELiTrGNOd2YgkWVheQDGCk4hcqEIWZc9fI2alaRSSkkLVw==", + "license": "MIT", + "dependencies": { + "@turf/clone": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/quadrat-analysis": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/quadrat-analysis/-/quadrat-analysis-7.3.5.tgz", + "integrity": "sha512-e5Am3cJuiP43f89Xv7n9cv3Z4P0I17zBvQPvhj6UowpRbiYoD4TKHfOr2PWHLYUkXjQ+vKY5CwiWvCYbfj3BIg==", + "license": "MIT", + "dependencies": { + "@turf/area": "7.3.5", + "@turf/bbox": "7.3.5", + "@turf/bbox-polygon": "7.3.5", + "@turf/centroid": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/point-grid": "7.3.5", + "@turf/random": "7.3.5", + "@turf/square-grid": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/random": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/random/-/random-7.3.5.tgz", + "integrity": "sha512-Fid43jfmQpvrpr/wrUaW9hr66ukPqfZPuwzEt3gfCx6mAVpFWbCPx2yRuVlLNiRkMgmKTphFfh6267UCPOSnCg==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rectangle-grid": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/rectangle-grid/-/rectangle-grid-7.3.5.tgz", + "integrity": "sha512-SVtXOJIz7FYaRUinxb0HfE/GNSJU6eU9tlKQaERDo/vG7wjPoTCDvnH8p4BdE5GRdXZMjvBUhtNdMj+M3rGRjQ==", + "license": "MIT", + "dependencies": { + "@turf/boolean-intersects": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rewind": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/rewind/-/rewind-7.3.5.tgz", + "integrity": "sha512-4AZdDh55JeCoKWLS5AC6MuXqAvoqSpj2WigtowtA3JIJ/1J4SclRrV6BGq/Xemwm5yKtRePHazBVUmG5uU75og==", + "license": "MIT", + "dependencies": { + "@turf/boolean-clockwise": "7.3.5", + "@turf/clone": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-bearing": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/rhumb-bearing/-/rhumb-bearing-7.3.5.tgz", + "integrity": "sha512-pYjBAuQTND0+6Y+v+zlQ7Y68SGjP4iG8qJ5QKjFRbB/yeorTY3m9yiXIN4lSyno3TPzEgBeNULuo26H6ygDyng==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-destination": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/rhumb-destination/-/rhumb-destination-7.3.5.tgz", + "integrity": "sha512-znICdPBtZq5EKh/Qu0TkiMyNhqiYfM2VUlFOWa7iegCWe1E+X7q/f6rlZ5TcmYVyLZ95XZ6eciDNmgVmpHVWaw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-distance": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/rhumb-distance/-/rhumb-distance-7.3.5.tgz", + "integrity": "sha512-dBFxmKrjRaAdwc4SCmGyAS2BDPCH35IBNl++Ypd1RB8JR2D3khl3zrTvxrlJ5qoN1WDvyPbvDYCrt2UnTX+8Nw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/sample": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/sample/-/sample-7.3.5.tgz", + "integrity": "sha512-ayl/QlDAkqIDJjbzcBeAsMzFmIDanQP4xXdNKZmnYg83FhvH/Sgu7mMNNhrYwCVMWrmOicviDHu3xKuJ6jVnMA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/sector": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/sector/-/sector-7.3.5.tgz", + "integrity": "sha512-9mtBorGPZfbZI2MoI0nkN5ogmbCz/NLpHdEM0UwwWiOW430iPhwZ649DXH32lDGerfzREX10vpamX8v1P9YVrw==", + "license": "MIT", + "dependencies": { + "@turf/circle": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/line-arc": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/shortest-path": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/shortest-path/-/shortest-path-7.3.5.tgz", + "integrity": "sha512-RmrfdDVTuBsHDNr88tGMRmIdJNFTdna3nQWRF8yFsgKR9LhZ4MWqebL24eQFn2hkyclL7O6lyPpOEJJtQxvcDw==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/bbox-polygon": "7.3.5", + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/clean-coords": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/transform-scale": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/simplify": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/simplify/-/simplify-7.3.5.tgz", + "integrity": "sha512-9wzxlRA+0yNALeqyXNHFgj+8ebsg2aKdMrWRiSMS+ZqbiknZ/mCARiDYqM2Qz8TgTqdrNt53ze4o1vS6WeJrJw==", + "license": "MIT", + "dependencies": { + "@turf/clean-coords": "7.3.5", + "@turf/clone": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/square": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/square/-/square-7.3.5.tgz", + "integrity": "sha512-zUh9cxlZ4bPkSK2XynY26JSLDVy8oUss94mXACqSGrGjv308q3Voj4dzvfeh0E/Q3PQ3D8GJRZECXdCB/PU78Q==", + "license": "MIT", + "dependencies": { + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/square-grid": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/square-grid/-/square-grid-7.3.5.tgz", + "integrity": "sha512-mcwefBumsO3nwRG4nPfmXsq7YqHOsa71Z3h4JwWQn/XOrhV/8l1/QX3IAIx1qUWC2RqRMOImt3et5mlc+g2SxQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/rectangle-grid": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/standard-deviational-ellipse": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/standard-deviational-ellipse/-/standard-deviational-ellipse-7.3.5.tgz", + "integrity": "sha512-CIJaQ61bjmxxqi5CpRLWAwxnbeHcG6e7esK2IX2DXBIE/7p/F7Sk9F2GOAL6vt1o29GnmzU2APHZvTX/YKcLbw==", + "license": "MIT", + "dependencies": { + "@turf/center-mean": "7.3.5", + "@turf/ellipse": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/points-within-polygon": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/tag": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/tag/-/tag-7.3.5.tgz", + "integrity": "sha512-jwLOP7ZFfOcMPbK+0puT0SMOs0urSKYSYax7G4LDtZ9oPFAicVJtr2K0OB/rgmdoTK4VfUwb2nVZUdYAVnXtAw==", + "license": "MIT", + "dependencies": { + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/clone": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/tesselate": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/tesselate/-/tesselate-7.3.5.tgz", + "integrity": "sha512-MI+pSkehJyZmbl2L5/43B9DlD6MEDcr63pW/LDSXYRDoRUXtSGY/NAAibIQ0gMAr8VxsimGCZKSuGMNUZdsuRQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "earcut": "^2.2.4", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/tesselate/node_modules/earcut": { + "version": "2.2.4", + "resolved": "http://mirrors.tencentyun.com/npm/earcut/-/earcut-2.2.4.tgz", + "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", + "license": "ISC" + }, + "node_modules/@turf/tin": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/tin/-/tin-7.3.5.tgz", + "integrity": "sha512-70747SmLQttt+ywq+NmMqmkHdXsinO57SjHNFKX6G6qHuvxUu48vN7Kf3zjkqGAp2kQnu38OOqB4QPus6RdUqw==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-rotate": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/transform-rotate/-/transform-rotate-7.3.5.tgz", + "integrity": "sha512-WXkteI0DihwCukZesVXVVYpsoyftYoiBtq1b+u1Dz4HyATK25zfEeWChlgRtApbiePF6uqG7bSQS+K8vjC4c0A==", + "license": "MIT", + "dependencies": { + "@turf/centroid": "7.3.5", + "@turf/clone": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/rhumb-bearing": "7.3.5", + "@turf/rhumb-destination": "7.3.5", + "@turf/rhumb-distance": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-scale": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/transform-scale/-/transform-scale-7.3.5.tgz", + "integrity": "sha512-eAmey/LtJVT6WlCMULsnd+sCAOwCezG6lVP67qN5HARZ8ft+b7yBiU4FC+IGXbVsrdRcCRLSzoQc6K0fROoo2Q==", + "license": "MIT", + "dependencies": { + "@turf/bbox": "7.3.5", + "@turf/center": "7.3.5", + "@turf/centroid": "7.3.5", + "@turf/clone": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/rhumb-bearing": "7.3.5", + "@turf/rhumb-destination": "7.3.5", + "@turf/rhumb-distance": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-translate": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/transform-translate/-/transform-translate-7.3.5.tgz", + "integrity": "sha512-OMQLOFLIjqeDNARaa2kdh1AgvWKFgq41/I6k3CAaj1UcB4javpVFMlcjRJY+pL2oZtMRZRcUZxhO+zSNl6p83Q==", + "license": "MIT", + "dependencies": { + "@turf/clone": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/rhumb-destination": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/triangle-grid": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/triangle-grid/-/triangle-grid-7.3.5.tgz", + "integrity": "sha512-oiwtTm+yqZwuODOSEyLSQSFaZFyjC6kgftUFFW6kLGQtm+Fw1GjxwS7QjiY55GRWxgfgbg2l1iNZNgfsCiPQWA==", + "license": "MIT", + "dependencies": { + "@turf/distance": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/intersect": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/truncate": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/truncate/-/truncate-7.3.5.tgz", + "integrity": "sha512-Qx2iv3KIqKuDAUduMfaJ5fFegEWBeRve5zePalRevS16bMUqEX+jnKPK9fWGyUuPqT61qP1Kybz0PTWPbUbljQ==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/turf": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/turf/-/turf-7.3.5.tgz", + "integrity": "sha512-l5Z1ZFEizN9p5GxX3mzUGf+i4t7AP3YpWcNdf9+kIzJcQD3eYuGBabj2hLrfrluqFJ+uxsuo4RgPtortQ9Dwpg==", + "license": "MIT", + "dependencies": { + "@turf/along": "7.3.5", + "@turf/angle": "7.3.5", + "@turf/area": "7.3.5", + "@turf/bbox": "7.3.5", + "@turf/bbox-clip": "7.3.5", + "@turf/bbox-polygon": "7.3.5", + "@turf/bearing": "7.3.5", + "@turf/bezier-spline": "7.3.5", + "@turf/boolean-clockwise": "7.3.5", + "@turf/boolean-concave": "7.3.5", + "@turf/boolean-contains": "7.3.5", + "@turf/boolean-crosses": "7.3.5", + "@turf/boolean-disjoint": "7.3.5", + "@turf/boolean-equal": "7.3.5", + "@turf/boolean-intersects": "7.3.5", + "@turf/boolean-overlap": "7.3.5", + "@turf/boolean-parallel": "7.3.5", + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/boolean-point-on-line": "7.3.5", + "@turf/boolean-touches": "7.3.5", + "@turf/boolean-valid": "7.3.5", + "@turf/boolean-within": "7.3.5", + "@turf/buffer": "7.3.5", + "@turf/center": "7.3.5", + "@turf/center-mean": "7.3.5", + "@turf/center-median": "7.3.5", + "@turf/center-of-mass": "7.3.5", + "@turf/centroid": "7.3.5", + "@turf/circle": "7.3.5", + "@turf/clean-coords": "7.3.5", + "@turf/clone": "7.3.5", + "@turf/clusters": "7.3.5", + "@turf/clusters-dbscan": "7.3.5", + "@turf/clusters-kmeans": "7.3.5", + "@turf/collect": "7.3.5", + "@turf/combine": "7.3.5", + "@turf/concave": "7.3.5", + "@turf/convex": "7.3.5", + "@turf/destination": "7.3.5", + "@turf/difference": "7.3.5", + "@turf/directional-mean": "7.3.5", + "@turf/dissolve": "7.3.5", + "@turf/distance": "7.3.5", + "@turf/distance-weight": "7.3.5", + "@turf/ellipse": "7.3.5", + "@turf/envelope": "7.3.5", + "@turf/explode": "7.3.5", + "@turf/flatten": "7.3.5", + "@turf/flip": "7.3.5", + "@turf/geojson-rbush": "7.3.5", + "@turf/great-circle": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/hex-grid": "7.3.5", + "@turf/interpolate": "7.3.5", + "@turf/intersect": "7.3.5", + "@turf/invariant": "7.3.5", + "@turf/isobands": "7.3.5", + "@turf/isolines": "7.3.5", + "@turf/kinks": "7.3.5", + "@turf/length": "7.3.5", + "@turf/line-arc": "7.3.5", + "@turf/line-chunk": "7.3.5", + "@turf/line-intersect": "7.3.5", + "@turf/line-offset": "7.3.5", + "@turf/line-overlap": "7.3.5", + "@turf/line-segment": "7.3.5", + "@turf/line-slice": "7.3.5", + "@turf/line-slice-along": "7.3.5", + "@turf/line-split": "7.3.5", + "@turf/line-to-polygon": "7.3.5", + "@turf/mask": "7.3.5", + "@turf/meta": "7.3.5", + "@turf/midpoint": "7.3.5", + "@turf/moran-index": "7.3.5", + "@turf/nearest-neighbor-analysis": "7.3.5", + "@turf/nearest-point": "7.3.5", + "@turf/nearest-point-on-line": "7.3.5", + "@turf/nearest-point-to-line": "7.3.5", + "@turf/planepoint": "7.3.5", + "@turf/point-grid": "7.3.5", + "@turf/point-on-feature": "7.3.5", + "@turf/point-to-line-distance": "7.3.5", + "@turf/point-to-polygon-distance": "7.3.5", + "@turf/points-within-polygon": "7.3.5", + "@turf/polygon-smooth": "7.3.5", + "@turf/polygon-tangents": "7.3.5", + "@turf/polygon-to-line": "7.3.5", + "@turf/polygonize": "7.3.5", + "@turf/projection": "7.3.5", + "@turf/quadrat-analysis": "7.3.5", + "@turf/random": "7.3.5", + "@turf/rectangle-grid": "7.3.5", + "@turf/rewind": "7.3.5", + "@turf/rhumb-bearing": "7.3.5", + "@turf/rhumb-destination": "7.3.5", + "@turf/rhumb-distance": "7.3.5", + "@turf/sample": "7.3.5", + "@turf/sector": "7.3.5", + "@turf/shortest-path": "7.3.5", + "@turf/simplify": "7.3.5", + "@turf/square": "7.3.5", + "@turf/square-grid": "7.3.5", + "@turf/standard-deviational-ellipse": "7.3.5", + "@turf/tag": "7.3.5", + "@turf/tesselate": "7.3.5", + "@turf/tin": "7.3.5", + "@turf/transform-rotate": "7.3.5", + "@turf/transform-scale": "7.3.5", + "@turf/transform-translate": "7.3.5", + "@turf/triangle-grid": "7.3.5", + "@turf/truncate": "7.3.5", + "@turf/union": "7.3.5", + "@turf/unkink-polygon": "7.3.5", + "@turf/voronoi": "7.3.5", + "@types/geojson": "^7946.0.10", + "@types/kdbush": "^3.0.5", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/union": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/union/-/union-7.3.5.tgz", + "integrity": "sha512-/FSKhl+LX4+M7L/Trmiln0CDPWS8vCneGnQktt1o5XbCY/zIpH1JdxHEBFXhFZg4beAyXCz0uuxRyW9N/DH+KA==", + "license": "MIT", + "dependencies": { + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "polyclip-ts": "^0.16.8", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/unkink-polygon": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/unkink-polygon/-/unkink-polygon-7.3.5.tgz", + "integrity": "sha512-7MwKCm7sPHVF4xBO/3s08/DtA/09UEBXaLNnm8/RUq3abS5zZ9PnakLsd36J18IHDscM6RmH7IZPLSwYh4TLcQ==", + "license": "MIT", + "dependencies": { + "@turf/area": "7.3.5", + "@turf/boolean-point-in-polygon": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/meta": "7.3.5", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/voronoi": { + "version": "7.3.5", + "resolved": "http://mirrors.tencentyun.com/npm/@turf/voronoi/-/voronoi-7.3.5.tgz", + "integrity": "sha512-v51D9H+er/K5lP+rBs7jIBEXTFhl0FQOZn4mfhb7brN5sGGDmnfEFOaxIYOiJN4Qco1GtFD2Tq0NgZ8+dmJmEA==", + "license": "MIT", + "dependencies": { + "@turf/clone": "7.3.5", + "@turf/helpers": "7.3.5", + "@turf/invariant": "7.3.5", + "@types/d3-voronoi": "^1.1.12", + "@types/geojson": "^7946.0.10", + "d3-voronoi": "1.1.2", + "tslib": "^2.8.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/d3-voronoi": { + "version": "1.1.12", + "resolved": "http://mirrors.tencentyun.com/npm/@types/d3-voronoi/-/d3-voronoi-1.1.12.tgz", + "integrity": "sha512-DauBl25PKZZ0WVJr42a6CNvI6efsdzofl9sajqZr2Gf5Gu733WkDdUGiPkUHXiUvYGzNNlFQde2wdZdfQPG+yw==", + "license": "MIT" + }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "http://mirrors.tencentyun.com/npm/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "license": "MIT" + }, + "node_modules/@types/kdbush": { + "version": "3.0.5", + "resolved": "http://mirrors.tencentyun.com/npm/@types/kdbush/-/kdbush-3.0.5.tgz", + "integrity": "sha512-tdJz7jaWFu4nR+8b2B+CdPZ6811ighYylWsu2hpsivapzW058yP0KdfZuNY89IiRe5jbKvBGXN3LQdN2KPXVdQ==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.13.2", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@vant/popperjs": { + "version": "1.3.0", + "resolved": "http://mirrors.tencentyun.com/npm/@vant/popperjs/-/popperjs-1.3.0.tgz", + "integrity": "sha512-hB+czUG+aHtjhaEmCJDuXOep0YTZjdlRR+4MSmIFnkCQIxJaXLQdSsR90XWvAI2yvKUI7TCGqR8pQg2RtvkMHw==", + "license": "MIT" + }, + "node_modules/@vant/use": { + "version": "1.6.0", + "resolved": "http://mirrors.tencentyun.com/npm/@vant/use/-/use-1.6.0.tgz", + "integrity": "sha512-PHHxeAASgiOpSmMjceweIrv2AxDZIkWXyaczksMoWvKV2YAYEhoizRuk/xFnKF+emUIi46TsQ+rvlm/t2BBCfA==", + "license": "MIT", + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.28", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.28" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.28", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.28", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.38", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/shared": "3.5.38", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.38", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.38", + "@vue/shared": "3.5.38" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.38", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/compiler-core": "3.5.38", + "@vue/compiler-dom": "3.5.38", + "@vue/compiler-ssr": "3.5.38", + "@vue/shared": "3.5.38", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.15", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.38", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.38", + "@vue/shared": "3.5.38" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "http://mirrors.tencentyun.com/npm/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "http://mirrors.tencentyun.com/npm/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "http://mirrors.tencentyun.com/npm/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/language-core": { + "version": "3.3.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.2.0", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "picomatch": "^4.0.4" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.38", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.38" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.38", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.38", + "@vue/shared": "3.5.38" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.38", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.38", + "@vue/runtime-core": "3.5.38", + "@vue/shared": "3.5.38", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.38", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.38", + "@vue/shared": "3.5.38" + }, + "peerDependencies": { + "vue": "3.5.38" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.38", + "license": "MIT" + }, + "node_modules/@vue/tsconfig": { + "version": "0.9.1", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">= 5.8", + "vue": "^3.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "http://mirrors.tencentyun.com/npm/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/alien-signals": { + "version": "3.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/arc": { + "version": "0.2.0", + "resolved": "http://mirrors.tencentyun.com/npm/arc/-/arc-0.2.0.tgz", + "integrity": "sha512-8NFOo126uYKQJyXNSLY/jSklgfLQL+XWAcPXGo876JwEQ8nSOPXWNI3TV2jLZMN8QEw8uksJ1ZwS4npjBca8MA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "http://mirrors.tencentyun.com/npm/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.18.0", + "resolved": "http://mirrors.tencentyun.com/npm/axios/-/axios-1.18.0.tgz", + "integrity": "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "http://mirrors.tencentyun.com/npm/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "http://mirrors.tencentyun.com/npm/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "http://mirrors.tencentyun.com/npm/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "http://mirrors.tencentyun.com/npm/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/colorjs.io": { + "version": "0.5.2", + "resolved": "http://mirrors.tencentyun.com/npm/colorjs.io/-/colorjs.io-0.5.2.tgz", + "integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "http://mirrors.tencentyun.com/npm/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "http://mirrors.tencentyun.com/npm/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/concaveman": { + "version": "1.2.1", + "resolved": "http://mirrors.tencentyun.com/npm/concaveman/-/concaveman-1.2.1.tgz", + "integrity": "sha512-PwZYKaM/ckQSa8peP5JpVr7IMJ4Nn/MHIaWUjP4be+KoZ7Botgs8seAZGpmaOM+UZXawcdYRao/px9ycrCihHw==", + "license": "ISC", + "dependencies": { + "point-in-polygon": "^1.1.0", + "rbush": "^3.0.1", + "robust-predicates": "^2.0.4", + "tinyqueue": "^2.0.3" + } + }, + "node_modules/concaveman/node_modules/tinyqueue": { + "version": "2.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/tinyqueue/-/tinyqueue-2.0.3.tgz", + "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==", + "license": "ISC" + }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "http://mirrors.tencentyun.com/npm/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "http://mirrors.tencentyun.com/npm/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "license": "MIT" + }, + "node_modules/d3-array": { + "version": "1.2.4", + "resolved": "http://mirrors.tencentyun.com/npm/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-geo": { + "version": "1.7.1", + "resolved": "http://mirrors.tencentyun.com/npm/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/d3-voronoi": { + "version": "1.1.2", + "resolved": "http://mirrors.tencentyun.com/npm/d3-voronoi/-/d3-voronoi-1.1.2.tgz", + "integrity": "sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw==", + "license": "BSD-3-Clause" + }, + "node_modules/dayjs": { + "version": "1.11.21", + "resolved": "http://mirrors.tencentyun.com/npm/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "http://mirrors.tencentyun.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "http://mirrors.tencentyun.com/npm/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "http://mirrors.tencentyun.com/npm/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/earcut": { + "version": "3.0.2", + "resolved": "http://mirrors.tencentyun.com/npm/earcut/-/earcut-3.0.2.tgz", + "integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==", + "license": "ISC" + }, + "node_modules/echarts": { + "version": "6.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/echarts/-/echarts-6.1.0.tgz", + "integrity": "sha512-q0yaFPggC9FUdsWH4blavRWFmxdrIodbkoKNAjJudAI6CA9gNPxHtV2RcZNEepZVlk4yvBYkOkbk6HIVpIyHZA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "2.3.0", + "zrender": "6.1.0" + } + }, + "node_modules/echarts/node_modules/tslib": { + "version": "2.3.0", + "resolved": "http://mirrors.tencentyun.com/npm/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + }, + "node_modules/encryptlong": { + "version": "3.1.4", + "resolved": "http://mirrors.tencentyun.com/npm/encryptlong/-/encryptlong-3.1.4.tgz", + "integrity": "sha512-nx+om7MXaSBSBPBNKKPrOWMot/C0L0Ru8dy9WTyjO5k8Wo+1hsnK0d8uX1UjctkgcgEWhkKhVScniYDjXvnKgw==", + "license": "MIT" + }, + "node_modules/entities": { + "version": "7.0.1", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "http://mirrors.tencentyun.com/npm/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "http://mirrors.tencentyun.com/npm/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "http://mirrors.tencentyun.com/npm/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "http://mirrors.tencentyun.com/npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "http://mirrors.tencentyun.com/npm/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "http://mirrors.tencentyun.com/npm/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "http://mirrors.tencentyun.com/npm/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/geojson-equality-ts": { + "version": "1.0.2", + "resolved": "http://mirrors.tencentyun.com/npm/geojson-equality-ts/-/geojson-equality-ts-1.0.2.tgz", + "integrity": "sha512-h3Ryq+0mCSN/7yLs0eDgrZhvc9af23o/QuC4aTiuuzP/MRCtd6mf5rLsLRY44jX0RPUfM8c4GqERQmlUxPGPoQ==", + "license": "MIT", + "dependencies": { + "@types/geojson": "^7946.0.14" + } + }, + "node_modules/geojson-polygon-self-intersections": { + "version": "1.2.2", + "resolved": "http://mirrors.tencentyun.com/npm/geojson-polygon-self-intersections/-/geojson-polygon-self-intersections-1.2.2.tgz", + "integrity": "sha512-6XRNF4CsRHYmR9z5YuIk5f/aOototnDf0dgMqYGcS7y1l57ttt6MAIAxl3rXyas6lq1HEbTuLMh4PgvO+OV42w==", + "license": "MIT", + "dependencies": { + "rbush": "^2.0.1" + } + }, + "node_modules/geojson-polygon-self-intersections/node_modules/quickselect": { + "version": "1.1.1", + "resolved": "http://mirrors.tencentyun.com/npm/quickselect/-/quickselect-1.1.1.tgz", + "integrity": "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ==", + "license": "ISC" + }, + "node_modules/geojson-polygon-self-intersections/node_modules/rbush": { + "version": "2.0.2", + "resolved": "http://mirrors.tencentyun.com/npm/rbush/-/rbush-2.0.2.tgz", + "integrity": "sha512-XBOuALcTm+O/H8G90b6pzu6nX6v2zCKiFG4BJho8a+bY6AER6t8uQUZdi5bomQc0AprCWhEGa7ncAbbRap0bRA==", + "license": "MIT", + "dependencies": { + "quickselect": "^1.0.1" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "http://mirrors.tencentyun.com/npm/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "http://mirrors.tencentyun.com/npm/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gl-matrix": { + "version": "3.4.4", + "resolved": "http://mirrors.tencentyun.com/npm/gl-matrix/-/gl-matrix-3.4.4.tgz", + "integrity": "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==", + "license": "MIT" + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "http://mirrors.tencentyun.com/npm/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "http://mirrors.tencentyun.com/npm/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "http://mirrors.tencentyun.com/npm/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "http://mirrors.tencentyun.com/npm/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "http://mirrors.tencentyun.com/npm/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "http://mirrors.tencentyun.com/npm/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/immutable": { + "version": "5.1.6", + "resolved": "http://mirrors.tencentyun.com/npm/immutable/-/immutable-5.1.6.tgz", + "integrity": "sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "http://mirrors.tencentyun.com/npm/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "http://mirrors.tencentyun.com/npm/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/json-stringify-pretty-compact": { + "version": "4.0.0", + "resolved": "http://mirrors.tencentyun.com/npm/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz", + "integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==", + "license": "MIT" + }, + "node_modules/jsts": { + "version": "2.7.1", + "resolved": "http://mirrors.tencentyun.com/npm/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/kdbush": { + "version": "4.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/kdbush/-/kdbush-4.1.0.tgz", + "integrity": "sha512-e9vurzrXJQrFX6ckpHP3bvj5l+9CnYzkxDNnNQ1h2QTqdWsUAJgXiKdGNcOa1EY85dU8KbQ+z/FdQdB7P+9yfQ==", + "license": "ISC" + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss/node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "http://mirrors.tencentyun.com/npm/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss/node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "http://mirrors.tencentyun.com/npm/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss/node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "http://mirrors.tencentyun.com/npm/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss/node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "http://mirrors.tencentyun.com/npm/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss/node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "http://mirrors.tencentyun.com/npm/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss/node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "http://mirrors.tencentyun.com/npm/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss/node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "http://mirrors.tencentyun.com/npm/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss/node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "http://mirrors.tencentyun.com/npm/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss/node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "http://mirrors.tencentyun.com/npm/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss/node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "http://mirrors.tencentyun.com/npm/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/maplibre-gl": { + "version": "5.24.0", + "resolved": "http://mirrors.tencentyun.com/npm/maplibre-gl/-/maplibre-gl-5.24.0.tgz", + "integrity": "sha512-ALyFxgtd5R+65UqZ/++lOqwWcC0SNho9c27fYSyLmG7AfnAul2o46F05aDJGPbFU57wos9dgcIySHs0Xe6ia3A==", + "license": "BSD-3-Clause", + "dependencies": { + "@mapbox/jsonlint-lines-primitives": "^2.0.2", + "@mapbox/point-geometry": "^1.1.0", + "@mapbox/tiny-sdf": "^2.1.0", + "@mapbox/unitbezier": "^0.0.1", + "@mapbox/vector-tile": "^2.0.4", + "@mapbox/whoots-js": "^3.1.0", + "@maplibre/geojson-vt": "^6.1.0", + "@maplibre/maplibre-gl-style-spec": "^24.8.1", + "@maplibre/mlt": "^1.1.8", + "@maplibre/vt-pbf": "^4.3.0", + "@types/geojson": "^7946.0.16", + "earcut": "^3.0.2", + "gl-matrix": "^3.4.4", + "kdbush": "^4.0.2", + "murmurhash-js": "^1.0.0", + "pbf": "^4.0.1", + "potpack": "^2.1.0", + "quickselect": "^3.0.0", + "tinyqueue": "^3.0.0" + }, + "engines": { + "node": ">=16.14.0", + "npm": ">=8.1.0" + }, + "funding": { + "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "http://mirrors.tencentyun.com/npm/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "http://mirrors.tencentyun.com/npm/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "http://mirrors.tencentyun.com/npm/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "http://mirrors.tencentyun.com/npm/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "http://mirrors.tencentyun.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/murmurhash-js": { + "version": "1.0.0", + "resolved": "http://mirrors.tencentyun.com/npm/murmurhash-js/-/murmurhash-js-1.0.0.tgz", + "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "http://mirrors.tencentyun.com/npm/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/pbf": { + "version": "4.0.2", + "resolved": "http://mirrors.tencentyun.com/npm/pbf/-/pbf-4.0.2.tgz", + "integrity": "sha512-J0ajxARhZfpUEebxYs1vhMGMuLSXtBe1e+fFPDrf2uA2hgo+UshKfNUWOz92HJNz6/NFEXseQPddnHkTreWRqg==", + "license": "BSD-3-Clause", + "dependencies": { + "resolve-protobuf-schema": "^2.1.0" + }, + "bin": { + "pbf": "bin/pbf" + } + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "http://mirrors.tencentyun.com/npm/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinia": { + "version": "3.0.4", + "resolved": "http://mirrors.tencentyun.com/npm/pinia/-/pinia-3.0.4.tgz", + "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^7.7.7" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.5.0", + "vue": "^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/point-in-polygon": { + "version": "1.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/point-in-polygon/-/point-in-polygon-1.1.0.tgz", + "integrity": "sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw==", + "license": "MIT" + }, + "node_modules/point-in-polygon-hao": { + "version": "1.2.4", + "resolved": "http://mirrors.tencentyun.com/npm/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/point-in-polygon-hao/node_modules/robust-predicates": { + "version": "3.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/robust-predicates/-/robust-predicates-3.0.3.tgz", + "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==", + "license": "Unlicense" + }, + "node_modules/polyclip-ts": { + "version": "0.16.8", + "resolved": "http://mirrors.tencentyun.com/npm/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/postcss": { + "version": "8.5.15", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/potpack": { + "version": "2.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/potpack/-/potpack-2.1.0.tgz", + "integrity": "sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ==", + "license": "ISC" + }, + "node_modules/protocol-buffers-schema": { + "version": "3.6.1", + "resolved": "http://mirrors.tencentyun.com/npm/protocol-buffers-schema/-/protocol-buffers-schema-3.6.1.tgz", + "integrity": "sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==", + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/quickselect": { + "version": "3.0.0", + "resolved": "http://mirrors.tencentyun.com/npm/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==", + "license": "ISC" + }, + "node_modules/rbush": { + "version": "3.0.1", + "resolved": "http://mirrors.tencentyun.com/npm/rbush/-/rbush-3.0.1.tgz", + "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==", + "license": "MIT", + "dependencies": { + "quickselect": "^2.0.0" + } + }, + "node_modules/rbush/node_modules/quickselect": { + "version": "2.0.0", + "resolved": "http://mirrors.tencentyun.com/npm/quickselect/-/quickselect-2.0.0.tgz", + "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==", + "license": "ISC" + }, + "node_modules/readdirp": { + "version": "5.0.0", + "resolved": "http://mirrors.tencentyun.com/npm/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "license": "MIT", + "dependencies": { + "protocol-buffers-schema": "^3.3.1" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "http://mirrors.tencentyun.com/npm/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, + "node_modules/robust-predicates": { + "version": "2.0.4", + "resolved": "http://mirrors.tencentyun.com/npm/robust-predicates/-/robust-predicates-2.0.4.tgz", + "integrity": "sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg==", + "license": "Unlicense" + }, + "node_modules/rolldown": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.133.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.3", + "@rolldown/binding-darwin-arm64": "1.0.3", + "@rolldown/binding-darwin-x64": "1.0.3", + "@rolldown/binding-freebsd-x64": "1.0.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", + "@rolldown/binding-linux-arm64-gnu": "1.0.3", + "@rolldown/binding-linux-arm64-musl": "1.0.3", + "@rolldown/binding-linux-ppc64-gnu": "1.0.3", + "@rolldown/binding-linux-s390x-gnu": "1.0.3", + "@rolldown/binding-linux-x64-gnu": "1.0.3", + "@rolldown/binding-linux-x64-musl": "1.0.3", + "@rolldown/binding-openharmony-arm64": "1.0.3", + "@rolldown/binding-wasm32-wasi": "1.0.3", + "@rolldown/binding-win32-arm64-msvc": "1.0.3", + "@rolldown/binding-win32-x64-msvc": "1.0.3" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", + "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz", + "integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz", + "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz", + "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz", + "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz", + "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz", + "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz", + "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz", + "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", + "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz", + "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz", + "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz", + "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.3", + "resolved": "http://mirrors.tencentyun.com/npm/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz", + "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "http://mirrors.tencentyun.com/npm/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/sass": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass/-/sass-1.100.0.tgz", + "integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "chokidar": "^5.0.0", + "immutable": "^5.1.5", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sass-embedded": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded/-/sass-embedded-1.100.0.tgz", + "integrity": "sha512-Ut8wlQSk19tm7jMK6mz6cF1+e+E7tUnW2tM02zQDPnOTcVbV8qCQG8UWxZkkNlY50+hV3hqP24OOkUlMz8xBpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bufbuild/protobuf": "^2.5.0", + "colorjs.io": "^0.5.0", + "immutable": "^5.1.5", + "rxjs": "^7.4.0", + "supports-color": "^8.1.1", + "sync-child-process": "^1.0.2", + "varint": "^6.0.0" + }, + "bin": { + "sass": "dist/bin/sass.js" + }, + "engines": { + "node": ">=16.0.0" + }, + "optionalDependencies": { + "sass-embedded-all-unknown": "1.100.0", + "sass-embedded-android-arm": "1.100.0", + "sass-embedded-android-arm64": "1.100.0", + "sass-embedded-android-riscv64": "1.100.0", + "sass-embedded-android-x64": "1.100.0", + "sass-embedded-darwin-arm64": "1.100.0", + "sass-embedded-darwin-x64": "1.100.0", + "sass-embedded-linux-arm": "1.100.0", + "sass-embedded-linux-arm64": "1.100.0", + "sass-embedded-linux-musl-arm": "1.100.0", + "sass-embedded-linux-musl-arm64": "1.100.0", + "sass-embedded-linux-musl-riscv64": "1.100.0", + "sass-embedded-linux-musl-x64": "1.100.0", + "sass-embedded-linux-riscv64": "1.100.0", + "sass-embedded-linux-x64": "1.100.0", + "sass-embedded-unknown-all": "1.100.0", + "sass-embedded-win32-arm64": "1.100.0", + "sass-embedded-win32-x64": "1.100.0" + } + }, + "node_modules/sass-embedded-all-unknown": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.100.0.tgz", + "integrity": "sha512-auFtXY/kwYILmSVjtBDwyj0axcLbYYiffOKWoaXHnI5bsYwiRbBh3EneR1rpbX2ZIZCrwX93i5pxKLTZF/662Q==", + "cpu": [ + "!arm", + "!arm64", + "!riscv64", + "!x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "sass": "1.100.0" + } + }, + "node_modules/sass-embedded-android-arm": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-android-arm/-/sass-embedded-android-arm-1.100.0.tgz", + "integrity": "sha512-70f3HgX2pFNmzpGQ86n5e6QfWn2fP4QUQGfFQK0P1XH73ZLIzLo2YqygrGKGKeeqtc5eU2Wl1/xQzhzuKnO4kw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-arm64": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.100.0.tgz", + "integrity": "sha512-W+Ru9JwTnfU0UX3jSZcbqFdtKFMcYdfFwytc57h2DgnqCOIiAqI2E06mABZBZC+r3LwXCBuS5GbXAGeVgvVDkA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-riscv64": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.100.0.tgz", + "integrity": "sha512-icU3o0V/uCSytSpf+tX5Lf51BvyQEbLzDUJfUi9etSauYBGHpPKkdtdZH0si4v98phq11Kl8rSV1SggksxF1Hg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-x64": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-android-x64/-/sass-embedded-android-x64-1.100.0.tgz", + "integrity": "sha512-mevF9VQk6gEYByy8+jusaHGmd7Usb2ytX/DsEOd0JtOGCtcf1kh575xJ6OUBDIcJ15uLnbau/0iy1eP6WVBvWA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-darwin-arm64": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.100.0.tgz", + "integrity": "sha512-1PVlYi61POo93IT/FfrG1mc1tAHxeSTyUALF2aOFmXGWjVXr3bQzEQiBGCOvQbj/ix+5hNyXFXcEMEyKvtUJJA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-darwin-x64": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.100.0.tgz", + "integrity": "sha512-x97o3JnGyImZNCIVs9wQHJUE5QCvmVIKaH1cwrz/5dK7OT1FpeNiW+u9TUomP9hG6Ekjd8EL8NBHpxTfIhdjmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-arm": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.100.0.tgz", + "integrity": "sha512-9Ul7O1eKrc5YlhwWjkp8tZPSe3UEwSZ1uwUZOQom1HL0pRlBA6F/IlGZYFTLwnHMIP1fc77MMNaBRfc05mKMpw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-arm64": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.100.0.tgz", + "integrity": "sha512-Dwjmj8Z6VRy7rAi53JAdEwIyUjpfl7PhpSc2/LpQPQx+aO5Dp7Spaipkax0ufJl1SoDUdchCsM4y/88YaluorQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-arm": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.100.0.tgz", + "integrity": "sha512-sl0JgbGloPyJg66XXx5UDSDScZ0oU85DpMQU4JU/sCUCFj1Z8zZ69SJWKTCNE4/jwnce7WI2zPCV5AG+RHOZJw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-arm64": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.100.0.tgz", + "integrity": "sha512-XpACJB2KjSLjf2e9uuvGVdOURsoNrFqgRiihhXyUHK9W0t3LIHb7z5MA/7XGPIT9bWSOO2zyw+rH/FHtDV/Yrg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-riscv64": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.100.0.tgz", + "integrity": "sha512-ShvI0Kx04mwoCARwZ0UjiT97isQvzO80tAt91zmFyHLN9kelc/IrQi940farSm2xQVPCKdeVyeG0ekBsokSpYQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-x64": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.100.0.tgz", + "integrity": "sha512-TDBCRWNuS4RDLQXvRc1gjZlWiWTWaWGp0Bwu/IKwJxov81lsvrCs3TihTyNXtW7V5aoN4Ky3r0QOkNb3mwmBnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-riscv64": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.100.0.tgz", + "integrity": "sha512-j4ENJGOheO+fm3j/yorLxCjBP6/XskrZx7dTLlT+lXYwN/qqCqoA/gsNLI0McS3DFM6GBwPiffzWsdWS8t6sEQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-x64": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.100.0.tgz", + "integrity": "sha512-0vUSN8j0WGtCJIOPh//EmUvYGHW0QOe5iul8qyhPk50MAcw49MA0r34AhftjDdx94ILPF6vApFs0gwHPQRlpVA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-unknown-all": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.100.0.tgz", + "integrity": "sha512-c+naBgWId4MIpToXcI0DgqetjdAkwTTAxFAuOaBz7HUXLdyG1oZRrEvSsbe41nEdQOKH0vgofVFCeSQgoXOG9A==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "!android", + "!darwin", + "!linux", + "!win32" + ], + "dependencies": { + "sass": "1.100.0" + } + }, + "node_modules/sass-embedded-win32-arm64": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.100.0.tgz", + "integrity": "sha512-iE+yxj+hUXwwbqpHkXxgAWTzeRfcWxJ7SSTQEPMk48lwq3oCrWLlz5sQuWHbuTK/i0GKQfROdP+hOmPi89yjUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-win32-x64": { + "version": "1.100.0", + "resolved": "http://mirrors.tencentyun.com/npm/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.100.0.tgz", + "integrity": "sha512-qI4F8MI7/KYoy9NdjJfhSspG42WPkADSNDvwEV7qWvCSFC83koJssRsKO2/PfY+niZz6BG65Ic/D+A11h959hw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/skmeans": { + "version": "0.9.7", + "resolved": "http://mirrors.tencentyun.com/npm/skmeans/-/skmeans-0.9.7.tgz", + "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg==", + "license": "MIT" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "http://mirrors.tencentyun.com/npm/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/splaytree-ts": { + "version": "1.0.2", + "resolved": "http://mirrors.tencentyun.com/npm/splaytree-ts/-/splaytree-ts-1.0.2.tgz", + "integrity": "sha512-0kGecIZNIReCSiznK3uheYB8sbstLjCZLiwcQwbmLhgHJj2gz6OnSPkVzJQCMnmEz1BQ4gPK59ylhBoEWOhGNA==", + "license": "BDS-3-Clause" + }, + "node_modules/supercluster": { + "version": "8.0.1", + "resolved": "http://mirrors.tencentyun.com/npm/supercluster/-/supercluster-8.0.1.tgz", + "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", + "license": "ISC", + "dependencies": { + "kdbush": "^4.0.2" + } + }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "http://mirrors.tencentyun.com/npm/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "http://mirrors.tencentyun.com/npm/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/sweepline-intersections": { + "version": "1.5.0", + "resolved": "http://mirrors.tencentyun.com/npm/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": "http://mirrors.tencentyun.com/npm/tinyqueue/-/tinyqueue-2.0.3.tgz", + "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==", + "license": "ISC" + }, + "node_modules/sync-child-process": { + "version": "1.0.2", + "resolved": "http://mirrors.tencentyun.com/npm/sync-child-process/-/sync-child-process-1.0.2.tgz", + "integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sync-message-port": "^1.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/sync-message-port": { + "version": "1.2.0", + "resolved": "http://mirrors.tencentyun.com/npm/sync-message-port/-/sync-message-port-1.2.0.tgz", + "integrity": "sha512-gAQ9qrUN/UCypHtGFbbe7Rc/f9bzO88IwrG8TDo/aMKAApKyD6E3W4Cm0EfhfBb6Z6SKt59tTCTfD+n1xmAvMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyqueue": { + "version": "3.0.0", + "resolved": "http://mirrors.tencentyun.com/npm/tinyqueue/-/tinyqueue-3.0.0.tgz", + "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==", + "license": "ISC" + }, + "node_modules/topojson-client": { + "version": "3.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/topojson-client/-/topojson-client-3.1.0.tgz", + "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", + "license": "ISC", + "dependencies": { + "commander": "2" + }, + "bin": { + "topo2geo": "bin/topo2geo", + "topomerge": "bin/topomerge", + "topoquantize": "bin/topoquantize" + } + }, + "node_modules/topojson-server": { + "version": "3.0.1", + "resolved": "http://mirrors.tencentyun.com/npm/topojson-server/-/topojson-server-3.0.1.tgz", + "integrity": "sha512-/VS9j/ffKr2XAOjlZ9CgyyeLmgJ9dMwq6Y0YEON8O7p/tGGk+dCWnrE03zEdu7i4L7YsFZLEPZPzCvcB7lEEXw==", + "license": "ISC", + "dependencies": { + "commander": "2" + }, + "bin": { + "geo2topo": "bin/geo2topo" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "6.0.3", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.18.2", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "14.0.0", + "resolved": "http://mirrors.tencentyun.com/npm/uuid/-/uuid-14.0.0.tgz", + "integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/vant": { + "version": "4.9.24", + "resolved": "http://mirrors.tencentyun.com/npm/vant/-/vant-4.9.24.tgz", + "integrity": "sha512-tP1A7Vjzv1/B1ljb95Jhv9Q9w6acaaZDJvy6wcKrwGgY0gQZlg+FXLZH/AIKZBE3xvYGDUsv/M7AuGcr/Pqd6A==", + "license": "MIT", + "dependencies": { + "@vant/popperjs": "^1.3.0", + "@vant/use": "^1.6.0", + "@vue/shared": "^3.5.31" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/varint": { + "version": "6.0.0", + "resolved": "http://mirrors.tencentyun.com/npm/varint/-/varint-6.0.0.tgz", + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "8.0.16", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.15", + "rolldown": "1.0.3", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.18", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "http://mirrors.tencentyun.com/npm/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.38", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.38", + "@vue/compiler-sfc": "3.5.38", + "@vue/runtime-dom": "3.5.38", + "@vue/server-renderer": "3.5.38", + "@vue/shared": "3.5.38" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-tsc": { + "version": "3.3.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.28", + "@vue/language-core": "3.3.5" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/zrender": { + "version": "6.1.0", + "resolved": "http://mirrors.tencentyun.com/npm/zrender/-/zrender-6.1.0.tgz", + "integrity": "sha512-oEGMDB6pOP2S6OwRR4PdVv610zrjnA3Bh+JnSG12fYJlBKjtNAoEb5fSUoCOOINlH96I2fU38/A2UpRKs67xYQ==", + "license": "BSD-3-Clause", + "dependencies": { + "tslib": "2.3.0" + } + }, + "node_modules/zrender/node_modules/tslib": { + "version": "2.3.0", + "resolved": "http://mirrors.tencentyun.com/npm/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c2832d2 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "yuto-water-h5", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc -b && vite build", + "preview": "vite preview" + }, + "dependencies": { + "@turf/turf": "^7.3.5", + "axios": "^1.18.0", + "crypto-js": "^4.2.0", + "dayjs": "^1.11.21", + "echarts": "^6.1.0", + "encryptlong": "^3.1.4", + "maplibre-gl": "^5.24.0", + "mitt": "^3.0.1", + "pinia": "^3.0.4", + "supercluster": "^8.0.1", + "uuid": "^14.0.0", + "vant": "^4.9.24", + "vue": "^3.5.34" + }, + "devDependencies": { + "@types/node": "^24.12.3", + "@vitejs/plugin-vue": "^6.0.6", + "@vue/tsconfig": "^0.9.1", + "sass-embedded": "^1.100.0", + "typescript": "~6.0.2", + "vite": "^8.0.12", + "vue-tsc": "^3.2.8" + } +} diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..6893eb1 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons.svg b/public/icons.svg new file mode 100644 index 0000000..e952219 --- /dev/null +++ b/public/icons.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..388b05e --- /dev/null +++ b/src/App.vue @@ -0,0 +1,7 @@ + + + diff --git a/src/assets/hero.png b/src/assets/hero.png new file mode 100644 index 0000000..02251f4 Binary files /dev/null and b/src/assets/hero.png differ diff --git a/src/assets/vite.svg b/src/assets/vite.svg new file mode 100644 index 0000000..5101b67 --- /dev/null +++ b/src/assets/vite.svg @@ -0,0 +1 @@ +Vite diff --git a/src/assets/vue.svg b/src/assets/vue.svg new file mode 100644 index 0000000..770e9d3 --- /dev/null +++ b/src/assets/vue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/bridge/detector.ts b/src/bridge/detector.ts new file mode 100644 index 0000000..e5e811a --- /dev/null +++ b/src/bridge/detector.ts @@ -0,0 +1,87 @@ +/** + * 环境检测器 + * + * 检测当前运行环境类型,返回统一的环境标识, + * 供上层使用以决定加载哪个 Bridge 提供者。 + * + * @module bridge/detector + */ + +/** 可识别的运行环境 */ +export type Environment = 'browser' | 'wechat-mp' | 'uniapp-webview' + +/** wechat 全局声明扩展 */ +interface WechatWindow extends Window { + /** 微信 JS-SDK 桥接对象 */ + WeixinJSBridge?: Record + /** 微信环境标识 */ + __wxjs_environment?: string +} + +/** + * 全局 uni 对象(uni-app WebView 中存在) + * 声明为 any 以避免对 @dcloudio 类型包的硬依赖 + */ +declare const uni: Record | undefined + +/** + * 检测当前运行环境 + * + * 判断优先级: + * 1. 微信小程序 WebView —— userAgent 含 MicroMessenger 且标记为 miniprogram + * 2. uni-app WebView —— 全局存在 uni 对象(且非小程序场景) + * 3. 普通浏览器 —— 其余情况降级 + * + * @returns 环境标识字符串 + */ +export function detectEnvironment(): Environment { + const win = window as WechatWindow + + // ── 检测微信环境 ── + const ua = navigator.userAgent + const isWechat = /MicroMessenger/i.test(ua) + + if (isWechat) { + // 检查是否为小程序 WebView + // 方式一:WeixinJSBridge 注入的环境标识 + // 方式二:页面 URL 参数 __wxjs_environment(少数场景) + if (win.__wxjs_environment === 'miniprogram') { + return 'wechat-mp' + } + + // 微信 JS-SDK ready 后可通过 WeixinJSBridge 进一步确认, + // 但此处仅做同步检测,保守返回 wechat-mp(若 UA 匹配且环境变量已注入) + // 否则仍可能为普通微信内置浏览器,暂归为 wechat-mp + return 'wechat-mp' + } + + // ── 检测 uni-app WebView ── + // uni 对象在 uni-app 的 WebView 环境中由框架注入 + if (typeof uni !== 'undefined' && uni !== null) { + return 'uniapp-webview' + } + + // ── 默认:普通浏览器 ── + return 'browser' +} + +/** + * 判断当前是否在微信小程序 WebView 中 + */ +export function isWechatMiniProgram(): boolean { + return detectEnvironment() === 'wechat-mp' +} + +/** + * 判断当前是否在 uni-app WebView 中 + */ +export function isUniappWebView(): boolean { + return detectEnvironment() === 'uniapp-webview' +} + +/** + * 判断当前是否为普通浏览器环境 + */ +export function isBrowser(): boolean { + return detectEnvironment() === 'browser' +} diff --git a/src/bridge/index.ts b/src/bridge/index.ts new file mode 100644 index 0000000..32b7df6 --- /dev/null +++ b/src/bridge/index.ts @@ -0,0 +1,67 @@ +/** + * 桥接层统一入口 + * + * 导出类型定义、环境检测器以及各环境提供者, + * 并提供 createBridge() 工厂函数自动选择合适的提供者实例。 + * + * @module bridge + */ + +// ── 类型定义 ── +export type { + IBridge, + GetLocationOptions, + LocationResult, + ScanType, + ScanCodeOptions, + ScanCodeResult, + OpenMapParams, + ImageSourceType, + ChooseImageOptions, + ChooseImageResult, + DeviceInfo, +} from './types' + +// ── 环境检测 ── +export { + detectEnvironment, + isWechatMiniProgram, + isUniappWebView, + isBrowser, +} from './detector' +export type { Environment } from './detector' + +// ── 提供者 ── +export { default as browserProvider } from './providers/browser' + +// ── 工厂函数 ── +import type { IBridge } from './types' +import { detectEnvironment } from './detector' +import browserProvider from './providers/browser' + +/** + * 根据当前运行环境自动创建对应的 Bridge 实例 + * + * - 普通浏览器:返回 browserProvider(基于 Web API 降级实现) + * - 微信小程序 WebView:待实现 + * - uni-app WebView:待实现 + * + * @returns 符合 IBridge 接口的提供者实例 + */ +export function createBridge(): IBridge { + const env = detectEnvironment() + + switch (env) { + case 'wechat-mp': + // TODO: 引入 WechatProvider 后替换 + throw new Error('微信小程序 WebView Bridge 尚未实现') + + case 'uniapp-webview': + // TODO: 引入 UniappProvider 后替换 + throw new Error('uni-app WebView Bridge 尚未实现') + + case 'browser': + default: + return browserProvider + } +} diff --git a/src/bridge/providers/browser.ts b/src/bridge/providers/browser.ts new file mode 100644 index 0000000..0db028e --- /dev/null +++ b/src/bridge/providers/browser.ts @@ -0,0 +1,327 @@ +/** + * 浏览器环境 Bridge 提供者 + * + * 作为普通浏览器中的降级实现,利用 Web API 尽可能模拟原生能力。 + * 当 navigator.geolocation 不可用时,getLocation 会抛出清晰的错误。 + * + * @module bridge/providers/browser + */ + +import type { + IBridge, + GetLocationOptions, + LocationResult, + ScanCodeOptions, + ScanCodeResult, + OpenMapParams, + ChooseImageOptions, + ChooseImageResult, + DeviceInfo, +} from '../types' + +/** + * 浏览器降级提供者 + * + * 实现了 IBridge 接口的六个方法: + * - getLocation —— 依赖 navigator.geolocation + * - scanCode —— 浏览器无法扫码,直接抛出错误 + * - openMap —— 通过 URL Scheme 跳转高德/百度地图 + * - chooseImage —— 通过 选择图片 + * - getDeviceInfo —— 通过 navigator / screen 收集设备信息 + * - setTitle —— 通过 document.title 设置标题 + */ +const browserProvider: IBridge = { + // ──────────────────────────────────────────── + // 获取地理位置 + // ──────────────────────────────────────────── + async getLocation(options: GetLocationOptions = {}): Promise { + const geolocation = navigator.geolocation + + if (!geolocation) { + throw new Error('浏览器不支持定位功能(geolocation API 不可用)') + } + + const { + enableHighAccuracy = false, + timeout = 10000, + needAddress = false, + } = options + + return new Promise((resolve, reject) => { + geolocation.getCurrentPosition( + (position) => { + const result: LocationResult = { + latitude: position.coords.latitude, + longitude: position.coords.longitude, + speed: position.coords.speed ?? undefined, + accuracy: position.coords.accuracy, + } + + if (needAddress) { + // 浏览器原生 geolocation 不支持逆地理编码, + // address 留空,由调用方自行调用第三方服务补齐 + result.address = undefined + } + + resolve(result) + }, + (error) => { + let message: string + switch (error.code) { + case error.PERMISSION_DENIED: + message = '用户拒绝定位授权' + break + case error.POSITION_UNAVAILABLE: + message = '无法获取位置信息' + break + case error.TIMEOUT: + message = '定位请求超时' + break + default: + message = `定位失败: ${error.message}` + } + reject(new Error(message)) + }, + { + enableHighAccuracy, + timeout, + maximumAge: 0, + }, + ) + }) + }, + + // ──────────────────────────────────────────── + // 扫码 + // ──────────────────────────────────────────── + async scanCode(_options?: ScanCodeOptions): Promise { + throw new Error('浏览器不支持扫码功能,请使用移动端打开') + }, + + // ──────────────────────────────────────────── + // 打开地图 + // ──────────────────────────────────────────── + async openMap(params: OpenMapParams): Promise { + const { latitude, longitude, name, address, scale = 16 } = params + + const label = encodeURIComponent(name || address || '目标位置') + + // 优先尝试高德地图 URI + // 格式参考: https://lbs.amap.com/api/uri-api/guide/mobile-web/open + const amapUrl = `https://uri.amap.com/marker?position=${longitude},${latitude}&name=${label}&callnative=1` + + // 同时准备通用经纬度链接作为降级(打开系统默认地图) + const fallbackUrl = `https://maps.google.com/maps?q=${latitude},${longitude}(${label})&z=${scale}` + + // 检测当前环境 + const ua = navigator.userAgent + let mapUrl: string + + if (/iPhone|iPad|iPod/i.test(ua)) { + // iOS:使用 Apple Maps URL Scheme + mapUrl = `https://maps.apple.com/?q=${label}&ll=${latitude},${longitude}&z=${scale}` + } else if (/Android/i.test(ua)) { + // Android:优先使用高德,浏览器会自动唤起 + mapUrl = amapUrl + } else { + // 桌面端:打开 Google Maps + mapUrl = fallbackUrl + } + + try { + window.open(mapUrl, '_blank') + return true + } catch { + return false + } + }, + + // ──────────────────────────────────────────── + // 选择图片 + // ──────────────────────────────────────────── + async chooseImage(options: ChooseImageOptions = {}): Promise { + const { count = 1, sourceType = ['album', 'camera'], compress = true } = options + + return new Promise((resolve, reject) => { + const input = document.createElement('input') + input.type = 'file' + input.accept = 'image/*' + + // 根据 sourceType 设置 capture 属性 + if (sourceType.length === 1 && sourceType[0] === 'camera') { + input.capture = 'environment' + } + + // 支持多选 + if (count > 1) { + input.multiple = true + } + + // 压缩由 accept / 浏览器默认行为处理, + // 真实压缩需后续通过 Canvas 实现,此处仅标记 + + // 超时兜底:30s 后自动 reject + const timeoutId = setTimeout(() => { + reject(new Error('选择图片超时,请重试')) + cleanup() + }, 30000) + + const cleanup = () => { + clearTimeout(timeoutId) + input.removeEventListener('change', onChange) + input.removeEventListener('cancel', onCancel) + input.remove() + } + + const onChange = () => { + clearTimeout(timeoutId) + + const files = input.files + if (!files || files.length === 0) { + reject(new Error('未选择任何图片')) + cleanup() + return + } + + const tempFilePaths: string[] = [] + const tempFiles: Array<{ path: string; size: number }> = [] + + const validFiles: File[] = [] + for (let i = 0; i < files.length; i++) { + const file = files.item(i) + if (file) { + validFiles.push(file) + } + } + + for (const file of validFiles) { + // 通过 URL.createObjectURL 创建临时可访问路径 + const objectUrl = URL.createObjectURL(file) + tempFilePaths.push(objectUrl) + tempFiles.push({ path: objectUrl, size: file.size }) + } + + resolve({ + tempFilePaths, + tempFiles, + }) + cleanup() + } + + // 用户取消选择(部分浏览器支持) + const onCancel = () => { + clearTimeout(timeoutId) + reject(new Error('用户取消选择图片')) + cleanup() + } + + input.addEventListener('change', onChange) + // 监听 cancel 事件(部分浏览器) + input.addEventListener('cancel', onCancel) + + // 兼容移动端 webview 的取消操作: + // 通过 focus 丢失检测取消操作 + let focusLost = false + const onFocus = () => { + focusLost = false + } + const onBlur = () => { + focusLost = true + // 延迟检测:如果 blur 后 change 未触发,视为取消 + setTimeout(() => { + if (focusLost && input.files && input.files.length === 0) { + clearTimeout(timeoutId) + reject(new Error('用户取消选择图片')) + cleanup() + } + }, 500) + } + + input.addEventListener('focus', onFocus) + input.addEventListener('blur', onBlur) + + // 触发文件选择 + input.click() + }) + }, + + // ──────────────────────────────────────────── + // 获取设备信息 + // ──────────────────────────────────────────── + async getDeviceInfo(): Promise { + const ua = navigator.userAgent + + // 解析平台 + let platform: string + if (/iPhone|iPad|iPod/i.test(ua)) { + platform = 'ios' + } else if (/Android/i.test(ua)) { + platform = 'android' + } else if (/Windows/i.test(ua)) { + platform = 'windows' + } else if (/Macintosh|Mac OS/i.test(ua)) { + platform = 'mac' + } else if (/Linux/i.test(ua)) { + platform = 'linux' + } else { + platform = 'unknown' + } + + // 尝试解析设备型号(粗糙方式) + let model = 'unknown' + const deviceMatch = ua.match(/\(([^)]+)\)/) + if (deviceMatch && deviceMatch[1]) { + // 从 UA 括号中取设备信息 + const parts = deviceMatch[1].split(';') + // 最后一个不含版本号的 token 通常是设备型号 + for (let i = parts.length - 1; i >= 0; i--) { + const part = parts[i].trim() + if ( + part && + !/AppleWebKit|KHTML|Gecko|Chrome|Safari|Firefox|Edge|Version|Mobile/i.test(part) && + !/^[0-9._]+$/.test(part) && + !/U;|CPU|iPhone|iPad|iPod|Mac OS|Windows|Android|Linux/i.test(part) + ) { + model = part + break + } + } + } + + // 解析版本 + let version = 'unknown' + if (platform === 'android') { + const match = ua.match(/Android\s+([0-9.]+)/i) + if (match && match[1]) { + version = match[1] + } + } else if (platform === 'ios') { + const match = ua.match(/OS\s+([0-9_]+)/i) + if (match && match[1]) { + version = match[1].replace(/_/g, '.') + } + } + + return { + platform, + model, + version, + language: navigator.language, + pixelRatio: window.devicePixelRatio || 1, + screenWidth: screen.width, + screenHeight: screen.height, + windowWidth: window.innerWidth, + windowHeight: window.innerHeight, + } + }, + + // ──────────────────────────────────────────── + // 设置标题 + // ──────────────────────────────────────────── + async setTitle(title: string): Promise { + document.title = title + return true + }, +} + +export default browserProvider diff --git a/src/bridge/types.ts b/src/bridge/types.ts new file mode 100644 index 0000000..63597b4 --- /dev/null +++ b/src/bridge/types.ts @@ -0,0 +1,184 @@ +/** + * 桥接层类型定义 + * + * 定义统一的能力接口 IBridge,屏蔽不同运行环境(浏览器、微信小程序、uni-app WebView)的差异, + * 让上层业务代码只需依赖此接口即可调用原生能力。 + * + * @module bridge/types + */ + +// ────────────────────────────────────────────── +// 地理位置 +// ────────────────────────────────────────────── + +/** 获取地理位置时的配置选项 */ +export interface GetLocationOptions { + /** 是否启用高精度模式(GPS),默认 false */ + enableHighAccuracy?: boolean + /** 超时时间(毫秒),默认 10000 */ + timeout?: number + /** 是否需要返回逆地理编码后的地址描述 */ + needAddress?: boolean +} + +/** 地理位置坐标 */ +export interface LocationResult { + /** 纬度,范围 -90 ~ 90 */ + latitude: number + /** 经度,范围 -180 ~ 180 */ + longitude: number + /** 速度(m/s) */ + speed?: number + /** 精度(米) */ + accuracy?: number + /** 逆地理编码后的地址描述(需要 needAddress 选项) */ + address?: string +} + +// ────────────────────────────────────────────── +// 扫码 +// ────────────────────────────────────────────── + +/** 扫码类型 */ +export type ScanType = 'qr' | 'barcode' | 'all' + +/** 扫码配置选项 */ +export interface ScanCodeOptions { + /** 扫码类型,默认 'all' */ + type?: ScanType +} + +/** 扫码结果 */ +export interface ScanCodeResult { + /** 扫码得到的字符串内容 */ + result: string + /** 码的类型,如 'QR_CODE'、'EAN_13' 等 */ + format?: string + /** 字符集 */ + charset?: string +} + +// ────────────────────────────────────────────── +// 地图 +// ────────────────────────────────────────────── + +/** 打开地图查看位置所需的参数 */ +export interface OpenMapParams { + /** 目标纬度 */ + latitude: number + /** 目标经度 */ + longitude: number + /** 位置名称 */ + name?: string + /** 地址详情 */ + address?: string + /** 缩放级别,默认 16 */ + scale?: number +} + +// ────────────────────────────────────────────── +// 图片选择 +// ────────────────────────────────────────────── + +/** 图片来源 */ +export type ImageSourceType = 'album' | 'camera' + +/** 选择图片的配置选项 */ +export interface ChooseImageOptions { + /** 最多可选图片数量,默认 1 */ + count?: number + /** 图片来源,默认 ['album', 'camera'] */ + sourceType?: ImageSourceType[] + /** 是否允许压缩,默认 true */ + compress?: boolean +} + +/** 选择图片的返回结果 */ +export interface ChooseImageResult { + /** 选中图片的临时文件路径列表 */ + tempFilePaths: string[] + /** 选中图片的临时文件对象列表 */ + tempFiles?: Array<{ + path: string + size: number + }> +} + +// ────────────────────────────────────────────── +// 设备信息 +// ────────────────────────────────────────────── + +/** 设备信息 */ +export interface DeviceInfo { + /** 操作系统平台,如 'ios'、'android'、'windows'、'mac' */ + platform: string + /** 设备型号 */ + model: string + /** 操作系统版本号 */ + version: string + /** 系统语言 */ + language?: string + /** 设备像素比 */ + pixelRatio?: number + /** 屏幕宽度(px) */ + screenWidth?: number + /** 屏幕高度(px) */ + screenHeight?: number + /** 窗口宽度(px) */ + windowWidth?: number + /** 窗口高度(px) */ + windowHeight?: number +} + +// ────────────────────────────────────────────── +// Bridge 接口 —— 所有提供者需实现此接口 +// ────────────────────────────────────────────── + +/** + * 统一桥接接口 + * + * 所有环境提供者(浏览器、微信小程序 WebView、uni-app WebView) + * 都必须实现此接口,确保上层业务代码不感知底层差异。 + */ +export interface IBridge { + /** + * 获取当前地理位置 + * @param options - 配置选项 + * @returns Promise 返回位置信息 + */ + getLocation(options?: GetLocationOptions): Promise + + /** + * 调起扫码 + * @param options - 扫码配置 + * @returns Promise 返回扫码结果 + */ + scanCode(options?: ScanCodeOptions): Promise + + /** + * 打开地图查看指定位置 + * @param params - 目标位置参数 + * @returns Promise 返回是否成功打开 + */ + openMap(params: OpenMapParams): Promise + + /** + * 从相册或相机选择图片 + * @param options - 选择配置 + * @returns Promise 返回选中图片信息 + */ + chooseImage(options?: ChooseImageOptions): Promise + + /** + * 获取设备信息 + * @returns Promise 返回设备信息 + */ + getDeviceInfo(): Promise + + /** + * 设置页面标题 + * @param title - 标题文本 + * @returns Promise 返回是否设置成功 + */ + setTitle(title: string): Promise +} diff --git a/src/components/HelloWorld.vue b/src/components/HelloWorld.vue new file mode 100644 index 0000000..abcc860 --- /dev/null +++ b/src/components/HelloWorld.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..06abdbe --- /dev/null +++ b/src/main.ts @@ -0,0 +1,5 @@ +import { createApp } from 'vue' +import './styles/index.scss' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/src/map/LayerFactory.ts b/src/map/LayerFactory.ts new file mode 100644 index 0000000..1fe169f --- /dev/null +++ b/src/map/LayerFactory.ts @@ -0,0 +1,691 @@ +/** + * LayerFactory - 旧版 GeoScene 图层配置 → MapLibre 样式规范转换器 + * + * 将原 GeoScene 项目中 jsonToLayerFactory.js 的图层配置对象 + * 转换为 maplibregl 兼容的 style spec(source + layer 组合)。 + * 支持的图层类型与原工厂保持一致。 + * + * @module map/LayerFactory + */ + +import type { GeoJSON } from 'geojson' +import maplibregl from 'maplibre-gl' +import type { + SourceSpecification, + RasterSourceSpecification, + VectorSourceSpecification, + GeoJSONSourceSpecification, + LayerSpecification, + RasterLayerSpecification, +} from 'maplibre-gl' +import { + createTdtSource, + type TdtSourceOptions, + type TdtSourceResult, +} from './sources/tdt-source' + +// ============================================================ +// 类型定义 +// ============================================================ + +/** + * 旧版 GeoScene 图层配置(jsonToLayerFactory 输入格式) + * + * 对应原 GeoScene 项目中各个图层构造函数所需的 options 参数。 + * type 字段决定使用哪种转换策略。 + */ +export interface OldLayerConfig { + /** + * 图层类型标识(必填) + * + * - `'TdtLayer'`: 天地图 WMTS 图层 + * - `'TileLayer'`: ArcGIS 切片服务 / 标准 XYZ 瓦片 + * - `'MapImageLayer'`: ArcGIS 动态地图服务 + * - `'VectorTileLayer'`: 矢量瓦片图层(Mapbox Vector Tile) + * - `'WMTSLayer'`: 通用 WMTS 图层(OGC 标准) + * - `'GeoJSONLayer'`: GeoJSON 图层(FeatureLayer) + */ + type: 'TdtLayer' | 'TileLayer' | 'MapImageLayer' | 'VectorTileLayer' | 'WMTSLayer' | 'GeoJSONLayer' + + /** 图层 ID,缺失时自动生成 */ + id?: string + + /** 图层标题/名称 */ + title?: string + + /** 初始可见性 */ + visible?: boolean + + /** 图层不透明度 (0-1) */ + opacity?: number + + /** 最小可见缩放级别 */ + minZoom?: number + + /** 最大可见缩放级别 */ + maxZoom?: number + + // ---- TdtLayer 专用 ---- + /** 天地图样式(vec/img/ter/cva/cia/cta) */ + style?: string + /** 天地图瓦片矩阵集(c=经纬度, w=墨卡托) */ + matrix?: string + /** 天地图 API 密钥 */ + tk?: string + /** 天地图服务地址 */ + url?: string + /** 天地图子域列表 */ + subdomains?: string[] + + // ---- TileLayer / MapImageLayer / WMTSLayer 专用 ---- + /** 服务 URL 或 URL 模板 */ + urlTemplate?: string + + // ---- VectorTileLayer 专用 ---- + /** 矢量瓦片样式 URL 或内联样式对象 */ + styleUrl?: string | object + + // ---- GeoJSONLayer 专用 ---- + /** GeoJSON 数据 URL 或内联对象 */ + data?: string | GeoJSON.GeoJSON + /** 矢量图层样式配置 */ + layerConfig?: GeoJSONLayerStyleConfig + + // ---- 通用扩展 ---- + /** 其他任意配置,透传处理 */ + [key: string]: unknown +} + +/** + * GeoJSON 图层渲染样式配置 + */ +export interface GeoJSONLayerStyleConfig { + /** 渲染类型 */ + type?: 'line' | 'fill' | 'circle' | 'symbol' + /** 线宽 */ + lineWidth?: number + /** 线颜色 */ + lineColor?: string + /** 线不透明度 */ + lineOpacity?: number + /** 填充颜色 */ + fillColor?: string + /** 填充不透明度 */ + fillOpacity?: number + /** 圆形半径 */ + circleRadius?: number + /** 圆形颜色 */ + circleColor?: string + /** 圆形不透明度 */ + circleOpacity?: number + /** 圆形描边宽度 */ + circleStrokeWidth?: number + /** 圆形描边颜色 */ + circleStrokeColor?: string + /** 其他 paint/layout 属性 */ + [key: string]: unknown +} + +/** + * LayerFactory 返回结果 + */ +export interface LayerFactoryResult { + /** + * 源配置列表(按顺序通过 map.addSource 添加) + */ + sources: Array<{ id: string; config: SourceSpecification }> + + /** + * 图层配置列表(按顺序通过 map.addLayer 添加) + */ + layers: LayerSpecification[] + + /** + * 源图层名称(用于追踪) + */ + originalType: string +} + +// ============================================================ +// 内部常量 +// ============================================================ + +/** + * ArcGIS 服务标准导出参数 + */ +const ARCGIS_EXPORT_PARAMS = { + f: 'image', + format: 'png32', + transparent: 'true', + dpi: '96', +} + +// ============================================================ +// ID 生成 +// ============================================================ + +/** ID 自增计数器 */ +let idCounter = 0 + +/** + * 生成唯一 ID + */ +function generateId(prefix: string): string { + idCounter += 1 + return `${prefix}-${idCounter}-${Date.now().toString(36)}` +} + +// ============================================================ +// 各类型转换函数 +// ============================================================ + +/** + * 转换天地图图层 (TdtLayer) + * + * 委托给 {@link createTdtSource} 完成实际转换。 + */ +function convertTdtLayer(config: OldLayerConfig): LayerFactoryResult { + const tdtOptions: TdtSourceOptions = { + style: (config.style as TdtSourceOptions['style']) ?? 'vec', + matrix: (config.matrix as TdtSourceOptions['matrix']) ?? 'c', + tk: config.tk, + url: config.url, + subdomains: config.subdomains, + minzoom: config.minZoom ?? 0, + maxzoom: config.maxZoom ?? 18, + layer: { + layout: { + visibility: config.visible === false ? 'none' : 'visible', + }, + paint: config.opacity !== undefined + ? { 'raster-opacity': config.opacity } + : undefined, + metadata: { + title: config.title, + }, + } as RasterLayerSpecification, + } + + const result: TdtSourceResult = createTdtSource(tdtOptions) + + return { + sources: [{ id: result.sourceId, config: result.source }], + layers: [result.layer], + originalType: 'TdtLayer', + } +} + +/** + * 转换 ArcGIS 切片服务图层 (TileLayer) + * + * ArcGIS 切片服务(MapServer/tile/{z}/{y}/{x})→ raster source + layer + */ +function convertTileLayer(config: OldLayerConfig): LayerFactoryResult { + const layerId = config.id || generateId('tile') + const sourceId = `${layerId}-source` + const url = config.urlTemplate || config.url || '' + + // ArcGIS 切片服务 URL 格式:{serviceUrl}/tile/{z}/{y}/{x} + // 如果已经是 {z}/{x}/{y} 模板,则直接使用 + const tileUrl: string = url.includes('{z}') + ? url + : url.replace(/\/?$/, '/tile/{z}/{y}/{x}') + + const source: RasterSourceSpecification = { + type: 'raster', + tiles: [tileUrl], + tileSize: 256, + minzoom: config.minZoom ?? 0, + maxzoom: config.maxZoom ?? 19, + attribution: config.title ?? '', + } + + const layer: RasterLayerSpecification = { + id: layerId, + type: 'raster', + source: sourceId, + minzoom: config.minZoom ?? 0, + maxzoom: config.maxZoom ?? 19, + layout: { + visibility: config.visible === false ? 'none' : 'visible', + }, + paint: { + ...(config.opacity !== undefined ? { 'raster-opacity': config.opacity } : {}), + }, + metadata: { + title: config.title ?? layerId, + type: 'TileLayer', + }, + } + + return { + sources: [{ id: sourceId, config: source }], + layers: [layer], + originalType: 'TileLayer', + } +} + +/** + * 转换 ArcGIS 动态地图服务图层 (MapImageLayer) + * + * ArcGIS MapServer/export → raster source(单张图片,非瓦片) + * 注意:MapLibre 的 raster 源需要瓦片,这里通过自定义 scheme 生成单瓦片 + */ +function convertMapImageLayer(config: OldLayerConfig): LayerFactoryResult { + const layerId = config.id || generateId('map-image') + const sourceId = `${layerId}-source` + const url = config.urlTemplate || config.url || '' + + // 构建 ArcGIS export 请求 URL 模板 + const params = new URLSearchParams({ + ...ARCGIS_EXPORT_PARAMS, + bbox: '{bbox-epsg-3857}', + bboxSR: '3857', + imageSR: '3857', + size: '256,256', + }).toString() + + // ArcGIS MapServer export 端点 + const exportUrl = url.replace(/\/?$/, '/export?' + params) + + const source: RasterSourceSpecification = { + type: 'raster', + tiles: [exportUrl], + tileSize: 256, + minzoom: config.minZoom ?? 0, + maxzoom: config.maxZoom ?? 19, + } + + const layer: RasterLayerSpecification = { + id: layerId, + type: 'raster', + source: sourceId, + minzoom: config.minZoom ?? 0, + maxzoom: config.maxZoom ?? 19, + layout: { + visibility: config.visible === false ? 'none' : 'visible', + }, + paint: { + ...(config.opacity !== undefined ? { 'raster-opacity': config.opacity } : {}), + }, + metadata: { + title: config.title ?? layerId, + type: 'MapImageLayer', + }, + } + + return { + sources: [{ id: sourceId, config: source }], + layers: [layer], + originalType: 'MapImageLayer', + } +} + +/** + * 转换矢量瓦片图层 (VectorTileLayer) + * + * 支持两种模式: + * 1. URL 指向 MapLibre 样式 JSON(直接作为 style URL 使用) + * 2. 直接使用矢量瓦片源 URL + */ +function convertVectorTileLayer(config: OldLayerConfig): LayerFactoryResult { + const layerId = config.id || generateId('vector-tile') + const sourceId = `${layerId}-source` + const url = config.urlTemplate || config.url || '' + + const source: VectorSourceSpecification = { + type: 'vector', + tiles: [url], + minzoom: config.minZoom ?? 0, + maxzoom: config.maxZoom ?? 14, + } + + // 返回一个占位图层,实际渲染样式需由调用方根据 vector source 的 source-layer 自行添加 + const layer: LayerSpecification = { + id: layerId, + type: 'line', + source: sourceId, + 'source-layer': '', + layout: { + visibility: config.visible === false ? 'none' : 'visible', + }, + metadata: { + title: config.title ?? layerId, + type: 'VectorTileLayer', + note: '需要调用方根据 source-layer 自行设置渲染样式', + }, + } + + return { + sources: [{ id: sourceId, config: source }], + layers: [layer], + originalType: 'VectorTileLayer', + } +} + +/** + * 转换 WMTS 图层 (WMTSLayer) + * + * OGC WMTS 标准 → raster source + * 使用 RESTful 风格的 WMTS URL 模板 + */ +function convertWMTSLayer(config: OldLayerConfig): LayerFactoryResult { + const layerId = config.id || generateId('wmts') + const sourceId = `${layerId}-source` + const url = config.urlTemplate || config.url || '' + + // 如果 URL 不含 {z}/{x}/{y},通常 WMTS RESTful URL 格式为: + // {serviceUrl}/{layer}/{style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol} + const tileUrl: string = url.includes('{z}') + ? url + : `${url}/{z}/{y}/{x}` + + const source: RasterSourceSpecification = { + type: 'raster', + tiles: [tileUrl], + tileSize: 256, + minzoom: config.minZoom ?? 0, + maxzoom: config.maxZoom ?? 19, + } + + const layer: RasterLayerSpecification = { + id: layerId, + type: 'raster', + source: sourceId, + minzoom: config.minZoom ?? 0, + maxzoom: config.maxZoom ?? 19, + layout: { + visibility: config.visible === false ? 'none' : 'visible', + }, + paint: { + ...(config.opacity !== undefined ? { 'raster-opacity': config.opacity } : {}), + }, + metadata: { + title: config.title ?? layerId, + type: 'WMTSLayer', + }, + } + + return { + sources: [{ id: sourceId, config: source }], + layers: [layer], + originalType: 'WMTSLayer', + } +} + +/** + * 转换 GeoJSON 图层 (GeoJSONLayer) + * + * GeoJSON 数据源 → source + 对应类型的渲染图层 + */ +function convertGeoJSONLayer(config: OldLayerConfig): LayerFactoryResult { + const layerId = config.id || generateId('geojson') + const sourceId = `${layerId}-source` + const styleConfig = config.layerConfig || {} + + // 数据源:支持 URL 和内联 GeoJSON + const data = config.data || undefined + + let geoJsonData: string | GeoJSON.GeoJSON = '' + + if (typeof data === 'string') { + // URL 字符串 + geoJsonData = data + } else if (data && typeof data === 'object') { + // 内联 GeoJSON 对象 + geoJsonData = data as GeoJSON.GeoJSON + } + + const source: GeoJSONSourceSpecification = { + type: 'geojson', + data: geoJsonData, + } + + // 根据 layerConfig.type 确定 MapLibre 图层类型 + const renderType = (styleConfig.type as string) || 'line' + + // 构建 paint 属性 + const paint: Record = {} + + switch (renderType) { + case 'line': + if (styleConfig.lineColor) paint['line-color'] = styleConfig.lineColor + if (styleConfig.lineWidth !== undefined) paint['line-width'] = styleConfig.lineWidth + if (styleConfig.lineOpacity !== undefined) paint['line-opacity'] = styleConfig.lineOpacity + break + case 'fill': + if (styleConfig.fillColor) paint['fill-color'] = styleConfig.fillColor + if (styleConfig.fillOpacity !== undefined) paint['fill-opacity'] = styleConfig.fillOpacity + break + case 'circle': + if (styleConfig.circleRadius !== undefined) paint['circle-radius'] = styleConfig.circleRadius + if (styleConfig.circleColor) paint['circle-color'] = styleConfig.circleColor + if (styleConfig.circleOpacity !== undefined) paint['circle-opacity'] = styleConfig.circleOpacity + if (styleConfig.circleStrokeWidth !== undefined) paint['circle-stroke-width'] = styleConfig.circleStrokeWidth + if (styleConfig.circleStrokeColor) paint['circle-stroke-color'] = styleConfig.circleStrokeColor + break + default: + break + } + + // 合并其他未映射的 paint 属性 + const knownKeys = [ + 'type', 'lineColor', 'lineWidth', 'lineOpacity', + 'fillColor', 'fillOpacity', + 'circleRadius', 'circleColor', 'circleOpacity', + 'circleStrokeWidth', 'circleStrokeColor', + ] + for (const key of Object.keys(styleConfig)) { + if (!knownKeys.includes(key)) { + paint[key] = styleConfig[key] + } + } + + const layer = { + id: layerId, + type: renderType as LayerSpecification['type'], + source: sourceId, + layout: { + visibility: config.visible === false ? 'none' : 'visible', + }, + paint: Object.keys(paint).length > 0 ? (paint as LayerSpecification['paint']) : undefined, + metadata: { + title: config.title ?? layerId, + type: 'GeoJSONLayer', + }, + } as LayerSpecification + + return { + sources: [{ id: sourceId, config: source }], + layers: [layer], + originalType: 'GeoJSONLayer', + } +} + +// ============================================================ +// 类型 → 转换函数映射表 +// ============================================================ + +/** + * 图层类型与转换函数的映射表 + * + * 保持与原 jsonToLayerFactory.js 中 `layerConstructors` 一致的 + * 图层类型支持范围。 + */ +const TYPE_CONVERTERS: Record LayerFactoryResult> = { + TdtLayer: convertTdtLayer, + TileLayer: convertTileLayer, + MapImageLayer: convertMapImageLayer, + VectorTileLayer: convertVectorTileLayer, + WMTSLayer: convertWMTSLayer, + GeoJSONLayer: convertGeoJSONLayer, +} + +// ============================================================ +// 公开 API +// ============================================================ + +/** + * 获取支持的图层类型列表 + * + * @returns 图层类型字符串数组 + */ +export function getSupportedLayerTypes(): string[] { + return Object.keys(TYPE_CONVERTERS) +} + +/** + * 检查给定的图层类型是否受支持 + * + * @param type - 图层类型字符串 + * @returns 是否支持 + */ +export function isLayerTypeSupported(type: string): boolean { + return type in TYPE_CONVERTERS +} + +/** + * 将旧版 GeoScene 图层配置转换为 MapLibre 样式配置 + * + * 根据配置中的 `type` 字段自动选择对应的转换策略, + * 返回 MapLibre 兼容的 source + layer 配置,可直接传入 + * `map.addSource()` 和 `map.addLayer()`。 + * + * @param config - 旧版图层配置对象(必须有 `type` 字段) + * @returns 包含 sources 和 layers 数组的转换结果 + * @throws 如果 config 为空或 type 不支持 + * + * @example + * ```ts + * import { convertLayer } from '@/map/LayerFactory' + * + * const map = MapFactory.getCurrentMap() + * + * // 转换天地图图层 + * const result = convertLayer({ + * type: 'TdtLayer', + * style: 'vec', + * matrix: 'c', + * tk: 'your-key', + * title: '天地图矢量底图', + * }) + * + * result.sources.forEach(s => map?.addSource(s.id, s.config)) + * result.layers.forEach(l => map?.addLayer(l)) + * + * // 转换 GeoJSON 图层 + * const geoResult = convertLayer({ + * type: 'GeoJSONLayer', + * id: 'my-points', + * data: '/api/points.geojson', + * layerConfig: { + * type: 'circle', + * circleRadius: 8, + * circleColor: '#ff6600', + * }, + * }) + * geoResult.sources.forEach(s => map?.addSource(s.id, s.config)) + * geoResult.layers.forEach(l => map?.addLayer(l)) + * ``` + */ +export function convertLayer(config: OldLayerConfig): LayerFactoryResult { + // 校验配置 + if (!config) { + throw new Error('[LayerFactory] 配置为空,无法转换图层') + } + + const type = config.type + + if (!type) { + throw new Error('[LayerFactory] 图层配置缺少 type 字段') + } + + const converter = TYPE_CONVERTERS[type] + + if (!converter) { + const supported = Object.keys(TYPE_CONVERTERS).join(', ') + throw new Error( + `[LayerFactory] 不支持的图层类型: "${type}",支持的类型: ${supported}` + ) + } + + return converter(config) +} + +/** + * 批量转换旧版 GeoScene 图层配置 + * + * 依次调用 {@link convertLayer} 转换配置数组中的每一个图层, + * 遇到不支持的类型会跳过并打印警告日志。 + * + * @param configs - 旧版图层配置数组 + * @returns 转换结果数组(仅包含成功转换的项) + * + * @example + * ```ts + * const results = convertLayers([ + * { type: 'TdtLayer', style: 'vec', tk: '...' }, + * { type: 'TdtLayer', style: 'cva', tk: '...' }, + * { type: 'GeoJSONLayer', data: '/api/points.json' }, + * ]) + * + * results.forEach(r => { + * r.sources.forEach(s => map?.addSource(s.id, s.config)) + * }) + * results.forEach(r => { + * r.layers.forEach(l => map?.addLayer(l)) + * }) + * ``` + */ +export function convertLayers(configs: OldLayerConfig[]): LayerFactoryResult[] { + const results: LayerFactoryResult[] = [] + + for (const config of configs) { + try { + results.push(convertLayer(config)) + } catch (err) { + console.warn( + `[LayerFactory] 跳过图层转换: ${config?.type ?? '未知类型'}`, + (err as Error).message + ) + } + } + + return results +} + +/** + * 将转换结果应用到 MapLibre 地图实例 + * + * 便捷方法:按先 source 后 layer 的顺序批量添加到地图中。 + * + * @param map - MapLibre 地图实例 + * @param results - 转换结果(单个或数组) + * @param beforeId - 在指定图层之前插入(可选) + * + * @example + * ```ts + * const result = convertLayer(config) + * applyToMap(map, result) + * ``` + */ +export function applyToMap( + map: maplibregl.Map, + results: LayerFactoryResult | LayerFactoryResult[], + beforeId?: string +): void { + const list = Array.isArray(results) ? results : [results] + + for (const result of list) { + for (const src of result.sources) { + if (!map.getSource(src.id)) { + map.addSource(src.id, src.config) + } + } + for (const layer of result.layers) { + if (!map.getLayer(layer.id)) { + map.addLayer(layer, beforeId) + } + } + } +} diff --git a/src/map/MapFactory.ts b/src/map/MapFactory.ts new file mode 100644 index 0000000..4e37b00 --- /dev/null +++ b/src/map/MapFactory.ts @@ -0,0 +1,325 @@ +/** + * MapFactory - 预配置 maplibregl.Map 实例工厂 + * + * 提供快速创建带有默认底图图层、控件和事件处理的地图实例的工具方法。 + * 内部使用 MapManager 单例管理地图生命周期,避免重复创建实例。 + * + * @module map/MapFactory + */ + +import { Map, MapOptions, NavigationControlOptions, StyleSpecification } from 'maplibre-gl' +import { + MapManager, + MapConfig, + DEFAULT_CENTER, + DEFAULT_ZOOM, + DEFAULT_NAVIGATION_CONTROL_OPTIONS, +} from './MapManager' + +// ============================================================ +// 类型定义 +// ============================================================ + +/** + * 地图工厂配置选项 + * + * 扩展自 MapConfig,增加工厂特有的便捷配置项 + */ +export interface MapFactoryOptions extends Omit { + /** + * 地图容器元素或其 id(必填) + */ + container: string | HTMLElement + + /** + * 是否自动添加 NavigationControl 导航控件 + * @defaultValue true + */ + enableNavigationControl?: boolean + + /** + * NavigationControl 导航控件配置 + * @defaultValue { showCompass: true, showZoom: true, visualizePitch: false } + */ + navigationControlOptions?: NavigationControlOptions + + /** + * 是否启用默认的中日韩本地字体渲染 + * @defaultValue true + */ + enableLocalIdeograph?: boolean + + /** + * 用户自定义的 map 'load' 事件处理器 + */ + onLoad?: (map: Map) => void +} + +/** + * 底图图层配置 + */ +export interface BasemapLayerConfig { + /** + * 图层 id + */ + id: string + + /** + * 图层名称(用于显示) + */ + name: string + + /** + * MapLibre 样式 URL 或 style 对象 + */ + style: string | StyleSpecification +} + +// ============================================================ +// 预置底图配置 +// ============================================================ + +/** + * 内置底图图层列表 + * + * 可根据项目需要扩展更多底图样式 + */ +export const PRESET_BASEMAPS: Record = { + /** + * MapLibre 官方 Demo 瓦片底图(开发/测试用) + */ + demotiles: { + id: 'basemap-demotiles', + name: 'Demo Tiles', + style: 'https://demotiles.maplibre.org/style.json', + }, + + /** + * OpenStreetMap 栅格瓦片底图 + */ + osm: { + id: 'basemap-osm', + name: 'OpenStreetMap', + style: { + version: 8, + sources: { + 'osm-raster': { + type: 'raster', + tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'], + tileSize: 256, + attribution: + '© OpenStreetMap contributors', + maxzoom: 19, + }, + }, + layers: [ + { + id: 'osm-raster-layer', + type: 'raster', + source: 'osm-raster', + minzoom: 0, + maxzoom: 19, + }, + ], + }, + }, +} + +// ============================================================ +// MapFactory +// ============================================================ + +/** + * 地图工厂 + * + * 提供一组静态方法,用于快速创建带有常用预配置的 maplibregl.Map 实例。 + * 所有方法内部通过 MapManager 单例管理地图生命周期。 + * + * @example + * ```ts + * // 使用预置 OSM 底图快速创建地图 + * const map = MapFactory.createWithBasemap('osm', { + * container: 'map-container', + * }) + * + * // 使用自定义样式创建地图 + * const map = MapFactory.create({ + * container: 'map-container', + * style: 'https://my-style-server/style.json', + * zoom: 12, + * }) + * + * // 创建带加载回调的地图 + * const map = MapFactory.create({ + * container: 'map-container', + * style: 'https://demotiles.maplibre.org/style.json', + * onLoad: (map) => { + * console.log('地图就绪', map.getCenter()) + * }, + * }) + * ``` + */ +export class MapFactory { + /** + * 获取 MapManager 单例 + * + * @returns MapManager 实例 + */ + private static getManager(): MapManager { + return MapManager.getInstance() + } + + /** + * 创建预配置的地图实例 + * + * 自动合并默认配置(南京中心点、默认缩放级别、本地字体等), + * 并添加 NavigationControl 导航控件。 + * + * @param options - 地图工厂配置选项 + * @returns 创建的 maplibregl.Map 实例 + */ + static create(options: MapFactoryOptions): Map { + const manager = MapFactory.getManager() + + // 提取 factory 特有参数 + const { + container, + enableNavigationControl = true, + navigationControlOptions, + enableLocalIdeograph = true, + onLoad, + ...mapOptions + } = options + + // 构建 MapConfig + const config: Omit = { + // 默认配置 + center: DEFAULT_CENTER, + zoom: DEFAULT_ZOOM, + + // 如果启用本地字体,设置中文字体回退 + localIdeographFontFamily: enableLocalIdeograph ? 'sans-serif' : false, + + // 导航控件配置 + navigationControl: enableNavigationControl + ? (navigationControlOptions ?? DEFAULT_NAVIGATION_CONTROL_OPTIONS) + : false, + + // 合并用户传入的其他配置 + ...mapOptions, + } + + // 如果用户提供了 onLoad 回调,先注册事件监听 + if (onLoad) { + manager.on('map:loaded', (map) => { + onLoad(map) + // onLoad 只触发一次,用完即移除 + manager.off('map:loaded', onLoad as () => void) + }) + } + + // 创建地图 + const map = manager.createMap(container, config) + + return map + } + + /** + * 使用预置底图创建地图 + * + * 从 {@link PRESET_BASEMAPS} 中选择一个预定义底图样式。 + * + * @param basemapKey - 底图键名,可选值:'demotiles' | 'osm' + * @param options - 地图工厂配置选项(可选,会覆盖底图默认样式中的 style) + * @returns 创建的 maplibregl.Map 实例 + * @throws 如果传入的 basemapKey 不存在于预置底图列表中 + */ + static createWithBasemap( + basemapKey: keyof typeof PRESET_BASEMAPS, + options: MapFactoryOptions + ): Map { + const basemap = PRESET_BASEMAPS[basemapKey] + + if (!basemap) { + throw new Error( + `[MapFactory] 未知的底图键名: "${basemapKey}",可用值: ${Object.keys(PRESET_BASEMAPS).join(', ')}` + ) + } + + // 使用预置底图的 style,但允许用户覆盖 + return MapFactory.create({ + style: basemap.style, + ...options, + }) + } + + /** + * 注册自定义底图到预置列表 + * + * @param key - 底图唯一键名 + * @param config - 底图图层配置 + */ + static registerBasemap(key: string, config: BasemapLayerConfig): void { + PRESET_BASEMAPS[key] = config + } + + /** + * 移除预置底图 + * + * @param key - 底图键名 + */ + static unregisterBasemap(key: string): void { + delete PRESET_BASEMAPS[key] + } + + /** + * 获取所有已注册的底图列表 + * + * @returns 底图配置记录 + */ + static getRegisteredBasemaps(): Record { + return { ...PRESET_BASEMAPS } + } + + /** + * 获取当前地图实例(便捷方法) + * + * @returns 当前 maplibregl.Map 实例,未创建时返回 null + */ + static getCurrentMap(): Map | null { + return MapFactory.getManager().getMap() + } + + /** + * 销毁当前地图实例(便捷方法) + */ + static destroy(): void { + MapFactory.getManager().destroyMap() + } + + /** + * 订阅地图事件(便捷方法) + * + * @param type - 事件类型 + * @param handler - 事件处理函数 + */ + static on( + type: 'map:loaded' | 'map:destroyed' | 'map:creating', + handler: (...args: any[]) => void + ): void { + MapFactory.getManager().on(type as any, handler) + } + + /** + * 取消订阅地图事件(便捷方法) + * + * @param type - 事件类型 + * @param handler - 要移除的事件处理函数 + */ + static off( + type: 'map:loaded' | 'map:destroyed' | 'map:creating', + handler?: (...args: any[]) => void + ): void { + MapFactory.getManager().off(type as any, handler as any) + } +} diff --git a/src/map/MapManager.ts b/src/map/MapManager.ts new file mode 100644 index 0000000..34bb9d2 --- /dev/null +++ b/src/map/MapManager.ts @@ -0,0 +1,417 @@ +/** + * MapManager - maplibregl.Map 单例管理器 + * + * 基于 mitt 事件总线的地图实例管理器,用于全局管理 maplibregl.Map 的生命周期。 + * 替代原有 GeoScene 项目中的 ytmapUtil.js 单例模式。 + * + * @module map/MapManager + */ + +import maplibregl, { + Map, + MapOptions, + NavigationControl, + NavigationControlOptions, +} from 'maplibre-gl' +import mitt, { Emitter } from 'mitt' + +// ============================================================ +// 类型定义 +// ============================================================ + +/** + * 地图配置接口,继承 maplibregl.MapOptions 并添加自定义配置项 + */ +export interface MapConfig extends Omit { + /** + * 地图容器元素或其 id + */ + container: string | HTMLElement + + /** + * 导航控件配置,设为 false 则禁用导航控件 + * @defaultValue { showCompass: true, showZoom: true, visualizePitch: false } + */ + navigationControl?: NavigationControlOptions | false +} + +/** + * 地图事件类型定义 + * + * 通过 mitt 事件总线触发,供其他模块订阅 + */ +export type MapEvents = { + /** + * 地图实例创建完毕并触发 'load' 事件后触发 + */ + 'map:loaded': Map + + /** + * 地图实例被销毁后触发 + */ + 'map:destroyed': void + + /** + * 地图实例创建开始时触发 + */ + 'map:creating': MapConfig +} + +// ============================================================ +// 默认配置 +// ============================================================ + +/** + * 默认地图中心点坐标(南京) + */ +export const DEFAULT_CENTER: [number, number] = [118.734575, 31.990939] + +/** + * 默认缩放级别 + */ +export const DEFAULT_ZOOM = 10 + +/** + * 默认导航控件配置 + */ +export const DEFAULT_NAVIGATION_CONTROL_OPTIONS: NavigationControlOptions = { + showCompass: true, + showZoom: true, + visualizePitch: false, +} + +// ============================================================ +// MapManager 单例类 +// ============================================================ + +/** + * 地图管理器单例 + * + * 负责全局唯一 maplibregl.Map 实例的创建、销毁与访问, + * 并通过 mitt 事件总线广播地图生命周期事件。 + * + * @example + * ```ts + * // 获取单例 + * const manager = MapManager.getInstance() + * + * // 订阅地图事件 + * manager.on('map:loaded', (map) => { + * console.log('地图已加载', map.getCenter()) + * }) + * + * // 创建地图 + * manager.createMap('map-container', { + * style: 'https://demotiles.maplibre.org/style.json', + * center: [118.734575, 31.990939], + * zoom: 10, + * }) + * + * // 获取当前地图实例 + * const map = manager.getMap() + * + * // 销毁地图 + * manager.destroyMap() + * ``` + */ +export class MapManager { + // ========================================================== + // 静态成员(单例模式) + // ========================================================== + + /** + * 单例实例持有者 + */ + private static instance: MapManager | null = null + + /** + * 获取 MapManager 单例实例 + * + * @returns MapManager 单例 + */ + static getInstance(): MapManager { + if (!MapManager.instance) { + MapManager.instance = new MapManager() + } + return MapManager.instance + } + + /** + * 重置单例(主要用于测试环境) + * + * @internal + */ + static resetInstance(): void { + if (MapManager.instance) { + MapManager.instance.destroyMap() + MapManager.instance = null + } + } + + // ========================================================== + // 实例成员 + // ========================================================== + + /** + * 当前持有的 maplibregl.Map 实例 + */ + private map: Map | null = null + + /** + * 当前持有的 NavigationControl 导航控件实例 + */ + private navigationControl: NavigationControl | null = null + + /** + * mitt 事件总线实例 + */ + private eventBus: Emitter + + /** + * 当前地图配置快照 + */ + private currentConfig: MapConfig | null = null + + /** + * 私有构造函数,防止外部实例化 + */ + private constructor() { + this.eventBus = mitt() + } + + // ========================================================== + // 事件总线 API + // ========================================================== + + /** + * 订阅地图事件 + * + * @typeParam K - 事件类型 + * @param type - 事件名称 + * @param handler - 事件处理函数 + */ + on(type: K, handler: (event: MapEvents[K]) => void): void { + this.eventBus.on(type, handler) + } + + /** + * 取消订阅地图事件 + * + * @typeParam K - 事件类型 + * @param type - 事件名称 + * @param handler - 要移除的事件处理函数(可选,不传则移除该事件的所有监听器) + */ + off(type: K, handler?: (event: MapEvents[K]) => void): void { + this.eventBus.off(type, handler) + } + + /** + * 触发地图事件(内部使用) + * + * @typeParam K - 事件类型 + * @param type - 事件名称 + * @param event - 事件负载 + * @internal + */ + private emit(type: K, event: MapEvents[K]): void { + this.eventBus.emit(type, event) + } + + /** + * 获取内部事件总线,用于高级场景 + * + * @returns mitt 事件发射器 + */ + getEventBus(): Emitter { + return this.eventBus + } + + // ========================================================== + // 地图生命周期 API + // ========================================================== + + /** + * 创建并返回 maplibregl.Map 实例 + * + * 如果已存在地图实例,会先销毁旧实例再创建新实例。 + * 创建完成后会监听地图 'load' 事件,触发后广播 'map:loaded'。 + * + * @param container - 地图容器元素或其 id + * @param options - 地图配置选项(不包含 container 字段) + * @returns 创建的 maplibregl.Map 实例 + * @throws 如果容器元素不存在 + */ + createMap( + container: string | HTMLElement, + options: Omit = {} + ): Map { + // 销毁已有地图实例 + if (this.map) { + this.destroyMap() + } + + // 合并配置 + const config: MapConfig = { + container, + center: options.center ?? DEFAULT_CENTER, + zoom: options.zoom ?? DEFAULT_ZOOM, + ...options, + } + + // 广播创建开始事件 + this.emit('map:creating', config) + + // 创建 MapLibre 地图实例 + this.map = new Map({ + container: config.container, + style: config.style, + center: config.center, + zoom: config.zoom, + bearing: config.bearing, + pitch: config.pitch, + minZoom: config.minZoom, + maxZoom: config.maxZoom, + maxBounds: config.maxBounds, + interactive: config.interactive, + hash: config.hash, + attributionControl: config.attributionControl, + renderWorldCopies: config.renderWorldCopies, + trackResize: config.trackResize, + localIdeographFontFamily: config.localIdeographFontFamily, + transformRequest: config.transformRequest, + scrollZoom: config.scrollZoom, + dragPan: config.dragPan, + dragRotate: config.dragRotate, + boxZoom: config.boxZoom, + doubleClickZoom: config.doubleClickZoom, + touchZoomRotate: config.touchZoomRotate, + touchPitch: config.touchPitch, + keyboard: config.keyboard, + cooperativeGestures: config.cooperativeGestures, + fadeDuration: config.fadeDuration, + crossSourceCollisions: config.crossSourceCollisions, + collectResourceTiming: config.collectResourceTiming, + clickTolerance: config.clickTolerance, + bounds: config.bounds, + fitBoundsOptions: config.fitBoundsOptions, + pixelRatio: config.pixelRatio, + validateStyle: config.validateStyle, + maxTileCacheSize: config.maxTileCacheSize, + maxTileCacheZoomLevels: config.maxTileCacheZoomLevels, + refreshExpiredTiles: config.refreshExpiredTiles, + logoPosition: config.logoPosition, + maplibreLogo: config.maplibreLogo, + bearingSnap: config.bearingSnap, + zoomSnap: config.zoomSnap, + pitchWithRotate: config.pitchWithRotate, + rollEnabled: config.rollEnabled, + reduceMotion: config.reduceMotion, + canvasContextAttributes: config.canvasContextAttributes, + maxCanvasSize: config.maxCanvasSize, + }) + + this.currentConfig = config + + // 添加导航控件 + this.addNavigationControl(config.navigationControl) + + // 监听地图加载完成事件,广播 'map:loaded' + this.map.once('load', () => { + if (this.map) { + this.emit('map:loaded', this.map) + } + }) + + return this.map + } + + /** + * 添加或更新导航控件 + * + * @param options - 导航控件配置,false 表示不添加导航控件 + */ + private addNavigationControl(options: NavigationControlOptions | false | undefined): void { + if (!this.map) return + + // 移除旧控件 + if (this.navigationControl) { + this.map.removeControl(this.navigationControl) + this.navigationControl = null + } + + // 如明确设为 false 则不添加 + if (options === false) return + + // 使用默认或用户配置创建 NavigationControl + const controlOptions = options ?? DEFAULT_NAVIGATION_CONTROL_OPTIONS + this.navigationControl = new NavigationControl(controlOptions) + this.map.addControl(this.navigationControl, 'top-left') + } + + /** + * 获取当前地图实例 + * + * @returns 当前 maplibregl.Map 实例,未创建时返回 null + */ + getMap(): Map | null { + return this.map + } + + /** + * 获取当前导航控件实例 + * + * @returns 当前 NavigationControl 实例,未创建时返回 null + */ + getNavigationControl(): NavigationControl | null { + return this.navigationControl + } + + /** + * 获取当前地图配置 + * + * @returns 当前地图配置快照,未创建时返回 null + */ + getCurrentConfig(): MapConfig | null { + return this.currentConfig + } + + /** + * 销毁当前地图实例 + * + * 调用 map.remove() 清理 DOM 节点和事件监听器, + * 并广播 'map:destroyed' 事件。 + * 销毁后可通过 createMap() 重新创建新实例。 + */ + destroyMap(): void { + if (this.map) { + // 移除导航控件引用 + this.navigationControl = null + + // 销毁地图实例 + this.map.remove() + this.map = null + this.currentConfig = null + + // 广播销毁事件 + this.emit('map:destroyed', undefined) + } + } + + /** + * 检查地图是否已创建 + * + * @returns 地图实例是否存在 + */ + hasMap(): boolean { + return this.map !== null + } + + /** + * 清除事件总线上的所有监听器 + * + * 通常在页面卸载或全局重置时调用。 + */ + clearAllListeners(): void { + this.eventBus.all.clear() + } +} diff --git a/src/map/composables/useLayer.ts b/src/map/composables/useLayer.ts new file mode 100644 index 0000000..28e5001 --- /dev/null +++ b/src/map/composables/useLayer.ts @@ -0,0 +1,480 @@ +/** + * useLayer - 图层 CRUD 操作组合式函数 + * + * 基于 MapManager 单例中的 Map 实例,提供图层的添加、移除、显隐切换、 + * 可见性查询等响应式操作方法。 + * + * @module map/composables/useLayer + */ + +import { ref, computed, readonly, onUnmounted, type Ref, type DeepReadonly } from 'vue' +import type { + LayerSpecification, + CustomLayerInterface, + FilterSpecification, +} from 'maplibre-gl' +import { MapManager } from '../MapManager' +import { useMap } from './useMap' + +// ============================================================ +// 类型定义 +// ============================================================ + +/** + * 图层操作结果 + */ +export interface LayerOperationResult { + /** 是否成功 */ + success: boolean + /** 错误信息(失败时) */ + error?: string +} + +/** + * 图层信息 + */ +export interface LayerInfo { + /** 图层 ID */ + id: string + /** 图层类型 */ + type: string + /** 当前可见性 */ + visible: boolean + /** 图层元数据(如有) */ + metadata?: Record +} + +/** + * 图层可见性映射表 + * + * key 为图层 ID,value 为 Ref 表示该图层可见性 + */ +export interface LayerVisibilityMap { + [layerId: string]: Ref +} + +/** + * useLayer 返回类型 + */ +export interface UseLayerReturn { + /** + * 添加图层到地图 + * + * @param layer - 图层配置(LayerSpecification 或 CustomLayerInterface) + * @param beforeId - 插入到指定图层之前(可选) + * @returns 操作结果 + */ + addLayer: ( + layer: LayerSpecification | CustomLayerInterface, + beforeId?: string + ) => LayerOperationResult + + /** + * 从地图移除图层 + * + * 同时清理该图层的可见性追踪 + * + * @param layerId - 图层 ID + * @returns 操作结果 + */ + removeLayer: (layerId: string) => LayerOperationResult + + /** + * 切换图层可见性 + * + * 如果图层当前可见则隐藏,反之则显示 + * + * @param layerId - 图层 ID + * @returns 操作结果 + */ + toggleLayer: (layerId: string) => LayerOperationResult + + /** + * 设置图层可见性 + * + * @param layerId - 图层 ID + * @param visible - 是否可见 + * @returns 操作结果 + */ + setLayerVisibility: (layerId: string, visible: boolean) => LayerOperationResult + + /** + * 获取图层可见性的响应式引用 + * + * 如果图层不存在则返回始终为 false 的 ref + * + * @param layerId - 图层 ID + * @returns 响应式可见性引用 + */ + getLayerVisibility: (layerId: string) => DeepReadonly> + + /** + * 获取所有已添加图层的 ID 列表 + * + * @returns 图层 ID 数组 + */ + getLayerIds: () => string[] + + /** + * 获取图层信息 + * + * @param layerId - 图层 ID + * @returns 图层信息,不存在则返回 null + */ + getLayerInfo: (layerId: string) => LayerInfo | null + + /** + * 设置图层滤镜 + * + * @param layerId - 图层 ID + * @param filter - 滤镜表达式,传 null 清除滤镜 + * @returns 操作结果 + */ + setLayerFilter: ( + layerId: string, + filter: FilterSpecification | null + ) => LayerOperationResult + + /** + * 所有已追踪图层的可见性映射表(只读) + */ + visibilityMap: DeepReadonly> + + /** + * 当前图层数量 + */ + layerCount: import('vue').ComputedRef +} + +// ============================================================ +// useLayer +// ============================================================ + +/** + * 图层 CRUD 操作组合式函数 + * + * 提供对 MapLibre GL 地图图层的添加、移除、显隐控制等操作。 + * 内部使用 useMap() 获取当前地图实例,确保操作始终针对当前地图。 + * + * @returns 图层操作方法集合 + * + * @example + * ```vue + * + * ``` + */ +export function useLayer(): UseLayerReturn { + // ---------------------------------------------------------- + // 获取当前地图 + // ---------------------------------------------------------- + const { map } = useMap() + + // ---------------------------------------------------------- + // 内部状态 + // ---------------------------------------------------------- + + /** + * 图层可见性映射表 + * + * 追踪所有通过本 composable 操作的图层的可见性 + */ + const visibilityMap = ref({}) + + // ---------------------------------------------------------- + // 内部辅助函数 + // ---------------------------------------------------------- + + /** + * 获取当前 Map 实例,不存在则返回 null + */ + function getMap() { + return map.value + } + + /** + * 检查图层是否存在 + */ + function layerExists(layerId: string): boolean { + const m = getMap() + if (!m) return false + try { + return !!m.getLayer(layerId) + } catch { + return false + } + } + + /** + * 同步图层可见性到内部状态 + */ + function syncLayerVisibility(layerId: string, visible: boolean): void { + if (!visibilityMap.value[layerId]) { + visibilityMap.value[layerId] = ref(visible) + } else { + visibilityMap.value[layerId].value = visible + } + } + + // ---------------------------------------------------------- + // 公开方法 + // ---------------------------------------------------------- + + /** + * 添加图层到地图 + */ + function addLayer( + layer: LayerSpecification | CustomLayerInterface, + beforeId?: string + ): LayerOperationResult { + const m = getMap() + if (!m) { + return { success: false, error: '地图实例不存在,请先创建地图' } + } + + try { + // 检查图层是否已存在 + if (m.getLayer(layer.id)) { + return { success: false, error: `图层 "${layer.id}" 已存在` } + } + + // 检查 beforeId 是否存在 + if (beforeId && !m.getLayer(beforeId)) { + return { + success: false, + error: `参考图层 "${beforeId}" 不存在`, + } + } + + m.addLayer(layer, beforeId) + + // 追踪可见性 + const visibility = 'layout' in layer && layer.layout && 'visibility' in layer.layout + ? (layer.layout as { visibility?: string }).visibility !== 'none' + : true + syncLayerVisibility(layer.id, visibility) + + // 触发响应式更新 + visibilityMap.value = { ...visibilityMap.value } + + return { success: true } + } catch (err) { + return { + success: false, + error: err instanceof Error ? err.message : '添加图层失败', + } + } + } + + /** + * 从地图移除图层 + */ + function removeLayer(layerId: string): LayerOperationResult { + const m = getMap() + if (!m) { + return { success: false, error: '地图实例不存在' } + } + + try { + if (!m.getLayer(layerId)) { + return { success: false, error: `图层 "${layerId}" 不存在` } + } + + m.removeLayer(layerId) + + // 清理可见性追踪 + if (visibilityMap.value[layerId]) { + const newMap = { ...visibilityMap.value } + delete newMap[layerId] + visibilityMap.value = newMap + } + + return { success: true } + } catch (err) { + return { + success: false, + error: err instanceof Error ? err.message : '移除图层失败', + } + } + } + + /** + * 切换图层可见性 + */ + function toggleLayer(layerId: string): LayerOperationResult { + if (!layerExists(layerId)) { + return { success: false, error: `图层 "${layerId}" 不存在` } + } + + const currentVisibility = visibilityMap.value[layerId]?.value ?? true + return setLayerVisibility(layerId, !currentVisibility) + } + + /** + * 设置图层可见性 + */ + function setLayerVisibility(layerId: string, visible: boolean): LayerOperationResult { + const m = getMap() + if (!m) { + return { success: false, error: '地图实例不存在' } + } + + try { + if (!m.getLayer(layerId)) { + return { success: false, error: `图层 "${layerId}" 不存在` } + } + + const visibility = visible ? 'visible' : 'none' + m.setLayoutProperty(layerId, 'visibility', visibility) + + syncLayerVisibility(layerId, visible) + + return { success: true } + } catch (err) { + return { + success: false, + error: err instanceof Error ? err.message : '设置图层可见性失败', + } + } + } + + /** + * 获取图层可见性的响应式引用 + */ + function getLayerVisibility(layerId: string): DeepReadonly> { + if (!visibilityMap.value[layerId]) { + // 惰性初始化:直接从地图读取当前状态 + const m = getMap() + let visible = false + if (m && m.getLayer(layerId)) { + try { + const v = m.getLayoutProperty(layerId, 'visibility') + visible = v !== 'none' + } catch { + visible = true + } + } + visibilityMap.value[layerId] = ref(visible) + visibilityMap.value = { ...visibilityMap.value } + } + + return readonly(visibilityMap.value[layerId]) + } + + /** + * 获取所有已添加图层的 ID 列表 + */ + function getLayerIds(): string[] { + const m = getMap() + if (!m) return [] + return m.getStyle()?.layers?.map((l) => l.id) ?? [] + } + + /** + * 获取图层信息 + */ + function getLayerInfo(layerId: string): LayerInfo | null { + const m = getMap() + if (!m) return null + + try { + const layer = m.getLayer(layerId) + if (!layer) return null + + const visibility = visibilityMap.value[layerId]?.value ?? true + + return { + id: layer.id, + type: layer.type, + visible: visibility, + metadata: (layer as LayerSpecification).metadata as Record | undefined, + } + } catch { + return null + } + } + + /** + * 设置图层滤镜 + */ + function setLayerFilter( + layerId: string, + filter: FilterSpecification | null + ): LayerOperationResult { + const m = getMap() + if (!m) { + return { success: false, error: '地图实例不存在' } + } + + try { + if (!m.getLayer(layerId)) { + return { success: false, error: `图层 "${layerId}" 不存在` } + } + + if (filter === null) { + // 清除滤镜 + m.setFilter(layerId, null as unknown as FilterSpecification) + } else { + m.setFilter(layerId, filter) + } + + return { success: true } + } catch (err) { + return { + success: false, + error: err instanceof Error ? err.message : '设置图层滤镜失败', + } + } + } + + // ---------------------------------------------------------- + // 计算属性 + // ---------------------------------------------------------- + + /** 当前图层数量 */ + const layerCount = computed(() => { + const m = getMap() + if (!m) return 0 + return m.getStyle()?.layers?.length ?? 0 + }) + + // ---------------------------------------------------------- + // 组件卸载时清理 + // ---------------------------------------------------------- + onUnmounted(() => { + visibilityMap.value = {} + }) + + // ---------------------------------------------------------- + // 返回 + // ---------------------------------------------------------- + return { + addLayer, + removeLayer, + toggleLayer, + setLayerVisibility, + getLayerVisibility, + getLayerIds, + getLayerInfo, + setLayerFilter, + visibilityMap: readonly(visibilityMap), + layerCount, + } +} diff --git a/src/map/composables/useMap.ts b/src/map/composables/useMap.ts new file mode 100644 index 0000000..9a78829 --- /dev/null +++ b/src/map/composables/useMap.ts @@ -0,0 +1,247 @@ +/** + * useMap - 响应式地图实例管理组合式函数 + * + * 基于 MapManager 单例提供响应式地图实例、加载状态、中心点、缩放级别等。 + * 自动订阅地图生命周期事件,组件卸载时自动清理。 + * + * @module map/composables/useMap + */ + +import { ref, readonly, onUnmounted, type Ref, type DeepReadonly } from 'vue' +import maplibregl from 'maplibre-gl' +import { MapManager } from '../MapManager' + +// Local type alias: use maplibregl.Map to avoid potential conflicts +// with types re-exported via `export type *` in maplibre-gl's d.ts +type MapInstance = maplibregl.Map + +// ============================================================ +// 类型定义 +// ============================================================ + +/** + * useMap 返回类型 + */ +export interface UseMapReturn { + /** + * 当前 maplibregl.Map 实例(只读) + * + * 地图未创建时为 null,加载完成后为 Map 实例 + */ + map: Ref + + /** + * 地图是否正在加载 + * + * 初始为 true,收到 'map:loaded' 事件后变为 false; + * 地图销毁后重置为 true + */ + loading: DeepReadonly> + + /** + * 地图加载/运行时的错误信息 + * + * 当 map 触发 'error' 事件时更新 + */ + error: DeepReadonly> + + /** + * 地图当前中心点坐标 [lng, lat](只读) + * + * 每次 'moveend' 事件后自动更新 + */ + center: DeepReadonly> + + /** + * 地图当前缩放级别(只读) + * + * 每次 'zoomend' 事件后自动更新 + */ + zoom: DeepReadonly> + + /** + * 地图是否已加载完成 + * + * 等同于 !loading && map !== null + */ + isReady: DeepReadonly> +} + +// ============================================================ +// useMap +// ============================================================ + +/** + * 响应式地图实例管理组合式函数 + * + * 订阅 MapManager 单例的生命周期事件,提供 Vue 响应式的地图状态。 + * 组件卸载时自动取消所有订阅。 + * + * @returns 地图响应式状态与方法 + * + * @example + * ```vue + * + * ``` + */ +export function useMap(): UseMapReturn { + // ---------------------------------------------------------- + // 获取单例 + // ---------------------------------------------------------- + const manager = MapManager.getInstance() + + // ---------------------------------------------------------- + // 响应式状态 + // ---------------------------------------------------------- + + /** 地图实例 */ + const map = ref(manager.getMap()) + + /** 加载状态:初始根据当前是否有已加载的地图判断 */ + const loading = ref(!manager.hasMap()) + + /** 错误信息 */ + const error = ref(null) + + /** 中心点坐标 */ + const center = ref<[number, number] | null>(null) + + /** 缩放级别 */ + const zoom = ref(null) + + /** 是否就绪 */ + const isReady = ref(manager.hasMap()) + + // ---------------------------------------------------------- + // 内部辅助函数 + // ---------------------------------------------------------- + + /** + * 同步中心点和缩放级别 + */ + function syncViewState(m: MapInstance): void { + const c = m.getCenter() + center.value = [c.lng, c.lat] + zoom.value = m.getZoom() + } + + /** + * 绑定 map 实例上的原生事件 + */ + function bindMapEvents(m: MapInstance): void { + m.on('moveend', () => syncViewState(m)) + m.on('zoomend', () => { + zoom.value = m.getZoom() + }) + m.on('error', (e: { error?: Error }) => { + error.value = e.error?.message ?? '地图发生未知错误' + }) + } + + /** + * 解绑 map 实例上的原生事件 + */ + function unbindMapEvents(m: MapInstance): void { + m.off('moveend', () => syncViewState(m)) + m.off('zoomend', () => { + zoom.value = m.getZoom() + }) + m.off('error', () => {}) + } + + // ---------------------------------------------------------- + // 订阅 MapManager 生命周期事件 + // ---------------------------------------------------------- + + /** 地图加载完成 */ + function onMapLoaded(m: MapInstance): void { + map.value = m + loading.value = false + error.value = null + isReady.value = true + + // 同步初始视图状态 + syncViewState(m) + + // 绑定后续的原生地图事件 + bindMapEvents(m) + } + + /** 地图即将创建 */ + function onMapCreating(): void { + loading.value = true + isReady.value = false + error.value = null + } + + /** 地图已销毁 */ + function onMapDestroyed(): void { + // 解绑旧实例的事件 + const m = map.value as MapInstance | null + if (m) { + unbindMapEvents(m) + } + + map.value = null + loading.value = true + isReady.value = false + center.value = null + zoom.value = null + } + + // 注册事件监听 + manager.on('map:loaded', onMapLoaded) + manager.on('map:creating', onMapCreating) + manager.on('map:destroyed', onMapDestroyed) + + // 如果当前已有已加载的地图实例,立即同步状态 + const currentMap = manager.getMap() + if (currentMap && currentMap.loaded()) { + onMapLoaded(currentMap) + } else if (currentMap) { + // 地图存在但尚未加载完成 + map.value = currentMap + loading.value = true + isReady.value = false + + // 监听该实例的 load 事件 + currentMap.once('load', () => { + onMapLoaded(currentMap) + }) + } + + // ---------------------------------------------------------- + // 组件卸载时清理 + // ---------------------------------------------------------- + onUnmounted(() => { + manager.off('map:loaded', onMapLoaded) + manager.off('map:creating', onMapCreating) + manager.off('map:destroyed', onMapDestroyed) + + // 清理原生地图事件 + const m2 = map.value as MapInstance | null + if (m2) { + unbindMapEvents(m2) + } + }) + + // ---------------------------------------------------------- + // 返回只读响应式状态 + // ---------------------------------------------------------- + return { + map: map as Ref, + loading: readonly(loading), + error: readonly(error), + center: readonly(center), + zoom: readonly(zoom), + isReady: readonly(isReady), + } as UseMapReturn +} diff --git a/src/map/composables/usePopup.ts b/src/map/composables/usePopup.ts new file mode 100644 index 0000000..8f0a771 --- /dev/null +++ b/src/map/composables/usePopup.ts @@ -0,0 +1,376 @@ +/** + * usePopup - 地图弹窗管理组合式函数 + * + * 基于 MapManager 单例中的 Map 实例,提供在地图上显示/隐藏 Popup 弹窗的 + * 响应式操作方法。支持自定义 HTML 内容和完整的 Popup 配置选项。 + * + * @module map/composables/usePopup + */ + +import { ref, readonly, onUnmounted, type Ref, type DeepReadonly } from 'vue' +import { Popup, type PopupOptions, type LngLatLike, type Offset } from 'maplibre-gl' +import { useMap } from './useMap' + +// ============================================================ +// 类型定义 +// ============================================================ + +/** + * 扩展的弹窗选项 + * + * 继承 maplibregl.PopupOptions 并增加便利配置项 + */ +export interface UsePopupOptions extends Omit { + /** + * Popup 的 CSS 类名 + */ + className?: string | string[] + + /** + * Popup 最大宽度 + * @defaultValue '240px' + */ + maxWidth?: string + + /** + * 是否在弹窗关闭时自动销毁(移除 DOM) + * @defaultValue true + */ + autoRemove?: boolean + + /** + * 弹窗关闭回调 + */ + onClose?: () => void +} + +/** + * usePopup 返回类型 + */ +export interface UsePopupReturn { + /** + * 当前 Popup 实例(只读) + * + * 无弹窗时为 null + */ + popup: Ref + + /** + * 弹窗是否可见(只读) + */ + isVisible: DeepReadonly> + + /** + * 弹窗当前位置(只读) + * + * 无弹窗时为 null + */ + position: DeepReadonly> + + /** + * 在地图上显示弹窗 + * + * 如果已有弹窗,会先关闭旧弹窗再显示新弹窗。 + * + * @param lngLat - 弹窗位置(经纬度坐标) + * @param html - 弹窗 HTML 内容 + * @param options - 弹窗配置选项(可选) + * @returns Popup 实例 + */ + showPopup: ( + lngLat: LngLatLike, + html: string, + options?: UsePopupOptions + ) => Popup | null + + /** + * 隐藏并销毁当前弹窗 + * + * 调用后 isVisible 变为 false,popup 变为 null + */ + hidePopup: () => void + + /** + * 更新弹窗位置 + * + * @param lngLat - 新的经纬度坐标 + * @returns 是否更新成功 + */ + setPosition: (lngLat: LngLatLike) => boolean + + /** + * 更新弹窗 HTML 内容 + * + * @param html - 新的 HTML 内容 + * @returns 是否更新成功 + */ + setHTML: (html: string) => boolean + + /** + * 设置弹窗偏移量 + * + * @param offset - 偏移量配置 + * @returns 是否设置成功 + */ + setOffset: (offset: Offset) => boolean +} + +// ============================================================ +// usePopup +// ============================================================ + +/** + * 地图弹窗管理组合式函数 + * + * 封装 maplibregl.Popup 的创建、显示、隐藏逻辑,提供 Vue 响应式状态。 + * 同一时间仅管理一个弹窗,新弹窗会覆盖旧弹窗。 + * 组件卸载时自动清理弹窗。 + * + * @returns 弹窗管理方法与响应式状态 + * + * @example + * ```vue + * + * ``` + */ +export function usePopup(): UsePopupReturn { + // ---------------------------------------------------------- + // 获取当前地图 + // ---------------------------------------------------------- + const { map } = useMap() + + // ---------------------------------------------------------- + // 响应式状态 + // ---------------------------------------------------------- + + /** 当前弹窗实例 */ + const popup = ref(null) + + /** 弹窗可见性 */ + const isVisible = ref(false) + + /** 弹窗当前位置 */ + const position = ref(null) + + /** 当前弹窗关闭回调 */ + let currentOnClose: (() => void) | null = null + + // ---------------------------------------------------------- + // 内部辅助函数 + // ---------------------------------------------------------- + + /** + * 获取当前 Map 实例 + */ + function getMap() { + return map.value + } + + /** + * 销毁当前弹窗 + */ + function destroyPopup(): void { + if (popup.value) { + try { + popup.value.remove() + } catch { + // 忽略已移除的弹窗错误 + } + popup.value = null + } + isVisible.value = false + position.value = null + + // 触发关闭回调 + if (currentOnClose) { + const cb = currentOnClose + currentOnClose = null + cb() + } + } + + // ---------------------------------------------------------- + // 公开方法 + // ---------------------------------------------------------- + + /** + * 在地图上显示弹窗 + */ + function showPopup( + lngLat: LngLatLike, + html: string, + options: UsePopupOptions = {} + ): Popup | null { + const m = getMap() + if (!m) { + console.warn('[usePopup] 地图实例不存在,无法显示弹窗') + return null + } + + // 如果已有弹窗,先销毁 + destroyPopup() + + // 提取自定义配置 + const { autoRemove = true, onClose, ...popupOptions } = options + + // 处理 className + let className: string | undefined + if (typeof popupOptions.className === 'string') { + className = popupOptions.className + } else if (Array.isArray(popupOptions.className)) { + className = popupOptions.className.join(' ') + } + + try { + const p = new Popup({ + closeButton: popupOptions.closeButton ?? true, + closeOnClick: popupOptions.closeOnClick ?? true, + closeOnMove: popupOptions.closeOnMove ?? false, + focusAfterOpen: popupOptions.focusAfterOpen ?? true, + anchor: popupOptions.anchor, + offset: popupOptions.offset, + className, + maxWidth: popupOptions.maxWidth ?? '240px', + subpixelPositioning: popupOptions.subpixelPositioning, + }) + + // 设置 HTML 内容和位置 + p.setLngLat(lngLat).setHTML(html).addTo(m) + + // 更新状态 + popup.value = p + isVisible.value = true + position.value = lngLat + currentOnClose = onClose ?? null + + // 监听弹窗关闭事件 + if (autoRemove || onClose) { + p.on('close', () => { + isVisible.value = false + position.value = null + // Use as unknown comparison to avoid TS deep type instantiation on Popup + if ((popup.value as unknown) === p) { + popup.value = null + } + if (currentOnClose) { + const cb = currentOnClose + currentOnClose = null + cb() + } + }) + } + + return p + } catch (err) { + console.error('[usePopup] 创建弹窗失败:', err) + return null + } + } + + /** + * 隐藏并销毁当前弹窗 + */ + function hidePopup(): void { + destroyPopup() + } + + /** + * 更新弹窗位置 + */ + function setPosition(lngLat: LngLatLike): boolean { + if (!popup.value) { + console.warn('[usePopup] 当前没有活动的弹窗') + return false + } + + try { + popup.value.setLngLat(lngLat) + position.value = lngLat + return true + } catch (err) { + console.error('[usePopup] 更新弹窗位置失败:', err) + return false + } + } + + /** + * 更新弹窗 HTML 内容 + */ + function setHTML(html: string): boolean { + if (!popup.value) { + console.warn('[usePopup] 当前没有活动的弹窗') + return false + } + + try { + popup.value.setHTML(html) + return true + } catch (err) { + console.error('[usePopup] 更新弹窗内容失败:', err) + return false + } + } + + /** + * 设置弹窗偏移量 + */ + function setOffset(offset: Offset): boolean { + if (!popup.value) { + console.warn('[usePopup] 当前没有活动的弹窗') + return false + } + + try { + popup.value.setOffset(offset) + return true + } catch (err) { + console.error('[usePopup] 设置弹窗偏移量失败:', err) + return false + } + } + + // ---------------------------------------------------------- + // 组件卸载时清理 + // ---------------------------------------------------------- + onUnmounted(() => { + destroyPopup() + currentOnClose = null + }) + + // ---------------------------------------------------------- + // 返回 + // ---------------------------------------------------------- + return { + popup: popup as Ref, + isVisible: readonly(isVisible), + position: readonly(position), + showPopup, + hidePopup, + setPosition, + setHTML, + setOffset, + } as UsePopupReturn +} diff --git a/src/map/sources/tdt-source.ts b/src/map/sources/tdt-source.ts new file mode 100644 index 0000000..fb123a2 --- /dev/null +++ b/src/map/sources/tdt-source.ts @@ -0,0 +1,354 @@ +/** + * TdtSource - 天地图 WMTS 栅格瓦片源(MapLibre GL 适配) + * + * 提供将天地图 WMTS 服务转换为 maplibregl 栅格瓦片源配置的工具函数。 + * 替代原有 GeoScene 项目中的 TdtLayer.js,通过自定义 tiles URL 模板 + * 实现天地图六种底图/注记样式的地图加载。 + * + * @module map/sources/tdt-source + */ + +import type { RasterSourceSpecification, RasterLayerSpecification } from 'maplibre-gl' + +// ============================================================ +// 常量定义 +// ============================================================ + +/** + * 天地图样式中文名称映射 + */ +export const TDT_STYLE_NAMES: Record = { + vec: '矢量底图', + img: '影像底图', + ter: '地形晕渲', + cva: '矢量注记', + cia: '影像注记', + cta: '地形注记', +} as const + +/** + * 天地图子域列表(用于负载均衡) + */ +export const TDT_SUBDOMAINS: string[] = ['0', '1', '2', '3', '4', '5', '6', '7'] + +/** + * 天地图默认瓦片服务器地址 + */ +export const TDT_DEFAULT_URL = 'https://t{s}.tianditu.gov.cn' + +/** + * 天地图 WMTS 地址模板 + * + * 占位符说明: + * - `{style}`: 图层样式(vec/img/ter/cva/cia/cta) + * - `{matrix}`: 瓦片矩阵集标识(c=经纬度,w=墨卡托) + * - `{z}`: 缩放级别(TILEMATRIX) + * - `{y}`: 瓦片行号(TILEROW) + * - `{x}`: 瓦片列号(TILECOL) + * - `{s}`: 子域编号(负载均衡) + */ +export const TDT_WMTS_TEMPLATE = + '/{style}_{matrix}/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER={style}&STYLE=default&TILEMATRIXSET={matrix}&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=tiles' + +// ============================================================ +// 类型定义 +// ============================================================ + +/** + * 天地图图层样式类型 + * + * - `vec`: 矢量底图 + * - `img`: 影像底图 + * - `ter`: 地形晕渲 + * - `cva`: 矢量注记(中文注记叠加层) + * - `cia`: 影像注记(中文注记叠加层) + * - `cta`: 地形注记(中文注记叠加层) + */ +export type TdtStyle = 'vec' | 'img' | 'ter' | 'cva' | 'cia' | 'cta' + +/** + * 天地图瓦片矩阵集类型 + * + * - `c`: 经纬度投影(EPSG:4490 / CGCS2000) + * - `w`: Web 墨卡托投影(EPSG:3857) + */ +export type TdtMatrix = 'c' | 'w' + +/** + * 天地图暗色主题效果 CSS filter + * + * 当 theme 为 'dark' 时,通过 canvas 渲染后应用此 CSS 滤镜 + */ +export const TDT_DARK_THEME_FILTER = + 'invert(82%) sepia(80%) hue-rotate(180deg) saturate(340%)' + +/** + * 天地图瓦片源配置选项 + */ +export interface TdtSourceOptions { + /** + * 天地图图层样式 + * @defaultValue 'vec' + */ + style?: TdtStyle + + /** + * 瓦片矩阵集 + * + * - `'c'`: 经纬度投影(CGCS2000),适合国内应用 + * - `'w'`: Web 墨卡托投影,适合与 OSM 等国际底图叠加 + * + * @defaultValue 'c' + */ + matrix?: TdtMatrix + + /** + * 天地图 API 密钥(tk 参数) + * + * 注册地址:https://console.tiangong.gov.cn/ + * + * @defaultValue ''(不传则不追加 tk 参数) + */ + tk?: string + + /** + * 天地图瓦片服务器地址 + * @defaultValue 'https://t{s}.tianditu.gov.cn' + */ + url?: string + + /** + * 子域列表(负载均衡用) + * @defaultValue ['0', '1', '2', '3', '4', '5', '6', '7'] + */ + subdomains?: string[] + + /** + * 最小缩放级别 + * @defaultValue 0 + */ + minzoom?: number + + /** + * 最大缩放级别(天地图在线瓦片最高 18 级) + * @defaultValue 18 + */ + maxzoom?: number + + /** + * 瓦片大小(像素) + * @defaultValue 256 + */ + tileSize?: number + + /** + * 图层属性(visible、opacity 等) + */ + layer?: Partial> +} + +/** + * 天地图源创建结果 + */ +export interface TdtSourceResult { + /** + * 源 ID(由 style 和 matrix 拼接生成) + */ + sourceId: string + + /** + * MapLibre 源配置(可直接传入 map.addSource) + */ + source: RasterSourceSpecification + + /** + * MapLibre 图层配置(可直接传入 map.addLayer) + */ + layer: RasterLayerSpecification +} + +// ============================================================ +// 内部工具函数 +// ============================================================ + +/** + * 构建天地图 WMTS 瓦片 URL 模板 + * + * 将 {style}/{matrix}/{tk}/{s} 等参数注入 URL 模板, + * 保留 {z}/{x}/{y} 占位符供 MapLibre 运行时替换。 + * + * @param options - 源配置选项 + * @returns 完整的瓦片 URL 模板字符串 + */ +function buildTileUrlTemplate(options: TdtSourceOptions): string { + const { + url = TDT_DEFAULT_URL, + style = 'vec', + matrix = 'c', + tk = '', + } = options + + let template = TDT_WMTS_TEMPLATE + .replace(/\{style\}/g, style) + .replace(/\{matrix\}/g, matrix) + + // 拼接基础 URL + let fullUrl = url + template + + // 追加 tk 参数(需编码) + if (tk) { + fullUrl += '&tk=' + encodeURIComponent(tk) + } + + return fullUrl +} + +// ============================================================ +// 公开 API +// ============================================================ + +/** + * 生成天地图源 ID + * + * 格式为 `tdt-{style}-{matrix}`,例如 `tdt-vec-c`。 + * + * @param style - 图层样式 + * @param matrix - 瓦片矩阵集 + * @returns 源 ID 字符串 + */ +export function getTdtSourceId(style: TdtStyle = 'vec', matrix: TdtMatrix = 'c'): string { + return `tdt-${style}-${matrix}` +} + +/** + * 生成天地图图层 ID + * + * @param style - 图层样式 + * @param matrix - 瓦片矩阵集 + * @returns 图层 ID 字符串 + */ +export function getTdtLayerId(style: TdtStyle = 'vec', matrix: TdtMatrix = 'c'): string { + return `tdt-layer-${style}-${matrix}` +} + +/** + * 创建天地图栅格瓦片源与图层配置 + * + * 返回 MapLibre GL 兼容的 source 和 layer 配置对象, + * 可用于 `map.addSource()` 和 `map.addLayer()`。 + * + * @param options - 天地图源配置选项 + * @returns 包含 source、layer 及 ID 的配置对象 + * + * @example + * ```ts + * import { createTdtSource } from '@/map/sources/tdt-source' + * + * // 创建矢量底图源 + * const { sourceId, source, layer } = createTdtSource({ + * style: 'vec', + * matrix: 'c', + * tk: 'your-tianditu-key', + * }) + * + * map.addSource(sourceId, source) + * map.addLayer(layer) + * + * // 叠加矢量注记层 + * const annotation = createTdtSource({ + * style: 'cva', + * matrix: 'c', + * tk: 'your-tianditu-key', + * }) + * map.addSource(annotation.sourceId, annotation.source) + * map.addLayer(annotation.layer) + * ``` + */ +export function createTdtSource(options: TdtSourceOptions = {}): TdtSourceResult { + const { + style = 'vec', + matrix = 'c', + subdomains = TDT_SUBDOMAINS, + minzoom = 0, + maxzoom = 18, + tileSize = 256, + layer: layerOptions = {}, + } = options + + const sourceId = getTdtSourceId(style, matrix) + const layerId = getTdtLayerId(style, matrix) + const tileUrl = buildTileUrlTemplate(options) + const title = TDT_STYLE_NAMES[style] ?? style + + // ---------------------------------------------------------- + // 构建源配置 + // ---------------------------------------------------------- + const source: RasterSourceSpecification = { + type: 'raster', + tiles: [tileUrl], + tileSize, + minzoom, + maxzoom, + attribution: + '© 天地图', + } + + // ---------------------------------------------------------- + // 构建图层配置 + // ---------------------------------------------------------- + const layer: RasterLayerSpecification = { + id: layerId, + type: 'raster', + source: sourceId, + minzoom, + maxzoom, + metadata: { + title, + style, + matrix, + type: 'TdtLayer', + }, + ...layerOptions, + } as RasterLayerSpecification + + return { sourceId, source, layer } +} + +/** + * 创建天地图底图+注记的完整图层组 + * + * 同时创建底图图层(vec/img/ter)和对应的中文注记图层(cva/cia/cta), + * 注记图层会自动放置在底图图层之上。 + * + * @param style - 底图样式(vec/img/ter),注记自动匹配 + * @param options - 共享的源配置(tk、matrix 等) + * @returns 包含底图和注记两个 TdtSourceResult 的数组 + * + * @example + * ```ts + * const [basemap, annotation] = createTdtLayerGroup('vec', { tk: 'your-key' }) + * // 先加底图,再加注记(注记在上层) + * map.addSource(basemap.sourceId, basemap.source) + * map.addLayer(basemap.layer) + * map.addSource(annotation.sourceId, annotation.source) + * map.addLayer(annotation.layer) + * ``` + */ +export function createTdtLayerGroup( + style: 'vec' | 'img' | 'ter', + options: Omit = {} +): [TdtSourceResult, TdtSourceResult] { + const annotationStyleMap: Record<'vec' | 'img' | 'ter', TdtStyle> = { + vec: 'cva', + img: 'cia', + ter: 'cta', + } + + const basemap = createTdtSource({ ...options, style }) + const annotation = createTdtSource({ + ...options, + style: annotationStyleMap[style], + }) + + return [basemap, annotation] +} diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..527d4fb --- /dev/null +++ b/src/style.css @@ -0,0 +1,296 @@ +:root { + --text: #6b6375; + --text-h: #08060d; + --bg: #fff; + --border: #e5e4e7; + --code-bg: #f4f3ec; + --accent: #aa3bff; + --accent-bg: rgba(170, 59, 255, 0.1); + --accent-border: rgba(170, 59, 255, 0.5); + --social-bg: rgba(244, 243, 236, 0.5); + --shadow: + rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px; + + --sans: system-ui, 'Segoe UI', Roboto, sans-serif; + --heading: system-ui, 'Segoe UI', Roboto, sans-serif; + --mono: ui-monospace, Consolas, monospace; + + font: 18px/145% var(--sans); + letter-spacing: 0.18px; + color-scheme: light dark; + color: var(--text); + background: var(--bg); + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + @media (max-width: 1024px) { + font-size: 16px; + } +} + +@media (prefers-color-scheme: dark) { + :root { + --text: #9ca3af; + --text-h: #f3f4f6; + --bg: #16171d; + --border: #2e303a; + --code-bg: #1f2028; + --accent: #c084fc; + --accent-bg: rgba(192, 132, 252, 0.15); + --accent-border: rgba(192, 132, 252, 0.5); + --social-bg: rgba(47, 48, 58, 0.5); + --shadow: + rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px; + } + + #social .button-icon { + filter: invert(1) brightness(2); + } +} + +body { + margin: 0; +} + +h1, +h2 { + font-family: var(--heading); + font-weight: 500; + color: var(--text-h); +} + +h1 { + font-size: 56px; + letter-spacing: -1.68px; + margin: 32px 0; + @media (max-width: 1024px) { + font-size: 36px; + margin: 20px 0; + } +} +h2 { + font-size: 24px; + line-height: 118%; + letter-spacing: -0.24px; + margin: 0 0 8px; + @media (max-width: 1024px) { + font-size: 20px; + } +} +p { + margin: 0; +} + +code, +.counter { + font-family: var(--mono); + display: inline-flex; + border-radius: 4px; + color: var(--text-h); +} + +code { + font-size: 15px; + line-height: 135%; + padding: 4px 8px; + background: var(--code-bg); +} + +.counter { + font-size: 16px; + padding: 5px 10px; + border-radius: 5px; + color: var(--accent); + background: var(--accent-bg); + border: 2px solid transparent; + transition: border-color 0.3s; + margin-bottom: 24px; + + &:hover { + border-color: var(--accent-border); + } + &:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; + } +} + +.hero { + position: relative; + + .base, + .framework, + .vite { + inset-inline: 0; + margin: 0 auto; + } + + .base { + width: 170px; + position: relative; + z-index: 0; + } + + .framework, + .vite { + position: absolute; + } + + .framework { + z-index: 1; + top: 34px; + height: 28px; + transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg) + scale(1.4); + } + + .vite { + z-index: 0; + top: 107px; + height: 26px; + width: auto; + transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg) + scale(0.8); + } +} + +#app { + width: 1126px; + max-width: 100%; + margin: 0 auto; + text-align: center; + border-inline: 1px solid var(--border); + min-height: 100svh; + display: flex; + flex-direction: column; + box-sizing: border-box; +} + +#center { + display: flex; + flex-direction: column; + gap: 25px; + place-content: center; + place-items: center; + flex-grow: 1; + + @media (max-width: 1024px) { + padding: 32px 20px 24px; + gap: 18px; + } +} + +#next-steps { + display: flex; + border-top: 1px solid var(--border); + text-align: left; + + & > div { + flex: 1 1 0; + padding: 32px; + @media (max-width: 1024px) { + padding: 24px 20px; + } + } + + .icon { + margin-bottom: 16px; + width: 22px; + height: 22px; + } + + @media (max-width: 1024px) { + flex-direction: column; + text-align: center; + } +} + +#docs { + border-right: 1px solid var(--border); + + @media (max-width: 1024px) { + border-right: none; + border-bottom: 1px solid var(--border); + } +} + +#next-steps ul { + list-style: none; + padding: 0; + display: flex; + gap: 8px; + margin: 32px 0 0; + + .logo { + height: 18px; + } + + a { + color: var(--text-h); + font-size: 16px; + border-radius: 6px; + background: var(--social-bg); + display: flex; + padding: 6px 12px; + align-items: center; + gap: 8px; + text-decoration: none; + transition: box-shadow 0.3s; + + &:hover { + box-shadow: var(--shadow); + } + .button-icon { + height: 18px; + width: 18px; + } + } + + @media (max-width: 1024px) { + margin-top: 20px; + flex-wrap: wrap; + justify-content: center; + + li { + flex: 1 1 calc(50% - 8px); + } + + a { + width: 100%; + justify-content: center; + box-sizing: border-box; + } + } +} + +#spacer { + height: 88px; + border-top: 1px solid var(--border); + @media (max-width: 1024px) { + height: 48px; + } +} + +.ticks { + position: relative; + width: 100%; + + &::before, + &::after { + content: ''; + position: absolute; + top: -4.5px; + border: 5px solid transparent; + } + + &::before { + left: 0; + border-left-color: var(--border); + } + &::after { + right: 0; + border-right-color: var(--border); + } +} diff --git a/src/styles/index.scss b/src/styles/index.scss new file mode 100644 index 0000000..d87e1fa --- /dev/null +++ b/src/styles/index.scss @@ -0,0 +1,291 @@ +// ============================================================ +// Yuto Water H5 — Global Styles +// Mobile-first · No Tailwind · Dark mode aware +// ============================================================ + +@use './variables' as *; + +// ── CSS Reset (minimal, mobile-focused) ──────────────────── +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +// ── HTML & Body ───────────────────────────────────────────── +html { + // Smooth scrolling + scroll-behavior: smooth; + // Prevent text size adjustment on orientation change + -webkit-text-size-adjust: 100%; + // Font smoothing + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + // Prevent pull-to-refresh / overscroll bounce on iOS + overscroll-behavior: none; +} + +body { + font-family: $font-family-base; + font-size: $font-size-base; + font-weight: $font-weight-regular; + line-height: $line-height-normal; + color: var(--color-text-primary); + background-color: var(--color-bg-page); + // Mobile-first: full viewport width + width: 100%; + min-height: 100vh; + // Safe area insets for notched devices + padding-top: $safe-area-inset-top; + padding-bottom: $safe-area-inset-bottom; + // Prevent horizontal overflow + overflow-x: hidden; + // Mobile tap highlight removal + -webkit-tap-highlight-color: transparent; + // Improve touch responsiveness + touch-action: manipulation; + // Enable momentum scrolling on iOS + -webkit-overflow-scrolling: touch; +} + +// ── Typography Defaults ───────────────────────────────────── +h1, h2, h3, h4, h5, h6 { + font-weight: $font-weight-semibold; + line-height: $line-height-tight; + color: var(--color-text-primary); +} + +h1 { font-size: $font-size-xxxl; } +h2 { font-size: $font-size-xxl; } +h3 { font-size: $font-size-xl; } +h4 { font-size: $font-size-lg; } +h5 { font-size: $font-size-md; } +h6 { font-size: $font-size-base; } + +p { + margin-bottom: $spacing-sm; + color: var(--color-text-regular); +} + +a { + color: var(--color-primary); + text-decoration: none; + -webkit-tap-highlight-color: transparent; + + &:active { + opacity: 0.7; + } +} + +// ── Form Elements ─────────────────────────────────────────── +input, +textarea, +select, +button { + font-family: inherit; + font-size: inherit; + color: inherit; + // iOS default styling reset + -webkit-appearance: none; + appearance: none; + // Remove inner shadow on iOS inputs + background-clip: padding-box; +} + +// Fix iOS input zoom on focus (prevents zoom for font-size >= 16px on iOS) +input, +textarea, +select { + font-size: $font-size-md; +} + +button { + cursor: pointer; + border: none; + background: none; + -webkit-tap-highlight-color: transparent; + touch-action: manipulation; + + &:disabled { + cursor: not-allowed; + opacity: 0.5; + } +} + +// ── Lists ─────────────────────────────────────────────────── +ul, ol { + list-style: none; +} + +// ── Images & Media ────────────────────────────────────────── +img, +video, +svg { + display: block; + max-width: 100%; + height: auto; +} + +img { + // Prevent image dragging + -webkit-user-drag: none; + user-select: none; +} + +// ── Table defaults ────────────────────────────────────────── +table { + border-collapse: collapse; + width: 100%; +} + +// ── Focus Styles (accessibility) ──────────────────────────── +:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 2px; +} + +// Remove focus outline for mouse/touch users (browser handles :focus-visible) +:focus:not(:focus-visible) { + outline: none; +} + +// ── Scrollbar Styling (WebKit) ────────────────────────────── +::-webkit-scrollbar { + width: 4px; + height: 4px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: var(--color-border-dark); + border-radius: $radius-round; + + &:hover { + background: var(--color-text-placeholder); + } +} + +// ── Selection ─────────────────────────────────────────────── +::selection { + background: var(--color-primary); + color: var(--color-text-inverse); +} + +// ── Utility: Safe Area Padding ────────────────────────────── +.safe-area-top { + padding-top: $safe-area-inset-top; +} + +.safe-area-bottom { + padding-bottom: $safe-area-inset-bottom; +} + +// ── Utility: Screen Reader Only ───────────────────────────── +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +// ── Utility: Custom Scroll Container ──────────────────────── +.scroll-container { + overflow-y: auto; + -webkit-overflow-scrolling: touch; +} + +// ── Page Wrapper (centered, max-width constrained) ────────── +.page-wrapper { + max-width: $max-width-mobile; + margin: 0 auto; + min-height: 100vh; + background: var(--color-bg-page); +} + +// ── Card Component Base ───────────────────────────────────── +.card { + background: var(--color-bg-card); + border-radius: var(--radius-md); + box-shadow: var(--shadow-sm); + padding: $spacing-md; + margin: $spacing-sm $spacing-md; + + &--elevated { + box-shadow: var(--shadow-md); + } + + &--flat { + box-shadow: none; + border: 1px solid var(--color-border); + } +} + +// ── Flex Helpers ──────────────────────────────────────────── +.flex-center { + display: flex; + align-items: center; + justify-content: center; +} + +.flex-between { + display: flex; + align-items: center; + justify-content: space-between; +} + +// ── Text Helpers ──────────────────────────────────────────── +.text-primary { color: var(--color-primary); } +.text-success { color: var(--color-success); } +.text-warning { color: var(--color-warning); } +.text-danger { color: var(--color-danger); } +.text-secondary { color: var(--color-text-secondary); } +.text-ellipsis { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +// ── Spacing Utility Classes ────────────────────────────────── +@each $size in (xxs, xs, sm, md, lg, xl, xxl, xxxl) { + .m-#{$size} { margin: var(--spacing-#{$size}); } + .mt-#{$size} { margin-top: var(--spacing-#{$size}); } + .mb-#{$size} { margin-bottom: var(--spacing-#{$size}); } + .ml-#{$size} { margin-left: var(--spacing-#{$size}); } + .mr-#{$size} { margin-right: var(--spacing-#{$size}); } + .mx-#{$size} { margin-left: var(--spacing-#{$size}); margin-right: var(--spacing-#{$size}); } + .my-#{$size} { margin-top: var(--spacing-#{$size}); margin-bottom: var(--spacing-#{$size}); } + + .p-#{$size} { padding: var(--spacing-#{$size}); } + .pt-#{$size} { padding-top: var(--spacing-#{$size}); } + .pb-#{$size} { padding-bottom: var(--spacing-#{$size}); } + .pl-#{$size} { padding-left: var(--spacing-#{$size}); } + .pr-#{$size} { padding-right: var(--spacing-#{$size}); } + .px-#{$size} { padding-left: var(--spacing-#{$size}); padding-right: var(--spacing-#{$size}); } + .py-#{$size} { padding-top: var(--spacing-#{$size}); padding-bottom: var(--spacing-#{$size}); } +} + +// ── Dark Mode Transition (smooth theme switch) ────────────── +body, +body *, +body *::before, +body *::after { + transition: + background-color $transition-base, + border-color $transition-base, + color $transition-fast; +} + +// Disable transitions on page load (prevents flash) +.preload * { + transition: none !important; +} diff --git a/src/styles/variables.scss b/src/styles/variables.scss new file mode 100644 index 0000000..b3d85df --- /dev/null +++ b/src/styles/variables.scss @@ -0,0 +1,274 @@ +// ============================================================ +// Yuto Water H5 — Design Tokens +// Water-blue theme · Mobile-first · Dark mode ready +// ============================================================ + +// ── Brand Colors ──────────────────────────────────────────── +$color-primary: #2196F3; +$color-primary-light: #64B5F6; +$color-primary-dark: #1976D2; +$color-primary-bg: #E3F2FD; + +$color-success: #07C160; +$color-success-light: #69E09E; +$color-success-dark: #06AD56; +$color-success-bg: #E8F8EF; + +$color-warning: #FF976A; +$color-warning-light: #FFB899; +$color-warning-dark: #ED7A4C; +$color-warning-bg: #FFF3ED; + +$color-danger: #EE0A24; +$color-danger-light: #F56C6C; +$color-danger-dark: #D0091F; +$color-danger-bg: #FDECEC; + +// ── Neutral Colors ────────────────────────────────────────── +$color-white: #FFFFFF; +$color-gray-1: #F7F8FA; +$color-gray-2: #F2F3F5; +$color-gray-3: #EBEDF0; +$color-gray-4: #DCDFE6; +$color-gray-5: #C8C9CC; +$color-gray-6: #969799; +$color-gray-7: #646566; +$color-gray-8: #323233; + +$color-black: #1A1A1A; + +// ── Text Colors ───────────────────────────────────────────── +$color-text-primary: $color-gray-8; +$color-text-regular: $color-gray-7; +$color-text-secondary: $color-gray-6; +$color-text-placeholder:$color-gray-5; +$color-text-inverse: $color-white; + +// ── Background Colors ─────────────────────────────────────── +$color-bg-page: $color-gray-1; +$color-bg-card: $color-white; +$color-bg-elevated: $color-white; +$color-bg-mask: rgba(0, 0, 0, 0.6); + +// ── Border Colors ─────────────────────────────────────────── +$color-border: $color-gray-3; +$color-border-light: $color-gray-2; +$color-border-dark: $color-gray-4; + +// ── Font Family ───────────────────────────────────────────── +$font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', + 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', + Helvetica, Arial, sans-serif; +$font-family-number: 'SF Mono', 'Menlo', 'Consolas', 'Courier New', monospace; + +// ── Font Sizes (mobile-first modular scale) ──────────────── +$font-size-xs: 10px; +$font-size-sm: 12px; +$font-size-base: 14px; +$font-size-md: 16px; +$font-size-lg: 18px; +$font-size-xl: 20px; +$font-size-xxl: 24px; +$font-size-xxxl: 30px; + +// ── Font Weights ──────────────────────────────────────────── +$font-weight-light: 300; +$font-weight-regular: 400; +$font-weight-medium: 500; +$font-weight-semibold: 600; +$font-weight-bold: 700; + +// ── Line Heights ──────────────────────────────────────────── +$line-height-tight: 1.2; +$line-height-normal: 1.4; +$line-height-relaxed: 1.6; +$line-height-loose: 1.8; + +// ── Spacing Scale (4px base) ─────────────────────────────── +$spacing-xxs: 4px; +$spacing-xs: 8px; +$spacing-sm: 12px; +$spacing-md: 16px; +$spacing-lg: 20px; +$spacing-xl: 24px; +$spacing-xxl: 32px; +$spacing-xxxl: 48px; + +// ── Border Radius ─────────────────────────────────────────── +$radius-sm: 4px; +$radius-md: 8px; +$radius-lg: 12px; +$radius-xl: 16px; +$radius-round: 999px; +$radius-circle: 50%; + +// ── Shadows ───────────────────────────────────────────────── +$shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05); +$shadow-md: 0 2px 8px rgba(0, 0, 0, 0.08); +$shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.1); +$shadow-xl: 0 8px 24px rgba(0, 0, 0, 0.12); + +// ── Z-Index Scale ─────────────────────────────────────────── +$z-index-dropdown: 1000; +$z-index-sticky: 1020; +$z-index-fixed: 1030; +$z-index-modal-backdrop:1040; +$z-index-modal: 1050; +$z-index-popover: 1060; +$z-index-tooltip: 1070; +$z-index-toast: 1080; + +// ── Transitions ───────────────────────────────────────────── +$transition-fast: 0.15s ease; +$transition-base: 0.3s ease; +$transition-slow: 0.5s ease; + +// ── Layout ────────────────────────────────────────────────── +$max-width-mobile: 750px; +$safe-area-inset-top: env(safe-area-inset-top, 0px); +$safe-area-inset-bottom: env(safe-area-inset-bottom, 0px); + +// ════════════════════════════════════════════════════════════ +// CSS Custom Properties (for runtime theme switching) +// ════════════════════════════════════════════════════════════ + +:root { + // Brand + --color-primary: #{$color-primary}; + --color-primary-light: #{$color-primary-light}; + --color-primary-dark: #{$color-primary-dark}; + --color-primary-bg: #{$color-primary-bg}; + + --color-success: #{$color-success}; + --color-success-light: #{$color-success-light}; + --color-success-dark: #{$color-success-dark}; + --color-success-bg: #{$color-success-bg}; + + --color-warning: #{$color-warning}; + --color-warning-light: #{$color-warning-light}; + --color-warning-dark: #{$color-warning-dark}; + --color-warning-bg: #{$color-warning-bg}; + + --color-danger: #{$color-danger}; + --color-danger-light: #{$color-danger-light}; + --color-danger-dark: #{$color-danger-dark}; + --color-danger-bg: #{$color-danger-bg}; + + // Text + --color-text-primary: #{$color-text-primary}; + --color-text-regular: #{$color-text-regular}; + --color-text-secondary: #{$color-text-secondary}; + --color-text-placeholder: #{$color-text-placeholder}; + --color-text-inverse: #{$color-text-inverse}; + + // Backgrounds + --color-bg-page: #{$color-bg-page}; + --color-bg-card: #{$color-bg-card}; + --color-bg-elevated: #{$color-bg-elevated}; + --color-bg-mask: #{$color-bg-mask}; + + // Borders + --color-border: #{$color-border}; + --color-border-light: #{$color-border-light}; + --color-border-dark: #{$color-border-dark}; + + // Shadows + --shadow-sm: #{$shadow-sm}; + --shadow-md: #{$shadow-md}; + --shadow-lg: #{$shadow-lg}; + --shadow-xl: #{$shadow-xl}; + + // Radii + --radius-sm: #{$radius-sm}; + --radius-md: #{$radius-md}; + --radius-lg: #{$radius-lg}; + --radius-xl: #{$radius-xl}; + --radius-round: #{$radius-round}; + + // Spacing + --spacing-xxs: #{$spacing-xxs}; + --spacing-xs: #{$spacing-xs}; + --spacing-sm: #{$spacing-sm}; + --spacing-md: #{$spacing-md}; + --spacing-lg: #{$spacing-lg}; + --spacing-xl: #{$spacing-xl}; + --spacing-xxl: #{$spacing-xxl}; + --spacing-xxxl: #{$spacing-xxxl}; + + // Font + --font-size-xs: #{$font-size-xs}; + --font-size-sm: #{$font-size-sm}; + --font-size-base: #{$font-size-base}; + --font-size-md: #{$font-size-md}; + --font-size-lg: #{$font-size-lg}; + --font-size-xl: #{$font-size-xl}; + --font-size-xxl: #{$font-size-xxl}; + --font-size-xxxl: #{$font-size-xxxl}; + + // Transitions + --transition-fast: #{$transition-fast}; + --transition-base: #{$transition-base}; + --transition-slow: #{$transition-slow}; +} + +// ── Dark Mode ─────────────────────────────────────────────── + +// Dark theme variable mapping (defined first so it can be @included below) +@mixin dark-theme-vars { + // Brand — slightly softened for dark backgrounds + --color-primary: #42A5F5; + --color-primary-light: #90CAF9; + --color-primary-dark: #1E88E5; + --color-primary-bg: #0D2137; + + --color-success: #07C160; + --color-success-light: #69E09E; + --color-success-dark: #06AD56; + --color-success-bg: #0D2818; + + --color-warning: #FF976A; + --color-warning-light: #FFB899; + --color-warning-dark: #ED7A4C; + --color-warning-bg: #2B1A10; + + --color-danger: #EE0A24; + --color-danger-light: #F56C6C; + --color-danger-dark: #D0091F; + --color-danger-bg: #2B0D10; + + // Text — inverted hierarchy + --color-text-primary: #E5E5E5; + --color-text-regular: #B3B3B3; + --color-text-secondary: #8C8C8C; + --color-text-placeholder: #666666; + --color-text-inverse: #1A1A1A; + + // Backgrounds + --color-bg-page: #0F0F0F; + --color-bg-card: #1A1A1A; + --color-bg-elevated: #242424; + --color-bg-mask: rgba(0, 0, 0, 0.7); + + // Borders + --color-border: #2E2E2E; + --color-border-light: #242424; + --color-border-dark: #3A3A3A; + + // Shadows — darker for dark mode + --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3); + --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.4); + --shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.5); + --shadow-xl: 0 8px 24px rgba(0, 0, 0, 0.6); +} + +// 1) System preference (auto) +@media (prefers-color-scheme: dark) { + :root:not([data-theme='light']) { + @include dark-theme-vars; + } +} + +// 2) Explicit [data-theme='dark'] override +[data-theme='dark'] { + @include dark-theme-vars; +} diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..46dca8f --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1,12 @@ +/// + +declare module '*.vue' { + import type { DefineComponent } from 'vue' + const component: DefineComponent<{}, {}, any> + export default component +} + +declare module '*.scss' { + const content: string + export default content +} diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..5c750c5 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "types": ["vite/client"], + + /* Linting */ + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..74ad5f6 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "erasableSyntaxOnly": true, + "skipLibCheck": true, + "paths": { + "@/*": ["./src/*"] + }, + "baseUrl": ".", + "ignoreDeprecations": "6.0", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "resolveJsonModule": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"], + "exclude": ["node_modules", "dist"] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..d3c52ea --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "es2023", + "lib": ["ES2023"], + "module": "esnext", + "types": ["node"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..c762e29 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,41 @@ +import { resolve } from 'node:path' +import { defineConfig, loadEnv } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vite.dev/config/ +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd(), '') + + return { + plugins: [vue()], + + resolve: { + alias: { + '@': resolve(__dirname, 'src'), + }, + }, + + css: { + preprocessorOptions: { + scss: { + additionalData: `@use "@/styles/variables.scss" as *;`, + }, + }, + }, + + server: { + host: '0.0.0.0', + port: Number(env.VITE_PORT) || 5173, + hmr: { + host: '0.0.0.0', + }, + proxy: { + '/dev-api': { + target: 'http://10.10.10.189:81/icp-api', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/dev-api/, ''), + }, + }, + }, + } +})