diff --git a/packages/core-data/package.json b/packages/core-data/package.json
index 6a9ddbbd..df165008 100644
--- a/packages/core-data/package.json
+++ b/packages/core-data/package.json
@@ -21,6 +21,7 @@
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-dialog": "^1.0.5",
"@samvera/clover-iiif": "^2.3.2",
+ "@turf/turf": "^6.5.0",
"i18next": "^23.8.2",
"lucide-react": "^0.321.0",
"react-instantsearch": "^7.5.4",
@@ -44,4 +45,4 @@
"tailwindcss": "^3.4.1",
"vite": "^5.1.4"
}
-}
\ No newline at end of file
+}
diff --git a/packages/core-data/src/components/PlaceMarker.js b/packages/core-data/src/components/PlaceMarker.js
deleted file mode 100644
index 9a0ba749..00000000
--- a/packages/core-data/src/components/PlaceMarker.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// @flow
-
-import { LocationMarker } from '@performant-software/geospatial';
-import React, { useCallback, useEffect, useState } from 'react';
-
-type Props = {
- /**
- * The URL of the Core Data place record.
- */
- url: string
-};
-
-/**
- * This component renders a map marker for a given Core Data Place record.
- */
-const PlaceMarker = (props: Props) => {
- const [place, setPlace] = useState();
-
- /**
- * Converts the passed data to a feature collection and sets it on the state.
- *
- * @type {(function(*): void)|*}
- */
- const onLoad = useCallback((data) => {
- const featureCollection = {
- type: 'FeatureCollection',
- features: [{
- ...data,
- properties: {
- ...data.properties,
- record_id: data.record_id
- }
- }]
- };
-
- setPlace(featureCollection);
- }, []);
-
- /**
- * Fetch the place record from the passed URL.
- */
- useEffect(() => {
- fetch(props.url)
- .then((res) => res.json())
- .then(onLoad);
- }, [props.url]);
-
- if (!place) {
- return null;
- }
-
- return (
-
- );
-};
-
-export default PlaceMarker;
diff --git a/packages/core-data/src/components/PlaceMarkers.js b/packages/core-data/src/components/PlaceMarkers.js
new file mode 100644
index 00000000..fc738d4e
--- /dev/null
+++ b/packages/core-data/src/components/PlaceMarkers.js
@@ -0,0 +1,77 @@
+// @flow
+
+import { LocationMarkers } from '@performant-software/geospatial';
+import { feature, featureCollection } from '@turf/turf';
+import React, {
+ useCallback,
+ useEffect,
+ useMemo,
+ useState
+} from 'react';
+import _ from 'underscore';
+
+type Props = {
+ animate?: boolean,
+
+ /**
+ * The URL of the Core Data place record.
+ */
+ urls: Array
+};
+
+/**
+ * This component renders a map marker for a given Core Data Place record.
+ */
+const PlaceMarkers = (props: Props) => {
+ const [places, setPlaces] = useState([]);
+
+ /**
+ * Converts the set of places into a FeatureCollection.
+ *
+ * @type {FeatureCollection}
+ */
+ const data = useMemo(() => featureCollection(places), [places]);
+
+ /**
+ * Fetches the passed URLs and converts the response to JSON.
+ *
+ * @type {function(): *}
+ */
+ const onFetch = useCallback(() => (
+ _.map(props.urls, (url) => fetch(url).then((res) => res.json()))
+ ), [props.urls]);
+
+ /**
+ * Converts the passed list of records to Features and sets them on the state.
+ *
+ * @type {function(*): *}
+ */
+ const onLoad = useCallback((records) => (
+ _.map(records, (record) => setPlaces((prevPlaces) => [
+ ...prevPlaces,
+ feature(record.geometry, record.properties)
+ ]))
+ ), []);
+
+ /**
+ * Fetch the place record from the passed URL.
+ */
+ useEffect(() => {
+ Promise
+ .all(onFetch())
+ .then(onLoad);
+ }, [onFetch, onLoad]);
+
+ if (_.isEmpty(data?.features)) {
+ return null;
+ }
+
+ return (
+
+ );
+};
+
+export default PlaceMarkers;
diff --git a/packages/core-data/src/index.js b/packages/core-data/src/index.js
index 4b3b0b77..b66872e9 100644
--- a/packages/core-data/src/index.js
+++ b/packages/core-data/src/index.js
@@ -7,7 +7,7 @@ import './index.css';
export { default as LoadAnimation } from './components/LoadAnimation';
export { default as MediaGallery } from './components/MediaGallery';
export { default as PlaceDetailsPanel } from './components/PlaceDetailsPanel';
-export { default as PlaceMarker } from './components/PlaceMarker';
+export { default as PlaceMarkers } from './components/PlaceMarkers';
export { default as PlaceResultsList } from './components/PlaceResultsList';
export { default as RelatedItemsList } from './components/RelatedItemsList';
export { default as RelatedList } from './components/RelatedList';
diff --git a/packages/geospatial/src/components/LocationMarker.js b/packages/geospatial/src/components/LocationMarkers.js
similarity index 82%
rename from packages/geospatial/src/components/LocationMarker.js
rename to packages/geospatial/src/components/LocationMarkers.js
index 8331cccd..ba8d59e3 100644
--- a/packages/geospatial/src/components/LocationMarker.js
+++ b/packages/geospatial/src/components/LocationMarkers.js
@@ -6,6 +6,11 @@ import { DEFAULT_FILL_STYLE, DEFAULT_POINT_STYLE, DEFAULT_STROKE_STYLE } from '.
import MapUtils from '../utils/Map';
type Props = {
+ /**
+ * If `true`, the point marker will display with a pulsing animation.
+ */
+ animate?: boolean,
+
/**
* The number of miles to buffer the GeoJSON data.
*/
@@ -37,7 +42,7 @@ const DEFAULT_BUFFER = 2;
/**
* This component renders a location marker to be used in a Peripleo context.
*/
-const LocationMarker = (props: Props) => {
+const LocationMarkers = (props: Props) => {
const map = useMap();
/**
@@ -52,12 +57,12 @@ const LocationMarker = (props: Props) => {
return (
<>
-
+ { props.animate && (
+
+ )}
{
);
};
-LocationMarker.defaultProps = {
+LocationMarkers.defaultProps = {
buffer: DEFAULT_BUFFER,
fillStyle: DEFAULT_FILL_STYLE,
pointStyle: DEFAULT_POINT_STYLE,
strokeStyle: DEFAULT_STROKE_STYLE
};
-export default LocationMarker;
+export default LocationMarkers;
diff --git a/packages/geospatial/src/index.js b/packages/geospatial/src/index.js
index 5b4bcf4f..6248dc3d 100644
--- a/packages/geospatial/src/index.js
+++ b/packages/geospatial/src/index.js
@@ -4,7 +4,7 @@
export { default as DrawControl } from './components/DrawControl';
export { default as GeoJsonLayer } from './components/GeoJsonLayer';
export { default as LayerMenu } from './components/LayerMenu';
-export { default as LocationMarker } from './components/LocationMarker';
+export { default as LocationMarkers } from './components/LocationMarkers';
export { default as MapControl } from './components/MapControl';
export { default as MapDraw } from './components/MapDraw';
export { default as RasterLayer } from './components/RasterLayer';
diff --git a/packages/storybook/.storybook/middleware.js b/packages/storybook/.storybook/middleware.js
index 05c3f251..a4208dd9 100644
--- a/packages/storybook/.storybook/middleware.js
+++ b/packages/storybook/.storybook/middleware.js
@@ -1,10 +1,11 @@
// @flow
-const bodyParser = require('body-parser');
-const ControlledVocabulary = require('./routes/ControlledVocabulary');
-const dotenv = require('dotenv');
-const UserDefinedFields = require('./routes/UserDefinedFields');
-const ZoteroTranslate = require('./routes/ZoteroTranslate');
+import bodyParser from 'body-parser';
+import dotenv from 'dotenv';
+import ControlledVocabulary from './routes/ControlledVocabulary';
+import CoreData from './routes/CoreData';
+import UserDefinedFields from './routes/UserDefinedFields';
+import ZoteroTranslate from './routes/ZoteroTranslate';
// Configure environment variables
dotenv.config();
@@ -14,8 +15,9 @@ const expressMiddleWare = (router) => {
router.use(bodyParser.json());
ControlledVocabulary.addRoutes(router);
+ CoreData.addRoutes(router);
UserDefinedFields.addRoutes(router);
ZoteroTranslate.addRoutes(router);
};
-module.exports = expressMiddleWare;
+export default expressMiddleWare;
diff --git a/packages/storybook/.storybook/routes/CoreData.js b/packages/storybook/.storybook/routes/CoreData.js
new file mode 100644
index 00000000..18b537c8
--- /dev/null
+++ b/packages/storybook/.storybook/routes/CoreData.js
@@ -0,0 +1,132 @@
+// @flow
+
+import { faker } from '@faker-js/faker';
+import _ from 'underscore';
+import StateBoundaries from '../../src/data/StateBoundaries.json';
+
+/**
+ * Returns the min/max latitude/longitude for the passed state. If no state is provided, we'll compute
+ * the boundary of all states.
+ *
+ * @param state
+ *
+ * @returns {{max_lat, min_lng, min_lat, max_lng}|*}
+ */
+const getBoundary = (state = null) => {
+ if (state) {
+ return StateBoundaries[state];
+ }
+
+ let minLatitude;
+ let maxLatitude;
+ let minLongitude;
+ let maxLongitude;
+
+ const keys = _.keys(StateBoundaries);
+ _.each(keys, (key) => {
+ const data = StateBoundaries[key];
+
+ if (!minLatitude || data.min_lat < minLatitude) {
+ minLatitude = data.min_lat;
+ }
+
+ if (!maxLatitude || data.max_lat > maxLatitude) {
+ maxLatitude = data.max_lat;
+ }
+
+ if (!minLongitude || data.min_lng < minLongitude) {
+ minLongitude = data.min_lng;
+ }
+
+ if (!maxLongitude || data.max_lng > maxLongitude) {
+ maxLongitude = data.max_lng;
+ }
+ });
+
+ return {
+ min_lat: minLatitude,
+ max_lat: maxLatitude,
+ min_lng: minLongitude,
+ max_lng: maxLongitude
+ };
+};
+
+/**
+ * Creates a sample place record in the Linked Places format.
+ *
+ * @returns {{
+ * names: [{
+ * toponym: string
+ * }],
+ * geometry: {
+ * coordinates: number[],
+ * type: string
+ * },
+ * '@id': string,
+ * type: string,
+ * properties: {
+ * ccode: *[],
+ * record_id: string,
+ * title: string,
+ * uuid: string
+ * }
+ * }}
+ */
+const createPlace = () => {
+ const uuid = faker.string.uuid();
+ const title = faker.location.city();
+
+ const boundary = getBoundary();
+ const latitude = faker.location.latitude({ min: boundary.min_lat, max: boundary.max_lat });
+ const longitude = faker.location.longitude({ min: boundary.min_lng, max: boundary.max_lng });
+
+ return {
+ '@id': `https://example.com/${uuid}`,
+ type: 'Place',
+ properties: {
+ ccode: [],
+ record_id: faker.string.numeric(7),
+ title,
+ uuid
+ },
+ geometry: {
+ type: 'Point',
+ coordinates: [longitude, latitude]
+ },
+ names: [{
+ toponym: title
+ }]
+ };
+};
+
+/**
+ * Adds the `/core_data/places` and `/core_data/places/:id` routes.
+ *
+ * @param router
+ */
+const addRoutes = (router) => {
+ router.get('/core_data/places', (request, response) => {
+ const { query } = request;
+
+ let number = 1;
+ if (query.number) {
+ number = query.number;
+ }
+
+ const places = [];
+
+ _.times(number, () => places.push(createPlace()));
+
+ response.send(places);
+ response.end();
+ });
+
+ router.get('/core_data/places/:id', (request, response) => {
+ response.send(createPlace());
+ response.end();
+ });
+};
+
+export default {
+ addRoutes
+};
diff --git a/packages/storybook/src/core-data/PlaceMarker.stories.js b/packages/storybook/src/core-data/PlaceMarker.stories.js
index 2829d5e8..a91a4274 100644
--- a/packages/storybook/src/core-data/PlaceMarker.stories.js
+++ b/packages/storybook/src/core-data/PlaceMarker.stories.js
@@ -3,16 +3,15 @@
import { Map, Zoom } from '@peripleo/maplibre';
import { Controls, Peripleo } from '@peripleo/peripleo';
import React from 'react';
+import _ from 'underscore';
import mapStyle from '../data/MapStyles.json';
-import PlaceMarker from '../../../core-data/src/components/PlaceMarker';
+import PlaceMarkers from '../../../core-data/src/components/PlaceMarkers';
export default {
title: 'Components/Core Data/PlaceMarker',
- component: PlaceMarker
+ component: PlaceMarkers
};
-const PLACE_URL = 'https://core-data-cloud-staging-2c51db0617a5.herokuapp.com/core_data/public/places/3aaf97a4-7052-4e2c-9056-4f4146ef0c87?project_ids=10';
-
export const Default = () => (
+
+);
+
+export const MultiplePlaces = () => (
+
+
diff --git a/packages/storybook/src/data/GeometryCollection.json b/packages/storybook/src/data/GeometryCollection.json
new file mode 100644
index 00000000..6796a200
--- /dev/null
+++ b/packages/storybook/src/data/GeometryCollection.json
@@ -0,0 +1,106 @@
+{
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "coordinates": [
+ [
+ [
+ 0.7754102888268619,
+ 46.680527155197694
+ ],
+ [
+ -0.7143321261315805,
+ 47.03810834128467
+ ],
+ [
+ -0.3687402400222197,
+ 45.29285985154556
+ ],
+ [
+ 1.7117022472057783,
+ 44.71076017077044
+ ],
+ [
+ 3.9138327406320172,
+ 45.815242131256525
+ ],
+ [
+ 3.6308350314942572,
+ 47.41785065445441
+ ],
+ [
+ 0.7754102888268619,
+ 46.680527155197694
+ ]
+ ]
+ ],
+ "type": "Polygon"
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "coordinates": [
+ [
+ 2.7751103745984835,
+ 47.98172986149493
+ ],
+ [
+ 6.829375470262562,
+ 48.14587129044554
+ ],
+ [
+ 6.414900417682219,
+ 47.169510642817755
+ ],
+ [
+ 5.760540227314522,
+ 46.41341938732728
+ ],
+ [
+ 6.390732145726702,
+ 45.59058409048566
+ ]
+ ],
+ "type": "LineString"
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "coordinates": [
+ -1.0759198798764373,
+ 48.04154361939712
+ ],
+ "type": "Point"
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "coordinates": [
+ 0.790629166637757,
+ 48.96345132277722
+ ],
+ "type": "Point"
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "coordinates": [
+ 4.3607542958423835,
+ 44.63510909496094
+ ],
+ "type": "Point"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/storybook/src/data/StateBoundaries.json b/packages/storybook/src/data/StateBoundaries.json
new file mode 100644
index 00000000..68a69faf
--- /dev/null
+++ b/packages/storybook/src/data/StateBoundaries.json
@@ -0,0 +1,402 @@
+{
+ "AK":
+ {
+ "name": "Alaska",
+ "min_lat": 52.5964,
+ "max_lat": 71.5232,
+ "min_lng": -169.9146,
+ "max_lng": -129.993
+ },
+ "AL":
+ {
+ "name": "Alabama",
+ "min_lat": 30.1463,
+ "max_lat": 35.0041,
+ "min_lng": -88.4743,
+ "max_lng": -84.8927
+ },
+ "AR":
+ {
+ "name": "Arkansas",
+ "min_lat": 33.0075,
+ "max_lat": 36.4997,
+ "min_lng": -94.6198,
+ "max_lng": -89.6594
+ },
+ "AZ":
+ {
+ "name": "Arizona",
+ "min_lat": 31.3325,
+ "max_lat": 37.0004,
+ "min_lng": -114.8126,
+ "max_lng": -109.0475
+ },
+ "CA":
+ {
+ "name": "California",
+ "min_lat": 32.5121,
+ "max_lat": 42.0126,
+ "min_lng": -124.6509,
+ "max_lng": -114.1315
+ },
+ "CO":
+ {
+ "name": "Colorado",
+ "min_lat": 36.9949,
+ "max_lat": 41.0006,
+ "min_lng": -109.0489,
+ "max_lng": -102.0424
+ },
+ "CT":
+ {
+ "name": "Connecticut",
+ "min_lat": 40.9509,
+ "max_lat": 42.0511,
+ "min_lng": -73.7272,
+ "max_lng": -71.7874
+ },
+ "DE":
+ {
+ "name": "Delaware",
+ "min_lat": 38.4482,
+ "max_lat": 39.8296,
+ "min_lng": -75.7919,
+ "max_lng": -74.8526
+ },
+ "FL":
+ {
+ "name": "Florida",
+ "min_lat": 24.3959,
+ "max_lat": 31.0035,
+ "min_lng": -87.6256,
+ "max_lng": -79.8198
+ },
+ "GA":
+ {
+ "name": "Georgia",
+ "min_lat": 30.3575,
+ "max_lat": 34.9996,
+ "min_lng": -85.6082,
+ "max_lng": -80.696
+ },
+ "HI":
+ {
+ "name": "Hawaii",
+ "min_lat": 18.71,
+ "max_lat": 22.3386,
+ "min_lng": -160.3922,
+ "max_lng": -154.6271
+ },
+ "IA":
+ {
+ "name": "Iowa",
+ "min_lat": 40.3622,
+ "max_lat": 43.5008,
+ "min_lng": -96.6357,
+ "max_lng": -90.1538
+ },
+ "ID":
+ {
+ "name": "Idaho",
+ "min_lat": 41.9871,
+ "max_lat": 49.0018,
+ "min_lng": -117.2372,
+ "max_lng": -111.0471
+ },
+ "IL":
+ {
+ "name": "Illinois",
+ "min_lat": 36.9894,
+ "max_lat": 42.5116,
+ "min_lng": -91.512,
+ "max_lng": -87.0213
+ },
+ "IN":
+ {
+ "name": "Indiana",
+ "min_lat": 37.7718,
+ "max_lat": 41.7611,
+ "min_lng": -88.098,
+ "max_lng": -84.809
+ },
+ "KS":
+ {
+ "name": "Kansas",
+ "min_lat": 36.9927,
+ "max_lat": 40.0087,
+ "min_lng": -102.0506,
+ "max_lng": -94.6046
+ },
+ "KY":
+ {
+ "name": "Kentucky",
+ "min_lat": 36.4931,
+ "max_lat": 39.1439,
+ "min_lng": -89.5372,
+ "max_lng": -82.0308
+ },
+ "LA":
+ {
+ "name": "Louisiana",
+ "min_lat": 28.8832,
+ "max_lat": 33.0225,
+ "min_lng": -94.043,
+ "max_lng": -88.7421
+ },
+ "MA":
+ {
+ "name": "Massachusetts",
+ "min_lat": 41.159,
+ "max_lat": 42.889,
+ "min_lng": -73.5081,
+ "max_lng": -69.7398
+ },
+ "MD":
+ {
+ "name": "Maryland",
+ "min_lat": 37.8889,
+ "max_lat": 39.722,
+ "min_lng": -79.4861,
+ "max_lng": -74.8581
+ },
+ "ME":
+ {
+ "name": "Maine",
+ "min_lat": 42.9182,
+ "max_lat": 47.455,
+ "min_lng": -71.0829,
+ "max_lng": -66.8628
+ },
+ "MI":
+ {
+ "name": "Michigan",
+ "min_lat": 41.6965,
+ "max_lat": 48.3042,
+ "min_lng": -90.4175,
+ "max_lng": -82.1221
+ },
+ "MN":
+ {
+ "name": "Minnesota",
+ "min_lat": 43.5008,
+ "max_lat": 49.3877,
+ "min_lng": -97.2304,
+ "max_lng": -89.4919
+ },
+ "MO":
+ {
+ "name": "Missouri",
+ "min_lat": 35.9958,
+ "max_lat": 40.6181,
+ "min_lng": -95.7527,
+ "max_lng": -89.1005
+ },
+ "MS":
+ {
+ "name": "Mississippi",
+ "min_lat": 30.0905,
+ "max_lat": 35.0075,
+ "min_lng": -91.6589,
+ "max_lng": -88.0994
+ },
+ "MT":
+ {
+ "name": "Montana",
+ "min_lat": 44.3563,
+ "max_lat": 48.9991,
+ "min_lng": -116.0458,
+ "max_lng": -104.0186
+ },
+ "NC":
+ {
+ "name": "North Carolina",
+ "min_lat": 33.7666,
+ "max_lat": 36.588,
+ "min_lng": -84.3201,
+ "max_lng": -75.4129
+ },
+ "ND":
+ {
+ "name": "North Dakota",
+ "min_lat": 45.934,
+ "max_lat": 48.9982,
+ "min_lng": -104.0501,
+ "max_lng": -96.5671
+ },
+ "NE":
+ {
+ "name": "Nebraska",
+ "min_lat": 39.9992,
+ "max_lat": 43.0006,
+ "min_lng": -104.0543,
+ "max_lng": -95.3091
+ },
+ "NH":
+ {
+ "name": "New Hampshire",
+ "min_lat": 42.6986,
+ "max_lat": 45.3058,
+ "min_lng": -72.5592,
+ "max_lng": -70.5583
+ },
+ "NJ":
+ {
+ "name": "New Jersey",
+ "min_lat": 38.8472,
+ "max_lat": 41.3593,
+ "min_lng": -75.5708,
+ "max_lng": -73.8885
+ },
+ "NM":
+ {
+ "name": "New Mexico",
+ "min_lat": 31.3337,
+ "max_lat": 36.9982,
+ "min_lng": -109.0489,
+ "max_lng": -103.0023
+ },
+ "NV":
+ {
+ "name": "Nevada",
+ "min_lat": 35.003,
+ "max_lat": 42.0003,
+ "min_lng": -120.0037,
+ "max_lng": -114.0436
+ },
+ "NY":
+ {
+ "name": "New York",
+ "min_lat": 40.4772,
+ "max_lat": 45.0153,
+ "min_lng": -79.7624,
+ "max_lng": -71.7517
+ },
+ "OH":
+ {
+ "name": "Ohio",
+ "min_lat": 38.3761,
+ "max_lat": 42.321,
+ "min_lng": -84.8172,
+ "max_lng": -80.5188
+ },
+ "OK":
+ {
+ "name": "Oklahoma",
+ "min_lat": 33.6386,
+ "max_lat": 37.0015,
+ "min_lng": -103.0064,
+ "max_lng": -94.4357
+ },
+ "OR":
+ {
+ "name": "Oregon",
+ "min_lat": 41.9952,
+ "max_lat": 46.2891,
+ "min_lng": -124.7305,
+ "max_lng": -116.4606
+ },
+ "PA":
+ {
+ "name": "Pennsylvania",
+ "min_lat": 39.7199,
+ "max_lat": 42.5167,
+ "min_lng": -80.5243,
+ "max_lng": -74.707
+ },
+ "RI":
+ {
+ "name": "Rhode Island",
+ "min_lat": 41.1849,
+ "max_lat": 42.0156,
+ "min_lng": -71.9041,
+ "max_lng": -71.0541
+ },
+ "SC":
+ {
+ "name": "South Carolina",
+ "min_lat": 32.0453,
+ "max_lat": 35.2075,
+ "min_lng": -83.3588,
+ "max_lng": -78.4836
+ },
+ "SD":
+ {
+ "name": "South Dakota",
+ "min_lat": 42.4772,
+ "max_lat": 45.9435,
+ "min_lng": -104.0529,
+ "max_lng": -96.438
+ },
+ "TN":
+ {
+ "name": "Tennessee",
+ "min_lat": 34.9884,
+ "max_lat": 36.6871,
+ "min_lng": -90.3131,
+ "max_lng": -81.6518
+ },
+ "TX":
+ {
+ "name": "Texas",
+ "min_lat": 25.8419,
+ "max_lat": 36.5008,
+ "min_lng": -106.6168,
+ "max_lng": -93.5074
+ },
+ "UT":
+ {
+ "name": "Utah",
+ "min_lat": 36.9982,
+ "max_lat": 41.9993,
+ "min_lng": -114.0504,
+ "max_lng": -109.0462
+ },
+ "VA":
+ {
+ "name": "Virginia",
+ "min_lat": 36.5427,
+ "max_lat": 39.4659,
+ "min_lng": -83.6753,
+ "max_lng": -74.9707
+ },
+ "VT":
+ {
+ "name": "Vermont",
+ "min_lat": 42.7289,
+ "max_lat": 45.0153,
+ "min_lng": -73.4381,
+ "max_lng": -71.4949
+ },
+ "WA":
+ {
+ "name": "Washington",
+ "min_lat": 45.5439,
+ "max_lat": 49.0027,
+ "min_lng": -124.8679,
+ "max_lng": -116.9165
+ },
+ "WI":
+ {
+ "name": "Wisconsin",
+ "min_lat": 42.4954,
+ "max_lat": 47.31,
+ "min_lng": -92.8564,
+ "max_lng": -86.2523
+ },
+ "WV":
+ {
+ "name": "West Virginia",
+ "min_lat": 37.1953,
+ "max_lat": 40.6338,
+ "min_lng": -82.6392,
+ "max_lng": -77.731
+ },
+ "WY":
+ {
+ "name": "Wyoming",
+ "min_lat": 40.9986,
+ "max_lat": 44.9998,
+ "min_lng": -111.0539,
+ "max_lng": -104.0556
+ }
+}
\ No newline at end of file
diff --git a/packages/storybook/src/geospatial/LocationMarker.stories.js b/packages/storybook/src/geospatial/LocationMarker.stories.js
index 0e6c37a6..c4f6a027 100644
--- a/packages/storybook/src/geospatial/LocationMarker.stories.js
+++ b/packages/storybook/src/geospatial/LocationMarker.stories.js
@@ -3,12 +3,13 @@
import { Peripleo, Controls } from '@peripleo/peripleo';
import { Map, Zoom } from '@peripleo/maplibre';
import React from 'react';
-import LocationMarker from '../../../geospatial/src/components/LocationMarker';
+import geometryCollection from '../data/GeometryCollection.json';
+import LocationMarkers from '../../../geospatial/src/components/LocationMarkers';
import mapStyle from '../data/MapStyles.json';
export default {
title: 'Components/Geospatial/LocationMarker',
- component: LocationMarker
+ component: LocationMarkers
};
export const Default = () => (
@@ -27,7 +28,38 @@ export const Default = () => (
height: '300px'
}}
>
-
+
+
+
+);
+
+export const Animation = () => (
+
+