diff --git a/.vscode/settings.json b/.vscode/settings.json index 25cc34e6..c5afc714 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -48,6 +48,7 @@ "nowrap", "Oklab", "oklch", + "openlayers", "parameterizes", "piexif", "piexifjs", diff --git a/package.json b/package.json index 348e52ea..0ef3b5d1 100644 --- a/package.json +++ b/package.json @@ -40,11 +40,13 @@ "next": "15.5.4", "next-auth": "5.0.0-beta.29", "next-themes": "^0.4.6", + "ol": "^10.6.1", "pg": "^8.16.3", "piexifjs": "^1.0.6", "react": "19.1.1", "react-dom": "19.1.1", "react-icons": "^5.5.0", + "react-openlayers": "^10.5.1", "sanitize-html": "^2.17.0", "sharp": "^0.34.4", "sonner": "^2.0.7", @@ -57,7 +59,7 @@ "devDependencies": { "@eslint/eslintrc": "^3.3.1", "@next/bundle-analyzer": "15.5.4", - "@next/eslint-plugin-next": "^15.5.4", + "@next/eslint-plugin-next": "15.5.4", "@stylistic/eslint-plugin": "^5.4.0", "@tailwindcss/postcss": "^4.1.13", "@testing-library/dom": "^10.4.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 94af60dd..9acff364 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -98,6 +98,9 @@ importers: next-themes: specifier: ^0.4.6 version: 0.4.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + ol: + specifier: ^10.6.1 + version: 10.6.1 pg: specifier: ^8.16.3 version: 8.16.3 @@ -113,6 +116,9 @@ importers: react-icons: specifier: ^5.5.0 version: 5.5.0(react@19.1.1) + react-openlayers: + specifier: ^10.5.1 + version: 10.5.1(ol@10.6.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) sanitize-html: specifier: ^2.17.0 version: 2.17.0 @@ -145,7 +151,7 @@ importers: specifier: 15.5.4 version: 15.5.4 '@next/eslint-plugin-next': - specifier: ^15.5.4 + specifier: 15.5.4 version: 15.5.4 '@stylistic/eslint-plugin': specifier: ^5.4.0 @@ -1066,6 +1072,9 @@ packages: '@panva/hkdf@1.2.1': resolution: {integrity: sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==} + '@petamoriken/float16@3.9.3': + resolution: {integrity: sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g==} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -1805,6 +1814,9 @@ packages: '@types/piexifjs@1.0.0': resolution: {integrity: sha512-PPiGeCkmkZQgYjvqtjD3kp4OkbCox2vEFVuK4DaLVOIazJLAXk+/ujbizkIPH5CN4AnN9Clo5ckzUlaj3+SzCA==} + '@types/rbush@4.0.0': + resolution: {integrity: sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ==} + '@types/react-dom@19.1.9': resolution: {integrity: sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==} peerDependencies: @@ -2491,6 +2503,9 @@ packages: duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + earcut@3.0.2: + resolution: {integrity: sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -2820,6 +2835,10 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + geotiff@2.1.3: + resolution: {integrity: sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==} + engines: {node: '>=10.19'} + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -3375,6 +3394,9 @@ packages: resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} engines: {node: '>=0.10'} + lerc@3.0.0: + resolution: {integrity: sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==} + leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -3673,6 +3695,9 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} + ol@10.6.1: + resolution: {integrity: sha512-xp174YOwPeLj7c7/8TCIEHQ4d41tgTDDhdv6SqNdySsql5/MaFJEJkjlsYcvOPt7xA6vrum/QG4UdJ0iCGT1cg==} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -3715,10 +3740,16 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + pako@2.1.0: + resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse-headers@2.0.6: + resolution: {integrity: sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==} + parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -3748,6 +3779,10 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + pbf@4.0.1: + resolution: {integrity: sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==} + hasBin: true + pg-cloudflare@1.2.7: resolution: {integrity: sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==} @@ -3859,6 +3894,9 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + 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'} @@ -3869,10 +3907,20 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-lru@6.1.2: + resolution: {integrity: sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==} + engines: {node: '>=12'} + quick-lru@7.1.0: resolution: {integrity: sha512-Pzd/4IFnTb8E+I1P5rbLQoqpUHcXKg48qTYKi4EANg+sTPwGFEMOcYGiiZz6xuQcOMZP7MPsrdAPx+16Q8qahg==} engines: {node: '>=18'} + quickselect@3.0.0: + resolution: {integrity: sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==} + + rbush@4.0.1: + resolution: {integrity: sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==} + react-dom@19.1.1: resolution: {integrity: sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==} peerDependencies: @@ -3892,6 +3940,13 @@ packages: react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + react-openlayers@10.5.1: + resolution: {integrity: sha512-IWEXerUjn/N6sbUP/FURKvYDtJj/FZVxmK0WBw4kbAVVyQvs/5JTlD/x9+QEPqNzbAITX6lwasdrQ+WW51y/6g==} + peerDependencies: + ol: ^10.5.0 + react: ^18 || ^19 + react-dom: ^18 || ^19 + react-remove-scroll-bar@2.3.8: resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} engines: {node: '>=10'} @@ -3957,6 +4012,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@1.22.10: resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} engines: {node: '>= 0.4'} @@ -4402,6 +4460,9 @@ packages: walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + web-worker@1.5.0: + resolution: {integrity: sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -4497,6 +4558,9 @@ packages: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} + xml-utils@1.10.2: + resolution: {integrity: sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==} + xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} @@ -4534,6 +4598,9 @@ packages: zod@4.1.11: resolution: {integrity: sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==} + zstddec@0.1.0: + resolution: {integrity: sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==} + snapshots: '@adobe/css-tools@4.4.4': {} @@ -5783,6 +5850,8 @@ snapshots: '@panva/hkdf@1.2.1': {} + '@petamoriken/float16@3.9.3': {} + '@pkgjs/parseargs@0.11.0': optional: true @@ -6630,6 +6699,8 @@ snapshots: '@types/piexifjs@1.0.0': {} + '@types/rbush@4.0.0': {} + '@types/react-dom@19.1.9(@types/react@19.1.15)': dependencies: '@types/react': 19.1.15 @@ -7294,6 +7365,8 @@ snapshots: duplexer@0.1.2: {} + earcut@3.0.2: {} + eastasianwidth@0.2.0: {} electron-to-chromium@1.5.218: {} @@ -7764,6 +7837,17 @@ snapshots: gensync@1.0.0-beta.2: {} + geotiff@2.1.3: + dependencies: + '@petamoriken/float16': 3.9.3 + lerc: 3.0.0 + pako: 2.1.0 + parse-headers: 2.0.6 + quick-lru: 6.1.2 + web-worker: 1.5.0 + xml-utils: 1.10.2 + zstddec: 0.1.0 + get-caller-file@2.0.5: {} get-intrinsic@1.3.0: @@ -8554,6 +8638,8 @@ snapshots: dependencies: language-subtag-registry: 0.3.23 + lerc@3.0.0: {} + leven@3.1.0: {} levn@0.4.1: @@ -8792,6 +8878,14 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + ol@10.6.1: + dependencies: + '@types/rbush': 4.0.0 + earcut: 3.0.2 + geotiff: 2.1.3 + pbf: 4.0.1 + rbush: 4.0.1 + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -8837,10 +8931,14 @@ snapshots: package-json-from-dist@1.0.1: {} + pako@2.1.0: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 + parse-headers@2.0.6: {} + parse-json@5.2.0: dependencies: '@babel/code-frame': 7.27.1 @@ -8867,6 +8965,10 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.2 + pbf@4.0.1: + dependencies: + resolve-protobuf-schema: 2.1.0 + pg-cloudflare@1.2.7: optional: true @@ -8972,14 +9074,24 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 + protocol-buffers-schema@3.6.0: {} + punycode@2.3.1: {} pure-rand@7.0.1: {} queue-microtask@1.2.3: {} + quick-lru@6.1.2: {} + quick-lru@7.1.0: {} + quickselect@3.0.0: {} + + rbush@4.0.1: + dependencies: + quickselect: 3.0.0 + react-dom@19.1.1(react@19.1.1): dependencies: react: 19.1.1 @@ -8995,6 +9107,12 @@ snapshots: react-is@18.3.1: {} + react-openlayers@10.5.1(ol@10.6.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + dependencies: + ol: 10.6.1 + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + react-remove-scroll-bar@2.3.8(@types/react@19.1.15)(react@19.1.1): dependencies: react: 19.1.1 @@ -9061,6 +9179,10 @@ snapshots: resolve-pkg-maps@1.0.0: {} + resolve-protobuf-schema@2.1.0: + dependencies: + protocol-buffers-schema: 3.6.0 + resolve@1.22.10: dependencies: is-core-module: 2.16.1 @@ -9589,6 +9711,8 @@ snapshots: dependencies: makeerror: 1.0.12 + web-worker@1.5.0: {} + webidl-conversions@3.0.1: {} webidl-conversions@7.0.0: {} @@ -9700,6 +9824,8 @@ snapshots: xml-name-validator@5.0.0: {} + xml-utils@1.10.2: {} + xmlchars@2.2.0: {} xtend@4.0.2: {} @@ -9727,3 +9853,5 @@ snapshots: yocto-queue@0.1.0: {} zod@4.1.11: {} + + zstddec@0.1.0: {} diff --git a/src/album/AlbumHeader.tsx b/src/album/AlbumHeader.tsx index 9f9e968e..68062012 100644 --- a/src/album/AlbumHeader.tsx +++ b/src/album/AlbumHeader.tsx @@ -66,8 +66,8 @@ export default async function AlbumHeader({ > {album.location && } {tags.length > 0 && <> + }}> {children} ; } diff --git a/src/components/shared-hover/SharedHover.tsx b/src/components/shared-hover/SharedHover.tsx index 7e13fda7..2b984e15 100644 --- a/src/components/shared-hover/SharedHover.tsx +++ b/src/components/shared-hover/SharedHover.tsx @@ -1,11 +1,15 @@ +'use client'; + import { ReactNode, useRef, useEffect } from 'react'; import { SharedHoverProps, useSharedHoverState } from '../shared-hover/state'; import useSupportsHover from '@/utility/useSupportsHover'; +import clsx from 'clsx/lite'; export default function SharedHover({ hoverKey: key, children, content, + className, width, height, offsetAbove = -1, @@ -15,6 +19,7 @@ export default function SharedHover({ hoverKey: string children :ReactNode content: ReactNode + className?: string width: number height: number offsetAbove?: number @@ -47,7 +52,7 @@ export default function SharedHover({ return (
supportsHover && showHover?.(ref.current, { diff --git a/src/photo/TopPhotoEntities.tsx b/src/photo/TopPhotoEntities.tsx index 1723bb8c..8a26112f 100644 --- a/src/photo/TopPhotoEntities.tsx +++ b/src/photo/TopPhotoEntities.tsx @@ -4,7 +4,7 @@ import MaskedScroll from '@/components/MaskedScroll'; import PhotoAlbum from '@/album/PhotoAlbum'; import PhotoTag from '@/tag/PhotoTag'; import PhotoFavs from '@/tag/PhotoFavs'; -import clsx from 'clsx'; +import clsx from 'clsx/lite'; import { CATEGORY_VISIBILITY } from '@/app/config'; import PhotoRecents from '@/recents/PhotoRecents'; import PhotoFilm from '@/film/PhotoFilm'; diff --git a/src/place/PlaceEntity.tsx b/src/place/PlaceEntity.tsx index 165b8b9f..c0faf85b 100644 --- a/src/place/PlaceEntity.tsx +++ b/src/place/PlaceEntity.tsx @@ -3,23 +3,50 @@ import { Place } from '.'; import EntityLink, { EntityLinkExternalProps, } from '@/components/entity/EntityLink'; +import { getDimensionsFromSize } from '@/utility/size'; +import PlaceMap from './PlaceMap'; +import SharedHover from '@/components/shared-hover/SharedHover'; +import clsx from 'clsx/lite'; + +const { width, height } = getDimensionsFromSize(300, 16 / 9); export default function PlaceEntity({ - location, + place, ...props }: { - location: Place + place: Place } & EntityLinkExternalProps) { return ( - } - label={location.nameFormatted || location.name} - path={location.link} - pathTarget="_blank" - badged - /> + + + + {place.nameFormatted || place.name} + +
, + className: 'inline-flex', + width, + height, + }}> + } + label={place.nameFormatted || place.name} + path={place.link} + pathTarget="_blank" + badged + /> + ); -} \ No newline at end of file +} diff --git a/src/place/PlaceMap.tsx b/src/place/PlaceMap.tsx new file mode 100644 index 00000000..0efbd55c --- /dev/null +++ b/src/place/PlaceMap.tsx @@ -0,0 +1,73 @@ +'use client'; + +import { OSM } from 'ol/source'; +import { fromLonLat } from 'ol/proj'; +import { useMemo, useRef } from 'react'; +import { Map, View, TileLayer } from 'react-openlayers'; +import { Place } from '.'; +import { boundingExtent } from 'ol/extent'; + +import 'react-openlayers/dist/index.css'; // for css + +const MULTIPLIER = 2; + +export default function PlaceMap({ + place, + width, + height, + monochrome, +}: { + place: Place + width: number + height: number + monochrome?: boolean +}) { + const osm = useRef(new OSM()); + + const centerLon = place.location?.longitude ?? 0; + const centerLat = place.location?.latitude ?? 0; + const highLon = place.viewport?.high?.longitude ?? 0; + const highLat = place.viewport?.high?.latitude ?? 0; + const lowLon = place.viewport?.low?.longitude ?? 0; + const lowLat = place.viewport?.low?.latitude ?? 0; + + const center = useMemo(() => + fromLonLat([centerLon, centerLat]) + , [centerLon, centerLat]); + + const extent = useMemo(() => + boundingExtent([ + fromLonLat([highLon, highLat]), + fromLonLat([lowLon, lowLat]), + ]) + , [highLon, highLat, lowLon, lowLat]); + + return ( +
+
+ + + + +
+
+ ); +}