From 4d25c158138c5892c837d7a575f4464d32a2569e Mon Sep 17 00:00:00 2001 From: Caden Buckhalt Date: Fri, 22 Nov 2024 15:13:12 -0800 Subject: [PATCH] first pass at geospatial interface set up interface, mapbox, tileset for census tracts, selected tract handling --- .env.example | 1 + env.js | 3 + .../containers/Interfaces/Geospatial.tsx | 102 ++++++++ lib/protocol-validation/schemas/src/8.zod.ts | 5 + lib/test-protocol.ts | 5 + package.json | 1 + pnpm-lock.yaml | 224 ++++++++++++++++++ 7 files changed, 341 insertions(+) create mode 100644 lib/interviewer/containers/Interfaces/Geospatial.tsx diff --git a/.env.example b/.env.example index 90199c6b..62374737 100644 --- a/.env.example +++ b/.env.example @@ -6,6 +6,7 @@ #SANDBOX_MODE=false # true or false - if true, the app will use the sandbox mode, which disables resetting the database and other features #PUBLIC_URL="http://yourdomain.com" # When using advanced deployment, this is required. Set to the domain name of your app #INSTALLATION_ID="your-app-name" # A unique identifier for your app, used for analytics. Generated automatically if not set. +#NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN='' # Public mapbox access token for geospatial feature # ------------------- # Required environment variables diff --git a/env.js b/env.js index 344f6349..c03d92e7 100644 --- a/env.js +++ b/env.js @@ -38,6 +38,7 @@ export const env = createEnv({ SANDBOX_MODE: strictBooleanSchema, APP_VERSION: z.string().optional(), COMMIT_HASH: z.string().optional(), + NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN: z.string().optional(), }, /** * You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g. @@ -53,6 +54,8 @@ export const env = createEnv({ SANDBOX_MODE: process.env.SANDBOX_MODE, APP_VERSION: process.env.APP_VERSION, COMMIT_HASH: process.env.COMMIT_HASH, + NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN: + process.env.NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN, }, /** * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially diff --git a/lib/interviewer/containers/Interfaces/Geospatial.tsx b/lib/interviewer/containers/Interfaces/Geospatial.tsx new file mode 100644 index 00000000..0dec1860 --- /dev/null +++ b/lib/interviewer/containers/Interfaces/Geospatial.tsx @@ -0,0 +1,102 @@ +import mapboxgl from 'mapbox-gl'; +import 'mapbox-gl/dist/mapbox-gl.css'; +import { useEffect, useRef, useState } from 'react'; +import { env } from '~/env'; + +const INITIAL_CENTER = [-87.6298, 41.8781]; //chicago +const INITIAL_ZOOM = 10; +const TILESET_URL = 'mapbox://buckhalt.8xmfmn5d'; // chicago census tracts tileset. private -- needs to be used with corresponding mapbox token. + +export default function GeospatialInterface() { + const mapRef = useRef(); + const mapContainerRef = useRef(); + const [selectedCensusTract, setSelectedCensusTract] = useState(null); + + const handleReset = () => { + mapRef.current.flyTo({ + center: INITIAL_CENTER, + zoom: INITIAL_ZOOM, + }); + setSelectedCensusTract(null); + }; + + useEffect(() => { + mapboxgl.accessToken = env.NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN; + mapRef.current = new mapboxgl.Map({ + container: mapContainerRef.current, + center: INITIAL_CENTER, + zoom: INITIAL_ZOOM, + style: 'mapbox://styles/mapbox/light-v11', + }); + + mapRef.current.on('load', () => { + // add census geojson using tileset + mapRef.current.addSource('chicago-census-tiles', { + type: 'vector', + url: TILESET_URL, + }); + + // census tract outlines + mapRef.current.addLayer({ + 'id': 'censusTractsOutlineLayer', + 'type': 'line', + 'source': 'chicago-census-tiles', + 'source-layer': 'Census_Tracts_2010-6h8rw5', + 'paint': { + 'line-color': 'purple', + 'line-width': 2, + }, + }); + mapRef.current.addLayer({ + 'id': 'censusTractsFillLayer', + 'type': 'fill', + 'source': 'chicago-census-tiles', + 'source-layer': 'Census_Tracts_2010-6h8rw5', + 'paint': { + 'fill-color': 'purple', + 'fill-opacity': 0.1, + }, + }); + + mapRef.current.addLayer({ + 'id': 'selectedCensusTract', + 'type': 'fill', + 'source': 'chicago-census-tiles', + 'source-layer': 'Census_Tracts_2010-6h8rw5', + 'paint': { + 'fill-color': 'green', + 'fill-opacity': 0.5, + }, + 'filter': ['==', 'namelsad10', ''], + }); + + // handle click of census tracts + mapRef.current.on('click', 'censusTractsFillLayer', (e) => { + const feature = e.features[0]; + const tractId = feature.properties.namelsad10; // census tract name prop in the tileset. comes from the geojson. + setSelectedCensusTract(tractId); + + mapRef.current.setFilter('selectedCensusTract', [ + '==', + 'namelsad10', + tractId, + ]); + }); + }); + + return () => { + mapRef.current.remove(); + }; + }, []); + + return ( +
+

