Skip to content

Commit 8277da3

Browse files
authored
1 parent a471d03 commit 8277da3

File tree

1 file changed

+120
-42
lines changed

1 file changed

+120
-42
lines changed

src/components/children.tsx

Lines changed: 120 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1-
import { Card, HStack, Icon, Link, Stack, Text } from "@chakra-ui/react";
2-
import type { ReactNode } from "react";
1+
import {
2+
Card,
3+
Checkbox,
4+
HStack,
5+
Icon,
6+
Link,
7+
Stack,
8+
Text,
9+
} from "@chakra-ui/react";
10+
import { useEffect, useState, type ReactNode } from "react";
311
import { LuFolderPlus, LuFolderSearch } from "react-icons/lu";
412
import { MarkdownHooks } from "react-markdown";
513
import type { StacCatalog, StacCollection } from "stac-ts";
@@ -8,6 +16,8 @@ import { useChildren } from "../hooks/stac-value";
816
import type { SetHref } from "../types/app";
917
import { CollectionSearch } from "./search/collection";
1018
import Section from "./section";
19+
import { useMap } from "react-map-gl/maplibre";
20+
import type { BBox } from "geojson";
1121

1222
export function Children({
1323
value,
@@ -18,51 +28,93 @@ export function Children({
1828
}) {
1929
const { collections } = useStacMap();
2030
const children = useChildren(value, !!collections);
31+
const { map } = useMap();
2132
const selfHref = value?.links?.find((link) => link.rel === "self")?.href;
33+
const [mapBbox, setMapBbox] = useState<BBox>();
34+
const [filterByViewport, setFilterByViewport] = useState(true);
35+
const [filteredCollections, setFilteredCollections] = useState(collections);
36+
37+
useEffect(() => {
38+
if (map) {
39+
map.on("moveend", () => {
40+
if (map) {
41+
setMapBbox(map.getBounds().toArray().flat() as BBox);
42+
}
43+
});
44+
}
45+
}, [map]);
46+
47+
useEffect(() => {
48+
if (filterByViewport && mapBbox) {
49+
setFilteredCollections(
50+
collections?.filter((collection) =>
51+
isCollectionInBbox(collection, mapBbox),
52+
),
53+
);
54+
} else {
55+
setFilteredCollections(collections);
56+
}
57+
}, [collections, filterByViewport, mapBbox]);
2258

2359
return (
2460
<>
25-
{collections && collections?.length > 0 && (
26-
<>
27-
<Section
28-
title={
29-
<HStack>
30-
<Icon>
31-
<LuFolderSearch></LuFolderSearch>
32-
</Icon>{" "}
33-
Collection search
34-
</HStack>
35-
}
36-
>
37-
<CollectionSearch
38-
href={selfHref}
39-
setHref={setHref}
40-
collections={collections}
41-
></CollectionSearch>
42-
</Section>
61+
{collections &&
62+
filteredCollections &&
63+
filteredCollections?.length > 0 && (
64+
<>
65+
<Section
66+
title={
67+
<HStack>
68+
<Icon>
69+
<LuFolderSearch></LuFolderSearch>
70+
</Icon>{" "}
71+
Collection search
72+
</HStack>
73+
}
74+
>
75+
<CollectionSearch
76+
href={selfHref}
77+
setHref={setHref}
78+
collections={filteredCollections}
79+
></CollectionSearch>
80+
</Section>
4381

44-
<Section
45-
title={
46-
<HStack>
47-
<Icon>
48-
<LuFolderPlus></LuFolderPlus>
49-
</Icon>{" "}
50-
Collections ({collections.length})
51-
</HStack>
52-
}
53-
>
54-
<Stack>
55-
{collections.map((collection) => (
56-
<ChildCard
57-
child={collection}
58-
setHref={setHref}
59-
key={"collection-" + collection.id}
60-
></ChildCard>
61-
))}
62-
</Stack>
63-
</Section>
64-
</>
65-
)}
82+
<Section
83+
title={
84+
<HStack>
85+
<Icon>
86+
<LuFolderPlus></LuFolderPlus>
87+
</Icon>{" "}
88+
Collections (
89+
{(filterByViewport &&
90+
filteredCollections.length + "/" + collections.length) ||
91+
collections.length}
92+
)
93+
</HStack>
94+
}
95+
>
96+
<Stack>
97+
<Checkbox.Root
98+
mb={2}
99+
size={"sm"}
100+
checked={filterByViewport}
101+
onCheckedChange={(e) => setFilterByViewport(!!e.checked)}
102+
>
103+
<Checkbox.HiddenInput></Checkbox.HiddenInput>
104+
<Checkbox.Control></Checkbox.Control>
105+
<Checkbox.Label>Filter by viewport</Checkbox.Label>
106+
</Checkbox.Root>
107+
{filteredCollections.map((collection) => (
108+
<ChildCard
109+
child={collection}
110+
setHref={setHref}
111+
key={"collection-" + collection.id}
112+
></ChildCard>
113+
))}
114+
</Stack>
115+
</Section>
116+
</>
117+
)}
66118

67119
{children && children.length > 0 && (
68120
<Section title="Children">
@@ -114,3 +166,29 @@ export function ChildCard({
114166
</Card.Root>
115167
);
116168
}
169+
170+
function isCollectionInBbox(collection: StacCollection, bbox: BBox) {
171+
if (bbox[2] - bbox[0] >= 360) {
172+
// A global bbox always contains every collection
173+
return true;
174+
}
175+
const collectionBbox = collection?.extent?.spatial?.bbox?.[0];
176+
if (collectionBbox) {
177+
return (
178+
!(
179+
collectionBbox[0] < bbox[0] &&
180+
collectionBbox[1] < bbox[1] &&
181+
collectionBbox[2] > bbox[2] &&
182+
collectionBbox[3] > bbox[3]
183+
) &&
184+
!(
185+
collectionBbox[0] > bbox[2] ||
186+
collectionBbox[1] > bbox[3] ||
187+
collectionBbox[2] < bbox[0] ||
188+
collectionBbox[3] < bbox[1]
189+
)
190+
);
191+
} else {
192+
return false;
193+
}
194+
}

0 commit comments

Comments
 (0)