{ props.label }
diff --git a/packages/core-data/src/components/RelatedItemsList.js b/packages/core-data/src/components/RelatedItemsList.js
index 8e9a6860..4810e591 100644
--- a/packages/core-data/src/components/RelatedItemsList.js
+++ b/packages/core-data/src/components/RelatedItemsList.js
@@ -4,6 +4,9 @@ import * as Accordion from '@radix-ui/react-accordion';
import React, { type Node } from 'react';
type Props = {
+ /**
+ * JSX child elements.
+ */
children: Node
};
diff --git a/packages/core-data/src/components/RelatedList.js b/packages/core-data/src/components/RelatedList.js
index a3b3a14c..270a8571 100644
--- a/packages/core-data/src/components/RelatedList.js
+++ b/packages/core-data/src/components/RelatedList.js
@@ -27,7 +27,7 @@ type Props = {
};
/**
- * This component is a helper component used to structure the lists for the other `Related*` comnponents.
+ * This component is a helper component used to structure the lists for the other `Related*` components.
*/
const RelatedList = (props: Props) => {
const { data, loading } = useLoader(props.onLoad, []);
diff --git a/packages/core-data/src/components/SearchResultsLayer.js b/packages/core-data/src/components/SearchResultsLayer.js
index d5e6e30f..c6ac88f9 100644
--- a/packages/core-data/src/components/SearchResultsLayer.js
+++ b/packages/core-data/src/components/SearchResultsLayer.js
@@ -7,13 +7,30 @@ import TypesenseUtils from '../utils/Typesense';
import { useCachedHits, useSearchCompleted } from '../hooks/Typesense';
type Props = {
+ /**
+ * Additional event data to pass to the fitToBounds function.
+ */
boundingBoxData?: any,
+
+ /**
+ * Additional options to pass to the fitToBounds function.
+ */
boundingBoxOptions?: any,
+
+ /**
+ * The number of miles to buffer the GeoJSON data.
+ */
buffer?: number,
- fitBoundingBox?: boolean,
- layerId: string
+
+ /**
+ * If `true`, the map will fit the bounding box around the passed data.
+ */
+ fitBoundingBox?: boolean
};
+/**
+ * This component renders a map layer for the search results from a Typesense search index.
+ */
const SearchResultsLayer = (props: Props) => {
const [mapLoaded, setMapLoaded] = useState(false);
@@ -58,4 +75,8 @@ const SearchResultsLayer = (props: Props) => {
);
};
+SearchResultsLayer.defaultProps = {
+ fitBoundingBox: true
+};
+
export default SearchResultsLayer;
From e68a140860f16457a77326c0d7d6923c356c035a Mon Sep 17 00:00:00 2001
From: dleadbetter <>
Date: Wed, 3 Apr 2024 09:16:16 -0400
Subject: [PATCH 101/109] Atlas #4 - Publishing v2.1.0-beta.49
---
packages/controlled-vocabulary/package.json | 6 +++---
packages/core-data/package.json | 4 ++--
packages/geospatial/package.json | 2 +-
packages/semantic-ui/package.json | 4 ++--
packages/shared/package.json | 2 +-
packages/user-defined-fields/package.json | 6 +++---
packages/visualize/package.json | 2 +-
react-components.json | 2 +-
8 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/packages/controlled-vocabulary/package.json b/packages/controlled-vocabulary/package.json
index c879c29f..45153edd 100644
--- a/packages/controlled-vocabulary/package.json
+++ b/packages/controlled-vocabulary/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/controlled-vocabulary",
- "version": "2.1.0-beta.48",
+ "version": "2.1.0-beta.49",
"description": "A package of components to allow user to configure dropdown elements. Use with the \"controlled_vocabulary\" gem.",
"license": "MIT",
"main": "./dist/index.cjs.js",
@@ -23,8 +23,8 @@
"underscore": "^1.13.2"
},
"peerDependencies": {
- "@performant-software/semantic-components": "^2.1.0-beta.48",
- "@performant-software/shared-components": "^2.1.0-beta.48",
+ "@performant-software/semantic-components": "^2.1.0-beta.49",
+ "@performant-software/shared-components": "^2.1.0-beta.49",
"react": ">= 16.13.1 < 19.0.0",
"react-dom": ">= 16.13.1 < 19.0.0"
},
diff --git a/packages/core-data/package.json b/packages/core-data/package.json
index 7dddc672..dcce7692 100644
--- a/packages/core-data/package.json
+++ b/packages/core-data/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/core-data",
- "version": "2.1.0-beta.48",
+ "version": "2.1.0-beta.49",
"description": "A package of components used with the Core Data platform.",
"license": "MIT",
"main": "./dist/index.cjs.js",
@@ -38,7 +38,7 @@
"underscore": "^1.13.2"
},
"peerDependencies": {
- "@performant-software/geospatial": "^2.1.0-beta.48",
+ "@performant-software/geospatial": "^2.1.0-beta.49",
"@peripleo/maplibre": "^0.5.1",
"@peripleo/peripleo": "^0.5.1",
"react": ">= 16.13.1 < 19.0.0",
diff --git a/packages/geospatial/package.json b/packages/geospatial/package.json
index a58c7c88..6b6a44d3 100644
--- a/packages/geospatial/package.json
+++ b/packages/geospatial/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/geospatial",
- "version": "2.1.0-beta.48",
+ "version": "2.1.0-beta.49",
"description": "A package of components for all things map-related.",
"license": "MIT",
"main": "./dist/index.cjs.js",
diff --git a/packages/semantic-ui/package.json b/packages/semantic-ui/package.json
index 7419e4e2..d5a31e56 100644
--- a/packages/semantic-ui/package.json
+++ b/packages/semantic-ui/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/semantic-components",
- "version": "2.1.0-beta.48",
+ "version": "2.1.0-beta.49",
"description": "A package of shared components based on the Semantic UI Framework.",
"license": "MIT",
"main": "./dist/index.cjs.js",
@@ -35,7 +35,7 @@
"zotero-translation-client": "^5.0.1"
},
"peerDependencies": {
- "@performant-software/shared-components": "^2.1.0-beta.48",
+ "@performant-software/shared-components": "^2.1.0-beta.49",
"@samvera/clover-iiif": "^2.3.2",
"react": ">= 16.13.1 < 19.0.0",
"react-dnd": "^11.1.3",
diff --git a/packages/shared/package.json b/packages/shared/package.json
index ffb0217a..0de8f96a 100644
--- a/packages/shared/package.json
+++ b/packages/shared/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/shared-components",
- "version": "2.1.0-beta.48",
+ "version": "2.1.0-beta.49",
"description": "A package of shared, framework agnostic, components.",
"license": "MIT",
"main": "./dist/index.cjs.js",
diff --git a/packages/user-defined-fields/package.json b/packages/user-defined-fields/package.json
index 8fb1f9c7..826b033c 100644
--- a/packages/user-defined-fields/package.json
+++ b/packages/user-defined-fields/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/user-defined-fields",
- "version": "2.1.0-beta.48",
+ "version": "2.1.0-beta.49",
"description": "A package of components used for allowing end users to define fields on models. Use with the \"user_defined_fields\" gem.",
"license": "MIT",
"main": "./dist/index.cjs.js",
@@ -23,8 +23,8 @@
"underscore": "^1.13.2"
},
"peerDependencies": {
- "@performant-software/semantic-components": "^2.1.0-beta.48",
- "@performant-software/shared-components": "^2.1.0-beta.48",
+ "@performant-software/semantic-components": "^2.1.0-beta.49",
+ "@performant-software/shared-components": "^2.1.0-beta.49",
"react": ">= 16.13.1 < 19.0.0",
"react-dom": ">= 16.13.1 < 19.0.0"
},
diff --git a/packages/visualize/package.json b/packages/visualize/package.json
index 99689f5b..4e6cf439 100644
--- a/packages/visualize/package.json
+++ b/packages/visualize/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/visualize",
- "version": "2.1.0-beta.48",
+ "version": "2.1.0-beta.49",
"description": "A package of components used for data visualization",
"license": "MIT",
"main": "./dist/index.cjs.js",
diff --git a/react-components.json b/react-components.json
index 29805257..082f795f 100644
--- a/react-components.json
+++ b/react-components.json
@@ -8,5 +8,5 @@
"packages/user-defined-fields",
"packages/visualize"
],
- "version": "2.1.0-beta.48"
+ "version": "2.1.0-beta.49"
}
From f6ee170d235dc7cf0e3c966751a448a0328c327f Mon Sep 17 00:00:00 2001
From: dleadbetter <>
Date: Wed, 3 Apr 2024 09:16:37 -0400
Subject: [PATCH 102/109] Atlas #4 - Adding example to LocationMarkers.stories
with no zoom animation
---
.../src/geospatial/LocationMarkers.stories.js | 33 +++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/packages/storybook/src/geospatial/LocationMarkers.stories.js b/packages/storybook/src/geospatial/LocationMarkers.stories.js
index a7954656..320a2bda 100644
--- a/packages/storybook/src/geospatial/LocationMarkers.stories.js
+++ b/packages/storybook/src/geospatial/LocationMarkers.stories.js
@@ -128,3 +128,36 @@ export const MultiplePoints = () => (
);
+
+export const NoZoom = () => (
+
+
+
+);
\ No newline at end of file
From 3f34ef8fda54dd8e60e0bc8f224b78778d7a0514 Mon Sep 17 00:00:00 2001
From: dleadbetter <>
Date: Wed, 3 Apr 2024 11:16:44 -0400
Subject: [PATCH 103/109] Atlas #4 - Adjusting fitBounds logic in
SearchResultsLayer to fire after the search has completed and after the map
has loaded
---
.../src/components/SearchResultsLayer.js | 22 ++++++++++++-------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/packages/core-data/src/components/SearchResultsLayer.js b/packages/core-data/src/components/SearchResultsLayer.js
index c6ac88f9..c61e4f52 100644
--- a/packages/core-data/src/components/SearchResultsLayer.js
+++ b/packages/core-data/src/components/SearchResultsLayer.js
@@ -33,12 +33,24 @@ type Props = {
*/
const SearchResultsLayer = (props: Props) => {
const [mapLoaded, setMapLoaded] = useState(false);
+ const [searchCompleted, setSearchCompleted] = useState(false);
const hits = useCachedHits();
const map = useMap();
const data = useMemo(() => TypesenseUtils.toFeatureCollection(hits), [hits]);
+ /**
+ * Here we'll implement our own fitting of the bounding box once the search has completed and the map has loaded,
+ * rather than using the default implementation in LocationMarker that will change when the "data" prop changes.
+ */
+ useEffect(() => {
+ if (props.fitBoundingBox && mapLoaded && searchCompleted) {
+ const boundingBox = MapUtils.getBoundingBox(data, props.buffer);
+ map.fitBounds(boundingBox, props.boundingBoxOptions, props.boundingBoxData);
+ }
+ }, [mapLoaded, searchCompleted, props.boundingBoxData, props.boundingBoxOptions, props.buffer, props.fitBoundingBox]);
+
/**
* Sets the mapLoaded state to true.
*/
@@ -56,15 +68,9 @@ const SearchResultsLayer = (props: Props) => {
}, [map]);
/**
- * Here we'll implement our own fitting of the bounding box, rather than using
- * the default implementation in LocationMarker that will change when the "data" prop changes.
+ * Sets the search completed state to true.
*/
- useSearchCompleted(() => {
- if (props.fitBoundingBox && mapLoaded && data) {
- const boundingBox = MapUtils.getBoundingBox(data, props.buffer);
- map.fitBounds(boundingBox, props.boundingBoxOptions, props.boundingBoxData);
- }
- }, [data, map, mapLoaded, props.boundingBoxData, props.boundingBoxOptions, props.buffer, props.fitBoundingBox]);
+ useSearchCompleted(() => setSearchCompleted(true), []);
return (
Date: Wed, 3 Apr 2024 11:25:08 -0400
Subject: [PATCH 104/109] Atlas #4 - Publishing v2.1.0-beta.50
---
packages/controlled-vocabulary/package.json | 6 +++---
packages/core-data/package.json | 4 ++--
packages/geospatial/package.json | 2 +-
packages/semantic-ui/package.json | 4 ++--
packages/shared/package.json | 2 +-
packages/user-defined-fields/package.json | 6 +++---
packages/visualize/package.json | 2 +-
react-components.json | 2 +-
8 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/packages/controlled-vocabulary/package.json b/packages/controlled-vocabulary/package.json
index 45153edd..5ea2d2a0 100644
--- a/packages/controlled-vocabulary/package.json
+++ b/packages/controlled-vocabulary/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/controlled-vocabulary",
- "version": "2.1.0-beta.49",
+ "version": "2.1.0-beta.50",
"description": "A package of components to allow user to configure dropdown elements. Use with the \"controlled_vocabulary\" gem.",
"license": "MIT",
"main": "./dist/index.cjs.js",
@@ -23,8 +23,8 @@
"underscore": "^1.13.2"
},
"peerDependencies": {
- "@performant-software/semantic-components": "^2.1.0-beta.49",
- "@performant-software/shared-components": "^2.1.0-beta.49",
+ "@performant-software/semantic-components": "^2.1.0-beta.50",
+ "@performant-software/shared-components": "^2.1.0-beta.50",
"react": ">= 16.13.1 < 19.0.0",
"react-dom": ">= 16.13.1 < 19.0.0"
},
diff --git a/packages/core-data/package.json b/packages/core-data/package.json
index dcce7692..d1884b27 100644
--- a/packages/core-data/package.json
+++ b/packages/core-data/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/core-data",
- "version": "2.1.0-beta.49",
+ "version": "2.1.0-beta.50",
"description": "A package of components used with the Core Data platform.",
"license": "MIT",
"main": "./dist/index.cjs.js",
@@ -38,7 +38,7 @@
"underscore": "^1.13.2"
},
"peerDependencies": {
- "@performant-software/geospatial": "^2.1.0-beta.49",
+ "@performant-software/geospatial": "^2.1.0-beta.50",
"@peripleo/maplibre": "^0.5.1",
"@peripleo/peripleo": "^0.5.1",
"react": ">= 16.13.1 < 19.0.0",
diff --git a/packages/geospatial/package.json b/packages/geospatial/package.json
index 6b6a44d3..10bbf3a2 100644
--- a/packages/geospatial/package.json
+++ b/packages/geospatial/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/geospatial",
- "version": "2.1.0-beta.49",
+ "version": "2.1.0-beta.50",
"description": "A package of components for all things map-related.",
"license": "MIT",
"main": "./dist/index.cjs.js",
diff --git a/packages/semantic-ui/package.json b/packages/semantic-ui/package.json
index d5a31e56..0ed23b2d 100644
--- a/packages/semantic-ui/package.json
+++ b/packages/semantic-ui/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/semantic-components",
- "version": "2.1.0-beta.49",
+ "version": "2.1.0-beta.50",
"description": "A package of shared components based on the Semantic UI Framework.",
"license": "MIT",
"main": "./dist/index.cjs.js",
@@ -35,7 +35,7 @@
"zotero-translation-client": "^5.0.1"
},
"peerDependencies": {
- "@performant-software/shared-components": "^2.1.0-beta.49",
+ "@performant-software/shared-components": "^2.1.0-beta.50",
"@samvera/clover-iiif": "^2.3.2",
"react": ">= 16.13.1 < 19.0.0",
"react-dnd": "^11.1.3",
diff --git a/packages/shared/package.json b/packages/shared/package.json
index 0de8f96a..11ada804 100644
--- a/packages/shared/package.json
+++ b/packages/shared/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/shared-components",
- "version": "2.1.0-beta.49",
+ "version": "2.1.0-beta.50",
"description": "A package of shared, framework agnostic, components.",
"license": "MIT",
"main": "./dist/index.cjs.js",
diff --git a/packages/user-defined-fields/package.json b/packages/user-defined-fields/package.json
index 826b033c..eee513a8 100644
--- a/packages/user-defined-fields/package.json
+++ b/packages/user-defined-fields/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/user-defined-fields",
- "version": "2.1.0-beta.49",
+ "version": "2.1.0-beta.50",
"description": "A package of components used for allowing end users to define fields on models. Use with the \"user_defined_fields\" gem.",
"license": "MIT",
"main": "./dist/index.cjs.js",
@@ -23,8 +23,8 @@
"underscore": "^1.13.2"
},
"peerDependencies": {
- "@performant-software/semantic-components": "^2.1.0-beta.49",
- "@performant-software/shared-components": "^2.1.0-beta.49",
+ "@performant-software/semantic-components": "^2.1.0-beta.50",
+ "@performant-software/shared-components": "^2.1.0-beta.50",
"react": ">= 16.13.1 < 19.0.0",
"react-dom": ">= 16.13.1 < 19.0.0"
},
diff --git a/packages/visualize/package.json b/packages/visualize/package.json
index 4e6cf439..f4df703f 100644
--- a/packages/visualize/package.json
+++ b/packages/visualize/package.json
@@ -1,6 +1,6 @@
{
"name": "@performant-software/visualize",
- "version": "2.1.0-beta.49",
+ "version": "2.1.0-beta.50",
"description": "A package of components used for data visualization",
"license": "MIT",
"main": "./dist/index.cjs.js",
diff --git a/react-components.json b/react-components.json
index 082f795f..c9d4fb67 100644
--- a/react-components.json
+++ b/react-components.json
@@ -8,5 +8,5 @@
"packages/user-defined-fields",
"packages/visualize"
],
- "version": "2.1.0-beta.49"
+ "version": "2.1.0-beta.50"
}
From 5626a5d39b323773e05efb565c97aeb0c42573b5 Mon Sep 17 00:00:00 2001
From: dleadbetter <>
Date: Wed, 3 Apr 2024 12:05:15 -0400
Subject: [PATCH 105/109] Atlas #11 - Adding GeoJSON validation to
LocationMarkers component
---
packages/geospatial/package.json | 3 +-
.../src/components/LocationMarkers.js | 17 +++++--
packages/geospatial/src/utils/Map.js | 13 ++++-
.../src/geospatial/LocationMarkers.stories.js | 48 +++++++++++++++++++
yarn.lock | 23 +++++++++
5 files changed, 99 insertions(+), 5 deletions(-)
diff --git a/packages/geospatial/package.json b/packages/geospatial/package.json
index 10bbf3a2..25d5216f 100644
--- a/packages/geospatial/package.json
+++ b/packages/geospatial/package.json
@@ -19,6 +19,7 @@
},
"dependencies": {
"@mapbox/mapbox-gl-draw": "^1.4.3",
+ "@turf/boolean-valid": "^6.5.0",
"@turf/turf": "^6.5.0",
"mapbox-gl": "npm:empty-npm-package@1.0.0",
"maplibre-gl": "^3.6.2",
@@ -38,4 +39,4 @@
"react-dom": "^18.2.0",
"vite": "^5.1.4"
}
-}
\ No newline at end of file
+}
diff --git a/packages/geospatial/src/components/LocationMarkers.js b/packages/geospatial/src/components/LocationMarkers.js
index a04d2ac1..1bfe526d 100644
--- a/packages/geospatial/src/components/LocationMarkers.js
+++ b/packages/geospatial/src/components/LocationMarkers.js
@@ -1,7 +1,7 @@
// @flow
import { GeoJSONLayer, PulsingMarkerLayer, useMap } from '@peripleo/maplibre';
-import React, { useEffect } from 'react';
+import React, { useEffect, useMemo } from 'react';
import MapStyles from '../utils/MapStyles';
import MapUtils from '../utils/Map';
@@ -91,15 +91,26 @@ const DEFAULT_BUFFER = 2;
const LocationMarkers = (props: Props) => {
const map = useMap();
+ /**
+ * Memo-izes the data validation.
+ *
+ * @type {boolean}
+ */
+ const isValid = useMemo(() => MapUtils.validateGeometry(props.data), [props.data]);
+
/**
* Sets the bounding box on the map.
*/
useEffect(() => {
- if (map && props.data && props.fitBoundingBox) {
+ if (map && isValid && props.data && props.fitBoundingBox) {
const boundingBox = MapUtils.getBoundingBox(props.data, props.buffer);
map.fitBounds(boundingBox, props.boundingBoxOptions, props.boundingBoxData);
}
- }, [map, props.buffer, props.data, props.boundingBoxData, props.boundingBoxOptions, props.fitBoundingBox]);
+ }, [isValid, map, props.buffer, props.data, props.boundingBoxData, props.boundingBoxOptions, props.fitBoundingBox]);
+
+ if (!isValid) {
+ return null;
+ }
return (
<>
diff --git a/packages/geospatial/src/utils/Map.js b/packages/geospatial/src/utils/Map.js
index a1cccb0f..e0c8f493 100644
--- a/packages/geospatial/src/utils/Map.js
+++ b/packages/geospatial/src/utils/Map.js
@@ -1,5 +1,6 @@
// @flow
+import booleanValid from '@turf/boolean-valid';
import { bbox, bboxPolygon, buffer } from '@turf/turf';
const MIN_LATITUDE = -90;
@@ -57,7 +58,17 @@ const validateCoordinates = (coordinates) => {
return valid;
};
+/**
+ * Returns true if the passed data set is valid GeoJSON.
+ *
+ * @param data
+ *
+ * @returns {boolean}
+ */
+const validateGeometry = (data) => booleanValid(data);
+
export default {
getBoundingBox,
- validateCoordinates
+ validateCoordinates,
+ validateGeometry
};
diff --git a/packages/storybook/src/geospatial/LocationMarkers.stories.js b/packages/storybook/src/geospatial/LocationMarkers.stories.js
index 320a2bda..aaed0db5 100644
--- a/packages/storybook/src/geospatial/LocationMarkers.stories.js
+++ b/packages/storybook/src/geospatial/LocationMarkers.stories.js
@@ -160,4 +160,52 @@ export const NoZoom = () => (
+);
+
+export const EmptyDataSet = () => (
+