From 32ee30fe19dad3f4ef16cd637362abc04df5d641 Mon Sep 17 00:00:00 2001 From: Kenneth Seals-Nutt Date: Tue, 17 Mar 2026 15:51:57 -0400 Subject: [PATCH 1/5] FIX: resolve stability of element visibility detection adds more logic to cleanup components in the hooks #169 --- src/hooks/useElementIsVisible.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/hooks/useElementIsVisible.ts b/src/hooks/useElementIsVisible.ts index 9369af4..82edaa7 100644 --- a/src/hooks/useElementIsVisible.ts +++ b/src/hooks/useElementIsVisible.ts @@ -7,13 +7,15 @@ type Options = { export default function useElementIsVisible(ref: RefObject, { persist, rootMargin = '0px' }: Options = {}) { const [isIntersecting, setIsIntersecting] = useState(false); + useEffect(() => { + let observer: IntersectionObserver | undefined; const timer = setTimeout(() => { - const observer = new IntersectionObserver( + const createdObserver = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { if (persist) { - observer.disconnect(); + createdObserver.disconnect(); } setIsIntersecting(true); return; @@ -25,21 +27,20 @@ export default function useElementIsVisible(ref: RefObject, { persist, }, { rootMargin }, ); + observer = createdObserver; const { current } = ref; if (current) { - observer.observe(current); + createdObserver.observe(current); } - return () => { - if (ref.current) { - observer.unobserve(ref.current); - } - }; }, 200); return () => { clearTimeout(timer); + if (observer) { + observer.disconnect(); + } }; - }); + }, [persist, ref, rootMargin]); return isIntersecting; } From 4acf1de1cc7eb3100c3f6943b1287429771d1a48 Mon Sep 17 00:00:00 2001 From: Kenneth Seals-Nutt Date: Thu, 19 Mar 2026 07:15:23 -0400 Subject: [PATCH 2/5] FEAT: support Search Suggestions for collection browsing --- .gitignore | 1 + package-lock.json | 102 +++++----- package.json | 10 +- .../CollectionLayout/CollectionLayout.tsx | 2 +- .../StoriesAPICollection.tsx | 22 +- .../UI/CardsBrowser/CardsBrowser.styles.ts | 192 +++++++++++++++++- .../UI/CardsBrowser/CardsBrowser.tsx | 3 +- .../UI/CardsBrowser/CardsBrowser.types.ts | 24 +++ .../CardsBrowserInputSuggestions.tsx | 62 ++++++ .../CardsBrowserLandingSuggestions.tsx | 67 ++++++ .../UI/CardsBrowser/CardsBrowserSearch.tsx | 103 ++++++++-- src/configs/localizationConfig.ts | 16 ++ src/hooks/index.ts | 1 + src/hooks/useCardsBrowserSearch.ts | 188 +++++++++++++++++ src/state/collectionStore.test.ts | 57 ++++++ src/state/collectionStore.ts | 57 +++++- src/state/searchStore.test.ts | 120 +++++++++++ src/state/searchStore.ts | 113 ++++++++++- src/types.ts | 18 ++ src/utils/searchFacetUtils.test.ts | 31 +++ src/utils/searchFacetUtils.ts | 51 +++++ src/utils/searchSuggestionUtils.ts | 8 + 22 files changed, 1167 insertions(+), 81 deletions(-) create mode 100644 src/components/UI/CardsBrowser/CardsBrowserInputSuggestions.tsx create mode 100644 src/components/UI/CardsBrowser/CardsBrowserLandingSuggestions.tsx create mode 100644 src/hooks/useCardsBrowserSearch.ts create mode 100644 src/state/collectionStore.test.ts create mode 100644 src/utils/searchFacetUtils.test.ts create mode 100644 src/utils/searchSuggestionUtils.ts diff --git a/.gitignore b/.gitignore index 8f91cd5..bbd3748 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ # dependencies node_modules yarn.lock +.npmrc # builds build diff --git a/package-lock.json b/package-lock.json index 3fee8f8..b3dd4af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,19 @@ { "name": "react-stories-api", - "version": "1.0.0-dev-54", + "version": "1.0.0-dev-55", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "react-stories-api", - "version": "1.0.0-dev-54", + "version": "1.0.0-dev-55", "license": "MIT", "dependencies": { "@fontsource/roboto": "^5.2.10", "@mui/stylis-plugin-rtl": "^7.3.8", "deck.gl": "^9.2.11", "lodash.debounce": "^4.0.8", - "maplibre-gl": "^5.19.0", + "maplibre-gl": "^5.20.2", "react-countup": "^6.5.3", "react-if": "^4.1.6", "react-map-gl": "^8.1.0", @@ -28,7 +28,7 @@ "swiper": "^11.2.10" }, "devDependencies": { - "@babel/preset-env": "^7.29.0", + "@babel/preset-env": "^7.29.2", "@babel/preset-react": "^7.28.5", "@babel/preset-typescript": "^7.28.5", "@chromatic-com/storybook": "^4.1.3", @@ -72,7 +72,7 @@ "react-dom": "^18.3.1", "relative-deps": "^1.0.7", "rollup": "^4.59.0", - "rollup-plugin-dts": "^6.3.0", + "rollup-plugin-dts": "^6.4.0", "rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-postcss": "^4.0.2", "standard-version": "^9.5.0", @@ -84,7 +84,7 @@ "peerDependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", - "@mui/icons-material": "^6.4.8", + "@mui/icons-material": "^6.5.0", "@mui/lab": "^6.0.1-beta.36", "@mui/material": "^6.5.0", "html-react-parser": "^5.2.17", @@ -1870,9 +1870,9 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.0.tgz", - "integrity": "sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.2.tgz", + "integrity": "sha512-DYD23veRYGvBFhcTY1iUvJnDNpuqNd/BzBwCvzOTKUnJjKg5kpUBh3/u9585Agdkgj+QuygG7jLfOPWMa2KVNw==", "dev": true, "license": "MIT", "dependencies": { @@ -4677,6 +4677,17 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -5107,19 +5118,6 @@ "@luma.gl/core": "~9.2.0" } }, - "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==", - "license": "ISC", - "dependencies": { - "get-stream": "^6.0.1", - "minimist": "^1.2.6" - }, - "bin": { - "geojson-rewind": "geojson-rewind" - } - }, "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", @@ -5177,9 +5175,9 @@ "license": "ISC" }, "node_modules/@maplibre/maplibre-gl-style-spec": { - "version": "24.6.0", - "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-24.6.0.tgz", - "integrity": "sha512-+lxMYE+DvInshwVrqSQ3CkW9YRwVlRXeDzfthVOa1c9pwK5d7YgCwhgFwlSmjJLvTXn4gL8EvPUGT620sk2Pzg==", + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-24.7.0.tgz", + "integrity": "sha512-Ed7rcKYU5iELfablg9Mj+TVCsXsPBgdMyXPRAxb2v7oWg9YJnpQdZ5msDs1LESu/mtXy3Z48Vdppv2t/x5kAhw==", "license": "ISC", "dependencies": { "@mapbox/jsonlint-lines-primitives": "~2.0.2", @@ -5197,9 +5195,9 @@ } }, "node_modules/@maplibre/mlt": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@maplibre/mlt/-/mlt-1.1.6.tgz", - "integrity": "sha512-rgtY3x65lrrfXycLf6/T22ZnjTg5WgIOsptOIoCaMZy4O4UAKTyZlYY0h6v8le721pTptF94U65yMDQkug+URw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@maplibre/mlt/-/mlt-1.1.7.tgz", + "integrity": "sha512-HZSsXrgn2V6T3o0qklMwKERfKaAxjO8shmiFnVygCtXTg4SPKWVX+U99RkvxUfCsjYBEcT4ltor8lSlBSCca7Q==", "license": "(MIT OR Apache-2.0)", "dependencies": { "@mapbox/point-geometry": "^1.1.0" @@ -5392,9 +5390,9 @@ } }, "node_modules/@mui/icons-material": { - "version": "6.4.8", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.4.8.tgz", - "integrity": "sha512-LKGWiLWRyoOw3dWxZQ+lV//mK+4DVTTAiLd2ljmJdD6XV0rDB8JFKjRD9nyn9cJAU5XgWnii7ZR3c93ttUnMKg==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.5.0.tgz", + "integrity": "sha512-VPuPqXqbBPlcVSA0BmnoE4knW4/xG6Thazo8vCLWkOKusko6DtwFV6B665MMWJ9j0KFohTIf3yx2zYtYacvG1g==", "license": "MIT", "peer": true, "dependencies": { @@ -5408,7 +5406,7 @@ "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@mui/material": "^6.4.8", + "@mui/material": "^6.5.0", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, @@ -15588,6 +15586,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -20352,24 +20351,22 @@ } }, "node_modules/maplibre-gl": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.19.0.tgz", - "integrity": "sha512-REhYUN8gNP3HlcIZS6QU2uy8iovl31cXsrNDkCcqWSQbCkcpdYLczqDz5PVIwNH42UQNyvukjes/RoHPDrOUmQ==", + "version": "5.20.2", + "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.20.2.tgz", + "integrity": "sha512-0UzMWOe+GZmIUmOA99yTI1vRh15YcGnHxADVB2s+JF3etpjj2/MBCqbPEuu4BP9mLsJWJcpHH0Nzr9uuimmbuQ==", "license": "BSD-3-Clause", "dependencies": { - "@mapbox/geojson-rewind": "^0.5.2", "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/point-geometry": "^1.1.0", "@mapbox/tiny-sdf": "^2.0.7", "@mapbox/unitbezier": "^0.0.1", "@mapbox/vector-tile": "^2.0.4", "@mapbox/whoots-js": "^3.1.0", - "@maplibre/geojson-vt": "^5.0.4", - "@maplibre/maplibre-gl-style-spec": "^24.4.1", - "@maplibre/mlt": "^1.1.6", - "@maplibre/vt-pbf": "^4.2.1", + "@maplibre/geojson-vt": "^6.0.3", + "@maplibre/maplibre-gl-style-spec": "^24.7.0", + "@maplibre/mlt": "^1.1.7", + "@maplibre/vt-pbf": "^4.3.0", "@types/geojson": "^7946.0.16", - "@types/supercluster": "^7.1.3", "earcut": "^3.0.2", "gl-matrix": "^3.4.4", "kdbush": "^4.0.2", @@ -20377,7 +20374,6 @@ "pbf": "^4.0.1", "potpack": "^2.1.0", "quickselect": "^3.0.0", - "supercluster": "^8.0.1", "tinyqueue": "^3.0.0" }, "engines": { @@ -20405,6 +20401,15 @@ "pbf": "^4.0.1" } }, + "node_modules/maplibre-gl/node_modules/@maplibre/geojson-vt": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@maplibre/geojson-vt/-/geojson-vt-6.0.3.tgz", + "integrity": "sha512-tJ8df2SAIacER7pWTiSlDjIULBBAfZnzAURvWb1d8kVzx/pmSJcG0L2p0DTAB6nEu8Lmsx5zAc8JFDcs2DTwaw==", + "license": "ISC", + "dependencies": { + "kdbush": "^4.0.2" + } + }, "node_modules/maplibre-gl/node_modules/earcut": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz", @@ -27128,12 +27133,15 @@ } }, "node_modules/rollup-plugin-dts": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.3.0.tgz", - "integrity": "sha512-d0UrqxYd8KyZ6i3M2Nx7WOMy708qsV/7fTHMHxCMCBOAe3V/U7OMPu5GkX8hC+cmkHhzGnfeYongl1IgiooddA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.4.0.tgz", + "integrity": "sha512-2i00A5UoPCoDecLEs13Eu105QegSGfrbp1sDeUj/54LKGmv6XFHDxWKC6Wsb4BobGUWYVCWWjmjAc8bXXbXH/Q==", "dev": true, "license": "LGPL-3.0-only", "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "@jridgewell/sourcemap-codec": "^1.5.5", + "convert-source-map": "^2.0.0", "magic-string": "^0.30.21" }, "engines": { @@ -27143,11 +27151,11 @@ "url": "https://github.com/sponsors/Swatinem" }, "optionalDependencies": { - "@babel/code-frame": "^7.27.1" + "@babel/code-frame": "^7.29.0" }, "peerDependencies": { "rollup": "^3.29.4 || ^4", - "typescript": "^4.5 || ^5.0" + "typescript": "^4.5 || ^5.0 || ^6.0" } }, "node_modules/rollup-plugin-peer-deps-external": { diff --git a/package.json b/package.json index 75561da..cedb2f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-stories-api", - "version": "1.0.0-dev-54", + "version": "1.0.0-dev-55", "author": "Kenneth Seals-Nutt", "babel": { "presets": [ @@ -29,7 +29,7 @@ "@mui/stylis-plugin-rtl": "^7.3.8", "deck.gl": "^9.2.11", "lodash.debounce": "^4.0.8", - "maplibre-gl": "^5.19.0", + "maplibre-gl": "^5.20.2", "react-countup": "^6.5.3", "react-if": "^4.1.6", "react-map-gl": "^8.1.0", @@ -44,7 +44,7 @@ "swiper": "^11.2.10" }, "devDependencies": { - "@babel/preset-env": "^7.29.0", + "@babel/preset-env": "^7.29.2", "@babel/preset-react": "^7.28.5", "@babel/preset-typescript": "^7.28.5", "@chromatic-com/storybook": "^4.1.3", @@ -88,7 +88,7 @@ "react-dom": "^18.3.1", "relative-deps": "^1.0.7", "rollup": "^4.59.0", - "rollup-plugin-dts": "^6.3.0", + "rollup-plugin-dts": "^6.4.0", "rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-postcss": "^4.0.2", "standard-version": "^9.5.0", @@ -129,7 +129,7 @@ "peerDependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", - "@mui/icons-material": "^6.4.8", + "@mui/icons-material": "^6.5.0", "@mui/lab": "^6.0.1-beta.36", "@mui/material": "^6.5.0", "html-react-parser": "^5.2.17", diff --git a/src/components/CollectionLayout/CollectionLayout.tsx b/src/components/CollectionLayout/CollectionLayout.tsx index 0f7db6f..8319184 100644 --- a/src/components/CollectionLayout/CollectionLayout.tsx +++ b/src/components/CollectionLayout/CollectionLayout.tsx @@ -61,7 +61,7 @@ const CollectionLayout = observer(({ children }: CollectionLayoutProps) => { return undefined; }; const card = renderStoryCard(); - const showListHeader = collection.shouldShowStoriesList + const showListHeader = collection.shouldShowStoriesListHeader && Boolean(collection.hasDescription || card); return ( diff --git a/src/components/StoriesAPICollection/StoriesAPICollection.tsx b/src/components/StoriesAPICollection/StoriesAPICollection.tsx index 08eeac8..5c6fc8b 100644 --- a/src/components/StoriesAPICollection/StoriesAPICollection.tsx +++ b/src/components/StoriesAPICollection/StoriesAPICollection.tsx @@ -7,6 +7,7 @@ import { useSearchParams } from 'react-router-dom'; import useCollections from '../../hooks/useCollections'; import CollectionProvider from '../../providers/CollectionProvider'; import type { CollectionStore } from '../../state'; +import { deserializeSelectedSearchFacets } from '../../utils/searchFacetUtils'; import CollectionLoader from '../CollectionLoader/CollectionLoader'; import type { StoriesAPICollectionProps } from './StoriesAPICollection.types'; // TODO: API Task handling @@ -23,12 +24,27 @@ const StoriesAPICollection = observer(({ }: StoriesAPICollectionProps) => { const [searchParams, setSearchParams] = useSearchParams(); const collections = useCollections(); - let { collectionId, page, searchInput } = props; + let { + collectionId, + page, + searchDefaultFacets, + searchInput, + } = props; + if (connectRouter) { const routeParams = collections.getCollectionRouteParams(); collectionId ||= routeParams.collectionId; page = Number(searchParams.get('page')) || page; - searchInput = searchParams.get('q') || searchInput; + const queryFromRoute = searchParams.get('q'); + if (queryFromRoute !== null) { + searchInput = queryFromRoute; + } else { + searchInput = searchInput ?? props.searchDefaultQuery; + } + + if (searchParams.has('facets')) { + searchDefaultFacets = deserializeSelectedSearchFacets(searchParams.get('facets')); + } } if (!collectionId) { throw new Error('Collection not found.'); @@ -60,6 +76,8 @@ const StoriesAPICollection = observer(({ onPageChange: handlePageChange, onSearch: handleSearch, page, + searchDefaultFacets, + searchDefaultQuery: props.searchDefaultQuery, searchInput, }, (collectionStore) => { diff --git a/src/components/UI/CardsBrowser/CardsBrowser.styles.ts b/src/components/UI/CardsBrowser/CardsBrowser.styles.ts index 74a4f87..d002628 100644 --- a/src/components/UI/CardsBrowser/CardsBrowser.styles.ts +++ b/src/components/UI/CardsBrowser/CardsBrowser.styles.ts @@ -5,6 +5,73 @@ const styles = { px: { xs: 1, md: 4 }, transition: 'opacity 0.2s', }), + landingSuggestionChip: ( + isSelected: boolean, + isFaded: boolean, + isTransitioning: boolean, + ) => ({ + animation: isTransitioning + ? 'none' + : 'landingSuggestionsFadeUp 480ms cubic-bezier(0.34, 1.56, 0.64, 1) 200ms both', + backdropFilter: 'blur(10px)', + bgcolor: 'background.paper', + borderColor: 'primary.main', + borderRadius: 999, + boxShadow: 4, + color: 'primary.main', + fontSize: 13, + fontWeight: 600, + opacity: isFaded ? 0 : 1, + px: 0.6, + py: 0.35, + transform: isSelected ? 'translateY(-2px) scale(1.01)' : 'none', + transition: 'all 0.42s ease', + ...(isSelected ? { + bgcolor: 'primary.main', + color: 'primary.contrastText', + } : undefined), + + '&& .MuiChip-icon': { + color: isSelected ? 'primary.contrastText' : 'primary.main', + }, + + '&&:hover': { + bgcolor: 'primary.main', + borderColor: 'primary.main', + boxShadow: 8, + color: 'primary.contrastText', + transform: 'translateY(-2px) scale(1.01)', + + '&& .MuiChip-icon': { + color: 'primary.contrastText', + }, + }, + }), + landingSuggestionsContainer: { + alignItems: 'center', + display: 'flex', + flexWrap: 'wrap', + gap: 1, + justifyContent: 'center', + mt: 1.5, + width: '100%', + }, + landingSuggestionsRoot: (isTransitioning: boolean) => ({ + alignItems: 'center', + display: 'flex', + flexDirection: 'column', + maxWidth: 760, + mt: 2, + opacity: isTransitioning ? 0 : 0.82, + px: 2, + py: 2, + transition: 'opacity 0.52s ease', + width: '100%', + + '&:hover': { + opacity: isTransitioning ? 0 : 1, + }, + }), loader: (isLoading: boolean) => ({ mx: { xs: 1, md: 6 }, visibility: isLoading ? 'visible' : 'hidden', @@ -30,10 +97,131 @@ const styles = { opacity: 1, }, }, + searchInlineLoader: (isLoading: boolean) => ({ + borderRadius: 999, + mt: 1, + opacity: isLoading ? 1 : 0, + transition: 'opacity 0.2s ease', + visibility: isLoading ? 'visible' : 'hidden', + width: '100%', + }), + searchInputOverlayAnchor: { + position: 'relative', + width: '100%', + }, + searchSuggestionOption: ( + index: number, + isActive: boolean, + isSelected: boolean, + isFaded: boolean, + isTransitioning: boolean, + ) => ({ + animation: isTransitioning + ? 'none' + : `cardsBrowserSuggestionFadeIn 220ms ease ${index * 40}ms both`, + alignItems: 'center', + borderRadius: 1.5, + color: 'text.primary', + display: 'flex', + justifyContent: 'flex-start', + minHeight: 38, + opacity: isFaded ? 0 : 1, + px: 1.25, + py: 0.75, + transition: 'all 0.42s ease', + width: '100%', + ...(isActive ? { + bgcolor: 'action.hover', + color: 'primary.main', + transform: 'translateX(1px)', + } : undefined), + ...(isSelected ? { + bgcolor: 'primary.main', + color: 'primary.contrastText', + transform: 'translateX(1px)', + } : undefined), + + '&:hover': { + bgcolor: 'primary.main', + color: 'primary.contrastText', + transform: 'translateX(1px)', + }, + + '&:focus-visible': { + bgcolor: 'primary.main', + color: 'primary.contrastText', + outline: '2px solid', + outlineColor: 'primary.main', + outlineOffset: 1, + }, + + '@keyframes cardsBrowserSuggestionFadeIn': { + from: { + opacity: 0, + transform: 'translateY(6px)', + }, + to: { + opacity: 1, + transform: 'translateY(0)', + }, + }, + '@keyframes landingSuggestionsFadeUp': { + from: { + opacity: 0, + transform: 'translateY(12px)', + }, + to: { + opacity: 1, + transform: 'translateY(0)', + }, + }, + }), + searchSuggestionTitle: { + color: 'inherit', + fontSize: 14, + fontWeight: 600, + textAlign: 'left', + }, + searchSuggestionTitleWrap: { + alignItems: 'center', + display: 'flex', + gap: 1, + width: '100%', + }, + searchSuggestionsOverlayPaper: (isTransitioning: boolean) => ({ + backdropFilter: 'blur(8px)', + bgcolor: 'background.paper', + border: '1px solid', + borderColor: 'divider', + borderRadius: 2, + boxShadow: 8, + left: 0, + mt: 0.75, + opacity: isTransitioning ? 0 : 1, + position: 'absolute', + right: 0, + top: '100%', + transition: 'opacity 0.52s ease', + zIndex: 20, + }), + searchSuggestionsPaper: { + bgcolor: 'background.paper', + border: '1px solid', + borderColor: 'divider', + borderRadius: 2, + px: 1, + py: 1, + width: '100%', + }, + searchSuggestionsStack: { + gap: 1, + width: '100%', + }, searchRoot: { alignItems: 'center', display: 'flex', flexDirection: 'column', + width: '100%', }, searchSectionContainer: { px: { md: 10, xs: 1 }, @@ -44,9 +232,9 @@ const styles = { borderRadius: 2, boxShadow: 1, m: 1, - maxHeight: '100%', + maxHeight: '85vh', opacity: 0.8, - overflowY: 'scroll', + overflowY: 'auto', p: 2, transition: 'box-shadow 0.4s, opacity 0.4s', width: 'auto', diff --git a/src/components/UI/CardsBrowser/CardsBrowser.tsx b/src/components/UI/CardsBrowser/CardsBrowser.tsx index e80969d..37ad763 100644 --- a/src/components/UI/CardsBrowser/CardsBrowser.tsx +++ b/src/components/UI/CardsBrowser/CardsBrowser.tsx @@ -40,6 +40,7 @@ const CardsBrowser = observer(({ sx={styles.searchSectionContainer} > {children} diff --git a/src/components/UI/CardsBrowser/CardsBrowser.types.ts b/src/components/UI/CardsBrowser/CardsBrowser.types.ts index 86ade2a..5b7f071 100644 --- a/src/components/UI/CardsBrowser/CardsBrowser.types.ts +++ b/src/components/UI/CardsBrowser/CardsBrowser.types.ts @@ -2,6 +2,7 @@ import type { PropsWithChildren } from 'react'; import type PaginationStore from '../../../state/paginationStore'; import type SearchStore from '../../../state/searchStore'; +import type { SearchSuggestion } from '../../../types'; export type CardsBrowserLayout = 'minimal' // cards and pagination @@ -17,9 +18,32 @@ export type CardsBrowserProps = PropsWithChildren<{ }; }>; +export type CardsBrowserInputSuggestionsProps = { + readonly activeSuggestionIndex: number; + readonly isSectionTransitioning: boolean; + readonly isTransitioning: boolean; + readonly onSuggestionClick: (suggestion: SearchSuggestion) => void | Promise; + readonly onSuggestionHover: (index: number) => void; + readonly suggestions: SearchSuggestion[]; + readonly transitioningSuggestionKey: string | null; +}; + +export type CardsBrowserLandingSuggestionsProps = { + readonly isSectionTransitioning: boolean; + readonly isTransitioning: boolean; + readonly onSuggestionClick: (suggestion: SearchSuggestion) => void | Promise; + readonly overlineText: string; + readonly showLandingOverline: boolean; + readonly showLandingTitle: boolean; + readonly suggestions: SearchSuggestion[]; + readonly titleText: string; + readonly transitioningSuggestionKey: string | null; +}; + export type CardsBrowserLayoutProps = Omit; export type CardsBrowserSearchProps = { + readonly isLoading?: boolean; readonly search: SearchStore; readonly slots?: { readonly AfterSearchInput?: React.ReactNode; diff --git a/src/components/UI/CardsBrowser/CardsBrowserInputSuggestions.tsx b/src/components/UI/CardsBrowser/CardsBrowserInputSuggestions.tsx new file mode 100644 index 0000000..95938cb --- /dev/null +++ b/src/components/UI/CardsBrowser/CardsBrowserInputSuggestions.tsx @@ -0,0 +1,62 @@ +import Box from '@mui/material/Box'; +import ButtonBase from '@mui/material/ButtonBase'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; + +import type { SearchSuggestion } from '../../../types'; +import getSuggestionKey from '../../../utils/searchSuggestionUtils'; +import styles from './CardsBrowser.styles'; +import type { CardsBrowserInputSuggestionsProps } from './CardsBrowser.types'; + +export default function CardsBrowserInputSuggestions({ + activeSuggestionIndex, + isSectionTransitioning, + isTransitioning, + onSuggestionClick, + onSuggestionHover, + suggestions, + transitioningSuggestionKey, +}: CardsBrowserInputSuggestionsProps) { + const handleMouseDown = (event: React.MouseEvent) => { + // Prevent the input from losing focus when clicking on suggestions, + // which allows for better keyboard navigation support. + event.preventDefault(); + }; + return ( + + + + {suggestions.map((suggestion: SearchSuggestion, index) => { + const suggestionKey = getSuggestionKey('input', suggestion); + const isSelected = transitioningSuggestionKey === suggestionKey; + const isFaded = isTransitioning && !isSelected; + + return ( + onSuggestionClick(suggestion)} + onMouseEnter={() => onSuggestionHover(index)} + sx={styles.searchSuggestionOption( + index, + activeSuggestionIndex === index, + isSelected, + isFaded, + isTransitioning, + )} + > + + + {suggestion.display_name} + + + + ); + })} + + + + ); +} diff --git a/src/components/UI/CardsBrowser/CardsBrowserLandingSuggestions.tsx b/src/components/UI/CardsBrowser/CardsBrowserLandingSuggestions.tsx new file mode 100644 index 0000000..91e57fa --- /dev/null +++ b/src/components/UI/CardsBrowser/CardsBrowserLandingSuggestions.tsx @@ -0,0 +1,67 @@ +import SearchIcon from '@mui/icons-material/Search'; +import Box from '@mui/material/Box'; +import Chip from '@mui/material/Chip'; +import Typography from '@mui/material/Typography'; +import { When } from 'react-if'; + +import type { SearchSuggestion } from '../../../types'; +import getSuggestionKey from '../../../utils/searchSuggestionUtils'; +import styles from './CardsBrowser.styles'; +import type { CardsBrowserLandingSuggestionsProps } from './CardsBrowser.types'; + +export default function CardsBrowserLandingSuggestions({ + isSectionTransitioning, + isTransitioning, + onSuggestionClick, + overlineText, + showLandingOverline, + showLandingTitle, + suggestions, + titleText, + transitioningSuggestionKey, +}: CardsBrowserLandingSuggestionsProps) { + return ( + + + + {overlineText} + + + + + + {titleText} + + + + + {suggestions.map((suggestion: SearchSuggestion) => { + const suggestionKey = getSuggestionKey('landing', suggestion); + const isSelected = transitioningSuggestionKey === suggestionKey; + const isFaded = isTransitioning && !isSelected; + return ( + } + label={suggestion.display_name} + onClick={() => onSuggestionClick(suggestion)} + size="small" + sx={styles.landingSuggestionChip( + isSelected, + isFaded, + isTransitioning, + )} + variant="outlined" + /> + ); + })} + + + ); +} diff --git a/src/components/UI/CardsBrowser/CardsBrowserSearch.tsx b/src/components/UI/CardsBrowser/CardsBrowserSearch.tsx index 45cc560..0d58b8e 100644 --- a/src/components/UI/CardsBrowser/CardsBrowserSearch.tsx +++ b/src/components/UI/CardsBrowser/CardsBrowserSearch.tsx @@ -1,28 +1,97 @@ import Box from '@mui/material/Box'; +import LinearProgress from '@mui/material/LinearProgress'; import { observer } from 'mobx-react-lite'; import { When } from 'react-if'; +import useCardsBrowserSearch from '../../../hooks/useCardsBrowserSearch'; +import useLocale from '../../../hooks/useLocale'; import SearchInput from '../SearchInput/SearchInput'; import styles from './CardsBrowser.styles'; import type { CardsBrowserSearchProps } from './CardsBrowser.types'; +import CardsBrowserInputSuggestions from './CardsBrowserInputSuggestions'; +import CardsBrowserLandingSuggestions from './CardsBrowserLandingSuggestions'; import CardsBrowserNoResultsCard from './CardsBrowserNoResultsCard'; -const CardsBrowserSearch = observer(({ search, slots }: CardsBrowserSearchProps) => ( - - - - {slots?.AfterSearchInput || null} - - - - - -)); +const CardsBrowserSearch = observer(({ + isLoading = false, + search, + slots, +}: CardsBrowserSearchProps) => { + const { t } = useLocale(); + const { + activeSuggestionIndex, + handleSearchInputBlur, + handleSearchInputFocus, + handleSearchInputKeyDown, + inputSuggestionsToRender, + isTransitioningInputSuggestionItems, + isTransitioningInputSuggestions, + isTransitioningLandingSuggestionItems, + isTransitioningLandingSuggestions, + landingSuggestionsToRender, + onInputSuggestionClick, + onLandingSuggestionClick, + setActiveSuggestionIndex, + shouldShowInputSuggestions, + shouldShowLandingSuggestions, + transitioningSuggestionKey, + } = useCardsBrowserSearch(search); + + const landingOverlineText = t('search.suggestions.landingOverline'); + const landingTitleText = t('search.suggestions.landingTitle'); + const showLandingOverline = !!landingOverlineText; + const showLandingTitle = !!landingTitleText; + + return ( + + + + + + + + + + + + {slots?.AfterSearchInput || null} + + + + + + + + + + ); +}); export default CardsBrowserSearch; diff --git a/src/configs/localizationConfig.ts b/src/configs/localizationConfig.ts index 3dff70a..7dc1a3f 100644 --- a/src/configs/localizationConfig.ts +++ b/src/configs/localizationConfig.ts @@ -41,7 +41,11 @@ const localizationConfig: LocalizationConfig = { translations: { ar: { 'collection.featuredStory.buttonLabel': 'عرض القصة المميزة', + 'collection.search.defaultPlaceholder': 'البحث في المجموعة...', 'collection.storiesList.header': 'استكشف جمیع القصص من مجموعة {collection_name}', + 'search.defaultPlaceholder': 'بحث...', + 'search.suggestions.landingOverline': 'اقتراحات مختارة', + 'search.suggestions.landingTitle': 'استكشف من خلال عمليات البحث الشائعة', 'story.collectionButtonLabel': 'استكشف المزيد من القصص', 'storyId.actions.clipboard': 'نسخ المعرف إلى الحافظة', 'storyId.actions.externalLink': 'الانتقال إلى الموقع الخارجي', @@ -63,7 +67,11 @@ const localizationConfig: LocalizationConfig = { }, en: { 'collection.featuredStory.buttonLabel': 'View Featured Story', + 'collection.search.defaultPlaceholder': 'Search collection...', 'collection.storiesList.header': 'Explore All Stories from the {collection_name} Collection', + 'search.defaultPlaceholder': 'Search...', + 'search.suggestions.landingOverline': 'Curated suggestions', + 'search.suggestions.landingTitle': 'Explore with Popular Searches', 'story.collectionButtonLabel': 'Explore More Stories', 'storyId.actions.clipboard': 'Copy to Clipboard', 'storyId.actions.externalLink': 'Go to External Site', @@ -85,7 +93,11 @@ const localizationConfig: LocalizationConfig = { }, es: { 'collection.featuredStory.buttonLabel': 'Ver historia destacada', + 'collection.search.defaultPlaceholder': 'Buscar en la colección...', 'collection.storiesList.header': 'Explorar todas las historias de la colección {collection_name}', + 'search.defaultPlaceholder': 'Buscar...', + 'search.suggestions.landingOverline': 'Sugerencias seleccionadas', + 'search.suggestions.landingTitle': 'Explora con búsquedas populares', 'story.collectionButtonLabel': 'Explorar más historias', 'storyId.actions.clipboard': 'Copiar ID al portapapeles', 'storyId.actions.externalLink': 'Ir al sitio externo', @@ -99,7 +111,11 @@ const localizationConfig: LocalizationConfig = { welcome: 'Bienvenido', }, fr: { + 'collection.search.defaultPlaceholder': 'Rechercher dans la collection...', 'collection.storiesList.header': 'Explorer toutes les histoires de la collection {collection_name}', + 'search.defaultPlaceholder': 'Rechercher...', + 'search.suggestions.landingOverline': 'Suggestions sélectionnées', + 'search.suggestions.landingTitle': 'Explorez les recherches populaires', 'story.collectionButtonLabel': 'Explorer plus d\'histoires', 'storyId.actions.clipboard': 'Copier l\'ID dans le presse-papiers', 'storyId.actions.externalLink': 'Aller vers le site externe', diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 144e131..e6a1d0b 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,4 +1,5 @@ export { default as useAV } from './useAV'; +export { default as useCardsBrowserSearch } from './useCardsBrowserSearch'; export { default as useCollection } from './useCollection'; export { default as useCollections } from './useCollections'; export { default as useColor } from './useColor'; diff --git a/src/hooks/useCardsBrowserSearch.ts b/src/hooks/useCardsBrowserSearch.ts new file mode 100644 index 0000000..63665e1 --- /dev/null +++ b/src/hooks/useCardsBrowserSearch.ts @@ -0,0 +1,188 @@ +import type { KeyboardEvent } from 'react'; +import { useEffect, useState } from 'react'; + +import type SearchStore from '../state/searchStore'; +import type { SearchSuggestion } from '../types'; +import getSuggestionKey from '../utils/searchSuggestionUtils'; + +const ITEM_FADE_DELAY_MS = 500; +const SECTION_FADE_DELAY_MS = 800; + +type SuggestionLocation = 'input' | 'landing'; +type SuggestionTransitionPhase = 'itemFade' | 'searchWait' | 'sectionFade' | null; +type NullableSuggestionLocation = SuggestionLocation | null; + +export type UseCardsBrowserSearch = { + readonly activeSuggestionIndex: number; + readonly handleSearchInputBlur: () => void; + readonly handleSearchInputFocus: () => void; + readonly handleSearchInputKeyDown: ( + event: KeyboardEvent, + ) => void | Promise; + readonly inputSuggestionsToRender: SearchSuggestion[]; + readonly isTransitioningInputSuggestionItems: boolean; + readonly isTransitioningInputSuggestions: boolean; + readonly isTransitioningLandingSuggestionItems: boolean; + readonly isTransitioningLandingSuggestions: boolean; + readonly landingSuggestionsToRender: SearchSuggestion[]; + readonly onInputSuggestionClick: (suggestion: SearchSuggestion) => void | Promise; + readonly onLandingSuggestionClick: (suggestion: SearchSuggestion) => void | Promise; + readonly setActiveSuggestionIndex: (index: number) => void; + readonly shouldShowInputSuggestions: boolean; + readonly shouldShowLandingSuggestions: boolean; + readonly transitioningSuggestionKey: string | null; +}; + +const delay = (ms: number) => new Promise((resolve) => { + setTimeout(resolve, ms); +}); + +export default function useCardsBrowserSearch(search: SearchStore): UseCardsBrowserSearch { + const [activeSuggestionIndex, setActiveSuggestionIndex] = useState(-1); + const [transitioningSuggestionKey, setTransitioningSuggestionKey] = useState(null); + const [transitioningSuggestionLocation, setTransitioningSuggestionLocation] = useState< + NullableSuggestionLocation + >(null); + const [transitionPhase, setTransitionPhase] = useState(null); + const [transitionLandingSuggestions, setTransitionLandingSuggestions] = useState< + typeof search.landingSuggestions + >([]); + + const isTransitioningSuggestion = transitioningSuggestionKey !== null; + + const applySuggestionWithTransition = async ( + suggestion: SearchSuggestion, + location: SuggestionLocation, + ) => { + if (isTransitioningSuggestion) { + return; + } + + const key = getSuggestionKey(location, suggestion); + setTransitioningSuggestionLocation(location); + setTransitioningSuggestionKey(key); + + if (location === 'input') { + // Close the input menu immediately once a selection is made. + search.setFocused(false); + setActiveSuggestionIndex(-1); + } + + if (location === 'landing') { + setTransitionLandingSuggestions([...search.landingSuggestions]); + } + + setTransitionPhase('itemFade'); + await delay(ITEM_FADE_DELAY_MS); + + // Phase 2: search fires, loader appears while section stays visible. + setTransitionPhase('searchWait'); + + try { + await search.applySuggestion(suggestion); + + // Phase 3: search is done; section fades out before results render. + setTransitionPhase('sectionFade'); + await delay(SECTION_FADE_DELAY_MS); + } finally { + setTransitionPhase(null); + setTransitioningSuggestionLocation(null); + setTransitioningSuggestionKey(null); + setTransitionLandingSuggestions([]); + } + }; + + useEffect(() => { + setActiveSuggestionIndex(-1); + }, [search.inputSuggestions.length, search.query]); + + const handleSearchInputKeyDown = async ( + event: KeyboardEvent, + ) => { + if (!search.shouldShowInputSuggestions) { + return; + } + + if (event.key === 'ArrowDown') { + event.preventDefault(); + setActiveSuggestionIndex((currentIndex) => { + const nextIndex = currentIndex + 1; + return nextIndex >= search.inputSuggestions.length ? 0 : nextIndex; + }); + return; + } + + if (event.key === 'ArrowUp') { + event.preventDefault(); + setActiveSuggestionIndex((currentIndex) => { + if (currentIndex <= 0) { + return search.inputSuggestions.length - 1; + } + return currentIndex - 1; + }); + return; + } + + if (event.key === 'Escape') { + setActiveSuggestionIndex(-1); + return; + } + + if (event.key === 'Enter' && activeSuggestionIndex >= 0) { + event.preventDefault(); + const [selectedSuggestion] = search.inputSuggestions.slice( + activeSuggestionIndex, + activeSuggestionIndex + 1, + ); + if (selectedSuggestion) { + await applySuggestionWithTransition(selectedSuggestion, 'input'); + } + } + }; + + const handleSearchInputFocus = () => { + search.setFocused(true); + }; + + const handleSearchInputBlur = () => { + search.setFocused(false); + }; + + const landingSuggestionsToRender = transitioningSuggestionLocation === 'landing' + ? transitionLandingSuggestions + : search.landingSuggestions; + + const shouldShowLandingSuggestions = search.shouldShowLandingSuggestions + || (transitioningSuggestionLocation === 'landing' && landingSuggestionsToRender.length > 0); + + return { + activeSuggestionIndex, + handleSearchInputBlur, + handleSearchInputFocus, + handleSearchInputKeyDown, + inputSuggestionsToRender: search.inputSuggestions, + isTransitioningInputSuggestionItems: ( + transitioningSuggestionLocation === 'input' && transitionPhase !== null + ), + isTransitioningInputSuggestions: ( + transitioningSuggestionLocation === 'input' && transitionPhase === 'sectionFade' + ), + isTransitioningLandingSuggestionItems: ( + transitioningSuggestionLocation === 'landing' && transitionPhase !== null + ), + isTransitioningLandingSuggestions: ( + transitioningSuggestionLocation === 'landing' && transitionPhase === 'sectionFade' + ), + landingSuggestionsToRender, + onInputSuggestionClick: (suggestion: SearchSuggestion) => ( + applySuggestionWithTransition(suggestion, 'input') + ), + onLandingSuggestionClick: (suggestion: SearchSuggestion) => ( + applySuggestionWithTransition(suggestion, 'landing') + ), + setActiveSuggestionIndex, + shouldShowInputSuggestions: search.shouldShowInputSuggestions, + shouldShowLandingSuggestions, + transitioningSuggestionKey, + }; +} diff --git a/src/state/collectionStore.test.ts b/src/state/collectionStore.test.ts new file mode 100644 index 0000000..adf97ec --- /dev/null +++ b/src/state/collectionStore.test.ts @@ -0,0 +1,57 @@ +import CollectionStore from './collectionStore'; + +const buildCollection = () => ({ + id: 1, + name: 'Test Collection', + status: 'PUBLISHED' as const, +}); + +const buildRoot = () => ({ + api: { + getStories: jest.fn().mockResolvedValue({ + count: 0, + last_page: 1, + stories: [], + total_count: 0, + }), + }, + formatters: { + collectionStoriesListHeader: 'Stories', + formatCollectionPageTitle: jest.fn(), + }, + locale: { + hasAlternativeLocales: false, + }, +}); + +describe('CollectionStore search start mode', () => { + it('defers initial stories load in emptyLanding mode when there is no search content', async () => { + const root = buildRoot(); + const store = new CollectionStore(root as never, { + collection: buildCollection(), + onSearch: async () => {}, + searchStartMode: 'emptyLanding', + source: 'api', + }); + + await store.init(); + + expect(root.api.getStories).not.toHaveBeenCalled(); + expect(store.initialized).toBe(true); + }); + + it('loads stories initially in emptyLanding mode when a default query is provided', async () => { + const root = buildRoot(); + const store = new CollectionStore(root as never, { + collection: buildCollection(), + onSearch: async () => {}, + searchDefaultQuery: 'langston hughes', + searchStartMode: 'emptyLanding', + source: 'api', + }); + + await store.init(); + + expect(root.api.getStories).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/state/collectionStore.ts b/src/state/collectionStore.ts index 1147e99..1e52df6 100644 --- a/src/state/collectionStore.ts +++ b/src/state/collectionStore.ts @@ -13,7 +13,11 @@ import type { DataSource, EditableCollectionKey, MutableCollection, + Nullable, SaveStatus, + SearchStartMode, + SearchSuggestions, + SelectedSearchFacets, SerializableRecord, StoriesAPIStatus, StoriesAPIStoriesResponse, @@ -39,8 +43,15 @@ export type CollectionStoreOptions = { readonly onSearch?: (searchInput: string, collection: CollectionStore) => Promise; readonly page?: number; readonly pageSize?: number; + readonly searchDefaultFacets?: SelectedSearchFacets; + readonly searchDefaultQuery?: string; readonly searchInput?: string; + readonly searchStartMode?: SearchStartMode; + readonly searchSuggestions?: Nullable; + readonly showInputSearchSuggestions?: boolean; + readonly showLandingSearchSuggestions?: boolean; readonly showLocaleSelector?: boolean; + readonly showStoriesListHeader?: boolean; readonly showStoryId?: boolean; readonly slots?: { [key: string]: FC> }; readonly source?: DataSource; @@ -231,10 +242,29 @@ export default class CollectionStore { ); } + get shouldDeferInitialStoriesLoad() { + return this.search.isEmptyLandingMode && !this.search.hasSearchContent; + } + + get shouldLazyInitWithSearchDefaults() { + return this.searchIsEnabled && this.search.hasSearchContent; + } + get shouldShowStoriesList() { + if ( + this.search.isEmptyLandingMode + && !this.search.hasSearchContent + && this.storiesCount === 0 + ) { + return false; + } return this.searchIsEnabled || this.totalStoriesCount > 1; } + get shouldShowStoriesListHeader() { + return this.options.showStoriesListHeader !== false; + } + get shouldShowStoryId() { return !!this.options.showStoryId; } @@ -309,12 +339,17 @@ export default class CollectionStore { buildSearchStore() { return new SearchStore(this.root, { disabled: !this.searchIsEnabled, + enableInputSuggestions: this.options.showInputSearchSuggestions, + enableLandingSuggestions: this.options.showLandingSearchSuggestions, facets: this.collection.search_facets, onSearch: this.searchStories.bind(this), - placeholder: 'Search collection...', - query: this.options.searchInput, - selectedFacets: {}, // TODO: support query param filters + placeholder: this.root.locale.translate?.('collection.search.defaultPlaceholder') + || 'Search collection...', + query: this.options.searchInput ?? this.options.searchDefaultQuery, + selectedFacets: this.options.searchDefaultFacets ?? {}, searchOnFacetChange: true, + startMode: this.options.searchStartMode, + suggestions: this.options.searchSuggestions ?? this.collection.search_suggestions, }); } @@ -346,7 +381,21 @@ export default class CollectionStore { async init() { if (this.sourceIsAPI) { - await this.loadStories(); + if (!this.shouldDeferInitialStoriesLoad) { + if (this.shouldLazyInitWithSearchDefaults) { + // Render collection shell immediately and let search loading state + // drive cards browser UI. + runInAction(() => { + this.initialized = true; + }); + this.search.submit().catch(() => { + // submit handles loading state; failures are surfaced by API flow. + }); + return; + } + + await this.loadStories(); + } } runInAction(() => { this.initialized = true; diff --git a/src/state/searchStore.test.ts b/src/state/searchStore.test.ts index 0ec0001..85c8167 100644 --- a/src/state/searchStore.test.ts +++ b/src/state/searchStore.test.ts @@ -88,3 +88,123 @@ describe('SearchStore request concurrency', () => { expect(store.count).toBe(8); }); }); + +describe('SearchStore suggestions', () => { + it('shows input suggestions when query is typed and input suggestions are enabled', () => { + const onSearch = jest.fn, [string]>().mockResolvedValue(0); + const store = new SearchStore({} as never, { + onSearch, + suggestions: [ + { + display_name: 'Langston Hughes', + query: 'langston hughes', + locations: { input: true, landing: false }, + }, + ], + }); + + store.setFocused(true); + store.setQuery('lang'); + + expect(store.shouldShowInputSuggestions).toBe(true); + expect(store.inputSuggestions).toHaveLength(1); + expect(store.shouldShowLandingSuggestions).toBe(false); + }); + + it('shows landing suggestions only in emptyLanding mode with no search content', () => { + const onSearch = jest.fn, [string]>().mockResolvedValue(0); + const store = new SearchStore({} as never, { + onSearch, + startMode: 'emptyLanding', + suggestions: [ + { + display_name: 'Civil Rights', + query: 'civil rights', + locations: { landing: true, input: false }, + }, + ], + }); + + expect(store.shouldShowLandingSuggestions).toBe(true); + + store.setQuery('civil'); + + expect(store.shouldShowLandingSuggestions).toBe(false); + }); + + it('applies suggestion query and facets before searching', async () => { + const onSearch = jest.fn, [string]>().mockResolvedValue(3); + const store = new SearchStore({} as never, { + onSearch, + suggestions: [ + { + display_name: 'Langston Hughes', + query: 'langston hughes', + facets: { + category: ['poetry'], + }, + }, + ], + }); + + await store.applySuggestion(store.suggestions[0]); + + expect(store.query).toBe('langston hughes'); + expect(store.selectedFacets).toEqual({ category: ['poetry'] }); + expect(onSearch).toHaveBeenCalledWith('langston hughes', false); + }); + + it('keeps query blank when suggestion query is missing or null', async () => { + const onSearch = jest.fn, [string]>().mockResolvedValue(5); + const store = new SearchStore({} as never, { + onSearch, + suggestions: [ + { + display_name: 'Works during the Harlem Renaissance', + facets: { + P8: ['Q4'], + }, + query: null, + }, + ], + }); + + await store.applySuggestion(store.suggestions[0]); + + expect(store.query).toBe(''); + expect(store.selectedFacets).toEqual({ P8: ['Q4'] }); + expect(onSearch).toHaveBeenCalledWith('', false); + }); + + it('shows suggestion display name as placeholder while loading, then restores default', async () => { + const deferred = createDeferred(); + const onSearch = jest.fn, [string]>().mockImplementation( + () => deferred.promise, + ); + const store = new SearchStore({} as never, { + onSearch, + placeholder: 'Search collection...', + suggestions: [ + { + display_name: 'Works during the Harlem Renaissance', + facets: { + P8: ['Q4'], + }, + query: null, + }, + ], + }); + + const applyPromise = store.applySuggestion(store.suggestions[0]); + + expect(store.loading).toBe(true); + expect(store.placeholder).toBe('Works during the Harlem Renaissance'); + expect(onSearch).toHaveBeenCalledWith('', false); + + deferred.resolve(4); + await applyPromise; + + expect(store.loading).toBe(false); + expect(store.placeholder).toBe('Search collection...'); + }); +}); diff --git a/src/state/searchStore.ts b/src/state/searchStore.ts index cf20b34..c2c0f3b 100644 --- a/src/state/searchStore.ts +++ b/src/state/searchStore.ts @@ -1,5 +1,5 @@ import debounce from 'lodash.debounce'; -import { makeAutoObservable } from 'mobx'; +import { makeAutoObservable, runInAction } from 'mobx'; import { DEFAULT_DEBOUNCE_DELAY } from '../constants'; import type { @@ -9,6 +9,9 @@ import type { SearchFacetNumberRangeValue, SearchFacets, SearchFacetValue, + SearchStartMode, + SearchSuggestion, + SearchSuggestions, SelectedSearchFacets, } from '../types'; import { @@ -20,14 +23,29 @@ import { } from '../utils/searchFacetUtils'; import type RootStore from './rootStore'; +const shouldShowSuggestionInLocation = ( + suggestion: SearchSuggestion, + location: 'input' | 'landing', +) => { + const locationValue = suggestion.locations?.[location]; + if (locationValue === undefined) { + return true; + } + return !!locationValue; +}; + export type SearchStoreOptions = { count?: number; debounceDelay?: number; disabled?: boolean; + enableInputSuggestions?: boolean; + enableLandingSuggestions?: boolean; facets?: Nullable; onSearch: (query: string, bypassCache?: boolean) => Promise; placeholder?: string; query?: string; + startMode?: SearchStartMode; + suggestions?: Nullable; searchOnFacetChange?: boolean; selectedFacets?: SelectedSearchFacets; }; @@ -39,8 +57,14 @@ export default class SearchStore { disabled: boolean; + enableInputSuggestions: boolean; + + enableLandingSuggestions: boolean; + facets: Nullable; + isFocused: boolean = false; + loading: boolean; private options: SearchStoreOptions; @@ -52,6 +76,12 @@ export default class SearchStore { selectedFacets: SelectedSearchFacets = {}; + startMode: SearchStartMode; + + suggestionLoadingPlaceholder: Nullable = null; + + suggestions: SearchSuggestions; + constructor(public root: RootStore, options: SearchStoreOptions) { makeAutoObservable(this); this.root = root; @@ -62,6 +92,10 @@ export default class SearchStore { this.selectedFacets = options.selectedFacets || {}; this.facets = options.facets; this.loading = false; + this.enableInputSuggestions = options.enableInputSuggestions ?? true; + this.enableLandingSuggestions = options.enableLandingSuggestions ?? true; + this.startMode = options.startMode ?? 'results'; + this.suggestions = options.suggestions ?? []; this.debouncedSubmit = debounce( this.submit.bind(this), options.debounceDelay || DEFAULT_DEBOUNCE_DELAY, @@ -107,8 +141,56 @@ export default class SearchStore { }); } + get inputSuggestions() { + if (!this.enableInputSuggestions) { + return []; + } + + const normalizedQuery = this.query.trim().toLowerCase(); + + // Show all input suggestions when focused, regardless of query + if (this.isFocused && normalizedQuery === '') { + return this.suggestions + .filter((suggestion) => shouldShowSuggestionInLocation(suggestion, 'input')) + .slice(0, 8); + } + + // When typing, filter suggestions by query + if (!normalizedQuery) { + return []; + } + + return this.suggestions + .filter((suggestion) => shouldShowSuggestionInLocation(suggestion, 'input')) + .filter((suggestion) => { + const displayName = suggestion.display_name.toLowerCase(); + const suggestionQuery = (suggestion.query ?? suggestion.display_name).toLowerCase(); + return displayName.includes(normalizedQuery) || suggestionQuery.includes(normalizedQuery); + }) + .slice(0, 8); + } + + get isEmptyLandingMode() { + return this.startMode === 'emptyLanding'; + } + + get landingSuggestions() { + if (!this.enableLandingSuggestions || !this.isEmptyLandingMode || this.hasSearchContent) { + return []; + } + + return this.suggestions + .filter((suggestion) => shouldShowSuggestionInLocation(suggestion, 'landing')) + .slice(0, 12); + } + get placeholder() { - return this.options.placeholder || 'Search...'; + if (this.suggestionLoadingPlaceholder !== null) { + return this.suggestionLoadingPlaceholder; + } + return this.options.placeholder + || this.root.locale.translate?.('search.defaultPlaceholder') + || 'Search...'; } get queryParams() { @@ -121,6 +203,14 @@ export default class SearchStore { }; } + get shouldShowInputSuggestions() { + return this.isFocused && this.inputSuggestions.length > 0 && !this.loading; + } + + get shouldShowLandingSuggestions() { + return this.landingSuggestions.length > 0 && !this.loading; + } + get shouldShowNoResultsMessage() { return this.count === 0 && !this.loading; } @@ -129,6 +219,21 @@ export default class SearchStore { return !this.disabled && this.hasSearchContent; } + async applySuggestion(suggestion: SearchSuggestion, bypassCache: boolean = false) { + runInAction(() => { + this.query = suggestion.query ?? ''; + this.selectedFacets = suggestion.facets ? { ...suggestion.facets } : {}; + this.suggestionLoadingPlaceholder = suggestion.display_name; + }); + try { + await this.submit(false, bypassCache); + } finally { + runInAction(() => { + this.suggestionLoadingPlaceholder = null; + }); + } + } + canSelectFacets(isDesktop: boolean) { return this.hasFacets && isDesktop; } @@ -266,6 +371,10 @@ export default class SearchStore { this.handleSelectedFacetsChange(); } + setFocused(focused: boolean) { + this.isFocused = focused; + } + setNumberRangeValue(key: string, value: SearchFacetNumberRangeValue) { if (value.min !== undefined || value.max !== undefined) { this.selectedFacets[key] = value; diff --git a/src/types.ts b/src/types.ts index 15df261..5adf1ac 100644 --- a/src/types.ts +++ b/src/types.ts @@ -109,6 +109,7 @@ export type Collection = { readonly is_featured?: boolean; readonly name: string; readonly search_facets?: Nullable; + readonly search_suggestions?: Nullable; readonly status: StoriesAPIStatus; readonly stories?: StorySummary[]; readonly subtitle?: NullableString; @@ -559,8 +560,24 @@ export type SearchFacetValueRef = { readonly value: string; }; +export type SearchStartMode = 'results' | 'emptyLanding'; + export type SelectedSearchFacets = Record; +export type SearchSuggestionLocations = { + readonly input?: boolean; + readonly landing?: boolean; +}; + +export type SearchSuggestion = { + readonly display_name: string; + readonly facets?: SelectedSearchFacets; + readonly locations?: SearchSuggestionLocations; + readonly query?: NullableString; +}; + +export type SearchSuggestions = SearchSuggestion[]; + export type SerializableRecord = Record; export type SerializeableValue = boolean | null | number | object | string; @@ -648,6 +665,7 @@ export type StoriesAPIListResponse = { export type StoriesAPIStatus = 'ARCHIVED' | 'DRAFT' | 'PREVIEW' | 'PUBLISHED' | 'UNLISTED'; export type StoriesAPIStoriesQueryParams = { + readonly facets?: string; readonly page?: number; readonly page_size?: number; readonly q?: string; diff --git a/src/utils/searchFacetUtils.test.ts b/src/utils/searchFacetUtils.test.ts new file mode 100644 index 0000000..7433b8c --- /dev/null +++ b/src/utils/searchFacetUtils.test.ts @@ -0,0 +1,31 @@ +import { + deserializeSelectedSearchFacets, + serializeSelectedSearchFacets, +} from './searchFacetUtils'; + +describe('searchFacetUtils serialization', () => { + it('deserializes serialized selected facets from router query string', () => { + const selectedFacets = { + category: ['poetry', 'history'], + publication_year: 1925, + range: { + max: 1940, + min: 1900, + }, + published_at: { + end: '1940-12-31', + start: '1900-01-01', + }, + }; + + const serialized = serializeSelectedSearchFacets(selectedFacets); + + expect(deserializeSelectedSearchFacets(serialized)).toEqual(selectedFacets); + }); + + it('returns an empty object for missing or empty facets string', () => { + expect(deserializeSelectedSearchFacets(undefined)).toEqual({}); + expect(deserializeSelectedSearchFacets(null)).toEqual({}); + expect(deserializeSelectedSearchFacets('')).toEqual({}); + }); +}); diff --git a/src/utils/searchFacetUtils.ts b/src/utils/searchFacetUtils.ts index 74f6dc6..413bfbd 100644 --- a/src/utils/searchFacetUtils.ts +++ b/src/utils/searchFacetUtils.ts @@ -70,6 +70,23 @@ export const buildYearRangeValue = (value: number[]): SearchFacetDateRangeValue start: formatYearAsDate(value[0]), }); +export const deserializeSelectedSearchFacets = ( + serializedFacets: string | undefined | null, +): SelectedSearchFacets => { + if (!serializedFacets) { + return {}; + } + + const selectedFacets: SelectedSearchFacets = {}; + const params = new URLSearchParams(serializedFacets); + + params.forEach((value, key) => { + selectedFacets[key] = parseSearchFacetValue(value); + }); + + return selectedFacets; +}; + export const doesSearchFacetHaveValue = (value: SearchFacetValue | undefined): boolean => { if (value === undefined) { return false; @@ -217,6 +234,40 @@ export const parseNumberInputValue = (value: string): number | null | undefined return Number.isNaN(numValue) ? undefined : numValue; }; +const parseSearchFacetValue = (value: string): SearchFacetValue => { + const trimmedValue = value.trim(); + if (!trimmedValue) { + return value; + } + + try { + const parsedValue: unknown = JSON.parse(trimmedValue); + if (Array.isArray(parsedValue) && parsedValue.every((item) => typeof item === 'string')) { + return parsedValue; + } + if (typeof parsedValue === 'number') { + return parsedValue; + } + if (typeof parsedValue === 'string') { + return parsedValue; + } + if ( + parsedValue + && typeof parsedValue === 'object' + && ('start' in parsedValue || 'end' in parsedValue || 'min' in parsedValue || 'max' in parsedValue) + ) { + return parsedValue as SearchFacetValue; + } + } catch { + const numberValue = Number(trimmedValue); + if (!Number.isNaN(numberValue) && trimmedValue !== '') { + return numberValue; + } + } + + return value; +}; + export const serializeSearchFacetValue = (value: SearchFacetValue): string => { if (isStringArrayValue(value)) { return JSON.stringify(value); diff --git a/src/utils/searchSuggestionUtils.ts b/src/utils/searchSuggestionUtils.ts new file mode 100644 index 0000000..3986496 --- /dev/null +++ b/src/utils/searchSuggestionUtils.ts @@ -0,0 +1,8 @@ +import type { SearchSuggestion } from '../types'; + +export default function getSuggestionKey( + prefix: 'input' | 'landing', + suggestion: SearchSuggestion, +) { + return `${prefix}-${suggestion.display_name}-${suggestion.query ?? suggestion.display_name}`; +} From 89d92b3a4c1d0c459cdffc7f952a1696d6e67386 Mon Sep 17 00:00:00 2001 From: Kenneth Seals-Nutt Date: Fri, 20 Mar 2026 06:59:50 -0400 Subject: [PATCH 3/5] FEAT: support Moment Plugin framework --- package-lock.json | 4 +- package.json | 2 +- .../Collection/Collection.stories.tsx | 42 +++++++ .../CollectionLayout/CollectionLayout.tsx | 2 +- .../CollectionSection.stories.tsx | 105 ++++++++++++++++ .../CollectionSection.styles.ts | 3 + .../CollectionSection/CollectionSection.tsx | 1 + .../CollectionStoriesList.tsx | 21 ++-- .../Collections/Collections.stories.tsx | 64 ++++++++-- src/components/Moments/AVBaseMoment/index.ts | 2 + src/components/Moments/BaseMoment/index.ts | 2 + .../Moments/CardsBaseMoment/index.ts | 2 + src/components/Moments/IFrameMoment/index.ts | 2 + .../StoriesAPICollection.tsx | 2 +- src/components/StoryMoment/StoryMoment.tsx | 30 ++++- src/components/UI/MenuTooltip/MenuTooltip.tsx | 2 +- src/components/UI/StoryId/StoryId.helpers.ts | 8 +- src/components/UI/StoryId/StoryId.types.ts | 6 +- src/components/index.ts | 4 + src/configs/momentConfig.ts | 15 +-- src/hooks/useCardsBrowserSearch.ts | 17 ++- src/state/collectionStore.ts | 9 +- src/state/rootStore.ts | 15 ++- src/state/searchStore.test.ts | 117 ++++++++++++++++-- src/state/searchStore.ts | 35 ++++-- src/types.ts | 23 +++- src/utils/momentConfigUtils.ts | 25 ++++ 27 files changed, 473 insertions(+), 87 deletions(-) create mode 100644 src/components/CollectionSection/CollectionSection.stories.tsx create mode 100644 src/components/Moments/AVBaseMoment/index.ts create mode 100644 src/components/Moments/BaseMoment/index.ts create mode 100644 src/components/Moments/CardsBaseMoment/index.ts create mode 100644 src/components/Moments/IFrameMoment/index.ts create mode 100644 src/utils/momentConfigUtils.ts diff --git a/package-lock.json b/package-lock.json index b3dd4af..44fe9cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "react-stories-api", - "version": "1.0.0-dev-55", + "version": "1.0.0-dev-56", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "react-stories-api", - "version": "1.0.0-dev-55", + "version": "1.0.0-dev-56", "license": "MIT", "dependencies": { "@fontsource/roboto": "^5.2.10", diff --git a/package.json b/package.json index cedb2f3..d0c9a60 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-stories-api", - "version": "1.0.0-dev-55", + "version": "1.0.0-dev-56", "author": "Kenneth Seals-Nutt", "babel": { "presets": [ diff --git a/src/components/Collection/Collection.stories.tsx b/src/components/Collection/Collection.stories.tsx index f7a1719..8057df2 100644 --- a/src/components/Collection/Collection.stories.tsx +++ b/src/components/Collection/Collection.stories.tsx @@ -46,6 +46,48 @@ export const SampleCollection = { }, }; +export const SingleStoryToolLayout = { + args: { + collection: { + id: 2, + name: 'A Single-Story Collection', + description: 'This collection has only one story. The stories list below the header should be hidden.', + status: 'PUBLISHED', + featured_stories: [ + { + collection_id: 2, + collection_name: 'A Single-Story Collection', + id: 'Q001', + label: 'The Only Story', + description: 'There is only one story in this collection.', + image: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Yale_Club_Exterior.tif/lossy-page1-1200px-Yale_Club_Exterior.tif.jpg', + status: 'PUBLISHED', + }, + ], + stories: [ + { + collection_id: 2, + collection_name: 'A Single-Story Collection', + id: 'Q001', + label: 'The Only Story', + description: 'There is only one story in this collection.', + image: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Yale_Club_Exterior.tif/lossy-page1-1200px-Yale_Club_Exterior.tif.jpg', + status: 'PUBLISHED', + }, + ], + total_stories_count: 1, + }, + layout: 'tool', + }, + parameters: { + docs: { + description: { + story: 'A collection with a single story in the tool layout. The featured story appears in the header, and the stories list section below should be hidden since there is only one total story.', + }, + }, + }, +}; + export const YaleClubCollectionDemo = { args: { collection: yaleClubCollectionData, diff --git a/src/components/CollectionLayout/CollectionLayout.tsx b/src/components/CollectionLayout/CollectionLayout.tsx index 8319184..e3c0617 100644 --- a/src/components/CollectionLayout/CollectionLayout.tsx +++ b/src/components/CollectionLayout/CollectionLayout.tsx @@ -39,7 +39,7 @@ const CollectionLayout = observer(({ children }: CollectionLayoutProps) => { ); } - if (collection.hasOneStory) { + if (collection.hasOneStory && collection.firstStory) { return ( new CollectionStore( + new RootStore(), + { collection: collectionData }, +); + +function StoryRenderer({ + buttonLabel = undefined, + collectionData, + collectionPathFormatter = undefined, + isEnabled = undefined, +}: CollectionSectionStoryArgs) { + const collectionStore = useMemo( + () => buildCollectionStore(collectionData), + [collectionData], + ); + + return ( + + ); +} + +function renderStory(args: CollectionSectionStoryArgs) { + return ( + + ); +} + +const unpublishedCollectionData: Collection = { + ...(baseCollectionData as Collection), + status: 'PREVIEW', +}; + +export default { + args: { + collectionData: yaleClubCollectionData as Collection, + }, + argTypes: { + collectionData: { + control: false, + table: { disable: true }, + }, + }, + component: CollectionSection, + decorators: [ + baseStorybookDecorator, + ], + parameters: { + layout: 'padded', + }, + render: renderStory, + tags: ['autodocs'], + title: 'Collection Section', +}; + +export const Default = { + args: { + collectionData: yaleClubCollectionData as Collection, + }, +}; + +export const Minimal = { + args: { + collectionData: baseCollectionData as Collection, + }, +}; + +export const UnpublishedNoButton = { + args: { + collectionData: unpublishedCollectionData, + }, +}; + +export const UnpublishedWithEnabledButton = { + args: { + collectionData: unpublishedCollectionData, + isEnabled: true, + }, +}; diff --git a/src/components/CollectionSection/CollectionSection.styles.ts b/src/components/CollectionSection/CollectionSection.styles.ts index 465c388..b4457c1 100644 --- a/src/components/CollectionSection/CollectionSection.styles.ts +++ b/src/components/CollectionSection/CollectionSection.styles.ts @@ -1,6 +1,9 @@ import type { Theme } from '@mui/material/styles'; const styles = { + badge: { + fontSize: 'inherit', + }, contentContainer: { alignContent: 'center', }, diff --git a/src/components/CollectionSection/CollectionSection.tsx b/src/components/CollectionSection/CollectionSection.tsx index 6e11a32..5d9275e 100644 --- a/src/components/CollectionSection/CollectionSection.tsx +++ b/src/components/CollectionSection/CollectionSection.tsx @@ -29,6 +29,7 @@ const CollectionSection = observer(({ {collection.badge} diff --git a/src/components/CollectionStoriesList/CollectionStoriesList.tsx b/src/components/CollectionStoriesList/CollectionStoriesList.tsx index 1d0b8e2..7db45d4 100644 --- a/src/components/CollectionStoriesList/CollectionStoriesList.tsx +++ b/src/components/CollectionStoriesList/CollectionStoriesList.tsx @@ -1,4 +1,5 @@ import { observer } from 'mobx-react-lite'; +import { When } from 'react-if'; import useCollection from '../../hooks/useCollection'; import StoryCards from '../StoryCards/StoryCards'; @@ -6,15 +7,17 @@ import StoryCards from '../StoryCards/StoryCards'; const CollectionStoriesList = observer(() => { const collection = useCollection(); return ( - + + + ); }); diff --git a/src/components/Collections/Collections.stories.tsx b/src/components/Collections/Collections.stories.tsx index bc59735..87c8504 100644 --- a/src/components/Collections/Collections.stories.tsx +++ b/src/components/Collections/Collections.stories.tsx @@ -1,44 +1,94 @@ import type { FC } from 'react'; +import { useMemo } from 'react'; import StoriesAPIProvider from '../../providers/StoriesAPIProvider'; import CollectionStore from '../../state/collectionStore'; +import RootStore from '../../state/rootStore'; import { baseStorybookDecorator } from '../../stories/decorators'; import yaleClubCollectionsData from '../../tests/fixtures/collections--yale-club.json'; import type { Collection } from '../../types'; import { fakeGoToPath } from '../../utils/debug'; import Collections from './Collections'; -const yaleClubCollections = yaleClubCollectionsData.map( - (data) => new CollectionStore(null as never, { collection: data as Collection }), -); +type CollectionsStoryArgs = { + readonly buttonLabel?: string; + readonly collectionPathFormatter?: string; + readonly collectionsData: Collection[]; + readonly isAllCollectionsEnabled?: boolean; + readonly layout?: 'list' | 'sections'; +}; + +const buildCollectionsStores = (collectionsData: Collection[]) => { + const rootStore = new RootStore(); + return collectionsData.map((collection) => new CollectionStore(rootStore, { collection })); +}; + +function StoryRenderer({ + buttonLabel = undefined, + collectionPathFormatter = undefined, + collectionsData, + isAllCollectionsEnabled = undefined, + layout = undefined, +}: CollectionsStoryArgs) { + const collections = useMemo( + () => buildCollectionsStores(collectionsData), + [collectionsData], + ); + + return ( + + ); +} + +function renderStory(args: CollectionsStoryArgs) { + return ( + + ); +} export default { args: { - collections: yaleClubCollections, + collectionsData: yaleClubCollectionsData as Collection[], }, argTypes: { + collectionsData: { + control: false, + table: { disable: true }, + }, }, component: Collections, decorators: [ baseStorybookDecorator, ], parameters: { - deepControls: { enabled: true }, layout: 'centered', }, + render: renderStory, tags: ['autodocs'], title: 'Collections', }; export const SampleCollection = { args: { - collections: yaleClubCollections, + collectionsData: yaleClubCollectionsData as Collection[], }, }; export const YaleClubCollectionDemo = { args: { - collection: yaleClubCollectionsData, + collectionsData: yaleClubCollectionsData as Collection[], layout: 'sections', }, decorators: [ diff --git a/src/components/Moments/AVBaseMoment/index.ts b/src/components/Moments/AVBaseMoment/index.ts new file mode 100644 index 0000000..78231b8 --- /dev/null +++ b/src/components/Moments/AVBaseMoment/index.ts @@ -0,0 +1,2 @@ +export { default as AVBaseMoment } from './AVBaseMoment'; +export type { AVBaseMomentProps } from './AVBaseMoment.types'; diff --git a/src/components/Moments/BaseMoment/index.ts b/src/components/Moments/BaseMoment/index.ts new file mode 100644 index 0000000..5dedb89 --- /dev/null +++ b/src/components/Moments/BaseMoment/index.ts @@ -0,0 +1,2 @@ +export { default as BaseMoment } from './BaseMoment'; +export type { BaseMomentProps } from './BaseMoment.types'; diff --git a/src/components/Moments/CardsBaseMoment/index.ts b/src/components/Moments/CardsBaseMoment/index.ts new file mode 100644 index 0000000..bc09b4f --- /dev/null +++ b/src/components/Moments/CardsBaseMoment/index.ts @@ -0,0 +1,2 @@ +export { default as CardsBaseMoment } from './CardsBaseMoment'; +export type { CardsBaseMomentProps } from './CardsBaseMoment.types'; diff --git a/src/components/Moments/IFrameMoment/index.ts b/src/components/Moments/IFrameMoment/index.ts new file mode 100644 index 0000000..269ffe7 --- /dev/null +++ b/src/components/Moments/IFrameMoment/index.ts @@ -0,0 +1,2 @@ +export { default as IFrameMoment } from './IFrameMoment'; +export type { IFrameMomentProps } from './IFrameMoment.types'; diff --git a/src/components/StoriesAPICollection/StoriesAPICollection.tsx b/src/components/StoriesAPICollection/StoriesAPICollection.tsx index 5c6fc8b..f534909 100644 --- a/src/components/StoriesAPICollection/StoriesAPICollection.tsx +++ b/src/components/StoriesAPICollection/StoriesAPICollection.tsx @@ -56,7 +56,7 @@ const StoriesAPICollection = observer(({ setSearchParams(queryParams); }; - const handleSearch = async (_: string, collectionStore: CollectionStore) => { + const handleSearch = async (collectionStore: CollectionStore) => { if (connectRouter) { updateSearchParams(collectionStore); } diff --git a/src/components/StoryMoment/StoryMoment.tsx b/src/components/StoryMoment/StoryMoment.tsx index 5ebf0a6..e9ab247 100644 --- a/src/components/StoryMoment/StoryMoment.tsx +++ b/src/components/StoryMoment/StoryMoment.tsx @@ -1,5 +1,6 @@ import { observer } from 'mobx-react-lite'; -import { lazy, Suspense } from 'react'; +import type { ComponentType, LazyExoticComponent } from 'react'; +import { lazy, Suspense, useMemo } from 'react'; import { useErrorBoundary } from 'react-use-error-boundary'; import { MomentProvider } from '../../providers'; @@ -7,12 +8,31 @@ import ErrorMoment from '../Moments/ErrorMoment/ErrorMoment'; import StatusPage from '../UI/StatusPage/StatusPage'; import type { StoryMomentProps } from './StoryMoment.types'; +type ResolvedMomentComponent = + ComponentType + | LazyExoticComponent>; + const StoryMoment = observer(({ moment }: StoryMomentProps) => { - const MomentComponent = lazy(() => import( - `../Moments/${moment.component}/${moment.component}.tsx` - )); + const BuiltInMomentComponent = useMemo(() => { + if (typeof moment.component !== 'string') { + return null; + } + + return lazy(() => import( + `../Moments/${moment.component}/${moment.component}.tsx` + )); + }, [moment.component]); + const [error] = useErrorBoundary(); - const Moment = error ? ErrorMoment : MomentComponent; + let Moment: ResolvedMomentComponent = ErrorMoment; + if (!error) { + if (typeof moment.component === 'string') { + Moment = BuiltInMomentComponent ?? ErrorMoment; + } else { + Moment = moment.component; + } + } + return ( , + customActionMap: Record, ): StoryIdAction[] => ( actionsProp || ([ @@ -87,7 +87,7 @@ export const isBuiltInStoryIdAction = ( ); export const isStoryIdActionDisabled = ( - actionConfig: StoryIdActionDefinition | undefined, + actionConfig: StoryIdActionPlugin | undefined, context: StoryIdActionContext, ): boolean => { if (!actionConfig) return true; @@ -98,7 +98,7 @@ export const isStoryIdActionDisabled = ( }; export const isStoryIdActionVisible = ( - actionConfig: StoryIdActionDefinition | undefined, + actionConfig: StoryIdActionPlugin | undefined, context: StoryIdActionContext, ): boolean => { if (!actionConfig) return false; diff --git a/src/components/UI/StoryId/StoryId.types.ts b/src/components/UI/StoryId/StoryId.types.ts index 9b8ccd4..b176149 100644 --- a/src/components/UI/StoryId/StoryId.types.ts +++ b/src/components/UI/StoryId/StoryId.types.ts @@ -4,7 +4,7 @@ import type { StoryIdAction, StoryIdActionConfig, StoryIdActionContext, - StoryIdActionDefinition, + StoryIdActionPlugin, StoryOrSummary, } from '../../../types'; import type { MenuTooltipProps } from '../MenuTooltip/MenuTooltip.types'; @@ -25,12 +25,12 @@ export type StoryIdEnabledActionsParams = { readonly actionMap: Record; readonly actions: StoryIdAction[]; readonly context: StoryIdActionContext; - readonly customActionMap: Record; + readonly customActionMap: Record; }; export type StoryIdResolveActionParams = { readonly actionMap: Record; - readonly customActionMap: Record; + readonly customActionMap: Record; }; export type StoryIdProps = Omit & { diff --git a/src/components/index.ts b/src/components/index.ts index 1f78845..2f2b18d 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,4 +1,8 @@ export * from './Collection'; +export * from './Moments/AVBaseMoment'; +export * from './Moments/BaseMoment'; +export * from './Moments/CardsBaseMoment'; +export * from './Moments/IFrameMoment'; export * from './StoriesAPIButton'; export * from './StoriesAPICollection'; export * from './StoriesAPICollections'; diff --git a/src/configs/momentConfig.ts b/src/configs/momentConfig.ts index b3c83c5..a6b3483 100644 --- a/src/configs/momentConfig.ts +++ b/src/configs/momentConfig.ts @@ -20,20 +20,9 @@ import VideoMomentStore from '../state/moments/videoMomentStore'; import WikidataMomentStore from '../state/moments/wikidataMomentStore'; import WikipediaMomentStore from '../state/moments/wikipediaMomentStore'; import YouTubeMomentStore from '../state/moments/youTubeMomentStore'; -import MomentsStore from '../state/momentsStore'; -import MomentStore from '../state/momentStore'; -import type { Icon, Moment, MomentType } from '../types'; +import type { MomentConfigMap as IMomentConfigMap } from '../types'; -// KSN TODO: Add Plugin framework to bind component as a caller -export type MomentConfig = { - component: string; - icon?: Icon; - store: (moments: MomentsStore, moment: Moment) => MomentStore; -}; - -export type IMomentConfigMap = Record; - -const MomentConfigMap: Record = { +const MomentConfigMap: IMomentConfigMap = { awards: { component: 'AwardsMoment', icon: { name: 'trophy', type: 'mui' }, diff --git a/src/hooks/useCardsBrowserSearch.ts b/src/hooks/useCardsBrowserSearch.ts index 63665e1..7a44f88 100644 --- a/src/hooks/useCardsBrowserSearch.ts +++ b/src/hooks/useCardsBrowserSearch.ts @@ -99,11 +99,8 @@ export default function useCardsBrowserSearch(search: SearchStore): UseCardsBrow const handleSearchInputKeyDown = async ( event: KeyboardEvent, ) => { - if (!search.shouldShowInputSuggestions) { - return; - } - if (event.key === 'ArrowDown') { + if (!search.shouldShowInputSuggestions) return; event.preventDefault(); setActiveSuggestionIndex((currentIndex) => { const nextIndex = currentIndex + 1; @@ -113,6 +110,7 @@ export default function useCardsBrowserSearch(search: SearchStore): UseCardsBrow } if (event.key === 'ArrowUp') { + if (!search.shouldShowInputSuggestions) return; event.preventDefault(); setActiveSuggestionIndex((currentIndex) => { if (currentIndex <= 0) { @@ -128,14 +126,15 @@ export default function useCardsBrowserSearch(search: SearchStore): UseCardsBrow return; } - if (event.key === 'Enter' && activeSuggestionIndex >= 0) { + if (event.key === 'Enter') { event.preventDefault(); - const [selectedSuggestion] = search.inputSuggestions.slice( - activeSuggestionIndex, - activeSuggestionIndex + 1, - ); + const selectedSuggestion = activeSuggestionIndex >= 0 + ? search.inputSuggestions[activeSuggestionIndex] + : undefined; if (selectedSuggestion) { await applySuggestionWithTransition(selectedSuggestion, 'input'); + } else { + await search.submit(); } } }; diff --git a/src/state/collectionStore.ts b/src/state/collectionStore.ts index 1e52df6..a708b2b 100644 --- a/src/state/collectionStore.ts +++ b/src/state/collectionStore.ts @@ -40,7 +40,7 @@ export type CollectionStoreOptions = { readonly layout?: CardsBrowserLayout; readonly onPageChange?: (page: number, collection: CollectionStore) => Promise; readonly onSave?: (collection: Collection) => Promise; - readonly onSearch?: (searchInput: string, collection: CollectionStore) => Promise; + readonly onSearch?: (collection: CollectionStore) => Promise; readonly page?: number; readonly pageSize?: number; readonly searchDefaultFacets?: SelectedSearchFacets; @@ -262,7 +262,7 @@ export default class CollectionStore { } get shouldShowStoriesListHeader() { - return this.options.showStoriesListHeader !== false; + return this.options.showStoriesListHeader !== false && this.shouldShowStoriesList; } get shouldShowStoryId() { @@ -341,6 +341,7 @@ export default class CollectionStore { disabled: !this.searchIsEnabled, enableInputSuggestions: this.options.showInputSearchSuggestions, enableLandingSuggestions: this.options.showLandingSearchSuggestions, + extraFingerprint: () => JSON.stringify(this.storyStatuses), facets: this.collection.search_facets, onSearch: this.searchStories.bind(this), placeholder: this.root.locale.translate?.('collection.search.defaultPlaceholder') @@ -457,10 +458,10 @@ export default class CollectionStore { } } - async searchStories(_query: string, bypassCache: boolean = false) { + async searchStories(bypassCache: boolean = false) { this.resetPage(); await this.loadStories(bypassCache); - await this.options.onSearch?.(this.search.query, this); + await this.options.onSearch?.(this); return this.storiesCount; } diff --git a/src/state/rootStore.ts b/src/state/rootStore.ts index 597d153..f3a484c 100644 --- a/src/state/rootStore.ts +++ b/src/state/rootStore.ts @@ -2,13 +2,15 @@ import type { ThemeOptions } from '@mui/material/styles'; import { makeAutoObservable } from 'mobx'; import { type Context, createContext } from 'react'; -import MomentConfigMap from '../configs/momentConfig'; import type { LocalizationConfig, + MomentConfigMap, + MomentPlugin, ProjectId, StoriesAPIFormatters, - StoryIdActionDefinition, + StoryIdActionPlugin, } from '../types'; +import { buildMomentConfigMap } from '../utils/momentConfigUtils'; import APIStore, { type APIStoreOptions } from './apiStore'; import AVStore from './avStore'; import CollectionsStore from './collectionsStore'; @@ -28,7 +30,8 @@ export type RootStoreOptions = { readonly goToPath?: (path: string) => void; readonly isDebugging?: boolean; readonly isMobile?: boolean; - readonly storyIdActions?: Record; + readonly momentPlugins?: Record; + readonly storyIdActions?: Record; readonly themeOptions?: ThemeOptions; }; @@ -55,13 +58,13 @@ export default class RootStore { isDebugging = false; - momentConfigMap = MomentConfigMap; + momentConfigMap: MomentConfigMap; projectId?: ProjectId; stories: StoriesStore; - storyIdActions: Record; + storyIdActions: Record; theme: ThemeStore; @@ -72,6 +75,7 @@ export default class RootStore { goToPath, isDebugging = false, isMobile, + momentPlugins, projectId, storyIdActions, themeOptions, @@ -89,6 +93,7 @@ export default class RootStore { this.stories = new StoriesStore(this); this.theme = new ThemeStore(this, { isMobile, themeOptions }); this.isDebugging = isDebugging; + this.momentConfigMap = buildMomentConfigMap(momentPlugins); this.projectId = projectId; this.storyIdActions = storyIdActions ?? {}; } diff --git a/src/state/searchStore.test.ts b/src/state/searchStore.test.ts index 85c8167..ec41682 100644 --- a/src/state/searchStore.test.ts +++ b/src/state/searchStore.test.ts @@ -18,7 +18,7 @@ describe('SearchStore request concurrency', () => { const first = createDeferred(); const second = createDeferred(); const onSearch = jest - .fn, [string]>() + .fn, [boolean?]>() .mockImplementationOnce(() => first.promise) .mockImplementationOnce(() => second.promise); @@ -55,7 +55,7 @@ describe('SearchStore request concurrency', () => { const first = createDeferred(); const second = createDeferred(); const onSearch = jest - .fn, [string]>() + .fn, [boolean?]>() .mockImplementationOnce(() => first.promise) .mockImplementationOnce(() => second.promise); @@ -87,11 +87,106 @@ describe('SearchStore request concurrency', () => { expect(store.loading).toBe(false); expect(store.count).toBe(8); }); + + it('does not trigger trailing fetch when only draft query changes during loading', async () => { + const first = createDeferred(); + const onSearch = jest + .fn, [boolean?]>() + .mockImplementationOnce(() => first.promise); + + const store = new SearchStore({} as never, { + onSearch, + query: 'langston', + }); + + const firstSubmitPromise = store.submit(); + + // User keeps typing, but has not submitted the new draft query. + store.setQuery('langston hughes'); + + first.resolve(10); + await firstSubmitPromise; + + expect(onSearch).toHaveBeenCalledTimes(1); + expect(onSearch).toHaveBeenNthCalledWith(1, false); + expect(store.committedQuery).toBe('langston'); + expect(store.count).toBe(10); + expect(store.loading).toBe(false); + }); + + it('queues explicit submit during loading and uses the latest draft query', async () => { + const first = createDeferred(); + const second = createDeferred(); + const onSearch = jest + .fn, [boolean?]>() + .mockImplementationOnce(() => first.promise) + .mockImplementationOnce(() => second.promise); + + const store = new SearchStore({} as never, { + onSearch, + query: 'langston', + }); + + const firstSubmitPromise = store.submit(); + + store.setQuery('langston hughes'); + store.submit(); + + first.resolve(10); + await Promise.resolve(); + + expect(onSearch).toHaveBeenCalledTimes(2); + expect(onSearch).toHaveBeenNthCalledWith(1, false); + expect(onSearch).toHaveBeenNthCalledWith(2, false); + expect(store.committedQuery).toBe('langston hughes'); + + second.resolve(20); + await firstSubmitPromise; + + expect(store.count).toBe(20); + expect(store.loading).toBe(false); + }); + + it('does not apply stale count when committed facets change during an in-flight request', async () => { + const first = createDeferred(); + const second = createDeferred(); + const onSearch = jest + .fn, [boolean?]>() + .mockImplementationOnce(() => first.promise) + .mockImplementationOnce(() => second.promise); + + const store = new SearchStore({} as never, { + onSearch, + searchOnFacetChange: true, + }); + + store.setQuery('langston'); + const firstSubmitPromise = store.submit(); + + // Simulate committed facet updates while the first request is running. + store.selectFacetValue('category', 'poetry'); + + first.resolve(10); + await Promise.resolve(); + + // A trailing request should run and stale count should not be committed. + expect(onSearch).toHaveBeenCalledTimes(2); + expect(onSearch).toHaveBeenNthCalledWith(1, false); + expect(onSearch).toHaveBeenNthCalledWith(2, false); + expect(store.count).not.toBe(10); + expect(store.loading).toBe(true); + + second.resolve(20); + await firstSubmitPromise; + + expect(store.count).toBe(20); + expect(store.loading).toBe(false); + }); }); describe('SearchStore suggestions', () => { it('shows input suggestions when query is typed and input suggestions are enabled', () => { - const onSearch = jest.fn, [string]>().mockResolvedValue(0); + const onSearch = jest.fn, [boolean?]>().mockResolvedValue(0); const store = new SearchStore({} as never, { onSearch, suggestions: [ @@ -112,7 +207,7 @@ describe('SearchStore suggestions', () => { }); it('shows landing suggestions only in emptyLanding mode with no search content', () => { - const onSearch = jest.fn, [string]>().mockResolvedValue(0); + const onSearch = jest.fn, [boolean?]>().mockResolvedValue(0); const store = new SearchStore({} as never, { onSearch, startMode: 'emptyLanding', @@ -133,7 +228,7 @@ describe('SearchStore suggestions', () => { }); it('applies suggestion query and facets before searching', async () => { - const onSearch = jest.fn, [string]>().mockResolvedValue(3); + const onSearch = jest.fn, [boolean?]>().mockResolvedValue(3); const store = new SearchStore({} as never, { onSearch, suggestions: [ @@ -150,12 +245,13 @@ describe('SearchStore suggestions', () => { await store.applySuggestion(store.suggestions[0]); expect(store.query).toBe('langston hughes'); + expect(store.committedQuery).toBe('langston hughes'); expect(store.selectedFacets).toEqual({ category: ['poetry'] }); - expect(onSearch).toHaveBeenCalledWith('langston hughes', false); + expect(onSearch).toHaveBeenCalledWith(false); }); it('keeps query blank when suggestion query is missing or null', async () => { - const onSearch = jest.fn, [string]>().mockResolvedValue(5); + const onSearch = jest.fn, [boolean?]>().mockResolvedValue(5); const store = new SearchStore({} as never, { onSearch, suggestions: [ @@ -172,13 +268,14 @@ describe('SearchStore suggestions', () => { await store.applySuggestion(store.suggestions[0]); expect(store.query).toBe(''); + expect(store.committedQuery).toBe(''); expect(store.selectedFacets).toEqual({ P8: ['Q4'] }); - expect(onSearch).toHaveBeenCalledWith('', false); + expect(onSearch).toHaveBeenCalledWith(false); }); it('shows suggestion display name as placeholder while loading, then restores default', async () => { const deferred = createDeferred(); - const onSearch = jest.fn, [string]>().mockImplementation( + const onSearch = jest.fn, [boolean?]>().mockImplementation( () => deferred.promise, ); const store = new SearchStore({} as never, { @@ -199,7 +296,7 @@ describe('SearchStore suggestions', () => { expect(store.loading).toBe(true); expect(store.placeholder).toBe('Works during the Harlem Renaissance'); - expect(onSearch).toHaveBeenCalledWith('', false); + expect(onSearch).toHaveBeenCalledWith(false); deferred.resolve(4); await applyPromise; diff --git a/src/state/searchStore.ts b/src/state/searchStore.ts index c2c0f3b..b0c13bd 100644 --- a/src/state/searchStore.ts +++ b/src/state/searchStore.ts @@ -40,8 +40,9 @@ export type SearchStoreOptions = { disabled?: boolean; enableInputSuggestions?: boolean; enableLandingSuggestions?: boolean; + extraFingerprint?: () => string; facets?: Nullable; - onSearch: (query: string, bypassCache?: boolean) => Promise; + onSearch: (bypassCache?: boolean) => Promise; placeholder?: string; query?: string; startMode?: SearchStartMode; @@ -51,6 +52,8 @@ export type SearchStoreOptions = { }; export default class SearchStore { + committedQuery: string; + count: Nullable = null; // null means unknown, 0 shows no results debouncedSubmit: () => void; @@ -63,6 +66,8 @@ export default class SearchStore { facets: Nullable; + private hasPendingSubmit = false; + isFocused: boolean = false; loading: boolean; @@ -89,6 +94,7 @@ export default class SearchStore { this.count = options.count; this.disabled = options.disabled || false; this.query = options.query ?? ''; + this.committedQuery = this.query; this.selectedFacets = options.selectedFacets || {}; this.facets = options.facets; this.loading = false; @@ -199,7 +205,7 @@ export default class SearchStore { ) : undefined; return { facets, - q: this.query || undefined, + q: this.committedQuery || undefined, }; } @@ -313,8 +319,8 @@ export default class SearchStore { private getQueryFingerprint(): string { return JSON.stringify({ facets: this.selectedFacets, - q: this.query, - }); + q: this.committedQuery, + }) + (this.options.extraFingerprint?.() ?? ''); } /** @@ -415,21 +421,34 @@ export default class SearchStore { } if (this.loading && !force) { + this.hasPendingSubmit = true; return; } + this.hasPendingSubmit = false; + + // Commit current draft query into the request state for this run. + this.committedQuery = this.query; + this.startLoading(); - this.runningQuery = this.getQueryFingerprint(); + const requestFingerprint = this.getQueryFingerprint(); + this.runningQuery = requestFingerprint; try { // Call onSearch with bypassCache parameter - const count = await this.options.onSearch(this.query, bypassCache); - this.setCount(count); + const count = await this.options.onSearch(bypassCache); + const currentQuery = this.getQueryFingerprint(); + + // Ignore stale responses when input changed while request was in flight. + if (currentQuery === requestFingerprint) { + this.setCount(count); + } } finally { const currentQuery = this.getQueryFingerprint(); - const needsRefetch = currentQuery !== this.runningQuery; + const needsRefetch = currentQuery !== this.runningQuery || this.hasPendingSubmit; this.runningQuery = ''; + this.hasPendingSubmit = false; if (needsRefetch) { await this.submit(true, false); diff --git a/src/types.ts b/src/types.ts index 5adf1ac..9f259a6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -5,6 +5,8 @@ import type { GeoJSONFeature } from 'maplibre-gl'; import type { ComponentType, ReactNode } from 'react'; import type { THEME_COLOR_OPTIONS } from './constants'; +import type MomentsStore from './state/momentsStore'; +import type MomentStore from './state/momentStore'; export type AtLeastOne }> = Partial & U[keyof U]; @@ -385,6 +387,14 @@ export type MomentCaptionFit = 'card' | 'full-width'; export type MomentCaptionPosition = 'bottom' | 'left' | 'right' | 'top'; +export type MomentConfig = { + component: string | ComponentType<{ moment: MomentStore }>; + icon?: Icon; + store: (moments: MomentsStore, moment: Moment) => MomentStore; +}; + +export type MomentConfigMap = Record; + export type MomentContentFit = 'card' | 'cover' | 'full'; export type MomentContentSize = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; @@ -425,7 +435,12 @@ export type MomentId = Moment['id']; export type MomentOrMomentGroup = (Moment | MomentGroupWithMoments); -// KSN TODO: remove string when all moments are typed +export type MomentPlugin = { + readonly component: ComponentType<{ moment: MomentStore }>; + readonly icon?: Icon; + readonly store?: (moments: MomentsStore, moment: Moment) => MomentStore; +}; + export type MomentType = 'awards' | 'base' | @@ -697,7 +712,7 @@ export type StoryId = Story['id']; export type StoryIdAction = StoryIdActionName | StoryIdCustomAction; -export type StoryIdActionConfig = StoryIdActionDefinition & { +export type StoryIdActionConfig = StoryIdActionPlugin & { readonly name: string; readonly icon?: ComponentType<{ sx?: SxProps }>; }; @@ -707,7 +722,7 @@ export type StoryIdActionContext = { readonly story: StoryOrSummary; }; -export type StoryIdActionDefinition = { +export type StoryIdActionPlugin = { readonly disabled?: boolean | ((context: StoryIdActionContext) => boolean); readonly icon?: ComponentType<{ sx?: SxProps }>; readonly label: string; @@ -718,7 +733,7 @@ export type StoryIdActionDefinition = { export type StoryIdActionName = 'story' | 'external-link' | 'clipboard' | (string & Record); -export type StoryIdCustomAction = StoryIdActionDefinition & { +export type StoryIdCustomAction = StoryIdActionPlugin & { readonly name: string; }; diff --git a/src/utils/momentConfigUtils.ts b/src/utils/momentConfigUtils.ts new file mode 100644 index 0000000..4ff0d36 --- /dev/null +++ b/src/utils/momentConfigUtils.ts @@ -0,0 +1,25 @@ +import MomentConfigMap from '../configs/momentConfig'; +import MomentStore from '../state/momentStore'; +import type { MomentConfigMap as IMomentConfigMap, MomentPlugin } from '../types'; + +export type MomentPluginsMap = Record; + +export const buildMomentConfigMap = (plugins?: MomentPluginsMap): IMomentConfigMap => { + if (!plugins) { + return MomentConfigMap; + } + + const pluginConfigs = Object.entries(plugins).reduce((acc, [type, plugin]) => { + acc[type] = { + component: plugin.component, + icon: plugin.icon, + store: plugin.store ?? MomentStore.build, + }; + return acc; + }, {} as IMomentConfigMap); + + return { + ...MomentConfigMap, + ...pluginConfigs, + }; +}; From 0f17635d60b5ee5dae20ed33987b1ec136f714b1 Mon Sep 17 00:00:00 2001 From: Kenneth Seals-Nutt Date: Fri, 20 Mar 2026 10:31:21 -0400 Subject: [PATCH 4/5] FIX: fix MobX actions and bundling configurations Reduces strict-mode errors in the console from MobX #169 --- package-lock.json | 4 +- package.json | 2 +- rollup.config.mjs | 27 ++++++++++++ src/state/avStore.ts | 4 +- src/state/collectionStore.ts | 27 ++++++++---- src/state/collectionsStore.ts | 8 ++-- src/state/geoMapStore.ts | 16 +++++-- src/state/localeStore.ts | 6 ++- src/state/momentStore.ts | 13 ++++-- src/state/searchStore.ts | 82 ++++++++++++++++++++++------------- src/state/storyStore.ts | 18 +++++--- 11 files changed, 149 insertions(+), 58 deletions(-) diff --git a/package-lock.json b/package-lock.json index 44fe9cd..dacf2af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "react-stories-api", - "version": "1.0.0-dev-56", + "version": "1.0.0-dev-57", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "react-stories-api", - "version": "1.0.0-dev-56", + "version": "1.0.0-dev-57", "license": "MIT", "dependencies": { "@fontsource/roboto": "^5.2.10", diff --git a/package.json b/package.json index d0c9a60..c2cac8c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-stories-api", - "version": "1.0.0-dev-56", + "version": "1.0.0-dev-57", "author": "Kenneth Seals-Nutt", "babel": { "presets": [ diff --git a/rollup.config.mjs b/rollup.config.mjs index dcddbbc..e9c0991 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -1,3 +1,6 @@ +import { builtinModules } from 'node:module'; +import { isAbsolute } from 'node:path'; + import commonjs from '@rollup/plugin-commonjs'; import dynamicImportVars from '@rollup/plugin-dynamic-import-vars'; import json from '@rollup/plugin-json'; @@ -9,9 +12,33 @@ import postcss from 'rollup-plugin-postcss'; import packageJSON from './package.json' with { type: 'json' }; +const nodeBuiltins = new Set([ + ...builtinModules, + ...builtinModules.map((moduleName) => `node:${moduleName}`), +]); + +const isExternal = (id) => { + // Keep Rollup virtual modules internal. + if (id.startsWith('\0')) { + return false; + } + + // Bundle only local source files; treat bare imports as externals. + if (!id.startsWith('.') && !isAbsolute(id)) { + return true; + } + + if (nodeBuiltins.has(id)) { + return true; + } + + return false; +}; + export default [ { input: './src/index.ts', + external: isExternal, output: [ { file: packageJSON.main, diff --git a/src/state/avStore.ts b/src/state/avStore.ts index 9061dae..518d035 100644 --- a/src/state/avStore.ts +++ b/src/state/avStore.ts @@ -110,6 +110,8 @@ export default class AVStore { } setIsPlaying(isPlaying: boolean) { - this.isPlaying = isPlaying; + runInAction(() => { + this.isPlaying = isPlaying; + }); } } diff --git a/src/state/collectionStore.ts b/src/state/collectionStore.ts index a708b2b..d26fc9b 100644 --- a/src/state/collectionStore.ts +++ b/src/state/collectionStore.ts @@ -422,19 +422,26 @@ export default class CollectionStore { } onEdit() { - this.isEdited = true; - this.saveStatus = undefined; + runInAction(() => { + this.isEdited = true; + this.saveStatus = undefined; + }); } refresh = async () => { - this.collection = await this.root.api.getCollection(this.id); + const collection = await this.root.api.getCollection(this.id); + runInAction(() => { + this.collection = collection; + }); await this.loadStories(); }; reset() { - this.collection = deepCopy(this.initialCollection); - this.init(); - this.isEdited = false; + runInAction(() => { + this.collection = deepCopy(this.initialCollection); + this.init(); + this.isEdited = false; + }); } resetPage() { @@ -442,7 +449,9 @@ export default class CollectionStore { } async save() { - this.saveStatus = 'SAVING'; + runInAction(() => { + this.saveStatus = 'SAVING'; + }); const collection = this.toJSON(); try { await this.options.onSave?.(collection); @@ -454,7 +463,9 @@ export default class CollectionStore { } catch (error) { // eslint-disable-next-line no-console console.error(error); - this.saveStatus = 'FAILED'; + runInAction(() => { + this.saveStatus = 'FAILED'; + }); } } diff --git a/src/state/collectionsStore.ts b/src/state/collectionsStore.ts index 88eecbc..eb1d443 100644 --- a/src/state/collectionsStore.ts +++ b/src/state/collectionsStore.ts @@ -115,8 +115,8 @@ export default class CollectionsStore { if (this.hasCollection(key)) { collectionStore = this.getCollection(key)!; if (!collectionStore.initialized && !collectionStore.storiesAreLoading) { - await runInAction(async () => { - await collectionStore.init(); + await collectionStore.init(); + runInAction(() => { this.collections.set(key, { isLoading: false, collection: collectionStore }); }); } @@ -184,6 +184,8 @@ export default class CollectionsStore { } removeCollection(collectionId: CollectionId) { - this.collections.delete(collectionId); + runInAction(() => { + this.collections.delete(collectionId); + }); } } diff --git a/src/state/geoMapStore.ts b/src/state/geoMapStore.ts index 3d934c6..b81a43c 100644 --- a/src/state/geoMapStore.ts +++ b/src/state/geoMapStore.ts @@ -499,13 +499,17 @@ export default class GeoMapStore { }; selectKey(key: string) { - this.selectedKey = key; + runInAction(() => { + this.selectedKey = key; + }); this.goToKey(key); this.scrollInfoPanelToKey?.(key); } setScrollInfoPanelToKeyFunction(func: (key: string) => void) { - this.scrollInfoPanelToKey = func; + runInAction(() => { + this.scrollInfoPanelToKey = func; + }); } setTooltipState(tooltipState: GeoMapTooltipState | null, delay = 600) { @@ -523,7 +527,9 @@ export default class GeoMapStore { } setViewState(viewState: MapViewState) { - this.viewState = viewState; + runInAction(() => { + this.viewState = viewState; + }); } unlockTooltip() { @@ -534,6 +540,8 @@ export default class GeoMapStore { } unselectKey() { - this.selectedKey = null; + runInAction(() => { + this.selectedKey = null; + }); } } diff --git a/src/state/localeStore.ts b/src/state/localeStore.ts index 0096a76..7ac3a29 100644 --- a/src/state/localeStore.ts +++ b/src/state/localeStore.ts @@ -1,5 +1,5 @@ import type { Theme } from '@mui/material/styles'; -import { makeAutoObservable } from 'mobx'; +import { makeAutoObservable, runInAction } from 'mobx'; import localizationConfig from '../configs/localizationConfig'; import type { LocalizationConfig } from '../types'; @@ -88,7 +88,9 @@ export default class LocaleStore { if (this.locale === locale) { return; } - this.locale = locale; + runInAction(() => { + this.locale = locale; + }); this.onLocaleChange(); } diff --git a/src/state/momentStore.ts b/src/state/momentStore.ts index 0b29c24..edc8a08 100644 --- a/src/state/momentStore.ts +++ b/src/state/momentStore.ts @@ -4,6 +4,7 @@ import { computed, makeObservable, observable, + runInAction, toJS, } from 'mobx'; @@ -258,18 +259,24 @@ export default class MomentStore { } reloadComponent() { - this.refreshKey += 1; + runInAction(() => { + this.refreshKey += 1; + }); } reset(hard = false) { - this.moment = deepCopy(this.initialMoment); + runInAction(() => { + this.moment = deepCopy(this.initialMoment); + }); if (hard) { this.reloadComponent(); } } setMuiTheme(theme: Partial) { - this.muiTheme = theme; + runInAction(() => { + this.muiTheme = theme; + }); } toJSON() { diff --git a/src/state/searchStore.ts b/src/state/searchStore.ts index b0c13bd..ea5c7a7 100644 --- a/src/state/searchStore.ts +++ b/src/state/searchStore.ts @@ -363,56 +363,74 @@ export default class SearchStore { const currentValue = this.selectedFacets[key]; const values = isStringArrayValue(currentValue) ? currentValue : []; if (!values.includes(value)) { - this.selectedFacets[key] = [...values, value]; + runInAction(() => { + this.selectedFacets[key] = [...values, value]; + }); this.handleSelectedFacetsChange(); } } setDateRangeValue(key: string, value: SearchFacetDateRangeValue) { - if (value.start || value.end) { - this.selectedFacets[key] = value; - } else { - delete this.selectedFacets[key]; - } + runInAction(() => { + if (value.start || value.end) { + this.selectedFacets[key] = value; + } else { + delete this.selectedFacets[key]; + } + }); this.handleSelectedFacetsChange(); } setFocused(focused: boolean) { - this.isFocused = focused; + runInAction(() => { + this.isFocused = focused; + }); } setNumberRangeValue(key: string, value: SearchFacetNumberRangeValue) { - if (value.min !== undefined || value.max !== undefined) { - this.selectedFacets[key] = value; - } else { - delete this.selectedFacets[key]; - } + runInAction(() => { + if (value.min !== undefined || value.max !== undefined) { + this.selectedFacets[key] = value; + } else { + delete this.selectedFacets[key]; + } + }); this.handleSelectedFacetsChange(); } setNumberValue(key: string, value: number | null) { - if (value !== null) { - this.selectedFacets[key] = value; - } else { - delete this.selectedFacets[key]; - } + runInAction(() => { + if (value !== null) { + this.selectedFacets[key] = value; + } else { + delete this.selectedFacets[key]; + } + }); this.handleSelectedFacetsChange(); } setCount(count: Nullable) { - this.count = count; + runInAction(() => { + this.count = count; + }); } setQuery(query: string) { - this.query = query; + runInAction(() => { + this.query = query; + }); } startLoading() { - this.loading = true; + runInAction(() => { + this.loading = true; + }); } stopLoading() { - this.loading = false; + runInAction(() => { + this.loading = false; + }); } async submit(force: boolean = false, bypassCache: boolean = false) { @@ -421,18 +439,22 @@ export default class SearchStore { } if (this.loading && !force) { - this.hasPendingSubmit = true; + runInAction(() => { + this.hasPendingSubmit = true; + }); return; } - this.hasPendingSubmit = false; - - // Commit current draft query into the request state for this run. - this.committedQuery = this.query; + runInAction(() => { + this.hasPendingSubmit = false; + this.committedQuery = this.query; + }); this.startLoading(); const requestFingerprint = this.getQueryFingerprint(); - this.runningQuery = requestFingerprint; + runInAction(() => { + this.runningQuery = requestFingerprint; + }); try { // Call onSearch with bypassCache parameter @@ -447,8 +469,10 @@ export default class SearchStore { const currentQuery = this.getQueryFingerprint(); const needsRefetch = currentQuery !== this.runningQuery || this.hasPendingSubmit; - this.runningQuery = ''; - this.hasPendingSubmit = false; + runInAction(() => { + this.runningQuery = ''; + this.hasPendingSubmit = false; + }); if (needsRefetch) { await this.submit(true, false); diff --git a/src/state/storyStore.ts b/src/state/storyStore.ts index 829645c..2eecd92 100644 --- a/src/state/storyStore.ts +++ b/src/state/storyStore.ts @@ -224,9 +224,11 @@ export default class StoryStore { } reset() { - this.story = deepCopy(this.initialStory); + runInAction(() => { + this.story = deepCopy(this.initialStory); + this.isEdited = false; + }); this.resetMoments(); - this.isEdited = false; } resetMoments() { @@ -234,7 +236,9 @@ export default class StoryStore { } async save() { - this.saveStatus = 'SAVING'; + runInAction(() => { + this.saveStatus = 'SAVING'; + }); const story = this.toJSON(); try { await this.options.onSave?.(story); @@ -246,7 +250,9 @@ export default class StoryStore { } catch (error) { // eslint-disable-next-line no-console console.error(error); - this.saveStatus = 'FAILED'; + runInAction(() => { + this.saveStatus = 'FAILED'; + }); } } @@ -263,7 +269,9 @@ export default class StoryStore { } toggleIsEditable() { - this.isEditable = !this.isEditable; + runInAction(() => { + this.isEditable = !this.isEditable; + }); } toJSON() { From 9fd25170b2a4a5f99680154be884dedd051ea477 Mon Sep 17 00:00:00 2001 From: Kenneth Seals-Nutt Date: Fri, 20 Mar 2026 18:46:00 -0400 Subject: [PATCH 5/5] FEAT: add support for custom moment stores and plugins --- configs/loadersGlNodeShimPlugin.mjs | 98 + package-lock.json | 3095 +--------------------- package.json | 21 +- rollup.config.mjs | 74 +- src/components/UI/GeoMap/GeoMap.types.ts | 2 +- src/components/UI/Timeline/Timeline.tsx | 10 +- src/components/index.ts | 4 - src/plugins.ts | 9 + src/state/collectionStore.ts | 8 +- src/state/geoMapStore.ts | 2 +- src/state/moments/iframeMomentStore.ts | 2 +- src/state/storiesStore.ts | 2 +- src/state/storyStore.ts | 6 + src/types.ts | 1 + src/utils/timelineUtils.ts | 35 + 15 files changed, 369 insertions(+), 3000 deletions(-) create mode 100644 configs/loadersGlNodeShimPlugin.mjs create mode 100644 src/plugins.ts create mode 100644 src/utils/timelineUtils.ts diff --git a/configs/loadersGlNodeShimPlugin.mjs b/configs/loadersGlNodeShimPlugin.mjs new file mode 100644 index 0000000..db68bba --- /dev/null +++ b/configs/loadersGlNodeShimPlugin.mjs @@ -0,0 +1,98 @@ +/** + * Rollup plugin: loaders-gl-node-shim + * + * Why this exists: + * - This library is consumed in browser apps (Vite/Rollup/Webpack). + * - Some transitive deck.gl/loaders.gl modules include Node-only imports such as + * `child_process` and `worker_threads`. + * - When those imports leak into a browser bundle, Vite resolves them to + * `__vite-browser-external` placeholders. At runtime/build time this can fail + * with errors like: + * - "Module \"worker_threads\" has been externalized for browser compatibility" + * - "\"Worker\" is not exported by __vite-browser-external" + * + * What this plugin does: + * - Intercepts only loaders.gl worker-utils imports that request Node built-ins. + * - Replaces those imports with tiny virtual browser-safe shims. + * - Keeps behavior deterministic for browser builds while avoiding Node leakage. + * + * Scope guard (important): + * - We intentionally only shim imports when the importer is inside + * `@loaders.gl/worker-utils`. This prevents accidentally changing semantics for + * unrelated packages that might rely on real Node behavior. + */ + +const LOADERS_GL_NODE_SHIMS = { + childProcess: '\0loaders-gl-child-process-shim', + workerThreads: '\0loaders-gl-worker-threads-shim', +}; + +const LOADERS_GL_WORKER_UTILS_PATH = '/node_modules/@loaders.gl/worker-utils/'; + +const CHILD_PROCESS_BROWSER_SHIM = ` + // Browser shim for Node's child_process module used by loaders.gl internals. + // The browser cannot spawn OS processes, so we expose no-op/error behavior. + const unsupported = () => { + throw new Error('child_process is not available in browser builds.'); + }; + + // Preserve callback shape expected by callers that treat exec as async. + export const exec = (command, callback) => { + if (typeof callback === 'function') { + callback(new Error('child_process is not available in browser builds.'), '', ''); + } + }; + + export const spawn = unsupported; + export default { exec, spawn }; +`; + +const WORKER_THREADS_BROWSER_SHIM = ` + // Browser shim for Node's worker_threads module. + // parentPort does not exist in browser Worker contexts. + export const parentPort = null; + + // If code path tries to instantiate Node worker threads in browser, + // fail loudly with a clear message. + export class Worker { + constructor() { + throw new Error('worker_threads is not available in browser builds.'); + } + } + + export default { Worker, parentPort }; +`; + +const loadersGlNodeShimPlugin = { + name: 'loaders-gl-node-shim', + + resolveId(source, importer) { + if (!importer?.includes(LOADERS_GL_WORKER_UTILS_PATH)) { + return null; + } + + if (source === 'child_process') { + return LOADERS_GL_NODE_SHIMS.childProcess; + } + + if (source === 'worker_threads') { + return LOADERS_GL_NODE_SHIMS.workerThreads; + } + + return null; + }, + + load(id) { + if (id === LOADERS_GL_NODE_SHIMS.childProcess) { + return CHILD_PROCESS_BROWSER_SHIM; + } + + if (id === LOADERS_GL_NODE_SHIMS.workerThreads) { + return WORKER_THREADS_BROWSER_SHIM; + } + + return null; + }, +}; + +export default loadersGlNodeShimPlugin; diff --git a/package-lock.json b/package-lock.json index dacf2af..ef2f6d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,21 @@ { "name": "react-stories-api", - "version": "1.0.0-dev-57", + "version": "1.0.0-dev-60", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "react-stories-api", - "version": "1.0.0-dev-57", + "version": "1.0.0-dev-60", "license": "MIT", "dependencies": { + "@deck.gl/core": "^9.2.11", + "@deck.gl/layers": "^9.2.11", + "@deck.gl/react": "^9.2.11", "@fontsource/roboto": "^5.2.10", "@mui/stylis-plugin-rtl": "^7.3.8", - "deck.gl": "^9.2.11", "lodash.debounce": "^4.0.8", - "maplibre-gl": "^5.20.2", + "maplibre-gl": "^5.21.0", "react-countup": "^6.5.3", "react-if": "^4.1.6", "react-map-gl": "^8.1.0", @@ -25,6 +27,7 @@ "react-use-error-boundary": "^3.0.0", "stylis": "^4.3.6", "stylis-plugin-rtl": "^2.1.1", + "supercluster": "^8.0.1", "swiper": "^11.2.10" }, "devDependencies": { @@ -101,40 +104,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@amcharts/amcharts5": { - "version": "5.14.4", - "resolved": "https://registry.npmjs.org/@amcharts/amcharts5/-/amcharts5-5.14.4.tgz", - "integrity": "sha512-Tl7wQLWvsvyWVtlCIm1yhZtJviSDYjuNTnlUkO0D49GyByoK0nb9fr0DK4rUw4DVgyLcySxWBsb2lzTJm5Rd9Q==", - "license": "SEE LICENSE IN LICENSE", - "peer": true, - "dependencies": { - "@types/d3": "^7.0.0", - "@types/d3-chord": "^3.0.0", - "@types/d3-hierarchy": "3.1.1", - "@types/d3-sankey": "^0.11.1", - "@types/d3-shape": "^3.0.0", - "@types/geojson": "^7946.0.8", - "@types/polylabel": "^1.0.5", - "@types/svg-arc-to-cubic-bezier": "^3.2.0", - "d3": "^7.0.0", - "d3-chord": "^3.0.0", - "d3-force": "^3.0.0", - "d3-geo": "^3.0.0", - "d3-hierarchy": "^3.0.0", - "d3-sankey": "^0.12.3", - "d3-selection": "^3.0.0", - "d3-shape": "^3.0.0", - "d3-transition": "^3.0.0", - "d3-voronoi-treemap": "^1.1.2", - "flatpickr": "^4.6.13", - "markerjs2": "^2.29.4", - "pdfmake": "^0.2.2", - "polylabel": "^1.1.0", - "seedrandom": "^3.0.5", - "svg-arc-to-cubic-bezier": "^3.2.0", - "tslib": "^2.2.0" - } - }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -149,55 +118,6 @@ "node": ">=6.0.0" } }, - "node_modules/@arcgis/core": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@arcgis/core/-/core-4.34.8.tgz", - "integrity": "sha512-UrEBTjXpSA9fhmmnAENBzz9GG81xALTezQFMXUs2iMB+tiOckmJyBbhATI/W4lIQyUfNEK7Zm/46EP2PhDga/A==", - "license": "SEE LICENSE IN copyright.txt", - "peer": true, - "dependencies": { - "@amcharts/amcharts5": "~5.14.1", - "@arcgis/toolkit": "^4.34.0", - "@esri/arcgis-html-sanitizer": "~4.1.0", - "@esri/calcite-components": "^3.3.2", - "@vaadin/grid": "~24.9.1", - "@zip.js/zip.js": "~2.8.7", - "luxon": "~3.7.2", - "marked": "~16.3.0", - "tslib": "^2.8.1" - } - }, - "node_modules/@arcgis/lumina": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@arcgis/lumina/-/lumina-4.34.9.tgz", - "integrity": "sha512-efqO+SwR+1IYf29AATh1l2FUeypRyRINTBNkaJY+KkaFe+8gqSJ45qOmputhyzF5WTRDb7WhOYgnChjp6VYPpA==", - "license": "SEE LICENSE IN LICENSE.md", - "peer": true, - "dependencies": { - "@arcgis/toolkit": "~4.34.9", - "csstype": "^3.1.3", - "tslib": "^2.8.1" - }, - "peerDependencies": { - "@lit/context": "^1.1.5", - "lit": "^3.3.0" - }, - "peerDependenciesMeta": { - "@lit/context": { - "optional": true - } - } - }, - "node_modules/@arcgis/toolkit": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@arcgis/toolkit/-/toolkit-4.34.9.tgz", - "integrity": "sha512-wFST+eVnCwmg9NyICVyn9bsBnR+TlWklsGqG3L7xqSTgfXo6TuCThE7wtTb8xWxsTBkGvImqMUgpgLuwQuTQ1g==", - "license": "SEE LICENSE IN LICENSE.md", - "peer": true, - "dependencies": { - "tslib": "^2.8.1" - } - }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -2071,21 +1991,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@carto/api-client": { - "version": "0.5.24", - "resolved": "https://registry.npmjs.org/@carto/api-client/-/api-client-0.5.24.tgz", - "integrity": "sha512-BeHxVxOZsQDZlh6mnPIwK0yMejSUtReNn877NDhJ+B0LRR8Apz0tNTpvKvWiy3WApjNGrelRplYcc4dS2iflYA==", - "license": "MIT", - "dependencies": { - "@loaders.gl/schema": "^4.3.3", - "@types/geojson": "^7946.0.16", - "d3-format": "^3.1.0", - "d3-scale": "^4.0.2", - "h3-js": "^4.1.0", - "jsep": "^1.4.0", - "quadbin": "^0.4.1-alpha.0" - } - }, "node_modules/@chromatic-com/storybook": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-4.1.3.tgz", @@ -2499,82 +2404,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@deck.gl/aggregation-layers": { - "version": "9.2.11", - "resolved": "https://registry.npmjs.org/@deck.gl/aggregation-layers/-/aggregation-layers-9.2.11.tgz", - "integrity": "sha512-MRFbBHtMcDkOthxXnMPm6nF08DjFDACaIQsJSyHkdWtLUTSLHsWnOTn/8QbB4ka86WyNyfJy3dibLu/m3ei2ow==", - "license": "MIT", - "dependencies": { - "@luma.gl/constants": "~9.2.6", - "@luma.gl/shadertools": "~9.2.6", - "@math.gl/core": "^4.1.0", - "@math.gl/web-mercator": "^4.1.0", - "d3-hexbin": "^0.2.1" - }, - "peerDependencies": { - "@deck.gl/core": "~9.2.0", - "@deck.gl/layers": "~9.2.0", - "@luma.gl/core": "~9.2.6", - "@luma.gl/engine": "~9.2.6" - } - }, - "node_modules/@deck.gl/arcgis": { - "version": "9.2.11", - "resolved": "https://registry.npmjs.org/@deck.gl/arcgis/-/arcgis-9.2.11.tgz", - "integrity": "sha512-HMGS67qgh0API5z8vEJpk6wjlYKWfWy71r9AYI4a8XubiCM1ekvLHuLDtsVNVQIdrBbT4D0CzSDwxl/pCOgslw==", - "license": "MIT", - "dependencies": { - "@luma.gl/constants": "~9.2.6", - "esri-loader": "^3.7.0" - }, - "peerDependencies": { - "@arcgis/core": "^4.0.0", - "@deck.gl/core": "~9.2.0", - "@luma.gl/core": "~9.2.6", - "@luma.gl/engine": "~9.2.6", - "@luma.gl/webgl": "~9.2.6" - } - }, - "node_modules/@deck.gl/carto": { - "version": "9.2.11", - "resolved": "https://registry.npmjs.org/@deck.gl/carto/-/carto-9.2.11.tgz", - "integrity": "sha512-2JVzsnlsQ+VTyiazpgJCS093xAV2q3g47/fkgkYrDDRuK27sISWZNgzvQ5xLCL4s/8nGa4GuMPnDIXPWasnuOA==", - "license": "MIT", - "dependencies": { - "@carto/api-client": "^0.5.19", - "@loaders.gl/compression": "~4.3.4", - "@loaders.gl/gis": "~4.3.4", - "@loaders.gl/loader-utils": "~4.3.4", - "@loaders.gl/mvt": "~4.3.4", - "@loaders.gl/schema": "~4.3.4", - "@loaders.gl/tiles": "~4.3.4", - "@luma.gl/core": "~9.2.6", - "@luma.gl/shadertools": "~9.2.6", - "@math.gl/web-mercator": "^4.1.0", - "@types/d3-array": "^3.0.2", - "@types/d3-color": "^1.4.2", - "@types/d3-scale": "^3.0.0", - "cartocolor": "^5.0.2", - "d3-array": "^3.2.0", - "d3-color": "^3.1.0", - "d3-format": "^3.1.0", - "d3-scale": "^4.0.0", - "earcut": "^2.2.4", - "h3-js": "^4.1.0", - "moment-timezone": "^0.6.0", - "pbf": "^3.2.1", - "quadbin": "^0.4.0" - }, - "peerDependencies": { - "@deck.gl/aggregation-layers": "~9.2.0", - "@deck.gl/core": "~9.2.0", - "@deck.gl/extensions": "~9.2.0", - "@deck.gl/geo-layers": "~9.2.0", - "@deck.gl/layers": "~9.2.0", - "@loaders.gl/core": "~4.3.4", - "@luma.gl/core": "~9.2.6" - } - }, "node_modules/@deck.gl/core": { "version": "9.2.11", "resolved": "https://registry.npmjs.org/@deck.gl/core/-/core-9.2.11.tgz", @@ -2600,95 +2429,6 @@ "mjolnir.js": "^3.0.0" } }, - "node_modules/@deck.gl/extensions": { - "version": "9.2.11", - "resolved": "https://registry.npmjs.org/@deck.gl/extensions/-/extensions-9.2.11.tgz", - "integrity": "sha512-zlpM4Bg1ifBziW1Juiii9NY5gyW2rEhyVTWnhagH/bpTCZ2E73OhnToYt1ouqmoxL6lMtIjhRXz6LPb7tJbHHQ==", - "license": "MIT", - "dependencies": { - "@luma.gl/constants": "~9.2.6", - "@luma.gl/shadertools": "~9.2.6", - "@math.gl/core": "^4.1.0" - }, - "peerDependencies": { - "@deck.gl/core": "~9.2.0", - "@luma.gl/core": "~9.2.6", - "@luma.gl/engine": "~9.2.6" - } - }, - "node_modules/@deck.gl/geo-layers": { - "version": "9.2.11", - "resolved": "https://registry.npmjs.org/@deck.gl/geo-layers/-/geo-layers-9.2.11.tgz", - "integrity": "sha512-Mr3yvKyZMPmQ3ho0hSqcJu1p7a881RqQaq/dRaPs2VP56UAkfk1e10zxXnrZ9/Dmo2MR5PH0j8tkOoGR3zKbfA==", - "license": "MIT", - "dependencies": { - "@loaders.gl/3d-tiles": "~4.3.4", - "@loaders.gl/gis": "~4.3.4", - "@loaders.gl/loader-utils": "~4.3.4", - "@loaders.gl/mvt": "~4.3.4", - "@loaders.gl/schema": "~4.3.4", - "@loaders.gl/terrain": "~4.3.4", - "@loaders.gl/tiles": "~4.3.4", - "@loaders.gl/wms": "~4.3.4", - "@luma.gl/gltf": "~9.2.6", - "@luma.gl/shadertools": "~9.2.6", - "@math.gl/core": "^4.1.0", - "@math.gl/culling": "^4.1.0", - "@math.gl/web-mercator": "^4.1.0", - "@types/geojson": "^7946.0.8", - "a5-js": "^0.5.0", - "h3-js": "^4.1.0", - "long": "^3.2.0" - }, - "peerDependencies": { - "@deck.gl/core": "~9.2.0", - "@deck.gl/extensions": "~9.2.0", - "@deck.gl/layers": "~9.2.0", - "@deck.gl/mesh-layers": "~9.2.0", - "@loaders.gl/core": "~4.3.4", - "@luma.gl/core": "~9.2.6", - "@luma.gl/engine": "~9.2.6" - } - }, - "node_modules/@deck.gl/google-maps": { - "version": "9.2.11", - "resolved": "https://registry.npmjs.org/@deck.gl/google-maps/-/google-maps-9.2.11.tgz", - "integrity": "sha512-ahA+u8wkyx9vyKGekJW+Juza2jX8Yhj2+VbYQjriV4aVIJmSNiNNUqYvOwLbwhThj5HBY0jUSSQ1WixwmrBZaA==", - "license": "MIT", - "dependencies": { - "@luma.gl/constants": "~9.2.6", - "@luma.gl/webgl": "~9.2.6", - "@math.gl/core": "^4.1.0", - "@types/google.maps": "^3.48.6" - }, - "peerDependencies": { - "@deck.gl/core": "~9.2.0", - "@luma.gl/constants": "~9.2.6", - "@luma.gl/core": "~9.2.6", - "@luma.gl/webgl": "~9.2.6" - } - }, - "node_modules/@deck.gl/json": { - "version": "9.2.11", - "resolved": "https://registry.npmjs.org/@deck.gl/json/-/json-9.2.11.tgz", - "integrity": "sha512-xUc8y79kAQNqDJegDkEFWgdfE3JDaTdLtSerzwX5gR7q8mZMMZ0tcFM5IqE+mB3EoNbUgTY7m/7LnzO58XGP6g==", - "license": "MIT", - "dependencies": { - "jsep": "^0.3.0" - }, - "peerDependencies": { - "@deck.gl/core": "~9.2.0" - } - }, - "node_modules/@deck.gl/json/node_modules/jsep": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/jsep/-/jsep-0.3.5.tgz", - "integrity": "sha512-AoRLBDc6JNnKjNcmonituEABS5bcfqDhQAWWXNTFrqu6nVXBpBAGfcoTGZMFlIrh9FjmE1CQyX9CTNwZrXMMDA==", - "license": "MIT", - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/@deck.gl/layers": { "version": "9.2.11", "resolved": "https://registry.npmjs.org/@deck.gl/layers/-/layers-9.2.11.tgz", @@ -2711,41 +2451,6 @@ "@luma.gl/engine": "~9.2.6" } }, - "node_modules/@deck.gl/mapbox": { - "version": "9.2.11", - "resolved": "https://registry.npmjs.org/@deck.gl/mapbox/-/mapbox-9.2.11.tgz", - "integrity": "sha512-5OaFZgjyA4Vq6WjHUdcEdl0Phi8dwj8hSCErej0NetW90mctdbxwMt0gSbqcvWBowwhyj2QAhH0P2FcITjKG/A==", - "license": "MIT", - "dependencies": { - "@luma.gl/constants": "~9.2.6", - "@math.gl/web-mercator": "^4.1.0" - }, - "peerDependencies": { - "@deck.gl/core": "~9.2.0", - "@luma.gl/constants": "~9.2.6", - "@luma.gl/core": "~9.2.6", - "@math.gl/web-mercator": "^4.1.0" - } - }, - "node_modules/@deck.gl/mesh-layers": { - "version": "9.2.11", - "resolved": "https://registry.npmjs.org/@deck.gl/mesh-layers/-/mesh-layers-9.2.11.tgz", - "integrity": "sha512-zPB7TtnPXB3tOEoOfcOkNZo7coIq/ukIQa8HIUQLLiOE8AVSQfz3kbMmMK6rUabXlQbgSw/I/j3kFSYRHg3NGg==", - "license": "MIT", - "dependencies": { - "@loaders.gl/gltf": "~4.3.4", - "@loaders.gl/schema": "~4.3.4", - "@luma.gl/gltf": "~9.2.6", - "@luma.gl/shadertools": "~9.2.6" - }, - "peerDependencies": { - "@deck.gl/core": "~9.2.0", - "@luma.gl/core": "~9.2.6", - "@luma.gl/engine": "~9.2.6", - "@luma.gl/gltf": "~9.2.6", - "@luma.gl/shadertools": "~9.2.6" - } - }, "node_modules/@deck.gl/react": { "version": "9.2.11", "resolved": "https://registry.npmjs.org/@deck.gl/react/-/react-9.2.11.tgz", @@ -2763,6 +2468,7 @@ "resolved": "https://registry.npmjs.org/@deck.gl/widgets/-/widgets-9.2.11.tgz", "integrity": "sha512-90HWlQPsiRyTPWR4aYfLwnYDrJdHG2mqCzRcyMUKewWBNQLu4upB//l4ewIkUeXXCzAprjjVeRnNb7wdYj2CXQ==", "license": "MIT", + "peer": true, "dependencies": { "preact": "^10.17.0" }, @@ -3516,53 +3222,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@esri/arcgis-html-sanitizer": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@esri/arcgis-html-sanitizer/-/arcgis-html-sanitizer-4.1.0.tgz", - "integrity": "sha512-einEveDJ/k1180NOp78PB/4Hje9eBy3dyOGLLtLn6bSkizpUfCwuYBIXOA7Y3F/k/BsTQXgKqUVwQ0eiscWMdA==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "xss": "1.0.13" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@esri/calcite-components": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@esri/calcite-components/-/calcite-components-3.3.3.tgz", - "integrity": "sha512-tw+EfJ3pb+Odj71W6E9GUkm8rMbNxfW1KeiI8GgsKDzhr39hMKwY+zYYFFYuO0FONxWGvAB+B8yqB0NvH7WeHw==", - "license": "SEE LICENSE.md", - "peer": true, - "dependencies": { - "@arcgis/lumina": ">=4.34.0-next.158 <4.35.0", - "@arcgis/toolkit": ">=4.34.0-next.158 <4.35.0", - "@esri/calcite-ui-icons": "4.3.0", - "@floating-ui/dom": "^1.6.12", - "@floating-ui/utils": "^0.2.8", - "@types/sortablejs": "^1.15.8", - "color": "^5.0.0", - "composed-offset-position": "^0.0.6", - "es-toolkit": "^1.39.8", - "focus-trap": "^7.6.5", - "interactjs": "^1.10.27", - "lit": "^3.3.0", - "sortablejs": "^1.15.6", - "timezone-groups": "^0.10.4", - "type-fest": "^4.30.1" - } - }, - "node_modules/@esri/calcite-ui-icons": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@esri/calcite-ui-icons/-/calcite-ui-icons-4.3.0.tgz", - "integrity": "sha512-iOOuRurpjFxFVw6+aXW2JpSkRBrdOpBcbdibfPOmSPqMd1aoHBtYmYXetKoH9vfrXoBiPyO2PkDnczhsu/N9IA==", - "license": "SEE LICENSE.md", - "peer": true, - "bin": { - "spriter": "bin/spriter.js" - } - }, "node_modules/@floating-ui/core": { "version": "1.6.9", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", @@ -3605,62 +3264,6 @@ "license": "MIT", "peer": true }, - "node_modules/@foliojs-fork/fontkit": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@foliojs-fork/fontkit/-/fontkit-1.9.2.tgz", - "integrity": "sha512-IfB5EiIb+GZk+77TRB86AHroVaqfq8JRFlUbz0WEwsInyCG0epX2tCPOy+UfaWPju30DeVoUAXfzWXmhn753KA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@foliojs-fork/restructure": "^2.0.2", - "brotli": "^1.2.0", - "clone": "^1.0.4", - "deep-equal": "^1.0.0", - "dfa": "^1.2.0", - "tiny-inflate": "^1.0.2", - "unicode-properties": "^1.2.2", - "unicode-trie": "^2.0.0" - } - }, - "node_modules/@foliojs-fork/linebreak": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@foliojs-fork/linebreak/-/linebreak-1.1.2.tgz", - "integrity": "sha512-ZPohpxxbuKNE0l/5iBJnOAfUaMACwvUIKCvqtWGKIMv1lPYoNjYXRfhi9FeeV9McBkBLxsMFWTVVhHJA8cyzvg==", - "license": "MIT", - "peer": true, - "dependencies": { - "base64-js": "1.3.1", - "unicode-trie": "^2.0.0" - } - }, - "node_modules/@foliojs-fork/linebreak/node_modules/base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", - "license": "MIT", - "peer": true - }, - "node_modules/@foliojs-fork/pdfkit": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/@foliojs-fork/pdfkit/-/pdfkit-0.15.3.tgz", - "integrity": "sha512-Obc0Wmy3bm7BINFVvPhcl2rnSSK61DQrlHU8aXnAqDk9LCjWdUOPwhgD8Ywz5VtuFjRxmVOM/kQ/XLIBjDvltw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@foliojs-fork/fontkit": "^1.9.2", - "@foliojs-fork/linebreak": "^1.1.1", - "crypto-js": "^4.2.0", - "jpeg-exif": "^1.1.4", - "png-js": "^1.0.0" - } - }, - "node_modules/@foliojs-fork/restructure": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@foliojs-fork/restructure/-/restructure-2.0.2.tgz", - "integrity": "sha512-59SgoZ3EXbkfSX7b63tsou/SDGzwUEK6MuB5sKqgVK1/XE0fxmpsOb9DQI8LXW3KfGnAjImCGhhEb7uPPAUVNA==", - "license": "MIT", - "peer": true - }, "node_modules/@fontsource/roboto": { "version": "5.2.10", "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.10.tgz", @@ -3798,13 +3401,6 @@ "node": ">=18" } }, - "node_modules/@interactjs/types": { - "version": "1.10.27", - "resolved": "https://registry.npmjs.org/@interactjs/types/-/types-1.10.27.tgz", - "integrity": "sha512-BUdv0cvs4H5ODuwft2Xp4eL8Vmi3LcihK42z0Ft/FbVJZoRioBsxH+LlsBdK4tAie7PqlKGy+1oyOncu1nQ6eA==", - "license": "MIT", - "peer": true - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -4713,78 +4309,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.5.1.tgz", - "integrity": "sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==", - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/@lit/reactive-element": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.2.tgz", - "integrity": "sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.5.0" - } - }, - "node_modules/@loaders.gl/3d-tiles": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/3d-tiles/-/3d-tiles-4.3.4.tgz", - "integrity": "sha512-JQ3y3p/KlZP7lfobwON5t7H9WinXEYTvuo3SRQM8TBKhM+koEYZhvI2GwzoXx54MbBbY+s3fm1dq5UAAmaTsZw==", - "license": "MIT", - "dependencies": { - "@loaders.gl/compression": "4.3.4", - "@loaders.gl/crypto": "4.3.4", - "@loaders.gl/draco": "4.3.4", - "@loaders.gl/gltf": "4.3.4", - "@loaders.gl/images": "4.3.4", - "@loaders.gl/loader-utils": "4.3.4", - "@loaders.gl/math": "4.3.4", - "@loaders.gl/tiles": "4.3.4", - "@loaders.gl/zip": "4.3.4", - "@math.gl/core": "^4.1.0", - "@math.gl/culling": "^4.1.0", - "@math.gl/geospatial": "^4.1.0", - "@probe.gl/log": "^4.0.4", - "long": "^5.2.1" - }, - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, - "node_modules/@loaders.gl/3d-tiles/node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, - "node_modules/@loaders.gl/compression": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/compression/-/compression-4.3.4.tgz", - "integrity": "sha512-+o+5JqL9Sx8UCwdc2MTtjQiUHYQGJALHbYY/3CT+b9g/Emzwzez2Ggk9U9waRfdHiBCzEgRBivpWZEOAtkimXQ==", - "license": "MIT", - "dependencies": { - "@loaders.gl/loader-utils": "4.3.4", - "@loaders.gl/worker-utils": "4.3.4", - "@types/brotli": "^1.3.0", - "@types/pako": "^1.0.1", - "fflate": "0.7.4", - "lzo-wasm": "^0.0.4", - "pako": "1.0.11", - "snappyjs": "^0.6.1" - }, - "optionalDependencies": { - "brotli": "^1.3.2", - "lz4js": "^0.2.0", - "zstd-codec": "^0.1" - }, - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, "node_modules/@loaders.gl/core": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/@loaders.gl/core/-/core-4.3.4.tgz", @@ -4797,242 +4321,50 @@ "@probe.gl/log": "^4.0.2" } }, - "node_modules/@loaders.gl/crypto": { + "node_modules/@loaders.gl/images": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/crypto/-/crypto-4.3.4.tgz", - "integrity": "sha512-3VS5FgB44nLOlAB9Q82VOQnT1IltwfRa1miE0mpHCe1prYu1M/dMnEyynusbrsp+eDs3EKbxpguIS9HUsFu5dQ==", + "resolved": "https://registry.npmjs.org/@loaders.gl/images/-/images-4.3.4.tgz", + "integrity": "sha512-qgc33BaNsqN9cWa/xvcGvQ50wGDONgQQdzHCKDDKhV2w/uptZoR5iofJfuG8UUV2vUMMd82Uk9zbopRx2rS4Ag==", "license": "MIT", "dependencies": { - "@loaders.gl/loader-utils": "4.3.4", - "@loaders.gl/worker-utils": "4.3.4", - "@types/crypto-js": "^4.0.2" + "@loaders.gl/loader-utils": "4.3.4" }, "peerDependencies": { "@loaders.gl/core": "^4.3.0" } }, - "node_modules/@loaders.gl/draco": { + "node_modules/@loaders.gl/loader-utils": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/draco/-/draco-4.3.4.tgz", - "integrity": "sha512-4Lx0rKmYENGspvcgV5XDpFD9o+NamXoazSSl9Oa3pjVVjo+HJuzCgrxTQYD/3JvRrolW/QRehZeWD/L/cEC6mw==", + "resolved": "https://registry.npmjs.org/@loaders.gl/loader-utils/-/loader-utils-4.3.4.tgz", + "integrity": "sha512-tjMZvlKQSaMl2qmYTAxg+ySR6zd6hQn5n3XaU8+Ehp90TD3WzxvDKOMNDqOa72fFmIV+KgPhcmIJTpq4lAdC4Q==", "license": "MIT", "dependencies": { - "@loaders.gl/loader-utils": "4.3.4", "@loaders.gl/schema": "4.3.4", "@loaders.gl/worker-utils": "4.3.4", - "draco3d": "1.5.7" - }, - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, - "node_modules/@loaders.gl/gis": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/gis/-/gis-4.3.4.tgz", - "integrity": "sha512-8xub38lSWW7+ZXWuUcggk7agRHJUy6RdipLNKZ90eE0ZzLNGDstGD1qiBwkvqH0AkG+uz4B7Kkiptyl7w2Oa6g==", - "license": "MIT", - "dependencies": { - "@loaders.gl/loader-utils": "4.3.4", - "@loaders.gl/schema": "4.3.4", - "@mapbox/vector-tile": "^1.3.1", - "@math.gl/polygon": "^4.1.0", - "pbf": "^3.2.1" + "@probe.gl/log": "^4.0.2", + "@probe.gl/stats": "^4.0.2" }, "peerDependencies": { "@loaders.gl/core": "^4.3.0" } }, - "node_modules/@loaders.gl/gltf": { + "node_modules/@loaders.gl/schema": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/gltf/-/gltf-4.3.4.tgz", - "integrity": "sha512-EiUTiLGMfukLd9W98wMpKmw+hVRhQ0dJ37wdlXK98XPeGGB+zTQxCcQY+/BaMhsSpYt/OOJleHhTfwNr8RgzRg==", + "resolved": "https://registry.npmjs.org/@loaders.gl/schema/-/schema-4.3.4.tgz", + "integrity": "sha512-1YTYoatgzr/6JTxqBLwDiD3AVGwQZheYiQwAimWdRBVB0JAzych7s1yBuE0CVEzj4JDPKOzVAz8KnU1TiBvJGw==", "license": "MIT", "dependencies": { - "@loaders.gl/draco": "4.3.4", - "@loaders.gl/images": "4.3.4", - "@loaders.gl/loader-utils": "4.3.4", - "@loaders.gl/schema": "4.3.4", - "@loaders.gl/textures": "4.3.4", - "@math.gl/core": "^4.1.0" + "@types/geojson": "^7946.0.7" }, "peerDependencies": { "@loaders.gl/core": "^4.3.0" } }, - "node_modules/@loaders.gl/images": { + "node_modules/@loaders.gl/worker-utils": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/images/-/images-4.3.4.tgz", - "integrity": "sha512-qgc33BaNsqN9cWa/xvcGvQ50wGDONgQQdzHCKDDKhV2w/uptZoR5iofJfuG8UUV2vUMMd82Uk9zbopRx2rS4Ag==", + "resolved": "https://registry.npmjs.org/@loaders.gl/worker-utils/-/worker-utils-4.3.4.tgz", + "integrity": "sha512-EbsszrASgT85GH3B7jkx7YXfQyIYo/rlobwMx6V3ewETapPUwdSAInv+89flnk5n2eu2Lpdeh+2zS6PvqbL2RA==", "license": "MIT", - "dependencies": { - "@loaders.gl/loader-utils": "4.3.4" - }, - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, - "node_modules/@loaders.gl/loader-utils": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/loader-utils/-/loader-utils-4.3.4.tgz", - "integrity": "sha512-tjMZvlKQSaMl2qmYTAxg+ySR6zd6hQn5n3XaU8+Ehp90TD3WzxvDKOMNDqOa72fFmIV+KgPhcmIJTpq4lAdC4Q==", - "license": "MIT", - "dependencies": { - "@loaders.gl/schema": "4.3.4", - "@loaders.gl/worker-utils": "4.3.4", - "@probe.gl/log": "^4.0.2", - "@probe.gl/stats": "^4.0.2" - }, - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, - "node_modules/@loaders.gl/math": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/math/-/math-4.3.4.tgz", - "integrity": "sha512-UJrlHys1fp9EUO4UMnqTCqvKvUjJVCbYZ2qAKD7tdGzHJYT8w/nsP7f/ZOYFc//JlfC3nq+5ogvmdpq2pyu3TA==", - "license": "MIT", - "dependencies": { - "@loaders.gl/images": "4.3.4", - "@loaders.gl/loader-utils": "4.3.4", - "@math.gl/core": "^4.1.0" - }, - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, - "node_modules/@loaders.gl/mvt": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/mvt/-/mvt-4.3.4.tgz", - "integrity": "sha512-9DrJX8RQf14htNtxsPIYvTso5dUce9WaJCWCIY/79KYE80Be6dhcEYMknxBS4w3+PAuImaAe66S5xo9B7Erm5A==", - "license": "MIT", - "dependencies": { - "@loaders.gl/gis": "4.3.4", - "@loaders.gl/images": "4.3.4", - "@loaders.gl/loader-utils": "4.3.4", - "@loaders.gl/schema": "4.3.4", - "@math.gl/polygon": "^4.1.0", - "@probe.gl/stats": "^4.0.0", - "pbf": "^3.2.1" - }, - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, - "node_modules/@loaders.gl/schema": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/schema/-/schema-4.3.4.tgz", - "integrity": "sha512-1YTYoatgzr/6JTxqBLwDiD3AVGwQZheYiQwAimWdRBVB0JAzych7s1yBuE0CVEzj4JDPKOzVAz8KnU1TiBvJGw==", - "license": "MIT", - "dependencies": { - "@types/geojson": "^7946.0.7" - }, - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, - "node_modules/@loaders.gl/terrain": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/terrain/-/terrain-4.3.4.tgz", - "integrity": "sha512-JszbRJGnxL5Fh82uA2U8HgjlsIpzYoCNNjy3cFsgCaxi4/dvjz3BkLlBilR7JlbX8Ka+zlb4GAbDDChiXLMJ/g==", - "license": "MIT", - "dependencies": { - "@loaders.gl/images": "4.3.4", - "@loaders.gl/loader-utils": "4.3.4", - "@loaders.gl/schema": "4.3.4", - "@mapbox/martini": "^0.2.0" - }, - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, - "node_modules/@loaders.gl/textures": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/textures/-/textures-4.3.4.tgz", - "integrity": "sha512-arWIDjlE7JaDS6v9by7juLfxPGGnjT9JjleaXx3wq/PTp+psLOpGUywHXm38BNECos3MFEQK3/GFShWI+/dWPw==", - "license": "MIT", - "dependencies": { - "@loaders.gl/images": "4.3.4", - "@loaders.gl/loader-utils": "4.3.4", - "@loaders.gl/schema": "4.3.4", - "@loaders.gl/worker-utils": "4.3.4", - "@math.gl/types": "^4.1.0", - "ktx-parse": "^0.7.0", - "texture-compressor": "^1.0.2" - }, - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, - "node_modules/@loaders.gl/tiles": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/tiles/-/tiles-4.3.4.tgz", - "integrity": "sha512-oC0zJfyvGox6Ag9ABF8fxOkx9yEFVyzTa9ryHXl2BqLiQoR1v3p+0tIJcEbh5cnzHfoTZzUis1TEAZluPRsHBQ==", - "license": "MIT", - "dependencies": { - "@loaders.gl/loader-utils": "4.3.4", - "@loaders.gl/math": "4.3.4", - "@math.gl/core": "^4.1.0", - "@math.gl/culling": "^4.1.0", - "@math.gl/geospatial": "^4.1.0", - "@math.gl/web-mercator": "^4.1.0", - "@probe.gl/stats": "^4.0.2" - }, - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, - "node_modules/@loaders.gl/wms": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/wms/-/wms-4.3.4.tgz", - "integrity": "sha512-yXF0wuYzJUdzAJQrhLIua6DnjOiBJusaY1j8gpvuH1VYs3mzvWlIRuZKeUd9mduQZKK88H2IzHZbj2RGOauq4w==", - "license": "MIT", - "dependencies": { - "@loaders.gl/images": "4.3.4", - "@loaders.gl/loader-utils": "4.3.4", - "@loaders.gl/schema": "4.3.4", - "@loaders.gl/xml": "4.3.4", - "@turf/rewind": "^5.1.5", - "deep-strict-equal": "^0.2.0" - }, - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, - "node_modules/@loaders.gl/worker-utils": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/worker-utils/-/worker-utils-4.3.4.tgz", - "integrity": "sha512-EbsszrASgT85GH3B7jkx7YXfQyIYo/rlobwMx6V3ewETapPUwdSAInv+89flnk5n2eu2Lpdeh+2zS6PvqbL2RA==", - "license": "MIT", - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, - "node_modules/@loaders.gl/xml": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/xml/-/xml-4.3.4.tgz", - "integrity": "sha512-p+y/KskajsvyM3a01BwUgjons/j/dUhniqd5y1p6keLOuwoHlY/TfTKd+XluqfyP14vFrdAHCZTnFCWLblN10w==", - "license": "MIT", - "dependencies": { - "@loaders.gl/loader-utils": "4.3.4", - "@loaders.gl/schema": "4.3.4", - "fast-xml-parser": "^4.2.5" - }, - "peerDependencies": { - "@loaders.gl/core": "^4.3.0" - } - }, - "node_modules/@loaders.gl/zip": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@loaders.gl/zip/-/zip-4.3.4.tgz", - "integrity": "sha512-bHY4XdKYJm3vl9087GMoxnUqSURwTxPPh6DlAGOmz6X9Mp3JyWuA2gk3tQ1UIuInfjXKph3WAUfGe6XRIs1sfw==", - "license": "MIT", - "dependencies": { - "@loaders.gl/compression": "4.3.4", - "@loaders.gl/crypto": "4.3.4", - "@loaders.gl/loader-utils": "4.3.4", - "jszip": "^3.1.5", - "md5": "^2.3.0" - }, "peerDependencies": { "@loaders.gl/core": "^4.3.0" } @@ -5072,24 +4404,6 @@ "@luma.gl/shadertools": "~9.2.0" } }, - "node_modules/@luma.gl/gltf": { - "version": "9.2.6", - "resolved": "https://registry.npmjs.org/@luma.gl/gltf/-/gltf-9.2.6.tgz", - "integrity": "sha512-is3YkiGsWqWTmwldMz6PRaIUleufQfUKYjJTKpsF5RS1OnN+xdAO0mJq5qJTtOQpppWAU0VrmDFEVZ6R3qvm0A==", - "license": "MIT", - "dependencies": { - "@loaders.gl/core": "^4.2.0", - "@loaders.gl/gltf": "^4.2.0", - "@loaders.gl/textures": "^4.2.0", - "@math.gl/core": "^4.1.0" - }, - "peerDependencies": { - "@luma.gl/constants": "~9.2.0", - "@luma.gl/core": "~9.2.0", - "@luma.gl/engine": "~9.2.0", - "@luma.gl/shadertools": "~9.2.0" - } - }, "node_modules/@luma.gl/shadertools": { "version": "9.2.6", "resolved": "https://registry.npmjs.org/@luma.gl/shadertools/-/shadertools-9.2.6.tgz", @@ -5126,16 +4440,10 @@ "node": ">= 0.6" } }, - "node_modules/@mapbox/martini": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@mapbox/martini/-/martini-0.2.0.tgz", - "integrity": "sha512-7hFhtkb0KTLEls+TRw/rWayq5EeHtTaErgm/NskVoXmtgAQu/9D299aeyj6mzAR/6XUnYRp2lU+4IcrYRFjVsQ==", - "license": "ISC" - }, "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==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz", + "integrity": "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==", "license": "ISC" }, "node_modules/@mapbox/tiny-sdf": { @@ -5150,15 +4458,6 @@ "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==", "license": "BSD-2-Clause" }, - "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==", - "license": "BSD-3-Clause", - "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", @@ -5195,20 +4494,14 @@ } }, "node_modules/@maplibre/mlt": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@maplibre/mlt/-/mlt-1.1.7.tgz", - "integrity": "sha512-HZSsXrgn2V6T3o0qklMwKERfKaAxjO8shmiFnVygCtXTg4SPKWVX+U99RkvxUfCsjYBEcT4ltor8lSlBSCca7Q==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@maplibre/mlt/-/mlt-1.1.8.tgz", + "integrity": "sha512-8vtfYGidr1rNkv5IwIoU2lfe3Oy+Wa8HluzQYcQi9cveU9K3pweAal/poQj4GJ0K/EW4bTQp2wVAs09g2yDRZg==", "license": "(MIT OR Apache-2.0)", "dependencies": { "@mapbox/point-geometry": "^1.1.0" } }, - "node_modules/@maplibre/mlt/node_modules/@mapbox/point-geometry": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz", - "integrity": "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==", - "license": "ISC" - }, "node_modules/@maplibre/vt-pbf": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@maplibre/vt-pbf/-/vt-pbf-4.3.0.tgz", @@ -5224,12 +4517,6 @@ "supercluster": "^8.0.1" } }, - "node_modules/@maplibre/vt-pbf/node_modules/@mapbox/point-geometry": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz", - "integrity": "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==", - "license": "ISC" - }, "node_modules/@maplibre/vt-pbf/node_modules/@mapbox/vector-tile": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-2.0.4.tgz", @@ -5262,26 +4549,6 @@ "@math.gl/types": "4.1.0" } }, - "node_modules/@math.gl/culling": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@math.gl/culling/-/culling-4.1.0.tgz", - "integrity": "sha512-jFmjFEACnP9kVl8qhZxFNhCyd47qPfSVmSvvjR0/dIL6R9oD5zhR1ub2gN16eKDO/UM7JF9OHKU3EBIfeR7gtg==", - "license": "MIT", - "dependencies": { - "@math.gl/core": "4.1.0", - "@math.gl/types": "4.1.0" - } - }, - "node_modules/@math.gl/geospatial": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@math.gl/geospatial/-/geospatial-4.1.0.tgz", - "integrity": "sha512-BzsUhpVvnmleyYF6qdqJIip6FtIzJmnWuPTGhlBuPzh7VBHLonCFSPtQpbkRuoyAlbSyaGXcVt6p6lm9eK2vtg==", - "license": "MIT", - "dependencies": { - "@math.gl/core": "4.1.0", - "@math.gl/types": "4.1.0" - } - }, "node_modules/@math.gl/polygon": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@math.gl/polygon/-/polygon-4.1.0.tgz", @@ -5741,13 +5008,6 @@ "node": ">= 8" } }, - "node_modules/@open-wc/dedupe-mixin": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@open-wc/dedupe-mixin/-/dedupe-mixin-1.4.0.tgz", - "integrity": "sha512-Sj7gKl1TLcDbF7B6KUhtvr+1UCxdhMbNY5KxdU5IfMFWqL8oy1ZeAcCANjoB1TL0AJTcPmcCFsCbHf8X2jGDUA==", - "license": "MIT", - "peer": true - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -5759,16 +5019,6 @@ "node": ">=14" } }, - "node_modules/@polymer/polymer": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@polymer/polymer/-/polymer-3.5.2.tgz", - "integrity": "sha512-fWwImY/UH4bb2534DVSaX+Azs2yKg8slkMBHOyGeU2kKx7Xmxp6Lee0jP8p6B3d7c1gFUPB2Z976dTUtX81pQA==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@webcomponents/shadycss": "^1.9.1" - } - }, "node_modules/@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -6696,62 +5946,6 @@ "node": ">=10.13.0" } }, - "node_modules/@turf/boolean-clockwise": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@turf/boolean-clockwise/-/boolean-clockwise-5.1.5.tgz", - "integrity": "sha512-FqbmEEOJ4rU4/2t7FKx0HUWmjFEVqR+NJrFP7ymGSjja2SQ7Q91nnBihGuT+yuHHl6ElMjQ3ttsB/eTmyCycxA==", - "license": "MIT", - "dependencies": { - "@turf/helpers": "^5.1.5", - "@turf/invariant": "^5.1.5" - } - }, - "node_modules/@turf/clone": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-5.1.5.tgz", - "integrity": "sha512-//pITsQ8xUdcQ9pVb4JqXiSqG4dos5Q9N4sYFoWghX21tfOV2dhc5TGqYOhnHrQS7RiKQL1vQ48kIK34gQ5oRg==", - "license": "MIT", - "dependencies": { - "@turf/helpers": "^5.1.5" - } - }, - "node_modules/@turf/helpers": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-5.1.5.tgz", - "integrity": "sha512-/lF+JR+qNDHZ8bF9d+Cp58nxtZWJ3sqFe6n3u3Vpj+/0cqkjk4nXKYBSY0azm+GIYB5mWKxUXvuP/m0ZnKj1bw==", - "license": "MIT" - }, - "node_modules/@turf/invariant": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-5.2.0.tgz", - "integrity": "sha512-28RCBGvCYsajVkw2EydpzLdcYyhSA77LovuOvgCJplJWaNVyJYH6BOR3HR9w50MEkPqb/Vc/jdo6I6ermlRtQA==", - "license": "MIT", - "dependencies": { - "@turf/helpers": "^5.1.5" - } - }, - "node_modules/@turf/meta": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-5.2.0.tgz", - "integrity": "sha512-ZjQ3Ii62X9FjnK4hhdsbT+64AYRpaI8XMBMcyftEOGSmPMUVnkbvuv3C9geuElAXfQU7Zk1oWGOcrGOD9zr78Q==", - "license": "MIT", - "dependencies": { - "@turf/helpers": "^5.1.5" - } - }, - "node_modules/@turf/rewind": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@turf/rewind/-/rewind-5.1.5.tgz", - "integrity": "sha512-Gdem7JXNu+G4hMllQHXRFRihJl3+pNl7qY+l4qhQFxq+hiU1cQoVFnyoleIqWKIrdK/i2YubaSwc3SCM7N5mMw==", - "license": "MIT", - "dependencies": { - "@turf/boolean-clockwise": "^5.1.5", - "@turf/clone": "^5.1.5", - "@turf/helpers": "^5.1.5", - "@turf/invariant": "^5.1.5", - "@turf/meta": "^5.1.5" - } - }, "node_modules/@types/aria-query": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", @@ -6805,15 +5999,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/brotli": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@types/brotli/-/brotli-1.3.4.tgz", - "integrity": "sha512-cKYjgaS2DMdCKF7R0F5cgx1nfBYObN2ihIuPGQ4/dlIY6RpV7OWNwe9L8V4tTVKL2eZqOkNM9FM/rgTvLf4oXw==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/chai": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", @@ -6834,362 +6019,42 @@ "@types/node": "*" } }, - "node_modules/@types/crypto-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz", - "integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==", - "license": "MIT" - }, - "node_modules/@types/d3": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", - "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/d3-array": "*", - "@types/d3-axis": "*", - "@types/d3-brush": "*", - "@types/d3-chord": "*", - "@types/d3-color": "*", - "@types/d3-contour": "*", - "@types/d3-delaunay": "*", - "@types/d3-dispatch": "*", - "@types/d3-drag": "*", - "@types/d3-dsv": "*", - "@types/d3-ease": "*", - "@types/d3-fetch": "*", - "@types/d3-force": "*", - "@types/d3-format": "*", - "@types/d3-geo": "*", - "@types/d3-hierarchy": "*", - "@types/d3-interpolate": "*", - "@types/d3-path": "*", - "@types/d3-polygon": "*", - "@types/d3-quadtree": "*", - "@types/d3-random": "*", - "@types/d3-scale": "*", - "@types/d3-scale-chromatic": "*", - "@types/d3-selection": "*", - "@types/d3-shape": "*", - "@types/d3-time": "*", - "@types/d3-time-format": "*", - "@types/d3-timer": "*", - "@types/d3-transition": "*", - "@types/d3-zoom": "*" - } - }, - "node_modules/@types/d3-array": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", - "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", - "license": "MIT" - }, - "node_modules/@types/d3-axis": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", - "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "license": "MIT", - "peer": true, "dependencies": { - "@types/d3-selection": "*" + "@types/ms": "*" } }, - "node_modules/@types/d3-brush": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", - "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/d3-selection": "*" - } + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" }, - "node_modules/@types/d3-chord": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", - "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", - "license": "MIT", - "peer": true + "node_modules/@types/doctrine": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz", + "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==", + "dev": true, + "license": "MIT" }, - "node_modules/@types/d3-color": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-1.4.5.tgz", - "integrity": "sha512-5sNP3DmtSnSozxcjqmzQKsDOuVJXZkceo1KJScDc1982kk/TS9mTPc6lpli1gTu1MIBF1YWutpHpjucNWcIj5g==", + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, - "node_modules/@types/d3-contour": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", - "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", "license": "MIT", - "peer": true, "dependencies": { - "@types/d3-array": "*", - "@types/geojson": "*" - } - }, - "node_modules/@types/d3-delaunay": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", - "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-dispatch": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", - "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-drag": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", - "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-dsv": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", - "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-ease": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", - "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-fetch": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", - "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/d3-dsv": "*" - } - }, - "node_modules/@types/d3-force": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", - "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-format": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", - "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-geo": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", - "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/geojson": "*" - } - }, - "node_modules/@types/d3-hierarchy": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.1.tgz", - "integrity": "sha512-QwjxA3+YCKH3N1Rs3uSiSy1bdxlLB1uUiENXeJudBoAFvtDuswUxLcanoOaR2JYn1melDTuIXR8VhnVyI3yG/A==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-interpolate": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", - "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/d3-color": "*" - } - }, - "node_modules/@types/d3-path": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", - "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-polygon": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", - "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-quadtree": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", - "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-random": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", - "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-sankey": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/@types/d3-sankey/-/d3-sankey-0.11.2.tgz", - "integrity": "sha512-U6SrTWUERSlOhnpSrgvMX64WblX1AxX6nEjI2t3mLK2USpQrnbwYYK+AS9SwiE7wgYmOsSSKoSdr8aoKBH0HgQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/d3-shape": "^1" - } - }, - "node_modules/@types/d3-sankey/node_modules/@types/d3-path": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.11.tgz", - "integrity": "sha512-4pQMp8ldf7UaB/gR8Fvvy69psNHkTpD/pVw3vmEi8iZAB9EPMBruB1JvHO4BIq9QkUUd2lV1F5YXpMNj7JPBpw==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-sankey/node_modules/@types/d3-shape": { - "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-1.3.12.tgz", - "integrity": "sha512-8oMzcd4+poSLGgV0R1Q1rOlx/xdmozS4Xab7np0eamFFUYq71AU9pOCJEFnkXW2aI/oXdVYJzw6pssbSut7Z9Q==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/d3-path": "^1" - } - }, - "node_modules/@types/d3-scale": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-3.3.5.tgz", - "integrity": "sha512-YOpKj0kIEusRf7ofeJcSZQsvKbnTwpe1DUF+P2qsotqG53kEsjm7EzzliqQxMkAWdkZcHrg5rRhB4JiDOQPX+A==", - "license": "MIT", - "dependencies": { - "@types/d3-time": "^2" - } - }, - "node_modules/@types/d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-scale/node_modules/@types/d3-time": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-2.1.4.tgz", - "integrity": "sha512-BTfLsxTeo7yFxI/haOOf1ZwJ6xKgQLT9dCp+EcmQv87Gox6X+oKl4mLKfO6fnWm3P22+A6DknMNEZany8ql2Rw==", - "license": "MIT" - }, - "node_modules/@types/d3-selection": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", - "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-shape": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", - "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/d3-path": "*" - } - }, - "node_modules/@types/d3-time": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", - "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-time-format": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", - "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-timer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", - "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/d3-transition": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", - "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-zoom": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", - "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/d3-interpolate": "*", - "@types/d3-selection": "*" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/doctrine": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz", - "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "license": "MIT" - }, - "node_modules/@types/estree-jsx": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", - "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", - "license": "MIT", - "dependencies": { - "@types/estree": "*" + "@types/estree": "*" } }, "node_modules/@types/geojson": { @@ -7209,12 +6074,6 @@ "@types/node": "*" } }, - "node_modules/@types/google.maps": { - "version": "3.58.1", - "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.58.1.tgz", - "integrity": "sha512-X9QTSvGJ0nCfMzYOnaVs/k6/4L+7F5uCS+4iUmkLEls6J9S/Phv+m/i3mDeyc49ZBgwab3EFO1HEoBY7k98EGQ==", - "license": "MIT" - }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -7377,6 +6236,7 @@ "version": "22.7.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.19.2" @@ -7395,12 +6255,6 @@ "integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==", "license": "MIT" }, - "node_modules/@types/pako": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.7.tgz", - "integrity": "sha512-YBtzT2ztNF6R/9+UXj2wTGFnC9NklAnASt3sC0h2m1bbH7G6FyBIkt4AN8ThZpNfxUo1b2iMVO0UawiJymEt8A==", - "license": "MIT" - }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", @@ -7408,13 +6262,6 @@ "license": "MIT", "peer": true }, - "node_modules/@types/polylabel": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@types/polylabel/-/polylabel-1.1.3.tgz", - "integrity": "sha512-9Zw2KoDpi+T4PZz2G6pO2xArE0m/GSMTW1MIxF2s8ZY8x9XDO6fv9um0ydRGvcbkFLlaq8yNK6eZxnmMZtDgWQ==", - "license": "MIT", - "peer": true - }, "node_modules/@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", @@ -7458,13 +6305,6 @@ "rollup": "*" } }, - "node_modules/@types/sortablejs": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.9.tgz", - "integrity": "sha512-7HP+rZGE2p886PKV9c9OJzLBI6BBJu1O7lJGYnPyG3fS4/duUCcngkNCjsLwIMV+WMqANe3tt4irrXHSIe68OQ==", - "license": "MIT", - "peer": true - }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -7488,13 +6328,6 @@ "@types/geojson": "*" } }, - "node_modules/@types/svg-arc-to-cubic-bezier": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@types/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.3.tgz", - "integrity": "sha512-UNOnbTtl0nVTm8hwKaz5R5VZRvSulFMGojO5+Q7yucKxBoCaTtS4ibSQVRHo5VW5AaRo145U8p1Vfg5KrYe9Bg==", - "license": "MIT", - "peer": true - }, "node_modules/@types/tough-cookie": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", @@ -7502,13 +6335,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT", - "peer": true - }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -7744,202 +6570,6 @@ "integrity": "sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==", "license": "ISC" }, - "node_modules/@vaadin/a11y-base": { - "version": "24.9.11", - "resolved": "https://registry.npmjs.org/@vaadin/a11y-base/-/a11y-base-24.9.11.tgz", - "integrity": "sha512-R9gZEOtN9SS7HkkAKzPn0o/pM6PjI8HcBVllh7C1pn+zW554bgt31I6oClkt7ypxLa0vYReZ7bBhnGSMtHbz9w==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", - "@vaadin/component-base": "~24.9.11", - "lit": "^3.0.0" - } - }, - "node_modules/@vaadin/checkbox": { - "version": "24.9.11", - "resolved": "https://registry.npmjs.org/@vaadin/checkbox/-/checkbox-24.9.11.tgz", - "integrity": "sha512-aXXuF9K1eE67NgeTCs/aPfu/Dy96tZrMjWE6/RkK+FTYhyptCIq7pN2Ipg04ZxFyjLeMiyB4yHl/pQd5nsYT2A==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", - "@vaadin/a11y-base": "~24.9.11", - "@vaadin/component-base": "~24.9.11", - "@vaadin/field-base": "~24.9.11", - "@vaadin/vaadin-lumo-styles": "~24.9.11", - "@vaadin/vaadin-material-styles": "~24.9.11", - "@vaadin/vaadin-themable-mixin": "~24.9.11", - "lit": "^3.0.0" - } - }, - "node_modules/@vaadin/component-base": { - "version": "24.9.11", - "resolved": "https://registry.npmjs.org/@vaadin/component-base/-/component-base-24.9.11.tgz", - "integrity": "sha512-iXyrJ/VCwgoj1DNlkE2K3otDljbRa1DIysit7y/h1y/clN5gysKs4NVUFoH9j6TUHT/oQwqRaR25jN2dwRvhSQ==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", - "@vaadin/vaadin-development-mode-detector": "^2.0.0", - "@vaadin/vaadin-usage-statistics": "^2.1.0", - "lit": "^3.0.0" - } - }, - "node_modules/@vaadin/field-base": { - "version": "24.9.11", - "resolved": "https://registry.npmjs.org/@vaadin/field-base/-/field-base-24.9.11.tgz", - "integrity": "sha512-gFeomXfYsrzsaf9wJA9Av/0dJTiPNd7G27MrV3wv30nDQTL0aJ8FF7zIJsbqBRsev2F0sL7uUZEKwGhf8astew==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", - "@vaadin/a11y-base": "~24.9.11", - "@vaadin/component-base": "~24.9.11", - "lit": "^3.0.0" - } - }, - "node_modules/@vaadin/grid": { - "version": "24.9.11", - "resolved": "https://registry.npmjs.org/@vaadin/grid/-/grid-24.9.11.tgz", - "integrity": "sha512-e2TZz0r3jvodeOmEOjn5YnyDbfS1Pf7P6bzYx8yqj3psQjmZm/FhadOvpGiiJEI28CB3s9h1+QePtdZzTsb36A==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", - "@vaadin/a11y-base": "~24.9.11", - "@vaadin/checkbox": "~24.9.11", - "@vaadin/component-base": "~24.9.11", - "@vaadin/lit-renderer": "~24.9.11", - "@vaadin/text-field": "~24.9.11", - "@vaadin/vaadin-lumo-styles": "~24.9.11", - "@vaadin/vaadin-material-styles": "~24.9.11", - "@vaadin/vaadin-themable-mixin": "~24.9.11", - "lit": "^3.0.0" - } - }, - "node_modules/@vaadin/icon": { - "version": "24.9.11", - "resolved": "https://registry.npmjs.org/@vaadin/icon/-/icon-24.9.11.tgz", - "integrity": "sha512-E2Ic5BHXgcBM+JvuUjZ9mXrnmD7GG4YBd33sp1OTGelnUD2R+5M9JGpFG8etE7IhibwIWORRKlmTvyDYHHKPpQ==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", - "@vaadin/component-base": "~24.9.11", - "@vaadin/vaadin-lumo-styles": "~24.9.11", - "@vaadin/vaadin-themable-mixin": "~24.9.11", - "lit": "^3.0.0" - } - }, - "node_modules/@vaadin/input-container": { - "version": "24.9.11", - "resolved": "https://registry.npmjs.org/@vaadin/input-container/-/input-container-24.9.11.tgz", - "integrity": "sha512-gjLlTU4LlFQsiejZCvoeedSEd+ZdE9acHPBQ3ACDYikKeFp4+ENoriO/o8caEDiYX1gDyKABAkjN8oa4vTGZbA==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@polymer/polymer": "^3.0.0", - "@vaadin/component-base": "~24.9.11", - "@vaadin/vaadin-lumo-styles": "~24.9.11", - "@vaadin/vaadin-material-styles": "~24.9.11", - "@vaadin/vaadin-themable-mixin": "~24.9.11", - "lit": "^3.0.0" - } - }, - "node_modules/@vaadin/lit-renderer": { - "version": "24.9.11", - "resolved": "https://registry.npmjs.org/@vaadin/lit-renderer/-/lit-renderer-24.9.11.tgz", - "integrity": "sha512-AJUD3YK6+e+ic9n4uBQtfh/g9OZuIUeytmYe0gHNMXqVcdsBR9ZFmhwoAwFsJMUsSQy+xJuL5cQ+2GmuK37izA==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "lit": "^3.0.0" - } - }, - "node_modules/@vaadin/text-field": { - "version": "24.9.11", - "resolved": "https://registry.npmjs.org/@vaadin/text-field/-/text-field-24.9.11.tgz", - "integrity": "sha512-YPXJbAqK4XeouMB9j5BzHD+u/aVhQp+F2IZFMc2jfPPrK648m/3tb4SndMNXX8gtU0PNwCKH8WG1DT2l55DK9A==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", - "@vaadin/a11y-base": "~24.9.11", - "@vaadin/component-base": "~24.9.11", - "@vaadin/field-base": "~24.9.11", - "@vaadin/input-container": "~24.9.11", - "@vaadin/vaadin-lumo-styles": "~24.9.11", - "@vaadin/vaadin-material-styles": "~24.9.11", - "@vaadin/vaadin-themable-mixin": "~24.9.11", - "lit": "^3.0.0" - } - }, - "node_modules/@vaadin/vaadin-development-mode-detector": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@vaadin/vaadin-development-mode-detector/-/vaadin-development-mode-detector-2.0.7.tgz", - "integrity": "sha512-9FhVhr0ynSR3X2ao+vaIEttcNU5XfzCbxtmYOV8uIRnUCtNgbvMOIcyGBvntsX9I5kvIP2dV3cFAOG9SILJzEA==", - "license": "Apache-2.0", - "peer": true - }, - "node_modules/@vaadin/vaadin-lumo-styles": { - "version": "24.9.11", - "resolved": "https://registry.npmjs.org/@vaadin/vaadin-lumo-styles/-/vaadin-lumo-styles-24.9.11.tgz", - "integrity": "sha512-kU1SbpvkaCe1iZ2IrDfMRMMsauX9Ul76wFjNgJtEy43J4m4n+jekVc+KH4u6lwGmC35EOaevOIUtERi00icMSA==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@polymer/polymer": "^3.0.0", - "@vaadin/component-base": "~24.9.11", - "@vaadin/icon": "~24.9.11", - "@vaadin/vaadin-themable-mixin": "~24.9.11" - } - }, - "node_modules/@vaadin/vaadin-material-styles": { - "version": "24.9.11", - "resolved": "https://registry.npmjs.org/@vaadin/vaadin-material-styles/-/vaadin-material-styles-24.9.11.tgz", - "integrity": "sha512-c0nMkUopgvRkPtzIgx4XlXd9aQafQ1ts2LFFDmUXP8Xq/6/Voclnennrav2k0cA3gI/6ca4nEtEyruq99rI5YQ==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@polymer/polymer": "^3.0.0", - "@vaadin/component-base": "~24.9.11", - "@vaadin/vaadin-themable-mixin": "~24.9.11" - } - }, - "node_modules/@vaadin/vaadin-themable-mixin": { - "version": "24.9.11", - "resolved": "https://registry.npmjs.org/@vaadin/vaadin-themable-mixin/-/vaadin-themable-mixin-24.9.11.tgz", - "integrity": "sha512-yhVsF8hJjFqYlHuxY5ioU78MgUjUxN+khDN+czj+i9Sntss9uADkeYJH8JjzY91skMTPWY6OwJD8pJOx6WUtWA==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@open-wc/dedupe-mixin": "^1.3.0", - "lit": "^3.0.0", - "style-observer": "^0.0.8" - } - }, - "node_modules/@vaadin/vaadin-usage-statistics": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vaadin/vaadin-usage-statistics/-/vaadin-usage-statistics-2.1.3.tgz", - "integrity": "sha512-8r4TNknD7OJQADe3VygeofFR7UNAXZ2/jjBFP5dgI8+2uMfnuGYgbuHivasKr9WSQ64sPej6m8rDoM1uSllXjQ==", - "hasInstallScript": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@vaadin/vaadin-development-mode-detector": "^2.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, "node_modules/@vis.gl/react-mapbox": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/@vis.gl/react-mapbox/-/react-mapbox-8.1.0.tgz", @@ -8095,34 +6725,6 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/@webcomponents/shadycss": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.11.2.tgz", - "integrity": "sha512-vRq+GniJAYSBmTRnhCYPAPq6THYqovJ/gzGThWbgEZUQaBccndGTi1hdiUP15HzEco0I6t4RCtXyX0rsSmwgPw==", - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/@zip.js/zip.js": { - "version": "2.8.23", - "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.8.23.tgz", - "integrity": "sha512-RB+RLnxPJFPrGvQ9rgO+4JOcsob6lD32OcF0QE0yg24oeW9q8KnTTNlugcDaIveEcCbclobJcZP+fLQ++sH0bw==", - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "bun": ">=0.7.0", - "deno": ">=1.0.0", - "node": ">=18.0.0" - } - }, - "node_modules/a5-js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/a5-js/-/a5-js-0.5.0.tgz", - "integrity": "sha512-VAw19sWdYadhdovb0ViOIi1SdKx6H6LwcGMRFKwMfgL5gcmL/1fKJHfgsNgNaJ7xC/eEyjs6VK+VVd4N0a+peg==", - "license": "Apache-2.0", - "dependencies": { - "gl-matrix": "^3.4.3" - } - }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -8987,6 +7589,7 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, "funding": [ { "type": "github", @@ -9071,15 +7674,6 @@ "node": ">=8" } }, - "node_modules/brotli": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", - "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", - "license": "MIT", - "dependencies": { - "base64-js": "^1.1.2" - } - }, "node_modules/browserslist": { "version": "4.28.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", @@ -9124,15 +7718,6 @@ "node-int64": "^0.4.0" } }, - "node_modules/buf-compare": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buf-compare/-/buf-compare-1.0.1.tgz", - "integrity": "sha512-Bvx4xH00qweepGc43xFvMs5BKASXTbHaHm6+kDYIK9p/4iFwjATQkmPKHQSgJZzKbAymhztRbXUf1Nqhzl73/Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -9219,6 +7804,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.0", @@ -9237,6 +7823,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -9250,6 +7837,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -9340,15 +7928,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/cartocolor": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/cartocolor/-/cartocolor-5.0.2.tgz", - "integrity": "sha512-Ihb/wU5V6BVbHwapd8l/zg7bnhZ4YPFVfa7quSpL86lfkPJSf4YuNBT+EvesPRP5vSqhl6vZVsQJwCR8alBooQ==", - "license": "CC-BY-4.0", - "dependencies": { - "colorbrewer": "1.5.6" - } - }, "node_modules/ccount": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", @@ -9458,15 +8037,6 @@ "dev": true, "license": "MIT" }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", - "license": "BSD-3-Clause", - "engines": { - "node": "*" - } - }, "node_modules/check-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", @@ -9692,6 +8262,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8" @@ -9739,20 +8310,6 @@ "node": ">=0.10.0" } }, - "node_modules/color": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", - "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^3.1.3", - "color-string": "^2.1.3" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -9773,63 +8330,6 @@ "dev": true, "license": "MIT" }, - "node_modules/color-string": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", - "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", - "license": "MIT", - "peer": true, - "dependencies": { - "color-name": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/color-string/node_modules/color-name": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", - "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12.20" - } - }, - "node_modules/color/node_modules/color-convert": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", - "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", - "license": "MIT", - "peer": true, - "dependencies": { - "color-name": "^2.0.0" - }, - "engines": { - "node": ">=14.6" - } - }, - "node_modules/color/node_modules/color-name": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", - "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12.20" - } - }, - "node_modules/colorbrewer": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/colorbrewer/-/colorbrewer-1.5.6.tgz", - "integrity": "sha512-fONg2pGXyID8zNgKHBlagW8sb/AMShGzj4rRJfz5biZ7iuHQZYquSCLE/Co1oSQFmt/vvwjyezJCejQl7FG/tg==", - "license": [ - { - "type": "Apache-Style", - "url": "https://github.com/saikocat/colorbrewer/blob/master/LICENSE.txt" - } - ] - }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", @@ -9864,6 +8364,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, "license": "MIT", "engines": { "node": ">= 10" @@ -10095,16 +8596,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/composed-offset-position": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/composed-offset-position/-/composed-offset-position-0.0.6.tgz", - "integrity": "sha512-Q7dLompI6lUwd7LWyIcP66r4WcS9u7AL2h8HaeipiRfCRPLMWqRx8fYsjb4OHi6UQFifO7XtNC2IlEJ1ozIFxw==", - "license": "MIT", - "peer": true, - "peerDependencies": { - "@floating-ui/utils": "^0.2.5" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -11490,19 +9981,6 @@ "node": ">=0.10.0" } }, - "node_modules/core-assert": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/core-assert/-/core-assert-0.2.1.tgz", - "integrity": "sha512-IG97qShIP+nrJCXMCgkNZgH7jZQ4n8RpPyPeXX++T6avR/KhLhgLiHKoEn5Rc1KjfycSfA9DMa6m+4C4eguHhw==", - "license": "MIT", - "dependencies": { - "buf-compare": "^1.0.0", - "is-error": "^2.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/core-js": { "version": "3.42.0", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.42.0.tgz", @@ -11532,6 +10010,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, "license": "MIT" }, "node_modules/cosmiconfig": { @@ -11678,22 +10157,6 @@ "node": ">= 8" } }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", - "license": "BSD-3-Clause", - "engines": { - "node": "*" - } - }, - "node_modules/crypto-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", - "license": "MIT", - "peer": true - }, "node_modules/css-declaration-sorter": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", @@ -11781,13 +10244,6 @@ "node": ">=4" } }, - "node_modules/cssfilter": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", - "integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==", - "license": "MIT", - "peer": true - }, "node_modules/cssjanus": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cssjanus/-/cssjanus-2.3.0.tgz", @@ -11913,612 +10369,44 @@ "dev": true, "license": "MIT", "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true, - "license": "MIT" - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "license": "MIT" - }, - "node_modules/cz-conventional-changelog": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz", - "integrity": "sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^2.4.1", - "commitizen": "^4.0.3", - "conventional-commit-types": "^3.0.0", - "lodash.map": "^4.5.1", - "longest": "^2.0.1", - "word-wrap": "^1.0.3" - }, - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@commitlint/load": ">6.1.1" - } - }, - "node_modules/d3": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", - "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", - "license": "ISC", - "peer": true, - "dependencies": { - "d3-array": "3", - "d3-axis": "3", - "d3-brush": "3", - "d3-chord": "3", - "d3-color": "3", - "d3-contour": "4", - "d3-delaunay": "6", - "d3-dispatch": "3", - "d3-drag": "3", - "d3-dsv": "3", - "d3-ease": "3", - "d3-fetch": "3", - "d3-force": "3", - "d3-format": "3", - "d3-geo": "3", - "d3-hierarchy": "3", - "d3-interpolate": "3", - "d3-path": "3", - "d3-polygon": "3", - "d3-quadtree": "3", - "d3-random": "3", - "d3-scale": "4", - "d3-scale-chromatic": "3", - "d3-selection": "3", - "d3-shape": "3", - "d3-time": "3", - "d3-time-format": "4", - "d3-timer": "3", - "d3-transition": "3", - "d3-zoom": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "license": "ISC", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-axis": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", - "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-brush": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", - "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", - "license": "ISC", - "peer": true, - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "3", - "d3-transition": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-chord": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", - "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", - "license": "ISC", - "peer": true, - "dependencies": { - "d3-path": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-contour": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", - "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", - "license": "ISC", - "peer": true, - "dependencies": { - "d3-array": "^3.2.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-delaunay": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", - "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", - "license": "ISC", - "peer": true, - "dependencies": { - "delaunator": "5" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-drag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", - "license": "ISC", - "peer": true, - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-selection": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dsv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", - "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", - "license": "ISC", - "peer": true, - "dependencies": { - "commander": "7", - "iconv-lite": "0.6", - "rw": "1" - }, - "bin": { - "csv2json": "bin/dsv2json.js", - "csv2tsv": "bin/dsv2dsv.js", - "dsv2dsv": "bin/dsv2dsv.js", - "dsv2json": "bin/dsv2json.js", - "json2csv": "bin/json2dsv.js", - "json2dsv": "bin/json2dsv.js", - "json2tsv": "bin/json2dsv.js", - "tsv2csv": "bin/dsv2dsv.js", - "tsv2json": "bin/dsv2json.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dsv/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-fetch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", - "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", - "license": "ISC", - "peer": true, - "dependencies": { - "d3-dsv": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-force": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", - "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", - "license": "ISC", - "peer": true, - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-quadtree": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", - "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-geo": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", - "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", - "license": "ISC", - "peer": true, - "dependencies": { - "d3-array": "2.5.0 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-hexbin": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/d3-hexbin/-/d3-hexbin-0.2.2.tgz", - "integrity": "sha512-KS3fUT2ReD4RlGCjvCEm1RgMtp2NFZumdMu4DBzQK8AZv3fXRM6Xm8I4fSU07UXvH4xxg03NwWKWdvxfS/yc4w==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-hierarchy": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", - "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-polygon": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", - "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-quadtree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", - "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-random": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", - "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-sankey": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", - "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "d3-array": "1 - 2", - "d3-shape": "^1.2.0" - } - }, - "node_modules/d3-sankey/node_modules/d3-array": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", - "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "internmap": "^1.0.0" - } - }, - "node_modules/d3-sankey/node_modules/d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/d3-sankey/node_modules/d3-shape": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", - "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "d3-path": "1" - } - }, - "node_modules/d3-sankey/node_modules/internmap": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", - "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", - "license": "ISC", - "peer": true - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "license": "ISC", - "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", - "license": "ISC", - "peer": true, - "dependencies": { - "d3-color": "1 - 3", - "d3-interpolate": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-shape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", - "license": "ISC", - "peer": true, - "dependencies": { - "d3-path": "^3.1.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "license": "ISC", - "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", - "license": "ISC", - "peer": true, - "dependencies": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "d3-selection": "2 - 3" - } - }, - "node_modules/d3-voronoi-map": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/d3-voronoi-map/-/d3-voronoi-map-2.1.1.tgz", - "integrity": "sha512-mCXfz/kD9IQxjHaU2IMjkO8fSo4J6oysPR2iL+omDsCy1i1Qn6BQ/e4hEAW8C6ms2kfuHwqtbNom80Hih94YsA==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "d3-dispatch": "2.*", - "d3-polygon": "2.*", - "d3-timer": "2.*", - "d3-weighted-voronoi": "1.*" - } - }, - "node_modules/d3-voronoi-map/node_modules/d3-dispatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz", - "integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA==", - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/d3-voronoi-map/node_modules/d3-polygon": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-2.0.0.tgz", - "integrity": "sha512-MsexrCK38cTGermELs0cO1d79DcTsQRN7IWMJKczD/2kBjzNXxLUWP33qRF6VDpiLV/4EI4r6Gs0DAWQkE8pSQ==", - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/d3-voronoi-map/node_modules/d3-timer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz", - "integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA==", - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/d3-voronoi-treemap": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-voronoi-treemap/-/d3-voronoi-treemap-1.1.2.tgz", - "integrity": "sha512-7odu9HdG/yLPWwzDteJq4yd9Q/NwgQV7IE/u36VQtcCK7k1sZwDqbkHCeMKNTBsq5mQjDwolTsrXcU0j8ZEMCA==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "d3-voronoi-map": "2.*" - } - }, - "node_modules/d3-weighted-voronoi": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/d3-weighted-voronoi/-/d3-weighted-voronoi-1.1.3.tgz", - "integrity": "sha512-C3WdvSKl9aqhAy+f3QT3PPsQG6V+ajDfYO3BSclQDSD+araW2xDBFIH67aKzsSuuuKaX8K2y2dGq1fq/dWTVig==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "d3-array": "2", - "d3-polygon": "2" - } - }, - "node_modules/d3-weighted-voronoi/node_modules/d3-array": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", - "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "internmap": "^1.0.0" + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" } }, - "node_modules/d3-weighted-voronoi/node_modules/d3-polygon": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-2.0.0.tgz", - "integrity": "sha512-MsexrCK38cTGermELs0cO1d79DcTsQRN7IWMJKczD/2kBjzNXxLUWP33qRF6VDpiLV/4EI4r6Gs0DAWQkE8pSQ==", - "license": "BSD-3-Clause", - "peer": true + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true, + "license": "MIT" }, - "node_modules/d3-weighted-voronoi/node_modules/internmap": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", - "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", - "license": "ISC", - "peer": true + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" }, - "node_modules/d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "license": "ISC", - "peer": true, + "node_modules/cz-conventional-changelog": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz", + "integrity": "sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==", + "dev": true, + "license": "MIT", "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" + "chalk": "^2.4.1", + "commitizen": "^4.0.3", + "conventional-commit-types": "^3.0.0", + "lodash.map": "^4.5.1", + "longest": "^2.0.1", + "word-wrap": "^1.0.3" }, "engines": { - "node": ">=12" + "node": ">= 10" + }, + "optionalDependencies": { + "@commitlint/load": ">6.1.1" } }, "node_modules/damerau-levenshtein": { @@ -12681,46 +10569,6 @@ "dev": true, "license": "MIT" }, - "node_modules/deck.gl": { - "version": "9.2.11", - "resolved": "https://registry.npmjs.org/deck.gl/-/deck.gl-9.2.11.tgz", - "integrity": "sha512-oFKjJWWjEoQczfh725ypGphYGKh2sOQAFNO5/eXFlWNUZEXTTrj44ol3bmDMegL/l5qCzF4RoGWXgvLqNWphuQ==", - "license": "MIT", - "dependencies": { - "@deck.gl/aggregation-layers": "9.2.11", - "@deck.gl/arcgis": "9.2.11", - "@deck.gl/carto": "9.2.11", - "@deck.gl/core": "9.2.11", - "@deck.gl/extensions": "9.2.11", - "@deck.gl/geo-layers": "9.2.11", - "@deck.gl/google-maps": "9.2.11", - "@deck.gl/json": "9.2.11", - "@deck.gl/layers": "9.2.11", - "@deck.gl/mapbox": "9.2.11", - "@deck.gl/mesh-layers": "9.2.11", - "@deck.gl/react": "9.2.11", - "@deck.gl/widgets": "9.2.11", - "@loaders.gl/core": "~4.3.4", - "@luma.gl/core": "~9.2.6", - "@luma.gl/engine": "~9.2.6" - }, - "peerDependencies": { - "@arcgis/core": "^4.0.0", - "react": ">=16.3.0", - "react-dom": ">=16.3.0" - }, - "peerDependenciesMeta": { - "@arcgis/core": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, "node_modules/decode-named-character-reference": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz", @@ -12761,27 +10609,6 @@ "node": ">=6" } }, - "node_modules/deep-equal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", - "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", - "license": "MIT", - "peer": true, - "dependencies": { - "is-arguments": "^1.1.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.5.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -12789,18 +10616,6 @@ "dev": true, "license": "MIT" }, - "node_modules/deep-strict-equal": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/deep-strict-equal/-/deep-strict-equal-0.2.0.tgz", - "integrity": "sha512-3daSWyvZ/zwJvuMGlzG1O+Ow0YSadGfb3jsh9xoCutv2tWyB9dA4YvR9L9/fSdDZa2dByYQe+TqapSGUrjnkoA==", - "license": "MIT", - "dependencies": { - "core-assert": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -12827,6 +10642,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -12854,6 +10670,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", @@ -12881,16 +10698,6 @@ "node": ">=0.10.0" } }, - "node_modules/delaunator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", - "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", - "license": "ISC", - "peer": true, - "dependencies": { - "robust-predicates": "^3.0.2" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -12953,13 +10760,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/dfa": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", - "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==", - "license": "MIT", - "peer": true - }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -13214,16 +11014,11 @@ "node": ">=4" } }, - "node_modules/draco3d": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.7.tgz", - "integrity": "sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==", - "license": "Apache-2.0" - }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -13372,6 +11167,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -13381,6 +11177,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -13418,6 +11215,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -13469,17 +11267,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-toolkit": { - "version": "1.45.1", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.45.1.tgz", - "integrity": "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==", - "license": "MIT", - "peer": true, - "workspaces": [ - "docs", - "benchmarks" - ] - }, "node_modules/esbuild": { "version": "0.25.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", @@ -14573,13 +12360,6 @@ "node": ">=4.0" } }, - "node_modules/esri-loader": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/esri-loader/-/esri-loader-3.7.0.tgz", - "integrity": "sha512-cB1Sw9EQjtW4mtT7eFBjn/6VaaIWNTjmTd2asnnEyuZk1xVSFRMCfLZSBSjZM7ZarDcVu5WIjOP0t0MYVu4hVQ==", - "deprecated": "Use @arcgis/core instead.", - "license": "Apache-2.0" - }, "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", @@ -14931,24 +12711,6 @@ ], "license": "BSD-3-Clause" }, - "node_modules/fast-xml-parser": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.4.tgz", - "integrity": "sha512-jE8ugADnYOBsu1uaoayVl1tVKAMNOXyjwvv2U6udEA2ORBhDooJDWoGxTkhd4Qn4yh59JVVt/pKXtjPwx9OguQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "dependencies": { - "strnum": "^1.0.5" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, "node_modules/fastq": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", @@ -14984,12 +12746,6 @@ } } }, - "node_modules/fflate": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz", - "integrity": "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==", - "license": "MIT" - }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -15118,13 +12874,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/flatpickr": { - "version": "4.6.13", - "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz", - "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==", - "license": "MIT", - "peer": true - }, "node_modules/flatted": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", @@ -15132,16 +12881,6 @@ "dev": true, "license": "ISC" }, - "node_modules/focus-trap": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.8.0.tgz", - "integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==", - "license": "MIT", - "peer": true, - "dependencies": { - "tabbable": "^6.4.0" - } - }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -15309,6 +13048,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -15348,6 +13088,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -15573,6 +13314,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -16085,6 +13827,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -16107,17 +13850,6 @@ "dev": true, "license": "MIT" }, - "node_modules/h3-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/h3-js/-/h3-js-4.4.0.tgz", - "integrity": "sha512-DvJh07MhGgY2KcC4OeZc8SSyA+ZXpdvoh6uCzGpoKvWtZxJB+g6VXXC1+eWYkaMIsLz7J/ErhOalHCpcs1KYog==", - "license": "Apache-2.0", - "engines": { - "node": ">=4", - "npm": ">=3", - "yarn": ">=1.3.0" - } - }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -16194,6 +13926,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -16222,6 +13955,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -16234,6 +13968,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -16697,6 +14432,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, "funding": [ { "type": "github", @@ -16723,24 +14459,6 @@ "node": ">= 4" } }, - "node_modules/image-size": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.7.5.tgz", - "integrity": "sha512-Hiyv+mXHfFEP7LzUL/llg9RwFxxY+o9N3JVLIeG5E7iFIFAalxvRU9UZthBdYDEVnzHMgjnKJPPpay5BWf1g9g==", - "license": "MIT", - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "license": "MIT" - }, "node_modules/import-cwd": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz", @@ -16859,6 +14577,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, "license": "ISC" }, "node_modules/ini": { @@ -16923,16 +14642,6 @@ "node": ">= 0.10" } }, - "node_modules/interactjs": { - "version": "1.10.27", - "resolved": "https://registry.npmjs.org/interactjs/-/interactjs-1.10.27.tgz", - "integrity": "sha512-y/8RcCftGAF24gSp76X2JS3XpHiUvDQyhF8i7ujemBz77hwiHDuJzftHx7thY8cxGogwGiPJ+o97kWB6eAXnsA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@interactjs/types": "1.10.27" - } - }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -16948,15 +14657,6 @@ "node": ">= 0.4" } }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/is-accessor-descriptor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", @@ -16994,23 +14694,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-arguments": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", - "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", - "license": "MIT", - "peer": true, - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -17088,6 +14771,7 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, "license": "MIT" }, "node_modules/is-callable": { @@ -17153,6 +14837,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -17205,12 +14890,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-error": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-error/-/is-error-2.2.2.tgz", - "integrity": "sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==", - "license": "MIT" - }, "node_modules/is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", @@ -17428,6 +15107,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -19548,14 +17228,6 @@ "jiti": "lib/jiti-cli.mjs" } }, - "node_modules/jpeg-exif": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/jpeg-exif/-/jpeg-exif-1.1.4.tgz", - "integrity": "sha512-a+bKEcCjtuW5WTdgeXFzswSrdqi0jk4XlEtZlx5A94wCoBpFjfFTbo/Tra5SpNCl/YFZPvcV1dJc+TAYeg6ROQ==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "license": "MIT", - "peer": true - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -19621,15 +17293,6 @@ } } }, - "node_modules/jsep": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", - "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", - "license": "MIT", - "engines": { - "node": ">= 10.16.0" - } - }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -19758,54 +17421,6 @@ "node": ">=4.0" } }, - "node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "license": "(MIT OR GPL-3.0-or-later)", - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, - "node_modules/jszip/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" - }, - "node_modules/jszip/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/jszip/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, - "node_modules/jszip/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/kdbush": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", @@ -19842,12 +17457,6 @@ "node": ">=6" } }, - "node_modules/ktx-parse": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ktx-parse/-/ktx-parse-0.7.1.tgz", - "integrity": "sha512-FeA3g56ksdFNwjXJJsc1CCc7co+AJYDp6ipIp878zZ2bU8kWROatLYf39TQEd4/XRSUvBXovQ8gaVKWPXsCLEQ==", - "license": "MIT" - }, "node_modules/language-subtag-registry": { "version": "0.3.23", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", @@ -19892,15 +17501,6 @@ "node": ">= 0.8.0" } }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "license": "MIT", - "dependencies": { - "immediate": "~3.0.5" - } - }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -19915,41 +17515,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "license": "MIT" - }, - "node_modules/lit": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.2.tgz", - "integrity": "sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@lit/reactive-element": "^2.1.0", - "lit-element": "^4.2.0", - "lit-html": "^3.3.0" - } - }, - "node_modules/lit-element": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.2.tgz", - "integrity": "sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.5.0", - "@lit/reactive-element": "^2.1.0", - "lit-html": "^3.3.0" - } - }, - "node_modules/lit-html": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.2.tgz", - "integrity": "sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@types/trusted-types": "^2.0.2" - } + "license": "MIT" }, "node_modules/load-json-file": { "version": "4.0.0", @@ -20202,15 +17768,6 @@ "node": ">=8" } }, - "node_modules/long": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", - "integrity": "sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.6" - } - }, "node_modules/longest": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz", @@ -20260,16 +17817,6 @@ "yallist": "^3.0.2" } }, - "node_modules/luxon": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", - "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - } - }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", @@ -20281,19 +17828,6 @@ "lz-string": "bin/bin.js" } }, - "node_modules/lz4js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/lz4js/-/lz4js-0.2.0.tgz", - "integrity": "sha512-gY2Ia9Lm7Ep8qMiuGRhvUq0Q7qUereeldZPP1PMEJxPtEWHJLqw9pgX68oHajBH0nzJK4MaZEA/YNV3jT8u8Bg==", - "license": "ISC", - "optional": true - }, - "node_modules/lzo-wasm": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/lzo-wasm/-/lzo-wasm-0.0.4.tgz", - "integrity": "sha512-VKlnoJRFrB8SdJhlVKvW5vI1gGwcZ+mvChEXcSX6r2xDNc/Q2FD9esfBmGCuPZdrJ1feO+YcVFd2PTk0c137Gw==", - "license": "BSD-2-Clause" - }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -20351,9 +17885,9 @@ } }, "node_modules/maplibre-gl": { - "version": "5.20.2", - "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.20.2.tgz", - "integrity": "sha512-0UzMWOe+GZmIUmOA99yTI1vRh15YcGnHxADVB2s+JF3etpjj2/MBCqbPEuu4BP9mLsJWJcpHH0Nzr9uuimmbuQ==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.21.0.tgz", + "integrity": "sha512-n0v4J/Ge0EG8ix/z3TY3ragtJYMqzbtSnj1riOC0OwQbzwp0lUF2maS1ve1z8HhitQCKtZZiZJhb8to36aMMfQ==", "license": "BSD-3-Clause", "dependencies": { "@mapbox/jsonlint-lines-primitives": "^2.0.2", @@ -20362,9 +17896,9 @@ "@mapbox/unitbezier": "^0.0.1", "@mapbox/vector-tile": "^2.0.4", "@mapbox/whoots-js": "^3.1.0", - "@maplibre/geojson-vt": "^6.0.3", + "@maplibre/geojson-vt": "^6.0.4", "@maplibre/maplibre-gl-style-spec": "^24.7.0", - "@maplibre/mlt": "^1.1.7", + "@maplibre/mlt": "^1.1.8", "@maplibre/vt-pbf": "^4.3.0", "@types/geojson": "^7946.0.16", "earcut": "^3.0.2", @@ -20384,12 +17918,6 @@ "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1" } }, - "node_modules/maplibre-gl/node_modules/@mapbox/point-geometry": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz", - "integrity": "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==", - "license": "ISC" - }, "node_modules/maplibre-gl/node_modules/@mapbox/vector-tile": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-2.0.4.tgz", @@ -20402,9 +17930,9 @@ } }, "node_modules/maplibre-gl/node_modules/@maplibre/geojson-vt": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@maplibre/geojson-vt/-/geojson-vt-6.0.3.tgz", - "integrity": "sha512-tJ8df2SAIacER7pWTiSlDjIULBBAfZnzAURvWb1d8kVzx/pmSJcG0L2p0DTAB6nEu8Lmsx5zAc8JFDcs2DTwaw==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@maplibre/geojson-vt/-/geojson-vt-6.0.4.tgz", + "integrity": "sha512-HYv3POhMRCdhP3UPPATM/hfcy6/WuVIf5FKboH8u/ZuFMTnAIcSVlq5nfOqroLokd925w2QtE7YwquFOIacwVQ==", "license": "ISC", "dependencies": { "kdbush": "^4.0.2" @@ -20428,46 +17956,16 @@ "pbf": "bin/pbf" } }, - "node_modules/marked": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-16.3.0.tgz", - "integrity": "sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w==", - "license": "MIT", - "peer": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/markerjs2": { - "version": "2.32.7", - "resolved": "https://registry.npmjs.org/markerjs2/-/markerjs2-2.32.7.tgz", - "integrity": "sha512-HeFRZjmc43DOG3lSQp92z49cq2oCYpYn2pX++SkJAW1Dij4xJtRquVRf+cXeSZQWDX3ufns1Ry/bGk+zveP7rA==", - "license": "SEE LICENSE IN LICENSE", - "peer": true - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" } }, - "node_modules/md5": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", - "license": "BSD-3-Clause", - "dependencies": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" - } - }, "node_modules/mdast-util-from-markdown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", @@ -21346,27 +18844,6 @@ "node": ">=0.10.0" } }, - "node_modules/moment": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.6.0.tgz", - "integrity": "sha512-ldA5lRNm3iJCWZcBCab4pnNL3HSZYXVb/3TYr75/1WCTWYuTqYUb5f/S384pncYjJ88lbO8Z4uPDvmoluHJc8Q==", - "license": "MIT", - "dependencies": { - "moment": "^2.29.4" - }, - "engines": { - "node": "*" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -24168,27 +21645,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "license": "MIT", - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -24604,12 +22065,6 @@ "dev": true, "license": "BlueOak-1.0.0" }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "license": "(MIT AND Zlib)" - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -24784,52 +22239,6 @@ "node": ">= 14.16" } }, - "node_modules/pbf": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.3.0.tgz", - "integrity": "sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==", - "license": "BSD-3-Clause", - "dependencies": { - "ieee754": "^1.1.12", - "resolve-protobuf-schema": "^2.1.0" - }, - "bin": { - "pbf": "bin/pbf" - } - }, - "node_modules/pdfmake": { - "version": "0.2.23", - "resolved": "https://registry.npmjs.org/pdfmake/-/pdfmake-0.2.23.tgz", - "integrity": "sha512-A/IksoKb/ikOZH1edSDJ/2zBbqJKDghD4+fXn3rT7quvCJDlsZMs3NmIB3eajLMMFU9Bd3bZPVvlUMXhvFI+bQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@foliojs-fork/linebreak": "^1.1.2", - "@foliojs-fork/pdfkit": "^0.15.3", - "iconv-lite": "^0.7.1", - "xmldoc": "^2.0.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/pdfmake/node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "license": "MIT", - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -24951,29 +22360,6 @@ "node": ">=8" } }, - "node_modules/png-js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", - "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==", - "peer": true - }, - "node_modules/polylabel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/polylabel/-/polylabel-1.1.0.tgz", - "integrity": "sha512-bxaGcA40sL3d6M4hH72Z4NdLqxpXRsCFk8AITYg6x1rn1Ei3izf00UMLklerBZTO49aPA3CYrIwVulx2Bce2pA==", - "license": "ISC", - "peer": true, - "dependencies": { - "tinyqueue": "^2.0.3" - } - }, - "node_modules/polylabel/node_modules/tinyqueue": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", - "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==", - "license": "ISC", - "peer": true - }, "node_modules/posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -25611,6 +22997,7 @@ "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.4.tgz", "integrity": "sha512-uKFfOHWuSNpRFVTnljsCluEFq57OKT+0QdOiQo8XWnQ/pSvg7OpX5eNOejELXJMWy+BwM2nobz0FkvzmnpCNsQ==", "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -25668,6 +23055,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, "license": "MIT" }, "node_modules/promise.series": { @@ -25773,18 +23161,6 @@ "teleport": ">=0.2.0" } }, - "node_modules/quadbin": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/quadbin/-/quadbin-0.4.2.tgz", - "integrity": "sha512-1NFzjFVM23Um51/ttD6lFDqGtUHNS5Ky1slZHk3YPwMbC+7Jl3ULLb4QvDo6+Nerv8b8SgUV+ysOhziUh4B5cQ==", - "license": "MIT", - "dependencies": { - "@math.gl/web-mercator": "^4.1.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -26346,6 +23722,7 @@ "version": "1.5.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.7", @@ -27080,13 +24457,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/robust-predicates": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", - "license": "Unlicense", - "peer": true - }, "node_modules/rollup": { "version": "4.59.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", @@ -27399,18 +24769,9 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, "license": "MIT" }, - "node_modules/sax": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz", - "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==", - "license": "BlueOak-1.0.0", - "peer": true, - "engines": { - "node": ">=11.0.0" - } - }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -27433,13 +24794,6 @@ "loose-envify": "^1.1.0" } }, - "node_modules/seedrandom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", - "license": "MIT", - "peer": true - }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -27468,6 +24822,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -27485,6 +24840,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -27532,12 +24888,6 @@ "node": ">=0.10.0" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "license": "MIT" - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -27802,12 +25152,6 @@ "dev": true, "license": "MIT" }, - "node_modules/snappyjs": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/snappyjs/-/snappyjs-0.6.1.tgz", - "integrity": "sha512-YIK6I2lsH072UE0aOFxxY1dPDCS43I5ktqHpeAsuLNYWkE5pGxRGWfDM4/vSUfNzXjC1Ivzt3qx31PCLmc9yqg==", - "license": "MIT" - }, "node_modules/sort-asc": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz", @@ -27852,13 +25196,6 @@ "node": ">=0.10.0" } }, - "node_modules/sortablejs": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.7.tgz", - "integrity": "sha512-Kk8wLQPlS+yi1ZEf48a4+fzHa4yxjC30M/Sr2AnQu+f/MPwvvX9XjZ6OWejiz8crBsLwSq8GHqaxaET7u6ux0A==", - "license": "MIT", - "peer": true - }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -28008,6 +25345,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/stable": { @@ -28701,18 +26039,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strnum": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", - "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT" - }, "node_modules/style-inject": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz", @@ -28720,23 +26046,6 @@ "dev": true, "license": "MIT" }, - "node_modules/style-observer": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/style-observer/-/style-observer-0.0.8.tgz", - "integrity": "sha512-UaIPn33Sx4BJ+goia51Q++VFWoplWK1995VdxQYzwwbFa+FUNLKlG+aiIdG2Vw7VyzIUBi8tqu8mTyg0Ppu6Yg==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/LeaVerou" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/leaverou" - } - ], - "license": "MIT", - "peer": true - }, "node_modules/style-to-js": { "version": "1.1.21", "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", @@ -28824,13 +26133,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/svg-arc-to-cubic-bezier": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz", - "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==", - "license": "ISC", - "peer": true - }, "node_modules/svgo": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", @@ -28879,13 +26181,6 @@ "dev": true, "license": "MIT" }, - "node_modules/tabbable": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", - "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", - "license": "MIT", - "peer": true - }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -28970,28 +26265,6 @@ "dev": true, "license": "MIT" }, - "node_modules/texture-compressor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/texture-compressor/-/texture-compressor-1.0.2.tgz", - "integrity": "sha512-dStVgoaQ11mA5htJ+RzZ51ZxIZqNOgWKAIvtjLrW1AliQQLCmrDqNzQZ8Jh91YealQ95DXt4MEduLzJmbs6lig==", - "license": "MIT", - "dependencies": { - "argparse": "^1.0.10", - "image-size": "^0.7.4" - }, - "bin": { - "texture-compressor": "bin/texture-compressor.js" - } - }, - "node_modules/texture-compressor/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -29009,23 +26282,6 @@ "readable-stream": "3" } }, - "node_modules/timezone-groups": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/timezone-groups/-/timezone-groups-0.10.4.tgz", - "integrity": "sha512-AnkJYrbb7uPkDCEqGeVJiawZNiwVlSkkeX4jZg1gTEguClhyX+/Ezn07KB6DT29tG3UN418ldmS/W6KqGOTDjg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18.12.0" - } - }, - "node_modules/tiny-inflate": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", - "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", - "license": "MIT", - "peer": true - }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -29280,6 +26536,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, "license": "0BSD" }, "node_modules/type-check": { @@ -29305,19 +26562,6 @@ "node": ">=4" } }, - "node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "peer": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -29469,6 +26713,7 @@ "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -29505,17 +26750,6 @@ "node": ">=4" } }, - "node_modules/unicode-properties": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", - "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", - "license": "MIT", - "peer": true, - "dependencies": { - "base64-js": "^1.3.0", - "unicode-trie": "^2.0.0" - } - }, "node_modules/unicode-property-aliases-ecmascript": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", @@ -29526,24 +26760,6 @@ "node": ">=4" } }, - "node_modules/unicode-trie": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", - "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "pako": "^0.2.5", - "tiny-inflate": "^1.0.0" - } - }, - "node_modules/unicode-trie/node_modules/pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", - "license": "MIT", - "peer": true - }, "node_modules/unicorn-magic": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", @@ -29847,6 +27063,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, "license": "MIT" }, "node_modules/v8-to-istanbul": { @@ -30368,43 +27585,6 @@ "dev": true, "license": "MIT" }, - "node_modules/xmldoc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/xmldoc/-/xmldoc-2.0.3.tgz", - "integrity": "sha512-6gRk4NY/Jvg67xn7OzJuxLRsGgiXBaPUQplVJ/9l99uIugxh4FTOewYz5ic8WScj7Xx/2WvhENiQKwkK9RpE4w==", - "license": "MIT", - "peer": true, - "dependencies": { - "sax": "^1.4.3" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/xss": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.13.tgz", - "integrity": "sha512-clu7dxTm1e8Mo5fz3n/oW3UCXBfV89xZ72jM8yzo1vR/pIS0w3sgB3XV2H8Vm6zfGnHL0FzvLJPJEBhd86/z4Q==", - "license": "MIT", - "peer": true, - "dependencies": { - "commander": "^2.20.3", - "cssfilter": "0.0.10" - }, - "bin": { - "xss": "bin/xss" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/xss/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT", - "peer": true - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -30578,13 +27758,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/zstd-codec": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/zstd-codec/-/zstd-codec-0.1.5.tgz", - "integrity": "sha512-v3fyjpK8S/dpY/X5WxqTK3IoCnp/ZOLxn144GZVlNUjtwAchzrVo03h+oMATFhCIiJ5KTr4V3vDQQYz4RU684g==", - "license": "MIT", - "optional": true - }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/package.json b/package.json index c2cac8c..f48aaeb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-stories-api", - "version": "1.0.0-dev-57", + "version": "1.0.0-dev-60", "author": "Kenneth Seals-Nutt", "babel": { "presets": [ @@ -25,11 +25,13 @@ }, "description": "React Components for building interactive data storytelling interfaces with the Stories API", "dependencies": { + "@deck.gl/core": "^9.2.11", + "@deck.gl/layers": "^9.2.11", + "@deck.gl/react": "^9.2.11", "@fontsource/roboto": "^5.2.10", "@mui/stylis-plugin-rtl": "^7.3.8", - "deck.gl": "^9.2.11", "lodash.debounce": "^4.0.8", - "maplibre-gl": "^5.20.2", + "maplibre-gl": "^5.21.0", "react-countup": "^6.5.3", "react-if": "^4.1.6", "react-map-gl": "^8.1.0", @@ -41,6 +43,7 @@ "react-use-error-boundary": "^3.0.0", "stylis": "^4.3.6", "stylis-plugin-rtl": "^2.1.1", + "supercluster": "^8.0.1", "swiper": "^11.2.10" }, "devDependencies": { @@ -108,6 +111,16 @@ "default": "./dist/cjs/index.js" } }, + "./plugins": { + "import": { + "types": "./dist/plugins.d.ts", + "default": "./dist/esm/plugins.js" + }, + "require": { + "types": "./dist/plugins.d.ts", + "default": "./dist/cjs/plugins.js" + } + }, "./types": "./dist/esm/types/types.d.ts" }, "files": [ @@ -143,7 +156,7 @@ "url": "git+https://github.com/kennethsn/react-stories-api.git" }, "scripts": { - "build": "rollup -c", + "build": "rollup -c", "build-storybook": "storybook build", "clean": "rm -rf dist", "commit": "git-cz", diff --git a/rollup.config.mjs b/rollup.config.mjs index e9c0991..beda6b7 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -1,6 +1,3 @@ -import { builtinModules } from 'node:module'; -import { isAbsolute } from 'node:path'; - import commonjs from '@rollup/plugin-commonjs'; import dynamicImportVars from '@rollup/plugin-dynamic-import-vars'; import json from '@rollup/plugin-json'; @@ -10,12 +7,11 @@ import dts from 'rollup-plugin-dts'; import peerDepsExternal from 'rollup-plugin-peer-deps-external'; import postcss from 'rollup-plugin-postcss'; +// eslint-disable-next-line import/extensions +import loadersGlNodeShimPlugin from './configs/loadersGlNodeShimPlugin.mjs'; import packageJSON from './package.json' with { type: 'json' }; -const nodeBuiltins = new Set([ - ...builtinModules, - ...builtinModules.map((moduleName) => `node:${moduleName}`), -]); +const peerDependencyNames = Object.keys(packageJSON.peerDependencies ?? {}); const isExternal = (id) => { // Keep Rollup virtual modules internal. @@ -23,16 +19,7 @@ const isExternal = (id) => { return false; } - // Bundle only local source files; treat bare imports as externals. - if (!id.startsWith('.') && !isAbsolute(id)) { - return true; - } - - if (nodeBuiltins.has(id)) { - return true; - } - - return false; + return peerDependencyNames.some((dependencyName) => id === dependencyName || id.startsWith(`${dependencyName}/`)); }; export default [ @@ -54,6 +41,48 @@ export default [ }, ], plugins: [ + loadersGlNodeShimPlugin, + peerDepsExternal(), + commonjs(), + postcss({ + extensions: ['.css'], + extract: false, + inject: true, + }), + resolve({ + browser: true, + preferBuiltins: false, + }), + dynamicImportVars({ + exclude: ['**/*.test.ts', '**/*.stories.tsx', '**/*.json', 'node_modules/**'], + }), + typescript({ + exclude: ['**/*.test.ts', '**/*.stories.tsx', 'dist'], + filterRoot: './src', + tsconfig: './tsconfig.json', + }), + json(), + ], + }, + { + input: './src/plugins.ts', + external: isExternal, + output: [ + { + file: 'dist/cjs/plugins.js', + format: 'cjs', + sourcemap: true, + inlineDynamicImports: true, + }, + { + file: 'dist/esm/plugins.js', + format: 'esm', + sourcemap: true, + inlineDynamicImports: true, + }, + ], + plugins: [ + loadersGlNodeShimPlugin, peerDepsExternal(), commonjs(), postcss({ @@ -61,7 +90,10 @@ export default [ extract: false, inject: true, }), - resolve(), + resolve({ + browser: true, + preferBuiltins: false, + }), dynamicImportVars({ exclude: ['**/*.test.ts', '**/*.stories.tsx', '**/*.json', 'node_modules/**'], }), @@ -79,4 +111,10 @@ export default [ output: [{ file: 'dist/index.d.ts', format: 'esm' }], plugins: [dts()], }, + { + external: [/\.css$/], + input: 'dist/esm/types/plugins.d.ts', + output: [{ file: 'dist/plugins.d.ts', format: 'esm' }], + plugins: [dts()], + }, ]; diff --git a/src/components/UI/GeoMap/GeoMap.types.ts b/src/components/UI/GeoMap/GeoMap.types.ts index 8a96988..a8e84cc 100644 --- a/src/components/UI/GeoMap/GeoMap.types.ts +++ b/src/components/UI/GeoMap/GeoMap.types.ts @@ -1,5 +1,5 @@ +import type { PickingInfo } from '@deck.gl/core'; import type { SxProps } from '@mui/material/styles'; -import type { PickingInfo } from 'deck.gl'; import type { PropsWithChildren } from 'react'; import type { GeoMapStoreOptions } from '../../../state/geoMapStore'; diff --git a/src/components/UI/Timeline/Timeline.tsx b/src/components/UI/Timeline/Timeline.tsx index 12fc83a..97ed530 100644 --- a/src/components/UI/Timeline/Timeline.tsx +++ b/src/components/UI/Timeline/Timeline.tsx @@ -1,13 +1,9 @@ import MuiTimeline from '@mui/lab/Timeline'; import { observer } from 'mobx-react-lite'; +import { getTimelineEventDirection, getTimelineEventKey } from '../../../utils/timelineUtils'; import TimelineEvent from '../TimelineEvent/TimelineEvent'; -import type { TimelineDirection, TimelinePosition, TimelineProps } from './Timeline.types'; - -const getTimelineEventDirection = ( - index: number, - position: TimelinePosition, -): TimelineDirection => ((position === 'right' || index % 2 === 0) ? 'right' : 'left'); +import type { TimelineProps } from './Timeline.types'; const Timeline = observer(({ color, @@ -18,7 +14,7 @@ const Timeline = observer(({ {events.map((event, index) => ( { + this.storiesAreLoading = true; + }); } stopLoadingStories() { - this.storiesAreLoading = false; + runInAction(() => { + this.storiesAreLoading = false; + }); } toJSON() { diff --git a/src/state/geoMapStore.ts b/src/state/geoMapStore.ts index b81a43c..6b526ac 100644 --- a/src/state/geoMapStore.ts +++ b/src/state/geoMapStore.ts @@ -1,5 +1,5 @@ +import { FlyToInterpolator, type MapViewState, type PickingInfo } from '@deck.gl/core'; import { GeoJsonLayer, TextLayer } from '@deck.gl/layers'; -import { FlyToInterpolator, type MapViewState, type PickingInfo } from 'deck.gl'; import { makeAutoObservable, runInAction } from 'mobx'; import type { ClusterProperties } from 'supercluster'; diff --git a/src/state/moments/iframeMomentStore.ts b/src/state/moments/iframeMomentStore.ts index b4596f3..716ae6e 100644 --- a/src/state/moments/iframeMomentStore.ts +++ b/src/state/moments/iframeMomentStore.ts @@ -26,7 +26,7 @@ export default class IFrameMomentStore extends MomentStore) { + runInAction(() => { + this.options = { ...this.options, ...options }; + }); + } + updatePageTitle() { const title = this.root.formatters.formatStoryPageTitle({ collection_id: this.collectionId, diff --git a/src/types.ts b/src/types.ts index 9f259a6..8ebb978 100644 --- a/src/types.ts +++ b/src/types.ts @@ -777,6 +777,7 @@ export type TimelineEvent = { readonly year?: number; }; readonly description?: string; + readonly id?: string | number; readonly image?: { readonly alt: string; readonly position?: string; // Object-fit CSS property for cover fit diff --git a/src/utils/timelineUtils.ts b/src/utils/timelineUtils.ts new file mode 100644 index 0000000..d35b7cc --- /dev/null +++ b/src/utils/timelineUtils.ts @@ -0,0 +1,35 @@ +import type { TimelineDirection, TimelinePosition, TimelineProps } from '../components/UI/Timeline/Timeline.types'; + +const asKeyPart = (value: unknown) => { + if (typeof value === 'string' || typeof value === 'number') { + return String(value); + } + + if (value && typeof value === 'object') { + try { + return JSON.stringify(value); + } catch { + return ''; + } + } + + return ''; +}; + +export const getTimelineEventDirection = ( + index: number, + position: TimelinePosition, +): TimelineDirection => ((position === 'right' || index % 2 === 0) ? 'right' : 'left'); + +export const getTimelineEventKey = (event: TimelineProps['events'][number], index: number) => { + const idKey = asKeyPart(event.id); + if (idKey) { + return `${idKey}-${index}`; + } + const dateKey = [event.date.year, event.date.month, event.date.day, asKeyPart(event.date.label)] + .filter((value) => value !== undefined && value !== '') + .join('-'); + const titleKey = asKeyPart(event.title); + const imageKey = event.image?.url ?? ''; + return [dateKey, titleKey, imageKey, index].filter(Boolean).join('-'); +};