@teamimpact/veda-ui-blocks 0.1.0-beta.11 → 0.1.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +33 -11
- package/dist/index.js +212 -188
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -318,9 +318,6 @@ type TagProps = {
|
|
|
318
318
|
*/
|
|
319
319
|
declare function Tag({ variant, size, color, bgColor, borderColor, textColor, icon, onClose, children, className, }: TagProps): react_jsx_runtime.JSX.Element;
|
|
320
320
|
|
|
321
|
-
/** NASA Blue Marble imagery basemap */
|
|
322
|
-
declare const NASA_BLUE_MARBLE_BASEMAP_STYLE: StyleSpecification;
|
|
323
|
-
|
|
324
321
|
interface GeoConfigProviderProps {
|
|
325
322
|
stacApiUrl?: string;
|
|
326
323
|
titilerBaseUrl?: string;
|
|
@@ -337,20 +334,22 @@ type TileMatrixSet = "WebMercatorQuad" | "GDALWebMercatorQuad" | "WorldCRS84Quad
|
|
|
337
334
|
type StacRasterLayerConfig = {
|
|
338
335
|
type: "raster";
|
|
339
336
|
collectionId: string;
|
|
337
|
+
collectionAssetId: string;
|
|
340
338
|
dateRange: DateRange;
|
|
341
339
|
tileMatrixSet?: TileMatrixSet;
|
|
340
|
+
hideLegend?: boolean;
|
|
342
341
|
};
|
|
343
342
|
interface GradientLegendProps {
|
|
344
343
|
type: "gradient";
|
|
345
|
-
colorStops
|
|
344
|
+
colorStops?: string[];
|
|
346
345
|
title?: string;
|
|
347
346
|
description?: string;
|
|
348
347
|
provider?: string;
|
|
349
348
|
spatialExtent?: string;
|
|
350
349
|
timeDensity?: string;
|
|
351
350
|
unit?: string;
|
|
352
|
-
min
|
|
353
|
-
max
|
|
351
|
+
min?: number;
|
|
352
|
+
max?: number;
|
|
354
353
|
}
|
|
355
354
|
type LegendProps = GradientLegendProps & {
|
|
356
355
|
initialExpanded?: boolean;
|
|
@@ -358,9 +357,32 @@ type LegendProps = GradientLegendProps & {
|
|
|
358
357
|
|
|
359
358
|
declare function Legend({ initialExpanded, ...props }: LegendProps): react_jsx_runtime.JSX.Element;
|
|
360
359
|
|
|
360
|
+
/** NASA Blue Marble imagery basemap */
|
|
361
|
+
declare const NASA_BLUE_MARBLE_BASEMAP_STYLE: StyleSpecification;
|
|
362
|
+
/** Carto Dark Matter raster basemap without labels */
|
|
363
|
+
declare const CARTO_DARK_BASEMAP_STYLE: StyleSpecification;
|
|
364
|
+
/**
|
|
365
|
+
* Carto Dark Matter vector style with labels.
|
|
366
|
+
* Data layers should render beneath `waterway_label`.
|
|
367
|
+
*/
|
|
368
|
+
declare const CARTO_DARK_WITH_LABELS_BASEMAP_STYLE = "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json";
|
|
369
|
+
declare const CARTO_LABELS_LAYER_ID = "waterway_label";
|
|
370
|
+
/**
|
|
371
|
+
* OpenFreeMap Dark vector style.
|
|
372
|
+
* Data layers should render beneath `highway_name_other`.
|
|
373
|
+
*/
|
|
374
|
+
declare const OPEN_FREE_MAP_DARK_BASEMAP_STYLE = "https://tiles.openfreemap.org/styles/dark";
|
|
375
|
+
declare const OPEN_FREE_MAP_LABELS_LAYER_ID = "highway_name_other";
|
|
376
|
+
/**
|
|
377
|
+
* Maps vector basemap styles to the first label layer that should render
|
|
378
|
+
* above data overlays.
|
|
379
|
+
*/
|
|
380
|
+
declare const BASEMAP_LABEL_LAYER_IDS: Record<string, string>;
|
|
381
|
+
type BaseMaps = keyof typeof BASEMAP_LABEL_LAYER_IDS;
|
|
382
|
+
|
|
361
383
|
type StacCompareMapProps = {
|
|
362
|
-
/** MapLibre base map style URL or style object. */
|
|
363
|
-
baseMapStyle?:
|
|
384
|
+
/** MapLibre base map style URL or style object. Defaults to Carto Dark with labels. For known vector styles the label layer is derived automatically so STAC data renders beneath labels. */
|
|
385
|
+
baseMapStyle?: BaseMaps | StyleSpecification;
|
|
364
386
|
/** Initial map center (longitude/latitude), zoom level, and optional bearing/pitch. MapLibre applies defaults for any properties not provided. */
|
|
365
387
|
initialViewState?: Partial<ViewState>;
|
|
366
388
|
/** Layer config for the left panel. */
|
|
@@ -394,8 +416,8 @@ type StacCompareMapProps = {
|
|
|
394
416
|
declare function StacCompareMap({ baseMapStyle, initialViewState, leftLayerConfig, rightLayerConfig, className, }: StacCompareMapProps): react_jsx_runtime.JSX.Element;
|
|
395
417
|
|
|
396
418
|
type StacSingleLayerMapProps = {
|
|
397
|
-
/** MapLibre base map style URL or style object. Defaults to
|
|
398
|
-
baseMapStyle?:
|
|
419
|
+
/** MapLibre base map style URL or style object. Defaults to Carto Dark with labels. For known vector styles the label layer is derived automatically so STAC data renders beneath labels. */
|
|
420
|
+
baseMapStyle?: BaseMaps | StyleSpecification;
|
|
399
421
|
/** Initial map center (longitude/latitude), zoom level, and optional bearing/pitch. MapLibre applies defaults for any properties not provided. */
|
|
400
422
|
initialViewState?: Partial<ViewState>;
|
|
401
423
|
/** STAC collection and date range to fetch and display as a raster tile layer. */
|
|
@@ -420,4 +442,4 @@ type StacSingleLayerMapProps = {
|
|
|
420
442
|
*/
|
|
421
443
|
declare function StacSingleLayerMap({ baseMapStyle, initialViewState, layerConfig, }: StacSingleLayerMapProps): react_jsx_runtime.JSX.Element;
|
|
422
444
|
|
|
423
|
-
export { Banner, type BannerProps, Card, CardCTA, type CardCTAProps, CardDetailed, type CardDetailedProps, CardMini, type CardMiniProps, type CardProps, CardSimple, type CardSimpleProps, Footer, type FooterProps, GeoConfigProvider, type GeoConfigProviderProps, Header, type HeaderProps, Legend, type LegendProps, Link, type LinkProps, NASA_BLUE_MARBLE_BASEMAP_STYLE, StacCompareMap, type StacCompareMapProps, StacSingleLayerMap, type StacSingleLayerMapProps, Tag, type TagProps };
|
|
445
|
+
export { Banner, type BannerProps, CARTO_DARK_BASEMAP_STYLE, CARTO_DARK_WITH_LABELS_BASEMAP_STYLE, CARTO_LABELS_LAYER_ID, Card, CardCTA, type CardCTAProps, CardDetailed, type CardDetailedProps, CardMini, type CardMiniProps, type CardProps, CardSimple, type CardSimpleProps, Footer, type FooterProps, GeoConfigProvider, type GeoConfigProviderProps, Header, type HeaderProps, Legend, type LegendProps, Link, type LinkProps, NASA_BLUE_MARBLE_BASEMAP_STYLE, OPEN_FREE_MAP_DARK_BASEMAP_STYLE, OPEN_FREE_MAP_LABELS_LAYER_ID, StacCompareMap, type StacCompareMapProps, StacSingleLayerMap, type StacSingleLayerMapProps, Tag, type TagProps };
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,7 @@ var isArray = (as) => Array.isArray(as);
|
|
|
26
26
|
var isEmptyArray = (as) => isArray(as) && as.length === 0;
|
|
27
27
|
var isNonEmptyArray = (as) => isArray(as) && as.length > 0;
|
|
28
28
|
var getTypedValues = Object.values;
|
|
29
|
+
var getTypedEntries = Object.entries;
|
|
29
30
|
|
|
30
31
|
// src/utils/component-utils.tsx
|
|
31
32
|
var get_external_anchor_props = (isExternal) => isExternal ? { target: "_blank", rel: "noopener noreferrer" } : {};
|
|
@@ -737,43 +738,17 @@ function Tag({
|
|
|
737
738
|
] });
|
|
738
739
|
}
|
|
739
740
|
|
|
741
|
+
// src/geo/GeoConfigProvider.tsx
|
|
742
|
+
import { StacApiProvider } from "@developmentseed/stac-react";
|
|
743
|
+
import { createContext, useContext } from "react";
|
|
744
|
+
|
|
740
745
|
// src/geo/constants.ts
|
|
741
|
-
var NASA_BLUE_MARBLE_BASEMAP_STYLE = {
|
|
742
|
-
version: 8,
|
|
743
|
-
sources: {
|
|
744
|
-
"nasa-blue-marble": {
|
|
745
|
-
type: "raster",
|
|
746
|
-
tiles: [
|
|
747
|
-
"https://gibs.earthdata.nasa.gov/wmts/epsg3857/best/BlueMarble_NextGeneration/default/GoogleMapsCompatible_Level8/{z}/{y}/{x}.jpeg"
|
|
748
|
-
],
|
|
749
|
-
tileSize: 256,
|
|
750
|
-
maxzoom: 8,
|
|
751
|
-
attribution: "Imagery courtesy NASA EOSDIS/GIBS"
|
|
752
|
-
}
|
|
753
|
-
},
|
|
754
|
-
layers: [
|
|
755
|
-
{
|
|
756
|
-
id: "nasa-blue-marble",
|
|
757
|
-
type: "raster",
|
|
758
|
-
source: "nasa-blue-marble"
|
|
759
|
-
}
|
|
760
|
-
]
|
|
761
|
-
};
|
|
762
746
|
var STAC_API_URL = "https://openveda.cloud/api/stac";
|
|
763
747
|
var TITILER_BASE_URL = "https://openveda.cloud/api/raster";
|
|
764
|
-
var DEFAULT_RENDER_PARAMS = {
|
|
765
|
-
assets: ["cog_default"],
|
|
766
|
-
rescale: "0,0.0001",
|
|
767
|
-
resampling: "bilinear",
|
|
768
|
-
colormap_name: "viridis",
|
|
769
|
-
bidx: [1]
|
|
770
|
-
};
|
|
771
748
|
var DEFAULT_TILE_MATRIX_SET = "WebMercatorQuad";
|
|
772
749
|
var STAC_COLORSTOP_RGBA_ARG_COUNT = 4;
|
|
773
750
|
|
|
774
751
|
// src/geo/GeoConfigProvider.tsx
|
|
775
|
-
import { StacApiProvider } from "@developmentseed/stac-react";
|
|
776
|
-
import { createContext, useContext } from "react";
|
|
777
752
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
778
753
|
var GeoConfigContext = createContext(null);
|
|
779
754
|
function useGeoConfig() {
|
|
@@ -792,7 +767,7 @@ function GeoConfigProvider({
|
|
|
792
767
|
// src/geo/Legend/Legend.tsx
|
|
793
768
|
import { Icon as Icon3 } from "@trussworks/react-uswds";
|
|
794
769
|
import { useState as useState3 } from "react";
|
|
795
|
-
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
770
|
+
import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
796
771
|
function Legend({ initialExpanded = false, ...props }) {
|
|
797
772
|
const { title, description, unit, min, max, colorStops, provider, spatialExtent, timeDensity } = props;
|
|
798
773
|
const [isExpanded, setIsExpanded] = useState3(initialExpanded);
|
|
@@ -815,19 +790,21 @@ function Legend({ initialExpanded = false, ...props }) {
|
|
|
815
790
|
}
|
|
816
791
|
)
|
|
817
792
|
] }),
|
|
818
|
-
/* @__PURE__ */
|
|
819
|
-
"div",
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
793
|
+
colorStops && /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
794
|
+
/* @__PURE__ */ jsx15("div", { className: "blocks-legend__gradient-bar", children: /* @__PURE__ */ jsx15(
|
|
795
|
+
"div",
|
|
796
|
+
{
|
|
797
|
+
className: "blocks-legend__gradient",
|
|
798
|
+
style: {
|
|
799
|
+
background: `linear-gradient(to right, ${colorStops.join(", ")})`
|
|
800
|
+
}
|
|
824
801
|
}
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
802
|
+
) }),
|
|
803
|
+
isDefined(min) && isDefined(max) && /* @__PURE__ */ jsxs13("div", { className: "blocks-legend__labels", children: [
|
|
804
|
+
/* @__PURE__ */ jsx15("span", { className: "blocks-legend__min", children: min }),
|
|
805
|
+
/* @__PURE__ */ jsx15("span", { className: "blocks-legend__unit", children: unit }),
|
|
806
|
+
/* @__PURE__ */ jsx15("span", { className: "blocks-legend__max", children: max })
|
|
807
|
+
] })
|
|
831
808
|
] }),
|
|
832
809
|
isExpanded && description && /* @__PURE__ */ jsx15("div", { className: "blocks-legend__description", children: /* @__PURE__ */ jsx15("div", { className: "blocks-legend__description-inner", children: description }) })
|
|
833
810
|
] });
|
|
@@ -850,7 +827,17 @@ function AttributionMapControl({ position = "top-right" }) {
|
|
|
850
827
|
return null;
|
|
851
828
|
}
|
|
852
829
|
|
|
853
|
-
// src/geo/utils/
|
|
830
|
+
// src/geo/utils/stac.formatters.ts
|
|
831
|
+
var formatSpatialExtent = (spatialExtent) => {
|
|
832
|
+
const [minX, minY, maxX, maxY] = spatialExtent?.bbox?.[0] ?? [];
|
|
833
|
+
if (minX === void 0 || minY === void 0 || maxX === void 0 || maxY === void 0)
|
|
834
|
+
return void 0;
|
|
835
|
+
return maxX - minX >= 359 && maxY - minY >= 179 ? "global" : "regional";
|
|
836
|
+
};
|
|
837
|
+
function formatDateToISODatetime(date, isEndOfDay) {
|
|
838
|
+
const datetime = /* @__PURE__ */ new Date(`${date}${isEndOfDay ? "T23:59:59Z" : "T00:00:00Z"}`);
|
|
839
|
+
return datetime.toISOString();
|
|
840
|
+
}
|
|
854
841
|
function formatDateRange(dateRange) {
|
|
855
842
|
const from = /* @__PURE__ */ new Date(`${dateRange.from}T00:00:00Z`);
|
|
856
843
|
const to = /* @__PURE__ */ new Date(`${dateRange.to}T00:00:00Z`);
|
|
@@ -875,6 +862,18 @@ function formatDateRange(dateRange) {
|
|
|
875
862
|
});
|
|
876
863
|
return `${fromStr} \u2013 ${toStr}`;
|
|
877
864
|
}
|
|
865
|
+
var formatRenderPropertiesToQuery = (renderProperties) => {
|
|
866
|
+
const query = new URLSearchParams();
|
|
867
|
+
getTypedEntries(renderProperties).forEach(([key, value]) => {
|
|
868
|
+
if (!isDefined(value)) return;
|
|
869
|
+
if (isArray(value)) {
|
|
870
|
+
value.map((v) => query.append(key, String(v)));
|
|
871
|
+
} else {
|
|
872
|
+
query.append(key, String(value));
|
|
873
|
+
}
|
|
874
|
+
});
|
|
875
|
+
return query.toString();
|
|
876
|
+
};
|
|
878
877
|
|
|
879
878
|
// src/geo/DateChip/DateChip.tsx
|
|
880
879
|
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
@@ -886,43 +885,11 @@ function DateChip({ left, right }) {
|
|
|
886
885
|
// src/geo/hooks/useStacRasterLayer.ts
|
|
887
886
|
import { useCollection } from "@developmentseed/stac-react";
|
|
888
887
|
|
|
889
|
-
// src/geo/hooks/
|
|
888
|
+
// src/geo/hooks/useRasterTiles.ts
|
|
890
889
|
import { useQuery } from "@tanstack/react-query";
|
|
891
890
|
|
|
892
|
-
// src/geo/api/titiler/
|
|
893
|
-
async function
|
|
894
|
-
const response = await fetch(`${tilejsonUrl}?${queryString}`);
|
|
895
|
-
if (!response.ok) {
|
|
896
|
-
const error = { detail: `Failed to fetch tilejson: ${response.statusText}` };
|
|
897
|
-
throw error;
|
|
898
|
-
}
|
|
899
|
-
const tilejson = await response.json();
|
|
900
|
-
if (!tilejson.tiles?.[0]) {
|
|
901
|
-
const error = { detail: "No tile URL found in response" };
|
|
902
|
-
throw error;
|
|
903
|
-
}
|
|
904
|
-
return tilejson.tiles[0];
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
// src/geo/api/titiler/mosaicLinks.ts
|
|
908
|
-
function findTileLink(links) {
|
|
909
|
-
return links.find((link) => link.rel === "tiles") ?? links.at(1) ?? links.at(0) ?? null;
|
|
910
|
-
}
|
|
911
|
-
function buildTilejsonUrl(tileLinkHref, tileMatrixSet) {
|
|
912
|
-
return tileLinkHref.replace("/{tileMatrixSetId}", `/${tileMatrixSet}`);
|
|
913
|
-
}
|
|
914
|
-
function extractTileUrl(registrationResponse, tileMatrixSet) {
|
|
915
|
-
const tileLink = findTileLink(registrationResponse.links);
|
|
916
|
-
if (!tileLink?.href) {
|
|
917
|
-
const error = { detail: "No tile URL found in registration response" };
|
|
918
|
-
throw error;
|
|
919
|
-
}
|
|
920
|
-
const tilejsonUrl = buildTilejsonUrl(tileLink.href, tileMatrixSet);
|
|
921
|
-
return tilejsonUrl;
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
// src/geo/api/titiler/registerMosaic.ts
|
|
925
|
-
async function registerMosaic(request) {
|
|
891
|
+
// src/geo/api/titiler/rasterSearchRegister.ts
|
|
892
|
+
async function rasterSearchRegister(request) {
|
|
926
893
|
const { rasterApiUrl, collectionId, datetime } = request;
|
|
927
894
|
const response = await fetch(`${rasterApiUrl}/searches/register`, {
|
|
928
895
|
method: "POST",
|
|
@@ -939,93 +906,70 @@ async function registerMosaic(request) {
|
|
|
939
906
|
};
|
|
940
907
|
throw error;
|
|
941
908
|
}
|
|
942
|
-
|
|
909
|
+
const responseJson = await response.json();
|
|
910
|
+
return responseJson;
|
|
943
911
|
}
|
|
944
912
|
|
|
945
|
-
// src/geo/api/titiler/
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
const
|
|
955
|
-
if (
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
return params;
|
|
962
|
-
}
|
|
963
|
-
async function fetchMosaicTileUrl(request) {
|
|
964
|
-
const { sourceParams, tileMatrixSet } = request;
|
|
965
|
-
const queryParams = buildQueryParams(sourceParams);
|
|
966
|
-
const queryString = queryParams.toString();
|
|
967
|
-
const registrationResponse = await registerMosaic(request);
|
|
968
|
-
const tilejsonUrl = extractTileUrl(registrationResponse, tileMatrixSet);
|
|
969
|
-
return fetchTilejson(tilejsonUrl, queryString);
|
|
913
|
+
// src/geo/api/titiler/rasterSearchTileJson.ts
|
|
914
|
+
async function rasterSearchTileJson({
|
|
915
|
+
rasterApiUrl,
|
|
916
|
+
searchId,
|
|
917
|
+
renderProperties,
|
|
918
|
+
tileMatrixSet
|
|
919
|
+
}) {
|
|
920
|
+
const tilejsonUrl = `${rasterApiUrl}/searches/${searchId}/${tileMatrixSet}/tilejson.json`;
|
|
921
|
+
const queryString = formatRenderPropertiesToQuery(renderProperties);
|
|
922
|
+
const response = await fetch(`${tilejsonUrl}?${queryString}`);
|
|
923
|
+
if (!response.ok) {
|
|
924
|
+
const error = { detail: `Failed to fetch tilejson: ${response.statusText}` };
|
|
925
|
+
throw error;
|
|
926
|
+
}
|
|
927
|
+
const responseJson = await response.json();
|
|
928
|
+
return responseJson;
|
|
970
929
|
}
|
|
971
930
|
|
|
972
|
-
// src/geo/
|
|
973
|
-
function
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
}
|
|
984
|
-
return "cog_default";
|
|
931
|
+
// src/geo/api/titiler/fetchRasterTileUrl.ts
|
|
932
|
+
async function fetchRasterTileUrl(request) {
|
|
933
|
+
const { collectionId, datetime, rasterApiUrl, renderProperties, tileMatrixSet } = request;
|
|
934
|
+
const { id: searchId } = await rasterSearchRegister({ collectionId, datetime, rasterApiUrl });
|
|
935
|
+
const { tiles } = await rasterSearchTileJson({
|
|
936
|
+
rasterApiUrl,
|
|
937
|
+
searchId,
|
|
938
|
+
renderProperties,
|
|
939
|
+
tileMatrixSet
|
|
940
|
+
});
|
|
941
|
+
return tiles[0];
|
|
985
942
|
}
|
|
986
943
|
|
|
987
|
-
// src/geo/hooks/
|
|
988
|
-
function
|
|
944
|
+
// src/geo/hooks/useRasterTiles.ts
|
|
945
|
+
function useRasterTiles(rasterLayerConfig, collection) {
|
|
989
946
|
const { titilerBaseUrl } = useGeoConfig();
|
|
990
|
-
const {
|
|
991
|
-
const datetime = dateRange.from === dateRange.to ? dateRange.from : `${dateRange.from}/${dateRange.to}`;
|
|
992
|
-
const assetName = collection ? resolveAssetName(collection) : DEFAULT_RENDER_PARAMS.assets[0];
|
|
993
|
-
const colormapName = collection?.renders?.dashboard?.colormap_name ?? DEFAULT_RENDER_PARAMS.colormap_name;
|
|
994
|
-
const rescale = collection?.renders?.dashboard?.rescale?.join(",") ?? DEFAULT_RENDER_PARAMS.rescale;
|
|
995
|
-
const resampling = collection?.renders?.dashboard?.resampling ?? DEFAULT_RENDER_PARAMS.resampling;
|
|
996
|
-
const request = {
|
|
997
|
-
rasterApiUrl: titilerBaseUrl,
|
|
947
|
+
const {
|
|
998
948
|
collectionId,
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
resampling
|
|
1006
|
-
},
|
|
1007
|
-
tileMatrixSet
|
|
1008
|
-
};
|
|
949
|
+
collectionAssetId,
|
|
950
|
+
dateRange,
|
|
951
|
+
tileMatrixSet = DEFAULT_TILE_MATRIX_SET
|
|
952
|
+
} = rasterLayerConfig;
|
|
953
|
+
const datetime = `${formatDateToISODatetime(dateRange.from)}/${formatDateToISODatetime(dateRange.to, true)}`;
|
|
954
|
+
const renderProperties = collection?.renders?.[collectionAssetId] ?? {};
|
|
1009
955
|
return useQuery({
|
|
1010
|
-
queryKey: [collectionId,
|
|
1011
|
-
queryFn: () =>
|
|
956
|
+
queryKey: [collectionId, collectionAssetId, datetime, titilerBaseUrl],
|
|
957
|
+
queryFn: () => fetchRasterTileUrl({
|
|
958
|
+
rasterApiUrl: titilerBaseUrl,
|
|
959
|
+
collectionId,
|
|
960
|
+
datetime,
|
|
961
|
+
renderProperties,
|
|
962
|
+
tileMatrixSet
|
|
963
|
+
}),
|
|
1012
964
|
staleTime: 30 * 60 * 1e3,
|
|
1013
965
|
gcTime: 60 * 60 * 1e3,
|
|
1014
|
-
enabled:
|
|
966
|
+
enabled: isDefined(collection) && !isEmptyObject(collection) && !isEmptyObject(renderProperties)
|
|
1015
967
|
});
|
|
1016
968
|
}
|
|
1017
969
|
|
|
1018
970
|
// src/geo/hooks/useStacRasterLegend.ts
|
|
1019
971
|
import { useQuery as useQuery2 } from "@tanstack/react-query";
|
|
1020
972
|
|
|
1021
|
-
// src/geo/utils/stac.formatters.ts
|
|
1022
|
-
var formatSpatialExtent = (spatialExtent) => {
|
|
1023
|
-
const [minX, minY, maxX, maxY] = spatialExtent?.bbox?.[0] ?? [];
|
|
1024
|
-
if (minX === void 0 || minY === void 0 || maxX === void 0 || maxY === void 0)
|
|
1025
|
-
return void 0;
|
|
1026
|
-
return maxX - minX >= 359 && maxY - minY >= 179 ? "global" : "regional";
|
|
1027
|
-
};
|
|
1028
|
-
|
|
1029
973
|
// src/geo/utils/stac.typeguards.ts
|
|
1030
974
|
var isRgbaColorStopMap = (value) => {
|
|
1031
975
|
return !isNil(value) && isObject(value) && !isEmptyObject(value) && getTypedValues(value).every(
|
|
@@ -1034,53 +978,58 @@ var isRgbaColorStopMap = (value) => {
|
|
|
1034
978
|
};
|
|
1035
979
|
|
|
1036
980
|
// src/geo/utils/extractLegendProps.ts
|
|
1037
|
-
function extractLegendProps(collection, colorStopMap) {
|
|
1038
|
-
const rescale = collection.renders?.
|
|
1039
|
-
|
|
1040
|
-
if (
|
|
1041
|
-
|
|
981
|
+
function extractLegendProps(collection, collectionAssetId, colorStopMap) {
|
|
982
|
+
const rescale = collection.renders?.[collectionAssetId]?.rescale?.[0];
|
|
983
|
+
let colorStops;
|
|
984
|
+
if (isRgbaColorStopMap(colorStopMap)) {
|
|
985
|
+
colorStops = getTypedValues(colorStopMap).map((rgba) => `rgba(${rgba.join(",")})`);
|
|
986
|
+
}
|
|
1042
987
|
const title = collection.title;
|
|
1043
988
|
const description = collection.description;
|
|
1044
989
|
const provider = collection.providers?.[0]?.name;
|
|
1045
990
|
const timeDensity = collection.properties?.["dashboard:time_density"];
|
|
1046
991
|
const spatialExtent = formatSpatialExtent(collection.extent?.spatial);
|
|
1047
|
-
const
|
|
1048
|
-
const unit = collection.item_assets?.[assetName]?.["raster:bands"]?.[0]?.unit;
|
|
992
|
+
const unit = collection.item_assets?.[collectionAssetId]?.["raster:bands"]?.[0]?.unit;
|
|
1049
993
|
return {
|
|
1050
994
|
type: "gradient",
|
|
1051
|
-
...
|
|
1052
|
-
...
|
|
1053
|
-
|
|
1054
|
-
max
|
|
1055
|
-
|
|
1056
|
-
...
|
|
1057
|
-
...
|
|
1058
|
-
...
|
|
1059
|
-
...
|
|
995
|
+
...{ title },
|
|
996
|
+
...{ description },
|
|
997
|
+
// TODO 271: existing datasets for use do not include rescale, are we certain this is required
|
|
998
|
+
// is there another way to determine min and max
|
|
999
|
+
...isDefined(rescale) ? { min: rescale[0] } : {},
|
|
1000
|
+
...isDefined(rescale) ? { max: rescale[1] } : {},
|
|
1001
|
+
...{ colorStops },
|
|
1002
|
+
...{ provider },
|
|
1003
|
+
...{ timeDensity },
|
|
1004
|
+
...{ spatialExtent },
|
|
1005
|
+
...{ unit }
|
|
1060
1006
|
};
|
|
1061
1007
|
}
|
|
1062
1008
|
|
|
1063
1009
|
// src/geo/hooks/useStacRasterLegend.ts
|
|
1064
|
-
function useStacRasterLegend(collection) {
|
|
1010
|
+
function useStacRasterLegend(collectionAssetId, collection, options) {
|
|
1065
1011
|
const { titilerBaseUrl } = useGeoConfig();
|
|
1012
|
+
const { hideLegend } = options ?? {};
|
|
1066
1013
|
const query = useQuery2({
|
|
1067
|
-
queryKey: ["legend", collection, titilerBaseUrl],
|
|
1014
|
+
queryKey: ["legend", collection, collectionAssetId, titilerBaseUrl],
|
|
1068
1015
|
queryFn: async () => {
|
|
1069
1016
|
if (!collection) return null;
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1017
|
+
let colormap;
|
|
1018
|
+
const colormapName = collection?.renders?.[collectionAssetId]?.colormap_name;
|
|
1019
|
+
if (colormapName) {
|
|
1020
|
+
const response = await fetch(`${titilerBaseUrl}/colorMaps/${colormapName}`);
|
|
1021
|
+
if (!response.ok) {
|
|
1022
|
+
const error = {
|
|
1023
|
+
detail: `Colormap "${colormapName}" not found (HTTP ${response.status})`,
|
|
1024
|
+
status: response.status
|
|
1025
|
+
};
|
|
1026
|
+
throw error;
|
|
1027
|
+
}
|
|
1028
|
+
colormap = await response.json();
|
|
1079
1029
|
}
|
|
1080
|
-
|
|
1081
|
-
return extractLegendProps(collection, colorMap);
|
|
1030
|
+
return extractLegendProps(collection, collectionAssetId, colormap);
|
|
1082
1031
|
},
|
|
1083
|
-
enabled: !!collection
|
|
1032
|
+
enabled: !!collection && !hideLegend
|
|
1084
1033
|
});
|
|
1085
1034
|
return {
|
|
1086
1035
|
legend: query.data ?? null,
|
|
@@ -1091,7 +1040,7 @@ function useStacRasterLegend(collection) {
|
|
|
1091
1040
|
|
|
1092
1041
|
// src/geo/hooks/useStacRasterLayer.ts
|
|
1093
1042
|
function useStacRasterLayer(rasterLayerConfig) {
|
|
1094
|
-
const { collectionId } = rasterLayerConfig;
|
|
1043
|
+
const { collectionId, collectionAssetId, hideLegend } = rasterLayerConfig;
|
|
1095
1044
|
const {
|
|
1096
1045
|
collection,
|
|
1097
1046
|
isLoading: isLoadingCollection,
|
|
@@ -1102,12 +1051,12 @@ function useStacRasterLayer(rasterLayerConfig) {
|
|
|
1102
1051
|
data: tiles,
|
|
1103
1052
|
isLoading: tilesetLoading,
|
|
1104
1053
|
error: tilesetError
|
|
1105
|
-
} =
|
|
1054
|
+
} = useRasterTiles(rasterLayerConfig, extCollection);
|
|
1106
1055
|
const {
|
|
1107
1056
|
legend,
|
|
1108
1057
|
isLoading: isLoadingLegend,
|
|
1109
1058
|
error: legendError
|
|
1110
|
-
} = useStacRasterLegend(extCollection);
|
|
1059
|
+
} = useStacRasterLegend(collectionAssetId, extCollection, { hideLegend });
|
|
1111
1060
|
return {
|
|
1112
1061
|
mapSource: {
|
|
1113
1062
|
tiles: tiles ?? null
|
|
@@ -1118,6 +1067,53 @@ function useStacRasterLayer(rasterLayerConfig) {
|
|
|
1118
1067
|
};
|
|
1119
1068
|
}
|
|
1120
1069
|
|
|
1070
|
+
// src/geo/stac.basemaps.ts
|
|
1071
|
+
var createRasterBasemapStyle = ({
|
|
1072
|
+
id,
|
|
1073
|
+
tiles,
|
|
1074
|
+
maxzoom,
|
|
1075
|
+
attribution
|
|
1076
|
+
}) => ({
|
|
1077
|
+
version: 8,
|
|
1078
|
+
sources: {
|
|
1079
|
+
[id]: {
|
|
1080
|
+
type: "raster",
|
|
1081
|
+
tiles,
|
|
1082
|
+
tileSize: 256,
|
|
1083
|
+
maxzoom,
|
|
1084
|
+
attribution
|
|
1085
|
+
}
|
|
1086
|
+
},
|
|
1087
|
+
layers: [{ id, type: "raster", source: id }]
|
|
1088
|
+
});
|
|
1089
|
+
var NASA_BLUE_MARBLE_BASEMAP_STYLE = createRasterBasemapStyle({
|
|
1090
|
+
id: "nasa-blue-marble",
|
|
1091
|
+
tiles: [
|
|
1092
|
+
"https://gibs.earthdata.nasa.gov/wmts/epsg3857/best/BlueMarble_NextGeneration/default/GoogleMapsCompatible_Level8/{z}/{y}/{x}.jpeg"
|
|
1093
|
+
],
|
|
1094
|
+
maxzoom: 8,
|
|
1095
|
+
attribution: "Imagery courtesy NASA EOSDIS/GIBS"
|
|
1096
|
+
});
|
|
1097
|
+
var CARTO_DARK_BASEMAP_STYLE = createRasterBasemapStyle({
|
|
1098
|
+
id: "carto-dark",
|
|
1099
|
+
tiles: [
|
|
1100
|
+
"https://a.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png",
|
|
1101
|
+
"https://b.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png",
|
|
1102
|
+
"https://c.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png",
|
|
1103
|
+
"https://d.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png"
|
|
1104
|
+
],
|
|
1105
|
+
maxzoom: 19,
|
|
1106
|
+
attribution: "Map tiles by Carto, under CC BY 3.0. Data by OpenStreetMap, under ODbL."
|
|
1107
|
+
});
|
|
1108
|
+
var CARTO_DARK_WITH_LABELS_BASEMAP_STYLE = "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json";
|
|
1109
|
+
var CARTO_LABELS_LAYER_ID = "waterway_label";
|
|
1110
|
+
var OPEN_FREE_MAP_DARK_BASEMAP_STYLE = "https://tiles.openfreemap.org/styles/dark";
|
|
1111
|
+
var OPEN_FREE_MAP_LABELS_LAYER_ID = "highway_name_other";
|
|
1112
|
+
var BASEMAP_LABEL_LAYER_IDS = {
|
|
1113
|
+
[CARTO_DARK_WITH_LABELS_BASEMAP_STYLE]: CARTO_LABELS_LAYER_ID,
|
|
1114
|
+
[OPEN_FREE_MAP_DARK_BASEMAP_STYLE]: OPEN_FREE_MAP_LABELS_LAYER_ID
|
|
1115
|
+
};
|
|
1116
|
+
|
|
1121
1117
|
// src/geo/StacCompareMap/StacCompareMap.tsx
|
|
1122
1118
|
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1123
1119
|
var MAP_PANEL_STYLE = {
|
|
@@ -1127,12 +1123,13 @@ var MAP_PANEL_STYLE = {
|
|
|
1127
1123
|
width: "100%"
|
|
1128
1124
|
};
|
|
1129
1125
|
function StacCompareMap({
|
|
1130
|
-
baseMapStyle,
|
|
1126
|
+
baseMapStyle = CARTO_DARK_WITH_LABELS_BASEMAP_STYLE,
|
|
1131
1127
|
initialViewState,
|
|
1132
1128
|
leftLayerConfig,
|
|
1133
1129
|
rightLayerConfig,
|
|
1134
1130
|
className
|
|
1135
1131
|
}) {
|
|
1132
|
+
const resolvedBeforeLayerId = typeof baseMapStyle === "string" ? BASEMAP_LABEL_LAYER_IDS[baseMapStyle] : void 0;
|
|
1136
1133
|
const instanceId = useId();
|
|
1137
1134
|
const leftMapRef = useRef3(null);
|
|
1138
1135
|
const rightMapRef = useRef3(null);
|
|
@@ -1174,7 +1171,7 @@ function StacCompareMap({
|
|
|
1174
1171
|
};
|
|
1175
1172
|
}, []);
|
|
1176
1173
|
const mapProps = {
|
|
1177
|
-
|
|
1174
|
+
mapStyle: baseMapStyle,
|
|
1178
1175
|
...initialViewState && { initialViewState },
|
|
1179
1176
|
style: MAP_PANEL_STYLE
|
|
1180
1177
|
};
|
|
@@ -1189,7 +1186,14 @@ function StacCompareMap({
|
|
|
1189
1186
|
children: [
|
|
1190
1187
|
/* @__PURE__ */ jsx17(AttributionMapControl, {}),
|
|
1191
1188
|
/* @__PURE__ */ jsx17(NavigationControl, { position: "top-left", showCompass: false }),
|
|
1192
|
-
left.mapSource.tiles && /* @__PURE__ */ jsx17(Source, { id: leftSourceId, type: "raster", tiles: [left.mapSource.tiles], children: /* @__PURE__ */ jsx17(
|
|
1189
|
+
left.mapSource.tiles && /* @__PURE__ */ jsx17(Source, { id: leftSourceId, type: "raster", tiles: [left.mapSource.tiles], children: /* @__PURE__ */ jsx17(
|
|
1190
|
+
Layer,
|
|
1191
|
+
{
|
|
1192
|
+
id: leftLayerId,
|
|
1193
|
+
type: "raster",
|
|
1194
|
+
...resolvedBeforeLayerId && { beforeId: resolvedBeforeLayerId }
|
|
1195
|
+
}
|
|
1196
|
+
) })
|
|
1193
1197
|
]
|
|
1194
1198
|
}
|
|
1195
1199
|
),
|
|
@@ -1202,7 +1206,14 @@ function StacCompareMap({
|
|
|
1202
1206
|
onLoad: () => setRightMapLoaded(true),
|
|
1203
1207
|
children: [
|
|
1204
1208
|
/* @__PURE__ */ jsx17(AttributionMapControl, {}),
|
|
1205
|
-
right.mapSource.tiles && /* @__PURE__ */ jsx17(Source, { id: rightSourceId, type: "raster", tiles: [right.mapSource.tiles], children: /* @__PURE__ */ jsx17(
|
|
1209
|
+
right.mapSource.tiles && /* @__PURE__ */ jsx17(Source, { id: rightSourceId, type: "raster", tiles: [right.mapSource.tiles], children: /* @__PURE__ */ jsx17(
|
|
1210
|
+
Layer,
|
|
1211
|
+
{
|
|
1212
|
+
id: rightLayerId,
|
|
1213
|
+
type: "raster",
|
|
1214
|
+
...resolvedBeforeLayerId && { beforeId: resolvedBeforeLayerId }
|
|
1215
|
+
}
|
|
1216
|
+
) })
|
|
1206
1217
|
]
|
|
1207
1218
|
}
|
|
1208
1219
|
),
|
|
@@ -1222,10 +1233,11 @@ import {
|
|
|
1222
1233
|
} from "react-map-gl/maplibre";
|
|
1223
1234
|
import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1224
1235
|
function StacSingleLayerMap({
|
|
1225
|
-
baseMapStyle =
|
|
1236
|
+
baseMapStyle = CARTO_DARK_WITH_LABELS_BASEMAP_STYLE,
|
|
1226
1237
|
initialViewState,
|
|
1227
1238
|
layerConfig
|
|
1228
1239
|
}) {
|
|
1240
|
+
const resolvedBeforeLayerId = typeof baseMapStyle === "string" ? BASEMAP_LABEL_LAYER_IDS[baseMapStyle] : void 0;
|
|
1229
1241
|
const instanceId = useId2();
|
|
1230
1242
|
const sourceId = `${layerConfig.collectionId}-raster-source-${instanceId}`;
|
|
1231
1243
|
const layerId = `${layerConfig.collectionId}-raster-layer-${instanceId}`;
|
|
@@ -1241,7 +1253,14 @@ function StacSingleLayerMap({
|
|
|
1241
1253
|
children: [
|
|
1242
1254
|
/* @__PURE__ */ jsx18(AttributionMapControl, {}),
|
|
1243
1255
|
/* @__PURE__ */ jsx18(NavigationControl2, { position: "top-left", showCompass: false }),
|
|
1244
|
-
mapSource.tiles && /* @__PURE__ */ jsx18(Source2, { id: sourceId, type: "raster", tiles: [mapSource.tiles], children: /* @__PURE__ */ jsx18(
|
|
1256
|
+
mapSource.tiles && /* @__PURE__ */ jsx18(Source2, { id: sourceId, type: "raster", tiles: [mapSource.tiles], children: /* @__PURE__ */ jsx18(
|
|
1257
|
+
Layer2,
|
|
1258
|
+
{
|
|
1259
|
+
id: layerId,
|
|
1260
|
+
type: "raster",
|
|
1261
|
+
...resolvedBeforeLayerId && { beforeId: resolvedBeforeLayerId }
|
|
1262
|
+
}
|
|
1263
|
+
) })
|
|
1245
1264
|
]
|
|
1246
1265
|
}
|
|
1247
1266
|
),
|
|
@@ -1251,6 +1270,9 @@ function StacSingleLayerMap({
|
|
|
1251
1270
|
}
|
|
1252
1271
|
export {
|
|
1253
1272
|
Banner,
|
|
1273
|
+
CARTO_DARK_BASEMAP_STYLE,
|
|
1274
|
+
CARTO_DARK_WITH_LABELS_BASEMAP_STYLE,
|
|
1275
|
+
CARTO_LABELS_LAYER_ID,
|
|
1254
1276
|
Card,
|
|
1255
1277
|
CardCTA,
|
|
1256
1278
|
CardDetailed,
|
|
@@ -1262,6 +1284,8 @@ export {
|
|
|
1262
1284
|
Legend,
|
|
1263
1285
|
Link3 as Link,
|
|
1264
1286
|
NASA_BLUE_MARBLE_BASEMAP_STYLE,
|
|
1287
|
+
OPEN_FREE_MAP_DARK_BASEMAP_STYLE,
|
|
1288
|
+
OPEN_FREE_MAP_LABELS_LAYER_ID,
|
|
1265
1289
|
StacCompareMap,
|
|
1266
1290
|
StacSingleLayerMap,
|
|
1267
1291
|
Tag
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamimpact/veda-ui-blocks",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.12",
|
|
4
4
|
"description": "UI component library for VEDA-based portals, built on USWDS and React",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"storybook": "^10.2.17",
|
|
68
68
|
"tsup": "^8.5.1",
|
|
69
69
|
"typescript": "5.9.3",
|
|
70
|
-
"vitest": "^4.0
|
|
70
|
+
"vitest": "^4.1.0"
|
|
71
71
|
},
|
|
72
72
|
"scripts": {
|
|
73
73
|
"build": "tsup src/index.ts --format esm --dts && pnpm run build:css",
|