Geospatial Interface

+
+ +

Selected: {selectedCensusTract}

+
+
+
+ ); +} diff --git a/lib/protocol-validation/schemas/src/8.zod.ts b/lib/protocol-validation/schemas/src/8.zod.ts index 9888de3d..5182df54 100644 --- a/lib/protocol-validation/schemas/src/8.zod.ts +++ b/lib/protocol-validation/schemas/src/8.zod.ts @@ -464,6 +464,10 @@ const familyTreeCensusStage = baseStageSchema.extend({ type: z.literal('FamilyTreeCensus'), }); +const geospatialStage = baseStageSchema.extend({ + type: z.literal('Geospatial'), +}); + // Combine all stage types const stageSchema = z.discriminatedUnion('type', [ egoFormStage, @@ -482,6 +486,7 @@ const stageSchema = z.discriminatedUnion('type', [ anonymisationStage, oneToManyDyadCensusStage, familyTreeCensusStage, + geospatialStage, ]); // Main Protocol Schema diff --git a/lib/test-protocol.ts b/lib/test-protocol.ts index ba61c81b..fcec5d49 100644 --- a/lib/test-protocol.ts +++ b/lib/test-protocol.ts @@ -2,6 +2,11 @@ import { type Protocol } from './protocol-validation/schemas/src/8.zod'; export const protocol: Protocol = { stages: [ + { + id: 'geospatial-interface', + label: 'Geospatial Interface', + type: 'Geospatial', + }, { id: 'anonymisation-interface', label: 'Anonymisation Interface', diff --git a/package.json b/package.json index f35c4f11..0ec95d18 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "lucia": "^2.7.7", "lucide-react": "^0.314.0", "luxon": "^3.5.0", + "mapbox-gl": "^3.8.0", "motion": "^11.12.0", "next": "^14.2.16", "nuqs": "^1.19.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e0294c97..36419fc8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -143,6 +143,9 @@ importers: luxon: specifier: ^3.5.0 version: 3.5.0 + mapbox-gl: + specifier: ^3.8.0 + version: 3.8.0 motion: specifier: ^11.12.0 version: 11.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1137,6 +1140,29 @@ packages: '@prisma/client': ^4.2.0 || ^5.0.0 lucia: ^2.0.0 + '@mapbox/jsonlint-lines-primitives@2.0.2': + resolution: {integrity: sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==} + engines: {node: '>= 0.6'} + + '@mapbox/mapbox-gl-supported@3.0.0': + resolution: {integrity: sha512-2XghOwu16ZwPJLOFVuIOaLbN0iKMn867evzXFyf0P22dqugezfJwLmdanAgU25ITvz1TvOfVP4jsDImlDJzcWg==} + + '@mapbox/point-geometry@0.1.0': + resolution: {integrity: sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==} + + '@mapbox/tiny-sdf@2.0.6': + resolution: {integrity: sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA==} + + '@mapbox/unitbezier@0.0.1': + resolution: {integrity: sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==} + + '@mapbox/vector-tile@1.3.1': + resolution: {integrity: sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==} + + '@mapbox/whoots-js@3.1.0': + resolution: {integrity: sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==} + engines: {node: '>=6.0.0'} + '@next/env@14.2.16': resolution: {integrity: sha512-fLrX5TfJzHCbnZ9YUSnGW63tMV3L4nSfhgOQ0iCcX21Pt+VSTDuaLsSuL8J/2XAiVA5AnzvXDpf6pMs60QxOag==} @@ -2077,6 +2103,12 @@ packages: '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/geojson-vt@3.2.5': + resolution: {integrity: sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g==} + + '@types/geojson@7946.0.14': + resolution: {integrity: sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==} + '@types/graceful-fs@4.1.9': resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} @@ -2104,6 +2136,12 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + '@types/mapbox__point-geometry@0.1.4': + resolution: {integrity: sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==} + + '@types/mapbox__vector-tile@1.3.4': + resolution: {integrity: sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==} + '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} @@ -2119,6 +2157,9 @@ packages: '@types/papaparse@5.3.15': resolution: {integrity: sha512-JHe6vF6x/8Z85nCX4yFdDslN11d+1pr12E526X8WAfhadOeaOTx5AuIkvDKIBopfvlzpzkdMx4YyvSKCM9oqtw==} + '@types/pbf@3.0.5': + resolution: {integrity: sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==} + '@types/prop-types@15.7.13': resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} @@ -2140,6 +2181,9 @@ packages: '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + '@types/supercluster@7.1.3': + resolution: {integrity: sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -2598,6 +2642,9 @@ packages: character-reference-invalid@2.0.1: resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + cheap-ruler@4.0.0: + resolution: {integrity: sha512-0BJa8f4t141BYKQyn9NSQt1PguFQXMXwZiA5shfoaBYHAb2fFk2RAX+tiWMoQU+Agtzt3mdt0JtuyshAXqZ+Vw==} + check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -2725,6 +2772,9 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + csscolorparser@1.0.3: + resolution: {integrity: sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -2881,6 +2931,9 @@ packages: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} + earcut@3.0.0: + resolution: {integrity: sha512-41Fs7Q/PLq1SDbqjsgcY7GA42T0jvaCNGXgGtsNdvg+Yv8eIu06bxv4/PoREkZ9nMDNwnUSG9OFB9+yv8eKhDg==} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -3264,6 +3317,9 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + geojson-vt@4.0.2: + resolution: {integrity: sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==} + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -3291,6 +3347,9 @@ packages: get-tsconfig@4.8.1: resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==} + gl-matrix@3.4.3: + resolution: {integrity: sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -3335,6 +3394,9 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + grid-index@1.1.0: + resolution: {integrity: sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==} + has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} @@ -3862,6 +3924,9 @@ packages: jszip@3.10.1: resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + kdbush@4.0.2: + resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -4030,6 +4095,9 @@ packages: makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + mapbox-gl@3.8.0: + resolution: {integrity: sha512-7iQ6wxAf8UedbNYTzNsyr2J25ozIBA4vmKY0xUDXQlHEokulzPENwjjmLxHQGRylDpOmR0c8kPEbtHCaQE2eMw==} + mdast-util-find-and-replace@3.0.1: resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} @@ -4195,6 +4263,9 @@ packages: multipasta@0.2.5: resolution: {integrity: sha512-c8eMDb1WwZcE02WVjHoOmUVk7fnKU/RmUcosHACglrWAuPQsEJv+E8430sXj6jNc1jHw0zrS16aCjQh4BcEb4A==} + murmurhash-js@1.0.0: + resolution: {integrity: sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==} + nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -4377,6 +4448,10 @@ packages: resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} engines: {node: '>= 14.16'} + pbf@3.3.0: + resolution: {integrity: sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==} + hasBin: true + picocolors@1.1.0: resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} @@ -4415,6 +4490,9 @@ packages: resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} engines: {node: ^10 || ^12 || >=14} + potpack@2.0.0: + resolution: {integrity: sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw==} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -4509,6 +4587,9 @@ packages: property-information@6.5.0: resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} + protocol-buffers-schema@3.6.0: + resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -4525,6 +4606,9 @@ packages: quickselect@2.0.0: resolution: {integrity: sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==} + quickselect@3.0.0: + resolution: {integrity: sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==} + rbush@3.0.1: resolution: {integrity: sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==} @@ -4758,6 +4842,9 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve-protobuf-schema@2.1.0: + resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==} + resolve.exports@2.0.2: resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} engines: {node: '>=10'} @@ -4837,6 +4924,10 @@ packages: engines: {node: '>=10'} hasBin: true + serialize-to-js@3.1.2: + resolution: {integrity: sha512-owllqNuDDEimQat7EPG0tH7JjO090xKNzUtYz6X+Sk2BXDnOCilDdNLwjWeFywG9xkJul1ULvtUQa9O4pUaY0w==} + engines: {node: '>=4.0.0'} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -5031,6 +5122,9 @@ packages: summary@2.1.0: resolution: {integrity: sha512-nMIjMrd5Z2nuB2RZCKJfFMjgS3fygbeyGk9PxPPaJR1RIcyN9yn4A63Isovzm3ZtQuEkLBVgMdPup8UeLH7aQw==} + supercluster@8.0.1: + resolution: {integrity: sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==} + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -5100,6 +5194,9 @@ packages: tinyqueue@2.0.3: resolution: {integrity: sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==} + tinyqueue@3.0.0: + resolution: {integrity: sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==} + tinyrainbow@1.2.0: resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} engines: {node: '>=14.0.0'} @@ -5405,6 +5502,9 @@ packages: jsdom: optional: true + vt-pbf@3.1.3: + resolution: {integrity: sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==} + w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} @@ -6278,6 +6378,22 @@ snapshots: '@prisma/client': 5.22.0(prisma@5.22.0) lucia: 2.7.7 + '@mapbox/jsonlint-lines-primitives@2.0.2': {} + + '@mapbox/mapbox-gl-supported@3.0.0': {} + + '@mapbox/point-geometry@0.1.0': {} + + '@mapbox/tiny-sdf@2.0.6': {} + + '@mapbox/unitbezier@0.0.1': {} + + '@mapbox/vector-tile@1.3.1': + dependencies: + '@mapbox/point-geometry': 0.1.0 + + '@mapbox/whoots-js@3.1.0': {} + '@next/env@14.2.16': {} '@next/eslint-plugin-next@15.0.3': @@ -7131,6 +7247,12 @@ snapshots: '@types/estree@1.0.6': {} + '@types/geojson-vt@3.2.5': + dependencies: + '@types/geojson': 7946.0.14 + + '@types/geojson@7946.0.14': {} + '@types/graceful-fs@4.1.9': dependencies: '@types/node': 22.9.0 @@ -7163,6 +7285,20 @@ snapshots: '@types/json5@0.0.29': {} + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.13 + + '@types/lodash@4.17.13': {} + + '@types/mapbox__point-geometry@0.1.4': {} + + '@types/mapbox__vector-tile@1.3.4': + dependencies: + '@types/geojson': 7946.0.14 + '@types/mapbox__point-geometry': 0.1.4 + '@types/pbf': 3.0.5 + '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3 @@ -7181,6 +7317,8 @@ snapshots: dependencies: '@types/node': 20.16.5 + '@types/pbf@3.0.5': {} + '@types/prop-types@15.7.13': {} '@types/react-dom@18.3.1': @@ -7205,6 +7343,10 @@ snapshots: '@types/stack-utils@2.0.3': {} + '@types/supercluster@7.1.3': + dependencies: + '@types/geojson': 7946.0.14 + '@types/unist@2.0.11': {} '@types/unist@3.0.3': {} @@ -7760,6 +7902,8 @@ snapshots: character-reference-invalid@2.0.1: {} + cheap-ruler@4.0.0: {} + check-error@2.1.1: {} chokidar@4.0.0: @@ -7897,6 +8041,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + csscolorparser@1.0.3: {} + cssesc@3.0.0: {} cssstyle@4.1.0: @@ -8044,6 +8190,8 @@ snapshots: dotenv@16.4.5: {} + earcut@3.0.0: {} + eastasianwidth@0.2.0: {} easy-table@1.2.0: @@ -8613,6 +8761,8 @@ snapshots: gensync@1.0.0-beta.2: {} + geojson-vt@4.0.2: {} + get-caller-file@2.0.5: {} get-intrinsic@1.2.4: @@ -8639,6 +8789,8 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 + gl-matrix@3.4.3: {} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -8695,6 +8847,8 @@ snapshots: graphemer@1.4.0: {} + grid-index@1.1.0: {} + has-bigints@1.0.2: {} has-flag@3.0.0: {} @@ -9486,6 +9640,8 @@ snapshots: readable-stream: 2.3.8 setimmediate: 1.0.5 + kdbush@4.0.2: {} + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -9636,6 +9792,37 @@ snapshots: dependencies: tmpl: 1.0.5 + mapbox-gl@3.8.0: + dependencies: + '@mapbox/jsonlint-lines-primitives': 2.0.2 + '@mapbox/mapbox-gl-supported': 3.0.0 + '@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 + '@types/geojson': 7946.0.14 + '@types/geojson-vt': 3.2.5 + '@types/mapbox__point-geometry': 0.1.4 + '@types/mapbox__vector-tile': 1.3.4 + '@types/pbf': 3.0.5 + '@types/supercluster': 7.1.3 + cheap-ruler: 4.0.0 + csscolorparser: 1.0.3 + earcut: 3.0.0 + geojson-vt: 4.0.2 + gl-matrix: 3.4.3 + grid-index: 1.1.0 + kdbush: 4.0.2 + murmurhash-js: 1.0.0 + pbf: 3.3.0 + potpack: 2.0.0 + quickselect: 3.0.0 + serialize-to-js: 3.1.2 + supercluster: 8.0.1 + tinyqueue: 3.0.0 + vt-pbf: 3.1.3 + mdast-util-find-and-replace@3.0.1: dependencies: '@types/mdast': 4.0.4 @@ -9919,6 +10106,14 @@ snapshots: multipasta@0.2.5: {} + murmurhash-js@1.0.0: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + nanoid@3.3.7: {} natural-compare@1.4.0: {} @@ -10106,6 +10301,11 @@ snapshots: pathval@2.0.0: {} + pbf@3.3.0: + dependencies: + ieee754: 1.2.1 + resolve-protobuf-schema: 2.1.0 + picocolors@1.1.0: {} picomatch@2.3.1: {} @@ -10139,6 +10339,8 @@ snapshots: picocolors: 1.1.0 source-map-js: 1.2.1 + potpack@2.0.0: {} + prelude-ls@1.2.1: {} prettier-plugin-tailwindcss@0.6.9(prettier@3.3.3): @@ -10180,6 +10382,8 @@ snapshots: property-information@6.5.0: {} + protocol-buffers-schema@3.6.0: {} + punycode@2.3.1: {} pure-rand@6.1.0: {} @@ -10190,6 +10394,8 @@ snapshots: quickselect@2.0.0: {} + quickselect@3.0.0: {} + rbush@3.0.1: dependencies: quickselect: 2.0.0 @@ -10469,6 +10675,10 @@ snapshots: resolve-pkg-maps@1.0.0: {} + resolve-protobuf-schema@2.1.0: + dependencies: + protocol-buffers-schema: 3.6.0 + resolve.exports@2.0.2: {} resolve@1.22.8: @@ -10566,6 +10776,8 @@ snapshots: semver@7.6.3: {} + serialize-to-js@3.1.2: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -10797,6 +11009,10 @@ snapshots: summary@2.1.0: {} + supercluster@8.0.1: + dependencies: + kdbush: 4.0.2 + supports-color@5.5.0: dependencies: has-flag: 3.0.0 @@ -10859,6 +11075,8 @@ snapshots: tinyqueue@2.0.3: {} + tinyqueue@3.0.0: {} + tinyrainbow@1.2.0: {} tinyspy@3.0.2: {} @@ -11175,6 +11393,12 @@ snapshots: - supports-color - terser + vt-pbf@3.1.3: + dependencies: + '@mapbox/point-geometry': 0.1.0 + '@mapbox/vector-tile': 1.3.1 + pbf: 3.3.0 + w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0