From eb0e7ab2e31a63d254fd57cf0a7f943d6c4ab2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Wed, 19 Jun 2024 11:46:22 -0700 Subject: [PATCH 01/14] Added OpenHistoricalMap layer to maps --- package-lock.json | 937 ++++++++++++++++++++- package.json | 6 +- src/LocateControl.js | 73 +- src/components/GrampsjsFormEditLatLong.js | 1 + src/components/GrampsjsFormEditMapLayer.js | 1 + src/components/GrampsjsMap.js | 44 +- src/components/GrampsjsObject.js | 2 + src/components/GrampsjsPersonTimeline.js | 1 + 8 files changed, 979 insertions(+), 86 deletions(-) diff --git a/package-lock.json b/package-lock.json index a0715e0b..74d1b6f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "AGPL", "dependencies": { "@hpcc-js/wasm": "^2.16.0", + "@maplibre/maplibre-gl-leaflet": "0.0.21", "@material/mwc-button": "^0.27.0", "@material/mwc-checkbox": "^0.27.0", "@material/mwc-circular-progress": "^0.27.0", @@ -34,7 +35,7 @@ "@material/mwc-top-app-bar": "^0.27.0", "@material/web": "^1.4.0", "@mdi/js": "^7.4.47", - "@types/leaflet": "^1.5.19", + "@types/leaflet": "^1.9.12", "d3": "^7.8.2", "d3-array": "^3.2.4", "d3-axis": "^3.0.0", @@ -49,6 +50,7 @@ "jwt-decode": "^3.1.2", "leaflet": "^1.9.4", "lit": "^2.1.1", + "maplibre-gl": "^4.4.1", "pwa-helper-components": "^0.2.10", "pwa-helpers": "^0.9.1", "tippy.js": "^6.3.7" @@ -2075,6 +2077,87 @@ "@lit-labs/ssr-dom-shim": "^1.1.2" } }, + "node_modules/@mapbox/geojson-rewind": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz", + "integrity": "sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==", + "dependencies": { + "get-stream": "^6.0.1", + "minimist": "^1.2.6" + }, + "bin": { + "geojson-rewind": "geojson-rewind" + } + }, + "node_modules/@mapbox/jsonlint-lines-primitives": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@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": "0.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz", + "integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==" + }, + "node_modules/@mapbox/tiny-sdf": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz", + "integrity": "sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA==" + }, + "node_modules/@mapbox/unitbezier": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz", + "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==" + }, + "node_modules/@mapbox/vector-tile": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz", + "integrity": "sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==", + "dependencies": { + "@mapbox/point-geometry": "~0.1.0" + } + }, + "node_modules/@mapbox/whoots-js": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz", + "integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@maplibre/maplibre-gl-leaflet": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-leaflet/-/maplibre-gl-leaflet-0.0.21.tgz", + "integrity": "sha512-IizDNJt8bqFxj7cNRk7+qpOgFjS5Z9UM32r2YkWEADasPLt9Zt34u5gKk7ZJg8M5AARp/PGaHP4F1GvFtbNWTA==", + "peerDependencies": { + "@types/leaflet": "^1.9.0", + "leaflet": "^1.9.3", + "maplibre-gl": "^2.4.0 || ^3.3.1 || ^4.3.2" + } + }, + "node_modules/@maplibre/maplibre-gl-style-spec": { + "version": "20.3.0", + "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-20.3.0.tgz", + "integrity": "sha512-eSiQ3E5LUSxAOY9ABXGyfNhout2iEa6mUxKeaQ9nJ8NL1NuaQYU7zKqzx/LEYcXe1neT4uYAgM1wYZj3fTSXtA==", + "dependencies": { + "@mapbox/jsonlint-lines-primitives": "~2.0.2", + "@mapbox/unitbezier": "^0.0.1", + "json-stringify-pretty-compact": "^4.0.0", + "minimist": "^1.2.8", + "quickselect": "^2.0.0", + "rw": "^1.3.3", + "sort-object": "^3.0.3", + "tinyqueue": "^2.0.3" + }, + "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/@material/animation": { "version": "14.0.0-canary.53b3cad2f.0", "resolved": "https://registry.npmjs.org/@material/animation/-/animation-14.0.0-canary.53b3cad2f.0.tgz", @@ -3942,9 +4025,17 @@ } }, "node_modules/@types/geojson": { - "version": "7946.0.8", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz", - "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==" + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" + }, + "node_modules/@types/geojson-vt": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@types/geojson-vt/-/geojson-vt-3.2.5.tgz", + "integrity": "sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g==", + "dependencies": { + "@types/geojson": "*" + } }, "node_modules/@types/glob": { "version": "7.1.4", @@ -4000,6 +4091,11 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/junit-report-builder": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/junit-report-builder/-/junit-report-builder-3.0.2.tgz", + "integrity": "sha512-R5M+SYhMbwBeQcNXYWNCZkl09vkVfAtcPIaCGdzIkkbeaTrVbGQ7HVgi4s+EmM/M1K4ZuWQH0jGcvMvNePfxYA==" + }, "node_modules/@types/keygrip": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", @@ -4080,9 +4176,9 @@ } }, "node_modules/@types/leaflet": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.5.tgz", - "integrity": "sha512-+Myo00Yb5OuvUyrH+vUwn9DRgOaBJsF/etIMdMcNhWGBMo58Mo1cxLInvCd0ZpvItju/AeDYFB/Od2pLiHB3VA==", + "version": "1.9.12", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.12.tgz", + "integrity": "sha512-BK7XS+NyRI291HIo0HCfE18Lp8oA30H1gpi1tf0mF3TgiCEzanQjOqNZ4x126SXzzi2oNSZhZ5axJp1k0iM6jg==", "dependencies": { "@types/geojson": "*" } @@ -4093,6 +4189,21 @@ "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", "dev": true }, + "node_modules/@types/mapbox__point-geometry": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz", + "integrity": "sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==" + }, + "node_modules/@types/mapbox__vector-tile": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/mapbox__vector-tile/-/mapbox__vector-tile-1.3.4.tgz", + "integrity": "sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==", + "dependencies": { + "@types/geojson": "*", + "@types/mapbox__point-geometry": "*", + "@types/pbf": "*" + } + }, "node_modules/@types/mdast": { "version": "3.0.10", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", @@ -4150,6 +4261,11 @@ "integrity": "sha512-hfnXRGugz+McgX2jxyy5qz9sB21LRzlGn24zlwN2KEgoPtEvjzNRrLtUkOOebPDPZl3Rq7ywKxYvylVcEZDnEw==", "dev": true }, + "node_modules/@types/pbf": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/pbf/-/pbf-3.0.5.tgz", + "integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==" + }, "node_modules/@types/puppeteer": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-2.1.6.tgz", @@ -4224,6 +4340,14 @@ "@types/sinon": "*" } }, + "node_modules/@types/supercluster": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/supercluster/-/supercluster-7.1.3.tgz", + "integrity": "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==", + "dependencies": { + "@types/geojson": "*" + } + }, "node_modules/@types/trusted-types": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", @@ -5339,6 +5463,14 @@ "node": ">=6.0" } }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", @@ -5411,6 +5543,14 @@ "node": "*" } }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -5853,6 +5993,23 @@ "node": ">= 0.8" } }, + "node_modules/bytewise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz", + "integrity": "sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ==", + "dependencies": { + "bytewise-core": "^1.2.2", + "typewise": "^1.0.3" + } + }, + "node_modules/bytewise-core": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz", + "integrity": "sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA==", + "dependencies": { + "typewise-core": "^1.2" + } + }, "node_modules/cache-content-type": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", @@ -7371,6 +7528,11 @@ "integrity": "sha512-m953zv0w5oDagTItWm6Auhmk/pY7EiejaqiVbnzSS3HIjh1FCUeK7WzuaVtWPNs58A+/xpIE+/dVk6pKsrua8g==", "dev": true }, + "node_modules/earcut": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", + "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==" + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -8419,6 +8581,17 @@ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -8714,6 +8887,11 @@ "node": ">=6.9.0" } }, + "node_modules/geojson-vt": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz", + "integrity": "sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==" + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -8755,7 +8933,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, "engines": { "node": ">=10" }, @@ -8763,6 +8940,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/github-markdown-css": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-3.0.1.tgz", @@ -8778,6 +8963,11 @@ "integrity": "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==", "dev": true }, + "node_modules/gl-matrix": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz", + "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==" + }, "node_modules/glob": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", @@ -8816,6 +9006,30 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -9547,7 +9761,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -9631,6 +9844,11 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, "node_modules/inline-style-parser": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", @@ -9858,6 +10076,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -10135,8 +10361,15 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/istanbul-lib-coverage": { "version": "3.0.0", @@ -10300,6 +10533,11 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "node_modules/json-stringify-pretty-compact": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz", + "integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -10360,6 +10598,11 @@ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" }, + "node_modules/kdbush": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", + "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==" + }, "node_modules/keygrip": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", @@ -10372,6 +10615,14 @@ "node": ">= 0.6" } }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/koa": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.1.tgz", @@ -11092,6 +11343,47 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/maplibre-gl": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-4.4.1.tgz", + "integrity": "sha512-tD+wn8qWSLCGhABKBrbewmgFfyopZDz+fkYXeOM8vdBhnf126DvMPyaYGGoKvoF4QuswCsgikETd2c39wK+OQw==", + "dependencies": { + "@mapbox/geojson-rewind": "^0.5.2", + "@mapbox/jsonlint-lines-primitives": "^2.0.2", + "@mapbox/point-geometry": "^0.1.0", + "@mapbox/tiny-sdf": "^2.0.6", + "@mapbox/unitbezier": "^0.0.1", + "@mapbox/vector-tile": "^1.3.1", + "@mapbox/whoots-js": "^3.1.0", + "@maplibre/maplibre-gl-style-spec": "^20.3.0", + "@types/geojson": "^7946.0.14", + "@types/geojson-vt": "3.2.5", + "@types/junit-report-builder": "^3.0.2", + "@types/mapbox__point-geometry": "^0.1.4", + "@types/mapbox__vector-tile": "^1.3.4", + "@types/pbf": "^3.0.5", + "@types/supercluster": "^7.1.3", + "earcut": "^2.2.4", + "geojson-vt": "^3.2.1", + "gl-matrix": "^3.4.3", + "global-prefix": "^3.0.0", + "kdbush": "^4.0.2", + "murmurhash-js": "^1.0.0", + "pbf": "^3.2.1", + "potpack": "^2.0.0", + "quickselect": "^2.0.0", + "supercluster": "^8.0.1", + "tinyqueue": "^2.0.3", + "vt-pbf": "^3.1.3" + }, + "engines": { + "node": ">=16.14.0", + "npm": ">=8.1.0" + }, + "funding": { + "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1" + } + }, "node_modules/markdown-escapes": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", @@ -11309,7 +11601,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -11586,6 +11877,11 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/murmurhash-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz", + "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==" + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -12153,6 +12449,18 @@ "node": "*" } }, + "node_modules/pbf": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz", + "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==", + "dependencies": { + "ieee754": "^1.1.12", + "resolve-protobuf-schema": "^2.1.0" + }, + "bin": { + "pbf": "bin/pbf" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -12268,6 +12576,11 @@ "ms": "^2.1.1" } }, + "node_modules/potpack": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-2.0.0.tgz", + "integrity": "sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw==" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -12335,6 +12648,11 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/protocol-buffers-schema": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -12526,6 +12844,11 @@ } ] }, + "node_modules/quickselect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", + "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -13671,6 +13994,14 @@ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true }, + "node_modules/resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "dependencies": { + "protocol-buffers-schema": "^3.3.1" + } + }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -14107,6 +14438,31 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -14268,6 +14624,38 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/sort-asc": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz", + "integrity": "sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-desc": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.2.0.tgz", + "integrity": "sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-object": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-3.0.3.tgz", + "integrity": "sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ==", + "dependencies": { + "bytewise": "^1.1.0", + "get-value": "^2.0.2", + "is-extendable": "^0.1.1", + "sort-asc": "^0.2.0", + "sort-desc": "^0.2.0", + "union-value": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -14350,6 +14738,51 @@ "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "dev": true }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -14585,6 +15018,14 @@ "inline-style-parser": "0.1.1" } }, + "node_modules/supercluster": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz", + "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", + "dependencies": { + "kdbush": "^4.0.2" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -14878,6 +15319,11 @@ "dev": true, "optional": true }, + "node_modules/tinyqueue": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", + "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==" + }, "node_modules/tippy.js": { "version": "6.3.7", "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", @@ -15058,6 +15504,19 @@ "node": ">= 0.6" } }, + "node_modules/typewise": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz", + "integrity": "sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ==", + "dependencies": { + "typewise-core": "^1.2.0" + } + }, + "node_modules/typewise-core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz", + "integrity": "sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg==" + }, "node_modules/typical": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", @@ -15212,6 +15671,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/unique-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", @@ -15560,6 +16033,16 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/vt-pbf": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-3.1.3.tgz", + "integrity": "sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==", + "dependencies": { + "@mapbox/point-geometry": "0.1.0", + "@mapbox/vector-tile": "^1.3.1", + "pbf": "^3.2.1" + } + }, "node_modules/web-namespaces": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", @@ -17700,6 +18183,69 @@ "@lit-labs/ssr-dom-shim": "^1.1.2" } }, + "@mapbox/geojson-rewind": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz", + "integrity": "sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==", + "requires": { + "get-stream": "^6.0.1", + "minimist": "^1.2.6" + } + }, + "@mapbox/jsonlint-lines-primitives": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz", + "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==" + }, + "@mapbox/point-geometry": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz", + "integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==" + }, + "@mapbox/tiny-sdf": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz", + "integrity": "sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA==" + }, + "@mapbox/unitbezier": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz", + "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==" + }, + "@mapbox/vector-tile": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz", + "integrity": "sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==", + "requires": { + "@mapbox/point-geometry": "~0.1.0" + } + }, + "@mapbox/whoots-js": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz", + "integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==" + }, + "@maplibre/maplibre-gl-leaflet": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-leaflet/-/maplibre-gl-leaflet-0.0.21.tgz", + "integrity": "sha512-IizDNJt8bqFxj7cNRk7+qpOgFjS5Z9UM32r2YkWEADasPLt9Zt34u5gKk7ZJg8M5AARp/PGaHP4F1GvFtbNWTA==", + "requires": {} + }, + "@maplibre/maplibre-gl-style-spec": { + "version": "20.3.0", + "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-20.3.0.tgz", + "integrity": "sha512-eSiQ3E5LUSxAOY9ABXGyfNhout2iEa6mUxKeaQ9nJ8NL1NuaQYU7zKqzx/LEYcXe1neT4uYAgM1wYZj3fTSXtA==", + "requires": { + "@mapbox/jsonlint-lines-primitives": "~2.0.2", + "@mapbox/unitbezier": "^0.0.1", + "json-stringify-pretty-compact": "^4.0.0", + "minimist": "^1.2.8", + "quickselect": "^2.0.0", + "rw": "^1.3.3", + "sort-object": "^3.0.3", + "tinyqueue": "^2.0.3" + } + }, "@material/animation": { "version": "14.0.0-canary.53b3cad2f.0", "resolved": "https://registry.npmjs.org/@material/animation/-/animation-14.0.0-canary.53b3cad2f.0.tgz", @@ -19468,9 +20014,17 @@ } }, "@types/geojson": { - "version": "7946.0.8", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz", - "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==" + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" + }, + "@types/geojson-vt": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@types/geojson-vt/-/geojson-vt-3.2.5.tgz", + "integrity": "sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g==", + "requires": { + "@types/geojson": "*" + } }, "@types/glob": { "version": "7.1.4", @@ -19526,6 +20080,11 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/junit-report-builder": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/junit-report-builder/-/junit-report-builder-3.0.2.tgz", + "integrity": "sha512-R5M+SYhMbwBeQcNXYWNCZkl09vkVfAtcPIaCGdzIkkbeaTrVbGQ7HVgi4s+EmM/M1K4ZuWQH0jGcvMvNePfxYA==" + }, "@types/keygrip": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", @@ -19606,9 +20165,9 @@ } }, "@types/leaflet": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.5.tgz", - "integrity": "sha512-+Myo00Yb5OuvUyrH+vUwn9DRgOaBJsF/etIMdMcNhWGBMo58Mo1cxLInvCd0ZpvItju/AeDYFB/Od2pLiHB3VA==", + "version": "1.9.12", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.12.tgz", + "integrity": "sha512-BK7XS+NyRI291HIo0HCfE18Lp8oA30H1gpi1tf0mF3TgiCEzanQjOqNZ4x126SXzzi2oNSZhZ5axJp1k0iM6jg==", "requires": { "@types/geojson": "*" } @@ -19619,6 +20178,21 @@ "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", "dev": true }, + "@types/mapbox__point-geometry": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz", + "integrity": "sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==" + }, + "@types/mapbox__vector-tile": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/mapbox__vector-tile/-/mapbox__vector-tile-1.3.4.tgz", + "integrity": "sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==", + "requires": { + "@types/geojson": "*", + "@types/mapbox__point-geometry": "*", + "@types/pbf": "*" + } + }, "@types/mdast": { "version": "3.0.10", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", @@ -19676,6 +20250,11 @@ "integrity": "sha512-hfnXRGugz+McgX2jxyy5qz9sB21LRzlGn24zlwN2KEgoPtEvjzNRrLtUkOOebPDPZl3Rq7ywKxYvylVcEZDnEw==", "dev": true }, + "@types/pbf": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/pbf/-/pbf-3.0.5.tgz", + "integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==" + }, "@types/puppeteer": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-2.1.6.tgz", @@ -19750,6 +20329,14 @@ "@types/sinon": "*" } }, + "@types/supercluster": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/supercluster/-/supercluster-7.1.3.tgz", + "integrity": "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==", + "requires": { + "@types/geojson": "*" + } + }, "@types/trusted-types": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", @@ -20641,6 +21228,11 @@ "@babel/runtime-corejs3": "^7.10.2" } }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==" + }, "array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", @@ -20689,6 +21281,11 @@ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==" + }, "astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -21014,6 +21611,23 @@ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", "dev": true }, + "bytewise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz", + "integrity": "sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ==", + "requires": { + "bytewise-core": "^1.2.2", + "typewise": "^1.0.3" + } + }, + "bytewise-core": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz", + "integrity": "sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA==", + "requires": { + "typewise-core": "^1.2" + } + }, "cache-content-type": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", @@ -22169,6 +22783,11 @@ "integrity": "sha512-m953zv0w5oDagTItWm6Auhmk/pY7EiejaqiVbnzSS3HIjh1FCUeK7WzuaVtWPNs58A+/xpIE+/dVk6pKsrua8g==", "dev": true }, + "earcut": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", + "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==" + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -22970,6 +23589,14 @@ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + }, "extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -23197,6 +23824,11 @@ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, + "geojson-vt": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz", + "integrity": "sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==" + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -23228,8 +23860,12 @@ "get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==" }, "github-markdown-css": { "version": "3.0.1", @@ -23243,6 +23879,11 @@ "integrity": "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==", "dev": true }, + "gl-matrix": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz", + "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==" + }, "glob": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", @@ -23272,6 +23913,26 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -23805,8 +24466,7 @@ "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { "version": "4.0.6", @@ -23858,6 +24518,11 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, "inline-style-parser": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", @@ -24005,6 +24670,11 @@ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==" + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -24189,8 +24859,12 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" }, "istanbul-lib-coverage": { "version": "3.0.0", @@ -24322,6 +24996,11 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "json-stringify-pretty-compact": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz", + "integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==" + }, "json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -24366,6 +25045,11 @@ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" }, + "kdbush": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", + "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==" + }, "keygrip": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", @@ -24375,6 +25059,11 @@ "tsscmp": "1.0.6" } }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, "koa": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.1.tgz", @@ -24987,6 +25676,40 @@ "semver": "^6.0.0" } }, + "maplibre-gl": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-4.4.1.tgz", + "integrity": "sha512-tD+wn8qWSLCGhABKBrbewmgFfyopZDz+fkYXeOM8vdBhnf126DvMPyaYGGoKvoF4QuswCsgikETd2c39wK+OQw==", + "requires": { + "@mapbox/geojson-rewind": "^0.5.2", + "@mapbox/jsonlint-lines-primitives": "^2.0.2", + "@mapbox/point-geometry": "^0.1.0", + "@mapbox/tiny-sdf": "^2.0.6", + "@mapbox/unitbezier": "^0.0.1", + "@mapbox/vector-tile": "^1.3.1", + "@mapbox/whoots-js": "^3.1.0", + "@maplibre/maplibre-gl-style-spec": "^20.3.0", + "@types/geojson": "^7946.0.14", + "@types/geojson-vt": "3.2.5", + "@types/junit-report-builder": "^3.0.2", + "@types/mapbox__point-geometry": "^0.1.4", + "@types/mapbox__vector-tile": "^1.3.4", + "@types/pbf": "^3.0.5", + "@types/supercluster": "^7.1.3", + "earcut": "^2.2.4", + "geojson-vt": "^3.2.1", + "gl-matrix": "^3.4.3", + "global-prefix": "^3.0.0", + "kdbush": "^4.0.2", + "murmurhash-js": "^1.0.0", + "pbf": "^3.2.1", + "potpack": "^2.0.0", + "quickselect": "^2.0.0", + "supercluster": "^8.0.1", + "tinyqueue": "^2.0.3", + "vt-pbf": "^3.1.3" + } + }, "markdown-escapes": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", @@ -25158,8 +25881,7 @@ "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "mkdirp": { "version": "0.5.6", @@ -25374,6 +26096,11 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "murmurhash-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz", + "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==" + }, "mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -25829,6 +26556,15 @@ "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, + "pbf": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz", + "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==", + "requires": { + "ieee754": "^1.1.12", + "resolve-protobuf-schema": "^2.1.0" + } + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -25925,6 +26661,11 @@ } } }, + "potpack": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-2.0.0.tgz", + "integrity": "sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw==" + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -25967,6 +26708,11 @@ "xtend": "^4.0.0" } }, + "protocol-buffers-schema": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" + }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -26106,6 +26852,11 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, + "quickselect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", + "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -27079,6 +27830,14 @@ } } }, + "resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "requires": { + "protocol-buffers-schema": "^3.3.1" + } + }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -27424,6 +28183,27 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + } + } + }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -27552,6 +28332,29 @@ } } }, + "sort-asc": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz", + "integrity": "sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA==" + }, + "sort-desc": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.2.0.tgz", + "integrity": "sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w==" + }, + "sort-object": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-3.0.3.tgz", + "integrity": "sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ==", + "requires": { + "bytewise": "^1.1.0", + "get-value": "^2.0.2", + "is-extendable": "^0.1.1", + "sort-asc": "^0.2.0", + "sort-desc": "^0.2.0", + "union-value": "^1.0.1" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -27626,6 +28429,41 @@ "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "dev": true }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + } + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -27802,6 +28640,14 @@ "inline-style-parser": "0.1.1" } }, + "supercluster": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz", + "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", + "requires": { + "kdbush": "^4.0.2" + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -28039,6 +28885,11 @@ "dev": true, "optional": true }, + "tinyqueue": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", + "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==" + }, "tippy.js": { "version": "6.3.7", "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", @@ -28175,6 +29026,19 @@ "mime-types": "~2.1.24" } }, + "typewise": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz", + "integrity": "sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ==", + "requires": { + "typewise-core": "^1.2.0" + } + }, + "typewise-core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz", + "integrity": "sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg==" + }, "typical": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", @@ -28293,6 +29157,17 @@ } } }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, "unique-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", @@ -28560,6 +29435,16 @@ "unist-util-stringify-position": "^3.0.0" } }, + "vt-pbf": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-3.1.3.tgz", + "integrity": "sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==", + "requires": { + "@mapbox/point-geometry": "0.1.0", + "@mapbox/vector-tile": "^1.3.1", + "pbf": "^3.2.1" + } + }, "web-namespaces": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", diff --git a/package.json b/package.json index 67edabeb..e79a6911 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "license": "AGPL", "dependencies": { "@hpcc-js/wasm": "^2.16.0", + "@maplibre/maplibre-gl-leaflet": "0.0.21", "@material/mwc-button": "^0.27.0", "@material/mwc-checkbox": "^0.27.0", "@material/mwc-circular-progress": "^0.27.0", @@ -105,7 +106,7 @@ "@material/mwc-top-app-bar": "^0.27.0", "@material/web": "^1.4.0", "@mdi/js": "^7.4.47", - "@types/leaflet": "^1.5.19", + "@types/leaflet": "^1.9.12", "d3": "^7.8.2", "d3-array": "^3.2.4", "d3-axis": "^3.0.0", @@ -120,8 +121,9 @@ "jwt-decode": "^3.1.2", "leaflet": "^1.9.4", "lit": "^2.1.1", + "maplibre-gl": "^4.4.1", "pwa-helper-components": "^0.2.10", "pwa-helpers": "^0.9.1", "tippy.js": "^6.3.7" } -} \ No newline at end of file +} diff --git a/src/LocateControl.js b/src/LocateControl.js index 4a6f5f4a..8ff6d6d0 100644 --- a/src/LocateControl.js +++ b/src/LocateControl.js @@ -1,16 +1,5 @@ /* eslint-disable */ -import { - control, - Control, - Marker, - DomUtil, - divIcon, - Util, - LayerGroup, - extend, - DomEvent, - circle, -} from '../node_modules/leaflet/dist/leaflet-src.esm.js' +import 'leaflet' /*! Copyright (c) 2016 Dominik Moritz @@ -22,7 +11,7 @@ You can find the project at: https://github.com/domoritz/leaflet-locatecontrol const LDomUtilApplyClassesMethod = (method, element, classNames) => { classNames = classNames.split(' ') classNames.forEach(function (className) { - DomUtil[method].call(this, element, className) + L.DomUtil[method].call(this, element, className) }) } @@ -34,7 +23,7 @@ const removeClasses = (el, names) => /** * Compatible with L.Circle but a true marker instead of a path */ -const LocationMarker = Marker.extend({ +const LocationMarker = L.Marker.extend({ initialize(latlng, options) { Util.setOptions(this, options) this._latlng = latlng @@ -67,7 +56,7 @@ const LocationMarker = Marker.extend({ const icon = this._getIconSVG(opt, style) - this._locationIcon = divIcon({ + this._locationIcon = L.divIcon({ className: icon.className, html: icon.svg, iconSize: [icon.w, icon.h], @@ -103,14 +92,14 @@ const LocationMarker = Marker.extend({ }, setStyle(style) { - Util.setOptions(this, style) + L.Util.setOptions(this, style) this.createIcon() }, }) const CompassMarker = LocationMarker.extend({ initialize(latlng, heading, options) { - Util.setOptions(this, options) + L.Util.setOptions(this, options) this._latlng = latlng this._heading = heading this.createIcon() @@ -148,7 +137,7 @@ const CompassMarker = LocationMarker.extend({ }, }) -export const LocateControl = Control.extend({ +export const LocateControl = L.Control.extend({ options: { /** Position of the control */ position: 'topleft', @@ -286,7 +275,7 @@ export const LocateControl = Control.extend({ * This function should return an object with HtmlElement for the button (link property) and the icon (icon property). */ createButtonCallback(container, options) { - const link = DomUtil.create( + const link = L.DomUtil.create( 'a', 'leaflet-bar-part leaflet-bar-part-single', container @@ -294,10 +283,10 @@ export const LocateControl = Control.extend({ link.title = options.strings.title link.href = '#' link.setAttribute('role', 'button') - const icon = DomUtil.create(options.iconElementTag, options.icon, link) + const icon = L.DomUtil.create(options.iconElementTag, options.icon, link) if (options.strings.text !== undefined) { - const text = DomUtil.create( + const text = L.DomUtil.create( options.textElementTag, 'leaflet-locate-text', link @@ -346,24 +335,24 @@ export const LocateControl = Control.extend({ // set default options if nothing is set (merge one step deep) for (const i in options) { if (typeof this.options[i] === 'object') { - extend(this.options[i], options[i]) + L.extend(this.options[i], options[i]) } else { this.options[i] = options[i] } } // extend the follow marker style and circle from the normal style - this.options.followMarkerStyle = extend( + this.options.followMarkerStyle = L.extend( {}, this.options.markerStyle, this.options.followMarkerStyle ) - this.options.followCircleStyle = extend( + this.options.followCircleStyle = L.extend( {}, this.options.circleStyle, this.options.followCircleStyle ) - this.options.followCompassStyle = extend( + this.options.followCompassStyle = L.extend( {}, this.options.compassStyle, this.options.followCompassStyle @@ -374,13 +363,13 @@ export const LocateControl = Control.extend({ * Add control to map. Returns the container for the control. */ onAdd(map) { - const container = DomUtil.create( + const container = L.DomUtil.create( 'div', 'leaflet-control-locate leaflet-bar leaflet-control' ) this._container = container this._map = map - this._layer = this.options.layer || new LayerGroup() + this._layer = this.options.layer || new L.LayerGroup() this._layer.addTo(map) this._event = undefined this._compassHeading = null @@ -393,16 +382,16 @@ export const LocateControl = Control.extend({ this._link = linkAndIcon.link this._icon = linkAndIcon.icon - DomEvent.on( + L.DomEvent.on( this._link, 'click', function (ev) { - DomEvent.stopPropagation(ev) - DomEvent.preventDefault(ev) + L.DomEvent.stopPropagation(ev) + L.DomEvent.preventDefault(ev) this._onClick() }, this - ).on(this._link, 'dblclick', DomEvent.stopPropagation) + ).on(this._link, 'dblclick', L.DomEvent.stopPropagation) this._resetVariables() @@ -530,7 +519,7 @@ export const LocateControl = Control.extend({ if (oriAbs || 'ondeviceorientation' in window) { const _this = this const deviceorientation = function () { - DomEvent.on( + L.DomEvent.on( window, oriAbs ? 'deviceorientationabsolute' : 'deviceorientation', _this._onDeviceOrientation, @@ -579,14 +568,14 @@ export const LocateControl = Control.extend({ if (this.options.showCompass) { this._compassHeading = null if ('ondeviceorientationabsolute' in window) { - DomEvent.off( + L.DomEvent.off( window, 'deviceorientationabsolute', this._onDeviceOrientation, this ) } else if ('ondeviceorientation' in window) { - DomEvent.off( + L.DomEvent.off( window, 'deviceorientation', this._onDeviceOrientation, @@ -623,7 +612,7 @@ export const LocateControl = Control.extend({ maxZoom: this.options.initialZoomLevel || this.options.locateOptions.maxZoom, }) - Util.requestAnimFrame(function () { + L.Util.requestAnimFrame(function () { // Wait until after the next animFrame because the flyTo can be async this._ignoreEvent = false }, this) @@ -690,7 +679,7 @@ export const LocateControl = Control.extend({ : this.options.circleStyle if (!this._circle) { - this._circle = circle(latlng, radius, style).addTo(this._layer) + this._circle = L.circle(latlng, radius, style).addTo(this._layer) } else { this._circle.setLatLng(latlng).setRadius(radius).setStyle(style) } @@ -729,7 +718,7 @@ export const LocateControl = Control.extend({ const t = this.options.strings.popup function getPopupText() { if (typeof t === 'string') { - return Util.template(t, {distance, unit}) + return L.Util.template(t, {distance, unit}) } else if (typeof t === 'function') { return t({distance, unit}) } else { @@ -770,7 +759,7 @@ export const LocateControl = Control.extend({ angle = Math.round(angle) this._compassHeading = angle - Util.requestAnimFrame(this._drawCompass, this) + L.Util.requestAnimFrame(this._drawCompass, this) } else { this._compassHeading = null } @@ -988,9 +977,9 @@ export const LocateControl = Control.extend({ * Removes all classes from button. */ _cleanClasses() { - DomUtil.removeClass(this._container, 'requesting') - DomUtil.removeClass(this._container, 'active') - DomUtil.removeClass(this._container, 'following') + L.DomUtil.removeClass(this._container, 'requesting') + L.DomUtil.removeClass(this._container, 'active') + L.DomUtil.removeClass(this._container, 'following') removeClasses(this._icon, this.options.iconLoading) addClasses(this._icon, this.options.icon) @@ -1015,4 +1004,4 @@ export const LocateControl = Control.extend({ }, }) -control.locate = options => new LocateControl(options) +L.control.locate = options => new LocateControl(options) diff --git a/src/components/GrampsjsFormEditLatLong.js b/src/components/GrampsjsFormEditLatLong.js index e32fb874..5c87739d 100644 --- a/src/components/GrampsjsFormEditLatLong.js +++ b/src/components/GrampsjsFormEditLatLong.js @@ -114,6 +114,7 @@ class GrampsjsFormEditLatLong extends GrampsjsObjectForm { OSM contributors; CARTO', leafletTileSize: 256, leafletZoomOffset: 0, + glStyle: 'https://www.openhistoricalmap.org/map-styles/main/main.json', } class GrampsjsMap extends LitElement { @@ -77,18 +77,18 @@ class GrampsjsMap extends LitElement { firstUpdated() { const mapel = this.shadowRoot.getElementById(this.mapid) if (this.latMin === 0 && this.latMax === 0) { - this._map = new Map(mapel, {zoomControl: false}).setView( + this._map = new L.Map(mapel, {zoomControl: false}).setView( [this.latitude, this.longitude], this.zoom ) } else { - this._map = new Map(mapel, {zoomControl: false}).fitBounds([ + this._map = new L.Map(mapel, {zoomControl: false}).fitBounds([ [this.latMin, this.longMin], [this.latMax, this.longMax], ]) } const config = {...defaultConfig, ...window.grampsjsConfig} - const tileLayer = new TileLayer(config.leafletTileUrl, { + const tileLayer = new L.TileLayer(config.leafletTileUrl, { attribution: config.leafletTileAttribution, tileSize: config.leafletTileSize, zoomOffset: config.leafletZoomOffset, @@ -96,15 +96,25 @@ class GrampsjsMap extends LitElement { zoomControl: false, }) tileLayer.addTo(this._map) - this._map.addControl(control.zoom({position: 'bottomright'})) + const gl = L.maplibreGL({ + style: config.glStyle, + }).addTo(this._map) + this._map.addControl(L.control.zoom({position: 'bottomright'})) if (this.locateControl) { this._map.addControl( - control.locate({position: 'bottomright', drawCircle: false}) + L.control.locate({position: 'bottomright', drawCircle: false}) ) } - this._layercontrol = control.layers({OpenStreetMap: tileLayer}, null, { - position: 'bottomleft', - }) + this._layercontrol = L.control.layers( + { + OpenHistoricalMap: gl, + OpenStreetMap: tileLayer, + }, + null, + { + position: 'bottomleft', + } + ) if (this.layerSwitcher) { this._map.addControl(this._layercontrol) } @@ -118,7 +128,8 @@ class GrampsjsMap extends LitElement { panTo(latitude, longitude) { if (this._map !== undefined) { - this._map.panTo(new LatLng(latitude, longitude)) + // eslint-disable-next-line new-cap + this._map.panTo(new L.latLng(latitude, longitude)) } } @@ -126,7 +137,8 @@ class GrampsjsMap extends LitElement { if (this._map !== undefined) { if (this.latMin === 0 && this.latMax === 0) { this._map.setZoom(this.zoom) - this._map.panTo(new LatLng(this.latitude, this.longitude)) + // eslint-disable-next-line new-cap + this._map.panTo(new L.latLng(this.latitude, this.longitude)) } else { this._map.fitBounds([ [this.latMin, this.longMin], diff --git a/src/components/GrampsjsObject.js b/src/components/GrampsjsObject.js index 56e595fb..70707c18 100644 --- a/src/components/GrampsjsObject.js +++ b/src/components/GrampsjsObject.js @@ -408,6 +408,7 @@ export class GrampsjsObject extends GrampsjsTranslateMixin(LitElement) { ? html` @@ -428,6 +429,7 @@ export class GrampsjsObject extends GrampsjsTranslateMixin(LitElement) { zoom="${this._getZoomFromBounds( JSON.parse(mapBounds[0].value) )}" + layerSwitcher mapid="media-map" id="map" > diff --git a/src/components/GrampsjsPersonTimeline.js b/src/components/GrampsjsPersonTimeline.js index 68310770..b5cc7067 100644 --- a/src/components/GrampsjsPersonTimeline.js +++ b/src/components/GrampsjsPersonTimeline.js @@ -150,6 +150,7 @@ export class GrampsjsPersonTimeline extends GrampsjsTranslateMixin(LitElement) { longMin="${mapCorners[0][1]}" latMax="${mapCorners[1][0]}" longMax="${mapCorners[1][1]}" + layerSwitcher mapid="timeline-map" id="timeline-map" @marker:clicked="${this._handleMapClick}" From 95da99ca74610765cdfbc83997c5f8f366afcad8 Mon Sep 17 00:00:00 2001 From: David Straub Date: Mon, 1 Jul 2024 22:06:39 +0200 Subject: [PATCH 02/14] Add simple time slider to map view --- src/components/GrampsjsMapTimeSlider.js | 58 +++++++++++++++++++++++++ src/views/GrampsjsViewMap.js | 14 ++++++ 2 files changed, 72 insertions(+) create mode 100644 src/components/GrampsjsMapTimeSlider.js diff --git a/src/components/GrampsjsMapTimeSlider.js b/src/components/GrampsjsMapTimeSlider.js new file mode 100644 index 00000000..3e4b2e1f --- /dev/null +++ b/src/components/GrampsjsMapTimeSlider.js @@ -0,0 +1,58 @@ +import {html, css, LitElement} from 'lit' +import '@material/web/slider/slider.js' + +import {sharedStyles} from '../SharedStyles.js' +import {GrampsjsTranslateMixin} from '../mixins/GrampsjsTranslateMixin.js' +import {fireEvent} from '../util.js' + +class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { + static get styles() { + return [ + sharedStyles, + css` + #container { + z-index: 999; + background-color: #ffffff; + border-radius: 14px; + width: calc(100% - 150px); + position: absolute; + bottom: 25px; + height: 28px; + left: 50%; + transform: translateX(-50%); + display: flex; + justify-content: center; + align-items: center; + } + + md-slider { + width: 100%; + } + `, + ] + } + + render() { + return html` +
+ +
+ ` + } + + _handleInput() { + const slider = this.renderRoot.querySelector('md-slider') + const detail = {start: slider.valueStart, end: slider.valueEnd} + fireEvent(this, 'timeslider:change', detail) + } +} + +window.customElements.define('grampsjs-map-time-slider', GrampsjsMapTimeSlider) diff --git a/src/views/GrampsjsViewMap.js b/src/views/GrampsjsViewMap.js index a616fb6b..20ed8585 100644 --- a/src/views/GrampsjsViewMap.js +++ b/src/views/GrampsjsViewMap.js @@ -5,6 +5,7 @@ import {GrampsjsView} from './GrampsjsView.js' import '../components/GrampsjsMap.js' import '../components/GrampsjsMapMarker.js' import '../components/GrampsjsMapSearchbox.js' +import '../components/GrampsjsMapTimeSlider.js' import '../components/GrampsjsPlaceBox.js' import {apiGet, getMediaUrl} from '../api.js' import '@material/mwc-textfield' @@ -76,6 +77,8 @@ export class GrampsjsViewMap extends GrampsjsView { _valueSearch: {type: String}, _bounds: {type: Object}, _placeFilters: {type: Object}, + _dateRangeStart: {type: Number}, + _dateRangeEnd: {type: Number}, } } @@ -90,6 +93,8 @@ export class GrampsjsViewMap extends GrampsjsView { this._valueSearch = '' this._bounds = {} this._placeFilters = {} + this._dateRangeStart = -1 + this._dateRangeEnd = -1 } renderContent() { @@ -119,6 +124,10 @@ export class GrampsjsViewMap extends GrampsjsView { value="${this._valueSearch}" >${this._renderPlaceDetails()} + ` } @@ -154,6 +163,11 @@ export class GrampsjsViewMap extends GrampsjsView { } } + _handleTimeSliderChange(event) { + this._dateRangeStart = event.detail.start + this._dateRangeEnd = event.detail.end + } + _handlePlaceFilterChanged(event) { this._placeFilters = {...event.detail} this._applyPlaceFilter() From e5fa8c696143c2eb14203f9799418b4a6b638b66 Mon Sep 17 00:00:00 2001 From: David Straub Date: Tue, 2 Jul 2024 20:16:30 +0200 Subject: [PATCH 03/14] Use single-knob slider, add map filter --- src/components/GrampsjsMap.js | 12 ++- src/components/GrampsjsMapTimeSlider.js | 38 +++++++- src/util.js | 117 ++++++++++++++++++++++++ src/views/GrampsjsViewMap.js | 10 +- 4 files changed, 165 insertions(+), 12 deletions(-) diff --git a/src/components/GrampsjsMap.js b/src/components/GrampsjsMap.js index 146cd386..24309ac8 100644 --- a/src/components/GrampsjsMap.js +++ b/src/components/GrampsjsMap.js @@ -4,7 +4,7 @@ import 'maplibre-gl' import '@maplibre/maplibre-gl-leaflet' import './GrampsjsMapOverlay.js' import './GrampsjsMapMarker.js' -import {fireEvent} from '../util.js' +import {fireEvent, filterByDecimalYear} from '../util.js' import '../LocateControl.js' const {L} = window @@ -46,6 +46,7 @@ class GrampsjsMap extends LitElement { width: {type: String}, latitude: {type: Number}, longitude: {type: Number}, + year: {type: Number}, mapid: {type: String}, zoom: {type: Number}, latMin: {type: Number}, @@ -55,6 +56,7 @@ class GrampsjsMap extends LitElement { layerSwitcher: {type: Boolean}, locateControl: {type: Boolean}, _map: {type: Object}, + _glMap: {type: Object}, _layercontrol: {type: Object}, } } @@ -67,6 +69,7 @@ class GrampsjsMap extends LitElement { this.mapid = 'mapid' this.latitude = 0 this.longitude = 0 + this.year = -1 this.latMin = 0 this.latMax = 0 this.longMin = 0 @@ -115,6 +118,7 @@ class GrampsjsMap extends LitElement { position: 'bottomleft', } ) + this._glMap = gl if (this.layerSwitcher) { this._map.addControl(this._layercontrol) } @@ -133,7 +137,11 @@ class GrampsjsMap extends LitElement { } } - updated() { + updated(changed) { + if (changed.has('year') && this.year > 0) { + filterByDecimalYear(this._glMap._glMap, this.year) + return + } if (this._map !== undefined) { if (this.latMin === 0 && this.latMax === 0) { this._map.setZoom(this.zoom) diff --git a/src/components/GrampsjsMapTimeSlider.js b/src/components/GrampsjsMapTimeSlider.js index 3e4b2e1f..a55a7698 100644 --- a/src/components/GrampsjsMapTimeSlider.js +++ b/src/components/GrampsjsMapTimeSlider.js @@ -28,29 +28,59 @@ class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { md-slider { width: 100%; } + + div.date { + display: inline-block; + font-size: 13px; + font-weight: 500; + color: rgba(0, 0, 0, 0.6); + white-space: nowrap; + margin-left: 4px; + margin-right: 14px; + line-height: 22px; + height: 22px; + } + + .date .year { + font-weight: 600; + } `, ] } + static get properties() { + return { + value: {type: Number}, + } + } + + constructor() { + super() + this.value = 2024 + } + render() { return html`
+
+ ${this.value} ± + 10 +
` } _handleInput() { const slider = this.renderRoot.querySelector('md-slider') - const detail = {start: slider.valueStart, end: slider.valueEnd} + const detail = {value: slider.value} + this.value = slider.value fireEvent(this, 'timeslider:change', detail) } } diff --git a/src/util.js b/src/util.js index 675fd087..c8ede945 100644 --- a/src/util.js +++ b/src/util.js @@ -588,3 +588,120 @@ export function dateIsEmpty(date) { } return true } + +// OpenHistoricalMap functions + +/** + * Returns a `Date` object representing the given UTC date components. + * + * @param year A one-based year in the proleptic Gregorian calendar. + * @param month A zero-based month. + * @param day A one-based day. + * @returns A date object. + */ +function dateFromUTC(year, month, day) { + const date = new Date(Date.UTC(year, month, day)) + // Date.UTC() treats a two-digit year as an offset from 1900. + date.setUTCFullYear(year) + return date +} + +/** + * Converts the given ISO 8601-1 date to a decimal year. + * + * @param isoDate A date string in ISO 8601-1 format. + * @returns A floating point number of years since year 0. + */ +function decimalYearFromISODate(isoDate) { + // Require a valid YYYY, YYYY-MM, or YYYY-MM-DD date, but allow the year + // to be a variable number of digits or negative, unlike ISO 8601-1. + if (!isoDate || !/^-?\d{1,4}(?:-\d\d){0,2}$/.test(isoDate)) return undefined + + const ymd = isoDate.split('-') + // A negative year results in an extra element at the beginning. + if (ymd[0] === '') { + ymd.shift() + ymd[0] *= -1 + } + const year = +ymd[0] + const date = dateFromUTC(year, +ymd[1] - 1, +ymd[2]) + if (Number.isNaN(date)) return undefined + + // Add the year and the fraction of the date between two New Year’s Days. + const nextNewYear = dateFromUTC(year + 1, 0, 1).getTime() + const lastNewYear = dateFromUTC(year, 0, 1).getTime() + return year + (date.getTime() - lastNewYear) / (nextNewYear - lastNewYear) +} + +/** + * Returns a modified version of the given filter that only evaluates to + * true if the feature coincides with the given decimal year. + * + * @param filter The original layer filter. + * @param decimalYear The decimal year to filter by. + * @returns A filter similar to the given filter, but with added conditions + * that require the feature to coincide with the decimal year. + */ +function constrainFilterByDate(filter, decimalYear) { + const newFilter = filter + if (filter && filter[0] === 'all' && filter[1] && filter[1][0] === 'any') { + if ( + filter[1][2] && + filter[1][2][0] === '<=' && + filter[1][2][1] === 'start_decdate' + ) { + newFilter[1][2][2] = decimalYear + } + if ( + newFilter[2][2] && + newFilter[2][2][0] === '>=' && + newFilter[2][2][1] === 'end_decdate' + ) { + newFilter[2][2][2] = decimalYear + } + return newFilter + } + + const dateFilter = [ + 'all', + ['any', ['!has', 'start_decdate'], ['<=', 'start_decdate', decimalYear]], + ['any', ['!has', 'end_decdate'], ['>=', 'end_decdate', decimalYear]], + ] + if (filter) { + dateFilter.push(filter) + } + return dateFilter +} + +/** + * Filters the map’s features by the `date` data attribute. + * + * @param map The MapboxGL map object to filter the style of. + * @param year The numeric ear to filter by + */ +export function filterByDecimalYear(map, decimalYear) { + // eslint-disable-next-line array-callback-return + map.getStyle().layers.map(layer => { + if (!('source-layer' in layer)) return + + const filter = constrainFilterByDate(layer.filter, decimalYear) + map.setFilter(layer.id, filter) + }) +} + +/** + * Filters the map’s features by the `date` data attribute. + * + * @param map The MapboxGL map object to filter the style of. + * @param date The date to filter by in YYYY-MM-DD format. + */ +export function filterByDate(map, dateP) { + let date = dateP + if (date === null || date === '') { + ;[date] = new Date().toISOString().split('T') + } + const decimalYear = date && decimalYearFromISODate(date) + if (!decimalYear) return + + filterByDecimalYear(map, decimalYear) +} diff --git a/src/views/GrampsjsViewMap.js b/src/views/GrampsjsViewMap.js index 20ed8585..6c8b7bbb 100644 --- a/src/views/GrampsjsViewMap.js +++ b/src/views/GrampsjsViewMap.js @@ -77,8 +77,7 @@ export class GrampsjsViewMap extends GrampsjsView { _valueSearch: {type: String}, _bounds: {type: Object}, _placeFilters: {type: Object}, - _dateRangeStart: {type: Number}, - _dateRangeEnd: {type: Number}, + _year: {type: Number}, } } @@ -93,8 +92,7 @@ export class GrampsjsViewMap extends GrampsjsView { this._valueSearch = '' this._bounds = {} this._placeFilters = {} - this._dateRangeStart = -1 - this._dateRangeEnd = -1 + this._year = -1 } renderContent() { @@ -107,6 +105,7 @@ export class GrampsjsViewMap extends GrampsjsView { height="calc(100vh - 64px)" latitude="${center[0]}" longitude="${center[1]}" + year="${this._year}" mapid="map-mapview" @map:moveend="${this._handleMoveEnd}" id="map" @@ -164,8 +163,7 @@ export class GrampsjsViewMap extends GrampsjsView { } _handleTimeSliderChange(event) { - this._dateRangeStart = event.detail.start - this._dateRangeEnd = event.detail.end + this._year = event.detail.value } _handlePlaceFilterChanged(event) { From eb8bcb7325e692ed119dd6fb4e622f6eee11ee31 Mon Sep 17 00:00:00 2001 From: David Straub Date: Tue, 2 Jul 2024 20:42:34 +0200 Subject: [PATCH 04/14] Update src/util.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Minh Nguyễn --- src/util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.js b/src/util.js index c8ede945..3e0d741e 100644 --- a/src/util.js +++ b/src/util.js @@ -684,7 +684,7 @@ export function filterByDecimalYear(map, decimalYear) { map.getStyle().layers.map(layer => { if (!('source-layer' in layer)) return - const filter = constrainFilterByDate(layer.filter, decimalYear) + const filter = constrainFilterByDate(map.getFilter(layer.id), decimalYear) map.setFilter(layer.id, filter) }) } From 74a8b06d22ef3257398bfa0cacb2c02dc3e7c8af Mon Sep 17 00:00:00 2001 From: David Straub Date: Tue, 2 Jul 2024 20:43:11 +0200 Subject: [PATCH 05/14] Update src/components/GrampsjsMapTimeSlider.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Minh Nguyễn --- src/components/GrampsjsMapTimeSlider.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/GrampsjsMapTimeSlider.js b/src/components/GrampsjsMapTimeSlider.js index a55a7698..ef066c4c 100644 --- a/src/components/GrampsjsMapTimeSlider.js +++ b/src/components/GrampsjsMapTimeSlider.js @@ -66,7 +66,7 @@ class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { @change="${this._handleInput}" labeled min="1500" - max="2024" + max="${new Date().getFullYear()}" value="${this.value}" >
From 3d2deebdfc525ae2b17dd433de55faf41b4420f2 Mon Sep 17 00:00:00 2001 From: David Straub Date: Tue, 2 Jul 2024 20:43:27 +0200 Subject: [PATCH 06/14] Update src/components/GrampsjsMapTimeSlider.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Minh Nguyễn --- src/components/GrampsjsMapTimeSlider.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/GrampsjsMapTimeSlider.js b/src/components/GrampsjsMapTimeSlider.js index ef066c4c..dd121d13 100644 --- a/src/components/GrampsjsMapTimeSlider.js +++ b/src/components/GrampsjsMapTimeSlider.js @@ -56,7 +56,7 @@ class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { constructor() { super() - this.value = 2024 + this.value = new Date().getFullYear() - 100 } render() { From 6e786095ccd833d4f6e00f9c7ec48e4a3134f784 Mon Sep 17 00:00:00 2001 From: David Straub Date: Tue, 2 Jul 2024 20:49:06 +0200 Subject: [PATCH 07/14] Use input event instead of change --- src/components/GrampsjsMapTimeSlider.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/GrampsjsMapTimeSlider.js b/src/components/GrampsjsMapTimeSlider.js index dd121d13..9149672c 100644 --- a/src/components/GrampsjsMapTimeSlider.js +++ b/src/components/GrampsjsMapTimeSlider.js @@ -63,7 +63,7 @@ class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { return html`
Date: Tue, 2 Jul 2024 21:52:04 +0200 Subject: [PATCH 08/14] Update src/util.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Minh Nguyễn --- src/util.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util.js b/src/util.js index 3e0d741e..2e72c4de 100644 --- a/src/util.js +++ b/src/util.js @@ -647,10 +647,10 @@ function constrainFilterByDate(filter, decimalYear) { if (filter && filter[0] === 'all' && filter[1] && filter[1][0] === 'any') { if ( filter[1][2] && - filter[1][2][0] === '<=' && + filter[1][2][0] === '<' && filter[1][2][1] === 'start_decdate' ) { - newFilter[1][2][2] = decimalYear + newFilter[1][2][2] = decimalYear + 1 } if ( newFilter[2][2] && @@ -664,7 +664,7 @@ function constrainFilterByDate(filter, decimalYear) { const dateFilter = [ 'all', - ['any', ['!has', 'start_decdate'], ['<=', 'start_decdate', decimalYear]], + ['any', ['!has', 'start_decdate'], ['<', 'start_decdate', decimalYear + 1]], ['any', ['!has', 'end_decdate'], ['>=', 'end_decdate', decimalYear]], ] if (filter) { From 5958d8c3bc6669c572c8377f0cbc036bbd5b1eaf Mon Sep 17 00:00:00 2001 From: David Straub Date: Wed, 3 Jul 2024 20:50:59 +0200 Subject: [PATCH 09/14] Filter map pins, add toggle button to time slider --- src/components/GrampsjsMap.js | 23 +++-- src/components/GrampsjsMapTimeSlider.js | 112 ++++++++++++++++++++++-- src/util.js | 32 +++++++ src/views/GrampsjsViewMap.js | 63 ++++++++++--- 4 files changed, 205 insertions(+), 25 deletions(-) diff --git a/src/components/GrampsjsMap.js b/src/components/GrampsjsMap.js index 24309ac8..46b625ce 100644 --- a/src/components/GrampsjsMap.js +++ b/src/components/GrampsjsMap.js @@ -58,6 +58,7 @@ class GrampsjsMap extends LitElement { _map: {type: Object}, _glMap: {type: Object}, _layercontrol: {type: Object}, + _currentLayer: {type: String}, } } @@ -75,6 +76,7 @@ class GrampsjsMap extends LitElement { this.longMin = 0 this.longMax = 0 this.layerSwitcher = false + this._currentLayer = 'OpenStreetMap' } firstUpdated() { @@ -99,9 +101,9 @@ class GrampsjsMap extends LitElement { zoomControl: false, }) tileLayer.addTo(this._map) - const gl = L.maplibreGL({ + this._gl = L.maplibreGL({ style: config.glStyle, - }).addTo(this._map) + }) this._map.addControl(L.control.zoom({position: 'bottomright'})) if (this.locateControl) { this._map.addControl( @@ -110,7 +112,7 @@ class GrampsjsMap extends LitElement { } this._layercontrol = L.control.layers( { - OpenHistoricalMap: gl, + OpenHistoricalMap: this._gl, OpenStreetMap: tileLayer, }, null, @@ -118,14 +120,19 @@ class GrampsjsMap extends LitElement { position: 'bottomleft', } ) - this._glMap = gl if (this.layerSwitcher) { this._map.addControl(this._layercontrol) } + this._map.on('baselayerchange', e => this._handleBaseLayerChange(e)) this._map.invalidateSize(false) this._map.on('moveend', e => this._handleMoveEnd(e)) } + _handleBaseLayerChange(e) { + this._currentLayer = e.name + fireEvent(this, 'map:layerchange', {layer: this._currentLayer}) + } + _handleMoveEnd(e) { fireEvent(this, 'map:moveend', {bounds: e.target.getBounds()}) } @@ -138,8 +145,12 @@ class GrampsjsMap extends LitElement { } updated(changed) { - if (changed.has('year') && this.year > 0) { - filterByDecimalYear(this._glMap._glMap, this.year) + if ( + changed.has('year') && + this.year > 0 && + this._currentLayer === 'OpenHistoricalMap' + ) { + filterByDecimalYear(this._gl._glMap, this.year) return } if (this._map !== undefined) { diff --git a/src/components/GrampsjsMapTimeSlider.js b/src/components/GrampsjsMapTimeSlider.js index 9149672c..19b44926 100644 --- a/src/components/GrampsjsMapTimeSlider.js +++ b/src/components/GrampsjsMapTimeSlider.js @@ -1,9 +1,16 @@ import {html, css, LitElement} from 'lit' import '@material/web/slider/slider.js' +import '@material/web/iconbutton/icon-button.js' +import '@material/web/icon/icon.js' +import '@material/web/menu/menu' +import '@material/web/menu/menu-item' +import '@material/web/switch/switch' +import {mdiCog} from '@mdi/js' import {sharedStyles} from '../SharedStyles.js' import {GrampsjsTranslateMixin} from '../mixins/GrampsjsTranslateMixin.js' import {fireEvent} from '../util.js' +import {renderIconSvg} from '../icons.js' class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { static get styles() { @@ -27,6 +34,8 @@ class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { md-slider { width: 100%; + --md-slider-active-track-color: var(--md-sys-color-primary); + --md-slider-inactive-track-color: var(--md-sys-color-primary); } div.date { @@ -36,14 +45,33 @@ class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { color: rgba(0, 0, 0, 0.6); white-space: nowrap; margin-left: 4px; - margin-right: 14px; - line-height: 22px; - height: 22px; + margin-right: 8px; + line-height: 24px; + height: 24px; + min-width: 75px; + text-align: right; } .date .year { font-weight: 600; } + + .control { + --md-icon-button-icon-size: 18px; + --md-icon-button-state-layer-height: 22px; + --md-icon-button-state-layer-width: 22px; + height: 22px; + width: 22px; + display: inline-block; + } + + md-menu { + --md-menu-item-one-line-container-height: 48px; + } + + md-switch { + transform: scale(0.5); + } `, ] } @@ -51,12 +79,16 @@ class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { static get properties() { return { value: {type: Number}, + span: {type: Number}, + filterMap: {type: Boolean}, } } constructor() { super() - this.value = new Date().getFullYear() - 100 + this.value = new Date().getFullYear() - 50 + this.span = 50 + this.filterMap = false } render() { @@ -64,24 +96,88 @@ class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) {
- ${this.value} ± - 10 + ${!this.filterMap && this.span < 0 + ? '' + : html` ${this.value}`} + ${this.span > 0 + ? html`± ${this.span}` + : ''}
+
+ + ${renderIconSvg(mdiCog, 'var(--md-sys-color-primary)')} + +
+
+ + ${[0, 10, 25, 50, 100].map( + years => html` + +
± ${years}
+
+ ` + )} +
` } + _fireEvent() { + const detail = { + value: this.value, + span: this.span, + } + fireEvent(this, 'timeslider:change', detail) + } + + connectedCallback() { + super.connectedCallback() + this._fireEvent() + } + + _handleSwitch() { + const el = this.renderRoot.querySelector('md-switch') + if (el.selected !== this.span > 0) { + this.span = -this.span + } + this._fireEvent() + } + + _handleSpanYearsClick(years) { + this.span = years + this._fireEvent() + } + + _handleSpanClick() { + const menu = this.renderRoot.querySelector('#span-menu') + menu.open = true + } + _handleInput() { const slider = this.renderRoot.querySelector('md-slider') - const detail = {value: slider.value} this.value = slider.value - fireEvent(this, 'timeslider:change', detail) + this._fireEvent() } } diff --git a/src/util.js b/src/util.js index 2e72c4de..5d3c233e 100644 --- a/src/util.js +++ b/src/util.js @@ -705,3 +705,35 @@ export function filterByDate(map, dateP) { filterByDecimalYear(map, decimalYear) } + +export function isDateBetweenYears(date, yearMin, yearMax) { + const MOD_BEFORE = 1 + const MOD_AFTER = 2 + const MOD_ABOUT = 3 + const MOD_TEXTONLY = 6 + const MOD_FROM = 7 + const MOD_TO = 8 + + const RANGE_ABOUT = 50 + const RANGE_BEFORE = 50 + const RANGE_AFTER = 50 + + if (dateIsEmpty(date) || date.modifier === MOD_TEXTONLY) { + return false + } + + let year1 = date.dateval[2] + let year2 = date.dateval[6] ?? year1 + + if (date.modifier === MOD_BEFORE || date.modifier === MOD_TO) { + year1 -= RANGE_BEFORE + } + if (date.modifier === MOD_AFTER || date.modifier === MOD_FROM) { + year2 += RANGE_AFTER + } + if (date.modifier === MOD_ABOUT) { + year1 -= RANGE_ABOUT + year2 += RANGE_ABOUT + } + return yearMin <= year2 && year1 <= yearMax +} diff --git a/src/views/GrampsjsViewMap.js b/src/views/GrampsjsViewMap.js index 6c8b7bbb..55a26c0e 100644 --- a/src/views/GrampsjsViewMap.js +++ b/src/views/GrampsjsViewMap.js @@ -8,6 +8,7 @@ import '../components/GrampsjsMapSearchbox.js' import '../components/GrampsjsMapTimeSlider.js' import '../components/GrampsjsPlaceBox.js' import {apiGet, getMediaUrl} from '../api.js' +import {isDateBetweenYears} from '../util.js' import '@material/mwc-textfield' // This is used for initial map center in absence of places @@ -68,7 +69,8 @@ export class GrampsjsViewMap extends GrampsjsView { static get properties() { return { - _data: {type: Array}, + _dataPlaces: {type: Array}, + _dataEvents: {type: Array}, _filteredPlaces: {type: Array}, _handlesHighlight: {type: Array}, _dataSearch: {type: Array}, @@ -78,12 +80,15 @@ export class GrampsjsViewMap extends GrampsjsView { _bounds: {type: Object}, _placeFilters: {type: Object}, _year: {type: Number}, + _yearSpan: {type: Number}, + _currentLayer: {type: String}, } } constructor() { super() - this._data = [] + this._dataPlaces = [] + this._dataEvents = [] this._filteredPlaces = [] this._handlesHighlight = [] this._dataSearch = [] @@ -93,6 +98,8 @@ export class GrampsjsViewMap extends GrampsjsView { this._bounds = {} this._placeFilters = {} this._year = -1 + this._yearSpan = -1 + this._currentLayer = '' } renderContent() { @@ -107,6 +114,7 @@ export class GrampsjsViewMap extends GrampsjsView { longitude="${center[1]}" year="${this._year}" mapid="map-mapview" + @map:layerchange="${this._handleLayerChange}" @map:moveend="${this._handleMoveEnd}" id="map" zoom="6" @@ -124,6 +132,7 @@ export class GrampsjsViewMap extends GrampsjsView { >${this._renderPlaceDetails()} @@ -148,6 +157,10 @@ export class GrampsjsViewMap extends GrampsjsView { ` } + _handleLayerChange(e) { + this._currentLayer = e.detail.layer + } + update(changed) { super.update(changed) if (changed.has('active') && this.active) { @@ -164,6 +177,8 @@ export class GrampsjsViewMap extends GrampsjsView { _handleTimeSliderChange(event) { this._year = event.detail.value + this._yearSpan = event.detail.span + this._applyPlaceFilter() } _handlePlaceFilterChanged(event) { @@ -302,23 +317,37 @@ export class GrampsjsViewMap extends GrampsjsView { ) const filterFunction = place => { if (enabledFilters.includes('hasEvent')) { - return place?.backlinks?.event?.length ?? false + if (place?.backlinks?.event?.length === undefined) return false + } + if (this._year > 0 && this._yearSpan > 0) { + const placeEvents = + place?.backlinks?.event?.map(handle => + this._dataEvents?.find(event => event.handle === handle) + ) ?? [] + if (placeEvents.length === 0) return false + const yearMin = this._year - this._yearSpan + const yearMax = this._year + this._yearSpan + return placeEvents.some(event => + isDateBetweenYears(event.date, yearMin, yearMax) + ) } return true } this._filteredPlaces = [ - ...this._data.filter(place => filterFunction(place)), + ...this._dataPlaces.filter(place => filterFunction(place)), ] } firstUpdated() { - this._fetchData() + this._fetchPlaces() this._fetchDataLayers() + this._fetchEvents() } _fetchDataAll() { - this._fetchData() + this._fetchPlaces() this._fetchDataLayers() + this._fetchEvents() } async _fetchDataSearch(value) { @@ -337,7 +366,7 @@ export class GrampsjsViewMap extends GrampsjsView { } } - async _fetchData() { + async _fetchPlaces() { const data = await apiGet( `/api/places/?locale=${ this.strings?.__lang__ || 'en' @@ -346,7 +375,7 @@ export class GrampsjsViewMap extends GrampsjsView { this.loading = false if ('data' in data) { this.error = false - this._data = data.data + this._dataPlaces = data.data this._applyPlaceFilter() } else if ('error' in data) { this.error = true @@ -354,6 +383,18 @@ export class GrampsjsViewMap extends GrampsjsView { } } + async _fetchEvents() { + const data = await apiGet('/api/events/?keys=date,handle,place') + this.loading = false + if ('data' in data) { + this.error = false + this._dataEvents = data.data.filter(event => event.place) + } else if ('error' in data) { + this.error = true + this._errorMessage = data.error + } + } + async _fetchDataLayers() { const rules = { rules: [ @@ -378,15 +419,15 @@ export class GrampsjsViewMap extends GrampsjsView { } _getMapCenter() { - if (this._data.length === 0) { + if (this._dataPlaces.length === 0) { const locale = this.strings?.__lang__ || 'en' return languageCoordinates[locale] || [0, 0] } let x = 0 let y = 0 let n = 0 - for (let i = 0; i < this._data.length; i += 1) { - const p = this._data[i] + for (let i = 0; i < this._dataPlaces.length; i += 1) { + const p = this._dataPlaces[i] if ( p?.profile?.lat !== undefined && p?.profile?.lat !== null && From 7628d92b16a0fa0fec8668715983bb214067ec3d Mon Sep 17 00:00:00 2001 From: David Straub Date: Wed, 3 Jul 2024 21:49:47 +0200 Subject: [PATCH 10/14] Apply filter on layer change --- src/components/GrampsjsMap.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/GrampsjsMap.js b/src/components/GrampsjsMap.js index 46b625ce..c31e04fa 100644 --- a/src/components/GrampsjsMap.js +++ b/src/components/GrampsjsMap.js @@ -130,6 +130,12 @@ class GrampsjsMap extends LitElement { _handleBaseLayerChange(e) { this._currentLayer = e.name + if (this._currentLayer === 'OpenHistoricalMap') { + const mapLibreMap = this._gl.getMaplibreMap() + mapLibreMap.on('styledata', () => + filterByDecimalYear(mapLibreMap, this.year) + ) + } fireEvent(this, 'map:layerchange', {layer: this._currentLayer}) } @@ -150,7 +156,7 @@ class GrampsjsMap extends LitElement { this.year > 0 && this._currentLayer === 'OpenHistoricalMap' ) { - filterByDecimalYear(this._gl._glMap, this.year) + filterByDecimalYear(this._gl.getMaplibreMap(), this.year) return } if (this._map !== undefined) { From 734ea4c68d6fd024a17b3cc6826806d98613be09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Wed, 3 Jul 2024 14:02:54 -0700 Subject: [PATCH 11/14] Added OpenHistoricalMap attribution --- src/components/GrampsjsMap.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/GrampsjsMap.js b/src/components/GrampsjsMap.js index c31e04fa..ce469844 100644 --- a/src/components/GrampsjsMap.js +++ b/src/components/GrampsjsMap.js @@ -17,6 +17,8 @@ const defaultConfig = { leafletTileSize: 256, leafletZoomOffset: 0, glStyle: 'https://www.openhistoricalmap.org/map-styles/main/main.json', + glAttribution: + 'OpenHistoricalMap', } class GrampsjsMap extends LitElement { @@ -103,6 +105,7 @@ class GrampsjsMap extends LitElement { tileLayer.addTo(this._map) this._gl = L.maplibreGL({ style: config.glStyle, + attribution: config.glAttribution, }) this._map.addControl(L.control.zoom({position: 'bottomright'})) if (this.locateControl) { From 2a31281802dacc14ebd22b8770c7fcb1468e7e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Wed, 3 Jul 2024 14:09:38 -0700 Subject: [PATCH 12/14] Link directly to OHM homepage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The copyright page is naturally sparse for a projecct that doesn’t demand it, so the homepage would be a less confusing place for people who’ve never heard of the projecct to land. --- src/components/GrampsjsMap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/GrampsjsMap.js b/src/components/GrampsjsMap.js index ce469844..56b01380 100644 --- a/src/components/GrampsjsMap.js +++ b/src/components/GrampsjsMap.js @@ -18,7 +18,7 @@ const defaultConfig = { leafletZoomOffset: 0, glStyle: 'https://www.openhistoricalmap.org/map-styles/main/main.json', glAttribution: - 'OpenHistoricalMap', + 'OpenHistoricalMap', } class GrampsjsMap extends LitElement { From 7ed30bed7c6a81edd9fdea42306a6db9daeecbc0 Mon Sep 17 00:00:00 2001 From: David Straub Date: Fri, 5 Jul 2024 12:45:46 +0200 Subject: [PATCH 13/14] Handle all calendars --- src/components/GrampsjsMap.js | 8 +++++- src/components/GrampsjsMapTimeSlider.js | 6 ++-- src/util.js | 38 +++++++++++++++++++++++-- src/views/GrampsjsViewMap.js | 18 +++++++++++- 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/components/GrampsjsMap.js b/src/components/GrampsjsMap.js index 56b01380..1f0b3916 100644 --- a/src/components/GrampsjsMap.js +++ b/src/components/GrampsjsMap.js @@ -162,7 +162,13 @@ class GrampsjsMap extends LitElement { filterByDecimalYear(this._gl.getMaplibreMap(), this.year) return } - if (this._map !== undefined) { + if ( + this._map !== undefined && + (changed.has('latitude') || + changed.has('longitude') || + changed.has('mapid') || + changed.has('zoom')) + ) { if (this.latMin === 0 && this.latMax === 0) { this._map.setZoom(this.zoom) // eslint-disable-next-line new-cap diff --git a/src/components/GrampsjsMapTimeSlider.js b/src/components/GrampsjsMapTimeSlider.js index 19b44926..86e58ee6 100644 --- a/src/components/GrampsjsMapTimeSlider.js +++ b/src/components/GrampsjsMapTimeSlider.js @@ -80,12 +80,14 @@ class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { return { value: {type: Number}, span: {type: Number}, + min: {type: Number}, filterMap: {type: Boolean}, } } constructor() { super() + this.min = 1500 this.value = new Date().getFullYear() - 50 this.span = 50 this.filterMap = false @@ -98,7 +100,7 @@ class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { @input="${this._handleInput}" ?disabled="${!this.filterMap && this.span < 0}" labeled - min="1500" + min="${this.min}" max="${new Date().getFullYear()}" value="${this.value}" >
@@ -132,7 +134,7 @@ class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { anchor="span-button" skip-restore-focus > - ${[0, 10, 25, 50, 100].map( + ${[1, 10, 25, 50, 100].map( years => html`
± ${years}
diff --git a/src/util.js b/src/util.js index 5d3c233e..b54948e2 100644 --- a/src/util.js +++ b/src/util.js @@ -706,6 +706,38 @@ export function filterByDate(map, dateP) { filterByDecimalYear(map, decimalYear) } +export function getGregorianYears(date) { + if (date === undefined || dateIsEmpty(date)) { + return [undefined, undefined] + } + + let year1 = date.dateval[2] + let year2 = date.dateval[6] ?? year1 + + // handle different calendars. + // we appoximate to +/- 1 year, so we ignore the difference + // between Gregorian, Julian, and Swedish, and use simple + // linear approximations to the Islamic, Persian, and Hebrew calendars. + const CAL_HEBREW = 2 + const CAL_FRENCH = 3 + const CAL_PERSIAN = 4 + const CAL_ISLAMIC = 5 + if (date.calendar === CAL_HEBREW) { + year1 -= 3760 + year2 -= 3760 + } else if (date.calendar === CAL_FRENCH) { + year1 += 1791 + year2 += 1791 + } else if (date.calendar === CAL_PERSIAN) { + year1 += 621 + year2 += 621 + } else if (date.calendar === CAL_ISLAMIC) { + year1 = Math.floor(0.97022 * year1 + 621.565) + year2 = Math.floor(0.97022 * year2 + 621.565) + } + return [year1, year2] +} + export function isDateBetweenYears(date, yearMin, yearMax) { const MOD_BEFORE = 1 const MOD_AFTER = 2 @@ -722,8 +754,10 @@ export function isDateBetweenYears(date, yearMin, yearMax) { return false } - let year1 = date.dateval[2] - let year2 = date.dateval[6] ?? year1 + let [year1, year2] = getGregorianYears(date) + if (year1 === undefined) { + return false + } if (date.modifier === MOD_BEFORE || date.modifier === MOD_TO) { year1 -= RANGE_BEFORE diff --git a/src/views/GrampsjsViewMap.js b/src/views/GrampsjsViewMap.js index 55a26c0e..b65cfa05 100644 --- a/src/views/GrampsjsViewMap.js +++ b/src/views/GrampsjsViewMap.js @@ -8,7 +8,7 @@ import '../components/GrampsjsMapSearchbox.js' import '../components/GrampsjsMapTimeSlider.js' import '../components/GrampsjsPlaceBox.js' import {apiGet, getMediaUrl} from '../api.js' -import {isDateBetweenYears} from '../util.js' +import {isDateBetweenYears, getGregorianYears} from '../util.js' import '@material/mwc-textfield' // This is used for initial map center in absence of places @@ -82,6 +82,7 @@ export class GrampsjsViewMap extends GrampsjsView { _year: {type: Number}, _yearSpan: {type: Number}, _currentLayer: {type: String}, + _minYear: {type: Number}, } } @@ -100,6 +101,7 @@ export class GrampsjsViewMap extends GrampsjsView { this._year = -1 this._yearSpan = -1 this._currentLayer = '' + this._minYear = 1500 } renderContent() { @@ -132,6 +134,7 @@ export class GrampsjsViewMap extends GrampsjsView { >${this._renderPlaceDetails()} event.place) + this._minYear = this._getMinYear() } else if ('error' in data) { this.error = true this._errorMessage = data.error } } + _getMinYear() { + const years = this._dataEvents + ?.filter(event => event.place) + ?.map(event => getGregorianYears(event.date)?.[0]) + ?.filter(y => y !== undefined) + let minYear = Math.min(...years) + const lastYear = new Date().getFullYear() - 1 + minYear = Math.min(minYear, lastYear) + minYear = Math.max(minYear, 1) // disallow negative + return minYear + } + async _fetchDataLayers() { const rules = { rules: [ From cbe4cbd6397b78f88858d9df729cc9e91bf744ca Mon Sep 17 00:00:00 2001 From: David Straub Date: Fri, 5 Jul 2024 12:57:16 +0200 Subject: [PATCH 14/14] Add tooltips to buttons --- lang/en.json | 3 ++- src/components/GrampsjsMapTimeSlider.js | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lang/en.json b/lang/en.json index 57b0e664..4e1f93ba 100644 --- a/lang/en.json +++ b/lang/en.json @@ -170,5 +170,6 @@ "simple": "simple", "Are you sure?": "Are you sure?", "This action cannot be undone.": "This action cannot be undone.", - "Yes": "Yes" + "Yes": "Yes", + "Toggle time filter for places": "Toggle time filter for places" } \ No newline at end of file diff --git a/src/components/GrampsjsMapTimeSlider.js b/src/components/GrampsjsMapTimeSlider.js index 86e58ee6..f0075d7b 100644 --- a/src/components/GrampsjsMapTimeSlider.js +++ b/src/components/GrampsjsMapTimeSlider.js @@ -11,6 +11,7 @@ import {sharedStyles} from '../SharedStyles.js' import {GrampsjsTranslateMixin} from '../mixins/GrampsjsTranslateMixin.js' import {fireEvent} from '../util.js' import {renderIconSvg} from '../icons.js' +import './GrampsjsTooltip.js' class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { static get styles() { @@ -118,15 +119,22 @@ class GrampsjsMapTimeSlider extends GrampsjsTranslateMixin(LitElement) { @click="${this._handleSpanClick}" ?disabled="${this.span < 0}" > + ${this._('Span')} ${renderIconSvg(mdiCog, 'var(--md-sys-color-primary)')}
+ ${this._('Toggle time filter for places')}