diff --git a/packages/create-react/.env b/packages/create-react/.env index ad068d2..1809182 100644 --- a/packages/create-react/.env +++ b/packages/create-react/.env @@ -1,5 +1,5 @@ VITE_APP_TITLE="React template" -VITE_ACCESS_TOKEN="eyJhbGciOiJIUzI1NiJ9.eyJhIjoiYWNfNDd1dW5tZWciLCJqdGkiOiJhZjRlM2QxMSJ9.e1GDIOtg3Jy2zcwbFpAxsvK38RqycRrWII1NVTH7KtQ" +VITE_ACCESS_TOKEN="eyJhbGciOiJIUzI1NiJ9.eyJhIjoiYWNfN3hoZnd5bWwiLCJqdGkiOiIwNjU0ZTQ5MyJ9.WoBKztKg5ExQFkUsbAFbwjSZK9nV0ESE9S0_hWS5WgE" VITE_API_BASE_URL="https://gcp-us-east1.api.carto.com" VITE_AUTH_ENABLED="false" diff --git a/packages/create-react/package.json b/packages/create-react/package.json index 8cb1fda..c56b284 100644 --- a/packages/create-react/package.json +++ b/packages/create-react/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "@auth0/auth0-react": "^2.3.0", - "@carto/api-client": "^0.4.6", + "@carto/api-client": "0.5.0-alpha.2", "@carto/create-common": "^0.1.3", "@deck.gl/aggregation-layers": "~9.1.0", "@deck.gl/carto": "~9.1.0", @@ -31,6 +31,7 @@ "@luma.gl/core": "~9.1.0", "@luma.gl/engine": "~9.1.0", "@luma.gl/shadertools": "~9.1.0", + "echarts": "^5.6.0", "maplibre-gl": "^4.7.1", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/packages/create-react/src/components/views/RiversView.tsx b/packages/create-react/src/components/views/RiversView.tsx new file mode 100644 index 0000000..f747fb1 --- /dev/null +++ b/packages/create-react/src/components/views/RiversView.tsx @@ -0,0 +1,233 @@ +import { MapView, MapViewState, WebMercatorViewport } from "@deck.gl/core"; +import { useContext, useEffect, useMemo, useState } from "react"; +import { AppContext } from "../../context"; +import { useDebouncedState } from "../../hooks/useDebouncedState"; +import { createViewportSpatialFilter, vectorTilesetSource } from "@carto/api-client"; +import { BASEMAP, VectorTileLayer } from "@deck.gl/carto"; +import { Card } from "../Card"; +import { FormulaWidget } from "../widgets/FormulaWidget"; +import DeckGL from "@deck.gl/react"; +import { Map } from 'react-map-gl/maplibre'; +import { Layers } from "../Layers"; +import { HistogramWidget } from "../widgets/HistogramWidget"; + +const CONNECTION_NAME = 'amanzanares-pm-bq'; +const TILESET_NAME = 'cartodb-on-gcp-pm-team.amanzanares_opensource_demo.national_water_model_tileset_final_test_4'; +const MAP_VIEW = new MapView({ repeat: true }); + +const INITIAL_VIEW_STATE: MapViewState = { + latitude: 31.8028, + longitude: -103.0078, + zoom: 4, +}; + +const histogramTicks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + +function hexToRgb(hex: string) { + const r = parseInt(hex.slice(1, 3), 16); + const g = parseInt(hex.slice(3, 5), 16); + const b = parseInt(hex.slice(5, 7), 16); + return [r, g, b]; +} + +/** + * Example application page, showing U.S. streams network. + */ +export default function IncomeView() { + // With authentication enabled, access token may change. + const { accessToken, apiBaseUrl } = useContext(AppContext); + const [attributionHTML, setAttributionHTML] = useState(''); + + // data to calculate feature dropping for each zoom level + const [fractionsDropped, setFractionsDropped] = useState([]); + const [minZoom, setMinZoom] = useState(0); + const [maxZoom, setMaxZoom] = useState(20); + const [tilesLoaded, setTilesLoaded] = useState(false); + + // Debounce view state to avoid excessive re-renders during pan and zoom. + const [viewState, setViewState] = useDebouncedState(INITIAL_VIEW_STATE, 200); + + /**************************************************************************** + * Sources (https://deck.gl/docs/api-reference/carto/data-sources) + */ + + const data = useMemo( + () => + vectorTilesetSource({ + accessToken, + apiBaseUrl, + connectionName: CONNECTION_NAME, + tableName: TILESET_NAME, + }), + [accessToken, apiBaseUrl], + ); + + /**************************************************************************** + * Layers (https://deck.gl/docs/api-reference/carto/overview#carto-layers) + */ + + const LAYER_ID = 'Income by block group' + + // Layer visibility represented as name/visibility pairs, managed by the Layers component. + const [layerVisibility, setLayerVisibility] = useState< + Record + >({ + [LAYER_ID]: true, + }); + + // Update layers when data or visualization parameters change. + const layers = useMemo(() => { + return [ + new VectorTileLayer({ + id: LAYER_ID, + pickable: true, + visible: layerVisibility[LAYER_ID], + data, + getLineColor: d => { + const [r, g, b] = hexToRgb('#d5d5d7'); + const n = d.properties.streamOrder; + const alphaPart = Math.min(n / 10, 1); + const alpha = 120 + 128 * alphaPart; + return [r, g, b, alpha]; + }, + getLineWidth: d => { + const n = d.properties.streamOrder; + return n * 0.5; + }, + lineWidthUnits: 'pixels', + lineWidthMinPixels: 1, + onViewportLoad(tiles) { + data?.then((res) => { + setTilesLoaded(true) + res.widgetSource.loadTiles(tiles) + setViewState({ ...viewState }) + }) + }, + }), + ]; + }, [data, viewState, setViewState, layerVisibility]); + + /**************************************************************************** + * Attribution + */ + + useEffect(() => { + data?.then((res) => { + const { fraction_dropped_per_zoom, minzoom, maxzoom, attribution } = res + setFractionsDropped(fraction_dropped_per_zoom ?? []) + setMinZoom(minzoom ?? 0) + setMaxZoom(maxzoom ?? 20) + setAttributionHTML(attribution) + }) + }, [data]); + + useEffect(() => { + if (data && viewState && tilesLoaded) { + data?.then((res) => { + const bbox = new WebMercatorViewport(viewState).getBounds() + const spatialFilter = createViewportSpatialFilter(bbox) + if (spatialFilter) { + res.widgetSource.extractTileFeatures({ spatialFilter }) + } + }) + } + }, [data, viewState, tilesLoaded]) + + function clamp(n: number, min: number, max: number) { + return Math.min(Math.max(n, min), max); + } + + const droppingPercent = useMemo(() => { + if (!fractionsDropped.length) { + return 0 + } + const roundedZoom = Math.round(viewState.zoom) + const clampedZoom = clamp(roundedZoom, minZoom, maxZoom) + const percent = fractionsDropped[clampedZoom] + return percent + }, [minZoom, maxZoom, fractionsDropped, viewState.zoom]) + + return ( + <> + +
+ setViewState(viewState)} + > + + + + {/* + + colors[histogramTicks.indexOf(Number(value))] as Color + } + /> + */} + +
+ + ) +} diff --git a/packages/create-react/src/components/widgets/CategoryWidget.tsx b/packages/create-react/src/components/widgets/CategoryWidget.tsx index b1c7962..59c6803 100644 --- a/packages/create-react/src/components/widgets/CategoryWidget.tsx +++ b/packages/create-react/src/components/widgets/CategoryWidget.tsx @@ -9,6 +9,7 @@ import { removeFilter, getFilter, hasFilter, + WidgetSourceProps, } from '@carto/api-client'; import { createSpatialFilter, @@ -21,11 +22,13 @@ const { IN } = FilterType; export interface CategoryWidgetProps { /** Widget-compatible data source, from vectorTableSource, vectorQuerySource, etc. */ - data: Promise<{ widgetSource: WidgetSource }>; + data: Promise<{ widgetSource: WidgetSource }>; /** Column containing category names. */ column: string; /** Operation used to aggregate features in each category. */ operation?: Exclude; + /** Column containing a value to be aggregated. */ + operationColumn: string; /** Map view state. If specified, widget will be filtered to the view. */ viewState?: MapViewState; /** Filter state. If specified, widget will be filtered. */ @@ -42,6 +45,7 @@ export function CategoryWidget({ data, column, operation, + operationColumn, viewState, filters, onFiltersChange, @@ -66,6 +70,7 @@ export function CategoryWidget({ widgetSource.getCategories({ column, operation, + operationColumn, spatialFilter: viewState && createSpatialFilter(viewState), abortController, filterOwner: owner, @@ -84,7 +89,7 @@ export function CategoryWidget({ setStatus('loading'); return () => abortController.abort(); - }, [data, column, operation, viewState, owner]); + }, [data, column, operation, operationColumn, viewState, owner]); // Compute min/max over category values. const [min, max] = useMemo(() => { diff --git a/packages/create-react/src/components/widgets/FormulaWidget.tsx b/packages/create-react/src/components/widgets/FormulaWidget.tsx index 4aee4de..236bd80 100644 --- a/packages/create-react/src/components/widgets/FormulaWidget.tsx +++ b/packages/create-react/src/components/widgets/FormulaWidget.tsx @@ -1,5 +1,5 @@ import { MapViewState } from '@deck.gl/core'; -import { AggregationType, WidgetSource } from '@carto/api-client'; +import { AggregationType, WidgetSource, WidgetSourceProps } from '@carto/api-client'; import { useEffect, useState } from 'react'; import { createSpatialFilter, @@ -9,7 +9,7 @@ import { export interface FormulaWidgetProps { /** Widget-compatible data source, from vectorTableSource, vectorQuerySource, etc. */ - data: Promise<{ widgetSource: WidgetSource }>; + data: Promise<{ widgetSource: WidgetSource }>; /** Column containing a value to be aggregated. */ column: string; /** Operation used to aggregate the specified column. */ @@ -45,7 +45,9 @@ export function FormulaWidget({ }), ) .then((response) => { - setValue(response.value); + if (response.value) { + setValue(response.value); + } setStatus('complete'); }) .catch(() => { diff --git a/packages/create-react/src/components/widgets/HistogramWidget.tsx b/packages/create-react/src/components/widgets/HistogramWidget.tsx new file mode 100644 index 0000000..671303c --- /dev/null +++ b/packages/create-react/src/components/widgets/HistogramWidget.tsx @@ -0,0 +1,181 @@ +import { AggregationType, Filter, HistogramResponse, WidgetSourceProps } from "@carto/api-client"; +import { WidgetSource } from '@carto/api-client'; +import { MapViewState } from "@deck.gl/core"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { createSpatialFilter, WidgetStatus } from "../../utils"; +import * as echarts from 'echarts'; + +export interface HistogramWidgetProps { + /** Widget-compatible data source, from vectorTableSource, vectorQuerySource, etc. */ + data: Promise<{ widgetSource: WidgetSource }>; + /** Column containing a value to be aggregated. */ + column: string; + /** Operation used to aggregate the specified column. */ + operation?: Exclude; + /** Ticks to use for the histogram calculation. */ + ticks: number[]; + /** Filter state. If specified, widget will be filtered. */ + filters?: Record; + /** Callback, to be invoked by the widget when its filters are set or cleared. */ + onFiltersChange?: (filters: Record) => void; + /** Map view state. If specified, widget will be filtered to the view. */ + viewState?: MapViewState; +} + +export function HistogramWidget({ + data, + column, + operation, + ticks, + viewState +}: HistogramWidgetProps) { + const [owner] = useState(crypto.randomUUID()); + const [status, setStatus] = useState('complete'); + const chartRef = useRef(null); + + const createChart = useCallback((ref: HTMLDivElement | null) => { + const onClick = (params: echarts.ECElementEvent) => { + if (params.componentType === 'series') { + // filterViaHistogram(params.dataIndex); + } + } + + if (ref && !chartRef.current) { + const chart = echarts.init(ref, null, { height: 200, width: 300 }); + chartRef.current = chart; + chartRef.current?.on('click', onClick); + } + }, []) + + // Fetches data for the widget to display, watching changes to filters, + // view state, and widget configuration to refresh. + useEffect(() => { + const abortController = new AbortController(); + chartRef.current?.showLoading(); + + function getOption(data: HistogramResponse) { + const option = { + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + } + }, + grid: { + left: 60, + right: 30, + top: 20, + bottom: 20, + width: 'auto', + height: 'auto' + }, + xAxis: { + type: 'category', + data: ticks, + // axisLabel: { + // interval: 4 // Show every 5th label + // }, + axisTick: { + alignWithLabel: true + } + }, + yAxis: { + type: 'value', + axisLabel: { + formatter: (value: number) => + Intl.NumberFormat('en-US', {compactDisplay: 'short', notation: 'compact'}).format(value) + } + }, + series: [ + { + name: 'Count', + type: 'bar', + data, + itemStyle: { + color: '#3398DB' + } + } + ] + }; + return option; + } + + data + .then(({ widgetSource }) => + widgetSource.getHistogram({ + column, + operation, + ticks, + spatialFilter: viewState && createSpatialFilter(viewState), + abortController, + filterOwner: owner, + }), + ) + .then((response) => { + setStatus('complete'); + chartRef.current?.hideLoading(); + chartRef.current?.setOption(getOption(response)); + }) + .catch(() => { + chartRef.current?.hideLoading(); + if (!abortController.signal.aborted) { + setStatus('error'); + } + }); + + return () => abortController.abort(); + }, [data, column, operation, ticks, viewState, owner]); + + // function onClearFilters() { + // if (filters && onFiltersChange) { + // // Replace, not mutate, the filters object. + // onFiltersChange(removeFilter({ ...filters }, { column, owner })); + // } + // } + + // function filterViaHistogram(dataIndex: number) { + // // clearFiltersButton.style.display = 'inherit'; + + // // removeFilter(filters, { + // // column: 'streamOrder' + // // }); + + // // const minValue = histogramTicks[dataIndex]; + // // const maxValue = histogramTicks[dataIndex + 1] - 0.0001; + + // // if (dataIndex === histogramTicks.length - 1) { + // // // For the last category (> 600), use CLOSED_OPEN + // // addFilter(filters, { + // // column: 'streamOrder', + // // type: FilterType.CLOSED_OPEN, + // // values: [[minValue, Infinity]] + // // }); + // // } else { + // // // For first and middle categories, use BETWEEN + // // addFilter(filters, { + // // column: 'streamOrder', + // // type: FilterType.BETWEEN, + // // values: [[minValue, maxValue]] + // // }); + // // } + + // // initialize(); + // } + + // if (status === 'loading') { + // return ...; + // } + + if (status === 'error') { + return ⚠ Error; + } + + // if (!response || !response.length) { + // return No data; + // } + + return ( +
+
+ ) +} diff --git a/packages/create-react/src/routes.tsx b/packages/create-react/src/routes.tsx index 4e54c7f..20c2152 100644 --- a/packages/create-react/src/routes.tsx +++ b/packages/create-react/src/routes.tsx @@ -6,6 +6,7 @@ import PopulationView from './components/views/PopulationView'; import NotFoundView from './components/views/NotFoundView'; import LoginView from './components/views/LoginView'; import LogoutView from './components/views/LogoutView'; +import RiversView from './components/views/RiversView'; /** * Available paths (URLs) in the application. @@ -13,6 +14,7 @@ import LogoutView from './components/views/LogoutView'; export const RoutePath = { CELL_TOWERS: '/', POPULATION: '/usa-population', + RIVERS: '/rivers', LOGIN: '/login', LOGOUT: '/logout', NOT_FOUND: '/404', @@ -24,6 +26,7 @@ export const RoutePath = { export const NAV_ROUTES: { text: string; path: string }[] = [ { text: 'Cell towers', path: RoutePath.CELL_TOWERS }, { text: 'U.S. population', path: RoutePath.POPULATION }, + { text: 'U.S. rivers', path: RoutePath.RIVERS }, ]; /** @@ -40,6 +43,7 @@ export const routes: RouteObject[] = [ children: [ { path: RoutePath.CELL_TOWERS, element: }, { path: RoutePath.POPULATION, element: }, + { path: RoutePath.RIVERS, element: }, ], }, { path: RoutePath.LOGIN, element: }, diff --git a/yarn.lock b/yarn.lock index 1bdfdf1..a923b56 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2645,6 +2645,25 @@ __metadata: languageName: node linkType: hard +"@carto/api-client@npm:0.5.0-alpha.2": + version: 0.5.0-alpha.2 + resolution: "@carto/api-client@npm:0.5.0-alpha.2" + dependencies: + "@loaders.gl/schema": "npm:^4.3.3" + "@turf/bbox-clip": "npm:^7.1.0" + "@turf/bbox-polygon": "npm:^7.1.0" + "@turf/boolean-intersects": "npm:^7.1.0" + "@turf/boolean-within": "npm:^7.1.0" + "@turf/helpers": "npm:^7.1.0" + "@turf/intersect": "npm:^7.1.0" + "@turf/invariant": "npm:^7.1.0" + "@turf/union": "npm:^7.1.0" + "@types/geojson": "npm:^7946.0.15" + h3-js: "npm:4.1.0" + checksum: 10c0/fc67454045f90311bdbba361f28a650b096bae3c5fdb4befcde595a8b1b492e551c95935b9c10a10aeb83166240649d59533c07d7d7d725db06be764fd768ca7 + languageName: node + linkType: hard + "@carto/api-client@npm:^0.4.4, @carto/api-client@npm:^0.4.6": version: 0.4.6 resolution: "@carto/api-client@npm:0.4.6" @@ -2718,7 +2737,7 @@ __metadata: resolution: "@carto/create-react@workspace:packages/create-react" dependencies: "@auth0/auth0-react": "npm:^2.3.0" - "@carto/api-client": "npm:^0.4.6" + "@carto/api-client": "npm:0.5.0-alpha.2" "@carto/create-common": "npm:^0.1.3" "@deck.gl/aggregation-layers": "npm:~9.1.0" "@deck.gl/carto": "npm:~9.1.0" @@ -2738,6 +2757,7 @@ __metadata: "@types/react-dom": "npm:^18.3.5" "@vitejs/plugin-basic-ssl": "npm:^1.2.0" "@vitejs/plugin-react": "npm:^4.3.4" + echarts: "npm:^5.6.0" maplibre-gl: "npm:^4.7.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" @@ -4344,7 +4364,7 @@ __metadata: languageName: node linkType: hard -"@loaders.gl/schema@npm:4.3.3": +"@loaders.gl/schema@npm:4.3.3, @loaders.gl/schema@npm:^4.3.3": version: 4.3.3 resolution: "@loaders.gl/schema@npm:4.3.3" dependencies: @@ -5823,6 +5843,18 @@ __metadata: languageName: node linkType: hard +"@turf/bbox@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/bbox@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@turf/meta": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/766d59d5f75c272481e971cd4004e139962607e8f34391b2abfb15bb34f9544a0479ceb14772565e005e4a12fdd82adf0d440ab1c9e0decbde6de50a5706db43 + languageName: node + linkType: hard + "@turf/boolean-clockwise@npm:^5.1.5": version: 5.1.5 resolution: "@turf/boolean-clockwise@npm:5.1.5" @@ -5833,6 +5865,74 @@ __metadata: languageName: node linkType: hard +"@turf/boolean-disjoint@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/boolean-disjoint@npm:7.2.0" + dependencies: + "@turf/boolean-point-in-polygon": "npm:^7.2.0" + "@turf/helpers": "npm:^7.2.0" + "@turf/line-intersect": "npm:^7.2.0" + "@turf/meta": "npm:^7.2.0" + "@turf/polygon-to-line": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/f9e27f3b46fdddd5e96e67e7f130e25678922c843afd5d898a1c13b599285b126a8ab9df5bd5e76454e88deacc359ebc1fa47d50cbd21f64c0547201d0fb9118 + languageName: node + linkType: hard + +"@turf/boolean-intersects@npm:^7.1.0": + version: 7.2.0 + resolution: "@turf/boolean-intersects@npm:7.2.0" + dependencies: + "@turf/boolean-disjoint": "npm:^7.2.0" + "@turf/helpers": "npm:^7.2.0" + "@turf/meta": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/2b4ef09eb77fa02db9671e5c4d0c0c4133a815bbd9a744e70e65a3b37a8b6a13c26d51dc77de0822f39ed2b882646f416fa07561888d4813bb4d31b7003fcba5 + languageName: node + linkType: hard + +"@turf/boolean-point-in-polygon@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/boolean-point-in-polygon@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@turf/invariant": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + point-in-polygon-hao: "npm:^1.1.0" + tslib: "npm:^2.8.1" + checksum: 10c0/eeb431f70175e466205b27076dbc331b862d3e6867d43730ac4099ecd7e6d6f0fed9e3301fd29f6375f340e379f477489f09060e6aec9fc0f7afa01ac58d5c09 + languageName: node + linkType: hard + +"@turf/boolean-point-on-line@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/boolean-point-on-line@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@turf/invariant": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/a7f81170ff795025f209602559a289330304adf046340133e1b18f950aca386e8f2d4f1f91b85c2456306d95359fdd19b8323c13f88327491dbf2f196fa1e635 + languageName: node + linkType: hard + +"@turf/boolean-within@npm:^7.1.0": + version: 7.2.0 + resolution: "@turf/boolean-within@npm:7.2.0" + dependencies: + "@turf/bbox": "npm:^7.2.0" + "@turf/boolean-point-in-polygon": "npm:^7.2.0" + "@turf/boolean-point-on-line": "npm:^7.2.0" + "@turf/helpers": "npm:^7.2.0" + "@turf/invariant": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/2aed21d55b820a19d1d7f22f521fdd9c780ba8ab036828ac2a316efea984d3c70c71190aeaa5766fce922b5dcd52987d86dc0fcb27a0d50306a9e7e270cf80ce + languageName: node + linkType: hard + "@turf/clone@npm:^5.1.5": version: 5.1.5 resolution: "@turf/clone@npm:5.1.5" @@ -5859,6 +5959,29 @@ __metadata: languageName: node linkType: hard +"@turf/helpers@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/helpers@npm:7.2.0" + dependencies: + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/4d6f57164cca00ec7a18e2d3c0200d0274e4ab2b6b3201c6a867b867d899f3f618a82ae242617d467efb04f32740cec150ae06a0e07ee39318397ebc34914687 + languageName: node + linkType: hard + +"@turf/intersect@npm:^7.1.0": + version: 7.2.0 + resolution: "@turf/intersect@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@turf/meta": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + polyclip-ts: "npm:^0.16.8" + tslib: "npm:^2.8.1" + checksum: 10c0/16c39a87819c0173572e1030e29eca1c522115f9aa2c07a3baa00b6b28626573e6e54b428cd919d055f80e49ab1dd90c17166f5e8ba46eb3da738d1a8c8bbd71 + languageName: node + linkType: hard + "@turf/invariant@npm:^5.1.5": version: 5.2.0 resolution: "@turf/invariant@npm:5.2.0" @@ -5879,6 +6002,29 @@ __metadata: languageName: node linkType: hard +"@turf/invariant@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/invariant@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/6968b766d5522488bb2b149a72f863e3f0d4bb0342b14f3992e3e920d9e32c252e1e07e84213732cb51609aef7a82833a8fe76b1c7d0db4cd384954cfedaa4e5 + languageName: node + linkType: hard + +"@turf/line-intersect@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/line-intersect@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + sweepline-intersections: "npm:^1.5.0" + tslib: "npm:^2.8.1" + checksum: 10c0/d2ed0159ce84e179f999ed461c5481f063c813bedfdfb4af45e46432503b0acd240128be5c6c2d324e05edc4981fd806a41ee0282567c5d0c80c223497e40cb4 + languageName: node + linkType: hard + "@turf/meta@npm:^5.1.5": version: 5.2.0 resolution: "@turf/meta@npm:5.2.0" @@ -5898,6 +6044,28 @@ __metadata: languageName: node linkType: hard +"@turf/meta@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/meta@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + checksum: 10c0/707ed63ba64fe48769806bf2419f5c0cd2ebf821a6467aeffb784ba7ebd6a63ec98d4192b97915948529c00304ed46ddc83842a80714fb1f2018fd4e3c455498 + languageName: node + linkType: hard + +"@turf/polygon-to-line@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/polygon-to-line@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@turf/invariant": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/b840b218e631a252655d233b2c569607d4d3e8d3715a1eab7d26394e4acc1f325b736837d2a82e5c4f678600b2ddc32004782ed3825ca5b1027dce12a4e4cde9 + languageName: node + linkType: hard + "@turf/rewind@npm:^5.1.5": version: 5.1.5 resolution: "@turf/rewind@npm:5.1.5" @@ -7706,6 +7874,13 @@ __metadata: languageName: node linkType: hard +"bignumber.js@npm:^9.1.0": + version: 9.1.2 + resolution: "bignumber.js@npm:9.1.2" + checksum: 10c0/e17786545433f3110b868725c449fa9625366a6e675cd70eb39b60938d6adbd0158cb4b3ad4f306ce817165d37e63f4aa3098ba4110db1d9a3b9f66abfbaf10d + languageName: node + linkType: hard + "bin-links@npm:^4.0.4": version: 4.0.4 resolution: "bin-links@npm:4.0.4" @@ -9374,6 +9549,16 @@ __metadata: languageName: node linkType: hard +"echarts@npm:^5.6.0": + version: 5.6.0 + resolution: "echarts@npm:5.6.0" + dependencies: + tslib: "npm:2.3.0" + zrender: "npm:5.6.1" + checksum: 10c0/6d6a2ee88534d1ff0433e935c542237b9896de1c94959f47ebc7e0e9da26f59bf11c91ed6fc135b62ad2786c779ee12bc536fa481e60532dad5b6a2f5167e9ea + languageName: node + linkType: hard + "ee-first@npm:1.1.1": version: 1.1.1 resolution: "ee-first@npm:1.1.1" @@ -11133,7 +11318,7 @@ __metadata: languageName: node linkType: hard -"h3-js@npm:^4.1.0": +"h3-js@npm:4.1.0, h3-js@npm:^4.1.0": version: 4.1.0 resolution: "h3-js@npm:4.1.0" checksum: 10c0/58adb7c7a19ff6e6959ef97a60b383bb06c560ffd12826ce603470b25bb34bb26b9bedee6e406591b97017fb888a6194b4043d16abd0d100e6cb51d449e9c3d1 @@ -14840,6 +15025,25 @@ __metadata: languageName: node linkType: hard +"point-in-polygon-hao@npm:^1.1.0": + version: 1.2.4 + resolution: "point-in-polygon-hao@npm:1.2.4" + dependencies: + robust-predicates: "npm:^3.0.2" + checksum: 10c0/12badef8b15216acdae7d609a8aca1b916d6a9cac2f53ace2928e3b521bee57224489ea8fba41d001c0c05c50e64152c175e3d6583d8cad6fe7af929f082b49a + languageName: node + linkType: hard + +"polyclip-ts@npm:^0.16.8": + version: 0.16.8 + resolution: "polyclip-ts@npm:0.16.8" + dependencies: + bignumber.js: "npm:^9.1.0" + splaytree-ts: "npm:^1.0.2" + checksum: 10c0/8de02c32e566421875c70890fe6d3d7bd55a92fc39867446e65999e042c4632fb27ab1a7e106e96edd12d63b32a643f3a690d9a980aeda655a41ddf4e8750f5d + languageName: node + linkType: hard + "polygon-clipping@npm:^0.15.3": version: 0.15.7 resolution: "polygon-clipping@npm:0.15.7" @@ -17008,6 +17212,13 @@ __metadata: languageName: node linkType: hard +"splaytree-ts@npm:^1.0.2": + version: 1.0.2 + resolution: "splaytree-ts@npm:1.0.2" + checksum: 10c0/4c34573891a749055ffe22381ea841ae03dbf7b55a3ea4a1d7df5013bfbe128e79f6c468579358ec573734cdbdf5f77a97ae7185f155248eb8be58151428c85e + languageName: node + linkType: hard + "splaytree@npm:^3.1.0": version: 3.1.2 resolution: "splaytree@npm:3.1.2" @@ -17368,6 +17579,15 @@ __metadata: languageName: node linkType: hard +"sweepline-intersections@npm:^1.5.0": + version: 1.5.0 + resolution: "sweepline-intersections@npm:1.5.0" + dependencies: + tinyqueue: "npm:^2.0.0" + checksum: 10c0/587a597c75b787e61054ef88b98463af47f60855265b7829fa8acc5ebe68fb4bc3d148a80e9f72c69c16a0241bfed38d3fbbe93a735ea5a2276c00116adc5283 + languageName: node + linkType: hard + "symbol-observable@npm:4.0.0": version: 4.0.0 resolution: "symbol-observable@npm:4.0.0" @@ -17549,6 +17769,13 @@ __metadata: languageName: node linkType: hard +"tinyqueue@npm:^2.0.0": + version: 2.0.3 + resolution: "tinyqueue@npm:2.0.3" + checksum: 10c0/d7b590088f015a94a17132fa209c2f2a80c45158259af5474901fdf5932e95ea13ff6f034bcc725a6d5f66d3e5b888b048c310229beb25ad5bebb4f0a635abf2 + languageName: node + linkType: hard + "tinyqueue@npm:^3.0.0": version: 3.0.0 resolution: "tinyqueue@npm:3.0.0" @@ -17654,6 +17881,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:2.3.0": + version: 2.3.0 + resolution: "tslib@npm:2.3.0" + checksum: 10c0/a845aed84e7e7dbb4c774582da60d7030ea39d67307250442d35c4c5dd77e4b44007098c37dd079e100029c76055f2a362734b8442ba828f8cc934f15ed9be61 + languageName: node + linkType: hard + "tslib@npm:2.6.3, tslib@npm:^2.0.0, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.4.0": version: 2.6.3 resolution: "tslib@npm:2.6.3" @@ -18869,6 +19103,15 @@ __metadata: languageName: node linkType: hard +"zrender@npm:5.6.1": + version: 5.6.1 + resolution: "zrender@npm:5.6.1" + dependencies: + tslib: "npm:2.3.0" + checksum: 10c0/dc1cc570054640cbd8fbb7b92e6252f225319522bfe3e8dc8bf02cc02d414e00a4c8d0a6f89bfc9d96e5e9511fdca94dd3d06bf53690df2b2f12b0fc560ac307 + languageName: node + linkType: hard + "zstd-codec@npm:^0.1": version: 0.1.4 resolution: "zstd-codec@npm:0.1.4"