From e81ad976593871b7bdc3cba46370249759bd6426 Mon Sep 17 00:00:00 2001 From: Michael Beckemeyer Date: Fri, 7 Feb 2025 11:30:52 +0100 Subject: [PATCH] Implement demo for client side routing based on wouter --- package.json | 2 - pnpm-lock.yaml | 239 +++---------- pnpm-workspace.yaml | 2 + src/samples/map-sample/ol-app/MapApp.tsx | 326 +++++++++++------- src/samples/map-sample/ol-app/app.ts | 30 +- .../map-sample/ol-app/build.config.mjs | 3 + src/samples/map-sample/ol-app/package.json | 9 +- src/samples/map-sample/ol-app/routes.ts | 31 ++ 8 files changed, 316 insertions(+), 326 deletions(-) create mode 100644 src/samples/map-sample/ol-app/routes.ts diff --git a/package.json b/package.json index de52ca1..dc8cd25 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "", "patches", "=======", - "react-select: patched to use composedPath() in event conditions; needed for web component integration (see https://github.com/JedWatson/react-select/issues/5824)", "@chakra-ui/menu;react-use-outside-click;hooks: patched to fix menus in shadow dom (see https://github.com/open-pioneer/trails-openlayers-base-packages/issues/184)", "", "peer dependency rules", @@ -64,7 +63,6 @@ "ignoreCves": [] }, "patchedDependencies": { - "react-select@5.8.0": "patches/react-select@5.8.0.patch", "@chakra-ui/hooks@2.4.3": "patches/@chakra-ui__hooks.patch" }, "peerDependencyRules": {} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 23f659f..91d8090 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,9 +15,6 @@ catalogs: '@emotion/styled': specifier: ^11.13.0 version: 11.13.0 - '@open-pioneer/basemap-switcher': - specifier: ^0.8.0 - version: 0.8.0 '@open-pioneer/build-package-cli': specifier: ^2.1.1 version: 2.1.1 @@ -33,9 +30,6 @@ catalogs: '@open-pioneer/coordinate-viewer': specifier: ^0.8.0 version: 0.8.0 - '@open-pioneer/geolocation': - specifier: ^0.8.0 - version: 0.8.0 '@open-pioneer/map': specifier: ^0.8.0 version: 0.8.0 @@ -45,15 +39,15 @@ catalogs: '@open-pioneer/map-ui-components': specifier: ^0.8.0 version: 0.8.0 - '@open-pioneer/measurement': - specifier: ^0.8.0 - version: 0.8.0 '@open-pioneer/notifier': specifier: ^2.4.0 version: 2.4.0 '@open-pioneer/overview-map': specifier: ^0.8.0 version: 0.8.0 + '@open-pioneer/reactivity': + specifier: ^2.4.0 + version: 2.4.0 '@open-pioneer/runtime': specifier: ^2.4.0 version: 2.4.0 @@ -195,6 +189,9 @@ catalogs: vitest: specifier: ^2.1.9 version: 2.1.9 + wouter: + specifier: ^3.5.1 + version: 3.5.1 overrides: semver@<7.5.2: '>=7.5.2' @@ -212,9 +209,6 @@ patchedDependencies: '@chakra-ui/hooks@2.4.3': hash: mayfbuoknaogevz43ogq74es4q path: patches/@chakra-ui__hooks.patch - react-select@5.8.0: - hash: dmr4eel47u7r4xswxh72mgmyuq - path: patches/react-select@5.8.0.patch importers: @@ -386,18 +380,12 @@ importers: '@emotion/styled': specifier: 'catalog:' version: 11.13.0(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react@18.3.1) - '@open-pioneer/basemap-switcher': - specifier: 'catalog:' - version: 0.8.0(@chakra-ui/react@2.10.4(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(framer-motion@11.3.31(@emotion/is-prop-valid@1.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/is-prop-valid@1.3.0)(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(typescript@5.6.3) '@open-pioneer/chakra-integration': specifier: 'catalog:' version: 2.4.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11) '@open-pioneer/coordinate-viewer': specifier: 'catalog:' version: 0.8.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) - '@open-pioneer/geolocation': - specifier: 'catalog:' - version: 0.8.0(@chakra-ui/react@2.10.4(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(framer-motion@11.3.31(@emotion/is-prop-valid@1.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) '@open-pioneer/map': specifier: 'catalog:' version: 0.8.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) @@ -407,15 +395,15 @@ importers: '@open-pioneer/map-ui-components': specifier: 'catalog:' version: 0.8.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11) - '@open-pioneer/measurement': - specifier: 'catalog:' - version: 0.8.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) '@open-pioneer/notifier': specifier: 'catalog:' version: 2.4.0(@chakra-ui/react@2.10.4(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(framer-motion@11.3.31(@emotion/is-prop-valid@1.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) '@open-pioneer/overview-map': specifier: 'catalog:' version: 0.8.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) + '@open-pioneer/reactivity': + specifier: 'catalog:' + version: 2.4.0 '@open-pioneer/runtime': specifier: 'catalog:' version: 2.4.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) @@ -443,6 +431,9 @@ importers: react-use: specifier: 'catalog:' version: 17.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + wouter: + specifier: 'catalog:' + version: 3.5.1(react@18.3.1) support/disabled-package: {} @@ -1038,15 +1029,6 @@ packages: resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@floating-ui/core@1.6.7': - resolution: {integrity: sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==} - - '@floating-ui/dom@1.6.10': - resolution: {integrity: sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==} - - '@floating-ui/utils@0.2.7': - resolution: {integrity: sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==} - '@formatjs/ecma402-abstract@2.2.4': resolution: {integrity: sha512-lFyiQDVvSbQOpU+WFd//ILolGj4UgA/qXrKeZxdV14uKiAUiPAtX6XAn7WBCRi7Mx6I7EybM9E5yYn4BIpZWYg==} @@ -1130,9 +1112,6 @@ packages: '@open-pioneer/base-theme@2.4.0': resolution: {integrity: sha512-MxvgHSW1nyw09DM46IDGzYspJphdcTlv8YwDuqxvApp5IoY4wm8LPTO7pQXxNLQ0houlffNBYgSxGGzMIqusRg==} - '@open-pioneer/basemap-switcher@0.8.0': - resolution: {integrity: sha512-5EM8F89iddoFstHRq1S6V62+WDK0s9ptgZtp3WHPzRqz/22QkIgq5gAMm14vNUMsQQ4gmsBtOCtsqhXBfR1MiQ==} - '@open-pioneer/build-common@2.0.5': resolution: {integrity: sha512-RtCVsPp6FrVTUgkWb7S2xO8CbpruY/M9i1JGDdqgyRGDPQjmZSZJQevS4a2aaucZSB3Klfa/xHee8xI82HKcbw==} engines: {node: '>= 18'} @@ -1172,9 +1151,6 @@ packages: '@open-pioneer/core@2.4.0': resolution: {integrity: sha512-Z8zAqyZT7qNldPmZj7s5uZA1Hy2UmQgdTvvwRcRnfr+M0WMHDQoPyLQX1gViuzrK6KqmkfNM9GsJ8ENO6EqSTg==} - '@open-pioneer/geolocation@0.8.0': - resolution: {integrity: sha512-9gAX1bvrrtcvi6YYqWnI6Vc5Fo6dtt9jUcXfd8XPwM50JoWyiolg4+GLx5v3L6KfEGYHflE0wv0IHNGi9n14hw==} - '@open-pioneer/http@2.4.0': resolution: {integrity: sha512-RSPRQrs41qYRakskxdrYlyFPUWZr+G83akiSNaikFZvSriibTXeKya2tPXm9MRuJa7e1xrMhIyFD4FQEWnouWw==} @@ -1187,9 +1163,6 @@ packages: '@open-pioneer/map@0.8.0': resolution: {integrity: sha512-wkxr0kvQ40/g6FeIN2sRpZWLos0QpbQVsWl/W6xIuOBhiWUqaYe76XxXJJ8BzU8qzkomjrs6ze6n+AEhjBa8Ww==} - '@open-pioneer/measurement@0.8.0': - resolution: {integrity: sha512-hUeeBynqsju9I5VcrTl6lUda6xvtg3SvDPYX1kvhXB8n7CVj3qSukQwNrfNhneLZUIy+AL2fQWzkJejA4gxAeg==} - '@open-pioneer/notifier@2.4.0': resolution: {integrity: sha512-6p8yI3Ai05rH5jc/OCfsYKGVftlbvO9JnEjxrDgnUeEyEr48XQzPSLrj/G/sbgi7AStUx4uEgTm8zYFf75/ngQ==} @@ -1725,9 +1698,6 @@ packages: '@types/react-dom@18.3.1': resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==} - '@types/react-transition-group@4.4.11': - resolution: {integrity: sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==} - '@types/react@18.3.11': resolution: {integrity: sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==} @@ -2020,14 +1990,6 @@ packages: resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==} engines: {node: '>=12'} - chakra-react-select@5.0.2: - resolution: {integrity: sha512-DI82ICGya/yu99Np8Uk8rW14o4NIt45i4qHDm/h0eRFVTHsRJqE+My99A9cPGJ72V5tM/WK1EeWxYUxWxhzxkA==} - peerDependencies: - '@chakra-ui/react': 2.x - '@emotion/react': ^11.8.1 - react: ^18.0.0 - react-dom: ^18.0.0 - chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -2245,9 +2207,6 @@ packages: dom-accessibility-api@0.6.3: resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - dom-helpers@5.2.1: - resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} - earcut@3.0.0: resolution: {integrity: sha512-41Fs7Q/PLq1SDbqjsgcY7GA42T0jvaCNGXgGtsNdvg+Yv8eIu06bxv4/PoREkZ9nMDNwnUSG9OFB9+yv8eKhDg==} @@ -3107,9 +3066,6 @@ packages: mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} - memoize-one@6.0.0: - resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} - merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -3177,6 +3133,9 @@ packages: resolution: {integrity: sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==} engines: {node: '>=16 || 14 >=14.17'} + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + mlly@1.4.2: resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==} @@ -3483,12 +3442,6 @@ packages: '@types/react': optional: true - react-select@5.8.0: - resolution: {integrity: sha512-TfjLDo58XrhP6VG5M/Mi56Us0Yt8X7xD6cDybC7yoRMUNm7BGO7qk8J0TLQOua/prb8vUOtsfnXZwfm30HGsAA==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-style-singleton@2.2.1: resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} engines: {node: '>=10'} @@ -3499,12 +3452,6 @@ packages: '@types/react': optional: true - react-transition-group@4.4.5: - resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} - peerDependencies: - react: '>=16.6.0' - react-dom: '>=16.6.0' - react-universal-interface@0.6.2: resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==} peerDependencies: @@ -3550,6 +3497,10 @@ packages: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} engines: {node: '>= 0.4'} + regexparam@3.0.0: + resolution: {integrity: sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==} + engines: {node: '>=8'} + resize-observer-polyfill@1.5.1: resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} @@ -4033,15 +3984,6 @@ packages: '@types/react': optional: true - use-isomorphic-layout-effect@1.1.2: - resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - use-sidecar@1.1.2: resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} engines: {node: '>=10'} @@ -4052,6 +3994,11 @@ packages: '@types/react': optional: true + use-sync-external-store@1.4.0: + resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -4197,6 +4144,11 @@ packages: wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + wouter@3.5.1: + resolution: {integrity: sha512-CCmd9qOJnQBO8Ja6kUuTr3/MvS8t+YCDQqlvVcuu8sG9L+FxP/Dv75s1UfjdSO0ahvewo+KBpMN+yTL1Q0BrtA==} + peerDependencies: + react: '>=16.8.0' + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -4710,17 +4662,6 @@ snapshots: '@eslint/js@8.57.0': {} - '@floating-ui/core@1.6.7': - dependencies: - '@floating-ui/utils': 0.2.7 - - '@floating-ui/dom@1.6.10': - dependencies: - '@floating-ui/core': 1.6.7 - '@floating-ui/utils': 0.2.7 - - '@floating-ui/utils@0.2.7': {} - '@formatjs/ecma402-abstract@2.2.4': dependencies: '@formatjs/fast-memoize': 2.2.3 @@ -4829,26 +4770,6 @@ snapshots: - '@emotion/is-prop-valid' - '@types/react' - '@open-pioneer/basemap-switcher@0.8.0(@chakra-ui/react@2.10.4(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(framer-motion@11.3.31(@emotion/is-prop-valid@1.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/is-prop-valid@1.3.0)(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(typescript@5.6.3)': - dependencies: - '@conterra/reactivity-core': 0.4.3 - '@open-pioneer/chakra-integration': 2.4.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11) - '@open-pioneer/map': 0.8.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) - '@open-pioneer/react-utils': 2.4.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11) - '@open-pioneer/reactivity': 2.4.0 - '@open-pioneer/runtime': 2.4.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) - chakra-react-select: 5.0.2(@chakra-ui/react@2.10.4(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(framer-motion@11.3.31(@emotion/is-prop-valid@1.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - ol: 10.3.1 - react: 18.3.1 - react-icons: 5.3.0(react@18.3.1) - transitivePeerDependencies: - - '@chakra-ui/react' - - '@emotion/is-prop-valid' - - '@emotion/react' - - '@types/react' - - react-dom - - typescript - '@open-pioneer/build-common@2.0.5': dependencies: semver: 7.6.3 @@ -4934,26 +4855,6 @@ snapshots: '@open-pioneer/core@2.4.0': {} - '@open-pioneer/geolocation@0.8.0(@chakra-ui/react@2.10.4(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(framer-motion@11.3.31(@emotion/is-prop-valid@1.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3)': - dependencies: - '@conterra/reactivity-core': 0.4.3 - '@open-pioneer/chakra-integration': 2.4.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11) - '@open-pioneer/core': 2.4.0 - '@open-pioneer/map': 0.8.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) - '@open-pioneer/map-ui-components': 0.8.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11) - '@open-pioneer/notifier': 2.4.0(@chakra-ui/react@2.10.4(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(framer-motion@11.3.31(@emotion/is-prop-valid@1.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) - '@open-pioneer/react-utils': 2.4.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11) - '@open-pioneer/reactivity': 2.4.0 - '@open-pioneer/runtime': 2.4.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) - ol: 10.3.1 - react: 18.3.1 - react-icons: 5.3.0(react@18.3.1) - transitivePeerDependencies: - - '@chakra-ui/react' - - '@emotion/is-prop-valid' - - '@types/react' - - typescript - '@open-pioneer/http@2.4.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3)': dependencies: '@open-pioneer/core': 2.4.0 @@ -5011,21 +4912,6 @@ snapshots: - '@types/react' - typescript - '@open-pioneer/measurement@0.8.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3)': - dependencies: - '@open-pioneer/chakra-integration': 2.4.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11) - '@open-pioneer/core': 2.4.0 - '@open-pioneer/map': 0.8.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) - '@open-pioneer/react-utils': 2.4.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11) - '@open-pioneer/runtime': 2.4.0(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3) - classnames: 2.5.1 - ol: 10.3.1 - react: 18.3.1 - transitivePeerDependencies: - - '@emotion/is-prop-valid' - - '@types/react' - - typescript - '@open-pioneer/notifier@2.4.0(@chakra-ui/react@2.10.4(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(framer-motion@11.3.31(@emotion/is-prop-valid@1.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/is-prop-valid@1.3.0)(@types/react@18.3.11)(typescript@5.6.3)': dependencies: '@chakra-ui/icons': 2.2.4(@chakra-ui/react@2.10.4(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(framer-motion@11.3.31(@emotion/is-prop-valid@1.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) @@ -5646,10 +5532,6 @@ snapshots: dependencies: '@types/react': 18.3.11 - '@types/react-transition-group@4.4.11': - dependencies: - '@types/react': 18.3.11 - '@types/react@18.3.11': dependencies: '@types/prop-types': 15.7.12 @@ -6003,16 +5885,6 @@ snapshots: loupe: 3.1.1 pathval: 2.0.0 - chakra-react-select@5.0.2(@chakra-ui/react@2.10.4(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(framer-motion@11.3.31(@emotion/is-prop-valid@1.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@chakra-ui/react': 2.10.4(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(react@18.3.1))(@types/react@18.3.11)(framer-motion@11.3.31(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@emotion/react': 11.13.3(@types/react@18.3.11)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-select: 5.8.0(patch_hash=dmr4eel47u7r4xswxh72mgmyuq)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - transitivePeerDependencies: - - '@types/react' - chalk@2.4.2: dependencies: ansi-styles: 3.2.1 @@ -6209,11 +6081,6 @@ snapshots: dom-accessibility-api@0.6.3: {} - dom-helpers@5.2.1: - dependencies: - '@babel/runtime': 7.25.6 - csstype: 3.1.3 - earcut@3.0.0: {} eastasianwidth@0.2.0: {} @@ -7320,8 +7187,6 @@ snapshots: mdurl@2.0.0: {} - memoize-one@6.0.0: {} - merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -7376,6 +7241,8 @@ snapshots: minipass@6.0.2: {} + mitt@3.0.1: {} + mlly@1.4.2: dependencies: acorn: 8.11.2 @@ -7681,22 +7548,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.11 - react-select@5.8.0(patch_hash=dmr4eel47u7r4xswxh72mgmyuq)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.25.6 - '@emotion/cache': 11.13.1 - '@emotion/react': 11.13.3(@types/react@18.3.11)(react@18.3.1) - '@floating-ui/dom': 1.6.10 - '@types/react-transition-group': 4.4.11 - memoize-one: 6.0.0 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - use-isomorphic-layout-effect: 1.1.2(@types/react@18.3.11)(react@18.3.1) - transitivePeerDependencies: - - '@types/react' - react-style-singleton@2.2.1(@types/react@18.3.11)(react@18.3.1): dependencies: get-nonce: 1.0.1 @@ -7706,15 +7557,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.11 - react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.25.6 - dom-helpers: 5.2.1 - loose-envify: 1.4.0 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-universal-interface@0.6.2(react@18.3.1)(tslib@2.7.0): dependencies: react: 18.3.1 @@ -7780,6 +7622,8 @@ snapshots: es-errors: 1.3.0 set-function-name: 2.0.2 + regexparam@3.0.0: {} + resize-observer-polyfill@1.5.1: {} resolve-from@4.0.0: {} @@ -8307,12 +8151,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.11 - use-isomorphic-layout-effect@1.1.2(@types/react@18.3.11)(react@18.3.1): - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.11 - use-sidecar@1.1.2(@types/react@18.3.11)(react@18.3.1): dependencies: detect-node-es: 1.1.0 @@ -8321,6 +8159,10 @@ snapshots: optionalDependencies: '@types/react': 18.3.11 + use-sync-external-store@1.4.0(react@18.3.1): + dependencies: + react: 18.3.1 + util-deprecate@1.0.2: {} uuid@10.0.0: {} @@ -8484,6 +8326,13 @@ snapshots: wordwrap@1.0.0: {} + wouter@3.5.1(react@18.3.1): + dependencies: + mitt: 3.0.1 + react: 18.3.1 + regexparam: 3.0.0 + use-sync-external-store: 1.4.0(react@18.3.1) + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 1414b02..770a030 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -36,6 +36,7 @@ catalog: "@open-pioneer/integration": *core_packages_version "@open-pioneer/notifier": *core_packages_version "@open-pioneer/react-utils": *core_packages_version + "@open-pioneer/reactivity": *core_packages_version "@open-pioneer/runtime-react-support": *core_packages_version "@open-pioneer/runtime": *core_packages_version "@open-pioneer/test-utils": *core_packages_version @@ -96,3 +97,4 @@ catalog: vite-plugin-eslint: ^1.8.1 vite: ^5.4.14 vitest: ^2.1.9 + wouter: ^3.5.1 diff --git a/src/samples/map-sample/ol-app/MapApp.tsx b/src/samples/map-sample/ol-app/MapApp.tsx index 646b231..68b942b 100644 --- a/src/samples/map-sample/ol-app/MapApp.tsx +++ b/src/samples/map-sample/ol-app/MapApp.tsx @@ -1,45 +1,56 @@ // SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer) // SPDX-License-Identifier: Apache-2.0 -import { Box, Divider, Flex, FormControl, FormLabel, Text } from "@open-pioneer/chakra-integration"; -import { DefaultMapProvider, MapAnchor, MapContainer } from "@open-pioneer/map"; -import { ScaleBar } from "@open-pioneer/scale-bar"; -import { InitialExtent, ZoomIn, ZoomOut } from "@open-pioneer/map-navigation"; -import { useIntl } from "open-pioneer:react-hooks"; +import { + Box, + chakra, + Drawer, + DrawerBody, + DrawerCloseButton, + DrawerContent, + DrawerFooter, + DrawerHeader, + Flex, + HStack, + Link, + List, + ListItem +} from "@open-pioneer/chakra-integration"; import { CoordinateViewer } from "@open-pioneer/coordinate-viewer"; +import { + BaseFeature, + DefaultMapProvider, + MapAnchor, + MapContainer, + MapModel, + useMapModel +} from "@open-pioneer/map"; +import { InitialExtent, ZoomIn, ZoomOut } from "@open-pioneer/map-navigation"; +import { NotificationService, Notifier } from "@open-pioneer/notifier"; import { SectionHeading, TitledSection } from "@open-pioneer/react-utils"; -import { ToolButton } from "@open-pioneer/map-ui-components"; +import { useReactiveSnapshot } from "@open-pioneer/reactivity"; +import { ScaleBar } from "@open-pioneer/scale-bar"; import { ScaleViewer } from "@open-pioneer/scale-viewer"; -import { Geolocation } from "@open-pioneer/geolocation"; -import { Notifier } from "@open-pioneer/notifier"; -import { OverviewMap } from "@open-pioneer/overview-map"; +import { Point, Polygon } from "ol/geom"; +import { useIntl, useService } from "open-pioneer:react-hooks"; +import { ReactNode, useEffect, useMemo } from "react"; +import { Link as WouterLink, Router, useLocation } from "wouter"; +import { getFeatureUrl, useCurrentFeatureId, useRouterOptions } from "./routes"; import { MAP_ID } from "./services"; -import { useId, useMemo, useState } from "react"; -import TileLayer from "ol/layer/Tile"; -import { Measurement } from "@open-pioneer/measurement"; -import OSM from "ol/source/OSM"; -import { PiRulerLight } from "react-icons/pi"; -import { BasemapSwitcher } from "@open-pioneer/basemap-switcher"; export function MapApp() { const intl = useIntl(); - const measurementTitleId = useId(); + const { map } = useMapModel(MAP_ID); - const [measurementIsActive, setMeasurementIsActive] = useState(false); - function toggleMeasurement() { - setMeasurementIsActive(!measurementIsActive); - } - - const overviewMapLayer = useMemo( - () => - new TileLayer({ - source: new OSM() - }), - [] - ); + const linkIds = ["1", "2", "123", undefined]; + const links = linkIds.map((id) => ( + + {id ? `Select ${id}` : "Reset"} + + )); return ( - + - Open Pioneer Trails - Map Sample + Open Pioneer Trails - Map with routing } > - - - - - {measurementIsActive && ( - - - - {intl.formatMessage({ - id: "measurementTitle" - })} - - } - > - - - - - )} - - - - - - - - - {intl.formatMessage({ id: "basemapLabel" })} - - - - - - - - - } - isActive={measurementIsActive} - onClick={toggleMeasurement} - /> - - - - - - - - - - - - - - + + + {links} + + {map && } + ); } + +const DRAWER_WIDTH = 400; // pixels + +function AppContent(props: { map: MapModel }) { + const { map } = props; + const intl = useIntl(); + const [, navigate] = useLocation(); + const drawerContent = useFeatureSelection(map); + + return ( + + {drawerContent && ( + { + navigate(getFeatureUrl(undefined)); + }} + placement="left" + variant={"clickThrough"} + closeOnOverlayClick={false} + closeOnEsc={false} + blockScrollOnMount={false} + > + {drawerContent} + + )} + + + + + + + + + + + + + + + + + + ); +} + +/** + * Handles feature selection logic. + * We can select (at most) one feature at a time via URL state. + * + * If the feature is found, it is highlighted in the map and the content for the drawer is returned from this hook. + * If the feature cannot be found, a notification is emitted (and no drawer content is returned). + */ +function useFeatureSelection(map: MapModel): ReactNode { + const selectedFeatureId = useCurrentFeatureId(); + const selectedFeature = selectedFeatureId != null ? FEATURES[selectedFeatureId] : undefined; + const notifier = useService("notifier.NotificationService"); + const mapIsReady = useReactiveSnapshot(() => !!map.container, [map]); + + // Emit a notification if the feature cannot be found. + useEffect(() => { + if (selectedFeatureId && !selectedFeature) { + notifier.warning(`Feature '${selectedFeatureId}' not found`); + } + }, [notifier, selectedFeature, selectedFeatureId]); + + // Highlight the selected feature. + useEffect(() => { + if (!selectedFeature || !mapIsReady) { + return; + } + + const highlight = map.highlightAndZoom([selectedFeature], { + viewPadding: { + bottom: 50, + left: 50, + right: 50, + top: 50 + } + }); + return () => highlight.destroy(); + }, [map, mapIsReady, selectedFeature]); + + const drawerContent = useMemo(() => { + if (!selectedFeature) { + return undefined; + } + + const title = `Feature ${selectedFeature.id}`; + const properties = Object.entries(selectedFeature.properties ?? {}).map(([key, value]) => ( + + {key}: {String(value)} + + )); + + return ( + + + {title} + + + Properties: + {properties.length > 0 ? {properties} : "No properties"} + + + + + ); + }, [selectedFeature]); + + return drawerContent; +} + +const FEATURES: Record = { + "1": { + id: "1", + geometry: new Polygon([ + [ + [851728.251553, 6788384.425292], + [851518.049725, 6788651.954891], + [852182.096409, 6788881.265976], + [851728.251553, 6788384.425292] + ] + ]), + properties: { + name: "Feature 1", + description: "This is the first feature", + area: 100 + } + }, + "2": { + id: "2", + geometry: new Point([852011.307424, 6788511.322702]), + properties: { + name: "Feature 2", + description: "This is the second feature", + area: 0 + } + } +}; diff --git a/src/samples/map-sample/ol-app/app.ts b/src/samples/map-sample/ol-app/app.ts index 8c12cf6..a2e3506 100644 --- a/src/samples/map-sample/ol-app/app.ts +++ b/src/samples/map-sample/ol-app/app.ts @@ -1,9 +1,37 @@ // SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer) // SPDX-License-Identifier: Apache-2.0 import { createCustomElement } from "@open-pioneer/runtime"; -import { theme } from "@open-pioneer/theme"; +import { theme as baseTheme } from "@open-pioneer/theme"; import * as appMetadata from "open-pioneer:app"; import { MapApp } from "./MapApp"; +import { extendTheme } from "@open-pioneer/chakra-integration"; + +const theme = extendTheme( + { + components: { + // See https://github.com/chakra-ui/chakra-ui/issues/2893#issuecomment-1540895564 + // Drawer variant to allow pointer events to the underlying content + Drawer: { + variants: { + clickThrough: { + overlay: { + pointerEvents: "none", + background: "transparent" + }, + dialogContainer: { + pointerEvents: "none", + background: "transparent" + }, + dialog: { + pointerEvents: "auto" + } + } + } + } + } + }, + baseTheme +); const element = createCustomElement({ component: MapApp, diff --git a/src/samples/map-sample/ol-app/build.config.mjs b/src/samples/map-sample/ol-app/build.config.mjs index 5664fd0..94f815f 100644 --- a/src/samples/map-sample/ol-app/build.config.mjs +++ b/src/samples/map-sample/ol-app/build.config.mjs @@ -9,5 +9,8 @@ export default defineBuildConfig({ MainMapProvider: { provides: ["map.MapConfigProvider"] } + }, + ui: { + references: ["notifier.NotificationService"] } }); diff --git a/src/samples/map-sample/ol-app/package.json b/src/samples/map-sample/ol-app/package.json index e717b84..84163db 100644 --- a/src/samples/map-sample/ol-app/package.json +++ b/src/samples/map-sample/ol-app/package.json @@ -5,16 +5,14 @@ "@chakra-ui/icons": "catalog:", "@emotion/react": "catalog:", "@emotion/styled": "catalog:", - "@open-pioneer/basemap-switcher": "catalog:", "@open-pioneer/chakra-integration": "catalog:", "@open-pioneer/coordinate-viewer": "catalog:", - "@open-pioneer/geolocation": "catalog:", - "@open-pioneer/map": "catalog:", "@open-pioneer/map-navigation": "catalog:", "@open-pioneer/map-ui-components": "catalog:", - "@open-pioneer/measurement": "catalog:", + "@open-pioneer/map": "catalog:", "@open-pioneer/notifier": "catalog:", "@open-pioneer/overview-map": "catalog:", + "@open-pioneer/reactivity": "catalog:", "@open-pioneer/runtime": "catalog:", "@open-pioneer/scale-bar": "catalog:", "@open-pioneer/scale-viewer": "catalog:", @@ -23,6 +21,7 @@ "react": "catalog:", "react-dom": "catalog:", "react-icons": "catalog:", - "react-use": "catalog:" + "react-use": "catalog:", + "wouter": "catalog:" } } diff --git a/src/samples/map-sample/ol-app/routes.ts b/src/samples/map-sample/ol-app/routes.ts new file mode 100644 index 0000000..764403f --- /dev/null +++ b/src/samples/map-sample/ol-app/routes.ts @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer) +// SPDX-License-Identifier: Apache-2.0 +import { RouterOptions, useRoute } from "wouter"; +import { useHashLocation } from "wouter/use-hash-location"; + +const SELECTED_FEATURE_PATTERN = "/feature/:featureId"; + +/** Configuration for the main `` parent. */ +export function useRouterOptions(): RouterOptions { + return { + // Client side only routing using `#/foo/bar?baz=123` urls + hook: useHashLocation + }; +} + +/** Returns the ID of the currently selected feature from the current URL, or `undefined`. */ +export function useCurrentFeatureId(): string | undefined { + const [match, params] = useRoute(SELECTED_FEATURE_PATTERN); + if (!match) { + return undefined; + } + return params.featureId; +} + +/** Generates a URL that points to the given feature id. */ +export function getFeatureUrl(featureId: string | undefined) { + if (!featureId) { + return "/"; + } + return `/feature/${featureId}`; +}