diff --git a/.github/workflows/percy-snapshots.yml b/.github/workflows/percy-snapshots.yml index 0d43eed1f..015c109db 100644 --- a/.github/workflows/percy-snapshots.yml +++ b/.github/workflows/percy-snapshots.yml @@ -13,3 +13,4 @@ jobs: percy_script: npx percy storybook ./storybook-static secrets: PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }} + MAPBOX_API_KEY: ${{ secrets.MAPBOX_API_KEY }} diff --git a/.github/workflows/run-linting.yml b/.github/workflows/run-linting.yml index 30401cb39..afca2cd51 100644 --- a/.github/workflows/run-linting.yml +++ b/.github/workflows/run-linting.yml @@ -2,7 +2,7 @@ name: Run Linter on: pull_request: - branches: [main, develop] + branches: [main, develop, feature/*] jobs: linting: diff --git a/.storybook/main.js b/.storybook/main.js index 6e9b79227..446e5af58 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -33,5 +33,9 @@ module.exports = { config.resolve.alias['./SearchCore'] = require.resolve('../tests/__fixtures__/core/SearchCore.ts'); config.resolve.alias['../utils/location-operations'] = require.resolve('../tests/__fixtures__/utils/location-operations.ts'); return config; - } + }, + env: (config) => ({ + ...config, + REACT_APP_MAPBOX_API_KEY: process.env.MAPBOX_API_KEY || process.env.REACT_APP_MAPBOX_API_KEY, + }), }; \ No newline at end of file diff --git a/.storybook/preview.js b/.storybook/preview.js index 80235a413..9bf99b604 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,4 +1,5 @@ import './index.css'; +import 'mapbox-gl/dist/mapbox-gl.css'; import { SearchCoreDecorator } from '../tests/__fixtures__/core/SearchCore'; import { runOnly } from './wcagConfig'; @@ -22,6 +23,7 @@ export const parameters = { 'SearchBar', 'UniversalResults', 'VerticalResults', + 'MapboxMap', 'DirectAnswer', 'FilterSearch', 'StaticFilters', @@ -42,4 +44,4 @@ export const parameters = { }; // Add the decorator to all stories -export const decorators = [SearchCoreDecorator]; \ No newline at end of file +export const decorators = [SearchCoreDecorator]; diff --git a/docs/search-ui-react.pincomponent.md b/docs/search-ui-react.pincomponent.md index 70d8da273..719f022bf 100644 --- a/docs/search-ui-react.pincomponent.md +++ b/docs/search-ui-react.pincomponent.md @@ -10,7 +10,8 @@ A functional component that can be used to render a custom marker on the map. ```typescript export declare type PinComponent = (props: { - result?: Result; - index?: number; + index: number; + mapbox: Map; + result: Result; }) => JSX.Element; ``` diff --git a/etc/search-ui-react.api.md b/etc/search-ui-react.api.md index 373790e53..64b98e3f2 100644 --- a/etc/search-ui-react.api.md +++ b/etc/search-ui-react.api.md @@ -13,6 +13,7 @@ import { DirectAnswer as DirectAnswer_2 } from '@yext/search-headless-react'; import { HighlightedValue } from '@yext/search-headless-react'; import { LngLat } from 'mapbox-gl'; import { LngLatBounds } from 'mapbox-gl'; +import { Map as Map_2 } from 'mapbox-gl'; import { MapboxOptions } from 'mapbox-gl'; import { Matcher } from '@yext/search-headless-react'; import { NumberRangeValue } from '@yext/search-headless-react'; @@ -419,8 +420,9 @@ export interface PaginationProps { // @public export type PinComponent = (props: { - result?: Result; - index?: number; + index: number; + mapbox: Map_2; + result: Result; }) => JSX.Element; // @public diff --git a/sample.env b/sample.env new file mode 100644 index 000000000..5ca147605 --- /dev/null +++ b/sample.env @@ -0,0 +1 @@ +REACT_APP_MAPBOX_API_KEY=[[Your Mapbox API Key]] \ No newline at end of file diff --git a/src/components/MapboxMap.tsx b/src/components/MapboxMap.tsx index 974fe18d7..94c0b04c2 100644 --- a/src/components/MapboxMap.tsx +++ b/src/components/MapboxMap.tsx @@ -9,7 +9,11 @@ import ReactDOM from 'react-dom'; * * @public */ -export type PinComponent = (props: { result?: Result, index?: number }) => JSX.Element; +export type PinComponent = (props: { + index: number, + mapbox: Map, + result: Result +}) => JSX.Element; /** * A function use to derive a result's coordinate. @@ -132,7 +136,11 @@ export function MapboxMap({ const el = document.createElement('div'); const markerOptions: MarkerOptions = {}; if (PinComponent) { - ReactDOM.render(, el); + ReactDOM.render(, el); markerOptions.element = el; } const marker = new Marker(markerOptions) diff --git a/test-site/package-lock.json b/test-site/package-lock.json index e53f540e1..aaf42d66d 100644 --- a/test-site/package-lock.json +++ b/test-site/package-lock.json @@ -10,12 +10,14 @@ "dependencies": { "@tailwindcss/forms": "^0.5.0", "@yext/search-ui-react": "file:..", + "mapbox-gl": "^2.10.0", "react": "file:../node_modules/react", "react-dom": "file:../node_modules/react-dom", "react-router-dom": "^6.2.2", "uuid": "^9.0.0" }, "devDependencies": { + "@types/mapbox-gl": "^2.7.6", "@types/node": "^16.11.26", "@types/react": "^17.0.42", "@types/react-dom": "^17.0.14", @@ -34050,6 +34052,67 @@ "dev": true, "license": "MIT" }, + "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/geojson-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@mapbox/geojson-types/-/geojson-types-1.0.2.tgz", + "integrity": "sha512-e9EBqHHv3EORHrSfbR9DqecPNn+AmuAoQxV6aL8Xu30bJMJR1o8PZLZzpk1Wq7/NfCbuhmakHTPYRhoqLsXRnw==" + }, + "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/mapbox-gl-supported": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-2.0.1.tgz", + "integrity": "sha512-HP6XvfNIzfoMVfyGjBckjiAOQK9WfX0ywdLubuPMPv+Vqf5fj0uCbgBQYpiqcWZT6cbyyRnTSXDheT1ugvF6UQ==" + }, + "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.5", + "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.0.5.tgz", + "integrity": "sha512-OhXt2lS//WpLdkqrzo/KwB7SRD8AiNTFFzuo9n14IBupzIMa67yGItcK7I2W9D8Ghpa4T04Sw9FWsKCJG50Bxw==" + }, + "node_modules/@mapbox/unitbezier": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.0.tgz", + "integrity": "sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==" + }, + "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/@nodelib/fs.scandir": { "version": "2.1.5", "license": "MIT", @@ -34585,6 +34648,12 @@ "@types/range-parser": "*" } }, + "node_modules/@types/geojson": { + "version": "7946.0.10", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz", + "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==", + "dev": true + }, "node_modules/@types/graceful-fs": { "version": "4.1.5", "dev": true, @@ -34632,6 +34701,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/mapbox-gl": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/@types/mapbox-gl/-/mapbox-gl-2.7.6.tgz", + "integrity": "sha512-EPIfNO7WApXaFM7DuJBj+kpXmqffqJHMJ3Q9gbV/nNL23XHR0PC5CCDYbAFa4tKErm0xJd9C5kPLF6KvA/cRcA==", + "dev": true, + "dependencies": { + "@types/geojson": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.2", "dev": true, @@ -36390,6 +36468,11 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/csscolorparser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz", + "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==" + }, "node_modules/cssdb": { "version": "6.5.0", "dev": true, @@ -36876,6 +36959,11 @@ "dev": true, "license": "MIT" }, + "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", "dev": true, @@ -38060,6 +38148,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", "dev": true, @@ -38096,7 +38189,6 @@ }, "node_modules/get-stream": { "version": "6.0.1", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -38120,6 +38212,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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.2.0", "dev": true, @@ -38221,6 +38318,11 @@ "dev": true, "license": "ISC" }, + "node_modules/grid-index": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.1.0.tgz", + "integrity": "sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==" + }, "node_modules/gzip-size": { "version": "6.0.0", "dev": true, @@ -38601,6 +38703,25 @@ "node": ">=4" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.2.0", "dev": true, @@ -40997,6 +41118,11 @@ "node": ">=0.10.0" } }, + "node_modules/kdbush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz", + "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==" + }, "node_modules/kind-of": { "version": "6.0.3", "dev": true, @@ -41176,6 +41302,35 @@ "tmpl": "1.0.5" } }, + "node_modules/mapbox-gl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-2.10.0.tgz", + "integrity": "sha512-ZAlCe55LXlbg60l15okSBs70NQAPLw3yRO3SSJMTB1uU7uj2QQbLCQPy1Ds+3B4wlaa5W3ewv8FNOZPQOoSSPA==", + "dependencies": { + "@mapbox/geojson-rewind": "^0.5.1", + "@mapbox/geojson-types": "^1.0.2", + "@mapbox/jsonlint-lines-primitives": "^2.0.2", + "@mapbox/mapbox-gl-supported": "^2.0.1", + "@mapbox/point-geometry": "^0.1.0", + "@mapbox/tiny-sdf": "^2.0.5", + "@mapbox/unitbezier": "^0.0.0", + "@mapbox/vector-tile": "^1.3.1", + "@mapbox/whoots-js": "^3.1.0", + "csscolorparser": "~1.0.3", + "earcut": "^2.2.4", + "geojson-vt": "^3.2.1", + "gl-matrix": "^3.4.3", + "grid-index": "^1.1.0", + "murmurhash-js": "^1.0.0", + "pbf": "^3.2.1", + "potpack": "^1.0.2", + "quickselect": "^2.0.0", + "rw": "^1.3.3", + "supercluster": "^7.1.4", + "tinyqueue": "^2.0.3", + "vt-pbf": "^3.1.3" + } + }, "node_modules/mdn-data": { "version": "2.0.4", "dev": true, @@ -41376,6 +41531,11 @@ "multicast-dns": "cli.js" } }, + "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/nanoid": { "version": "3.3.2", "license": "MIT", @@ -41797,6 +41957,18 @@ "node": ">=8" } }, + "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/performance-now": { "version": "2.1.0", "dev": true, @@ -43103,6 +43275,11 @@ "version": "4.2.0", "license": "MIT" }, + "node_modules/potpack": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz", + "integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==" + }, "node_modules/prelude-ls": { "version": "1.2.1", "dev": true, @@ -43185,6 +43362,11 @@ "node": ">= 6" } }, + "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-addr": { "version": "2.0.7", "dev": true, @@ -43266,6 +43448,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/quickselect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", + "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" + }, "node_modules/raf": { "version": "3.4.1", "dev": true, @@ -43859,6 +44046,14 @@ "node": ">=4" } }, + "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/resolve-url-loader": { "version": "4.0.0", "dev": true, @@ -44042,6 +44237,11 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "node_modules/safe-buffer": { "version": "5.1.2", "dev": true, @@ -44684,6 +44884,14 @@ "postcss": "^8.2.15" } }, + "node_modules/supercluster": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.1.5.tgz", + "integrity": "sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==", + "dependencies": { + "kdbush": "^3.0.0" + } + }, "node_modules/supports-color": { "version": "5.5.0", "license": "MIT", @@ -45025,6 +45233,11 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyqueue": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", + "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==" + }, "node_modules/tmpl": { "version": "1.0.5", "dev": true, @@ -45326,6 +45539,16 @@ "node": ">= 0.8" } }, + "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/w3c-hr-time": { "version": "1.0.2", "dev": true, @@ -47779,6 +48002,58 @@ "version": "2.0.3", "dev": true }, + "@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/geojson-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@mapbox/geojson-types/-/geojson-types-1.0.2.tgz", + "integrity": "sha512-e9EBqHHv3EORHrSfbR9DqecPNn+AmuAoQxV6aL8Xu30bJMJR1o8PZLZzpk1Wq7/NfCbuhmakHTPYRhoqLsXRnw==" + }, + "@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/mapbox-gl-supported": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-2.0.1.tgz", + "integrity": "sha512-HP6XvfNIzfoMVfyGjBckjiAOQK9WfX0ywdLubuPMPv+Vqf5fj0uCbgBQYpiqcWZT6cbyyRnTSXDheT1ugvF6UQ==" + }, + "@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.5", + "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.0.5.tgz", + "integrity": "sha512-OhXt2lS//WpLdkqrzo/KwB7SRD8AiNTFFzuo9n14IBupzIMa67yGItcK7I2W9D8Ghpa4T04Sw9FWsKCJG50Bxw==" + }, + "@mapbox/unitbezier": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.0.tgz", + "integrity": "sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==" + }, + "@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==" + }, "@nodelib/fs.scandir": { "version": "2.1.5", "requires": { @@ -48095,6 +48370,12 @@ "@types/range-parser": "*" } }, + "@types/geojson": { + "version": "7946.0.10", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz", + "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==", + "dev": true + }, "@types/graceful-fs": { "version": "4.1.5", "dev": true, @@ -48135,6 +48416,15 @@ "version": "7.0.11", "dev": true }, + "@types/mapbox-gl": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/@types/mapbox-gl/-/mapbox-gl-2.7.6.tgz", + "integrity": "sha512-EPIfNO7WApXaFM7DuJBj+kpXmqffqJHMJ3Q9gbV/nNL23XHR0PC5CCDYbAFa4tKErm0xJd9C5kPLF6KvA/cRcA==", + "dev": true, + "requires": { + "@types/geojson": "*" + } + }, "@types/mime": { "version": "1.3.2", "dev": true @@ -70157,6 +70447,11 @@ "version": "3.4.2", "dev": true }, + "csscolorparser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz", + "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==" + }, "cssdb": { "version": "6.5.0", "dev": true @@ -70481,6 +70776,11 @@ "version": "0.1.2", "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", "dev": true @@ -71242,6 +71542,11 @@ "version": "1.0.0-beta.2", "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", "dev": true @@ -71264,8 +71569,7 @@ "dev": true }, "get-stream": { - "version": "6.0.1", - "dev": true + "version": "6.0.1" }, "get-symbol-description": { "version": "1.0.0", @@ -71275,6 +71579,11 @@ "get-intrinsic": "^1.1.1" } }, + "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.2.0", "dev": true, @@ -71342,6 +71651,11 @@ "version": "4.2.10", "dev": true }, + "grid-index": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.1.0.tgz", + "integrity": "sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==" + }, "gzip-size": { "version": "6.0.0", "dev": true, @@ -71582,6 +71896,11 @@ "harmony-reflect": "^1.4.6" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "ignore": { "version": "5.2.0", "dev": true @@ -73082,6 +73401,11 @@ "version": "5.0.0", "dev": true }, + "kdbush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz", + "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==" + }, "kind-of": { "version": "6.0.3", "dev": true @@ -73200,6 +73524,35 @@ "tmpl": "1.0.5" } }, + "mapbox-gl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-2.10.0.tgz", + "integrity": "sha512-ZAlCe55LXlbg60l15okSBs70NQAPLw3yRO3SSJMTB1uU7uj2QQbLCQPy1Ds+3B4wlaa5W3ewv8FNOZPQOoSSPA==", + "requires": { + "@mapbox/geojson-rewind": "^0.5.1", + "@mapbox/geojson-types": "^1.0.2", + "@mapbox/jsonlint-lines-primitives": "^2.0.2", + "@mapbox/mapbox-gl-supported": "^2.0.1", + "@mapbox/point-geometry": "^0.1.0", + "@mapbox/tiny-sdf": "^2.0.5", + "@mapbox/unitbezier": "^0.0.0", + "@mapbox/vector-tile": "^1.3.1", + "@mapbox/whoots-js": "^3.1.0", + "csscolorparser": "~1.0.3", + "earcut": "^2.2.4", + "geojson-vt": "^3.2.1", + "gl-matrix": "^3.4.3", + "grid-index": "^1.1.0", + "murmurhash-js": "^1.0.0", + "pbf": "^3.2.1", + "potpack": "^1.0.2", + "quickselect": "^2.0.0", + "rw": "^1.3.3", + "supercluster": "^7.1.4", + "tinyqueue": "^2.0.3", + "vt-pbf": "^3.1.3" + } + }, "mdn-data": { "version": "2.0.4", "dev": true @@ -73318,6 +73671,11 @@ "thunky": "^1.0.2" } }, + "murmurhash-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz", + "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==" + }, "nanoid": { "version": "3.3.2" }, @@ -73578,6 +73936,15 @@ "path-type": { "version": "4.0.0" }, + "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" + } + }, "performance-now": { "version": "2.1.0", "dev": true @@ -74280,6 +74647,11 @@ "postcss-value-parser": { "version": "4.2.0" }, + "potpack": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz", + "integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==" + }, "prelude-ls": { "version": "1.2.1", "dev": true @@ -74334,6 +74706,11 @@ "sisteransi": "^1.0.5" } }, + "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-addr": { "version": "2.0.7", "dev": true, @@ -74370,6 +74747,11 @@ "quick-lru": { "version": "5.1.1" }, + "quickselect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", + "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" + }, "raf": { "version": "3.4.1", "dev": true, @@ -74777,6 +75159,14 @@ "resolve-from": { "version": "4.0.0" }, + "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" + } + }, "resolve-url-loader": { "version": "4.0.0", "dev": true, @@ -74876,6 +75266,11 @@ "queue-microtask": "^1.2.2" } }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "safe-buffer": { "version": "5.1.2", "dev": true @@ -75309,6 +75704,14 @@ "postcss-selector-parser": "^6.0.4" } }, + "supercluster": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.1.5.tgz", + "integrity": "sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==", + "requires": { + "kdbush": "^3.0.0" + } + }, "supports-color": { "version": "5.5.0", "requires": { @@ -75515,6 +75918,11 @@ "version": "1.1.0", "dev": true }, + "tinyqueue": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", + "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==" + }, "tmpl": { "version": "1.0.5", "dev": true @@ -75700,6 +76108,16 @@ "version": "1.1.2", "dev": true }, + "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" + } + }, "w3c-hr-time": { "version": "1.0.2", "dev": true, diff --git a/test-site/package.json b/test-site/package.json index 9bb96a683..da6d1f035 100644 --- a/test-site/package.json +++ b/test-site/package.json @@ -5,6 +5,7 @@ "dependencies": { "@tailwindcss/forms": "^0.5.0", "@yext/search-ui-react": "file:..", + "mapbox-gl": "^2.10.0", "react": "file:../node_modules/react", "react-dom": "file:../node_modules/react-dom", "react-router-dom": "^6.2.2", @@ -12,6 +13,7 @@ }, "devDependencies": { "eslint-config-react-app": "file:../node_modules/eslint-config-react-app", + "@types/mapbox-gl": "^2.7.6", "@types/node": "^16.11.26", "@types/react": "^17.0.42", "@types/react-dom": "^17.0.14", diff --git a/test-site/src/components/MapPin.tsx b/test-site/src/components/MapPin.tsx index 2b4fea472..30a5d42d1 100644 --- a/test-site/src/components/MapPin.tsx +++ b/test-site/src/components/MapPin.tsx @@ -1,18 +1,46 @@ -import { PinComponent } from '@yext/search-ui-react'; +import { useEffect, useRef, useState, useCallback } from 'react'; +import { Popup, LngLatLike } from 'mapbox-gl'; +import { PinComponent, Coordinate } from '@yext/search-ui-react'; import { Location } from '../pages/LocationsPage'; -export const MapPin: PinComponent = () => { +const transformToMapboxCoord = (coordinate: Coordinate): LngLatLike => ({ + lng: coordinate.longitude, + lat: coordinate.latitude, +}); + +export const MapPin: PinComponent = props => { + const { mapbox, result } = props; + const yextCoordinate = result.rawData.yextDisplayCoordinate; + const [active, setActive] = useState(false); + const popupRef = useRef(new Popup({ offset: 15 }) + .on('close', () => setActive(false)) + ); + + useEffect(() => { + if (active && yextCoordinate) { + popupRef.current + .setLngLat(transformToMapboxCoord(yextCoordinate)) + .setText(result.name || 'unknown location') + .addTo(mapbox); + } + }, [active, mapbox, result, yextCoordinate]); + + const handleClick = useCallback(() => { + setActive(true); + }, []); + return ( -
+
+ ); }; diff --git a/test-site/src/pages/LocationsPage.tsx b/test-site/src/pages/LocationsPage.tsx index 5dfa2872f..65e04298b 100644 --- a/test-site/src/pages/LocationsPage.tsx +++ b/test-site/src/pages/LocationsPage.tsx @@ -10,16 +10,14 @@ import { Pagination, MapboxMapProps, OnDragHandler, + Coordinate } from '@yext/search-ui-react'; import { LngLat, LngLatBounds } from 'mapbox-gl'; import { useCallback, useLayoutEffect } from 'react'; import { MapPin } from '../components/MapPin'; export interface Location { - yextDisplayCoordinate: { - latitude: number, - longitude: number - } | undefined + yextDisplayCoordinate?: Coordinate } const mapboxOptions: MapboxMapProps['mapboxOptions'] = { diff --git a/tests/__fixtures__/data/mapbox.ts b/tests/__fixtures__/data/mapbox.ts new file mode 100644 index 000000000..2dad805f5 --- /dev/null +++ b/tests/__fixtures__/data/mapbox.ts @@ -0,0 +1,58 @@ +import { Source } from '@yext/search-headless-react'; + +export const locationVerticalSingle = { + vertical: { + results: [ + { + name: 'title1', + rawData: { + name: 'title1', + description: 'text1', + yextDisplayCoordinate: { + latitude: 40.741611, + longitude: -74.005371, + } + }, + source: Source.KnowledgeManager, + id: 'id1' + } + ], + resultsCount: 1, + limit: 1 + } +}; + +export const locationVerticalMultiple = { + vertical: { + results: [ + locationVerticalSingle.vertical.results[0], + { + name: 'title2', + rawData: { + name: 'title2', + description: 'text2', + yextDisplayCoordinate: { + latitude: 40.710000, + longitude: -74.005371, + } + }, + source: Source.KnowledgeManager, + id: 'id2' + }, + { + name: 'title3', + rawData: { + name: 'title3', + description: 'text3', + yextDisplayCoordinate: { + latitude: 40.741611, + longitude: -73.980000, + } + }, + source: Source.KnowledgeManager, + id: 'id3' + } + ], + resultsCount: 3 + } +}; diff --git a/tests/components/MapboxMap.stories.tsx b/tests/components/MapboxMap.stories.tsx new file mode 100644 index 000000000..816eac7a5 --- /dev/null +++ b/tests/components/MapboxMap.stories.tsx @@ -0,0 +1,57 @@ +import { ComponentMeta, Story } from '@storybook/react'; +import { userEvent, within } from '@storybook/testing-library'; +import { SearchHeadlessContext } from '@yext/search-headless-react'; + +import { generateMockedHeadless } from '../__fixtures__/search-headless'; +import { MapboxMap, MapboxMapProps } from '../../src/components/MapboxMap'; +import { MapPin } from '../../test-site/src/components/MapPin'; +import { Location } from '../../test-site/src/pages/LocationsPage'; +import { locationVerticalSingle, locationVerticalMultiple } from '../__fixtures__/data/mapbox'; + +const meta: ComponentMeta = { + title: 'MapboxMap', + component: MapboxMap, + argTypes: { + mapboxAccessToken: { + defaultValue: process.env.REACT_APP_MAPBOX_API_KEY, + control: false, + }, + PinComponent: { + control: false, + }, + }, + parameters: { layout: 'fullscreen', percy: { enableJavascript: true } }, + decorators: [(Story) => (
)] +}; +export default meta; + +const Template: Story> = (args) => ( + + + +); + +export const Primary = Template.bind({}); + +export const MultiplePins: Story> = (args) => { + return ( + + + + ); +}; + +export const CustomPin = Template.bind({}); + +CustomPin.args = { + PinComponent: MapPin, +}; + +CustomPin.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + const mapPin = await canvas.findByLabelText('Show pin details', undefined, { + timeout: 30000 + }); + userEvent.click(mapPin); + await canvas.findByText('title1'); +};