From e867a6ac4ccbcb00175ed48f0493e1a40d60eb58 Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Mon, 16 Mar 2026 15:07:56 +0000 Subject: [PATCH 01/26] Add plugin --- anndata-zarr/.eslintrc.json | 75 ++++++++ anndata-zarr/.gitignore | 24 +++ anndata-zarr/package.json | 45 +++++ .../src/components/AnndataController.jsx | 43 +++++ anndata-zarr/src/components/FeatureSelect.jsx | 115 +++++++++++++ anndata-zarr/src/components/Legend.jsx | 32 ++++ anndata-zarr/src/components/ObsSelect.jsx | 160 +++++++++++++++++ anndata-zarr/src/constants/colorscales.js | 138 +++++++++++++++ anndata-zarr/src/hooks.js | 113 ++++++++++++ anndata-zarr/src/index.css | 37 ++++ anndata-zarr/src/index.js | 6 + anndata-zarr/src/provider.jsx | 11 ++ anndata-zarr/src/utils.js | 161 ++++++++++++++++++ anndata-zarr/vite.config.js | 34 ++++ viewer/src/components/Viewer.tsx | 1 - 15 files changed, 994 insertions(+), 1 deletion(-) create mode 100644 anndata-zarr/.eslintrc.json create mode 100644 anndata-zarr/.gitignore create mode 100644 anndata-zarr/package.json create mode 100644 anndata-zarr/src/components/AnndataController.jsx create mode 100644 anndata-zarr/src/components/FeatureSelect.jsx create mode 100644 anndata-zarr/src/components/Legend.jsx create mode 100644 anndata-zarr/src/components/ObsSelect.jsx create mode 100644 anndata-zarr/src/constants/colorscales.js create mode 100644 anndata-zarr/src/hooks.js create mode 100644 anndata-zarr/src/index.css create mode 100644 anndata-zarr/src/index.js create mode 100644 anndata-zarr/src/provider.jsx create mode 100644 anndata-zarr/src/utils.js create mode 100644 anndata-zarr/vite.config.js diff --git a/anndata-zarr/.eslintrc.json b/anndata-zarr/.eslintrc.json new file mode 100644 index 00000000..b672f57c --- /dev/null +++ b/anndata-zarr/.eslintrc.json @@ -0,0 +1,75 @@ +{ + "extends": [ + "react-app", + "prettier", + "plugin:import/errors", + "plugin:import/warnings", + "plugin:prettier/recommended" + ], + "settings": { + "import/resolver": { + "node": { + "extensions": [ + ".js", + ".jsx", + ".ts", + ".tsx" + ] + }, + "alias": { + "map": [ + [ + "@app", + "./src" + ] + ], + "extensions": [ + ".js", + ".jsx", + ".ts", + ".tsx" + ] + } + } + }, + "rules": { + "import/order": [ + "error", + { + "groups": [ + "builtin", + "external", + "internal", + [ + "parent", + "sibling" + ], + "index" + ], + "pathGroups": [ + { + "pattern": "react", + "group": "external", + "position": "before" + } + ], + "pathGroupsExcludedImportTypes": [ + "react" + ], + "newlines-between": "always", + "alphabetize": { + "order": "asc", + "caseInsensitive": true + } + } + ], + "prettier/prettier": [ + "error", + { + "singleQuote": true, + "tabWidth": 2, + "useTabs": false + } + ] + } +} \ No newline at end of file diff --git a/anndata-zarr/.gitignore b/anndata-zarr/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/anndata-zarr/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/anndata-zarr/package.json b/anndata-zarr/package.json new file mode 100644 index 00000000..8adb6011 --- /dev/null +++ b/anndata-zarr/package.json @@ -0,0 +1,45 @@ +{ + "name": "@biongff/anndata-zarr", + "private": true, + "version": "0.0.0", + "type": "module", + "main": "dist/biongff-anndata-zarr.cjs.js", + "module": "dist/biongff-anndata-zarr.es.js", + "files": [ + "dist" + ], + "exports": { + ".": { + "import": "./dist/biongff-anndata-zarr.es.js", + "require": "./dist/biongff-anndata-zarr.cjs.js" + }, + "./dist/anndata-zarr.css": "./dist/anndata-zarr.css" + }, + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "preview": "vite preview", + "test": "vitest" + }, + "dependencies": { + "@tanstack/react-query": "^5.85.3", + "lodash": "^4.17.21", + "react-window": "^2.0.2", + "zarrita": "0.5.0" + }, + "peerDependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "@mui/icons-material": "^7.2.0", + "@mui/material": "^7.2.0", + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1" + }, + "devDependencies": { + "@vitejs/plugin-react": "^4.3.3", + "vite": "^6.2.3", + "vitest": "^3.0.8" + } +} diff --git a/anndata-zarr/src/components/AnndataController.jsx b/anndata-zarr/src/components/AnndataController.jsx new file mode 100644 index 00000000..131ae6c7 --- /dev/null +++ b/anndata-zarr/src/components/AnndataController.jsx @@ -0,0 +1,43 @@ +import React, { useState } from 'react'; + +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; + +import { FeatureSelect } from './FeatureSelect'; +import { ObsSelect } from './ObsSelect'; + +export const AnndataController = ({ adata, callback = () => {} }) => { + const [feature, setFeature] = useState(null); + const [obsCol, setObsCol] = useState(null); + + const handleFeatureSelect = (f) => { + setFeature(f); + setObsCol(null); + }; + + const handleObsSelect = (o) => { + setObsCol(o); + setFeature(null); + }; + + return ( + + + + + + + + + ); +}; diff --git a/anndata-zarr/src/components/FeatureSelect.jsx b/anndata-zarr/src/components/FeatureSelect.jsx new file mode 100644 index 00000000..23b4732b --- /dev/null +++ b/anndata-zarr/src/components/FeatureSelect.jsx @@ -0,0 +1,115 @@ +import React, { useEffect, useMemo, useState } from 'react'; + +import Box from '@mui/material/Box'; +import ListItem from '@mui/material/ListItem'; +import ListItemButton from '@mui/material/ListItemButton'; +import ListItemText from '@mui/material/ListItemText'; +import Stack from '@mui/material/Stack'; +import TextField from '@mui/material/TextField'; +import { List } from 'react-window'; + +import { useAnndataColors, useAnndataFeatures } from '../hooks'; +import { Legend } from './Legend'; + +const RowComponent = ({ index, items, style, onSelect, selectedIndex }) => { + return ( + + onSelect({ index: items[index].matrixIndex })} + selected={items[index].matrixIndex === selectedIndex} + > + + + + ); +}; + +export const FeatureSelect = ({ + adata, + feature, + onSelect, + callback = () => {}, +}) => { + const [searchTerm, setSearchTerm] = useState(''); + + const { data, isLoading, serverError } = useAnndataFeatures(adata); + const colorData = useAnndataColors( + { + ...adata, + matrixProps: { + feature: feature, + }, + }, + { enabled: !!feature }, + ); + + useEffect(() => { + if (colorData?.serverError) { + callback(null); + return; + } + if (!colorData?.isLoading && colorData?.data) { + callback(colorData.data.colors); + } + }, [colorData, callback]); + + const items = useMemo(() => { + if (!data) return []; + const allItems = data.map((name, index) => ({ + name, + matrixIndex: index, + })); + if (!searchTerm) return allItems; + return allItems.filter((item) => + item.name.toLowerCase().includes(searchTerm.toLowerCase()), + ); + }, [data, searchTerm]); + + const legend = useMemo(() => { + if (colorData?.serverError || colorData?.isLoading || !colorData?.data) { + return null; + } + const { min, max, colorscale } = colorData.data; + return ; + }, [colorData.data, colorData?.isLoading, colorData?.serverError]); + + if (isLoading) { + return <>; + } + if (serverError) { + return
Error loading features
; + } + return ( + + + setSearchTerm(e.target.value)} + /> + + {!!feature && legend} + + + ); +}; diff --git a/anndata-zarr/src/components/Legend.jsx b/anndata-zarr/src/components/Legend.jsx new file mode 100644 index 00000000..786bb58e --- /dev/null +++ b/anndata-zarr/src/components/Legend.jsx @@ -0,0 +1,32 @@ +import React, { useMemo } from 'react'; + +import _ from 'lodash'; + +import { getColor } from '../utils'; +import '../index.css'; + +export const Legend = ({ min, max, colorscale }) => { + const spanList = useMemo(() => { + return _.range(100).map((i) => { + const color = getColor({ value: i / 100, colorscale }); + return ( + + ); + }); + }, [colorscale]); + + return ( +
+
+ {spanList} + {min.toFixed(2)} + {((min + max) / 2).toFixed(2)} + {max.toFixed(2)} +
+
+ ); +}; diff --git a/anndata-zarr/src/components/ObsSelect.jsx b/anndata-zarr/src/components/ObsSelect.jsx new file mode 100644 index 00000000..84506a55 --- /dev/null +++ b/anndata-zarr/src/components/ObsSelect.jsx @@ -0,0 +1,160 @@ +import React, { useEffect, useMemo, useState } from 'react'; + +import ExpandLess from '@mui/icons-material/ExpandLess'; +import ExpandMore from '@mui/icons-material/ExpandMore'; +import Alert from '@mui/material/Alert'; +import Box from '@mui/material/Box'; +import Collapse from '@mui/material/Collapse'; +import Divider from '@mui/material/Divider'; +import FormControl from '@mui/material/FormControl'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import Radio from '@mui/material/Radio'; +import RadioGroup from '@mui/material/RadioGroup'; +import Stack from '@mui/material/Stack'; + +import { COLORSCALES } from '../constants/colorscales'; +import { useAnndataColors, useAnndataObs } from '../hooks'; +import { getColor } from '../utils'; +import { Legend } from './Legend'; + +// @TODO: fix styling (width) +const CategoricalCol = ({ col, showColor = false }) => { + const [open, setOpen] = useState(false); + const { categories } = col; + + return ( + + setOpen(!open)} + sx={{ display: 'flex', alignItems: 'center', cursor: 'pointer' }} + > + e.stopPropagation()} />} + label={col.name} + key={col.name} + value={col.name} + /> + {open ? : } + + + {categories.length > 100 && ( + + Truncated to 100 categories + + )} + + {categories.slice(0, 100).map((cat, i) => ( + + {showColor && ( + + + + )} + + + ))} + + + + ); +}; + +const NumericalCol = ({ col }) => { + return ( + } + label={col.name} + key={col.name} + value={col.name} + /> + ); +}; + +export const ObsSelect = ({ adata, obsCol, onSelect, callback = () => {} }) => { + const { data, isLoading, serverError } = useAnndataObs(adata); + const colorData = useAnndataColors( + { + ...adata, + matrixProps: { + obs: { col: obsCol }, + }, + }, + { + enabled: !!obsCol, + }, + ); + + useEffect(() => { + if (colorData?.serverError) { + callback(null); + return; + } + if (!colorData?.isLoading && colorData?.data) { + callback(colorData.data.colors); + } + }, [colorData, callback]); + + const legend = useMemo(() => { + if (colorData?.serverError || colorData?.isLoading || !colorData?.data) { + return null; + } + const { min, max, colorscale, categories } = colorData.data; + if (categories) { + return null; + } + return ; + }, [colorData.data, colorData?.isLoading, colorData?.serverError]); + + if (isLoading) { + return <>; + } + if (serverError) { + return
Error loading obs
; + } + return ( + + + Observations + + + onSelect(e.target.value)} + > + Categorical + {data.categorical.map((col) => ( + + ))} + Numerical + {data.numerical.map((col) => ( + + ))} + + + + {!!obsCol && legend} + + + ); +}; diff --git a/anndata-zarr/src/constants/colorscales.js b/anndata-zarr/src/constants/colorscales.js new file mode 100644 index 00000000..3834d121 --- /dev/null +++ b/anndata-zarr/src/constants/colorscales.js @@ -0,0 +1,138 @@ +// From plotly https://github.com/plotly/plotly.js/blob/5bc25b490702e5ed61265207833dbd58e8ab27f1/src/components/colorscale/scales.js +export const COLORSCALES = { + Greys: ['#000000', '#ffffff'], + + YlGnBu: [ + '#081d58', + '#253494', + '#225ea8', + '#1d91c0', + '#41b6c4', + '#7fcdbb', + '#c7e9b4', + '#edf8d9', + '#ffffd9', + ], + + Greens: [ + '#00441b', + '#006d2c', + '#238b45', + '#41ab5d', + '#74c476', + '#a1d9a5', + '#c7e9c0', + '#e5f5e0', + '#f7fcf5', + ], + + YlOrRd: [ + '#800026', + '#bd0026', + '#e31a1c', + '#fc4e2a', + '#fd8d3c', + '#feb24c', + '#fed976', + '#ffed9f', + '#ffffcc', + ], + + Bluered: ['#0000ff', '#ff0000'], + + RdBu: ['#050aac', '#6a89f7', '#bebebe', '#dcaa84', '#e6915a', '#b20a1c'], + + Reds: ['#dcdcdc', '#f5c39d', '#f5a069', '#b20a1c'], + + Blues: ['#050aac', '#283cba', '#4664f5', '#5a78f5', '#6a89f7', '#dcdcdc'], + + Picnic: [ + '#0000ff', + '#3399ff', + '#66ccff', + '#99ccff', + '#ccccff', + '#ffffff', + '#ffccff', + '#ff99ff', + '#ff66cc', + '#ff6666', + '#ff0000', + ], + + Rainbow: [ + '#96005a', + '#0000c8', + '#0019ff', + '#0098ff', + '#2cff96', + '#97ff00', + '#ffe600', + '#ff6f00', + '#ff0000', + ], + + Portland: ['#0c3383', '#0a88ba', '#f2d338', '#f28f38', '#d91e1e'], + + Jet: ['#000083', '#003caa', '#05ffff', '#ffff00', '#fa0000', '#800000'], + + Hot: ['#000000', '#e60000', '#ffd200', '#ffffff'], + + Blackbody: ['#000000', '#e60000', '#e6d200', '#ffffff', '#a0c8ff'], + + Earth: ['#000082', '#00b4b4', '#28d228', '#e6e632', '#784614', '#ffffff'], + + Electric: ['#000000', '#1e0064', '#780064', '#a05a00', '#e6c800', '#fffadc'], + + Viridis: [ + '#440154', + '#48186a', + '#472d7b', + '#424086', + '#3b528b', + '#33638d', + '#2c728e', + '#26828e', + '#21918c', + '#1fa088', + '#28ae80', + '#3fbc73', + '#5ec962', + '#84d44b', + '#addc30', + '#d8e219', + '#fde725', + ], + + Cividis: [ + '#00204c', + '#002a66', + '#00346e', + '#273f6c', + '#3c4a6c', + '#4c556b', + '#5b5f6d', + '#686a70', + '#757575', + '#838178', + '#929c78', + '#a19676', + '#b0a572', + '#c0af6d', + '#d1ba65', + '#e1c75c', + '#f3db4f', + '#ffe945', + ], + + Accent: [ + '#7fc97f', + '#beaed4', + '#fdc086', + '#ffff99', + '#386cb0', + '#f0027f', + '#bf5b17', + '#666666', + ], +}; diff --git a/anndata-zarr/src/hooks.js b/anndata-zarr/src/hooks.js new file mode 100644 index 00000000..76662c7c --- /dev/null +++ b/anndata-zarr/src/hooks.js @@ -0,0 +1,113 @@ +import { useCallback } from 'react'; + +import { useQueries, useQuery } from '@tanstack/react-query'; +import _ from 'lodash'; + +import { COLORSCALES } from './constants/colorscales'; +import { + fetchDataFromZarr, + getZarrPath, + getColors, + getVarNames, + getObs, +} from './utils'; + +const getAnndataColors = async (url, matrixProps, colorProps) => { + let zarrData; + try { + const zarrPath = await getZarrPath(url, matrixProps); + zarrData = await fetchDataFromZarr(zarrPath.url, zarrPath.path, zarrPath.s); + } catch (error) { + console.error(error); + return null; + } + if (!zarrData) return null; + + const { categories } = zarrData; + + const max = categories + ? categories.length - 1 + : colorProps?.max || _.max(zarrData.data); + const min = categories ? 0 : colorProps?.min || _.min(zarrData.data); + const colorscale = categories ? COLORSCALES.Accent : colorProps?.colorscale; + + return { + colors: getColors({ + data: zarrData.data, + max, + min, + colorProps: { ...colorProps, colorscale }, + categories, + }), + max, + min, + ...(categories ? { categories } : {}), + colorscale, + }; +}; + +export const useAnndataColors = (adata = { url: null }, opts = {}) => { + const { + data = null, + isLoading = false, + serverError = null, + } = useQuery({ + queryKey: ['anndataColor', adata.url, adata.matrixProps, adata.colorProps], + queryFn: () => + getAnndataColors(adata.url, adata.matrixProps, adata.colorProps), + ...opts, + }); + + return { data, isLoading, serverError }; +}; + +export const useAnndatasColors = (adatas = [], opts = {}) => { + const combine = useCallback((results) => { + return { + data: results.map((result) => result.data), + isLoading: results.some((result) => result.isLoading), + serverError: results.find((result) => result.error), + }; + }, []); + + const { + data = null, + isLoading = false, + serverError = null, + } = useQueries({ + queries: adatas.map(({ url, matrixProps, colorProps }) => ({ + queryKey: ['anndataColor', url, matrixProps, colorProps], + queryFn: () => getAnndataColors(url, matrixProps, colorProps), + })), + ...opts, + combine, + }); + + return { data, isLoading, serverError }; +}; + +export const useAnndataFeatures = (adata = { url: null, namesCol: null }) => { + const { + data = null, + isLoading = false, + serverError = null, + } = useQuery({ + queryKey: ['anndataFeatures', adata.url, adata.namesCol], + queryFn: () => getVarNames(adata.url, adata.namesCol), + }); + + return { data, isLoading, serverError }; +}; + +export const useAnndataObs = (adata = { url: null }) => { + const { + data = null, + isLoading = false, + serverError = null, + } = useQuery({ + queryKey: ['anndataObs', adata.url], + queryFn: () => getObs(adata.url), + }); + + return { data, isLoading, serverError }; +}; diff --git a/anndata-zarr/src/index.css b/anndata-zarr/src/index.css new file mode 100644 index 00000000..48548679 --- /dev/null +++ b/anndata-zarr/src/index.css @@ -0,0 +1,37 @@ +.grad-step { + display: inline-block; + height: 20px; + width: 1%; +} + +.gradient { + width: 100%; + white-space: nowrap; + position: relative; + display: inline-block; + top: 4px; + padding-bottom: 15px; +} + +.gradient .domain-min { + position: absolute; + left: 0; + font-size: 11px; + bottom: 3px; +} + +.gradient .domain-mid { + position: absolute; + right: 25%; + left: 25%; + text-align: center; + font-size: 11px; + bottom: 3px; +} + +.gradient .domain-max { + position: absolute; + right: 0; + font-size: 11px; + bottom: 3px; +} \ No newline at end of file diff --git a/anndata-zarr/src/index.js b/anndata-zarr/src/index.js new file mode 100644 index 00000000..ea88d0ef --- /dev/null +++ b/anndata-zarr/src/index.js @@ -0,0 +1,6 @@ +export { useAnndataColors } from './hooks'; +export { AnndataProvider } from './provider'; +export { COLORSCALES } from './constants/colorscales'; +export { FeatureSelect } from './components/FeatureSelect'; +export { ObsSelect } from './components/ObsSelect'; +export { AnndataController } from './components/AnndataController'; diff --git a/anndata-zarr/src/provider.jsx b/anndata-zarr/src/provider.jsx new file mode 100644 index 00000000..33d57582 --- /dev/null +++ b/anndata-zarr/src/provider.jsx @@ -0,0 +1,11 @@ +import React from 'react'; + +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; + +const queryClient = new QueryClient(); + +export function AnndataProvider({ children }) { + return ( + {children} + ); +} diff --git a/anndata-zarr/src/utils.js b/anndata-zarr/src/utils.js new file mode 100644 index 00000000..d8932cd7 --- /dev/null +++ b/anndata-zarr/src/utils.js @@ -0,0 +1,161 @@ +import _ from 'lodash'; +import { FetchStore, open, get } from 'zarrita'; + +import { COLORSCALES } from './constants/colorscales'; + +export const fetchDataFromZarr = async (url, path, s) => { + try { + const store = new FetchStore(url); + const node = await open(store, { kind: 'group' }); + + const dataNode = await open(node.resolve(path)); + let result; + if ( + dataNode.attrs?.['encoding-type'] === 'array' || + dataNode.attrs?.['encoding-type'] === 'string-array' + ) { + result = await get(dataNode, s); + } else if (dataNode.attrs?.['encoding-type'] === 'categorical') { + const categoriesArr = await open(dataNode.resolve('categories'), { + kind: 'array', + }); + const codesArr = await open(dataNode.resolve('codes'), { kind: 'array' }); + const { data: categories } = await get(categoriesArr); + const { data } = await get(codesArr, s); + result = { data, categories }; + } else { + throw new Error('Unsupported encoding-type'); + } + + return result; + } catch (error) { + throw error; + } +}; + +export const getVarNames = async (url, namesCol = '_index') => { + try { + const store = new FetchStore(url); + const node = await open(store, { kind: 'group' }); + + const arr = await open(node.resolve(`var/${namesCol}`, { kind: 'array' })); + const varNames = (await get(arr)).data; + return varNames; + } catch (error) { + console.error(error); + return []; + } +}; + +export const getObs = async (url) => { + try { + const store = new FetchStore(url); + const node = await open(store, { kind: 'group' }); + + const cols = (await open(node.resolve('obs', { kind: 'group' }))).attrs?.[ + 'column-order' + ]; + const obs = { categorical: [], numerical: [] }; + for (const col of cols) { + const dataNode = await open(node.resolve(`obs/${col}`)); + const { 'encoding-type': encodingType } = dataNode.attrs || {}; + if (encodingType === 'categorical') { + const categoriesArr = await open(dataNode.resolve('categories'), { + kind: 'array', + }); + const { data: categories } = await get(categoriesArr); + obs.categorical.push({ name: col, categories }); + } else if (encodingType === 'array') { + obs.numerical.push({ name: col }); + } + } + return obs; + } catch (error) { + console.error(error); + return []; + } +}; + +export const getVarIndex = async (url, varId, namesCol = '_index') => { + try { + const store = new FetchStore(url); + const node = await open(store, { kind: 'group' }); + + const arr = await open(node.resolve(`var/${namesCol}`, { kind: 'array' })); + const varNames = (await get(arr)).data; + const varIndex = varNames.findIndex((name) => name === varId); + return varIndex; + } catch (error) { + return -1; + } +}; + +export const getZarrPath = async (url, matrixProps) => { + const { feature, obs } = matrixProps; + if (feature) { + if (feature.index !== undefined && feature.index !== null) { + return { url, path: 'X', s: [null, feature.index] }; + } else if (feature.name) { + return { + url, + path: 'X', + s: [null, await getVarIndex(url, feature.name, feature.namesCol)], + }; + } + } + + if (obs) { + return { + url, + path: `obs/${obs.col}`, + s: null, + }; + } + + throw new Error('No feature or obs in matrixProps'); +}; + +const parseHexColor = (color) => { + const r = parseInt(color?.substring(1, 3), 16); + const g = parseInt(color?.substring(3, 5), 16); + const b = parseInt(color?.substring(5, 7), 16); + + return [r, g, b]; +}; + +const interpolateColor = (color1, color2, factor) => { + const [r1, g1, b1] = parseHexColor(color1); + const [r2, g2, b2] = parseHexColor(color2); + + const r = Math.round(r1 + factor * (r2 - r1)); + const g = Math.round(g1 + factor * (g2 - g1)); + const b = Math.round(b1 + factor * (b2 - b1)); + + return [r, g, b]; +}; + +const computeColor = (colormap, value) => { + if (!colormap || isNaN(value)) { + return [0, 0, 0, 255]; + } else if (value <= 0) { + return parseHexColor(colormap[0]); + } else if (value >= 1) { + return parseHexColor(colormap[colormap.length - 1]); + } + const index1 = Math.floor(value * (colormap.length - 1)); + const index2 = Math.ceil(value * (colormap.length - 1)); + const factor = (value * (colormap.length - 1)) % 1; + return interpolateColor(colormap[index1], colormap[index2], factor); +}; + +export const getColor = ({ value, colorscale = COLORSCALES.Viridis }) => { + return [...computeColor(colorscale, value), 255]; +}; + +export const getColors = ({ data, max, min, colorProps, categories }) => { + return _.map(data, (v, i) => ({ + labelValue: i + 1, + rgba: getColor({ value: (v - min) / (max - min), ...colorProps }), + value: categories ? categories[v] : v, + })); +}; diff --git a/anndata-zarr/vite.config.js b/anndata-zarr/vite.config.js new file mode 100644 index 00000000..9dc91aff --- /dev/null +++ b/anndata-zarr/vite.config.js @@ -0,0 +1,34 @@ +import path from 'path'; + +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], + build: { + // outDir: path.resolve(__dirname, '../dist'), + lib: { + entry: path.resolve(__dirname, 'src/index.js'), + name: 'BiongffAnndataZarr', + formats: ['es', 'cjs'], + fileName: (format) => `biongff-anndata-zarr.${format}.js`, + }, + rollupOptions: { + external: [ + 'react', + 'react-dom', + '@mui/material', + '@mui/icons-material', + '@emotion/react', + '@emotion/styled', + ], + output: { + globals: { + react: 'React', + 'react-dom': 'ReactDOM', + }, + }, + }, + }, +}); diff --git a/viewer/src/components/Viewer.tsx b/viewer/src/components/Viewer.tsx index 39e1e3ae..f1b67161 100644 --- a/viewer/src/components/Viewer.tsx +++ b/viewer/src/components/Viewer.tsx @@ -20,7 +20,6 @@ export default function Viewer() { const firstLayer = layers[0] as VizarrLayer; const axisNavigationSnackbar = useAxisNavigation(deckRef, viewport); - const resetViewState = React.useCallback( (layer: VizarrLayer) => { const { deck } = deckRef.current || {}; From 4e574429d584ef93caf4f636d67b0c60756bfc77 Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Thu, 19 Mar 2026 13:06:21 +0000 Subject: [PATCH 02/26] Working prototype --- .../src/components/AnndataController.jsx | 4 +- anndata-zarr/src/components/FeatureSelect.jsx | 2 +- pnpm-lock.yaml | 327 ++++++++++++++++++ pnpm-workspace.yaml | 3 +- sites/app/package.json | 1 + sites/app/src/App.tsx | 49 ++- sites/app/src/index.css | 9 + sites/app/src/main.tsx | 1 + sites/app/vite.config.js | 5 +- viewer/src/components/VizarrViewer.tsx | 15 +- 10 files changed, 401 insertions(+), 15 deletions(-) create mode 100644 sites/app/src/index.css diff --git a/anndata-zarr/src/components/AnndataController.jsx b/anndata-zarr/src/components/AnndataController.jsx index 131ae6c7..ac2d2dfe 100644 --- a/anndata-zarr/src/components/AnndataController.jsx +++ b/anndata-zarr/src/components/AnndataController.jsx @@ -6,7 +6,7 @@ import Stack from '@mui/material/Stack'; import { FeatureSelect } from './FeatureSelect'; import { ObsSelect } from './ObsSelect'; -export const AnndataController = ({ adata, callback = () => {} }) => { +export const AnndataController = ({ adata, callback = () => { } }) => { const [feature, setFeature] = useState(null); const [obsCol, setObsCol] = useState(null); @@ -40,4 +40,4 @@ export const AnndataController = ({ adata, callback = () => {} }) => { ); -}; +} diff --git a/anndata-zarr/src/components/FeatureSelect.jsx b/anndata-zarr/src/components/FeatureSelect.jsx index 23b4732b..43b987af 100644 --- a/anndata-zarr/src/components/FeatureSelect.jsx +++ b/anndata-zarr/src/components/FeatureSelect.jsx @@ -29,7 +29,7 @@ export const FeatureSelect = ({ adata, feature, onSelect, - callback = () => {}, + callback = () => { }, }) => { const [searchTerm, setSearchTerm] = useState(''); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7f2009ba..6d24b83e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,8 +62,54 @@ importers: specifier: ^4.0.15 version: 4.0.15(@types/node@24.3.0) + anndata-zarr: + dependencies: + '@emotion/react': + specifier: ^11.14.0 + version: 11.14.0(@types/react@18.3.18)(react@18.3.1) + '@emotion/styled': + specifier: ^11.14.1 + version: 11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) + '@mui/icons-material': + specifier: ^7.2.0 + version: 7.3.4(@mui/material@7.3.4(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) + '@mui/material': + specifier: ^7.2.0 + version: 7.3.4(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@tanstack/react-query': + specifier: ^5.85.3 + version: 5.90.21(react@18.3.1) + lodash: + specifier: ^4.17.21 + version: 4.17.21 + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) + react-window: + specifier: ^2.0.2 + version: 2.2.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + zarrita: + specifier: 0.5.0 + version: 0.5.0 + devDependencies: + '@vitejs/plugin-react': + specifier: ^4.3.3 + version: 4.3.4(vite@6.2.7(@types/node@24.3.0)) + vite: + specifier: ^6.2.3 + version: 6.2.7(@types/node@24.3.0) + vitest: + specifier: ^3.0.8 + version: 3.2.4(@types/node@24.3.0) + sites/app: dependencies: + '@biongff/anndata-zarr': + specifier: workspace:* + version: link:../../anndata-zarr '@biongff/vizarr': specifier: workspace:* version: link:../../viewer @@ -1293,6 +1339,14 @@ packages: '@standard-schema/spec@1.0.0': resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} + '@tanstack/query-core@5.90.20': + resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==} + + '@tanstack/react-query@5.90.21': + resolution: {integrity: sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg==} + peerDependencies: + react: ^18 || ^19 + '@turf/boolean-clockwise@5.1.5': resolution: {integrity: sha512-FqbmEEOJ4rU4/2t7FKx0HUWmjFEVqR+NJrFP7ymGSjja2SQ7Q91nnBihGuT+yuHHl6ElMjQ3ttsB/eTmyCycxA==} @@ -1454,9 +1508,23 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + '@vitest/expect@4.0.15': resolution: {integrity: sha512-Gfyva9/GxPAWXIWjyGDli9O+waHDC0Q0jaLdFP1qPAUUfo1FEXPXUfUkp3eZA0sSq340vPycSyOlYUeM15Ft1w==} + '@vitest/mocker@3.2.4': + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + '@vitest/mocker@4.0.15': resolution: {integrity: sha512-CZ28GLfOEIFkvCFngN8Sfx5h+Se0zN+h4B7yOsPVCcgtiO7t5jt9xQh2E1UkFep+eb9fjyMfuC5gBypwb07fvQ==} peerDependencies: @@ -1468,18 +1536,33 @@ packages: vite: optional: true + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + '@vitest/pretty-format@4.0.15': resolution: {integrity: sha512-SWdqR8vEv83WtZcrfLNqlqeQXlQLh2iilO1Wk1gv4eiHKjEzvgHb2OVc3mIPyhZE6F+CtfYjNlDJwP5MN6Km7A==} + '@vitest/runner@3.2.4': + resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} + '@vitest/runner@4.0.15': resolution: {integrity: sha512-+A+yMY8dGixUhHmNdPUxOh0la6uVzun86vAbuMT3hIDxMrAOmn5ILBHm8ajrqHE0t8R9T1dGnde1A5DTnmi3qw==} + '@vitest/snapshot@3.2.4': + resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} + '@vitest/snapshot@4.0.15': resolution: {integrity: sha512-A7Ob8EdFZJIBjLjeO0DZF4lqR6U7Ydi5/5LIZ0xcI+23lYlsYJAfGn8PrIWTYdZQRNnSRlzhg0zyGu37mVdy5g==} + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + '@vitest/spy@4.0.15': resolution: {integrity: sha512-+EIjOJmnY6mIfdXtE/bnozKEvTC4Uczg19yeZ2vtCz5Yyb0QQ31QWVQ8hswJ3Ysx/K2EqaNsVanjr//2+P3FHw==} + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + '@vitest/utils@4.0.15': resolution: {integrity: sha512-HXjPW2w5dxhTD0dLwtYHDnelK3j8sR8cWIaLxr22evTyY6q8pRCjZSmhRWVjBaOVXChQd6AwMzi9pucorXCPZA==} @@ -1680,6 +1763,10 @@ packages: resolution: {integrity: sha512-Bvx4xH00qweepGc43xFvMs5BKASXTbHaHm6+kDYIK9p/4iFwjATQkmPKHQSgJZzKbAymhztRbXUf1Nqhzl73/Q==} engines: {node: '>=0.10.0'} + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -1690,6 +1777,10 @@ packages: cartocolor@5.0.2: resolution: {integrity: sha512-Ihb/wU5V6BVbHwapd8l/zg7bnhZ4YPFVfa7quSpL86lfkPJSf4YuNBT+EvesPRP5vSqhl6vZVsQJwCR8alBooQ==} + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} + chai@6.2.1: resolution: {integrity: sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==} engines: {node: '>=18'} @@ -1713,6 +1804,10 @@ packages: charenc@0.0.2: resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} + clean-stack@2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} @@ -1911,6 +2006,15 @@ packages: supports-color: optional: true + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + deck.gl@9.0.41: resolution: {integrity: sha512-Exj/E18ZYWXdkZjz+gS+kSxll7kIpAO0dfOsI7jgMjdn6g0NWEv7W4GJIkPbGkr6E/GurAJRRC9gdjtTS/LKYA==} peerDependencies: @@ -1925,6 +2029,10 @@ packages: react-dom: optional: true + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -2409,6 +2517,9 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -2513,6 +2624,9 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -2883,6 +2997,10 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} + pbf@3.3.0: resolution: {integrity: sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==} hasBin: true @@ -2985,6 +3103,12 @@ packages: react: '>=16.6.0' react-dom: '>=16.6.0' + react-window@2.2.7: + resolution: {integrity: sha512-SH5nvfUQwGHYyriDUAOt7wfPsfG9Qxd6OdzQxl5oQ4dsSsUicqQvjV7dR+NqZ4coY0fUn3w1jnC5PwzIUWEg5w==} + peerDependencies: + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + react@18.3.1: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} @@ -3202,6 +3326,9 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + strnum@1.1.2: resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} @@ -3280,6 +3407,9 @@ packages: tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyexec@1.0.2: resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} engines: {node: '>=18'} @@ -3288,10 +3418,22 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + tinyrainbow@3.0.3: resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} engines: {node: '>=14.0.0'} + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + engines: {node: '>=14.0.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -3396,6 +3538,11 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + vite-plugin-dts@4.5.4: resolution: {integrity: sha512-d4sOM8M/8z7vRXHHq/ebbblfaxENjogAAekcfcDCCwAyvGqnPrc7f4NZbvItS+g4WTgerW0xDwSz5qz11JT3vg==} peerDependencies: @@ -3445,6 +3592,34 @@ packages: yaml: optional: true + vitest@3.2.4: + resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.2.4 + '@vitest/ui': 3.2.4 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vitest@4.0.15: resolution: {integrity: sha512-n1RxDp8UJm6N0IbJLQo+yzLZ2sQCDyl1o0LeugbPWf8+8Fttp29GghsQBjYJVmWq3gBFfe9Hs1spR44vovn2wA==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -4912,6 +5087,13 @@ snapshots: '@standard-schema/spec@1.0.0': {} + '@tanstack/query-core@5.90.20': {} + + '@tanstack/react-query@5.90.21(react@18.3.1)': + dependencies: + '@tanstack/query-core': 5.90.20 + react: 18.3.1 + '@turf/boolean-clockwise@5.1.5': dependencies: '@turf/helpers': 5.1.5 @@ -5147,6 +5329,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitest/expect@3.2.4': + dependencies: + '@types/chai': 5.2.3 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.3.3 + tinyrainbow: 2.0.0 + '@vitest/expect@4.0.15': dependencies: '@standard-schema/spec': 1.0.0 @@ -5156,6 +5346,14 @@ snapshots: chai: 6.2.1 tinyrainbow: 3.0.3 + '@vitest/mocker@3.2.4(vite@6.2.7(@types/node@24.3.0))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 6.2.7(@types/node@24.3.0) + '@vitest/mocker@4.0.15(vite@6.2.7(@types/node@24.3.0))': dependencies: '@vitest/spy': 4.0.15 @@ -5164,23 +5362,49 @@ snapshots: optionalDependencies: vite: 6.2.7(@types/node@24.3.0) + '@vitest/pretty-format@3.2.4': + dependencies: + tinyrainbow: 2.0.0 + '@vitest/pretty-format@4.0.15': dependencies: tinyrainbow: 3.0.3 + '@vitest/runner@3.2.4': + dependencies: + '@vitest/utils': 3.2.4 + pathe: 2.0.3 + strip-literal: 3.1.0 + '@vitest/runner@4.0.15': dependencies: '@vitest/utils': 4.0.15 pathe: 2.0.3 + '@vitest/snapshot@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + magic-string: 0.30.21 + pathe: 2.0.3 + '@vitest/snapshot@4.0.15': dependencies: '@vitest/pretty-format': 4.0.15 magic-string: 0.30.21 pathe: 2.0.3 + '@vitest/spy@3.2.4': + dependencies: + tinyspy: 4.0.4 + '@vitest/spy@4.0.15': {} + '@vitest/utils@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + loupe: 3.2.1 + tinyrainbow: 2.0.0 + '@vitest/utils@4.0.15': dependencies: '@vitest/pretty-format': 4.0.15 @@ -5421,6 +5645,8 @@ snapshots: buf-compare@1.0.1: {} + cac@6.7.14: {} + callsites@3.1.0: {} caniuse-lite@1.0.30001703: {} @@ -5429,6 +5655,14 @@ snapshots: dependencies: colorbrewer: 1.5.6 + chai@5.3.3: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.3 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 + chai@6.2.1: {} chalk@2.4.2: @@ -5448,6 +5682,8 @@ snapshots: charenc@0.0.2: {} + check-error@2.1.3: {} + clean-stack@2.2.0: {} clean-stack@5.3.0: @@ -5637,6 +5873,10 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.4.3: + dependencies: + ms: 2.1.3 + deck.gl@9.0.41(@arcgis/core@4.32.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@deck.gl/aggregation-layers': 9.0.41(@deck.gl/core@9.0.41)(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) @@ -5660,6 +5900,8 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + deep-eql@5.0.2: {} + deep-extend@0.6.0: {} deep-strict-equal@0.2.0: @@ -6080,6 +6322,8 @@ snapshots: js-tokens@4.0.0: {} + js-tokens@9.0.1: {} + js-yaml@4.1.0: dependencies: argparse: 2.0.1 @@ -6179,6 +6423,8 @@ snapshots: dependencies: js-tokens: 4.0.0 + loupe@3.2.1: {} + lru-cache@10.4.3: {} lru-cache@11.2.2: {} @@ -6449,6 +6695,8 @@ snapshots: pathe@2.0.3: {} + pathval@2.0.1: {} + pbf@3.3.0: dependencies: ieee754: 1.2.1 @@ -6547,6 +6795,11 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + react-window@2.2.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -6797,6 +7050,10 @@ snapshots: strip-json-comments@3.1.1: {} + strip-literal@3.1.0: + dependencies: + js-tokens: 9.0.1 + strnum@1.1.2: {} stylis@4.2.0: {} @@ -6869,6 +7126,8 @@ snapshots: tinybench@2.9.0: {} + tinyexec@0.3.2: {} + tinyexec@1.0.2: {} tinyglobby@0.2.15: @@ -6876,8 +7135,14 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 + tinypool@1.1.1: {} + + tinyrainbow@2.0.0: {} + tinyrainbow@3.0.3: {} + tinyspy@4.0.4: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -6952,6 +7217,27 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 + vite-node@3.2.4(@types/node@24.3.0): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 6.2.7(@types/node@24.3.0) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + vite-plugin-dts@4.5.4(@types/node@24.3.0)(rollup@4.40.1)(typescript@5.8.2)(vite@6.2.7(@types/node@24.3.0)): dependencies: '@microsoft/api-extractor': 7.55.2(@types/node@24.3.0) @@ -6980,6 +7266,47 @@ snapshots: '@types/node': 24.3.0 fsevents: 2.3.3 + vitest@3.2.4(@types/node@24.3.0): + dependencies: + '@types/chai': 5.2.3 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@6.2.7(@types/node@24.3.0)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.3.0 + magic-string: 0.30.21 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.15 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 6.2.7(@types/node@24.3.0) + vite-node: 3.2.4(@types/node@24.3.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.3.0 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + vitest@4.0.15(@types/node@24.3.0): dependencies: '@vitest/expect': 4.0.15 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 88f2d98a..b35b5f08 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,4 @@ packages: - 'viewer' - - 'sites/*' \ No newline at end of file + - 'sites/*' + - 'anndata-zarr' diff --git a/sites/app/package.json b/sites/app/package.json index 73ff1897..8012e1db 100644 --- a/sites/app/package.json +++ b/sites/app/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "@biongff/vizarr": "workspace:*", + "@biongff/anndata-zarr": "workspace:*", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", "@mui/icons-material": "^7.2.0", diff --git a/sites/app/src/App.tsx b/sites/app/src/App.tsx index 88695323..d8bc7c3c 100644 --- a/sites/app/src/App.tsx +++ b/sites/app/src/App.tsx @@ -1,6 +1,19 @@ import { type ViewState, Vizarr } from "@biongff/vizarr"; +import { AnndataProvider, AnndataController } from "@biongff/anndata-zarr" import debounce from "just-debounce-it"; import * as React from "react"; +import { ThemeProvider, createTheme } from '@mui/material/styles' +import CssBaseline from '@mui/material/CssBaseline' + + +const darkTheme = createTheme({ + palette: { + mode: 'dark', + }, + typography: { + fontSize: 12, + }, +}); function parseViewStateFromUrl(): ViewState | undefined { const url = new URL(window.location.href); @@ -17,18 +30,24 @@ function parseViewStateFromUrl(): ViewState | undefined { return undefined; } + export default function App() { const urlString = window.location.href; - const { sources, viewState } = React.useMemo(() => { + + const { sources, viewState, anndatas } = React.useMemo(() => { const url = new URL(urlString); const { searchParams } = url; return { sources: searchParams.getAll("source"), viewState: parseViewStateFromUrl(), + anndatas: searchParams + .getAll('anndata') + .map((v) => (v ? { url: v } : null)), }; }, [urlString]); + const [colors, setColors] = React.useState(() => Array(sources.length).fill(null)); // Debounced viewState change handler const handleViewStateChange = React.useMemo( () => @@ -45,10 +64,30 @@ export default function App() { }, 200), [], ); - + const selectCallback = (colorData: any, i: any) => { + setColors((prev) => { + return prev.map((c, ci) => (ci === i ? colorData : c)); + }); + }; + const anndataControllers = React.useMemo(() => { + return sources.map((_s, i) => { + if (!anndatas?.[i]?.url) return null; + return ( + selectCallback(colorData, i)} + /> + ); + }); + }, [anndatas, sources]); return ( -
- -
+ + + +
{anndataControllers}
+ +
+
); } diff --git a/sites/app/src/index.css b/sites/app/src/index.css new file mode 100644 index 00000000..308a6312 --- /dev/null +++ b/sites/app/src/index.css @@ -0,0 +1,9 @@ +.container-right { + position: absolute; + top: 1rem; + right: 1rem; + bottom: 1rem; + z-index: 1; + padding: 0.5rem; + overflow-y: auto; +} diff --git a/sites/app/src/main.tsx b/sites/app/src/main.tsx index dc0390d2..df8831ae 100644 --- a/sites/app/src/main.tsx +++ b/sites/app/src/main.tsx @@ -2,6 +2,7 @@ import { version } from "@biongff/vizarr"; import React, { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import App from "./App"; +import './index.css' console.log(`vizarr v${version}: https://github.com/BioNGFF/vizarr`); diff --git a/sites/app/vite.config.js b/sites/app/vite.config.js index b176e62e..6b88a7d9 100644 --- a/sites/app/vite.config.js +++ b/sites/app/vite.config.js @@ -9,8 +9,9 @@ export default defineConfig(({ mode }) => ({ alias: { ...(mode === "development" ? { - "@biongff/vizarr": path.resolve(__dirname, "../../viewer/src/index.tsx"), - } + "@biongff/vizarr": path.resolve(__dirname, "../../viewer/src/index.tsx"), + "@biongff/anndata-zarr": path.resolve(__dirname, "../../anndata-zarr/src/index.js") + } : {}), }, }, diff --git a/viewer/src/components/VizarrViewer.tsx b/viewer/src/components/VizarrViewer.tsx index 91dbfb96..0f1d7e73 100644 --- a/viewer/src/components/VizarrViewer.tsx +++ b/viewer/src/components/VizarrViewer.tsx @@ -20,10 +20,12 @@ export interface VizarrViewerProps { sources?: string[]; viewState?: ViewState; onViewStateChange?: (viewState: ViewState) => void; + colours: []; } -function VizarrViewerComponent({ sources = [], viewState: initialViewState, onViewStateChange }: VizarrViewerProps) { +function VizarrViewerComponent({ sources = [], viewState: initialViewState, onViewStateChange, colours }: VizarrViewerProps) { const setSourceInfo = useSetAtom(sourceInfoAtom); + const sourceInfo = useAtomValue(sourceInfoAtom) const setViewStateAtom = useSetAtom(viewStateAtom); const sourceError = useAtomValue(sourceErrorAtom); const redirectObj = useAtomValue(redirectObjAtom); @@ -58,7 +60,7 @@ function VizarrViewerComponent({ sources = [], viewState: initialViewState, onVi ); React.useEffect(() => { - async function loadSources() { + async function loadSources(colours) { const results = await Promise.allSettled( configs.map(async (config, index) => { const sourceData = await createSourceData(config); @@ -72,6 +74,10 @@ function VizarrViewerComponent({ sources = [], viewState: initialViewState, onVi let sourceDatas = []; for (const res of results) { if (res.status === "fulfilled") { + + if (colours[0] !== null) { + res.value.labels[0].colors = colours[0] + } sourceDatas.push(res.value); } else { console.error(res.reason); @@ -81,9 +87,10 @@ function VizarrViewerComponent({ sources = [], viewState: initialViewState, onVi setSourceInfo(sourceDatas); } - loadSources(); - }, [configs, setSourceInfo]); + + loadSources(colours); + }, [configs, setSourceInfo, colours]); return ( <> {sourceError === null && redirectObj === null && ( From 1ce7c08302c3fbdaa702731c678caa24d309ea7a Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Mon, 23 Mar 2026 10:32:59 +0000 Subject: [PATCH 03/26] Inject colours into viewer --- pnpm-lock.yaml | 4 +- sites/app/package.json | 4 +- sites/app/src/App.tsx | 10 ++--- viewer/src/api.tsx | 7 ++++ viewer/src/components/VizarrViewer.tsx | 57 ++++---------------------- viewer/src/index.tsx | 2 +- viewer/src/io.ts | 34 ++++++++++++++- 7 files changed, 59 insertions(+), 59 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6d24b83e..e55c50a8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -108,10 +108,10 @@ importers: sites/app: dependencies: '@biongff/anndata-zarr': - specifier: workspace:* + specifier: workspace:anndata-zarr version: link:../../anndata-zarr '@biongff/vizarr': - specifier: workspace:* + specifier: workspace:viewer version: link:../../viewer '@emotion/react': specifier: ^11.14.0 diff --git a/sites/app/package.json b/sites/app/package.json index 8012e1db..506f786a 100644 --- a/sites/app/package.json +++ b/sites/app/package.json @@ -9,8 +9,8 @@ "check": "tsc" }, "dependencies": { - "@biongff/vizarr": "workspace:*", - "@biongff/anndata-zarr": "workspace:*", + "@biongff/vizarr": "workspace:viewer", + "@biongff/anndata-zarr": "workspace:anndata-zarr", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", "@mui/icons-material": "^7.2.0", diff --git a/sites/app/src/App.tsx b/sites/app/src/App.tsx index d8bc7c3c..02812aff 100644 --- a/sites/app/src/App.tsx +++ b/sites/app/src/App.tsx @@ -1,4 +1,4 @@ -import { type ViewState, Vizarr } from "@biongff/vizarr"; +import { type ViewState, type labelColor, Vizarr } from "@biongff/vizarr"; import { AnndataProvider, AnndataController } from "@biongff/anndata-zarr" import debounce from "just-debounce-it"; import * as React from "react"; @@ -30,11 +30,9 @@ function parseViewStateFromUrl(): ViewState | undefined { return undefined; } - export default function App() { const urlString = window.location.href; - const { sources, viewState, anndatas } = React.useMemo(() => { const url = new URL(urlString); const { searchParams } = url; @@ -47,7 +45,9 @@ export default function App() { }; }, [urlString]); - const [colors, setColors] = React.useState(() => Array(sources.length).fill(null)); + + + const [colors, setColors] = React.useState((): labelColor[][] => Array(sources.length).fill([])); // Debounced viewState change handler const handleViewStateChange = React.useMemo( () => @@ -86,7 +86,7 @@ export default function App() {
{anndataControllers}
- +
); diff --git a/viewer/src/api.tsx b/viewer/src/api.tsx index d6284bab..5afa231e 100644 --- a/viewer/src/api.tsx +++ b/viewer/src/api.tsx @@ -27,6 +27,13 @@ type Events = { export type { ViewState, ImageLayerConfig }; +export type labelColor = { + labelValue: number, + rgba: [r: number, g: number, b: number, a: number], + value?: string | number | null +} + + export interface VizarrViewer { addImage(config: ImageLayerConfig): void; setViewState(viewState: ViewState): void; diff --git a/viewer/src/components/VizarrViewer.tsx b/viewer/src/components/VizarrViewer.tsx index 0f1d7e73..b4fbbbcf 100644 --- a/viewer/src/components/VizarrViewer.tsx +++ b/viewer/src/components/VizarrViewer.tsx @@ -3,7 +3,7 @@ import { Box, Link, Typography } from "@mui/material"; import { type PrimitiveAtom, Provider, atom, useAtomValue, useSetAtom } from "jotai"; import React from "react"; import { ViewStateContext } from "../hooks"; -import { createSourceData } from "../io"; +import { loadSources } from "../io" import { type ImageLayerConfig, type ViewState, @@ -15,26 +15,24 @@ import { import theme from "../theme"; import Menu from "./Menu"; import Viewer from "./Viewer"; +import type { OmeColor } from "../layers/label-layer"; export interface VizarrViewerProps { sources?: string[]; viewState?: ViewState; onViewStateChange?: (viewState: ViewState) => void; - colours: []; + labelColours?: OmeColor[][]; } -function VizarrViewerComponent({ sources = [], viewState: initialViewState, onViewStateChange, colours }: VizarrViewerProps) { +function VizarrViewerComponent({ sources = [], viewState: initialViewState, onViewStateChange, labelColours }: VizarrViewerProps) { const setSourceInfo = useSetAtom(sourceInfoAtom); - const sourceInfo = useAtomValue(sourceInfoAtom) const setViewStateAtom = useSetAtom(viewStateAtom); const sourceError = useAtomValue(sourceErrorAtom); const redirectObj = useAtomValue(redirectObjAtom); - React.useEffect(() => { - if (initialViewState) { - setViewStateAtom(initialViewState); - } - }, [initialViewState, setViewStateAtom]); + if (initialViewState) { + setViewStateAtom(initialViewState); + } const viewStateAtomWithEffect: PrimitiveAtom = atom( (get) => get(viewStateAtom), @@ -50,47 +48,10 @@ function VizarrViewerComponent({ sources = [], viewState: initialViewState, onVi }, ); - const [configs] = React.useState( - sources.map((source, index) => { - const config: ImageLayerConfig = { - source: source, - }; - return config; - }), - ); - React.useEffect(() => { - async function loadSources(colours) { - const results = await Promise.allSettled( - configs.map(async (config, index) => { - const sourceData = await createSourceData(config); - const id = Math.random().toString(36).slice(2); - if (!sourceData.name) { - sourceData.name = `image_${index}`; - } - return { id, ...sourceData }; - }), - ); - let sourceDatas = []; - for (const res of results) { - if (res.status === "fulfilled") { - - if (colours[0] !== null) { - res.value.labels[0].colors = colours[0] - } - sourceDatas.push(res.value); - } else { - console.error(res.reason); - } - } - sourceDatas = sourceDatas.filter((s) => s !== null); - setSourceInfo(sourceDatas); - } - - + loadSources(sources, labelColours).then((sourceData) => setSourceInfo(sourceData)) + }, [sources, labelColours, setSourceInfo]); - loadSources(colours); - }, [configs, setSourceInfo, colours]); return ( <> {sourceError === null && redirectObj === null && ( diff --git a/viewer/src/index.tsx b/viewer/src/index.tsx index 5fe6d55e..9a674bfd 100644 --- a/viewer/src/index.tsx +++ b/viewer/src/index.tsx @@ -5,6 +5,6 @@ export { default as Vizarr } from "./components/VizarrViewer"; export type { VizarrViewerProps } from "./components/VizarrViewer"; export { createViewer } from "./api"; -export type { VizarrViewer } from "./api"; +export type { VizarrViewer, labelColor } from "./api"; export type { ViewState, ImageLayerConfig } from "./state"; diff --git a/viewer/src/io.ts b/viewer/src/io.ts index 6102e3e9..0bffdd70 100644 --- a/viewer/src/io.ts +++ b/viewer/src/io.ts @@ -3,7 +3,7 @@ import { ZarrPixelSource } from "./ZarrPixelSource"; import { loadOmeMultiscales, loadPlate, loadWell } from "./ome"; import * as utils from "./utils"; -import { DEFAULT_LABEL_OPACITY } from "./layers/label-layer"; +import { DEFAULT_LABEL_OPACITY, type OmeColor } from "./layers/label-layer"; import type { BaseLayerProps } from "./layers/viv-layers"; import type { ImageLayerConfig, LayerState, MultichannelConfig, SingleChannelConfig, SourceData } from "./state"; @@ -277,3 +277,35 @@ function getSourceSelectionTransform( ); }; } + +export async function loadSources(sources: string[], labelColors?: OmeColor[][]) { + const results = await Promise.allSettled( + sources.map(async (source, index) => { + const sourceData = await createSourceData({ source: source }); + const id = Math.random().toString(36).slice(2); + if (!sourceData.name) { + sourceData.name = `image_${index}`; + } + debugger; + if (labelColors && labelColors[index].length) { + if (!sourceData.labels) { + utils.assert("Feature colours provided but source image has no label!") + } else { + debugger; + sourceData.labels[0].colors = labelColors[index] + } + } + return { id, ...sourceData }; + }), + ); + let sourceDatas = []; + for (const res of results) { + if (res.status === "fulfilled") { + + sourceDatas.push(res.value); + } else { + console.error(res.reason); + } + } + return sourceDatas.filter((s) => s !== null); +} From ab4fc92a0d935eb68126975c46b048fab4599973 Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Wed, 25 Mar 2026 15:16:14 +0000 Subject: [PATCH 04/26] Show label layer when feature colours provided --- viewer/src/components/VizarrViewer.tsx | 5 ++++- viewer/src/io.ts | 12 +++++++----- viewer/src/state.ts | 9 +++++---- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/viewer/src/components/VizarrViewer.tsx b/viewer/src/components/VizarrViewer.tsx index b4fbbbcf..253e6692 100644 --- a/viewer/src/components/VizarrViewer.tsx +++ b/viewer/src/components/VizarrViewer.tsx @@ -49,7 +49,10 @@ function VizarrViewerComponent({ sources = [], viewState: initialViewState, onVi ); React.useEffect(() => { - loadSources(sources, labelColours).then((sourceData) => setSourceInfo(sourceData)) + loadSources(sources, labelColours).then((sourceData) => { + setSourceInfo(sourceData) + } + ) }, [sources, labelColours, setSourceInfo]); return ( diff --git a/viewer/src/io.ts b/viewer/src/io.ts index 0bffdd70..2e002ce2 100644 --- a/viewer/src/io.ts +++ b/viewer/src/io.ts @@ -225,7 +225,7 @@ export function initLayerStateFromSource(source: SourceData & { id: string }): L let labels = undefined; if (source.labels && source.labels.length > 0) { labels = source.labels.map((label, i) => ({ - on: false, + on: label.on ? label.on : false, transformSourceSelection: getSourceSelectionTransform(label.loader[0], source.loader[0]), layerProps: { id: `${source.id}_${i}`, @@ -286,13 +286,15 @@ export async function loadSources(sources: string[], labelColors?: OmeColor[][]) if (!sourceData.name) { sourceData.name = `image_${index}`; } - debugger; if (labelColors && labelColors[index].length) { - if (!sourceData.labels) { - utils.assert("Feature colours provided but source image has no label!") + if (!sourceData.labels || (!sourceData.labels.length)) { + console.log('Did not find source labels') + throw new Error('Feature colours provided but source image has no label!') } else { - debugger; + //Really not the best way to do this but the layer state is heavily wrapped up in + //being derived directly from the sourceData and would require a fairly large refactor to find sourceData.labels[0].colors = labelColors[index] + sourceData.labels[0].on = true } } return { id, ...sourceData }; diff --git a/viewer/src/state.ts b/viewer/src/state.ts index 9a85c7b4..15e9bc31 100644 --- a/viewer/src/state.ts +++ b/viewer/src/state.ts @@ -62,6 +62,7 @@ export type ImageLabels = Array<{ loader: ZarrPixelSource[]; modelMatrix: Matrix4; colors?: ReadonlyArray; + on?: boolean }>; export type SourceData = { @@ -184,10 +185,10 @@ const imageLabelsIstanceFamily = atomFamily((a: Atom) => return labels.map((label) => label.on ? new LabelLayer({ - ...label.layerProps, - selection: label.transformSourceSelection(layerProps.selections[0]), - pickable: true, - }) + ...label.layerProps, + selection: label.transformSourceSelection(layerProps.selections[0]), + pickable: true, + }) : null, ); }), From 108ccf7ef111d5d0a9e37e3346ec78c3801278c4 Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Thu, 26 Mar 2026 07:46:10 +0000 Subject: [PATCH 05/26] Linting --- anndata-zarr/.eslintrc.json | 116 +++++------- anndata-zarr/package.json | 4 +- .../src/components/AnndataController.jsx | 34 ++-- anndata-zarr/src/components/FeatureSelect.jsx | 39 ++-- anndata-zarr/src/components/Legend.jsx | 16 +- anndata-zarr/src/components/ObsSelect.jsx | 73 +++----- anndata-zarr/src/constants/colorscales.js | 175 +++++++----------- anndata-zarr/src/hooks.js | 31 ++-- anndata-zarr/src/index.css | 2 +- anndata-zarr/src/index.js | 12 +- anndata-zarr/src/provider.jsx | 8 +- anndata-zarr/src/utils.js | 63 +++---- anndata-zarr/vite.config.js | 25 +-- sites/app/src/App.tsx | 32 ++-- sites/app/src/main.tsx | 2 +- sites/app/vite.config.js | 6 +- viewer/src/api.tsx | 9 +- viewer/src/components/VizarrViewer.tsx | 18 +- viewer/src/io.ts | 13 +- viewer/src/state.ts | 10 +- viewer/tests/features.test.js | 59 +++--- 21 files changed, 296 insertions(+), 451 deletions(-) diff --git a/anndata-zarr/.eslintrc.json b/anndata-zarr/.eslintrc.json index b672f57c..69304d74 100644 --- a/anndata-zarr/.eslintrc.json +++ b/anndata-zarr/.eslintrc.json @@ -1,75 +1,43 @@ { - "extends": [ - "react-app", - "prettier", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:prettier/recommended" - ], - "settings": { - "import/resolver": { - "node": { - "extensions": [ - ".js", - ".jsx", - ".ts", - ".tsx" - ] - }, - "alias": { - "map": [ - [ - "@app", - "./src" - ] - ], - "extensions": [ - ".js", - ".jsx", - ".ts", - ".tsx" - ] - } - } - }, - "rules": { - "import/order": [ - "error", - { - "groups": [ - "builtin", - "external", - "internal", - [ - "parent", - "sibling" - ], - "index" - ], - "pathGroups": [ - { - "pattern": "react", - "group": "external", - "position": "before" - } - ], - "pathGroupsExcludedImportTypes": [ - "react" - ], - "newlines-between": "always", - "alphabetize": { - "order": "asc", - "caseInsensitive": true - } - } - ], - "prettier/prettier": [ - "error", - { - "singleQuote": true, - "tabWidth": 2, - "useTabs": false - } - ] - } -} \ No newline at end of file + "extends": ["react-app", "prettier", "plugin:import/errors", "plugin:import/warnings", "plugin:prettier/recommended"], + "settings": { + "import/resolver": { + "node": { + "extensions": [".js", ".jsx", ".ts", ".tsx"] + }, + "alias": { + "map": [["@app", "./src"]], + "extensions": [".js", ".jsx", ".ts", ".tsx"] + } + } + }, + "rules": { + "import/order": [ + "error", + { + "groups": ["builtin", "external", "internal", ["parent", "sibling"], "index"], + "pathGroups": [ + { + "pattern": "react", + "group": "external", + "position": "before" + } + ], + "pathGroupsExcludedImportTypes": ["react"], + "newlines-between": "always", + "alphabetize": { + "order": "asc", + "caseInsensitive": true + } + } + ], + "prettier/prettier": [ + "error", + { + "singleQuote": true, + "tabWidth": 2, + "useTabs": false + } + ] + } +} diff --git a/anndata-zarr/package.json b/anndata-zarr/package.json index 8adb6011..bdd7650b 100644 --- a/anndata-zarr/package.json +++ b/anndata-zarr/package.json @@ -5,9 +5,7 @@ "type": "module", "main": "dist/biongff-anndata-zarr.cjs.js", "module": "dist/biongff-anndata-zarr.es.js", - "files": [ - "dist" - ], + "files": ["dist"], "exports": { ".": { "import": "./dist/biongff-anndata-zarr.es.js", diff --git a/anndata-zarr/src/components/AnndataController.jsx b/anndata-zarr/src/components/AnndataController.jsx index ac2d2dfe..5ea26f92 100644 --- a/anndata-zarr/src/components/AnndataController.jsx +++ b/anndata-zarr/src/components/AnndataController.jsx @@ -1,12 +1,12 @@ -import React, { useState } from 'react'; +import React, { useState } from "react"; -import Box from '@mui/material/Box'; -import Stack from '@mui/material/Stack'; +import Box from "@mui/material/Box"; +import Stack from "@mui/material/Stack"; -import { FeatureSelect } from './FeatureSelect'; -import { ObsSelect } from './ObsSelect'; +import { FeatureSelect } from "./FeatureSelect"; +import { ObsSelect } from "./ObsSelect"; -export const AnndataController = ({ adata, callback = () => { } }) => { +export const AnndataController = ({ adata, callback = () => {} }) => { const [feature, setFeature] = useState(null); const [obsCol, setObsCol] = useState(null); @@ -21,23 +21,13 @@ export const AnndataController = ({ adata, callback = () => { } }) => { }; return ( - - - + + + - - + + ); -} +}; diff --git a/anndata-zarr/src/components/FeatureSelect.jsx b/anndata-zarr/src/components/FeatureSelect.jsx index 43b987af..6614f23e 100644 --- a/anndata-zarr/src/components/FeatureSelect.jsx +++ b/anndata-zarr/src/components/FeatureSelect.jsx @@ -1,21 +1,21 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useMemo, useState } from "react"; -import Box from '@mui/material/Box'; -import ListItem from '@mui/material/ListItem'; -import ListItemButton from '@mui/material/ListItemButton'; -import ListItemText from '@mui/material/ListItemText'; -import Stack from '@mui/material/Stack'; -import TextField from '@mui/material/TextField'; -import { List } from 'react-window'; +import Box from "@mui/material/Box"; +import ListItem from "@mui/material/ListItem"; +import ListItemButton from "@mui/material/ListItemButton"; +import ListItemText from "@mui/material/ListItemText"; +import Stack from "@mui/material/Stack"; +import TextField from "@mui/material/TextField"; +import { List } from "react-window"; -import { useAnndataColors, useAnndataFeatures } from '../hooks'; -import { Legend } from './Legend'; +import { useAnndataColors, useAnndataFeatures } from "../hooks"; +import { Legend } from "./Legend"; const RowComponent = ({ index, items, style, onSelect, selectedIndex }) => { return ( onSelect({ index: items[index].matrixIndex })} selected={items[index].matrixIndex === selectedIndex} > @@ -25,13 +25,8 @@ const RowComponent = ({ index, items, style, onSelect, selectedIndex }) => { ); }; -export const FeatureSelect = ({ - adata, - feature, - onSelect, - callback = () => { }, -}) => { - const [searchTerm, setSearchTerm] = useState(''); +export const FeatureSelect = ({ adata, feature, onSelect, callback = () => {} }) => { + const [searchTerm, setSearchTerm] = useState(""); const { data, isLoading, serverError } = useAnndataFeatures(adata); const colorData = useAnndataColors( @@ -61,9 +56,7 @@ export const FeatureSelect = ({ matrixIndex: index, })); if (!searchTerm) return allItems; - return allItems.filter((item) => - item.name.toLowerCase().includes(searchTerm.toLowerCase()), - ); + return allItems.filter((item) => item.name.toLowerCase().includes(searchTerm.toLowerCase())); }, [data, searchTerm]); const legend = useMemo(() => { @@ -84,12 +77,12 @@ export const FeatureSelect = ({ - + { const spanList = useMemo(() => { return _.range(100).map((i) => { const color = getColor({ value: i / 100, colorscale }); - return ( - - ); + return ; }); }, [colorscale]); diff --git a/anndata-zarr/src/components/ObsSelect.jsx b/anndata-zarr/src/components/ObsSelect.jsx index 84506a55..f7b28012 100644 --- a/anndata-zarr/src/components/ObsSelect.jsx +++ b/anndata-zarr/src/components/ObsSelect.jsx @@ -1,25 +1,25 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useMemo, useState } from "react"; -import ExpandLess from '@mui/icons-material/ExpandLess'; -import ExpandMore from '@mui/icons-material/ExpandMore'; -import Alert from '@mui/material/Alert'; -import Box from '@mui/material/Box'; -import Collapse from '@mui/material/Collapse'; -import Divider from '@mui/material/Divider'; -import FormControl from '@mui/material/FormControl'; -import FormControlLabel from '@mui/material/FormControlLabel'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import ListItemText from '@mui/material/ListItemText'; -import Radio from '@mui/material/Radio'; -import RadioGroup from '@mui/material/RadioGroup'; -import Stack from '@mui/material/Stack'; +import ExpandLess from "@mui/icons-material/ExpandLess"; +import ExpandMore from "@mui/icons-material/ExpandMore"; +import Alert from "@mui/material/Alert"; +import Box from "@mui/material/Box"; +import Collapse from "@mui/material/Collapse"; +import Divider from "@mui/material/Divider"; +import FormControl from "@mui/material/FormControl"; +import FormControlLabel from "@mui/material/FormControlLabel"; +import List from "@mui/material/List"; +import ListItem from "@mui/material/ListItem"; +import ListItemIcon from "@mui/material/ListItemIcon"; +import ListItemText from "@mui/material/ListItemText"; +import Radio from "@mui/material/Radio"; +import RadioGroup from "@mui/material/RadioGroup"; +import Stack from "@mui/material/Stack"; -import { COLORSCALES } from '../constants/colorscales'; -import { useAnndataColors, useAnndataObs } from '../hooks'; -import { getColor } from '../utils'; -import { Legend } from './Legend'; +import { COLORSCALES } from "../constants/colorscales"; +import { useAnndataColors, useAnndataObs } from "../hooks"; +import { getColor } from "../utils"; +import { Legend } from "./Legend"; // @TODO: fix styling (width) const CategoricalCol = ({ col, showColor = false }) => { @@ -28,10 +28,7 @@ const CategoricalCol = ({ col, showColor = false }) => { return ( - setOpen(!open)} - sx={{ display: 'flex', alignItems: 'center', cursor: 'pointer' }} - > + setOpen(!open)} sx={{ display: "flex", alignItems: "center", cursor: "pointer" }}> e.stopPropagation()} />} label={col.name} @@ -70,14 +67,7 @@ const CategoricalCol = ({ col, showColor = false }) => { }; const NumericalCol = ({ col }) => { - return ( - } - label={col.name} - key={col.name} - value={col.name} - /> - ); + return } label={col.name} key={col.name} value={col.name} />; }; export const ObsSelect = ({ adata, obsCol, onSelect, callback = () => {} }) => { @@ -125,26 +115,19 @@ export const ObsSelect = ({ adata, obsCol, onSelect, callback = () => {} }) => { - + Observations - - - onSelect(e.target.value)} - > + + + onSelect(e.target.value)}> Categorical {data.categorical.map((col) => ( - + ))} Numerical {data.numerical.map((col) => ( diff --git a/anndata-zarr/src/constants/colorscales.js b/anndata-zarr/src/constants/colorscales.js index 3834d121..4d7ec392 100644 --- a/anndata-zarr/src/constants/colorscales.js +++ b/anndata-zarr/src/constants/colorscales.js @@ -1,138 +1,89 @@ // From plotly https://github.com/plotly/plotly.js/blob/5bc25b490702e5ed61265207833dbd58e8ab27f1/src/components/colorscale/scales.js export const COLORSCALES = { - Greys: ['#000000', '#ffffff'], - - YlGnBu: [ - '#081d58', - '#253494', - '#225ea8', - '#1d91c0', - '#41b6c4', - '#7fcdbb', - '#c7e9b4', - '#edf8d9', - '#ffffd9', - ], + Greys: ["#000000", "#ffffff"], - Greens: [ - '#00441b', - '#006d2c', - '#238b45', - '#41ab5d', - '#74c476', - '#a1d9a5', - '#c7e9c0', - '#e5f5e0', - '#f7fcf5', - ], + YlGnBu: ["#081d58", "#253494", "#225ea8", "#1d91c0", "#41b6c4", "#7fcdbb", "#c7e9b4", "#edf8d9", "#ffffd9"], - YlOrRd: [ - '#800026', - '#bd0026', - '#e31a1c', - '#fc4e2a', - '#fd8d3c', - '#feb24c', - '#fed976', - '#ffed9f', - '#ffffcc', - ], + Greens: ["#00441b", "#006d2c", "#238b45", "#41ab5d", "#74c476", "#a1d9a5", "#c7e9c0", "#e5f5e0", "#f7fcf5"], - Bluered: ['#0000ff', '#ff0000'], + YlOrRd: ["#800026", "#bd0026", "#e31a1c", "#fc4e2a", "#fd8d3c", "#feb24c", "#fed976", "#ffed9f", "#ffffcc"], - RdBu: ['#050aac', '#6a89f7', '#bebebe', '#dcaa84', '#e6915a', '#b20a1c'], + Bluered: ["#0000ff", "#ff0000"], - Reds: ['#dcdcdc', '#f5c39d', '#f5a069', '#b20a1c'], + RdBu: ["#050aac", "#6a89f7", "#bebebe", "#dcaa84", "#e6915a", "#b20a1c"], - Blues: ['#050aac', '#283cba', '#4664f5', '#5a78f5', '#6a89f7', '#dcdcdc'], + Reds: ["#dcdcdc", "#f5c39d", "#f5a069", "#b20a1c"], + + Blues: ["#050aac", "#283cba", "#4664f5", "#5a78f5", "#6a89f7", "#dcdcdc"], Picnic: [ - '#0000ff', - '#3399ff', - '#66ccff', - '#99ccff', - '#ccccff', - '#ffffff', - '#ffccff', - '#ff99ff', - '#ff66cc', - '#ff6666', - '#ff0000', + "#0000ff", + "#3399ff", + "#66ccff", + "#99ccff", + "#ccccff", + "#ffffff", + "#ffccff", + "#ff99ff", + "#ff66cc", + "#ff6666", + "#ff0000", ], - Rainbow: [ - '#96005a', - '#0000c8', - '#0019ff', - '#0098ff', - '#2cff96', - '#97ff00', - '#ffe600', - '#ff6f00', - '#ff0000', - ], + Rainbow: ["#96005a", "#0000c8", "#0019ff", "#0098ff", "#2cff96", "#97ff00", "#ffe600", "#ff6f00", "#ff0000"], - Portland: ['#0c3383', '#0a88ba', '#f2d338', '#f28f38', '#d91e1e'], + Portland: ["#0c3383", "#0a88ba", "#f2d338", "#f28f38", "#d91e1e"], - Jet: ['#000083', '#003caa', '#05ffff', '#ffff00', '#fa0000', '#800000'], + Jet: ["#000083", "#003caa", "#05ffff", "#ffff00", "#fa0000", "#800000"], - Hot: ['#000000', '#e60000', '#ffd200', '#ffffff'], + Hot: ["#000000", "#e60000", "#ffd200", "#ffffff"], - Blackbody: ['#000000', '#e60000', '#e6d200', '#ffffff', '#a0c8ff'], + Blackbody: ["#000000", "#e60000", "#e6d200", "#ffffff", "#a0c8ff"], - Earth: ['#000082', '#00b4b4', '#28d228', '#e6e632', '#784614', '#ffffff'], + Earth: ["#000082", "#00b4b4", "#28d228", "#e6e632", "#784614", "#ffffff"], - Electric: ['#000000', '#1e0064', '#780064', '#a05a00', '#e6c800', '#fffadc'], + Electric: ["#000000", "#1e0064", "#780064", "#a05a00", "#e6c800", "#fffadc"], Viridis: [ - '#440154', - '#48186a', - '#472d7b', - '#424086', - '#3b528b', - '#33638d', - '#2c728e', - '#26828e', - '#21918c', - '#1fa088', - '#28ae80', - '#3fbc73', - '#5ec962', - '#84d44b', - '#addc30', - '#d8e219', - '#fde725', + "#440154", + "#48186a", + "#472d7b", + "#424086", + "#3b528b", + "#33638d", + "#2c728e", + "#26828e", + "#21918c", + "#1fa088", + "#28ae80", + "#3fbc73", + "#5ec962", + "#84d44b", + "#addc30", + "#d8e219", + "#fde725", ], Cividis: [ - '#00204c', - '#002a66', - '#00346e', - '#273f6c', - '#3c4a6c', - '#4c556b', - '#5b5f6d', - '#686a70', - '#757575', - '#838178', - '#929c78', - '#a19676', - '#b0a572', - '#c0af6d', - '#d1ba65', - '#e1c75c', - '#f3db4f', - '#ffe945', + "#00204c", + "#002a66", + "#00346e", + "#273f6c", + "#3c4a6c", + "#4c556b", + "#5b5f6d", + "#686a70", + "#757575", + "#838178", + "#929c78", + "#a19676", + "#b0a572", + "#c0af6d", + "#d1ba65", + "#e1c75c", + "#f3db4f", + "#ffe945", ], - Accent: [ - '#7fc97f', - '#beaed4', - '#fdc086', - '#ffff99', - '#386cb0', - '#f0027f', - '#bf5b17', - '#666666', - ], + Accent: ["#7fc97f", "#beaed4", "#fdc086", "#ffff99", "#386cb0", "#f0027f", "#bf5b17", "#666666"], }; diff --git a/anndata-zarr/src/hooks.js b/anndata-zarr/src/hooks.js index 76662c7c..73f9b702 100644 --- a/anndata-zarr/src/hooks.js +++ b/anndata-zarr/src/hooks.js @@ -1,16 +1,10 @@ -import { useCallback } from 'react'; +import { useCallback } from "react"; -import { useQueries, useQuery } from '@tanstack/react-query'; -import _ from 'lodash'; +import { useQueries, useQuery } from "@tanstack/react-query"; +import _ from "lodash"; -import { COLORSCALES } from './constants/colorscales'; -import { - fetchDataFromZarr, - getZarrPath, - getColors, - getVarNames, - getObs, -} from './utils'; +import { COLORSCALES } from "./constants/colorscales"; +import { fetchDataFromZarr, getColors, getObs, getVarNames, getZarrPath } from "./utils"; const getAnndataColors = async (url, matrixProps, colorProps) => { let zarrData; @@ -25,9 +19,7 @@ const getAnndataColors = async (url, matrixProps, colorProps) => { const { categories } = zarrData; - const max = categories - ? categories.length - 1 - : colorProps?.max || _.max(zarrData.data); + const max = categories ? categories.length - 1 : colorProps?.max || _.max(zarrData.data); const min = categories ? 0 : colorProps?.min || _.min(zarrData.data); const colorscale = categories ? COLORSCALES.Accent : colorProps?.colorscale; @@ -52,9 +44,8 @@ export const useAnndataColors = (adata = { url: null }, opts = {}) => { isLoading = false, serverError = null, } = useQuery({ - queryKey: ['anndataColor', adata.url, adata.matrixProps, adata.colorProps], - queryFn: () => - getAnndataColors(adata.url, adata.matrixProps, adata.colorProps), + queryKey: ["anndataColor", adata.url, adata.matrixProps, adata.colorProps], + queryFn: () => getAnndataColors(adata.url, adata.matrixProps, adata.colorProps), ...opts, }); @@ -76,7 +67,7 @@ export const useAnndatasColors = (adatas = [], opts = {}) => { serverError = null, } = useQueries({ queries: adatas.map(({ url, matrixProps, colorProps }) => ({ - queryKey: ['anndataColor', url, matrixProps, colorProps], + queryKey: ["anndataColor", url, matrixProps, colorProps], queryFn: () => getAnndataColors(url, matrixProps, colorProps), })), ...opts, @@ -92,7 +83,7 @@ export const useAnndataFeatures = (adata = { url: null, namesCol: null }) => { isLoading = false, serverError = null, } = useQuery({ - queryKey: ['anndataFeatures', adata.url, adata.namesCol], + queryKey: ["anndataFeatures", adata.url, adata.namesCol], queryFn: () => getVarNames(adata.url, adata.namesCol), }); @@ -105,7 +96,7 @@ export const useAnndataObs = (adata = { url: null }) => { isLoading = false, serverError = null, } = useQuery({ - queryKey: ['anndataObs', adata.url], + queryKey: ["anndataObs", adata.url], queryFn: () => getObs(adata.url), }); diff --git a/anndata-zarr/src/index.css b/anndata-zarr/src/index.css index 48548679..ada27f24 100644 --- a/anndata-zarr/src/index.css +++ b/anndata-zarr/src/index.css @@ -34,4 +34,4 @@ right: 0; font-size: 11px; bottom: 3px; -} \ No newline at end of file +} diff --git a/anndata-zarr/src/index.js b/anndata-zarr/src/index.js index ea88d0ef..1a061206 100644 --- a/anndata-zarr/src/index.js +++ b/anndata-zarr/src/index.js @@ -1,6 +1,6 @@ -export { useAnndataColors } from './hooks'; -export { AnndataProvider } from './provider'; -export { COLORSCALES } from './constants/colorscales'; -export { FeatureSelect } from './components/FeatureSelect'; -export { ObsSelect } from './components/ObsSelect'; -export { AnndataController } from './components/AnndataController'; +export { useAnndataColors } from "./hooks"; +export { AnndataProvider } from "./provider"; +export { COLORSCALES } from "./constants/colorscales"; +export { FeatureSelect } from "./components/FeatureSelect"; +export { ObsSelect } from "./components/ObsSelect"; +export { AnndataController } from "./components/AnndataController"; diff --git a/anndata-zarr/src/provider.jsx b/anndata-zarr/src/provider.jsx index 33d57582..c250d401 100644 --- a/anndata-zarr/src/provider.jsx +++ b/anndata-zarr/src/provider.jsx @@ -1,11 +1,9 @@ -import React from 'react'; +import React from "react"; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; const queryClient = new QueryClient(); export function AnndataProvider({ children }) { - return ( - {children} - ); + return {children}; } diff --git a/anndata-zarr/src/utils.js b/anndata-zarr/src/utils.js index d8932cd7..881c32ba 100644 --- a/anndata-zarr/src/utils.js +++ b/anndata-zarr/src/utils.js @@ -1,30 +1,27 @@ -import _ from 'lodash'; -import { FetchStore, open, get } from 'zarrita'; +import _ from "lodash"; +import { FetchStore, get, open } from "zarrita"; -import { COLORSCALES } from './constants/colorscales'; +import { COLORSCALES } from "./constants/colorscales"; export const fetchDataFromZarr = async (url, path, s) => { try { const store = new FetchStore(url); - const node = await open(store, { kind: 'group' }); + const node = await open(store, { kind: "group" }); const dataNode = await open(node.resolve(path)); let result; - if ( - dataNode.attrs?.['encoding-type'] === 'array' || - dataNode.attrs?.['encoding-type'] === 'string-array' - ) { + if (dataNode.attrs?.["encoding-type"] === "array" || dataNode.attrs?.["encoding-type"] === "string-array") { result = await get(dataNode, s); - } else if (dataNode.attrs?.['encoding-type'] === 'categorical') { - const categoriesArr = await open(dataNode.resolve('categories'), { - kind: 'array', + } else if (dataNode.attrs?.["encoding-type"] === "categorical") { + const categoriesArr = await open(dataNode.resolve("categories"), { + kind: "array", }); - const codesArr = await open(dataNode.resolve('codes'), { kind: 'array' }); + const codesArr = await open(dataNode.resolve("codes"), { kind: "array" }); const { data: categories } = await get(categoriesArr); const { data } = await get(codesArr, s); result = { data, categories }; } else { - throw new Error('Unsupported encoding-type'); + throw new Error("Unsupported encoding-type"); } return result; @@ -33,12 +30,12 @@ export const fetchDataFromZarr = async (url, path, s) => { } }; -export const getVarNames = async (url, namesCol = '_index') => { +export const getVarNames = async (url, namesCol = "_index") => { try { const store = new FetchStore(url); - const node = await open(store, { kind: 'group' }); + const node = await open(store, { kind: "group" }); - const arr = await open(node.resolve(`var/${namesCol}`, { kind: 'array' })); + const arr = await open(node.resolve(`var/${namesCol}`, { kind: "array" })); const varNames = (await get(arr)).data; return varNames; } catch (error) { @@ -50,22 +47,20 @@ export const getVarNames = async (url, namesCol = '_index') => { export const getObs = async (url) => { try { const store = new FetchStore(url); - const node = await open(store, { kind: 'group' }); + const node = await open(store, { kind: "group" }); - const cols = (await open(node.resolve('obs', { kind: 'group' }))).attrs?.[ - 'column-order' - ]; + const cols = (await open(node.resolve("obs", { kind: "group" }))).attrs?.["column-order"]; const obs = { categorical: [], numerical: [] }; for (const col of cols) { const dataNode = await open(node.resolve(`obs/${col}`)); - const { 'encoding-type': encodingType } = dataNode.attrs || {}; - if (encodingType === 'categorical') { - const categoriesArr = await open(dataNode.resolve('categories'), { - kind: 'array', + const { "encoding-type": encodingType } = dataNode.attrs || {}; + if (encodingType === "categorical") { + const categoriesArr = await open(dataNode.resolve("categories"), { + kind: "array", }); const { data: categories } = await get(categoriesArr); obs.categorical.push({ name: col, categories }); - } else if (encodingType === 'array') { + } else if (encodingType === "array") { obs.numerical.push({ name: col }); } } @@ -76,12 +71,12 @@ export const getObs = async (url) => { } }; -export const getVarIndex = async (url, varId, namesCol = '_index') => { +export const getVarIndex = async (url, varId, namesCol = "_index") => { try { const store = new FetchStore(url); - const node = await open(store, { kind: 'group' }); + const node = await open(store, { kind: "group" }); - const arr = await open(node.resolve(`var/${namesCol}`, { kind: 'array' })); + const arr = await open(node.resolve(`var/${namesCol}`, { kind: "array" })); const varNames = (await get(arr)).data; const varIndex = varNames.findIndex((name) => name === varId); return varIndex; @@ -94,11 +89,11 @@ export const getZarrPath = async (url, matrixProps) => { const { feature, obs } = matrixProps; if (feature) { if (feature.index !== undefined && feature.index !== null) { - return { url, path: 'X', s: [null, feature.index] }; + return { url, path: "X", s: [null, feature.index] }; } else if (feature.name) { return { url, - path: 'X', + path: "X", s: [null, await getVarIndex(url, feature.name, feature.namesCol)], }; } @@ -112,13 +107,13 @@ export const getZarrPath = async (url, matrixProps) => { }; } - throw new Error('No feature or obs in matrixProps'); + throw new Error("No feature or obs in matrixProps"); }; const parseHexColor = (color) => { - const r = parseInt(color?.substring(1, 3), 16); - const g = parseInt(color?.substring(3, 5), 16); - const b = parseInt(color?.substring(5, 7), 16); + const r = Number.parseInt(color?.substring(1, 3), 16); + const g = Number.parseInt(color?.substring(3, 5), 16); + const b = Number.parseInt(color?.substring(5, 7), 16); return [r, g, b]; }; diff --git a/anndata-zarr/vite.config.js b/anndata-zarr/vite.config.js index 9dc91aff..f5eec469 100644 --- a/anndata-zarr/vite.config.js +++ b/anndata-zarr/vite.config.js @@ -1,7 +1,7 @@ -import path from 'path'; +import path from "path"; -import react from '@vitejs/plugin-react'; -import { defineConfig } from 'vite'; +import react from "@vitejs/plugin-react"; +import { defineConfig } from "vite"; // https://vite.dev/config/ export default defineConfig({ @@ -9,24 +9,17 @@ export default defineConfig({ build: { // outDir: path.resolve(__dirname, '../dist'), lib: { - entry: path.resolve(__dirname, 'src/index.js'), - name: 'BiongffAnndataZarr', - formats: ['es', 'cjs'], + entry: path.resolve(__dirname, "src/index.js"), + name: "BiongffAnndataZarr", + formats: ["es", "cjs"], fileName: (format) => `biongff-anndata-zarr.${format}.js`, }, rollupOptions: { - external: [ - 'react', - 'react-dom', - '@mui/material', - '@mui/icons-material', - '@emotion/react', - '@emotion/styled', - ], + external: ["react", "react-dom", "@mui/material", "@mui/icons-material", "@emotion/react", "@emotion/styled"], output: { globals: { - react: 'React', - 'react-dom': 'ReactDOM', + react: "React", + "react-dom": "ReactDOM", }, }, }, diff --git a/sites/app/src/App.tsx b/sites/app/src/App.tsx index 99aea353..1d752c30 100644 --- a/sites/app/src/App.tsx +++ b/sites/app/src/App.tsx @@ -1,17 +1,16 @@ -import { type ViewState, type labelColor, Vizarr } from "@biongff/vizarr"; +import { type ViewState, Vizarr, type labelColor } from "@biongff/vizarr"; -//@ts-ignore +//@ts-ignore //No types provided by anndata-zarr plugin -import { AnndataProvider, AnndataController } from "@biongff/anndata-zarr" +import { AnndataController, AnndataProvider } from "@biongff/anndata-zarr"; +import CssBaseline from "@mui/material/CssBaseline"; +import { ThemeProvider, createTheme } from "@mui/material/styles"; import debounce from "just-debounce-it"; import * as React from "react"; -import { ThemeProvider, createTheme } from '@mui/material/styles' -import CssBaseline from '@mui/material/CssBaseline' - const darkTheme = createTheme({ palette: { - mode: 'dark', + mode: "dark", }, typography: { fontSize: 12, @@ -42,14 +41,10 @@ export default function App() { return { sources: searchParams.getAll("source"), viewState: parseViewStateFromUrl(), - anndatas: searchParams - .getAll('anndata') - .map((v) => (v ? { url: v } : null)), + anndatas: searchParams.getAll("anndata").map((v) => (v ? { url: v } : null)), }; }, [urlString]); - - const [colors, setColors] = React.useState((): labelColor[][] => Array(sources.length).fill([])); // Debounced viewState change handler const handleViewStateChange = React.useMemo( @@ -76,11 +71,7 @@ export default function App() { return sources.map((_s, i) => { if (!anndatas?.[i]?.url) return null; return ( - selectCallback(colorData, i)} - /> + selectCallback(colorData, i)} /> ); }); }, [anndatas, sources]); @@ -89,7 +80,12 @@ export default function App() {
{anndataControllers}
- +
); diff --git a/sites/app/src/main.tsx b/sites/app/src/main.tsx index df8831ae..c4efe3c7 100644 --- a/sites/app/src/main.tsx +++ b/sites/app/src/main.tsx @@ -2,7 +2,7 @@ import { version } from "@biongff/vizarr"; import React, { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import App from "./App"; -import './index.css' +import "./index.css"; console.log(`vizarr v${version}: https://github.com/BioNGFF/vizarr`); diff --git a/sites/app/vite.config.js b/sites/app/vite.config.js index 6b88a7d9..537a9fcf 100644 --- a/sites/app/vite.config.js +++ b/sites/app/vite.config.js @@ -9,9 +9,9 @@ export default defineConfig(({ mode }) => ({ alias: { ...(mode === "development" ? { - "@biongff/vizarr": path.resolve(__dirname, "../../viewer/src/index.tsx"), - "@biongff/anndata-zarr": path.resolve(__dirname, "../../anndata-zarr/src/index.js") - } + "@biongff/vizarr": path.resolve(__dirname, "../../viewer/src/index.tsx"), + "@biongff/anndata-zarr": path.resolve(__dirname, "../../anndata-zarr/src/index.js"), + } : {}), }, }, diff --git a/viewer/src/api.tsx b/viewer/src/api.tsx index 5afa231e..a44c9497 100644 --- a/viewer/src/api.tsx +++ b/viewer/src/api.tsx @@ -28,11 +28,10 @@ type Events = { export type { ViewState, ImageLayerConfig }; export type labelColor = { - labelValue: number, - rgba: [r: number, g: number, b: number, a: number], - value?: string | number | null -} - + labelValue: number; + rgba: [r: number, g: number, b: number, a: number]; + value?: string | number | null; +}; export interface VizarrViewer { addImage(config: ImageLayerConfig): void; diff --git a/viewer/src/components/VizarrViewer.tsx b/viewer/src/components/VizarrViewer.tsx index ac4dd948..04ecdfcf 100644 --- a/viewer/src/components/VizarrViewer.tsx +++ b/viewer/src/components/VizarrViewer.tsx @@ -5,7 +5,8 @@ import { type PrimitiveAtom, Provider, atom, useAtomValue, useSetAtom } from "jo import React, { useId } from "react"; import { getSourceDataError, sourceDataValid, writeUserErrorMessage } from "../error"; import { ViewStateContext } from "../hooks"; -import { loadSources } from "../io" +import { loadSources } from "../io"; +import type { OmeColor } from "../layers/label-layer"; import { type ImageLayerConfig, type ViewState, @@ -19,7 +20,6 @@ import theme from "../theme"; import Menu from "./Menu"; import { InfoSnackbar } from "./Snackbar"; import Viewer from "./Viewer"; -import type { OmeColor } from "../layers/label-layer"; export interface VizarrViewerProps { sources?: string[]; @@ -28,7 +28,12 @@ export interface VizarrViewerProps { labelColours?: OmeColor[][]; } -function VizarrViewerComponent({ sources = [], viewState: initialViewState, onViewStateChange, labelColours }: VizarrViewerProps) { +function VizarrViewerComponent({ + sources = [], + viewState: initialViewState, + onViewStateChange, + labelColours, +}: VizarrViewerProps) { const setSourceInfo = useSetAtom(sourceInfoAtom); const setViewStateAtom = useSetAtom(viewStateAtom); const sourceError = useAtomValue(sourceErrorAtom); @@ -62,19 +67,16 @@ function VizarrViewerComponent({ sources = [], viewState: initialViewState, onVi let sourceDatas = []; for (const res of results) { if (res.status === "fulfilled") { - sourceDatas.push(res.value); } else { console.error(res.reason); } } const sourceData = sourceDatas.filter((s) => s !== null); - setSourceInfo(sourceData) - } - ) + setSourceInfo(sourceData); + }); }, [sources, labelColours, setSourceInfo]); - return ( <> {redirectObj === null && ( diff --git a/viewer/src/io.ts b/viewer/src/io.ts index ddec3c36..c61efafa 100644 --- a/viewer/src/io.ts +++ b/viewer/src/io.ts @@ -283,18 +283,17 @@ export async function loadSources(sources: string[], labelColors?: OmeColor[][]) sourceData.name = `image_${index}`; } if (labelColors && labelColors[index].length) { - if (!sourceData.labels || (!sourceData.labels.length)) { - throw new utils.AssertionError('Feature colours provided but source image has no label.') + if (!sourceData.labels || !sourceData.labels.length) { + throw new utils.AssertionError("Feature colours provided but source image has no label."); } else { - //Really not the best way to do this but the layer state is heavily wrapped up in + //Really not the best way to do this but the layer state is heavily wrapped up in //being derived directly from the sourceData and would require a fairly large refactor to find - sourceData.labels[0].colors = labelColors[index] - sourceData.labels[0].on = true + sourceData.labels[0].colors = labelColors[index]; + sourceData.labels[0].on = true; } } return { id, ...sourceData }; }), ); - return results - + return results; } diff --git a/viewer/src/state.ts b/viewer/src/state.ts index 3b70d3f1..8589b65c 100644 --- a/viewer/src/state.ts +++ b/viewer/src/state.ts @@ -62,7 +62,7 @@ export type ImageLabels = Array<{ loader: ZarrPixelSource[]; modelMatrix: Matrix4; colors?: ReadonlyArray; - on?: boolean + on?: boolean; }>; export type SourceData = { @@ -187,10 +187,10 @@ const imageLabelsIstanceFamily = atomFamily((a: Atom) => return labels.map((label) => label.on ? new LabelLayer({ - ...label.layerProps, - selection: label.transformSourceSelection(layerProps.selections[0]), - pickable: true, - }) + ...label.layerProps, + selection: label.transformSourceSelection(layerProps.selections[0]), + pickable: true, + }) : null, ); }), diff --git a/viewer/tests/features.test.js b/viewer/tests/features.test.js index a70f700d..44667330 100644 --- a/viewer/tests/features.test.js +++ b/viewer/tests/features.test.js @@ -1,42 +1,37 @@ +import { AssertionError } from "node:assert"; +import { expect, test } from "vitest"; import { loadSources } from "../src/io"; -import { test, expect } from "vitest"; import { range } from "../src/utils"; -import { AssertionError } from "node:assert"; -const labelImageURL = 'https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.5/idr0062A/6001240_labels.zarr' -const imageURL = 'https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.5/idr0066/ExpD_chicken_embryo_MIP.ome.zarr' -const labelIds = range(61) +const labelImageURL = "https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.5/idr0062A/6001240_labels.zarr"; +const imageURL = "https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.5/idr0066/ExpD_chicken_embryo_MIP.ome.zarr"; +const labelIds = range(61); function generateLabelColors(labelIds) { return labelIds.map((id) => { - return ( - { - labelValue: id + 1, - rgba: [Math.floor(Math.random() * 250), Math.floor(Math.random() * 250), Math.floor(Math.random() * 250), Math.floor(Math.random() * 250)], - value: Math.random() - } - ) - }) + return { + labelValue: id + 1, + rgba: [ + Math.floor(Math.random() * 250), + Math.floor(Math.random() * 250), + Math.floor(Math.random() * 250), + Math.floor(Math.random() * 250), + ], + value: Math.random(), + }; + }); } -test('Can create source data with externally-defined label colours', async () => { - const labelColours = generateLabelColors(labelIds) - const sources = await loadSources( - [labelImageURL], - [labelColours] - ) - console.log(labelColours[0]) - console.log(sources[0].value.labels[0].colors[0]) - expect(sources[0].value.labels[0].colors).toBe(labelColours) -}) +test("Can create source data with externally-defined label colours", async () => { + const labelColours = generateLabelColors(labelIds); + const sources = await loadSources([labelImageURL], [labelColours]); + expect(sources[0].value.labels[0].colors).toBe(labelColours); +}); -test('Attempting to add externally-defined label colours to image without label leads to an error', async () => { - const labelColours = generateLabelColors(labelIds) - const sources = await loadSources( - [imageURL], - [labelColours] - ) - expect(sources[0].status).toBe('rejected') +test("Attempting to add externally-defined label colours to image without label leads to an error", async () => { + const labelColours = generateLabelColors(labelIds); + const sources = await loadSources([imageURL], [labelColours]); + expect(sources[0].status).toBe("rejected"); //Requires AssertionError to provide correct error message to user - expect(sources[0].reason.name).toBe('AssertionError') -}) + expect(sources[0].reason.name).toBe("AssertionError"); +}); From 94607727352f8fb99969dcccc2d17446aa53c60d Mon Sep 17 00:00:00 2001 From: dannda Date: Thu, 23 Apr 2026 17:14:44 +0100 Subject: [PATCH 06/26] fix: anndata-zarr build and css --- anndata-zarr/src/components/Legend.jsx | 3 +-- package.json | 3 ++- sites/app/src/App.tsx | 12 +++++++++--- sites/app/vite.config.js | 1 + 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/anndata-zarr/src/components/Legend.jsx b/anndata-zarr/src/components/Legend.jsx index a83f1d3e..0320e54a 100644 --- a/anndata-zarr/src/components/Legend.jsx +++ b/anndata-zarr/src/components/Legend.jsx @@ -3,13 +3,12 @@ import React, { useMemo } from "react"; import _ from "lodash"; import { getColor } from "../utils"; -import "../index.css"; export const Legend = ({ min, max, colorscale }) => { const spanList = useMemo(() => { return _.range(100).map((i) => { const color = getColor({ value: i / 100, colorscale }); - return ; + return ; }); }, [colorscale]); diff --git a/package.json b/package.json index ad8821c4..7cd66d39 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "check": "pnpm build:viewer && pnpm -r run check", "build:viewer": "pnpm --filter vizarr build", "build:app": "pnpm --filter app build", - "build": "pnpm build:viewer && pnpm build:app", + "build:anndata-zarr": "pnpm --filter anndata-zarr build", + "build": "pnpm build:viewer && pnpm build:anndata-zarr && pnpm build:app", "test": "vitest" }, "devDependencies": { diff --git a/sites/app/src/App.tsx b/sites/app/src/App.tsx index 1d752c30..b2d0b3e7 100644 --- a/sites/app/src/App.tsx +++ b/sites/app/src/App.tsx @@ -8,6 +8,8 @@ import { ThemeProvider, createTheme } from "@mui/material/styles"; import debounce from "just-debounce-it"; import * as React from "react"; +import "@biongff/anndata-zarr/dist/anndata-zarr.css"; + const darkTheme = createTheme({ palette: { mode: "dark", @@ -46,6 +48,7 @@ export default function App() { }, [urlString]); const [colors, setColors] = React.useState((): labelColor[][] => Array(sources.length).fill([])); + // Debounced viewState change handler const handleViewStateChange = React.useMemo( () => @@ -62,11 +65,13 @@ export default function App() { }, 200), [], ); - const selectCallback = (colorData: any, i: any) => { + + const selectCallback = React.useCallback((colorData: any, i: any) => { setColors((prev) => { return prev.map((c, ci) => (ci === i ? colorData : c)); }); - }; + }, []); + const anndataControllers = React.useMemo(() => { return sources.map((_s, i) => { if (!anndatas?.[i]?.url) return null; @@ -74,7 +79,8 @@ export default function App() { selectCallback(colorData, i)} /> ); }); - }, [anndatas, sources]); + }, [anndatas, sources, selectCallback]); + return ( diff --git a/sites/app/vite.config.js b/sites/app/vite.config.js index 537a9fcf..f7e900f9 100644 --- a/sites/app/vite.config.js +++ b/sites/app/vite.config.js @@ -10,6 +10,7 @@ export default defineConfig(({ mode }) => ({ ...(mode === "development" ? { "@biongff/vizarr": path.resolve(__dirname, "../../viewer/src/index.tsx"), + "@biongff/anndata-zarr/dist/anndata-zarr.css": path.resolve(__dirname, "../../anndata-zarr/src/index.css"), "@biongff/anndata-zarr": path.resolve(__dirname, "../../anndata-zarr/src/index.js"), } : {}), From 0643b7f080296a10ba8b8a7e03e2a06019214a93 Mon Sep 17 00:00:00 2001 From: dannda Date: Fri, 24 Apr 2026 11:48:23 +0100 Subject: [PATCH 07/26] fix: import css lint --- anndata-zarr/src/components/ObsSelect.jsx | 2 +- anndata-zarr/src/index.js | 2 ++ anndata-zarr/src/utils.js | 12 ++++++++---- anndata-zarr/vite.config.js | 2 +- sites/app/src/App.tsx | 8 ++++++-- viewer/src/components/VizarrViewer.tsx | 2 +- viewer/src/io.ts | 11 +++++------ 7 files changed, 24 insertions(+), 15 deletions(-) diff --git a/anndata-zarr/src/components/ObsSelect.jsx b/anndata-zarr/src/components/ObsSelect.jsx index f7b28012..747f3862 100644 --- a/anndata-zarr/src/components/ObsSelect.jsx +++ b/anndata-zarr/src/components/ObsSelect.jsx @@ -54,7 +54,7 @@ const CategoricalCol = ({ col, showColor = false }) => { height: 10, bgcolor: `rgba(${getColor({ value: i / (categories.length - 1), colorscale: COLORSCALES.Accent })})`, }} - >
+ /> )} diff --git a/anndata-zarr/src/index.js b/anndata-zarr/src/index.js index 1a061206..3e49b763 100644 --- a/anndata-zarr/src/index.js +++ b/anndata-zarr/src/index.js @@ -1,3 +1,5 @@ +import "./index.css"; + export { useAnndataColors } from "./hooks"; export { AnndataProvider } from "./provider"; export { COLORSCALES } from "./constants/colorscales"; diff --git a/anndata-zarr/src/utils.js b/anndata-zarr/src/utils.js index 881c32ba..777cddde 100644 --- a/anndata-zarr/src/utils.js +++ b/anndata-zarr/src/utils.js @@ -26,6 +26,7 @@ export const fetchDataFromZarr = async (url, path, s) => { return result; } catch (error) { + // biome-ignore lint/complexity/noUselessCatch: @TODO: better error handling throw error; } }; @@ -90,7 +91,8 @@ export const getZarrPath = async (url, matrixProps) => { if (feature) { if (feature.index !== undefined && feature.index !== null) { return { url, path: "X", s: [null, feature.index] }; - } else if (feature.name) { + } + if (feature.name) { return { url, path: "X", @@ -130,11 +132,13 @@ const interpolateColor = (color1, color2, factor) => { }; const computeColor = (colormap, value) => { - if (!colormap || isNaN(value)) { + if (!colormap || Number.isNaN(value)) { return [0, 0, 0, 255]; - } else if (value <= 0) { + } + if (value <= 0) { return parseHexColor(colormap[0]); - } else if (value >= 1) { + } + if (value >= 1) { return parseHexColor(colormap[colormap.length - 1]); } const index1 = Math.floor(value * (colormap.length - 1)); diff --git a/anndata-zarr/vite.config.js b/anndata-zarr/vite.config.js index f5eec469..deb993fe 100644 --- a/anndata-zarr/vite.config.js +++ b/anndata-zarr/vite.config.js @@ -1,4 +1,4 @@ -import path from "path"; +import path from "node:path"; import react from "@vitejs/plugin-react"; import { defineConfig } from "vite"; diff --git a/sites/app/src/App.tsx b/sites/app/src/App.tsx index b2d0b3e7..43cdbfe9 100644 --- a/sites/app/src/App.tsx +++ b/sites/app/src/App.tsx @@ -66,7 +66,7 @@ export default function App() { [], ); - const selectCallback = React.useCallback((colorData: any, i: any) => { + const selectCallback = React.useCallback((colorData: labelColor[], i: number) => { setColors((prev) => { return prev.map((c, ci) => (ci === i ? colorData : c)); }); @@ -76,7 +76,11 @@ export default function App() { return sources.map((_s, i) => { if (!anndatas?.[i]?.url) return null; return ( - selectCallback(colorData, i)} /> + selectCallback(colorData, i)} + /> ); }); }, [anndatas, sources, selectCallback]); diff --git a/viewer/src/components/VizarrViewer.tsx b/viewer/src/components/VizarrViewer.tsx index 04ecdfcf..ef5c56e2 100644 --- a/viewer/src/components/VizarrViewer.tsx +++ b/viewer/src/components/VizarrViewer.tsx @@ -75,7 +75,7 @@ function VizarrViewerComponent({ const sourceData = sourceDatas.filter((s) => s !== null); setSourceInfo(sourceData); }); - }, [sources, labelColours, setSourceInfo]); + }, [sources, labelColours, setSourceInfo, setSourceError]); return ( <> diff --git a/viewer/src/io.ts b/viewer/src/io.ts index c61efafa..63b63533 100644 --- a/viewer/src/io.ts +++ b/viewer/src/io.ts @@ -282,15 +282,14 @@ export async function loadSources(sources: string[], labelColors?: OmeColor[][]) if (!sourceData.name) { sourceData.name = `image_${index}`; } - if (labelColors && labelColors[index].length) { + if (labelColors?.[index].length) { if (!sourceData.labels || !sourceData.labels.length) { throw new utils.AssertionError("Feature colours provided but source image has no label."); - } else { - //Really not the best way to do this but the layer state is heavily wrapped up in - //being derived directly from the sourceData and would require a fairly large refactor to find - sourceData.labels[0].colors = labelColors[index]; - sourceData.labels[0].on = true; } + //Really not the best way to do this but the layer state is heavily wrapped up in + //being derived directly from the sourceData and would require a fairly large refactor to find + sourceData.labels[0].colors = labelColors[index]; + sourceData.labels[0].on = true; } return { id, ...sourceData }; }), From bbb2082a2a1e55d77ca8f17c77674e5ba4b68e7a Mon Sep 17 00:00:00 2001 From: dannda Date: Thu, 30 Apr 2026 16:24:10 +0100 Subject: [PATCH 08/26] fix: anndata-zarr boolean arrays handle bool arrays as categorical --- anndata-zarr/src/utils.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/anndata-zarr/src/utils.js b/anndata-zarr/src/utils.js index 777cddde..3e206c43 100644 --- a/anndata-zarr/src/utils.js +++ b/anndata-zarr/src/utils.js @@ -10,7 +10,13 @@ export const fetchDataFromZarr = async (url, path, s) => { const dataNode = await open(node.resolve(path)); let result; - if (dataNode.attrs?.["encoding-type"] === "array" || dataNode.attrs?.["encoding-type"] === "string-array") { + if (dataNode.attrs?.["encoding-type"] === "array" && dataNode.dtype === "bool") { + const boolData = await get(dataNode, s); + result = { + data: Array.from(boolData.data), + categories: ["false", "true"], + }; + } else if (dataNode.attrs?.["encoding-type"] === "array" || dataNode.attrs?.["encoding-type"] === "string-array") { result = await get(dataNode, s); } else if (dataNode.attrs?.["encoding-type"] === "categorical") { const categoriesArr = await open(dataNode.resolve("categories"), { @@ -62,7 +68,11 @@ export const getObs = async (url) => { const { data: categories } = await get(categoriesArr); obs.categorical.push({ name: col, categories }); } else if (encodingType === "array") { - obs.numerical.push({ name: col }); + if (dataNode.dtype === "bool") { + obs.categorical.push({ name: col, categories: ["false", "true"] }); + } else { + obs.numerical.push({ name: col }); + } } } return obs; @@ -155,6 +165,6 @@ export const getColors = ({ data, max, min, colorProps, categories }) => { return _.map(data, (v, i) => ({ labelValue: i + 1, rgba: getColor({ value: (v - min) / (max - min), ...colorProps }), - value: categories ? categories[v] : v, + value: categories ? (categories[v] ?? v) : v, })); }; From 6ab5b3fccef56c1f728c87daf9615a31157b19ae Mon Sep 17 00:00:00 2001 From: dannda Date: Fri, 1 May 2026 11:36:34 +0100 Subject: [PATCH 09/26] fix: warning length displayed on screen --- viewer/src/components/VizarrViewer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/viewer/src/components/VizarrViewer.tsx b/viewer/src/components/VizarrViewer.tsx index ef5c56e2..7631fbc7 100644 --- a/viewer/src/components/VizarrViewer.tsx +++ b/viewer/src/components/VizarrViewer.tsx @@ -109,7 +109,7 @@ function VizarrViewerComponent({

)} - {sourceWarning.length && + {!!sourceWarning.length && sourceWarning.map((warning, index) => { return ; })} From 444ec2ee3f4e92e98f364e4d913ce8a757b53481 Mon Sep 17 00:00:00 2001 From: Luca Anceschi Date: Wed, 29 Apr 2026 14:16:02 +0200 Subject: [PATCH 10/26] feat!: anndata plugin support for csv, json, parquet table backends --- anndata-zarr/package.json | 13 +- anndata-zarr/src/hooks.js | 97 +++++++++--- anndata-zarr/src/table-loader.js | 248 +++++++++++++++++++++++++++++++ pnpm-lock.yaml | 8 + 4 files changed, 338 insertions(+), 28 deletions(-) create mode 100644 anndata-zarr/src/table-loader.js diff --git a/anndata-zarr/package.json b/anndata-zarr/package.json index bdd7650b..76e01e7d 100644 --- a/anndata-zarr/package.json +++ b/anndata-zarr/package.json @@ -5,7 +5,9 @@ "type": "module", "main": "dist/biongff-anndata-zarr.cjs.js", "module": "dist/biongff-anndata-zarr.es.js", - "files": ["dist"], + "files": [ + "dist" + ], "exports": { ".": { "import": "./dist/biongff-anndata-zarr.es.js", @@ -23,17 +25,18 @@ }, "dependencies": { "@tanstack/react-query": "^5.85.3", + "hyparquet": "^1.25.6", "lodash": "^4.17.21", "react-window": "^2.0.2", "zarrita": "0.5.0" }, "peerDependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0", + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", "@mui/icons-material": "^7.2.0", "@mui/material": "^7.2.0", - "@emotion/react": "^11.14.0", - "@emotion/styled": "^11.14.1" + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "devDependencies": { "@vitejs/plugin-react": "^4.3.3", diff --git a/anndata-zarr/src/hooks.js b/anndata-zarr/src/hooks.js index 73f9b702..4f84fd64 100644 --- a/anndata-zarr/src/hooks.js +++ b/anndata-zarr/src/hooks.js @@ -5,27 +5,43 @@ import _ from "lodash"; import { COLORSCALES } from "./constants/colorscales"; import { fetchDataFromZarr, getColors, getObs, getVarNames, getZarrPath } from "./utils"; +import { + getTableData, + getFeatureNamesFromTable, + getObsFromTable, + getFeatureDataFromTable, + getColumnDataFromTable, +} from "./table-loader"; -const getAnndataColors = async (url, matrixProps, colorProps) => { - let zarrData; - try { - const zarrPath = await getZarrPath(url, matrixProps); - zarrData = await fetchDataFromZarr(zarrPath.url, zarrPath.path, zarrPath.s); - } catch (error) { - console.error(error); - return null; +// --------------------------------------------------------------------------- +// Backend-aware data fetching functions +// --------------------------------------------------------------------------- + +async function getFeatureNames(url, namesCol) { + const { meta, data } = await getTableData(url); + if (meta.backend === "anndata") { + return getVarNames(url, namesCol); } - if (!zarrData) return null; + return getFeatureNamesFromTable(data, meta.indexKey, meta); +} - const { categories } = zarrData; +async function getObsColumns(url) { + const { meta, data } = await getTableData(url); + if (meta.backend === "anndata") { + return getObs(url); + } + return getObsFromTable(data, meta.indexKey, meta); +} - const max = categories ? categories.length - 1 : colorProps?.max || _.max(zarrData.data); - const min = categories ? 0 : colorProps?.min || _.min(zarrData.data); +function computeColorResult(columnData, colorProps) { + if (!columnData) return null; + const { categories } = columnData; + const max = categories ? categories.length - 1 : colorProps?.max || _.max(columnData.data); + const min = categories ? 0 : colorProps?.min || _.min(columnData.data); const colorscale = categories ? COLORSCALES.Accent : colorProps?.colorscale; - return { colors: getColors({ - data: zarrData.data, + data: columnData.data, max, min, colorProps: { ...colorProps, colorscale }, @@ -36,7 +52,42 @@ const getAnndataColors = async (url, matrixProps, colorProps) => { ...(categories ? { categories } : {}), colorscale, }; -}; +} + +async function getColorData(url, matrixProps, colorProps) { + const { meta, data } = await getTableData(url); + + let columnData; + if (meta.backend === "anndata") { + try { + const zarrPath = await getZarrPath(url, matrixProps); + columnData = await fetchDataFromZarr(zarrPath.url, zarrPath.path, zarrPath.s); + } catch (error) { + console.error(error); + return null; + } + } else { + const { feature, obs } = matrixProps || {}; + try { + if (feature?.index !== undefined && feature?.index !== null) { + columnData = getFeatureDataFromTable(data, feature.index, meta.indexKey, meta); + } else if (feature?.name) { + columnData = getColumnDataFromTable(data, feature.name); + } else if (obs?.col) { + columnData = getColumnDataFromTable(data, obs.col); + } + } catch (error) { + console.error(error); + return null; + } + } + + return computeColorResult(columnData, colorProps); +} + +// --------------------------------------------------------------------------- +// Hooks +// --------------------------------------------------------------------------- export const useAnndataColors = (adata = { url: null }, opts = {}) => { const { @@ -44,8 +95,8 @@ export const useAnndataColors = (adata = { url: null }, opts = {}) => { isLoading = false, serverError = null, } = useQuery({ - queryKey: ["anndataColor", adata.url, adata.matrixProps, adata.colorProps], - queryFn: () => getAnndataColors(adata.url, adata.matrixProps, adata.colorProps), + queryKey: ["tableColor", adata.url, adata.matrixProps, adata.colorProps], + queryFn: () => getColorData(adata.url, adata.matrixProps, adata.colorProps), ...opts, }); @@ -67,8 +118,8 @@ export const useAnndatasColors = (adatas = [], opts = {}) => { serverError = null, } = useQueries({ queries: adatas.map(({ url, matrixProps, colorProps }) => ({ - queryKey: ["anndataColor", url, matrixProps, colorProps], - queryFn: () => getAnndataColors(url, matrixProps, colorProps), + queryKey: ["tableColor", url, matrixProps, colorProps], + queryFn: () => getColorData(url, matrixProps, colorProps), })), ...opts, combine, @@ -83,8 +134,8 @@ export const useAnndataFeatures = (adata = { url: null, namesCol: null }) => { isLoading = false, serverError = null, } = useQuery({ - queryKey: ["anndataFeatures", adata.url, adata.namesCol], - queryFn: () => getVarNames(adata.url, adata.namesCol), + queryKey: ["tableFeatures", adata.url, adata.namesCol], + queryFn: () => getFeatureNames(adata.url, adata.namesCol), }); return { data, isLoading, serverError }; @@ -96,8 +147,8 @@ export const useAnndataObs = (adata = { url: null }) => { isLoading = false, serverError = null, } = useQuery({ - queryKey: ["anndataObs", adata.url], - queryFn: () => getObs(adata.url), + queryKey: ["tableObs", adata.url], + queryFn: () => getObsColumns(adata.url), }); return { data, isLoading, serverError }; diff --git a/anndata-zarr/src/table-loader.js b/anndata-zarr/src/table-loader.js new file mode 100644 index 00000000..819b00d9 --- /dev/null +++ b/anndata-zarr/src/table-loader.js @@ -0,0 +1,248 @@ +/** + * Table loader for non-anndata backends (CSV, JSON, Parquet). + * Detects backend type from .zattrs and normalizes data into + * a column-oriented format compatible with the anndata-zarr hooks. + */ + +// Promise-based caches to deduplicate concurrent requests +const _metaPromises = new Map(); +const _tablePromises = new Map(); + +/** + * Detect table backend and metadata from .zattrs. + * Result is cached per URL. + */ +export function getTableMeta(url) { + if (!_metaPromises.has(url)) { + _metaPromises.set(url, _fetchTableMeta(url)); + } + return _metaPromises.get(url); +} + +async function _fetchTableMeta(url) { + const res = await fetch(`${url}/.zattrs`); + if (!res.ok) throw new Error(`Failed to load table metadata from ${url}`); + const attrs = await res.json(); + const backend = attrs.backend || (attrs["encoding-type"] === "anndata" ? "anndata" : "unknown"); + if (backend === "unknown") { + console.warn(`[anndata-zarr] Unrecognized table backend at ${url}. Expected one of: anndata, csv, json, parquet.`); + } else { + console.log(`[anndata-zarr] Detected table backend: ${backend} (${url})`); + } + return { + backend, + indexKey: attrs.index_key || attrs.instance_key || null, + categoricalColumns: attrs.categorical_columns || [], + measurementColumns: attrs.measurement_columns || [], + metadataColumns: attrs.metadata_columns || [], + }; +} + +/** + * Load and cache table metadata + data. + * For anndata backend, returns { meta, data: null }. + * For flat backends, returns { meta, data: { col: values[] } }. + */ +export function getTableData(url) { + if (!_tablePromises.has(url)) { + _tablePromises.set(url, _fetchTableData(url)); + } + return _tablePromises.get(url); +} + +async function _fetchTableData(url) { + let meta; + try { + meta = await getTableMeta(url); + } catch (error) { + console.error(`[anndata-zarr] Failed to load table metadata from ${url}:`, error); + throw error; + } + if (meta.backend === "anndata") { + return { meta, data: null }; + } + try { + const data = await _loadFlatTable(url, meta.backend); + return { meta, data }; + } catch (error) { + console.error(`[anndata-zarr] Failed to load ${meta.backend} table from ${url}:`, error); + throw error; + } +} + +// --------------------------------------------------------------------------- +// CSV parser +// --------------------------------------------------------------------------- + +function _parseCsvLine(line) { + const values = []; + let current = ""; + let inQuotes = false; + + for (let i = 0; i < line.length; i++) { + const char = line[i]; + if (inQuotes) { + if (char === '"') { + if (i + 1 < line.length && line[i + 1] === '"') { + current += '"'; + i++; + } else { + inQuotes = false; + } + } else { + current += char; + } + } else if (char === '"') { + inQuotes = true; + } else if (char === ",") { + values.push(current); + current = ""; + } else { + current += char; + } + } + values.push(current); + return values; +} + +function _parseCsv(text) { + const lines = text.trim().split("\n"); + if (lines.length === 0) return {}; + + const headers = _parseCsvLine(lines[0]); + const columns = {}; + for (const h of headers) columns[h] = []; + + for (let i = 1; i < lines.length; i++) { + if (!lines[i].trim()) continue; + const values = _parseCsvLine(lines[i]); + for (let j = 0; j < headers.length; j++) { + columns[headers[j]].push(values[j]); + } + } + + // Auto-detect and convert numeric columns + for (const key of Object.keys(columns)) { + const col = columns[key]; + if (col.length > 0 && col.every((v) => v !== "" && !Number.isNaN(Number(v)))) { + columns[key] = col.map(Number); + } + } + + return columns; +} + +// --------------------------------------------------------------------------- +// Backend-specific loaders +// --------------------------------------------------------------------------- + +async function _loadFlatTable(url, backend) { + switch (backend) { + case "csv": { + const res = await fetch(`${url}/table.csv`); + if (!res.ok) throw new Error(`Failed to load CSV from ${url}/table.csv`); + return _parseCsv(await res.text()); + } + case "json": { + const res = await fetch(`${url}/table/.zattrs`); + if (!res.ok) throw new Error(`Failed to load JSON from ${url}/table/.zattrs`); + return await res.json(); + } + case "parquet": { + const { parquetMetadata, parquetRead } = await import("hyparquet"); + const res = await fetch(`${url}/table.parquet`); + if (!res.ok) throw new Error(`Failed to load parquet from ${url}/table.parquet`); + const buffer = await res.arrayBuffer(); + + const metadata = parquetMetadata(buffer); + const columnNames = metadata.schema.slice(1).map((s) => s.name); + const columns = {}; + for (const name of columnNames) columns[name] = []; + + await parquetRead({ + file: buffer, + metadata, + onComplete: (rows) => { + for (const row of rows) { + for (let i = 0; i < columnNames.length; i++) { + columns[columnNames[i]].push(row[i]); + } + } + }, + }); + + return columns; + } + default: + console.error(`[anndata-zarr] Unsupported table backend: "${backend}". Supported: csv, json, parquet.`); + throw new Error(`Unsupported table backend: ${backend}`); + } +} + +// --------------------------------------------------------------------------- +// Data extraction from flat (column-oriented) tables +// --------------------------------------------------------------------------- + +/** + * Get feature (numeric column) names from flat table data. + * Uses measurement_columns from metadata if available, otherwise infers + * from column data types. + */ +export function getFeatureNamesFromTable(tableData, indexKey, meta = {}) { + if (meta.measurementColumns?.length > 0) { + return meta.measurementColumns.filter((key) => key in tableData); + } + return Object.keys(tableData).filter((key) => { + if (key === indexKey) return false; + const col = tableData[key]; + return col.length > 0 && typeof col[0] === "number"; + }); +} + +/** + * Get observation metadata columns from flat table data. + * Returns { categorical: [{name, categories}], numerical: [] } matching + * the shape returned by getObs() for anndata. + */ +export function getObsFromTable(tableData, indexKey, meta = {}) { + const obs = { categorical: [], numerical: [] }; + for (const [key, values] of Object.entries(tableData)) { + if (key === indexKey) continue; + const isCategorical = + meta.categoricalColumns?.length > 0 + ? meta.categoricalColumns.includes(key) + : values.length > 0 && typeof values[0] === "string"; + if (isCategorical) { + const categories = [...new Set(values)].map(String); + obs.categorical.push({ name: key, categories }); + } + } + return obs; +} + +/** + * Get a single column's data, applying categorical encoding for string columns. + * Returns { data: number[] } or { data: number[], categories: string[] }. + */ +export function getColumnDataFromTable(tableData, colName) { + const values = tableData[colName]; + if (!values) throw new Error(`Column "${colName}" not found in table`); + + if (values.length > 0 && typeof values[0] === "string") { + const categories = [...new Set(values)]; + const categoryMap = new Map(categories.map((c, i) => [c, i])); + return { data: values.map((v) => categoryMap.get(v)), categories }; + } + return { data: values }; +} + +/** + * Get feature data by matrix index from a flat table. + */ +export function getFeatureDataFromTable(tableData, featureIndex, indexKey, meta = {}) { + const featureNames = getFeatureNamesFromTable(tableData, indexKey, meta); + if (featureIndex < 0 || featureIndex >= featureNames.length) { + throw new Error(`Feature index ${featureIndex} out of range (0-${featureNames.length - 1})`); + } + return { data: tableData[featureNames[featureIndex]] }; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cc5ddfd4..9efb559d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -82,6 +82,9 @@ importers: '@tanstack/react-query': specifier: ^5.85.3 version: 5.90.21(react@18.3.1) + hyparquet: + specifier: ^1.25.6 + version: 1.25.6 lodash: specifier: ^4.17.21 version: 4.17.21 @@ -2375,6 +2378,9 @@ packages: resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} engines: {node: '>=18.18.0'} + hyparquet@1.25.6: + resolution: {integrity: sha512-Q9W5IjkVch3ZMnYd4qFv2q8suu5Jc36yt7J+zUNM9grwnP1S189icp0jdEQKM5HJvQkTVy8NMiQ8n/dM5QAt1A==} + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -6269,6 +6275,8 @@ snapshots: human-signals@8.0.1: {} + hyparquet@1.25.6: {} + ieee754@1.2.1: {} image-size@0.7.5: {} From 21a1ab342bca6770e6fa1da82e93717191b67132 Mon Sep 17 00:00:00 2001 From: Luca Anceschi Date: Tue, 5 May 2026 16:34:56 +0200 Subject: [PATCH 11/26] fix: numerical values. handle BigInt values from zarr int64 and parquet columns --- anndata-zarr/src/hooks.js | 11 ++++++++--- anndata-zarr/src/table-loader.js | 17 +++++++++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/anndata-zarr/src/hooks.js b/anndata-zarr/src/hooks.js index 4f84fd64..038f0379 100644 --- a/anndata-zarr/src/hooks.js +++ b/anndata-zarr/src/hooks.js @@ -36,12 +36,17 @@ async function getObsColumns(url) { function computeColorResult(columnData, colorProps) { if (!columnData) return null; const { categories } = columnData; - const max = categories ? categories.length - 1 : colorProps?.max || _.max(columnData.data); - const min = categories ? 0 : colorProps?.min || _.min(columnData.data); + // Convert BigInt data (from int64 zarr arrays or parquet) to Number + let data = columnData.data; + if (data?.length > 0 && typeof data[0] === "bigint") { + data = Array.from(data, Number); + } + const max = categories ? categories.length - 1 : Number(colorProps?.max || _.max(data)); + const min = categories ? 0 : Number(colorProps?.min || _.min(data)); const colorscale = categories ? COLORSCALES.Accent : colorProps?.colorscale; return { colors: getColors({ - data: columnData.data, + data, max, min, colorProps: { ...colorProps, colorscale }, diff --git a/anndata-zarr/src/table-loader.js b/anndata-zarr/src/table-loader.js index 819b00d9..bd28c02c 100644 --- a/anndata-zarr/src/table-loader.js +++ b/anndata-zarr/src/table-loader.js @@ -195,7 +195,7 @@ export function getFeatureNamesFromTable(tableData, indexKey, meta = {}) { return Object.keys(tableData).filter((key) => { if (key === indexKey) return false; const col = tableData[key]; - return col.length > 0 && typeof col[0] === "number"; + return col.length > 0 && (typeof col[0] === "number" || typeof col[0] === "bigint"); }); } @@ -205,9 +205,11 @@ export function getFeatureNamesFromTable(tableData, indexKey, meta = {}) { * the shape returned by getObs() for anndata. */ export function getObsFromTable(tableData, indexKey, meta = {}) { + const featureNames = new Set(getFeatureNamesFromTable(tableData, indexKey, meta)); const obs = { categorical: [], numerical: [] }; for (const [key, values] of Object.entries(tableData)) { if (key === indexKey) continue; + if (featureNames.has(key)) continue; const isCategorical = meta.categoricalColumns?.length > 0 ? meta.categoricalColumns.includes(key) @@ -215,6 +217,8 @@ export function getObsFromTable(tableData, indexKey, meta = {}) { if (isCategorical) { const categories = [...new Set(values)].map(String); obs.categorical.push({ name: key, categories }); + } else if (values.length > 0 && (typeof values[0] === "number" || typeof values[0] === "bigint")) { + obs.numerical.push({ name: key }); } } return obs; @@ -233,6 +237,10 @@ export function getColumnDataFromTable(tableData, colName) { const categoryMap = new Map(categories.map((c, i) => [c, i])); return { data: values.map((v) => categoryMap.get(v)), categories }; } + // Convert BigInt values (e.g. from parquet int64) to Number + if (values.length > 0 && typeof values[0] === "bigint") { + return { data: values.map(Number) }; + } return { data: values }; } @@ -244,5 +252,10 @@ export function getFeatureDataFromTable(tableData, featureIndex, indexKey, meta if (featureIndex < 0 || featureIndex >= featureNames.length) { throw new Error(`Feature index ${featureIndex} out of range (0-${featureNames.length - 1})`); } - return { data: tableData[featureNames[featureIndex]] }; + const values = tableData[featureNames[featureIndex]]; + // Convert BigInt values (e.g. from parquet int64) to Number + if (values.length > 0 && typeof values[0] === "bigint") { + return { data: values.map(Number) }; + } + return { data: values }; } From acb5c3836f3a48151785e6e6f24fdb0f297e97cb Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Wed, 3 Jun 2026 09:54:50 +0100 Subject: [PATCH 12/26] Anndata-zarr plugin working --- pnpm-lock.yaml | 4798 ++++++++++++++++++++++++++--------------- pnpm-workspace.yaml | 2 +- sites/app/src/App.tsx | 95 +- viewer/package.json | 5 +- 4 files changed, 3049 insertions(+), 1851 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 10cac4b7..a9220aaa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,76 +18,76 @@ importers: version: 1.9.4 '@semantic-release/changelog': specifier: ^6.0.3 - version: 6.0.3(semantic-release@25.0.2(typescript@5.8.2)) + version: 6.0.3(semantic-release@25.0.3(typescript@5.9.3)) '@semantic-release/commit-analyzer': specifier: ^13.0.1 - version: 13.0.1(semantic-release@25.0.2(typescript@5.8.2)) + version: 13.0.1(semantic-release@25.0.3(typescript@5.9.3)) '@semantic-release/exec': specifier: ^7.1.0 - version: 7.1.0(semantic-release@25.0.2(typescript@5.8.2)) + version: 7.1.0(semantic-release@25.0.3(typescript@5.9.3)) '@semantic-release/git': specifier: ^10.0.1 - version: 10.0.1(semantic-release@25.0.2(typescript@5.8.2)) + version: 10.0.1(semantic-release@25.0.3(typescript@5.9.3)) '@semantic-release/github': specifier: ^12.0.2 - version: 12.0.2(semantic-release@25.0.2(typescript@5.8.2)) + version: 12.0.8(semantic-release@25.0.3(typescript@5.9.3)) '@semantic-release/npm': specifier: ^13.1.1 - version: 13.1.1(semantic-release@25.0.2(typescript@5.8.2)) + version: 13.1.5(semantic-release@25.0.3(typescript@5.9.3)) '@semantic-release/release-notes-generator': specifier: ^14.1.0 - version: 14.1.0(semantic-release@25.0.2(typescript@5.8.2)) + version: 14.1.1(semantic-release@25.0.3(typescript@5.9.3)) '@types/node': specifier: ^24.3.0 - version: 24.3.0 + version: 24.12.4 '@types/react': specifier: ^18.3.10 - version: 18.3.18 + version: 18.3.30 '@types/react-dom': specifier: ^18.2.18 - version: 18.3.5(@types/react@18.3.18) + version: 18.3.7(@types/react@18.3.30) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.3.4(vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2)) + version: 4.7.0(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)) '@vitest/coverage-v8': specifier: 4.0.15 - version: 4.0.15(vitest@4.0.15(@types/node@24.3.0)(yaml@2.8.2)) + version: 4.0.15(vitest@4.1.8) semantic-release: specifier: ^25.0.2 - version: 25.0.2(typescript@5.8.2) + version: 25.0.3(typescript@5.9.3) typescript: specifier: ^5.8.2 - version: 5.8.2 + version: 5.9.3 vite: specifier: ^6.2.7 - version: 6.2.7(@types/node@24.3.0)(yaml@2.8.2) + version: 6.4.3(@types/node@24.12.4)(yaml@2.9.0) vitest: specifier: ^4.0.15 - version: 4.0.15(@types/node@24.3.0)(yaml@2.8.2) + version: 4.1.8(@types/node@24.12.4)(@vitest/coverage-v8@4.0.15)(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)) anndata-zarr: dependencies: '@emotion/react': specifier: ^11.14.0 - version: 11.14.0(@types/react@18.3.18)(react@18.3.1) + version: 11.14.0(@types/react@18.3.30)(react@18.3.1) '@emotion/styled': specifier: ^11.14.1 - version: 11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) + version: 11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1) '@mui/icons-material': specifier: ^7.2.0 - version: 7.3.4(@mui/material@7.3.4(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) + version: 7.3.11(@mui/material@7.3.11(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.30)(react@18.3.1) '@mui/material': specifier: ^7.2.0 - version: 7.3.4(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 7.3.11(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tanstack/react-query': specifier: ^5.85.3 - version: 5.90.21(react@18.3.1) + version: 5.101.0(react@18.3.1) hyparquet: specifier: ^1.25.6 - version: 1.25.6 + version: 1.26.0 lodash: specifier: ^4.17.21 - version: 4.17.21 + version: 4.18.1 react: specifier: ^18.2.0 version: 18.3.1 @@ -103,13 +103,13 @@ importers: devDependencies: '@vitejs/plugin-react': specifier: ^4.3.3 - version: 4.3.4(vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2)) + version: 4.7.0(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)) vite: specifier: ^6.2.3 - version: 6.2.7(@types/node@24.3.0)(yaml@2.8.2) + version: 6.4.3(@types/node@24.12.4)(yaml@2.9.0) vitest: specifier: ^3.0.8 - version: 3.2.4(@types/node@24.3.0)(yaml@2.8.2) + version: 3.2.6(@types/node@24.12.4)(yaml@2.9.0) roi-selector: dependencies: @@ -118,19 +118,19 @@ importers: version: link:../viewer '@emotion/react': specifier: ^11.14.0 - version: 11.14.0(@types/react@18.3.18)(react@18.3.1) + version: 11.14.0(@types/react@18.3.30)(react@18.3.1) '@emotion/styled': specifier: ^11.14.1 - version: 11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) + version: 11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1) '@mui/icons-material': specifier: ^7.2.0 - version: 7.3.4(@mui/material@7.3.4(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) + version: 7.3.11(@mui/material@7.3.11(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.30)(react@18.3.1) '@mui/material': specifier: ^7.2.0 - version: 7.3.4(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 7.3.11(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) deck.gl: specifier: ~9.0.0 - version: 9.0.41(@arcgis/core@4.32.8(@lit/context@1.1.6))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 9.0.41(@arcgis/core@4.34.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18.2.0 version: 18.3.1 @@ -143,22 +143,22 @@ importers: devDependencies: '@types/react': specifier: ^18.3.10 - version: 18.3.18 + version: 18.3.30 '@types/react-dom': specifier: ^18.2.18 - version: 18.3.5(@types/react@18.3.18) + version: 18.3.7(@types/react@18.3.30) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.3.4(vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2)) + version: 4.7.0(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)) typescript: specifier: ^5.8.2 - version: 5.8.2 + version: 5.9.3 vite: specifier: ^6.2.7 - version: 6.2.7(@types/node@24.3.0)(yaml@2.8.2) + version: 6.4.3(@types/node@24.12.4)(yaml@2.9.0) vite-plugin-dts: specifier: ^4.5.4 - version: 4.5.4(@types/node@24.3.0)(rollup@4.40.1)(typescript@5.8.2)(vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2)) + version: 4.5.4(@types/node@24.12.4)(rollup@4.61.0)(typescript@5.9.3)(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)) sites/app: dependencies: @@ -173,16 +173,16 @@ importers: version: link:../../viewer '@emotion/react': specifier: ^11.14.0 - version: 11.14.0(@types/react@18.3.18)(react@18.3.1) + version: 11.14.0(@types/react@18.3.30)(react@18.3.1) '@emotion/styled': specifier: ^11.14.1 - version: 11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) + version: 11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1) '@mui/icons-material': specifier: ^7.2.0 - version: 7.3.4(@mui/material@7.3.4(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) + version: 7.3.11(@mui/material@7.3.11(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.30)(react@18.3.1) '@mui/material': specifier: ^7.2.0 - version: 7.3.4(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 7.3.11(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) just-debounce-it: specifier: ^3.1.1 version: 3.2.0 @@ -195,22 +195,22 @@ importers: devDependencies: '@types/node': specifier: ^24.3.0 - version: 24.3.0 + version: 24.12.4 '@types/react': specifier: ^18.3.10 - version: 18.3.18 + version: 18.3.30 '@types/react-dom': specifier: ^18.2.18 - version: 18.3.5(@types/react@18.3.18) + version: 18.3.7(@types/react@18.3.30) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.3.4(vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2)) + version: 4.7.0(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)) typescript: specifier: ^5.8.2 - version: 5.8.2 + version: 5.9.3 vite: specifier: ^6.2.7 - version: 6.2.7(@types/node@24.3.0)(yaml@2.8.2) + version: 6.4.3(@types/node@24.12.4)(yaml@2.9.0) viewer: dependencies: @@ -219,49 +219,52 @@ importers: version: 9.0.41 '@deck.gl/geo-layers': specifier: ~9.0.0 - version: 9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + version: 9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) '@deck.gl/layers': specifier: ~9.0.0 - version: 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + version: 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) '@emotion/react': specifier: ^11.14.0 - version: 11.14.0(@types/react@18.3.18)(react@18.3.1) + version: 11.14.0(@types/react@18.3.30)(react@18.3.1) '@emotion/styled': specifier: ^11.14.1 - version: 11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) + version: 11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1) '@hms-dbmi/viv': specifier: ~0.17.2 - version: 0.17.2(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/react@9.0.41(@deck.gl/core@9.0.41)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28))(react@18.3.1) + version: 0.17.3(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/react@9.0.41(@deck.gl/core@9.0.41)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28))(react@18.3.1) '@mui/icons-material': specifier: ^7.2.0 - version: 7.3.4(@mui/material@7.3.4(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) + version: 7.3.11(@mui/material@7.3.11(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.30)(react@18.3.1) '@mui/material': specifier: ^7.2.0 - version: 7.3.4(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 7.3.11(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@vivjs/loaders': + specifier: 0.17.2 + version: 0.17.2(patch_hash=auxsjwuajoz3k5rha2oxpwrlfm) '@vivjs/types': specifier: ~0.17.0 - version: 0.17.2 + version: 0.17.3 '@zarrita/storage': specifier: 0.1.4 version: 0.1.4 deck.gl: specifier: ~9.0.0 - version: 9.0.41(@arcgis/core@4.32.8(@lit/context@1.1.6))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 9.0.41(@arcgis/core@4.34.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) jotai: specifier: ^1.0.0 - version: 1.13.1(@babel/core@7.26.9)(@babel/template@7.26.9)(react@18.3.1) + version: 1.13.1(@babel/core@7.29.7)(@babel/template@7.29.7)(react@18.3.1) math.gl: specifier: ^4.1.0 version: 4.1.0 notistack: specifier: ^3.0.2 - version: 3.0.2(csstype@3.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 3.0.2(csstype@3.2.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) p-map: specifier: ^7.0.3 - version: 7.0.3 + version: 7.0.4 quick-lru: specifier: ^7.0.0 - version: 7.0.0 + version: 7.3.0 react: specifier: ^18.2.0 version: 18.3.1 @@ -273,53 +276,52 @@ importers: version: 18.3.1 yaml: specifier: ^2.8.2 - version: 2.8.2 + version: 2.9.0 zarrita: specifier: 0.5.0 version: 0.5.0 devDependencies: '@types/node': specifier: ^24.3.0 - version: 24.3.0 + version: 24.12.4 '@types/react': specifier: ^18.3.10 - version: 18.3.18 + version: 18.3.30 '@types/react-dom': specifier: ^18.2.18 - version: 18.3.5(@types/react@18.3.18) + version: 18.3.7(@types/react@18.3.30) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.3.4(vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2)) + version: 4.7.0(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)) typescript: specifier: ^5.8.2 - version: 5.8.2 + version: 5.9.3 vite: specifier: ^6.2.7 - version: 6.2.7(@types/node@24.3.0)(yaml@2.8.2) + version: 6.4.3(@types/node@24.12.4)(yaml@2.9.0) vite-plugin-dts: specifier: ^4.5.4 - version: 4.5.4(@types/node@24.3.0)(rollup@4.40.1)(typescript@5.8.2)(vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2)) + version: 4.5.4(@types/node@24.12.4)(rollup@4.61.0)(typescript@5.9.3)(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)) packages: - '@actions/core@1.11.1': - resolution: {integrity: sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==} + '@actions/core@3.0.1': + resolution: {integrity: sha512-a6d/Nwahm9fliVGRhdhofo40HjHQasUPusmc7vBfyky+7Z+P2A1J68zyFVaNcEclc/Se+eO595oAr5nwEIoIUA==} - '@actions/exec@1.1.1': - resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==} + '@actions/exec@3.0.0': + resolution: {integrity: sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw==} - '@actions/http-client@2.2.3': - resolution: {integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==} + '@actions/http-client@4.0.1': + resolution: {integrity: sha512-+Nvd1ImaOZBSoPbsUtEhv+1z99H12xzncCkz0a3RuehINE81FZSe2QTj3uvAPTcJX/SCzUQHQ0D1GrPMbrPitg==} - '@actions/io@1.1.3': - resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==} + '@actions/io@3.0.2': + resolution: {integrity: sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==} - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} + '@amcharts/amcharts5@5.14.4': + resolution: {integrity: sha512-Tl7wQLWvsvyWVtlCIm1yhZtJviSDYjuNTnlUkO0D49GyByoK0nb9fr0DK4rUw4DVgyLcySxWBsb2lzTJm5Rd9Q==} - '@arcgis/core@4.32.8': - resolution: {integrity: sha512-TyDh2FFWLUfyDf1h3DsHQjvNdXMzmtnstRM3hkMdKl0yKOVsiQEc9ErkC2YllQf3wgoY76O5bz8vDvqzzc5Zcg==} + '@arcgis/core@4.34.8': + resolution: {integrity: sha512-UrEBTjXpSA9fhmmnAENBzz9GG81xALTezQFMXUs2iMB+tiOckmJyBbhATI/W4lIQyUfNEK7Zm/46EP2PhDga/A==} '@arcgis/lumina@4.34.9': resolution: {integrity: sha512-efqO+SwR+1IYf29AATh1l2FUeypRyRINTBNkaJY+KkaFe+8gqSJ45qOmputhyzF5WTRDb7WhOYgnChjp6VYPpA==} @@ -333,113 +335,91 @@ packages: '@arcgis/toolkit@4.34.9': resolution: {integrity: sha512-wFST+eVnCwmg9NyICVyn9bsBnR+TlWklsGqG3L7xqSTgfXo6TuCThE7wtTb8xWxsTBkGvImqMUgpgLuwQuTQ1g==} - '@babel/code-frame@7.26.2': - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.26.8': - resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} - '@babel/core@7.26.9': - resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} engines: {node: '>=6.9.0'} - '@babel/generator@7.26.9': - resolution: {integrity: sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==} + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.26.5': - resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} + '@babel/generator@7.29.7': + resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.25.9': - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.26.0': - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@babel/helper-plugin-utils@7.26.5': - resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.25.9': - resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + '@babel/helper-plugin-utils@7.29.7': + resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.25.9': - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.25.9': - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.26.9': - resolution: {integrity: sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==} + '@babel/helpers@7.29.7': + resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} engines: {node: '>=6.9.0'} - '@babel/parser@7.26.9': - resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/parser@7.28.5': - resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/parser@7.29.0': - resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} + '@babel/parser@7.29.7': + resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-transform-react-jsx-self@7.25.9': - resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} + '@babel/plugin-transform-react-jsx-self@7.29.7': + resolution: {integrity: sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-source@7.25.9': - resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} + '@babel/plugin-transform-react-jsx-source@7.29.7': + resolution: {integrity: sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.28.4': - resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} - engines: {node: '>=6.9.0'} - - '@babel/template@7.26.9': - resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.26.9': - resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==} + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} engines: {node: '>=6.9.0'} - '@babel/types@7.26.9': - resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.5': - resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + '@babel/traverse@7.29.7': + resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} engines: {node: '>=6.9.0'} - '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@1.0.2': @@ -648,152 +628,158 @@ packages: '@emotion/weak-memoize@0.4.0': resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - '@esbuild/aix-ppc64@0.25.3': - resolution: {integrity: sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==} + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.3': - resolution: {integrity: sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==} + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.3': - resolution: {integrity: sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==} + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.3': - resolution: {integrity: sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==} + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.3': - resolution: {integrity: sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==} + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.3': - resolution: {integrity: sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==} + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.3': - resolution: {integrity: sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==} + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.3': - resolution: {integrity: sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==} + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.3': - resolution: {integrity: sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==} + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.3': - resolution: {integrity: sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==} + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.3': - resolution: {integrity: sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==} + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.3': - resolution: {integrity: sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==} + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.3': - resolution: {integrity: sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==} + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.3': - resolution: {integrity: sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==} + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.3': - resolution: {integrity: sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==} + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.3': - resolution: {integrity: sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==} + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.3': - resolution: {integrity: sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==} + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.3': - resolution: {integrity: sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==} + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.3': - resolution: {integrity: sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==} + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.3': - resolution: {integrity: sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==} + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.3': - resolution: {integrity: sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==} + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.25.3': - resolution: {integrity: sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==} + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.3': - resolution: {integrity: sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==} + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.3': - resolution: {integrity: sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==} + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.3': - resolution: {integrity: sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==} + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -809,155 +795,153 @@ packages: resolution: {integrity: sha512-iOOuRurpjFxFVw6+aXW2JpSkRBrdOpBcbdibfPOmSPqMd1aoHBtYmYXetKoH9vfrXoBiPyO2PkDnczhsu/N9IA==} hasBin: true - '@fastify/busboy@2.1.1': - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} - engines: {node: '>=14'} + '@floating-ui/core@1.7.5': + resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} + + '@floating-ui/dom@1.7.6': + resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==} + + '@floating-ui/utils@0.2.11': + resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} + + '@foliojs-fork/fontkit@1.9.2': + resolution: {integrity: sha512-IfB5EiIb+GZk+77TRB86AHroVaqfq8JRFlUbz0WEwsInyCG0epX2tCPOy+UfaWPju30DeVoUAXfzWXmhn753KA==} - '@floating-ui/core@1.7.4': - resolution: {integrity: sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==} + '@foliojs-fork/linebreak@1.1.2': + resolution: {integrity: sha512-ZPohpxxbuKNE0l/5iBJnOAfUaMACwvUIKCvqtWGKIMv1lPYoNjYXRfhi9FeeV9McBkBLxsMFWTVVhHJA8cyzvg==} - '@floating-ui/dom@1.7.5': - resolution: {integrity: sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==} + '@foliojs-fork/pdfkit@0.15.3': + resolution: {integrity: sha512-Obc0Wmy3bm7BINFVvPhcl2rnSSK61DQrlHU8aXnAqDk9LCjWdUOPwhgD8Ywz5VtuFjRxmVOM/kQ/XLIBjDvltw==} - '@floating-ui/utils@0.2.10': - resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + '@foliojs-fork/restructure@2.0.2': + resolution: {integrity: sha512-59SgoZ3EXbkfSX7b63tsou/SDGzwUEK6MuB5sKqgVK1/XE0fxmpsOb9DQI8LXW3KfGnAjImCGhhEb7uPPAUVNA==} - '@hms-dbmi/viv@0.17.2': - resolution: {integrity: sha512-TLXDLLRg3bJLJGIeKk0XuB5zLZyD0H9atUxlma57mLn/L4GTKCbed7pLR4qymt5aSKFcpyLcMLeFm2Y7d0WxTA==} + '@hms-dbmi/viv@0.17.3': + resolution: {integrity: sha512-2OR6gDBlTUN1oDdWK75++E/F8upnxD9lLgqAu3G80sQIdbLed+4WM6Y0duYNmm6/NGr3I3+TCxdqSO1IN8s5Qw==} '@interactjs/types@1.10.27': resolution: {integrity: sha512-BUdv0cvs4H5ODuwft2Xp4eL8Vmi3LcihK42z0Ft/FbVJZoRioBsxH+LlsBdK4tAie7PqlKGy+1oyOncu1nQ6eA==} - '@isaacs/balanced-match@4.0.1': - resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} - engines: {node: 20 || >=22} - - '@isaacs/brace-expansion@5.0.0': - resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} - engines: {node: 20 || >=22} + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - '@jridgewell/gen-mapping@0.3.8': - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@lit-labs/ssr-dom-shim@1.5.1': - resolution: {integrity: sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==} - - '@lit/context@1.1.6': - resolution: {integrity: sha512-M26qDE6UkQbZA2mQ3RjJ3Gzd8TxP+/0obMgE5HfkfLhEEyYE3Bui4A5XHiGPjy0MUGAyxB3QgVuw2ciS0kHn6A==} + '@lit-labs/ssr-dom-shim@1.6.0': + resolution: {integrity: sha512-VHb0ALPMTlgKjM6yIxxoQNnpKyUKLD04VzeQdsiXkMqkvYlAHxq9glGLmgbb889/1GsohSOAjvQYoiBppXFqrQ==} '@lit/reactive-element@2.1.2': resolution: {integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==} - '@loaders.gl/3d-tiles@4.3.3': - resolution: {integrity: sha512-3uOXE8W0ppbY7tI5ywrU3RwCLMZtd+Jh0KgY9+EbjBVnZDHcnFxytYuG4NzfJEf5zwv0jladeSbJS1oVbLi8Jw==} + '@loaders.gl/3d-tiles@4.4.2': + resolution: {integrity: sha512-rf2R7x/+t41hQpaQ3iKofooE6unZ0+sGlYUXBo7lYFEnoMmalzrOI6jCs+CV96TALMPQcpfPa566XWF74XkaBQ==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/compression@4.3.3': - resolution: {integrity: sha512-1IZIFb6MaIiwMwsLEUk5Tyu8qlY7ge2S2Uy2qJxTP23CHakdocue89c54ygo0CgOiUw3Tr1r5JVa3EhB4+lOJQ==} + '@loaders.gl/compression@4.4.2': + resolution: {integrity: sha512-/LzblCXn6wOg7ca2zkUOTO0zhjjaPAOqlLp4/kwd57v7KZU8M8aKUNlU1DAuWKW9p/+TpGsLKwDqOCO+hjrOnQ==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/core@4.3.3': - resolution: {integrity: sha512-RaQ3uNg4ZaVqDRgvJ2CjaOjeeHdKvbKuzFFgbGnflVB9is5bu+h3EKc3Jke7NGVvLBsZ6oIXzkwHijVsMfxv8g==} + '@loaders.gl/core@4.4.2': + resolution: {integrity: sha512-DZmsTwxdKh3q+mS1vSOW2EXFgwxZ4nIBte4H5g6e4VyQoQ6jAOkk0M6V+Asgy/eqjGTNjhfBA1HIkyBl0A9hcA==} - '@loaders.gl/crypto@4.3.3': - resolution: {integrity: sha512-uwqcSGJ4DdS2g3BYc4Noa4EGfnbK63wCQnke4Xyc7KTNl6P70oblDlRbL3df1WQPMTUoXYOERE+ei7Q0Tee4vQ==} + '@loaders.gl/crypto@4.4.2': + resolution: {integrity: sha512-3QQxNFmCeznMIsY/ZD4pYO4SvS4i3nq5aJJ993DEIZVB1i0z19OmyJu4TSovvirXXrNWPQRJFPUUwdPxol9wLA==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/draco@4.3.3': - resolution: {integrity: sha512-f2isxvOoH4Pm5p4mGvNN9gVigUwX84j9gdKNMV1aSo56GS1KE3GS2rXaIoy1qaIHMzkPySUTEcOTwayf0hWU7A==} + '@loaders.gl/draco@4.4.2': + resolution: {integrity: sha512-UByWIt/yhxMFBIlyoqJYaj0rnTz/wwDWbI4CVQc/MzbLZW7NtUkDyYDcjbjE2SBWpu6Ef4ryojGd/NWIA3Yknw==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/gis@4.3.3': - resolution: {integrity: sha512-OQNrieRMihsy2mVHuhi7d/SThUdNCgFXmUqhCG53qAVIS+7Nm//lO9zty3EzfOGWHjYcx6+nxl4QO3mR5fXMvg==} + '@loaders.gl/geoarrow@4.4.2': + resolution: {integrity: sha512-FGCtUsvTwdxiNqS8cEtys1FdM/m6pwMzvNEa32sHfrI4Si465Oa2iJkyu2q/XMgL/vhfE/G3EezpVKZARbCzkw==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/gltf@4.3.3': - resolution: {integrity: sha512-M7jQ7KIB5itctDmGYuT9gndmjNwk1lwQ+BV4l5CoFp38e4xJESPglj2Kj8csWdm3WJhrxIYEP4GpjXK02n8DSQ==} + '@loaders.gl/gis@4.4.2': + resolution: {integrity: sha512-VMs1XcqUCqLczfySsI9VA/L3WDuuNRPqVoHcXU3FZuSe49x++gtwmxF1TEhJCaQINk0CkCOnxBbKOz3I9M1e3w==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/images@4.3.3': - resolution: {integrity: sha512-s4InjIXqEu0T7anZLj4OBUuDBt2BNnAD0GLzSexSkBfQZfpXY0XJNl4mMf5nUKb5NDfXhIKIqv8y324US+I28A==} + '@loaders.gl/gltf@4.4.2': + resolution: {integrity: sha512-aBvI7P/1GxePdHIvuyTM4A8yt3F5ph4dq0mkyJHmEjBl1Cwh3mDZJI1JSlZAFVilTZ6NxJZOiHUYWe1pBloVvw==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/loader-utils@4.3.3': - resolution: {integrity: sha512-8erUIwWLiIsZX36fFa/seZsfTsWlLk72Sibh/YZJrPAefuVucV4mGGzMBZ96LE2BUfJhadn250eio/59TUFbNw==} + '@loaders.gl/images@4.4.2': + resolution: {integrity: sha512-b+1keNvPlyLniWtX4ZaThz2dF2aohi8Q+OEsDF2hJNZYyZJOqP9b/72UhlVk+inxTJfTLRBNARs2TJ2ssBlelg==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/math@4.3.3': - resolution: {integrity: sha512-oUfCFYsybm6fKnYHU1BzqXsh0sCJ+M9CXNnD/083ZNW+lWdxD44eeTE3DdFYPEMe+yyMkLSGx/8WTMv7ev2t5Q==} + '@loaders.gl/loader-utils@4.4.2': + resolution: {integrity: sha512-kqwBbyRC7rrQVsnJyKeoaig9hxaa5oj91OKqWm27HPuVn4q2dD67SEhiG0ND62eRp0tLY6jTqEcI5kDzHBZ6MA==} + + '@loaders.gl/math@4.4.2': + resolution: {integrity: sha512-Pcm1DKrzH3EqC5PkBxQX0oVjmXM3RIm2Gfj0cXQoqly+8c/NBtQrcBA9tl12h2ozZe8Ednue/kockbGsyKAx5A==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/mvt@4.3.3': - resolution: {integrity: sha512-y7YtrpPBOR4ek1Vj8vM2dRFrFfZHz7e5ZuYSgANOAyGzDXbnZ5TKPPIQC8Plm/y3ZQe+063yJ+kuGc91FBRbXg==} + '@loaders.gl/mvt@4.4.2': + resolution: {integrity: sha512-yji3TAUofTA3GXvvyemwfrRwbd1ILpv2qe4mRduHdzjJdy2httH1cCKkesavFuLeRQqEuVyhhxYK+aSAbdt9Kg==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/schema@4.3.3': - resolution: {integrity: sha512-zacc9/8je+VbuC6N/QRfiTjRd+BuxsYlddLX1u5/X/cg9s36WZZBlU1oNKUgTYe8eO6+qLyYx77yi+9JbbEehw==} + '@loaders.gl/schema-utils@4.4.2': + resolution: {integrity: sha512-yYYRD/POBEO72rhIyLASrqKUUhfIOQuFk/fgInN6Td2qvFgsHbo5UaCM4sTqVUWwNxNvXDQi8ezpbnCa/yi+OQ==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 + + '@loaders.gl/schema@4.4.2': + resolution: {integrity: sha512-mJTZehTHIFl8ed+03nebuPAMnLP8Yp00DKTzCnKT2HNy/uV4+Sw+GrGIuhPHGU8tdQmtBXRURGM2ZxUAxMfGKg==} - '@loaders.gl/terrain@4.3.3': - resolution: {integrity: sha512-qPfpYL0imojyic0dTW71d9M8k2SY+wD60m31658vtsMogdVeBiAX/WYtk8W/NKcqBS8FMv9CC41PlULrvcZ7TQ==} + '@loaders.gl/terrain@4.4.2': + resolution: {integrity: sha512-ScE90mhUrIOOf+248+G8bxgg5xfLptE94gVxtYsLysyG8b4Ne2WEb6J2gpvQqmaLz3k9OqgPR7M8F1zI5BVO0w==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/textures@4.3.3': - resolution: {integrity: sha512-qIo4ehzZnXFpPKl1BGQG4G3cAhBSczO9mr+H/bT7qFwtSirWVlqsvMlx1Q4VpmouDu+tudwwOlq7B3yqU5P5yQ==} + '@loaders.gl/textures@4.4.2': + resolution: {integrity: sha512-+GKcHEE0GjpuSJ6qbuRsB0CaOSUhJ1epUvhMP5GVK7I6+bwSvG8nqmRRGXFQNmYsbFANwG+wjwKf16wqJwP6vg==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/tiles@4.3.3': - resolution: {integrity: sha512-cmC/spc+DM5aCSHoHrEuTPhDLuZRtkrWnlHkhC2Tur9uiUr41U3vXnC5slJkOeIWkaN4Q7KRFGCQ6SCendYfMg==} + '@loaders.gl/tiles@4.4.2': + resolution: {integrity: sha512-DHqMC38e6IEzWEDc15GfIKsZT82VZH7ocF79xLRScey0eZfCb3qI5nDLeg5adSBBsHkG3Li0S0PEnwxQmKT3qw==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/wms@4.3.3': - resolution: {integrity: sha512-SmpdFB/Jhtzbc52TlMKRSxQkUDfYP/FN8qdTdL3PtVN74Vuh4eZ8t7nLzplUCx0tbkbT1D7nfreSU4ndWq2zjQ==} + '@loaders.gl/wms@4.4.2': + resolution: {integrity: sha512-7uhis6fOTHeqRLIU1EPoC1oqeXVk5p1pM136fSqMw0CbVSNj87b0FFMwlJwzwTfL8Vte8GyKrNcDa47PjaT19Q==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/worker-utils@4.3.3': - resolution: {integrity: sha512-eg45Ux6xqsAfqPUqJkhmbFZh9qfmYuPfA+34VcLtfeXIwAngeP6o4SrTmm9LWLGUKiSh47anCEV1p7borDgvGQ==} + '@loaders.gl/worker-utils@4.4.2': + resolution: {integrity: sha512-oiZ0SoC1QKrOkhYPlVZ6Q06CtmuFRyZw2rwzmT08ZyaGtOArIJHDjlhxzwWiv+6fdws47Ub5uIGsdI1Ab1xYsA==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/xml@4.3.3': - resolution: {integrity: sha512-p4GjJn7cElnSxZE2DVsTPWnEJWL3iqTVnGbW2ODHFpW2E7ClPmyoDsUxb8zdW8DuQKfLPJkUILtubbaHmwOwZg==} + '@loaders.gl/xml@4.4.2': + resolution: {integrity: sha512-OOPqpYH1PK9szuzXh3Oy7aErMXTXB+aiKi79LPCI93Wsb8pdbQiDiRRW8X/op9qABhxpCAMXF5N89eDJv3XdtQ==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 - '@loaders.gl/zip@4.3.3': - resolution: {integrity: sha512-PPNR9xBLfhBd4Fw69Ai5cUzIJZFCYg3DiYGeR8mA8ik9tuseH+hEBUSsmzU4RFP53xkPLLYvzXjVyiBzfbsjZg==} + '@loaders.gl/zip@4.4.2': + resolution: {integrity: sha512-KdgmJRNra9+9jt2zzHUvFXnBqwzeN7dW4MEgTmH/NtraGy8bz5Tk5NrIUj8JXPxhx+vP2vxUWbeCEUoLGO/m9A==} peerDependencies: - '@loaders.gl/core': ^4.3.0 + '@loaders.gl/core': ~4.4.0 '@luma.gl/constants@9.0.28': resolution: {integrity: sha512-mw3YwYfCbpCa8y28nNZGaJemprSkqthsunz0V79qpnMrFD3pOMIh+rw/hjQuqVW9ffmSXx+xY2bI8FT1YC8f7A==} @@ -996,8 +980,8 @@ packages: '@mapbox/tile-cover@3.0.1': resolution: {integrity: sha512-R8aoFY/87HWBOL9E2eBqzOY2lpfWYXCcTNgBpIxAv67rqQeD4IfnHD0iPXg/Z1cqXrklegEYZCp/7ZR/RsWqBQ==} - '@mapbox/tiny-sdf@2.0.6': - resolution: {integrity: sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA==} + '@mapbox/tiny-sdf@2.2.0': + resolution: {integrity: sha512-LVL4wgI9YAum5V+LNVQO6QgFBPw7/MIIY4XJPNsPDMrjEwcE+JfKk1LuIl8GnF197ejVdC9QdPaxrx5gfgdGXg==} '@mapbox/vector-tile@1.3.1': resolution: {integrity: sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==} @@ -1023,40 +1007,40 @@ packages: '@math.gl/web-mercator@4.1.0': resolution: {integrity: sha512-HZo3vO5GCMkXJThxRJ5/QYUYRr3XumfT8CzNNCwoJfinxy5NtKUd7dusNTXn7yJ40UoB8FMIwkVwNlqaiRZZAw==} - '@microsoft/api-extractor-model@7.32.2': - resolution: {integrity: sha512-Ussc25rAalc+4JJs9HNQE7TuO9y6jpYQX9nWD1DhqUzYPBr3Lr7O9intf+ZY8kD5HnIqeIRJX7ccCT0QyBy2Ww==} + '@microsoft/api-extractor-model@7.33.8': + resolution: {integrity: sha512-aIcoQggPyer3B6Ze3usz0YWC/oBwUHfRH5ETUsr+oT2BRA6SfTJl7IKPcPZkX4UR+PohowzW4uMxsvjrn8vm+w==} - '@microsoft/api-extractor@7.55.2': - resolution: {integrity: sha512-1jlWO4qmgqYoVUcyh+oXYRztZde/pAi7cSVzBz/rc+S7CoVzDasy8QE13dx6sLG4VRo8SfkkLbFORR6tBw4uGQ==} + '@microsoft/api-extractor@7.58.7': + resolution: {integrity: sha512-yK6OycD46gIzLRpj6ueVUWPk1ACSpkN1LBo05gY1qPTylbWyUCanXfH7+VgkI5LJrJoRSQR5F04XuCffCXLOBw==} hasBin: true - '@microsoft/tsdoc-config@0.18.0': - resolution: {integrity: sha512-8N/vClYyfOH+l4fLkkr9+myAoR6M7akc8ntBJ4DJdWH2b09uVfr71+LTMpNyG19fNqWDg8KEDZhx5wxuqHyGjw==} + '@microsoft/tsdoc-config@0.18.1': + resolution: {integrity: sha512-9brPoVdfN9k9g0dcWkFeA7IH9bbcttzDJlXvkf8b2OBzd5MueR1V2wkKBL0abn0otvmkHJC6aapBOTJDDeMCZg==} '@microsoft/tsdoc@0.16.0': resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} - '@mui/core-downloads-tracker@7.3.4': - resolution: {integrity: sha512-BIktMapG3r4iXwIhYNpvk97ZfYWTreBBQTWjQKbNbzI64+ULHfYavQEX2w99aSWHS58DvXESWIgbD9adKcUOBw==} + '@mui/core-downloads-tracker@7.3.11': + resolution: {integrity: sha512-a7I/b/nBTdXYz2cOSlEmkQ9WWE1x8FHpqMhFPp+Y1VPFxcOw91G5ELOHARQAGSPy5V+UCgJua6K/1x70bAtQPw==} - '@mui/icons-material@7.3.4': - resolution: {integrity: sha512-9n6Xcq7molXWYb680N2Qx+FRW8oT6j/LXF5PZFH3ph9X/Rct0B/BlLAsFI7iL9ySI6LVLuQIVtrLiPT82R7OZw==} + '@mui/icons-material@7.3.11': + resolution: {integrity: sha512-+hz5ilwHZ3djd5es3sCErLioqe/NhZcYTsV/TNXZAMdJdb23F4xzJjqnnZdnurc3S1+ietcssRNqieOhPQLZ7Q==} engines: {node: '>=14.0.0'} peerDependencies: - '@mui/material': ^7.3.4 + '@mui/material': ^7.3.11 '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: '@types/react': optional: true - '@mui/material@7.3.4': - resolution: {integrity: sha512-gEQL9pbJZZHT7lYJBKQCS723v1MGys2IFc94COXbUIyCTWa+qC77a7hUax4Yjd5ggEm35dk4AyYABpKKWC4MLw==} + '@mui/material@7.3.11': + resolution: {integrity: sha512-yq8bPc3LxOwKRWpcjRgDkYFmpM6aKlARfESTmOQcvLYFeJwtHte2tw6hJDrb8sk8wcvpDprHEHVaoUU0MslIkw==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.5.0 '@emotion/styled': ^11.3.0 - '@mui/material-pigment-css': ^7.3.3 + '@mui/material-pigment-css': ^7.3.11 '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -1070,8 +1054,8 @@ packages: '@types/react': optional: true - '@mui/private-theming@7.3.3': - resolution: {integrity: sha512-OJM+9nj5JIyPUvsZ5ZjaeC9PfktmK+W5YaVLToLR8L0lB/DGmv1gcKE43ssNLSvpoW71Hct0necfade6+kW3zQ==} + '@mui/private-theming@7.3.11': + resolution: {integrity: sha512-9B+YKms0fRHbNrqp9tOT/DNbNnU5gyvJ1o3qAGXfq8GmZcbJnE3At9x07Zr/o0pkhzg4aDdwXVqe4+AcgtOCPA==} engines: {node: '>=14.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -1080,8 +1064,8 @@ packages: '@types/react': optional: true - '@mui/styled-engine@7.3.3': - resolution: {integrity: sha512-CmFxvRJIBCEaWdilhXMw/5wFJ1+FT9f3xt+m2pPXhHPeVIbBg9MnMvNSJjdALvnQJMPw8jLhrUtXmN7QAZV2fw==} + '@mui/styled-engine@7.3.10': + resolution: {integrity: sha512-WxE9SiF8xskAQqGjsp0poXCkCqsoXFEsSr0HBXfApmGHR+DBnXRp+z46Vsltg4gpPM4Z96DeAQRpeAOnhNg7Ng==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.4.1 @@ -1093,8 +1077,8 @@ packages: '@emotion/styled': optional: true - '@mui/system@7.3.3': - resolution: {integrity: sha512-Lqq3emZr5IzRLKaHPuMaLBDVaGvxoh6z7HMWd1RPKawBM5uMRaQ4ImsmmgXWtwJdfZux5eugfDhXJUo2mliS8Q==} + '@mui/system@7.3.11': + resolution: {integrity: sha512-7izwGWdNawAKpBKcRlx7f2gFnAAjmASBWvMcyX4YYEeLOFsbfGRbUYGInvnAcUeql3rPxI7F9Ft4oY2OLRz44g==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -1109,16 +1093,16 @@ packages: '@types/react': optional: true - '@mui/types@7.4.7': - resolution: {integrity: sha512-8vVje9rdEr1rY8oIkYgP+Su5Kwl6ik7O3jQ0wl78JGSmiZhRHV+vkjooGdKD8pbtZbutXFVTWQYshu2b3sG9zw==} + '@mui/types@7.4.12': + resolution: {integrity: sha512-iKNAF2u9PzSIj40CjvKJWxFXJo122jXVdrmdh0hMYd+FR+NuJMkr/L88XwWLCRiJ5P1j+uyac25+Kp6YC4hu6w==} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: '@types/react': optional: true - '@mui/utils@7.3.3': - resolution: {integrity: sha512-kwNAUh7bLZ7mRz9JZ+6qfRnnxbE4Zuc+RzXnhSpRSxjTlSTj7b4JxRLXpG+MVtPVtqks5k/XC8No1Vs3x4Z2gg==} + '@mui/utils@7.3.11': + resolution: {integrity: sha512-XTjGnifwteg71/ij+0e7Y7d+hwyntMYP5wPoA/g2drdGH+Flkvjwy0OfrVpKBbaOvofq4zU/LIyUZyKgmWu18g==} engines: {node: '>=14.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -1127,6 +1111,9 @@ packages: '@types/react': optional: true + '@nodable/entities@2.1.1': + resolution: {integrity: sha512-Pig3HxDIoMgjdEH8OCf/dkcTmLFjJRjWuq8jSnklu284/TKOPibSRERmOykiwmyXTtv61mP+44f3GMx0tLAyjg==} + '@octokit/auth-token@6.0.0': resolution: {integrity: sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==} engines: {node: '>= 20'} @@ -1135,8 +1122,8 @@ packages: resolution: {integrity: sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==} engines: {node: '>= 20'} - '@octokit/endpoint@11.0.2': - resolution: {integrity: sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ==} + '@octokit/endpoint@11.0.3': + resolution: {integrity: sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==} engines: {node: '>= 20'} '@octokit/graphql@9.0.3': @@ -1152,8 +1139,8 @@ packages: peerDependencies: '@octokit/core': '>=6' - '@octokit/plugin-retry@8.0.3': - resolution: {integrity: sha512-vKGx1i3MC0za53IzYBSBXcrhmd+daQDzuZfYDd52X5S0M2otf3kVZTVP8bLA3EkU0lTvd1WEC2OlNNa4G+dohA==} + '@octokit/plugin-retry@8.1.0': + resolution: {integrity: sha512-O1FZgXeiGb2sowEr/hYTr6YunGdSAFWnr2fyW39Ah85H8O33ELASQxcvOFF5LE6Tjekcyu2ms4qAzJVhSaJxTw==} engines: {node: '>= 20'} peerDependencies: '@octokit/core': '>=7' @@ -1164,12 +1151,12 @@ packages: peerDependencies: '@octokit/core': ^7.0.0 - '@octokit/request-error@7.0.2': - resolution: {integrity: sha512-U8piOROoQQUyExw5c6dTkU3GKxts5/ERRThIauNL7yaRoeXW0q/5bgHWT7JfWBw1UyrbK8ERId2wVkcB32n0uQ==} + '@octokit/request-error@7.1.0': + resolution: {integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==} engines: {node: '>= 20'} - '@octokit/request@10.0.6': - resolution: {integrity: sha512-FO+UgZCUu+pPnZAR+iKdUt64kPE7QW7ciqpldaMXaNzixz5Jld8dJ31LAUewk0cfSRkNSRKyqG438ba9c/qDlQ==} + '@octokit/request@10.0.10': + resolution: {integrity: sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w==} engines: {node: '>= 20'} '@octokit/types@16.0.0': @@ -1178,8 +1165,8 @@ packages: '@open-wc/dedupe-mixin@1.4.0': resolution: {integrity: sha512-Sj7gKl1TLcDbF7B6KUhtvr+1UCxdhMbNY5KxdU5IfMFWqL8oy1ZeAcCANjoB1TL0AJTcPmcCFsCbHf8X2jGDUA==} - '@petamoriken/float16@3.9.2': - resolution: {integrity: sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==} + '@petamoriken/float16@3.9.3': + resolution: {integrity: sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g==} '@pnpm/config.env-replace@1.1.0': resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} @@ -1189,8 +1176,8 @@ packages: resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} engines: {node: '>=12.22.0'} - '@pnpm/npm-conf@2.3.1': - resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==} + '@pnpm/npm-conf@3.0.2': + resolution: {integrity: sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA==} engines: {node: '>=12'} '@polymer/polymer@3.5.2': @@ -1199,17 +1186,20 @@ packages: '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} - '@probe.gl/env@4.1.0': - resolution: {integrity: sha512-5ac2Jm2K72VCs4eSMsM7ykVRrV47w32xOGMvcgqn8vQdEMF9PRXyBGYEV9YbqRKWNKpNKmQJVi4AHM/fkCxs9w==} + '@probe.gl/env@4.1.1': + resolution: {integrity: sha512-+68seNDMVsEegRB47pFA/Ws1Fjy8agcFYXxzorKToyPcD6zd+gZ5uhwoLd7TzsSw6Ydns//2KEszWn+EnNHTbA==} + + '@probe.gl/log@4.1.1': + resolution: {integrity: sha512-kcZs9BT44pL7hS1OkRGKYRXI/SN9KejUlPD+BY40DguRLzdC5tLG/28WGMyfKdn/51GT4a0p+0P8xvDn1Ez+Kg==} - '@probe.gl/log@4.1.0': - resolution: {integrity: sha512-r4gRReNY6f+OZEMgfWEXrAE2qJEt8rX0HsDJQXUBMoc+5H47bdB7f/5HBHAmapK8UydwPKL9wCDoS22rJ0yq7Q==} + '@probe.gl/stats@4.1.1': + resolution: {integrity: sha512-4VpAyMHOqydSvPlEyHwXaE+AkIdR03nX+Qhlxsk2D/IW4OVmDZgIsvJB1cDzyEEtcfKcnaEbfXeiPgejBceT6g==} - '@probe.gl/stats@4.1.0': - resolution: {integrity: sha512-EI413MkWKBDVNIfLdqbeNSJTs7ToBz/KVGkwi3D+dQrSIkRI2IYbWGAU3xX+D6+CI4ls8ehxMhNpUVMaZggDvQ==} + '@rolldown/pluginutils@1.0.0-beta.27': + resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} - '@rollup/pluginutils@5.3.0': - resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + '@rollup/pluginutils@5.4.0': + resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 @@ -1217,135 +1207,160 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.40.1': - resolution: {integrity: sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw==} + '@rollup/rollup-android-arm-eabi@4.61.0': + resolution: {integrity: sha512-dnxczajOqt0gesZlN5pGQ1s1imQVrsmCw5G2Ci4oM+0WvNz3pyRnlWrT7McoZIb8VlFwCawdmbWRmxRn7HI+VQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.40.1': - resolution: {integrity: sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw==} + '@rollup/rollup-android-arm64@4.61.0': + resolution: {integrity: sha512-Bp3JpGP00Vu3f238ivRrjf7z3xSzVPXqCmaJYA9t2c+c8vKYvOzmXF7LkkeUalTEGd6cZcSWe+PFIP3Vy48fRg==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.40.1': - resolution: {integrity: sha512-VWXGISWFY18v/0JyNUy4A46KCFCb9NVsH+1100XP31lud+TzlezBbz24CYzbnA4x6w4hx+NYCXDfnvDVO6lcAA==} + '@rollup/rollup-darwin-arm64@4.61.0': + resolution: {integrity: sha512-zaYIpr670mUmmZ1tVzUFplbQbG7h3Gugx3L5FoqhsC2m/YnLlR1a7zVLmXNPy+iY1tFPEbNG+HHBXZGyId0G5w==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.40.1': - resolution: {integrity: sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw==} + '@rollup/rollup-darwin-x64@4.61.0': + resolution: {integrity: sha512-+P49fvkv2dSoeevUW+lgZ/I2JHSsJCK1Lyjj7Cu6E4UHG4tS9XIefzIjo5qhgELjAclnen1rLzK2PMKJdo+Dyg==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.40.1': - resolution: {integrity: sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw==} + '@rollup/rollup-freebsd-arm64@4.61.0': + resolution: {integrity: sha512-l3FAAOyKJXH2ea6KNFN+MMgC/rnE94YGLXs2ehYqDcCoHt1DpvgWX75BhUJxN38XojP7Ul+4H8PRn7EdyqSDrw==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.40.1': - resolution: {integrity: sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q==} + '@rollup/rollup-freebsd-x64@4.61.0': + resolution: {integrity: sha512-VokPN3TSctKj65cyCNPaUh4vMFA8awxOot/0sp+4J7ZlNRKQEhXhawqPwajoi8H5ZFt61i0ugZJuTKXBjGJ17Q==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.40.1': - resolution: {integrity: sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg==} + '@rollup/rollup-linux-arm-gnueabihf@4.61.0': + resolution: {integrity: sha512-DxH0P3wxm+Yzs/p3zrk9dw1rURu8p0Nv5+MRK/L7OtnLNg5rLZraSBFZ8iUXOd9f2BlhJyEpIZUH/emjq4UJ4g==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.40.1': - resolution: {integrity: sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg==} + '@rollup/rollup-linux-arm-musleabihf@4.61.0': + resolution: {integrity: sha512-T6ZvMNe84kAz6TBWHC7hGAoEtzP1LWYw/AqayGWEF6uISt3Abk/st06LqRD9THd7Xz3NxzurUpzAuEAUbZf+nw==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.40.1': - resolution: {integrity: sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg==} + '@rollup/rollup-linux-arm64-gnu@4.61.0': + resolution: {integrity: sha512-q/4hzvQkDs8b4jIBab1pnLiiM0ayTZsN2amBFPDzuyZxjEd4wDwx0UJFYM3cOZzSf5Kw8fnWSprJzIBMkcR44Q==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.40.1': - resolution: {integrity: sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ==} + '@rollup/rollup-linux-arm64-musl@4.61.0': + resolution: {integrity: sha512-vvYWX3akdEAY6km+9wAqFDnk6pQsbJKVnj7xawcvs/+fdlYBGp+U+Qq/lLfpIxYIZvZLHMAKD9HLdacSx/r3dw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.40.1': - resolution: {integrity: sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ==} + '@rollup/rollup-linux-loong64-gnu@4.61.0': + resolution: {integrity: sha512-DePa5cqOxDP/Zp0VOXpeWaGew5iIv5DXp9NYbzkX5PFQyWVX9184WCTh3hvr/7lhXo8ZVlbFLkz8+o/q1dU6gA==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.40.1': - resolution: {integrity: sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg==} + '@rollup/rollup-linux-loong64-musl@4.61.0': + resolution: {integrity: sha512-LV8aWMB8UChglMCEzs7RkN0GsH29RJaLLqwm9fCIjlqwxQTiWAqNcc7wjBkH31hV0PU/yVxGYvrYsgfea2qw6g==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.61.0': + resolution: {integrity: sha512-QoNSnwQtaeNu5grdBbsL0tt1uyl5EnS8DA8Mr3nluMXbhdQNyhN+G4tBax7VCdxLKj8YJ0/4OO9Ho84jMnJtKA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.61.0': + resolution: {integrity: sha512-/zZp5MKapIIApE8trN8qLGNSiRN9TUoaUZ1cmVu4XnVdd5LQLOXTtyi+vtfUbNnT3iyjzpPqYeKXmvJ+gJGYWw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.40.1': - resolution: {integrity: sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ==} + '@rollup/rollup-linux-riscv64-gnu@4.61.0': + resolution: {integrity: sha512-RbrzcD3aJ1k3UbtMRRBNwojdVVyXjuVAFTfn/xPa6EEl6GE9Sm/akPgFTb9aAC9pMKGJ6CtWxaGrqWcabH+ySg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.40.1': - resolution: {integrity: sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA==} + '@rollup/rollup-linux-riscv64-musl@4.61.0': + resolution: {integrity: sha512-ZF+onDsBso8PJf1XaG9lB+O9RnBpKGnY6OrzC4CSHrtC1jb6jWLTKK4bRqdoCXHd22gyr2hiYmEAm8Wns/BOCw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.40.1': - resolution: {integrity: sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg==} + '@rollup/rollup-linux-s390x-gnu@4.61.0': + resolution: {integrity: sha512-Atk0aSIk5Zx2Wuh9dgRQgLP0Koc8hOeYpbWryMXyk8G8/HmPkwPPkMqIIDhrXHHYqfUzSJA/I7IWSBv8xSmRBA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.40.1': - resolution: {integrity: sha512-XiK5z70PEFEFqcNj3/zRSz/qX4bp4QIraTy9QjwJAb/Z8GM7kVUsD0Uk8maIPeTyPCP03ChdI+VVmJriKYbRHQ==} + '@rollup/rollup-linux-x64-gnu@4.61.0': + resolution: {integrity: sha512-0uMOcf3eZ5K+K4cYHkdxShFMPlPXCOdfDFEFn9dNYAEEd2cVvmOfH7zFgRVoDgmtQ1m9k5q7qfrHzyMAubKYUA==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.40.1': - resolution: {integrity: sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ==} + '@rollup/rollup-linux-x64-musl@4.61.0': + resolution: {integrity: sha512-mvFtE4A/t/7hRJ7X8Ozmu8FsIkAUat2nzl12pgU337BRmq87AQUJztwHz2Zv5/tjo9/C95E66CK03SI/ToEDJw==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.40.1': - resolution: {integrity: sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg==} + '@rollup/rollup-openbsd-x64@4.61.0': + resolution: {integrity: sha512-z9b9+aTxvt8n2rNltMPvyaUfB8NJ+CVyOrGK/MdIKHx7B+lXmZpm/XbRsU7Rpf3fRqJ2uS6mBJiJveCtq8LHDg==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.61.0': + resolution: {integrity: sha512-jXaXFqKMehsOc+g8R6oo33RRC6w07G9jDBxAE5eAKX7mOcCbZloYIPNhfG9Wl+P9O9IWHFO4OJgPi1Ml2qkt7w==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.61.0': + resolution: {integrity: sha512-OXNWVFocS2IA4+QplhTZZ2a+8hPZR7T8KuozsNmJKK8y7cp83StHvGksfHzPG3wczWTczyWHVQuqeiTUbjiyBg==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.40.1': - resolution: {integrity: sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA==} + '@rollup/rollup-win32-ia32-msvc@4.61.0': + resolution: {integrity: sha512-AlAbNtBO637LxSldqV43z0FfXoGfl2TW1DgAg/bs7aQswFbDewz2SJm3BUhiGfbOVtW571xbc9p+REdxhyN/Eg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.40.1': - resolution: {integrity: sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA==} + '@rollup/rollup-win32-x64-gnu@4.61.0': + resolution: {integrity: sha512-QRSrQXyJ1M4tjNXdR0/G/IgV6lzfQQJYBjlWIEYkY2Xs86DRl/iEpQ4blMDjJxSl7n19eDKKXMg0AmuBVYy8pQ==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.61.0': + resolution: {integrity: sha512-tkuFxhvKO/HlGd0VsINF6vHSYH8AF8W0TcNxKDK6JZmrehngFj78pToc8iemtnvwilDjs2G/qSzYFhe9U8q+fw==} cpu: [x64] os: [win32] - '@rushstack/node-core-library@5.19.1': - resolution: {integrity: sha512-ESpb2Tajlatgbmzzukg6zyAhH+sICqJR2CNXNhXcEbz6UGCQfrKCtkxOpJTftWc8RGouroHG0Nud1SJAszvpmA==} + '@rushstack/node-core-library@5.23.1': + resolution: {integrity: sha512-wlKmIKIYCKuCASbITvOxLZXepPbwXvrv7S6ig6XNWFchSyhL/E2txmVXspHY49Wu2dzf7nI27a2k/yV5BA3EiA==} peerDependencies: '@types/node': '*' peerDependenciesMeta: '@types/node': optional: true - '@rushstack/problem-matcher@0.1.1': - resolution: {integrity: sha512-Fm5XtS7+G8HLcJHCWpES5VmeMyjAKaWeyZU5qPzZC+22mPlJzAsOxymHiWIfuirtPckX3aptWws+K2d0BzniJA==} + '@rushstack/problem-matcher@0.2.1': + resolution: {integrity: sha512-gulfhBs6n+I5b7DvjKRfhMGyUejtSgOHTclF/eONr8hcgF1APEDjhxIsfdUYYMzC3rvLwGluqLjbwCFZ8nxrog==} peerDependencies: '@types/node': '*' peerDependenciesMeta: '@types/node': optional: true - '@rushstack/rig-package@0.6.0': - resolution: {integrity: sha512-ZQmfzsLE2+Y91GF15c65L/slMRVhF6Hycq04D4TwtdGaUAbIXXg9c5pKA5KFU7M4QMaihoobp9JJYpYcaY3zOw==} + '@rushstack/rig-package@0.7.3': + resolution: {integrity: sha512-aAA518n6wxxjCfnTAOjQnm7ngNE0FVHxHAw2pxKlIhxrMn0XQjGcXKF0oKWpjBgJOmsaJpVob/v+zr3zxgPWuA==} - '@rushstack/terminal@0.19.5': - resolution: {integrity: sha512-6k5tpdB88G0K7QrH/3yfKO84HK9ggftfUZ51p7fePyCE7+RLLHkWZbID9OFWbXuna+eeCFE7AkKnRMHMxNbz7Q==} + '@rushstack/terminal@0.24.0': + resolution: {integrity: sha512-8ZQS4MMaGsv27EXCBiH7WMPkRZrffeDoIevs6z9TM5dzqiY6+Hn4evfK/G+gvgBTjfvfkHIZPQQmalmI2sM4TQ==} peerDependencies: '@types/node': '*' peerDependenciesMeta: '@types/node': optional: true - '@rushstack/ts-command-line@5.1.5': - resolution: {integrity: sha512-YmrFTFUdHXblYSa+Xc9OO9FsL/XFcckZy0ycQ6q7VSBsVs5P0uD9vcges5Q9vctGlVdu27w+Ct6IuJ458V0cTQ==} + '@rushstack/ts-command-line@5.3.9': + resolution: {integrity: sha512-GIHqU+sRGQ3LGWAZu1O+9Yh++qwtyNIIGuNbcWHJjBTm2qRez0cwINUHZ+pQLR8UuzZDcMajrDaNbUYoaL/XtQ==} '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} @@ -1382,24 +1397,28 @@ packages: peerDependencies: semantic-release: '>=18.0.0' - '@semantic-release/github@12.0.2': - resolution: {integrity: sha512-qyqLS+aSGH1SfXIooBKjs7mvrv0deg8v+jemegfJg1kq6ji+GJV8CO08VJDEsvjp3O8XJmTTIAjjZbMzagzsdw==} + '@semantic-release/github@12.0.8': + resolution: {integrity: sha512-tej5AAgK5X9wHRoDmYhecMXEHEkFeGOY1XsEblKxu8pIQwahzf1STYyr7iPU6Lpbg6C5I3N2w/ocXrBo+L7jhw==} engines: {node: ^22.14.0 || >= 24.10.0} peerDependencies: semantic-release: '>=24.1.0' - '@semantic-release/npm@13.1.1': - resolution: {integrity: sha512-c4tlp3STYaTYORmMcLjiTaI8SLoxJ0Uf7IXkem8EyihuOM624wnaGuH4OuY2HHcsHDerNAQNzZ8VO6d4PMHSzA==} + '@semantic-release/npm@13.1.5': + resolution: {integrity: sha512-Hq5UxzoatN3LHiq2rTsWS54nCdqJHlsssGERCo8WlvdfFA9LoN0vO+OuKVSjtNapIc/S8C2LBj206wKLHg62mg==} engines: {node: ^22.14.0 || >= 24.10.0} peerDependencies: semantic-release: '>=20.1.0' - '@semantic-release/release-notes-generator@14.1.0': - resolution: {integrity: sha512-CcyDRk7xq+ON/20YNR+1I/jP7BYKICr1uKd1HHpROSnnTdGqOTburi4jcRiTYz0cpfhxSloQO3cGhnoot7IEkA==} + '@semantic-release/release-notes-generator@14.1.1': + resolution: {integrity: sha512-Pbd2e2XRMUD0OxehHpgd5/YghsE76cddkRHSoDvKLK+OCy4Ewxn49rWR631MEUU01lgwF/uyVXvbnVuu6+Z6VA==} engines: {node: '>=20.8.1'} peerDependencies: semantic-release: '>=20.1.0' + '@simple-libs/stream-utils@1.2.0': + resolution: {integrity: sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==} + engines: {node: '>=18'} + '@sindresorhus/is@4.6.0': resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} @@ -1408,14 +1427,17 @@ packages: resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} - '@standard-schema/spec@1.0.0': - resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - '@tanstack/query-core@5.90.20': - resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==} + '@swc/helpers@0.5.23': + resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==} - '@tanstack/react-query@5.90.21': - resolution: {integrity: sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg==} + '@tanstack/query-core@5.101.0': + resolution: {integrity: sha512-cQetA74EB+seWySv1TTKr828TnP0u39m6LykwDXIo84SNortpDkp30TMEjkqtYCNP9c40uT/iwl6MLiufEt0Ow==} + + '@tanstack/react-query@5.101.0': + resolution: {integrity: sha512-rLlJXSpkqfizLWgkR5+eLeIk0MvTx/meEIR7LRjxic+qxiQP8zVjq7BqQkiCMNLQBlLfuOLqqr6KO5GtrDlmSg==} peerDependencies: react: ^18 || ^19 @@ -1443,53 +1465,158 @@ packages: '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - '@types/babel__generator@7.6.8': - resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} '@types/babel__template@7.4.4': resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - '@types/babel__traverse@7.20.6': - resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} - '@types/brotli@1.3.4': - resolution: {integrity: sha512-cKYjgaS2DMdCKF7R0F5cgx1nfBYObN2ihIuPGQ4/dlIY6RpV7OWNwe9L8V4tTVKL2eZqOkNM9FM/rgTvLf4oXw==} + '@types/brotli@1.3.5': + resolution: {integrity: sha512-9xoNr+bcxT236/7ZgcWw/6Pb2RRetE13p4bFy1xYSckKwyOiRfmInay8baUWZgH7/284Wl6IPe7+nOI9+OQg/A==} '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/command-line-args@5.2.3': + resolution: {integrity: sha512-uv0aG6R0Y8WHZLTamZwtfsDLVRnOa+n+n5rEvFWL5Na5gZ8V2Teab/duDPFzIIIhs9qizDpcavCusCLJZu62Kw==} + + '@types/command-line-usage@5.0.4': + resolution: {integrity: sha512-BwR5KP3Es/CSht0xqBcUXS3qCAUVXwpRKsV2+arxeb65atasuXG9LykC9Ab10Cw3s2raH92ZqOeILaQbsB2ACg==} + '@types/crypto-js@4.2.2': resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==} - '@types/d3-array@3.2.1': - resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} + '@types/d3-array@3.2.2': + resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} + + '@types/d3-axis@3.0.6': + resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==} + + '@types/d3-brush@3.0.6': + resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==} + + '@types/d3-chord@3.0.6': + resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==} '@types/d3-color@1.4.5': resolution: {integrity: sha512-5sNP3DmtSnSozxcjqmzQKsDOuVJXZkceo1KJScDc1982kk/TS9mTPc6lpli1gTu1MIBF1YWutpHpjucNWcIj5g==} + '@types/d3-color@3.1.3': + resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} + + '@types/d3-contour@3.0.6': + resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==} + + '@types/d3-delaunay@6.0.4': + resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==} + + '@types/d3-dispatch@3.0.7': + resolution: {integrity: sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==} + + '@types/d3-drag@3.0.7': + resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==} + + '@types/d3-dsv@3.0.7': + resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==} + + '@types/d3-ease@3.0.2': + resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} + + '@types/d3-fetch@3.0.7': + resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==} + + '@types/d3-force@3.0.10': + resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==} + + '@types/d3-format@3.0.4': + resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==} + + '@types/d3-geo@3.1.0': + resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} + + '@types/d3-hierarchy@3.1.1': + resolution: {integrity: sha512-QwjxA3+YCKH3N1Rs3uSiSy1bdxlLB1uUiENXeJudBoAFvtDuswUxLcanoOaR2JYn1melDTuIXR8VhnVyI3yG/A==} + + '@types/d3-interpolate@3.0.4': + resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} + + '@types/d3-path@1.0.11': + resolution: {integrity: sha512-4pQMp8ldf7UaB/gR8Fvvy69psNHkTpD/pVw3vmEi8iZAB9EPMBruB1JvHO4BIq9QkUUd2lV1F5YXpMNj7JPBpw==} + + '@types/d3-path@3.1.1': + resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==} + + '@types/d3-polygon@3.0.2': + resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==} + + '@types/d3-quadtree@3.0.6': + resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==} + + '@types/d3-random@3.0.3': + resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==} + + '@types/d3-sankey@0.11.2': + resolution: {integrity: sha512-U6SrTWUERSlOhnpSrgvMX64WblX1AxX6nEjI2t3mLK2USpQrnbwYYK+AS9SwiE7wgYmOsSSKoSdr8aoKBH0HgQ==} + + '@types/d3-scale-chromatic@3.1.0': + resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} + '@types/d3-scale@3.3.5': resolution: {integrity: sha512-YOpKj0kIEusRf7ofeJcSZQsvKbnTwpe1DUF+P2qsotqG53kEsjm7EzzliqQxMkAWdkZcHrg5rRhB4JiDOQPX+A==} + '@types/d3-scale@4.0.9': + resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==} + + '@types/d3-selection@3.0.11': + resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} + + '@types/d3-shape@1.3.12': + resolution: {integrity: sha512-8oMzcd4+poSLGgV0R1Q1rOlx/xdmozS4Xab7np0eamFFUYq71AU9pOCJEFnkXW2aI/oXdVYJzw6pssbSut7Z9Q==} + + '@types/d3-shape@3.1.8': + resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==} + + '@types/d3-time-format@4.0.3': + resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} + '@types/d3-time@2.1.4': resolution: {integrity: sha512-BTfLsxTeo7yFxI/haOOf1ZwJ6xKgQLT9dCp+EcmQv87Gox6X+oKl4mLKfO6fnWm3P22+A6DknMNEZany8ql2Rw==} + '@types/d3-time@3.0.4': + resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} + + '@types/d3-timer@3.0.2': + resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} + + '@types/d3-transition@3.0.9': + resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==} + + '@types/d3-zoom@3.0.8': + resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} + + '@types/d3@7.4.3': + resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==} + '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} - '@types/estree@1.0.7': - resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} '@types/geojson@7946.0.16': resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} - '@types/google.maps@3.58.1': - resolution: {integrity: sha512-X9QTSvGJ0nCfMzYOnaVs/k6/4L+7F5uCS+4iUmkLEls6J9S/Phv+m/i3mDeyc49ZBgwab3EFO1HEoBY7k98EGQ==} + '@types/google.maps@3.65.0': + resolution: {integrity: sha512-u4SHiRC3m27lPa4vDBxh2AI7mDcHcheX6GSHn1Mwi0Gap8/uhM2kFppiFTnWASXLHZO+1ahHciLeEIV+Sjqk/A==} '@types/hammerjs@2.0.46': resolution: {integrity: sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==} - '@types/node@24.3.0': - resolution: {integrity: sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==} + '@types/node@24.12.4': + resolution: {integrity: sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -1503,14 +1630,14 @@ packages: '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - '@types/prop-types@15.7.14': - resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} + '@types/polylabel@1.1.3': + resolution: {integrity: sha512-9Zw2KoDpi+T4PZz2G6pO2xArE0m/GSMTW1MIxF2s8ZY8x9XDO6fv9um0ydRGvcbkFLlaq8yNK6eZxnmMZtDgWQ==} '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} - '@types/react-dom@18.3.5': - resolution: {integrity: sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==} + '@types/react-dom@18.3.7': + resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==} peerDependencies: '@types/react': ^18.0.0 @@ -1519,63 +1646,66 @@ packages: peerDependencies: '@types/react': '*' - '@types/react@18.3.18': - resolution: {integrity: sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==} + '@types/react@18.3.30': + resolution: {integrity: sha512-3ek6mwJL5/VBewBcY4S66cqlCtK3qi4WIq37Z0m/NHw1hjhI7274Mx1qz/+ggSzyBCOEf7eHjBN6INjPAWYfYw==} '@types/sortablejs@1.15.9': resolution: {integrity: sha512-7HP+rZGE2p886PKV9c9OJzLBI6BBJu1O7lJGYnPyG3fS4/duUCcngkNCjsLwIMV+WMqANe3tt4irrXHSIe68OQ==} + '@types/svg-arc-to-cubic-bezier@3.2.3': + resolution: {integrity: sha512-UNOnbTtl0nVTm8hwKaz5R5VZRvSulFMGojO5+Q7yucKxBoCaTtS4ibSQVRHo5VW5AaRo145U8p1Vfg5KrYe9Bg==} + '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@vaadin/a11y-base@24.6.11': - resolution: {integrity: sha512-yBZ0QGPngbItIJQx3FRIa9IXDW2Ftf6SFFPGhbdAZafJPBlFi6FElP9cVtL3qjJlI5KKBp/UXEcC8ehPK207gw==} + '@vaadin/a11y-base@24.9.15': + resolution: {integrity: sha512-BgZRgVI4VMW/lEENvigbMZe0Cgez5AfVqT2fMW5FoYqAJHulck8cRkFE/bahulop1iQ34fH9kU86mg7qnjNoBg==} - '@vaadin/checkbox@24.6.11': - resolution: {integrity: sha512-Uvd6gZ3xQQrZTtCJL6f4uLbg6mXsAKjiZto7Je39yJwUHz8r5MIQr+4mLF4zc6mYVSH/Ihj/a4n9FOuTwSEuQw==} + '@vaadin/checkbox@24.9.15': + resolution: {integrity: sha512-1Y/E+LJMEZcQ03M4sgqVpXAX1F373I98ydZ63qeq1+K/x/TqE+cyfHOpKI/tmbgZz+2nmn2XJlQuiY+EyasFpQ==} - '@vaadin/component-base@24.6.11': - resolution: {integrity: sha512-7jR6vcJeCBgY2CNbAPLOcUTsxYspqdkA0slUGk3GwfgsRDD5FLkzqQDSM5+yE6O2+4Wah2Tk+kG/GsKGtlUlwg==} + '@vaadin/component-base@24.9.15': + resolution: {integrity: sha512-db1aG+TvOd5r4H2Sfj1tKr9w5B7sRi5qsBMKnbuNg9KnBlqaU1EIKG5+WbD28UdGk/+0OfwNo3my9a60O3a/RQ==} - '@vaadin/field-base@24.6.11': - resolution: {integrity: sha512-dRjxKzbW3xQAau1xuO8uZepVWaImS2wEyKDK9Oh+y8iiu4smYEmo9e4aqMqQN/sOHU6OSa4YtbyJZlvD1sBXrA==} + '@vaadin/field-base@24.9.15': + resolution: {integrity: sha512-czcNaONALqkyJKv7tAkzTUdKQC+osnYCRKRFm9LS/XqAt+gzeqybLdHocSlNutFq7PSG/IvHeoXM+ZNE29zWtQ==} - '@vaadin/grid@24.6.11': - resolution: {integrity: sha512-10ra384y81iIPwrVCsJwZda4vrdVeDk7SaZSXHe+pM8dVNAvBfmCNomdc9XdC6Q289GHt1AHn/3SaN+G3Wr7FQ==} + '@vaadin/grid@24.9.15': + resolution: {integrity: sha512-YpUNnzBffn4r6CPNP1EBrgqbafJQPrbz8YS6aZbSAh5O+Moc2zANCFnxf37FRZX71V+DuIzMOB4qA47Uc2Zyuw==} - '@vaadin/icon@24.6.11': - resolution: {integrity: sha512-CKOh+I84+GZRfMHrhtATtrw3bSW5eUArgGT4cKsOY3asoCZXUdTObPD/PqKfP4e2uAA1bgLl27kOc+W8dmibJA==} + '@vaadin/icon@24.9.15': + resolution: {integrity: sha512-Z2HmxAWMqHISyXMuSHjc7b0Nkq0jeGrUHQ7yUKGkEIdRjXaY+4WfPjSPTACLodACla370bxUBjkizQOzMEtvEg==} - '@vaadin/input-container@24.6.11': - resolution: {integrity: sha512-fT1DK1QDp6VNKaHKkHxuuF3OlbNWbZOtK9IcLs3Q78/9jzhs8gg/nhIbQbyvhIhvjjHncIhzp0vPiw1l7Xxl+Q==} + '@vaadin/input-container@24.9.15': + resolution: {integrity: sha512-pQ/Lq1hnMeXXuen3ijKYIykSJ/GVnxZlhHalv3dDWMBazNa43DvahSD+0kK5/IMh1NTM8Y8DlLbWhbiXIKaCNg==} - '@vaadin/lit-renderer@24.6.11': - resolution: {integrity: sha512-JugFumbBQP4r28+HcbdDUVVGs5VRsqanLsifjkVrz/xb4saWv460lEYco5ES+StH+xZ2IuJZmEjEFUBSrVR/tA==} + '@vaadin/lit-renderer@24.9.15': + resolution: {integrity: sha512-Gvg63xSiA6I+0GXmA4O3VjyoWAvizHbB8lsTdfZ/NzPGm26sV04fKe0lsiQAcR1aNGVJY7W36LH2t+9u18kFCQ==} - '@vaadin/text-field@24.6.11': - resolution: {integrity: sha512-pqDPTf5AGwz5CcMfyFmF2215WzwWpjfudKlCje6u2qOcA/9kqBYCTQolemVYCtMDwn0yHXFSp4dU8UasxMCUJA==} + '@vaadin/text-field@24.9.15': + resolution: {integrity: sha512-YzxpyOXAX88ee8OztmjN9d9TfSHeSIQ4ka5tDU7eYFOFNU44lHUxdVqIwuw8arGNQfUneC7SOi1mSGF6JXbcGA==} '@vaadin/vaadin-development-mode-detector@2.0.7': resolution: {integrity: sha512-9FhVhr0ynSR3X2ao+vaIEttcNU5XfzCbxtmYOV8uIRnUCtNgbvMOIcyGBvntsX9I5kvIP2dV3cFAOG9SILJzEA==} - '@vaadin/vaadin-lumo-styles@24.6.11': - resolution: {integrity: sha512-WRluczao8lZgImdtl66v09YjFULb1iLAhcU48aiR9igAT7h6aLeHYBvRH3AA/gBlUNwHd4xlBSl89p4HP2GGog==} + '@vaadin/vaadin-lumo-styles@24.9.15': + resolution: {integrity: sha512-CMr2Xwu5kRMu/cvcPf5ODPCJY2bcmsVv+RkQGDxdM0UEJz96T9ztxg2yjUaA/06DJceyQy0u/GYjTSFOggNy4w==} - '@vaadin/vaadin-material-styles@24.6.11': - resolution: {integrity: sha512-tDumwlaDp/s9u++MPi64I1o2ls/drWOZf4xVPhztUjt3NwYJUeVXtwu39q0wBRIeRM7UBrs06kug2CVT72U4qQ==} + '@vaadin/vaadin-material-styles@24.9.15': + resolution: {integrity: sha512-uAqr3FbbjXgVz89RJ6n5VF96gdjv3LuT0VUMWu8Zg6bFp9pwq4wn3Nn+ILfEWvSrHx1zAlEkwV9UIVybVd/pFw==} - '@vaadin/vaadin-themable-mixin@24.6.11': - resolution: {integrity: sha512-xCmn3X+2C7nI9LQn2OqLLkLw7VeJOCo99DlHwnxeLZpJJ/s8bjDXcIWflS+IOChzHixgEFkDSoLcNYoCR1RvYg==} + '@vaadin/vaadin-themable-mixin@24.9.15': + resolution: {integrity: sha512-RtEO1Fu0Prpa+dN9uIm1lMqs2MFPLV/JiZitcFZLHMnS4PnNC/Fadc1oThmmtvjre/HyJuAaukyRo4c1jHdDNA==} '@vaadin/vaadin-usage-statistics@2.1.3': resolution: {integrity: sha512-8r4TNknD7OJQADe3VygeofFR7UNAXZ2/jjBFP5dgI8+2uMfnuGYgbuHivasKr9WSQ64sPej6m8rDoM1uSllXjQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - '@vitejs/plugin-react@4.3.4': - resolution: {integrity: sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==} + '@vitejs/plugin-react@4.7.0': + resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 '@vitest/coverage-v8@4.0.15': resolution: {integrity: sha512-FUJ+1RkpTFW7rQITdgTi93qOCWJobWhBirEPCeXh2SW2wsTlFxy51apDz5gzG+ZEYt/THvWeNmhdAoS9DTwpCw==} @@ -1586,14 +1716,14 @@ packages: '@vitest/browser': optional: true - '@vitest/expect@3.2.4': - resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + '@vitest/expect@3.2.6': + resolution: {integrity: sha512-1+7q9BtaKzEmO+fmNT3kYvoNn5Y71XWAx2Q5HRim4tTVRQVRv4uJFAQ5FbK0OPUeNP/WmVCpxYxoJdvuHVjzBQ==} - '@vitest/expect@4.0.15': - resolution: {integrity: sha512-Gfyva9/GxPAWXIWjyGDli9O+waHDC0Q0jaLdFP1qPAUUfo1FEXPXUfUkp3eZA0sSq340vPycSyOlYUeM15Ft1w==} + '@vitest/expect@4.1.8': + resolution: {integrity: sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==} - '@vitest/mocker@3.2.4': - resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + '@vitest/mocker@3.2.6': + resolution: {integrity: sha512-EZOrpDbkKotFAP7wPAQV1UIyoGOk4oX7ynWhBhLB7v+meMHbQhU16oPpIYGTTe4oFlhpryGpgpcZP/sin3hYuw==} peerDependencies: msw: ^2.4.9 vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 @@ -1603,57 +1733,66 @@ packages: vite: optional: true - '@vitest/mocker@4.0.15': - resolution: {integrity: sha512-CZ28GLfOEIFkvCFngN8Sfx5h+Se0zN+h4B7yOsPVCcgtiO7t5jt9xQh2E1UkFep+eb9fjyMfuC5gBypwb07fvQ==} + '@vitest/mocker@4.1.8': + resolution: {integrity: sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==} peerDependencies: msw: ^2.4.9 - vite: ^6.0.0 || ^7.0.0-0 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@3.2.4': - resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + '@vitest/pretty-format@3.2.6': + resolution: {integrity: sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==} '@vitest/pretty-format@4.0.15': resolution: {integrity: sha512-SWdqR8vEv83WtZcrfLNqlqeQXlQLh2iilO1Wk1gv4eiHKjEzvgHb2OVc3mIPyhZE6F+CtfYjNlDJwP5MN6Km7A==} - '@vitest/runner@3.2.4': - resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} + '@vitest/pretty-format@4.1.8': + resolution: {integrity: sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==} + + '@vitest/runner@3.2.6': + resolution: {integrity: sha512-HYcoSj1w5tcgUnzoF0HcyaAQjpA1gj9ftUJ7iSJSuipc02jW9gKkigwZbjFldAfYHA1fa8UZVRftdMY5msWM9Q==} - '@vitest/runner@4.0.15': - resolution: {integrity: sha512-+A+yMY8dGixUhHmNdPUxOh0la6uVzun86vAbuMT3hIDxMrAOmn5ILBHm8ajrqHE0t8R9T1dGnde1A5DTnmi3qw==} + '@vitest/runner@4.1.8': + resolution: {integrity: sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==} - '@vitest/snapshot@3.2.4': - resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} + '@vitest/snapshot@3.2.6': + resolution: {integrity: sha512-H+ZjNTWGpObenh0YnlBctAPnJSI20P81PL8BPzWpx54YXLLTm8hEsWawtcYLMrwvpK48hGxLLbCS+1KRXhsKhw==} - '@vitest/snapshot@4.0.15': - resolution: {integrity: sha512-A7Ob8EdFZJIBjLjeO0DZF4lqR6U7Ydi5/5LIZ0xcI+23lYlsYJAfGn8PrIWTYdZQRNnSRlzhg0zyGu37mVdy5g==} + '@vitest/snapshot@4.1.8': + resolution: {integrity: sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==} - '@vitest/spy@3.2.4': - resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + '@vitest/spy@3.2.6': + resolution: {integrity: sha512-oq6BbH68WzcWmwtBrU9nqLeaXTR4XwJF7FSLkKEZo4i6eoXcrxjcwSuTvWBIRUTC6VC72nXYunzqgZA+IKdtxg==} - '@vitest/spy@4.0.15': - resolution: {integrity: sha512-+EIjOJmnY6mIfdXtE/bnozKEvTC4Uczg19yeZ2vtCz5Yyb0QQ31QWVQ8hswJ3Ysx/K2EqaNsVanjr//2+P3FHw==} + '@vitest/spy@4.1.8': + resolution: {integrity: sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==} - '@vitest/utils@3.2.4': - resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + '@vitest/utils@3.2.6': + resolution: {integrity: sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==} '@vitest/utils@4.0.15': resolution: {integrity: sha512-HXjPW2w5dxhTD0dLwtYHDnelK3j8sR8cWIaLxr22evTyY6q8pRCjZSmhRWVjBaOVXChQd6AwMzi9pucorXCPZA==} + '@vitest/utils@4.1.8': + resolution: {integrity: sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==} + '@vivjs/constants@0.17.2': resolution: {integrity: sha512-3WtCojnlAMXLtmGIxr71njKde3BM2XjqM61tRpRW6+PZ221EnGL0UP80Od5iWt1j1+8SdISDVjfYtjUhP8FxVw==} - '@vivjs/extensions@0.17.2': - resolution: {integrity: sha512-e0KXcMDppxWum3pKGnK+4uojciQwcFOqTbSd05nOi4xsEag/z3rSbhq5H87XnKiDS1CL2L+ggJk6Uhlpxca3Xg==} + '@vivjs/constants@0.17.3': + resolution: {integrity: sha512-6HUBlTHhHexuFNOCfmVQjixZyvRWD7mbu0TjRbgNB2eQ5OyS2vyYc1iYzxH+Yzx3vJmR1/RS5S4lLGAfJVP3Pw==} + + '@vivjs/extensions@0.17.3': + resolution: {integrity: sha512-d0uVIDR9L0pglY4JV/4XpNl1/KXTOSM4xjwPQJuJnVZ8IqrjPAKt0T/XwZyzDCq7tytiQ5BmJ7JGRwK7y4+paA==} peerDependencies: '@deck.gl/core': ~9.0.33 - '@vivjs/layers@0.17.2': - resolution: {integrity: sha512-jNUinNGjeIXhkxQ4+6vqb+g+oDGe0j2s3qC9oUJDGsUhJ44RNUClVPgdk1rUxzveKMhkhWHuRzNQpV2VHq32UQ==} + '@vivjs/layers@0.17.3': + resolution: {integrity: sha512-1onQDuaGOSZaxnTDVyGmKHWbT9FyTQ6Ay5o3FrpePvH70X69uXnoxL2ZqgdyNywaQ3lMdJFafpqnzEHqA5hNcw==} peerDependencies: '@deck.gl/core': ~9.0.33 '@deck.gl/geo-layers': ~9.0.33 @@ -1667,35 +1806,41 @@ packages: '@vivjs/loaders@0.17.2': resolution: {integrity: sha512-6TEUsguAlRAQuTUtqirC/2XVf2obDnuV6CVWBXFtFx7fDJPW0p3RBzJpztyAiqYSqTDHcDzhXOKb2RfBKGeSQQ==} + '@vivjs/loaders@0.17.3': + resolution: {integrity: sha512-jinDvmfWPxnN53nDEpv6PIPDws1RyHMobkWQK8Rr4glFFwzglsv0av/HWH8Q4plLcNuESdlj6hqWIVtdgGbtaA==} + '@vivjs/types@0.17.2': resolution: {integrity: sha512-ta63o+5QZfPBnDA4dTwPZKwNhwWne/FBfMMlKymuwrWFzWatGIjA42eTk0QbF4iWqzPcJDEC6BoCmyrx5TM91A==} - '@vivjs/viewers@0.17.2': - resolution: {integrity: sha512-e6RJKz66uLMkPLK80gOtEF5Zz+Vqb+lUXyI0bikzdO5u4Xck6GMNpgEQFoar1xAle94KUm0jk/HeaZZ/QkXiuA==} + '@vivjs/types@0.17.3': + resolution: {integrity: sha512-6JyfF9lQRdWpDK+KtYchgCZ++mbOHC1eGg42ZsCgVa1kzseyzfJ1C/ubUmXRiL/kSLpYeYPqoe5f7S4wDGAO9g==} + + '@vivjs/viewers@0.17.3': + resolution: {integrity: sha512-nxATO6UcZUwO/zrO0eHJi5VgjvNHUq2kG03rUZRtC/oNiBq+O3etg1vudCmpbjcicKnQtqSk8zXRoQZKFLpniw==} peerDependencies: '@deck.gl/react': ~9.0.33 react: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@vivjs/views@0.17.2': - resolution: {integrity: sha512-yggC8zhCNzJMNT4FyG3nu/8ZQ2tUrsXz1eYi/4Lnuyl3LxOSgy/pVofpbg9uCi9QhFaqMlTcQAAQ0rTOqPNGcA==} + '@vivjs/views@0.17.3': + resolution: {integrity: sha512-cbaEuIwfnTuUm0FbYje+1HwXOcVhsMGh8spKr9AS6TR/Jajz7Nb4CktuIO0SjMoaVVu+QnU1wu3QNQZL7bZX/w==} peerDependencies: '@deck.gl/core': ~9.0.33 '@deck.gl/layers': ~9.0.33 - '@volar/language-core@2.4.26': - resolution: {integrity: sha512-hH0SMitMxnB43OZpyF1IFPS9bgb2I3bpCh76m2WEK7BE0A0EzpYsRp0CCH2xNKshr7kacU5TQBLYn4zj7CG60A==} + '@volar/language-core@2.4.28': + resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==} - '@volar/source-map@2.4.26': - resolution: {integrity: sha512-JJw0Tt/kSFsIRmgTQF4JSt81AUSI1aEye5Zl65EeZ8H35JHnTvFGmpDOBn5iOxd48fyGE+ZvZBp5FcgAy/1Qhw==} + '@volar/source-map@2.4.28': + resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==} - '@volar/typescript@2.4.26': - resolution: {integrity: sha512-N87ecLD48Sp6zV9zID/5yuS1+5foj0DfuYGdQ6KHj/IbKvyKv1zNX6VCmnKYwtmHadEO6mFc2EKISiu3RDPAvA==} + '@volar/typescript@2.4.28': + resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==} - '@vue/compiler-core@3.5.25': - resolution: {integrity: sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==} + '@vue/compiler-core@3.5.35': + resolution: {integrity: sha512-BUmHaR1J+O+CKZ9uJucdVTEr1LHsdyvv7vG3eNRhK3CczEHeMd/LtsHAuD7PbrxvI2envCY2v7HI1vC1aBRzKw==} - '@vue/compiler-dom@3.5.25': - resolution: {integrity: sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==} + '@vue/compiler-dom@3.5.35': + resolution: {integrity: sha512-k+bprkXxuqhVajgTx5mUHuir7TwQzUKOWR40ng1ncAqQRPnrLngGGgqVEEhOnTMlc8btHYVKmrP8s5Qyg0hvYA==} '@vue/compiler-vue2@2.7.16': resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} @@ -1708,8 +1853,8 @@ packages: typescript: optional: true - '@vue/shared@3.5.25': - resolution: {integrity: sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==} + '@vue/shared@3.5.35': + resolution: {integrity: sha512-zSbjL7gRXwks2ZQLRGCajBtBXEOXW9Ddhn/HvSdrGkE2dqGnumzW8XtusRrxrE9LvqtiqDXQ+A60Hp6mvdYxfA==} '@webcomponents/shadycss@1.11.2': resolution: {integrity: sha512-vRq+GniJAYSBmTRnhCYPAPq6THYqovJ/gzGThWbgEZUQaBccndGTi1hdiUP15HzEco0I6t4RCtXyX0rsSmwgPw==} @@ -1717,18 +1862,18 @@ packages: '@zarrita/storage@0.1.4': resolution: {integrity: sha512-qURfJAQcQGRfDQ4J9HaCjGaj3jlJKc66bnRk6G/IeLUsM7WKyG7Bzsuf1EZurSXyc0I4LVcu6HaeQQ4d3kZ16g==} - '@zip.js/zip.js@2.7.73': - resolution: {integrity: sha512-I2UP8/rdQE5hTtVVL08B7P8XuwXiKuuMUPjNuFOVL/9b+8IsExR9S5jz2H58u0rJjU4M1BikLgqEMG8gZJZVBw==} - engines: {bun: '>=0.7.0', deno: '>=1.0.0', node: '>=16.5.0'} + '@zip.js/zip.js@2.8.26': + resolution: {integrity: sha512-RQ4h9F6DOiHxpdocUDrOl6xBM+yOtz+LkUol47AVWcfebGBDpZ7w7Xvz9PS24JgXvLGiXXzSAfdCdVy1tPlaFA==} + engines: {bun: '>=0.7.0', deno: '>=1.0.0', node: '>=18.0.0'} - acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} engines: {node: '>=0.4.0'} hasBin: true - agent-base@7.1.4: - resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} - engines: {node: '>= 14'} + agent-base@9.0.0: + resolution: {integrity: sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==} + engines: {node: '>= 20'} aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} @@ -1754,17 +1899,14 @@ packages: ajv: optional: true - ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - - ajv@8.13.0: - resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} alien-signals@0.4.14: resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} - ansi-escapes@7.2.0: - resolution: {integrity: sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==} + ansi-escapes@7.3.0: + resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} engines: {node: '>=18'} ansi-regex@5.0.1: @@ -1790,6 +1932,10 @@ packages: any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + apache-arrow@21.1.0: + resolution: {integrity: sha512-kQrYLxhC+NTVVZ4CCzGF6L/uPVOzJmD1T3XgbiUnP7oTeVFOFgEUu6IKNwCDkpFoBVqDKQivlX4RUFqqnWFlEA==} + hasBin: true + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -1799,6 +1945,10 @@ packages: argv-formatter@1.0.0: resolution: {integrity: sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==} + array-back@6.2.3: + resolution: {integrity: sha512-SGDvmg6QTYiTxCBkYVmThcoa67uLl35pyzRHdpCGBOcqFy6BtwnphoFPk7LhJshD+Yk1Kt35WGWeZPTgwR4Fhw==} + engines: {node: '>=12.17'} + array-ify@1.0.0: resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} @@ -1816,17 +1966,33 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + base64-js@1.3.1: + resolution: {integrity: sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + baseline-browser-mapping@2.10.33: + resolution: {integrity: sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==} + engines: {node: '>=6.0.0'} + hasBin: true + before-after-hook@4.0.0: resolution: {integrity: sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==} bottleneck@2.19.5: resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} - brace-expansion@2.0.2: - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + brace-expansion@2.1.1: + resolution: {integrity: sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==} + + brace-expansion@5.0.6: + resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} + engines: {node: 18 || 20 || >=22} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -1835,8 +2001,11 @@ packages: brotli@1.3.3: resolution: {integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==} - browserslist@4.24.4: - resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + browserify-zlib@0.2.0: + resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} + + browserslist@4.28.2: + resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1848,12 +2017,24 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001703: - resolution: {integrity: sha512-kRlAGTRWgPsOj7oARC9m1okJEXdL/8fekFVcxA8Hl7GH4r/sN4OJn/i6Flde373T50KS7Y37oFbMwlE8+F42kQ==} + caniuse-lite@1.0.30001793: + resolution: {integrity: sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==} cartocolor@5.0.2: resolution: {integrity: sha512-Ihb/wU5V6BVbHwapd8l/zg7bnhZ4YPFVfa7quSpL86lfkPJSf4YuNBT+EvesPRP5vSqhl6vZVsQJwCR8alBooQ==} @@ -1862,10 +2043,14 @@ packages: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} engines: {node: '>=18'} - chai@6.2.1: - resolution: {integrity: sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} + chalk-template@0.4.0: + resolution: {integrity: sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==} + engines: {node: '>=12'} + chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -1913,6 +2098,10 @@ packages: resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} engines: {node: '>=20'} + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + clsx@1.2.1: resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} engines: {node: '>=6'} @@ -1953,9 +2142,26 @@ packages: colorbrewer@1.5.6: resolution: {integrity: sha512-fONg2pGXyID8zNgKHBlagW8sb/AMShGzj4rRJfz5biZ7iuHQZYquSCLE/Co1oSQFmt/vvwjyezJCejQl7FG/tg==} + command-line-args@6.0.2: + resolution: {integrity: sha512-AIjYVxrV9X752LmPDLbVYv8aMCuHPSLZJXEo2qo/xJfv+NYhaZ4sMSF01rM+gHPaMgvPM0l5D/F+Qx+i2WfSmQ==} + engines: {node: '>=12.20'} + peerDependencies: + '@75lb/nature': latest + peerDependenciesMeta: + '@75lb/nature': + optional: true + + command-line-usage@7.0.4: + resolution: {integrity: sha512-85UdvzTNx/+s5CkSgBm/0hzP80RFHAa7PsfeADE5ezZF3uHz3/Tqj9gIKGT9PTtpycc3Ua64T0oVulGfKxzfqg==} + engines: {node: '>=12.20.0'} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + compare-func@2.0.0: resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} @@ -1970,18 +2176,22 @@ packages: confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} - confbox@0.2.2: - resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} + confbox@0.2.4: + resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} config-chain@1.1.13: resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} - conventional-changelog-angular@8.1.0: - resolution: {integrity: sha512-GGf2Nipn1RUCAktxuVauVr1e3r8QrLP/B0lEUsFktmGqc3ddbQkhoJZHJctVU829U1c6mTSWftrVOCHaL85Q3w==} + content-type@2.0.0: + resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} engines: {node: '>=18'} - conventional-changelog-writer@8.2.0: - resolution: {integrity: sha512-Y2aW4596l9AEvFJRwFGJGiQjt2sBYTjPD18DdvxX9Vpz0Z7HQ+g1Z+6iYDAm1vR3QOJrDBkRHixHK/+FhkR6Pw==} + conventional-changelog-angular@8.3.1: + resolution: {integrity: sha512-6gfI3otXK5Ph5DfCOI1dblr+kN3FAm5a97hYoQkqNZxOaYa5WKfXH+AnpsmS+iUH2mgVC2Cg2Qw9m5OKcmNrIg==} + engines: {node: '>=18'} + + conventional-changelog-writer@8.4.0: + resolution: {integrity: sha512-HHBFkk1EECxxmCi4CTu091iuDpQv5/OavuCUAuZmrkWpmYfyD816nom1CvtfXJ/uYfAAjavgHvXHX291tSLK8g==} engines: {node: '>=18'} hasBin: true @@ -1989,8 +2199,8 @@ packages: resolution: {integrity: sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==} engines: {node: '>=18'} - conventional-commits-parser@6.2.1: - resolution: {integrity: sha512-20pyHgnO40rvfI0NGF/xiEoFMkXDtkF8FwHvk5BokoFoCuTQRI8vrNCNFWUOfuolKJMm1tPCHc8GgYEtr1XRNA==} + conventional-commits-parser@6.4.0: + resolution: {integrity: sha512-tvRg7FIBNlyPzjdG8wWRlPHQJJHI7DylhtRGeU9Lq+JuoPh5BKpPRX83ZdLrvXuOSu5Eo/e7SzOQhU4Hd2Miuw==} engines: {node: '>=18'} hasBin: true @@ -2015,8 +2225,8 @@ packages: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} - cosmiconfig@9.0.0: - resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + cosmiconfig@9.0.1: + resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} engines: {node: '>=14'} peerDependencies: typescript: '>=4.9.5' @@ -2031,6 +2241,9 @@ packages: crypt@0.0.2: resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + crypto-random-string@4.0.0: resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} engines: {node: '>=12'} @@ -2038,32 +2251,131 @@ packages: cssfilter@0.0.10: resolution: {integrity: sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==} - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + d3-array@2.12.1: + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} d3-array@3.2.4: resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} engines: {node: '>=12'} + d3-axis@3.0.0: + resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} + engines: {node: '>=12'} + + d3-brush@3.0.0: + resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} + engines: {node: '>=12'} + + d3-chord@3.0.1: + resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} + engines: {node: '>=12'} + d3-color@3.1.0: resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} engines: {node: '>=12'} - d3-format@3.1.0: - resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} + d3-contour@4.0.2: + resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} + engines: {node: '>=12'} + + d3-delaunay@6.0.4: + resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} + engines: {node: '>=12'} + + d3-dispatch@2.0.0: + resolution: {integrity: sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA==} + + d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + + d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + + d3-dsv@3.0.1: + resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} + engines: {node: '>=12'} + hasBin: true + + d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + + d3-fetch@3.0.1: + resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} + engines: {node: '>=12'} + + d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + + d3-format@3.1.2: + resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==} + engines: {node: '>=12'} + + d3-geo@3.1.1: + resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} engines: {node: '>=12'} d3-hexbin@0.2.2: resolution: {integrity: sha512-KS3fUT2ReD4RlGCjvCEm1RgMtp2NFZumdMu4DBzQK8AZv3fXRM6Xm8I4fSU07UXvH4xxg03NwWKWdvxfS/yc4w==} + d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + d3-interpolate@3.0.1: resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} engines: {node: '>=12'} + d3-path@1.0.9: + resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==} + + d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + + d3-polygon@2.0.0: + resolution: {integrity: sha512-MsexrCK38cTGermELs0cO1d79DcTsQRN7IWMJKczD/2kBjzNXxLUWP33qRF6VDpiLV/4EI4r6Gs0DAWQkE8pSQ==} + + d3-polygon@3.0.1: + resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} + engines: {node: '>=12'} + + d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + + d3-random@3.0.1: + resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} + engines: {node: '>=12'} + + d3-sankey@0.12.3: + resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==} + + d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} + d3-scale@4.0.2: resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} engines: {node: '>=12'} + d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + + d3-shape@1.3.7: + resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} + + d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + d3-time-format@4.1.0: resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} engines: {node: '>=12'} @@ -2072,17 +2384,38 @@ packages: resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} engines: {node: '>=12'} - de-indent@1.0.2: - resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + d3-timer@2.0.0: + resolution: {integrity: sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA==} - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} - engines: {node: '>=6.0'} + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + + d3-transition@3.0.1: + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + d3-selection: 2 - 3 + + d3-voronoi-map@2.1.1: + resolution: {integrity: sha512-mCXfz/kD9IQxjHaU2IMjkO8fSo4J6oysPR2iL+omDsCy1i1Qn6BQ/e4hEAW8C6ms2kfuHwqtbNom80Hih94YsA==} + + d3-voronoi-treemap@1.1.2: + resolution: {integrity: sha512-7odu9HdG/yLPWwzDteJq4yd9Q/NwgQV7IE/u36VQtcCK7k1sZwDqbkHCeMKNTBsq5mQjDwolTsrXcU0j8ZEMCA==} + + d3-weighted-voronoi@1.1.3: + resolution: {integrity: sha512-C3WdvSKl9aqhAy+f3QT3PPsQG6V+ajDfYO3BSclQDSD+araW2xDBFIH67aKzsSuuuKaX8K2y2dGq1fq/dWTVig==} + + d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + + d3@7.9.0: + resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} + engines: {node: '>=12'} + + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} @@ -2111,6 +2444,10 @@ packages: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} + deep-equal@1.1.2: + resolution: {integrity: sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==} + engines: {node: '>= 0.4'} + deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -2119,8 +2456,22 @@ packages: resolution: {integrity: sha512-3daSWyvZ/zwJvuMGlzG1O+Ow0YSadGfb3jsh9xoCutv2tWyB9dA4YvR9L9/fSdDZa2dByYQe+TqapSGUrjnkoA==} engines: {node: '>=0.10.0'} - diff@8.0.2: - resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + delaunator@5.1.0: + resolution: {integrity: sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==} + + dfa@1.2.0: + resolution: {integrity: sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==} + + diff@8.0.4: + resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} engines: {node: '>=0.3.1'} dir-glob@3.0.1: @@ -2137,14 +2488,18 @@ packages: draco3d@1.5.7: resolution: {integrity: sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==} + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + duplexer2@0.1.4: resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} earcut@2.2.4: resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==} - electron-to-chromium@1.5.114: - resolution: {integrity: sha512-DFptFef3iktoKlFQK/afbo274/XNWD00Am0xa7M8FZUepHlHT8PEuiNBoRfFHbH1okqN58AlhbJ4QTkcnXorjA==} + electron-to-chromium@1.5.366: + resolution: {integrity: sha512-OlRuhb688YTCzzU3gXPLn6nGyd+F+53INE1qaKKlu6kETErE8FYsyDh0XqXEU+uBRn0MpCzz2vfNwORhkap8qg==} emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -2155,8 +2510,8 @@ packages: emojilib@2.4.0: resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==} - entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} engines: {node: '>=0.12'} env-ci@11.2.0: @@ -2174,14 +2529,29 @@ packages: error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - es-toolkit@1.44.0: - resolution: {integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==} + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} - esbuild@0.25.3: - resolution: {integrity: sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==} + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + es-toolkit@1.47.0: + resolution: {integrity: sha512-n1GuoD0WEQZMBk5tttoZSqwgyLx01oqa5XsBmCHwPyNe1S9jPBEmtR2pSgp2kJuWE3ciFZ6yRHmY4pM4C3OOkw==} + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} hasBin: true @@ -2211,8 +2581,8 @@ packages: estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} @@ -2222,8 +2592,8 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} - execa@9.6.0: - resolution: {integrity: sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==} + execa@9.6.1: + resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==} engines: {node: ^18.19.0 || >=20.5.0} expect-type@1.3.0: @@ -2233,14 +2603,17 @@ packages: exsolve@1.0.8: resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} - fast-content-type-parse@3.0.0: - resolution: {integrity: sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==} - fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-xml-parser@4.5.3: - resolution: {integrity: sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==} + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} + + fast-xml-builder@1.2.0: + resolution: {integrity: sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==} + + fast-xml-parser@5.8.0: + resolution: {integrity: sha512-6bIM7fsJxeo3uXv7OncQYsBAMPJ7V16Slahl/6M98C/i2q+vB1+4a0MtrvYwDFEUrwDSbAmeLDRXsOBwrL7yAg==} hasBin: true fdir@6.5.0: @@ -2255,8 +2628,8 @@ packages: fflate@0.7.4: resolution: {integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==} - fflate@0.8.2: - resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + fflate@0.8.3: + resolution: {integrity: sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==} figures@2.0.0: resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==} @@ -2270,6 +2643,15 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + find-replace@5.0.2: + resolution: {integrity: sha512-Y45BAiE3mz2QsrN2fb5QEtO4qb44NcS7en/0y9PEVsg351HsLeVclP8QPMH79Le9sH3rs5RSwJu99W0WPZO43Q==} + engines: {node: '>=14'} + peerDependencies: + '@75lb/nature': latest + peerDependenciesMeta: + '@75lb/nature': + optional: true + find-root@1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} @@ -2285,14 +2667,17 @@ packages: resolution: {integrity: sha512-2kCCtc+JvcZ86IGAz3Z2Y0A1baIz9fL31pH/0S1IqZr9Iwnjq8izfPtrCyQKO6TLMPELLsQMre7VDqeIKCsHkA==} engines: {node: '>=18'} + flatbuffers@25.9.23: + resolution: {integrity: sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==} + + flatpickr@4.6.13: + resolution: {integrity: sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==} + focus-trap@7.8.0: resolution: {integrity: sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==} - from2@2.3.0: - resolution: {integrity: sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==} - - fs-extra@11.3.2: - resolution: {integrity: sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==} + fs-extra@11.3.5: + resolution: {integrity: sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==} engines: {node: '>=14.14'} fsevents@2.3.3: @@ -2307,6 +2692,9 @@ packages: resolution: {integrity: sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA==} engines: {node: '>=18'} + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -2319,18 +2707,22 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-east-asian-width@1.4.0: - resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} + get-east-asian-width@1.6.0: + resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} engines: {node: '>=18'} + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - get-stream@7.0.1: - resolution: {integrity: sha512-3M8C1EOFN6r8AMUhwUAACIoXZJEOufDU5+0gFFN5uNs6XYOralD2Pqkl7m046va6x77FwposWXbAhPPIOus7mQ==} - engines: {node: '>=16'} - get-stream@8.0.1: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} @@ -2342,34 +2734,34 @@ packages: git-log-parser@1.2.1: resolution: {integrity: sha512-PI+sPDvHXNPl5WNOErAK05s3j0lgwUzMN6o8cyQrDaKfT3qd7TmNJKeXX+SknI5I0QhG5fVPAEwSY4tRGDtYoQ==} - gl-matrix@3.4.3: - resolution: {integrity: sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==} - - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} + gl-matrix@3.4.4: + resolution: {integrity: sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==} - goober@2.1.18: - resolution: {integrity: sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==} + goober@2.1.19: + resolution: {integrity: sha512-U7veizMqxyKlM58+Z5j2ngJBH/r9siDmxpvNxSw0PylF6WQvrASJEZrxh1hidRBJc2jqoBVSyOban5u8m+6Rxg==} peerDependencies: csstype: ^3.0.10 + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + graceful-fs@4.2.10: resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - h3-js@4.1.0: - resolution: {integrity: sha512-LQhmMl1dRQQjMXPzJc7MpZ/CqPOWWuAvVEoVJM9n/s7vHypj+c3Pd5rLQCkAsOgAoAYKbNCsYFE++LF7MvSfCQ==} + h3-js@4.4.0: + resolution: {integrity: sha512-DvJh07MhGgY2KcC4OeZc8SSyA+ZXpdvoh6uCzGpoKvWtZxJB+g6VXXC1+eWYkaMIsLz7J/ErhOalHCpcs1KYog==} engines: {node: '>=4', npm: '>=3', yarn: '>=1.3.0'} hammerjs@2.0.8: resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==} engines: {node: '>=0.8.0'} - handlebars@4.7.8: - resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + handlebars@4.7.9: + resolution: {integrity: sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==} engines: {node: '>=0.4.7'} hasBin: true @@ -2381,8 +2773,19 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} he@1.2.0: @@ -2403,20 +2806,20 @@ packages: resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} - hosted-git-info@9.0.2: - resolution: {integrity: sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==} + hosted-git-info@9.0.3: + resolution: {integrity: sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==} engines: {node: ^20.17.0 || >=22.9.0} html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} - engines: {node: '>= 14'} + http-proxy-agent@9.0.0: + resolution: {integrity: sha512-FcF8VhXYLQcxWCnt/cCpT2apKsRDUGeVEeMqGu4HSTu29U8Yw0TLOjdYIlDsYk3IkUh+taX4IDWpPcCqKDhCjA==} + engines: {node: '>= 20'} - https-proxy-agent@7.0.6: - resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} - engines: {node: '>= 14'} + https-proxy-agent@9.0.0: + resolution: {integrity: sha512-/MVmHp58WkOypgFhCLk4fzpPcFQvTJ/e6LBI7irpIO2HfxUbpmYoHF+KzipzJpxxzJu7aJNWQ0xojJ/dzV2G5g==} + engines: {node: '>= 20'} human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} @@ -2430,8 +2833,16 @@ packages: resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} engines: {node: '>=18.18.0'} - hyparquet@1.25.6: - resolution: {integrity: sha512-Q9W5IjkVch3ZMnYd4qFv2q8suu5Jc36yt7J+zUNM9grwnP1S189icp0jdEQKM5HJvQkTVy8NMiQ8n/dM5QAt1A==} + hyparquet@1.26.0: + resolution: {integrity: sha512-yxUiViPZ+z5h+xdX4rA1G+k30jXoEsG9I2xEpjaM84imGznbKjZzxuZFsdzqg6C4LxNnnAlDFvzpk4uxQWTbTQ==} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + engines: {node: '>=0.10.0'} ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -2480,13 +2891,16 @@ packages: interactjs@1.10.27: resolution: {integrity: sha512-y/8RcCftGAF24gSp76X2JS3XpHiUvDQyhF8i7ujemBz77hwiHDuJzftHx7thY8cxGogwGiPJ+o97kWB6eAXnsA==} + internmap@1.0.1: + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} + internmap@2.0.3: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} - into-stream@7.0.0: - resolution: {integrity: sha512-2dYz766i9HprMBasCMvHMuazJ7u4WzhJwo5kb3iPSiW/iRYV6uPari3zHoqZlnuaR7V1bEiNMxikhp37rdBXbw==} - engines: {node: '>=12'} + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -2494,8 +2908,12 @@ packages: is-buffer@1.1.6: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + is-core-module@2.16.2: + resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} engines: {node: '>= 0.4'} is-error@2.2.2: @@ -2517,6 +2935,10 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -2539,8 +2961,8 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - issue-parser@7.0.1: - resolution: {integrity: sha512-3YZcUUR2Wt1WsapF+S/WiA2WmlW0cWAoPccMqne7AxEBhCdFeTPjfv/Axb8V2gyCgY3nRw+ksZ3xSUX+R47iAg==} + issue-parser@7.0.2: + resolution: {integrity: sha512-7atWPjhGEIX3JEtMrOYd8TKzboYlq+5sNbdl9POiLYOI14G5HZiQbZP0Xj5EZdrufQVXfJlpTV0hys0CuxwxZw==} engines: {node: ^18.17 || >=20.6.1} istanbul-lib-coverage@3.2.2: @@ -2606,6 +3028,10 @@ packages: jotai-zustand: optional: true + jpeg-exif@1.1.4: + resolution: {integrity: sha512-a+bKEcCjtuW5WTdgeXFzswSrdqi0jk4XlEtZlx5A94wCoBpFjfFTbo/Tra5SpNCl/YFZPvcV1dJc+TAYeg6ROQ==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + js-tokens@10.0.0: resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} @@ -2615,8 +3041,8 @@ packages: js-tokens@9.0.1: resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + js-yaml@4.2.0: + resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} hasBin: true jsep@0.3.5: @@ -2628,6 +3054,10 @@ packages: engines: {node: '>=6'} hasBin: true + json-bignum@0.0.3: + resolution: {integrity: sha512-2WHyXj3OfHSgNyuzDbSxI1w2jgw5gkWSWhS7Qg4bWXx1nLk3jnbwfUeS0PSba3IzpTUWdHxBieELUzXRjQB2zg==} + engines: {node: '>=0.8'} + json-parse-better-errors@1.0.2: resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} @@ -2637,13 +3067,16 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-with-bigint@3.5.8: + resolution: {integrity: sha512-eq/4KP6K34kwa7TcFdtvnftvHCD9KvHOGGICWwMFc4dOOKF5t4iYqnfLK8otCRCRv06FXOzGGyqE8h8ElMvvdw==} + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true - jsonfile@6.2.0: - resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + jsonfile@6.2.1: + resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} jszip@3.10.1: resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} @@ -2669,26 +3102,29 @@ packages: lit-element@4.2.2: resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==} - lit-html@3.3.2: - resolution: {integrity: sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==} + lit-html@3.3.3: + resolution: {integrity: sha512-el8M6jK2o3RXBnrSHX3ZKrsN8zEV63pSExTO1wYJz7QndGYZ8353e2a5PPX+qHe2aGayfnchQmkAojaWAREOIA==} - lit@3.3.2: - resolution: {integrity: sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==} + lit@3.3.3: + resolution: {integrity: sha512-fycuvZg/hkpozL00lm1pEJH5nN/lr9ZXd6mJI2HSN4+Bzc+LDNdEApJ6HFbPkdFNHLvOplIIuJvxkS4XUxqirw==} load-json-file@4.0.0: resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} engines: {node: '>=4'} - local-pkg@1.1.2: - resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} + local-pkg@1.2.1: + resolution: {integrity: sha512-++gUqRDEvcnN6Zhqrr+y/CkVEHhlrR96vZn3nZZPYzMcBUyBtTKzB9NadClFIsIVSsu+3i9tfk/erqy9kAmt7Q==} engines: {node: '>=14'} locate-path@2.0.0: resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} engines: {node: '>=4'} - lodash-es@4.17.21: - resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + lodash-es@4.18.1: + resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} lodash.capitalize@4.2.1: resolution: {integrity: sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==} @@ -2705,15 +3141,15 @@ packages: lodash.uniqby@4.7.0: resolution: {integrity: sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==} - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} long@3.2.0: resolution: {integrity: sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==} engines: {node: '>=0.6'} - long@5.3.1: - resolution: {integrity: sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==} + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} @@ -2725,38 +3161,31 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.2.2: - resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} + lru-cache@11.5.1: + resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} engines: {node: 20 || >=22} lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - - luxon@3.5.0: - resolution: {integrity: sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==} + luxon@3.7.2: + resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} engines: {node: '>=12'} lz4js@0.2.0: resolution: {integrity: sha512-gY2Ia9Lm7Ep8qMiuGRhvUq0Q7qUereeldZPP1PMEJxPtEWHJLqw9pgX68oHajBH0nzJK4MaZEA/YNV3jT8u8Bg==} - lzo-wasm@0.0.4: - resolution: {integrity: sha512-VKlnoJRFrB8SdJhlVKvW5vI1gGwcZ+mvChEXcSX6r2xDNc/Q2FD9esfBmGCuPZdrJ1feO+YcVFd2PTk0c137Gw==} - lzw-tiff-decoder@0.1.1: resolution: {integrity: sha512-RUiNDPLzKEhX3JM9BgnFneerJd/uLgV4TeaNnkNJ0eO/GdlPeX01PKDCUsob8jhWILxOl3dGlDbD98KGex39ig==} magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - magicast@0.5.2: - resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} + magicast@0.5.3: + resolution: {integrity: sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==} - make-asynchronous@1.0.1: - resolution: {integrity: sha512-T9BPOmEOhp6SmV25SwLVcHK4E6JyG/coH3C6F1NjNXSziv/fd4GmsqMk8YR6qpPOswfaOCApSNkZv6fxoaYFcQ==} + make-asynchronous@1.1.0: + resolution: {integrity: sha512-ayF7iT+44LXdxJLTrTd3TLQpFDDvPCBxXxbv+pMUSuHA5Q8zyAfwkRP6aHHwNVFBUFWtxAHqwNJxF8vMZLAbVg==} engines: {node: '>=18'} make-dir@4.0.0: @@ -2774,6 +3203,18 @@ packages: engines: {node: '>= 18'} hasBin: true + marked@16.3.0: + resolution: {integrity: sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w==} + engines: {node: '>= 20'} + hasBin: true + + markerjs2@2.32.7: + resolution: {integrity: sha512-HeFRZjmc43DOG3lSQp92z49cq2oCYpYn2pX++SkJAW1Dij4xJtRquVRf+cXeSZQWDX3ufns1Ry/bGk+zveP7rA==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + math.gl@4.1.0: resolution: {integrity: sha512-FtvCJuuAlvn4358e2SkepTv2gnV7VTvu0y/hwkkjS/urDk+nY9x/4Tsn19LmaJl1wqKaqn+QFZhbnjAsuMOkWA==} @@ -2804,12 +3245,12 @@ packages: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - minimatch@10.0.3: - resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==} - engines: {node: 20 || >=22} + minimatch@10.2.3: + resolution: {integrity: sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==} + engines: {node: 18 || 20 || >=22} - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} engines: {node: '>=16 || 14 >=14.17'} minimist@1.2.8: @@ -2819,11 +3260,11 @@ packages: resolution: {integrity: sha512-Z5z/+FzZqOSO3juSVKV3zcm4R2eAlWwlKMcqHmyFEJAaLILNcDKnIbnb4/kbcGyIuhtdWrzu8WOIR7uM6I34aw==} engines: {node: '>= 4', npm: '>= 3'} - mlly@1.8.0: - resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} - moment-timezone@0.5.47: - resolution: {integrity: sha512-UbNt/JAWS0m/NJOebR0QMRHBk0hu03r5dx9GK8Cs0AS3I81yDcOc9k+DytPItgVvBP7J6Mf6U2n3BPAacAV9oA==} + moment-timezone@0.5.48: + resolution: {integrity: sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==} moment@2.30.1: resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} @@ -2837,8 +3278,8 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -2852,8 +3293,9 @@ packages: resolution: {integrity: sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==} engines: {node: '>=18'} - node-releases@2.0.19: - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + node-releases@2.0.47: + resolution: {integrity: sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==} + engines: {node: '>=18'} normalize-package-data@6.0.2: resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} @@ -2863,9 +3305,9 @@ packages: resolution: {integrity: sha512-RWk+PI433eESQ7ounYxIp67CYuVsS1uYSonX3kA6ps/3LWfjVQa/ptEg6Y3T6uAMq1mWpX9PQ+qx+QaHpsc7gQ==} engines: {node: ^20.17.0 || >=22.9.0} - normalize-url@8.1.0: - resolution: {integrity: sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==} - engines: {node: '>=14.16'} + normalize-url@9.0.1: + resolution: {integrity: sha512-ARftfC5HdUNu9jJeL8pHj8debUIHA2b91FizCoMzY4lG6dDX13jdvTK0TBe24IBDRf2HvJSzzwEPvmbkQWHRSg==} + engines: {node: '>=20'} notistack@3.0.2: resolution: {integrity: sha512-0R+/arLYbK5Hh7mEfR2adt0tyXJcCC9KkA2hc56FeWik2QN6Bm/S4uW+BjzDARsJth5u06nTjelSw/VSnB1YEA==} @@ -2886,8 +3328,8 @@ packages: resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} engines: {node: '>=18'} - npm@11.6.2: - resolution: {integrity: sha512-7iKzNfy8lWYs3zq4oFPa8EXZz5xt9gQNKJZau3B1ErLBb6bF7sBJ00x09485DOvRT2l5Gerbl3VlZNT57MxJVA==} + npm@11.16.0: + resolution: {integrity: sha512-A74XL8OxmcegZDMWPkWb5bEQppg8HdYwW3rBD2sPoS4UQHVajfaxBkqyzLeJ3wR0kZ+5xoTjItxXaF7eIXUsyw==} engines: {node: ^20.17.0 || >=22.9.0} hasBin: true bundledDependencies: @@ -2896,6 +3338,7 @@ packages: - '@npmcli/config' - '@npmcli/fs' - '@npmcli/map-workspaces' + - '@npmcli/metavuln-calculator' - '@npmcli/package-json' - '@npmcli/promise-spawn' - '@npmcli/redact' @@ -2906,7 +3349,6 @@ packages: - cacache - chalk - ci-info - - cli-columns - fastest-levenshtein - fs-minipass - glob @@ -2968,6 +3410,14 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + obug@2.1.1: resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} @@ -2991,10 +3441,6 @@ packages: resolution: {integrity: sha512-37/tPdZ3oJwHaS3gNJdenCDB3Tz26i9sjhnguBtvN0vYlRIiDNnvTWkuh+0hETV9rLPdJ3rlL3yVOYPIAnM8rw==} engines: {node: '>=18'} - p-is-promise@3.0.0: - resolution: {integrity: sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==} - engines: {node: '>=8'} - p-limit@1.3.0: resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} engines: {node: '>=4'} @@ -3003,8 +3449,8 @@ packages: resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} engines: {node: '>=4'} - p-map@7.0.3: - resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==} + p-map@7.0.4: + resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==} engines: {node: '>=18'} p-queue@7.4.1: @@ -3031,6 +3477,9 @@ packages: resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} engines: {node: '>=4'} + pako@0.2.9: + resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} + pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} @@ -3041,8 +3490,8 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} - parse-headers@2.0.5: - resolution: {integrity: sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==} + parse-headers@2.0.6: + resolution: {integrity: sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==} parse-json@4.0.0: resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} @@ -3076,6 +3525,10 @@ packages: resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} engines: {node: '>=4'} + path-expression-matcher@1.5.0: + resolution: {integrity: sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==} + engines: {node: '>=14.0.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -3102,15 +3555,19 @@ packages: resolution: {integrity: sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==} hasBin: true + pdfmake@0.2.23: + resolution: {integrity: sha512-A/IksoKb/ikOZH1edSDJ/2zBbqJKDghD4+fXn3rT7quvCJDlsZMs3NmIB3eajLMMFU9Bd3bZPVvlUMXhvFI+bQ==} + engines: {node: '>=18'} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} engines: {node: '>=8.6'} - picomatch@4.0.3: - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} pify@3.0.0: @@ -3124,15 +3581,21 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - pkg-types@2.3.0: - resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} + pkg-types@2.3.1: + resolution: {integrity: sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==} + + png-js@1.1.0: + resolution: {integrity: sha512-PM/uYGzGdNSzqeOgly68+6wKQDL1SY0a/N+OEa/+br6LnHWOAJB0Npiamnodfq3jd2LS/i2fMeOKSAILjA+m5Q==} - postcss@8.5.3: - resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + polylabel@1.1.0: + resolution: {integrity: sha512-bxaGcA40sL3d6M4hH72Z4NdLqxpXRsCFk8AITYg6x1rn1Ei3izf00UMLklerBZTO49aPA3CYrIwVulx2Bce2pA==} + + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} - preact@10.26.4: - resolution: {integrity: sha512-KJhO7LBFTjP71d83trW+Ilnjbo+ySsaAgCfXOXUlmGzJ4ygYPWmysm77yg4emwfmoz3b22yvH5IsVFHbhUaH5w==} + preact@10.29.2: + resolution: {integrity: sha512-7tNmwg/7mzzAoB/8kSg6Hl37JraAZw3Z3A0JSY7VXlZwo82Xn0G7wKbNNs2qoF4ZEEsQGTwDAroNdqKs1ofJxQ==} pretty-ms@9.3.0: resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} @@ -3147,12 +3610,8 @@ packages: proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - protocol-buffers-schema@3.6.0: - resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} + protocol-buffers-schema@3.6.1: + resolution: {integrity: sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==} quadbin@0.2.0: resolution: {integrity: sha512-bPgyRreIsFVwKxHRY+GFdaXatNmfQ1LzaQZj7aKEz07/gL893uWREhmRZpG6UuvlGHdTOPw/NGvqLsJica2goA==} @@ -3165,8 +3624,8 @@ packages: resolution: {integrity: sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==} engines: {node: '>=12'} - quick-lru@7.0.0: - resolution: {integrity: sha512-MX8gB7cVYTrYcFfAnfLlhRd0+Toyl8yX8uBx1MrX7K0jegiz9TumwOK27ldXrgDlHRdVi+MqU9Ssw6dr4BNreg==} + quick-lru@7.3.0: + resolution: {integrity: sha512-k9lSsjl36EJdK7I06v7APZCbyGT2vMTsYSRX1Q2nbYmnkBqgUhRkAuzH08Ciotteu/PLJmIF2+tti7o3C/ts2g==} engines: {node: '>=18'} quickselect@2.0.0: @@ -3187,11 +3646,11 @@ packages: react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react-is@19.2.0: - resolution: {integrity: sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==} + react-is@19.2.7: + resolution: {integrity: sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==} - react-refresh@0.14.2: - resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} + react-refresh@0.17.0: + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} react-transition-group@4.4.5: @@ -3218,8 +3677,8 @@ packages: resolution: {integrity: sha512-Q5hMVBYur/eQNWDdbF4/Wqqr9Bjvtrw2kjGxxBbKLbx8bVCL8gcArjTy8zDUuLGQicftpMuU0riQNcAsbtOVsw==} engines: {node: '>=20'} - read-pkg@10.0.0: - resolution: {integrity: sha512-A70UlgfNdKI5NSvTTfHzLQj7NJRpJ4mT5tGafkllJ4wh71oYuGm/pzphHcmW4s35iox56KSK721AihodoXSc/A==} + read-pkg@10.1.0: + resolution: {integrity: sha512-I8g2lArQiP78ll51UeMZojewtYgIRCKCWqZEgOO8c/uefTI+XDXvCSXu3+YNUaTNvZzobrL5+SqHjBrByRRTdg==} engines: {node: '>=20'} read-pkg@9.0.1: @@ -3232,8 +3691,12 @@ packages: reference-spec-reader@0.2.0: resolution: {integrity: sha512-q0mfCi5yZSSHXpCyxjgQeaORq3tvDsxDyzaadA/5+AbAUwRyRuuTh0aRQuE/vAOt/qzzxidJ5iDeu1cLHaNBlQ==} - registry-auth-token@5.1.0: - resolution: {integrity: sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==} + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + registry-auth-token@5.1.1: + resolution: {integrity: sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q==} engines: {node: '>=14'} require-directory@2.1.1: @@ -3255,32 +3718,43 @@ packages: resolve-protobuf-schema@2.1.0: resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==} - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + resolve@1.22.12: + resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} engines: {node: '>= 0.4'} hasBin: true - rollup@4.40.1: - resolution: {integrity: sha512-C5VvvgCCyfyotVITIAv+4efVytl5F7wt+/I2i9q9GZcEXW9BP52YYOXC58igUi+LFZVHukErIIqQSWwv/M3WRw==} + robust-predicates@3.0.3: + resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==} + + rollup@4.61.0: + resolution: {integrity: sha512-T9mWdbWfQtp0B5lv/HX+wrhYsmXRlcWnXXmJbXqKJhlRaoS6KMhq0gpyzW4UJfclcxrEdLnTgjT2NjruLONu0g==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sax@1.6.0: + resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} + engines: {node: '>=11.0.0'} + scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - semantic-release@25.0.2: - resolution: {integrity: sha512-6qGjWccl5yoyugHt3jTgztJ9Y0JVzyH8/Voc/D8PlLat9pwxQYXz7W1Dpnq5h0/G5GCYGUaDSlYcyk3AMh5A6g==} + seedrandom@3.0.5: + resolution: {integrity: sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==} + + semantic-release@25.0.3: + resolution: {integrity: sha512-WRgl5GcypwramYX4HV+eQGzUbD7UUbljVmS+5G1uMwX/wLgYuJAxGeerXJDMO2xshng4+FXqCgyB5QfClV6WjA==} engines: {node: ^22.14.0 || >= 24.10.0} hasBin: true - semver-diff@5.0.0: - resolution: {integrity: sha512-0HbGtOm+S7T6NGQ/pxJSJipJvc4DK3FcRVMRkhsIwJDJ4Jcz5DQC1cPPzB5GhzyHjwttW878HaWQq46CkL3cqg==} - engines: {node: '>=12'} - deprecated: Deprecated as the semver package now supports this built-in. - semver-regex@4.0.5: resolution: {integrity: sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==} engines: {node: '>=12'} @@ -3289,16 +3763,24 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} engines: {node: '>=10'} hasBin: true - semver@7.7.3: - resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + semver@7.8.1: + resolution: {integrity: sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==} engines: {node: '>=10'} hasBin: true + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} @@ -3358,8 +3840,8 @@ packages: spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - spdx-license-ids@3.0.22: - resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} + spdx-license-ids@3.0.23: + resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==} split2@1.0.0: resolution: {integrity: sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==} @@ -3373,6 +3855,9 @@ packages: std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} + stream-combiner2@1.1.1: resolution: {integrity: sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==} @@ -3395,8 +3880,8 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.2: - resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} engines: {node: '>=12'} strip-bom@3.0.0: @@ -3419,15 +3904,14 @@ packages: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - strip-literal@3.1.0: resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} - strnum@1.1.2: - resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} + strnum@2.3.0: + resolution: {integrity: sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==} + + style-observer@0.0.8: + resolution: {integrity: sha512-UaIPn33Sx4BJ+goia51Q++VFWoplWK1995VdxQYzwwbFa+FUNLKlG+aiIdG2Vw7VyzIUBi8tqu8mTyg0Ppu6Yg==} stylis@4.2.0: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} @@ -3456,9 +3940,16 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + svg-arc-to-cubic-bezier@3.2.0: + resolution: {integrity: sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==} + tabbable@6.4.0: resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} + table-layout@4.1.1: + resolution: {integrity: sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==} + engines: {node: '>=12.17'} + tagged-tag@1.0.0: resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} engines: {node: '>=20'} @@ -3467,8 +3958,8 @@ packages: resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} engines: {node: '>=14.16'} - tempy@3.1.0: - resolution: {integrity: sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==} + tempy@3.2.0: + resolution: {integrity: sha512-d79HhZya5Djd7am0q+W4RTsSU+D/aJzM+4Y4AGJGuGlgM2L6sx5ZvOYTmZjqPhrDrV6xJTtRSm1JCLj6V6LHLQ==} engines: {node: '>=14.16'} texture-compressor@1.0.2: @@ -3497,30 +3988,36 @@ packages: resolution: {integrity: sha512-AnkJYrbb7uPkDCEqGeVJiawZNiwVlSkkeX4jZg1gTEguClhyX+/Ezn07KB6DT29tG3UN418ldmS/W6KqGOTDjg==} engines: {node: '>=18.12.0'} + tiny-inflate@1.0.3: + resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - tinyexec@1.0.2: - resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} engines: {node: '>=18'} - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} tinypool@1.1.1: resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} engines: {node: ^18.0.0 || >=20.0.0} + tinyqueue@2.0.3: + resolution: {integrity: sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==} + tinyrainbow@2.0.0: resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} engines: {node: '>=14.0.0'} - tinyrainbow@3.0.3: - resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} tinyspy@4.0.4: @@ -3554,38 +4051,48 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} - type-fest@5.2.0: - resolution: {integrity: sha512-xxCJm+Bckc6kQBknN7i9fnP/xobQRsRQxR01CztFkp/h++yfVxUUcmMgfR2HttJx/dpWjS9ubVuyspJv24Q9DA==} + type-fest@5.7.0: + resolution: {integrity: sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg==} engines: {node: '>=20'} - typescript@5.8.2: - resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true - ufo@1.6.1: - resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} + typical@7.3.0: + resolution: {integrity: sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==} + engines: {node: '>=12.17'} + + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} uglify-js@3.19.3: resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} engines: {node: '>=0.8.0'} hasBin: true - undici-types@7.10.0: - resolution: {integrity: sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==} + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} - undici@5.29.0: - resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} - engines: {node: '>=14.0'} + undici@6.26.0: + resolution: {integrity: sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==} + engines: {node: '>=18.17'} - undici@7.16.0: - resolution: {integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==} + undici@7.27.0: + resolution: {integrity: sha512-+t2Z/GwkZQDtu00813aP66ygViGtPHKhhoFZpQKpKrE+9jIgES+Zw+mFNaDWOVRKiuJjuqKHzD3B1sfGg8+ZOQ==} engines: {node: '>=20.18.1'} unicode-emoji-modifier-base@1.0.0: resolution: {integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==} engines: {node: '>=4'} + unicode-properties@1.4.1: + resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==} + + unicode-trie@2.0.0: + resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==} + unicorn-magic@0.1.0: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} engines: {node: '>=18'} @@ -3594,6 +4101,10 @@ packages: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} + unicorn-magic@0.4.0: + resolution: {integrity: sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==} + engines: {node: '>=20'} + unique-string@3.0.0: resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} engines: {node: '>=12'} @@ -3609,15 +4120,12 @@ packages: resolution: {integrity: sha512-gsq2PdJIWWGhx5kcdWStvNWit9FVdTewm4SEG7gFskWs+XCVaULt9+BwuoBtJiRE8eo3L1IPAOrbByNLtLtIlg==} engines: {node: '>=12'} - update-browserslist-db@1.1.3: - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - url-join@5.0.0: resolution: {integrity: sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -3645,8 +4153,8 @@ packages: vite: optional: true - vite@6.2.7: - resolution: {integrity: sha512-qg3LkeuinTrZoJHHF94coSaTfIPyBYoywp+ys4qu20oSJFbKMYoIJo0FWJT9q6Vp49l6z9IsJRbHdcGtiKbGoQ==} + vite@6.4.3: + resolution: {integrity: sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -3685,16 +4193,16 @@ packages: yaml: optional: true - vitest@3.2.4: - resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} + vitest@3.2.6: + resolution: {integrity: sha512-xejya+bT/j/+R/AGa1XOfRxLmNUlLtlwjRsFUILF+xHfzElmGcmFydy2gqqIrd62ptIEfwVMofd19uNWD9L7Nw==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/debug': ^4.1.12 '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.2.4 - '@vitest/ui': 3.2.4 + '@vitest/browser': 3.2.6 + '@vitest/ui': 3.2.6 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -3713,20 +4221,23 @@ packages: jsdom: optional: true - vitest@4.0.15: - resolution: {integrity: sha512-n1RxDp8UJm6N0IbJLQo+yzLZ2sQCDyl1o0LeugbPWf8+8Fttp29GghsQBjYJVmWq3gBFfe9Hs1spR44vovn2wA==} + vitest@4.1.8: + resolution: {integrity: sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.0.15 - '@vitest/browser-preview': 4.0.15 - '@vitest/browser-webdriverio': 4.0.15 - '@vitest/ui': 4.0.15 + '@vitest/browser-playwright': 4.1.8 + '@vitest/browser-preview': 4.1.8 + '@vitest/browser-webdriverio': 4.1.8 + '@vitest/coverage-istanbul': 4.1.8 + '@vitest/coverage-v8': 4.1.8 + '@vitest/ui': 4.1.8 happy-dom: '*' jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true @@ -3740,6 +4251,10 @@ packages: optional: true '@vitest/browser-webdriverio': optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true '@vitest/ui': optional: true happy-dom: @@ -3750,14 +4265,11 @@ packages: vscode-uri@3.1.0: resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} - web-worker@1.2.0: - resolution: {integrity: sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==} - web-worker@1.5.0: resolution: {integrity: sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==} - wgsl_reflect@1.2.0: - resolution: {integrity: sha512-bDYcmWfbg4WsrBmPv6lsyjqXx02r8dkNAzR77OCNqIcR8snO4aNSBTjir9zqgR7rLnw6PaisiZxtCitSCIUlnQ==} + wgsl_reflect@1.3.0: + resolution: {integrity: sha512-liK+dXfDMQUrr8QcZhZi75EFD4us4VhsIT218YMkKZr8aDExc7A5znDpfmf7IxM3nIooFPCKAnK9u8WY5XizAw==} which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} @@ -3772,6 +4284,10 @@ packages: wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + wordwrapjs@5.1.1: + resolution: {integrity: sha512-0yweIbkINJodk27gX9LBGMzyQdBDan3s/dEAiwBOj+Mf0PPyWL6/rikalkv8EeD0E8jm4o5RXEOrFTP3NXbhJg==} + engines: {node: '>=12.17'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -3780,8 +4296,16 @@ packages: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} - xml-utils@1.10.1: - resolution: {integrity: sha512-Dn6vJ1Z9v1tepSjvnCpwk5QqwIPcEFKdgnjqfYOABv1ngSofuAhtlugcUC3ehS1OHdgDWSG6C5mvj+Qm15udTQ==} + xml-naming@0.1.0: + resolution: {integrity: sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==} + engines: {node: '>=16.0.0'} + + xml-utils@1.10.2: + resolution: {integrity: sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==} + + xmldoc@2.0.3: + resolution: {integrity: sha512-6gRk4NY/Jvg67xn7OzJuxLRsGgiXBaPUQplVJ/9l99uIugxh4FTOewYz5ic8WScj7Xx/2WvhENiQKwkK9RpE4w==} + engines: {node: '>=12.0.0'} xss@1.0.13: resolution: {integrity: sha512-clu7dxTm1e8Mo5fz3n/oW3UCXBfV89xZ72jM8yzo1vR/pIS0w3sgB3XV2H8Vm6zfGnHL0FzvLJPJEBhd86/z4Q==} @@ -3799,15 +4323,12 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - - yaml@1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + yaml@1.10.3: + resolution: {integrity: sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==} engines: {node: '>= 6'} - yaml@2.8.2: - resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} engines: {node: '>= 14.6'} hasBin: true @@ -3838,8 +4359,8 @@ packages: zarrita@0.5.0: resolution: {integrity: sha512-wyvnnzeXh9rBCZxsn6GEW4oXDv3LD2f4KSJ6LLFjYaMNtmAtaSt3qEO3fHuuq0VZWUGb8cjTYDEtwJTa09wp6g==} - zod@3.24.2: - resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} zstd-codec@0.1.5: resolution: {integrity: sha512-v3fyjpK8S/dpY/X5WxqTK3IoCnp/ZOLxn144GZVlNUjtwAchzrVo03h+oMATFhCIiJ5KTr4V3vDQQYz4RU684g==} @@ -3849,184 +4370,188 @@ packages: snapshots: - '@actions/core@1.11.1': + '@actions/core@3.0.1': dependencies: - '@actions/exec': 1.1.1 - '@actions/http-client': 2.2.3 + '@actions/exec': 3.0.0 + '@actions/http-client': 4.0.1 - '@actions/exec@1.1.1': + '@actions/exec@3.0.0': dependencies: - '@actions/io': 1.1.3 + '@actions/io': 3.0.2 - '@actions/http-client@2.2.3': + '@actions/http-client@4.0.1': dependencies: tunnel: 0.0.6 - undici: 5.29.0 + undici: 6.26.0 - '@actions/io@1.1.3': {} + '@actions/io@3.0.2': {} - '@ampproject/remapping@2.3.0': + '@amcharts/amcharts5@5.14.4': dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 + '@types/d3': 7.4.3 + '@types/d3-chord': 3.0.6 + '@types/d3-hierarchy': 3.1.1 + '@types/d3-sankey': 0.11.2 + '@types/d3-shape': 3.1.8 + '@types/geojson': 7946.0.16 + '@types/polylabel': 1.1.3 + '@types/svg-arc-to-cubic-bezier': 3.2.3 + d3: 7.9.0 + d3-chord: 3.0.1 + d3-force: 3.0.0 + d3-geo: 3.1.1 + d3-hierarchy: 3.1.2 + d3-sankey: 0.12.3 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-voronoi-treemap: 1.1.2 + flatpickr: 4.6.13 + markerjs2: 2.32.7 + pdfmake: 0.2.23 + polylabel: 1.1.0 + seedrandom: 3.0.5 + svg-arc-to-cubic-bezier: 3.2.0 + tslib: 2.8.1 - '@arcgis/core@4.32.8(@lit/context@1.1.6)': + '@arcgis/core@4.34.8': dependencies: + '@amcharts/amcharts5': 5.14.4 + '@arcgis/toolkit': 4.34.9 '@esri/arcgis-html-sanitizer': 4.1.0 - '@esri/calcite-components': 3.3.3(@lit/context@1.1.6) - '@vaadin/grid': 24.6.11 - '@zip.js/zip.js': 2.7.73 - luxon: 3.5.0 - marked: 15.0.12 + '@esri/calcite-components': 3.3.3 + '@vaadin/grid': 24.9.15 + '@zip.js/zip.js': 2.8.26 + luxon: 3.7.2 + marked: 16.3.0 + tslib: 2.8.1 transitivePeerDependencies: - '@lit/context' - '@arcgis/lumina@4.34.9(@lit/context@1.1.6)(lit@3.3.2)': + '@arcgis/lumina@4.34.9(lit@3.3.3)': dependencies: '@arcgis/toolkit': 4.34.9 - csstype: 3.1.3 - lit: 3.3.2 + csstype: 3.2.3 + lit: 3.3.3 tslib: 2.8.1 - optionalDependencies: - '@lit/context': 1.1.6 '@arcgis/toolkit@4.34.9': dependencies: tslib: 2.8.1 - '@babel/code-frame@7.26.2': + '@babel/code-frame@7.29.7': dependencies: - '@babel/helper-validator-identifier': 7.25.9 + '@babel/helper-validator-identifier': 7.29.7 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.26.8': {} + '@babel/compat-data@7.29.7': {} - '@babel/core@7.26.9': + '@babel/core@7.29.7': dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.9 - '@babel/helper-compilation-targets': 7.26.5 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) - '@babel/helpers': 7.26.9 - '@babel/parser': 7.26.9 - '@babel/template': 7.26.9 - '@babel/traverse': 7.26.9 - '@babel/types': 7.26.9 + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 + '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.4.0 + debug: 4.4.3 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/generator@7.26.9': + '@babel/generator@7.29.7': dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - '@babel/helper-compilation-targets@7.26.5': + '@babel/helper-compilation-targets@7.29.7': dependencies: - '@babel/compat-data': 7.26.8 - '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.4 + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.28.2 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-module-imports@7.25.9': + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-module-imports@7.29.7': dependencies: - '@babel/traverse': 7.26.9 - '@babel/types': 7.28.5 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.9)': + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': dependencies: - '@babel/core': 7.26.9 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.9 + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/helper-plugin-utils@7.26.5': {} - - '@babel/helper-string-parser@7.25.9': {} + '@babel/helper-plugin-utils@7.29.7': {} - '@babel/helper-string-parser@7.27.1': {} + '@babel/helper-string-parser@7.29.7': {} - '@babel/helper-validator-identifier@7.25.9': {} + '@babel/helper-validator-identifier@7.29.7': {} - '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-option@7.29.7': {} - '@babel/helper-validator-option@7.25.9': {} - - '@babel/helpers@7.26.9': - dependencies: - '@babel/template': 7.26.9 - '@babel/types': 7.28.5 - - '@babel/parser@7.26.9': - dependencies: - '@babel/types': 7.28.5 - - '@babel/parser@7.28.5': + '@babel/helpers@7.29.7': dependencies: - '@babel/types': 7.28.5 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 - '@babel/parser@7.29.0': + '@babel/parser@7.29.7': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 - '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.9)': + '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7)': dependencies: - '@babel/core': 7.26.9 - '@babel/helper-plugin-utils': 7.26.5 + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.9)': + '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7)': dependencies: - '@babel/core': 7.26.9 - '@babel/helper-plugin-utils': 7.26.5 + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 - '@babel/runtime@7.28.4': {} + '@babel/runtime@7.29.7': {} - '@babel/template@7.26.9': + '@babel/template@7.29.7': dependencies: - '@babel/code-frame': 7.26.2 - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 - '@babel/traverse@7.26.9': + '@babel/traverse@7.29.7': dependencies: - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.9 - '@babel/parser': 7.28.5 - '@babel/template': 7.26.9 - '@babel/types': 7.28.5 - debug: 4.4.0 - globals: 11.12.0 + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.26.9': - dependencies: - '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - - '@babel/types@7.28.5': + '@babel/types@7.29.7': dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - - '@babel/types@7.29.0': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 '@bcoe/v8-coverage@1.0.2': {} @@ -4068,10 +4593,10 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@deck.gl/aggregation-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))': + '@deck.gl/aggregation-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))': dependencies: '@deck.gl/core': 9.0.41 - '@deck.gl/layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@deck.gl/layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) '@luma.gl/constants': 9.0.28 '@luma.gl/core': 9.0.28 '@luma.gl/engine': 9.0.28(@luma.gl/core@9.0.28) @@ -4079,49 +4604,51 @@ snapshots: '@math.gl/web-mercator': 4.1.0 d3-hexbin: 0.2.2 - '@deck.gl/arcgis@9.0.41(@arcgis/core@4.32.8(@lit/context@1.1.6))(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))': + '@deck.gl/arcgis@9.0.41(@arcgis/core@4.34.8)(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))': dependencies: - '@arcgis/core': 4.32.8(@lit/context@1.1.6) + '@arcgis/core': 4.34.8 '@deck.gl/core': 9.0.41 '@luma.gl/constants': 9.0.28 '@luma.gl/core': 9.0.28 '@luma.gl/engine': 9.0.28(@luma.gl/core@9.0.28) esri-loader: 3.7.0 - '@deck.gl/carto@9.0.41(m67uvbolj56khq5wgiv5vk2uge)': + '@deck.gl/carto@9.0.41(h3geslv24d6m33k2qxfmttsmcm)': dependencies: - '@deck.gl/aggregation-layers': 9.0.41(@deck.gl/core@9.0.41)(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@deck.gl/aggregation-layers': 9.0.41(@deck.gl/core@9.0.41)(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) '@deck.gl/core': 9.0.41 '@deck.gl/extensions': 9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) - '@deck.gl/geo-layers': 9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) - '@deck.gl/layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) - '@loaders.gl/core': 4.3.3 - '@loaders.gl/gis': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/mvt': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/schema': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/tiles': 4.3.3(@loaders.gl/core@4.3.3) + '@deck.gl/geo-layers': 9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@deck.gl/layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/gis': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/mvt': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/schema': 4.4.2 + '@loaders.gl/tiles': 4.4.2(@loaders.gl/core@4.4.2) '@luma.gl/core': 9.0.28 '@luma.gl/shadertools': 9.0.28(@luma.gl/core@9.0.28) '@math.gl/web-mercator': 4.1.0 - '@types/d3-array': 3.2.1 + '@types/d3-array': 3.2.2 '@types/d3-color': 1.4.5 '@types/d3-scale': 3.3.5 cartocolor: 5.0.2 d3-array: 3.2.4 d3-color: 3.1.0 - d3-format: 3.1.0 + d3-format: 3.1.2 d3-scale: 4.0.2 earcut: 2.2.4 - h3-js: 4.1.0 - moment-timezone: 0.5.47 + h3-js: 4.4.0 + moment-timezone: 0.5.48 pbf: 3.3.0 quadbin: 0.2.0 + transitivePeerDependencies: + - '@75lb/nature' '@deck.gl/core@9.0.41': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/images': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/images': 4.4.2(@loaders.gl/core@4.4.2) '@luma.gl/constants': 9.0.28 '@luma.gl/core': 9.0.28 '@luma.gl/engine': 9.0.28(@luma.gl/core@9.0.28) @@ -4130,12 +4657,14 @@ snapshots: '@math.gl/core': 4.1.0 '@math.gl/sun': 4.1.0 '@math.gl/web-mercator': 4.1.0 - '@probe.gl/env': 4.1.0 - '@probe.gl/log': 4.1.0 - '@probe.gl/stats': 4.1.0 + '@probe.gl/env': 4.1.1 + '@probe.gl/log': 4.1.1 + '@probe.gl/stats': 4.1.1 '@types/offscreencanvas': 2019.7.3 - gl-matrix: 3.4.3 + gl-matrix: 3.4.4 mjolnir.js: 2.7.3 + transitivePeerDependencies: + - '@75lb/nature' '@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))': dependencies: @@ -4146,31 +4675,33 @@ snapshots: '@luma.gl/shadertools': 9.0.28(@luma.gl/core@9.0.28) '@math.gl/core': 4.1.0 - '@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))': + '@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))': dependencies: '@deck.gl/core': 9.0.41 '@deck.gl/extensions': 9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) - '@deck.gl/layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) - '@deck.gl/mesh-layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) - '@loaders.gl/3d-tiles': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/core': 4.3.3 - '@loaders.gl/gis': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/mvt': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/schema': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/terrain': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/tiles': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/wms': 4.3.3(@loaders.gl/core@4.3.3) + '@deck.gl/layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@deck.gl/mesh-layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@loaders.gl/3d-tiles': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/gis': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/mvt': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/schema': 4.4.2 + '@loaders.gl/terrain': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/tiles': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/wms': 4.4.2(@loaders.gl/core@4.4.2) '@luma.gl/core': 9.0.28 '@luma.gl/engine': 9.0.28(@luma.gl/core@9.0.28) - '@luma.gl/gltf': 9.0.28(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@luma.gl/gltf': 9.0.28(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) '@luma.gl/shadertools': 9.0.28(@luma.gl/core@9.0.28) '@math.gl/core': 4.1.0 '@math.gl/culling': 4.1.0 '@math.gl/web-mercator': 4.1.0 '@types/geojson': 7946.0.16 - h3-js: 4.1.0 + h3-js: 4.4.0 long: 3.2.0 + transitivePeerDependencies: + - '@75lb/nature' '@deck.gl/google-maps@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)': dependencies: @@ -4178,26 +4709,28 @@ snapshots: '@luma.gl/constants': 9.0.28 '@luma.gl/core': 9.0.28 '@math.gl/core': 4.1.0 - '@types/google.maps': 3.58.1 + '@types/google.maps': 3.65.0 '@deck.gl/json@9.0.41(@deck.gl/core@9.0.41)': dependencies: '@deck.gl/core': 9.0.41 jsep: 0.3.5 - '@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))': + '@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))': dependencies: '@deck.gl/core': 9.0.41 - '@loaders.gl/core': 4.3.3 - '@loaders.gl/images': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/schema': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/images': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/schema': 4.4.2 '@luma.gl/core': 9.0.28 '@luma.gl/engine': 9.0.28(@luma.gl/core@9.0.28) - '@mapbox/tiny-sdf': 2.0.6 + '@mapbox/tiny-sdf': 2.2.0 '@math.gl/core': 4.1.0 '@math.gl/polygon': 4.1.0 '@math.gl/web-mercator': 4.1.0 earcut: 2.2.4 + transitivePeerDependencies: + - '@75lb/nature' '@deck.gl/mapbox@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)': dependencies: @@ -4206,15 +4739,16 @@ snapshots: '@luma.gl/core': 9.0.28 '@math.gl/web-mercator': 4.1.0 - '@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))': + '@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))': dependencies: '@deck.gl/core': 9.0.41 - '@loaders.gl/gltf': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/gltf': 4.4.2(@loaders.gl/core@4.4.2) '@luma.gl/core': 9.0.28 '@luma.gl/engine': 9.0.28(@luma.gl/core@9.0.28) - '@luma.gl/gltf': 9.0.28(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@luma.gl/gltf': 9.0.28(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) '@luma.gl/shadertools': 9.0.28(@luma.gl/core@9.0.28) transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/core' '@deck.gl/react@9.0.41(@deck.gl/core@9.0.41)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -4226,12 +4760,12 @@ snapshots: '@deck.gl/widgets@9.0.41(@deck.gl/core@9.0.41)': dependencies: '@deck.gl/core': 9.0.41 - preact: 10.26.4 + preact: 10.29.2 '@emotion/babel-plugin@11.13.5': dependencies: - '@babel/helper-module-imports': 7.25.9 - '@babel/runtime': 7.28.4 + '@babel/helper-module-imports': 7.29.7 + '@babel/runtime': 7.29.7 '@emotion/hash': 0.9.2 '@emotion/memoize': 0.9.0 '@emotion/serialize': 1.3.3 @@ -4260,9 +4794,9 @@ snapshots: '@emotion/memoize@0.9.0': {} - '@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1)': + '@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.7 '@emotion/babel-plugin': 11.13.5 '@emotion/cache': 11.14.0 '@emotion/serialize': 1.3.3 @@ -4272,7 +4806,7 @@ snapshots: hoist-non-react-statics: 3.3.2 react: 18.3.1 optionalDependencies: - '@types/react': 18.3.18 + '@types/react': 18.3.30 transitivePeerDependencies: - supports-color @@ -4282,22 +4816,22 @@ snapshots: '@emotion/memoize': 0.9.0 '@emotion/unitless': 0.10.0 '@emotion/utils': 1.4.2 - csstype: 3.1.3 + csstype: 3.2.3 '@emotion/sheet@1.4.0': {} - '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1)': + '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.7 '@emotion/babel-plugin': 11.13.5 '@emotion/is-prop-valid': 1.4.0 - '@emotion/react': 11.14.0(@types/react@18.3.18)(react@18.3.1) + '@emotion/react': 11.14.0(@types/react@18.3.30)(react@18.3.1) '@emotion/serialize': 1.3.3 '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1) '@emotion/utils': 1.4.2 react: 18.3.1 optionalDependencies: - '@types/react': 18.3.18 + '@types/react': 18.3.30 transitivePeerDependencies: - supports-color @@ -4311,99 +4845,102 @@ snapshots: '@emotion/weak-memoize@0.4.0': {} - '@esbuild/aix-ppc64@0.25.3': + '@esbuild/aix-ppc64@0.25.12': + optional: true + + '@esbuild/android-arm64@0.25.12': optional: true - '@esbuild/android-arm64@0.25.3': + '@esbuild/android-arm@0.25.12': optional: true - '@esbuild/android-arm@0.25.3': + '@esbuild/android-x64@0.25.12': optional: true - '@esbuild/android-x64@0.25.3': + '@esbuild/darwin-arm64@0.25.12': optional: true - '@esbuild/darwin-arm64@0.25.3': + '@esbuild/darwin-x64@0.25.12': optional: true - '@esbuild/darwin-x64@0.25.3': + '@esbuild/freebsd-arm64@0.25.12': optional: true - '@esbuild/freebsd-arm64@0.25.3': + '@esbuild/freebsd-x64@0.25.12': optional: true - '@esbuild/freebsd-x64@0.25.3': + '@esbuild/linux-arm64@0.25.12': optional: true - '@esbuild/linux-arm64@0.25.3': + '@esbuild/linux-arm@0.25.12': optional: true - '@esbuild/linux-arm@0.25.3': + '@esbuild/linux-ia32@0.25.12': optional: true - '@esbuild/linux-ia32@0.25.3': + '@esbuild/linux-loong64@0.25.12': optional: true - '@esbuild/linux-loong64@0.25.3': + '@esbuild/linux-mips64el@0.25.12': optional: true - '@esbuild/linux-mips64el@0.25.3': + '@esbuild/linux-ppc64@0.25.12': optional: true - '@esbuild/linux-ppc64@0.25.3': + '@esbuild/linux-riscv64@0.25.12': optional: true - '@esbuild/linux-riscv64@0.25.3': + '@esbuild/linux-s390x@0.25.12': optional: true - '@esbuild/linux-s390x@0.25.3': + '@esbuild/linux-x64@0.25.12': optional: true - '@esbuild/linux-x64@0.25.3': + '@esbuild/netbsd-arm64@0.25.12': optional: true - '@esbuild/netbsd-arm64@0.25.3': + '@esbuild/netbsd-x64@0.25.12': optional: true - '@esbuild/netbsd-x64@0.25.3': + '@esbuild/openbsd-arm64@0.25.12': optional: true - '@esbuild/openbsd-arm64@0.25.3': + '@esbuild/openbsd-x64@0.25.12': optional: true - '@esbuild/openbsd-x64@0.25.3': + '@esbuild/openharmony-arm64@0.25.12': optional: true - '@esbuild/sunos-x64@0.25.3': + '@esbuild/sunos-x64@0.25.12': optional: true - '@esbuild/win32-arm64@0.25.3': + '@esbuild/win32-arm64@0.25.12': optional: true - '@esbuild/win32-ia32@0.25.3': + '@esbuild/win32-ia32@0.25.12': optional: true - '@esbuild/win32-x64@0.25.3': + '@esbuild/win32-x64@0.25.12': optional: true '@esri/arcgis-html-sanitizer@4.1.0': dependencies: xss: 1.0.13 - '@esri/calcite-components@3.3.3(@lit/context@1.1.6)': + '@esri/calcite-components@3.3.3': dependencies: - '@arcgis/lumina': 4.34.9(@lit/context@1.1.6)(lit@3.3.2) + '@arcgis/lumina': 4.34.9(lit@3.3.3) '@arcgis/toolkit': 4.34.9 '@esri/calcite-ui-icons': 4.3.0 - '@floating-ui/dom': 1.7.5 - '@floating-ui/utils': 0.2.10 + '@floating-ui/dom': 1.7.6 + '@floating-ui/utils': 0.2.11 '@types/sortablejs': 1.15.9 color: 5.0.3 - composed-offset-position: 0.0.6(@floating-ui/utils@0.2.10) - es-toolkit: 1.44.0 + composed-offset-position: 0.0.6(@floating-ui/utils@0.2.11) + es-toolkit: 1.47.0 focus-trap: 7.8.0 interactjs: 1.10.27 - lit: 3.3.2 + lit: 3.3.3 sortablejs: 1.15.7 timezone-groups: 0.10.4 type-fest: 4.41.0 @@ -4412,28 +4949,52 @@ snapshots: '@esri/calcite-ui-icons@4.3.0': {} - '@fastify/busboy@2.1.1': {} + '@floating-ui/core@1.7.5': + dependencies: + '@floating-ui/utils': 0.2.11 - '@floating-ui/core@1.7.4': + '@floating-ui/dom@1.7.6': dependencies: - '@floating-ui/utils': 0.2.10 + '@floating-ui/core': 1.7.5 + '@floating-ui/utils': 0.2.11 + + '@floating-ui/utils@0.2.11': {} - '@floating-ui/dom@1.7.5': + '@foliojs-fork/fontkit@1.9.2': dependencies: - '@floating-ui/core': 1.7.4 - '@floating-ui/utils': 0.2.10 + '@foliojs-fork/restructure': 2.0.2 + brotli: 1.3.3 + clone: 1.0.4 + deep-equal: 1.1.2 + dfa: 1.2.0 + tiny-inflate: 1.0.3 + unicode-properties: 1.4.1 + unicode-trie: 2.0.0 - '@floating-ui/utils@0.2.10': {} + '@foliojs-fork/linebreak@1.1.2': + dependencies: + base64-js: 1.3.1 + unicode-trie: 2.0.0 - '@hms-dbmi/viv@0.17.2(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/react@9.0.41(@deck.gl/core@9.0.41)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28))(react@18.3.1)': + '@foliojs-fork/pdfkit@0.15.3': dependencies: - '@vivjs/constants': 0.17.2 - '@vivjs/extensions': 0.17.2(@deck.gl/core@9.0.41) - '@vivjs/layers': 0.17.2(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28)) - '@vivjs/loaders': 0.17.2(patch_hash=auxsjwuajoz3k5rha2oxpwrlfm) - '@vivjs/types': 0.17.2 - '@vivjs/viewers': 0.17.2(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/react@9.0.41(@deck.gl/core@9.0.41)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28))(react@18.3.1) - '@vivjs/views': 0.17.2(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28)) + '@foliojs-fork/fontkit': 1.9.2 + '@foliojs-fork/linebreak': 1.1.2 + crypto-js: 4.2.0 + jpeg-exif: 1.1.4 + png-js: 1.1.0 + + '@foliojs-fork/restructure@2.0.2': {} + + '@hms-dbmi/viv@0.17.3(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/react@9.0.41(@deck.gl/core@9.0.41)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28))(react@18.3.1)': + dependencies: + '@vivjs/constants': 0.17.3 + '@vivjs/extensions': 0.17.3(@deck.gl/core@9.0.41) + '@vivjs/layers': 0.17.3(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28)) + '@vivjs/loaders': 0.17.3 + '@vivjs/types': 0.17.3 + '@vivjs/viewers': 0.17.3(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/react@9.0.41(@deck.gl/core@9.0.41)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28))(react@18.3.1) + '@vivjs/views': 0.17.3(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28)) transitivePeerDependencies: - '@deck.gl/core' - '@deck.gl/geo-layers' @@ -4448,224 +5009,262 @@ snapshots: '@interactjs/types@1.10.27': {} - '@isaacs/balanced-match@4.0.1': {} - - '@isaacs/brace-expansion@5.0.0': + '@jridgewell/gen-mapping@0.3.13': dependencies: - '@isaacs/balanced-match': 4.0.1 + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 - '@jridgewell/gen-mapping@0.3.8': + '@jridgewell/remapping@2.3.5': dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/set-array@1.2.1': {} - '@jridgewell/sourcemap-codec@1.5.5': {} - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@lit-labs/ssr-dom-shim@1.5.1': {} - - '@lit/context@1.1.6': - dependencies: - '@lit/reactive-element': 2.1.2 - optional: true + '@lit-labs/ssr-dom-shim@1.6.0': {} '@lit/reactive-element@2.1.2': dependencies: - '@lit-labs/ssr-dom-shim': 1.5.1 + '@lit-labs/ssr-dom-shim': 1.6.0 - '@loaders.gl/3d-tiles@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/3d-tiles@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/compression': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/core': 4.3.3 - '@loaders.gl/crypto': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/draco': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/gltf': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/images': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/math': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/tiles': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/zip': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/compression': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/crypto': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/draco': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/gltf': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/images': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/math': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/tiles': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/zip': 4.4.2(@loaders.gl/core@4.4.2) '@math.gl/core': 4.1.0 '@math.gl/culling': 4.1.0 '@math.gl/geospatial': 4.1.0 - '@probe.gl/log': 4.1.0 - long: 5.3.1 + '@probe.gl/log': 4.1.1 + long: 5.3.2 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/compression@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/compression@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/worker-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@types/brotli': 1.3.4 + '@loaders.gl/core': 4.4.2 + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/worker-utils': 4.4.2(@loaders.gl/core@4.4.2) '@types/pako': 1.0.7 fflate: 0.7.4 - lzo-wasm: 0.0.4 pako: 1.0.11 snappyjs: 0.6.1 optionalDependencies: + '@types/brotli': 1.3.5 brotli: 1.3.3 lz4js: 0.2.0 zstd-codec: 0.1.5 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/core@4.3.3': + '@loaders.gl/core@4.4.2': dependencies: - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/schema': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/worker-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@probe.gl/log': 4.1.0 + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/schema': 4.4.2 + '@loaders.gl/schema-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/worker-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@probe.gl/log': 4.1.1 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/crypto@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/crypto@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/worker-utils': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/worker-utils': 4.4.2(@loaders.gl/core@4.4.2) '@types/crypto-js': 4.2.2 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/draco@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/draco@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/schema': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/worker-utils': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/schema': 4.4.2 + '@loaders.gl/schema-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/worker-utils': 4.4.2(@loaders.gl/core@4.4.2) draco3d: 1.5.7 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/gis@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/geoarrow@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/schema': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 + '@math.gl/polygon': 4.1.0 + apache-arrow: 21.1.0 + transitivePeerDependencies: + - '@75lb/nature' + + '@loaders.gl/gis@4.4.2(@loaders.gl/core@4.4.2)': + dependencies: + '@loaders.gl/core': 4.4.2 + '@loaders.gl/geoarrow': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/schema': 4.4.2 + '@loaders.gl/schema-utils': 4.4.2(@loaders.gl/core@4.4.2) '@mapbox/vector-tile': 1.3.1 '@math.gl/polygon': 4.1.0 pbf: 3.3.0 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/gltf@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/gltf@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/draco': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/images': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/schema': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/textures': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/draco': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/images': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/schema': 4.4.2 + '@loaders.gl/textures': 4.4.2(@loaders.gl/core@4.4.2) '@math.gl/core': 4.1.0 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/images@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/images@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/loader-utils@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/loader-utils@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/schema': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/worker-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@probe.gl/log': 4.1.0 - '@probe.gl/stats': 4.1.0 + '@loaders.gl/schema': 4.4.2 + '@loaders.gl/worker-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@probe.gl/log': 4.1.1 + '@probe.gl/stats': 4.1.1 + transitivePeerDependencies: + - '@75lb/nature' + - '@loaders.gl/core' - '@loaders.gl/math@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/math@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/images': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 '@math.gl/core': 4.1.0 - '@loaders.gl/mvt@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/mvt@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/gis': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/images': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/schema': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/gis': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/images': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/schema': 4.4.2 '@math.gl/polygon': 4.1.0 - '@probe.gl/stats': 4.1.0 + '@probe.gl/stats': 4.1.1 pbf: 3.3.0 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/schema@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/schema-utils@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 + '@loaders.gl/core': 4.4.2 + '@loaders.gl/schema': 4.4.2 '@types/geojson': 7946.0.16 + apache-arrow: 21.1.0 + transitivePeerDependencies: + - '@75lb/nature' + + '@loaders.gl/schema@4.4.2': + dependencies: + '@types/geojson': 7946.0.16 + apache-arrow: 21.1.0 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/terrain@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/terrain@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/images': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/schema': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/images': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/schema': 4.4.2 '@mapbox/martini': 0.2.0 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/textures@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/textures@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/images': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/schema': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/worker-utils': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/images': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/schema': 4.4.2 + '@loaders.gl/worker-utils': 4.4.2(@loaders.gl/core@4.4.2) '@math.gl/types': 4.1.0 ktx-parse: 0.7.1 texture-compressor: 1.0.2 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/tiles@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/tiles@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/math': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/math': 4.4.2(@loaders.gl/core@4.4.2) '@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.1.0 + '@probe.gl/stats': 4.1.1 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/wms@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/wms@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/images': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/schema': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/xml': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/images': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/schema': 4.4.2 + '@loaders.gl/xml': 4.4.2(@loaders.gl/core@4.4.2) '@turf/rewind': 5.1.5 deep-strict-equal: 0.2.0 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/worker-utils@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/worker-utils@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 + '@loaders.gl/core': 4.4.2 - '@loaders.gl/xml@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/xml@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/schema': 4.3.3(@loaders.gl/core@4.3.3) - fast-xml-parser: 4.5.3 + '@loaders.gl/core': 4.4.2 + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/schema': 4.4.2 + fast-xml-parser: 5.8.0 + transitivePeerDependencies: + - '@75lb/nature' - '@loaders.gl/zip@4.3.3(@loaders.gl/core@4.3.3)': + '@loaders.gl/zip@4.4.2(@loaders.gl/core@4.4.2)': dependencies: - '@loaders.gl/compression': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/core': 4.3.3 - '@loaders.gl/crypto': 4.3.3(@loaders.gl/core@4.3.3) - '@loaders.gl/loader-utils': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/compression': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/crypto': 4.4.2(@loaders.gl/core@4.4.2) + '@loaders.gl/loader-utils': 4.4.2(@loaders.gl/core@4.4.2) jszip: 3.10.1 md5: 2.3.0 + transitivePeerDependencies: + - '@75lb/nature' '@luma.gl/constants@9.0.28': {} '@luma.gl/core@9.0.28': dependencies: '@math.gl/types': 4.1.0 - '@probe.gl/env': 4.1.0 - '@probe.gl/log': 4.1.0 - '@probe.gl/stats': 4.1.0 + '@probe.gl/env': 4.1.1 + '@probe.gl/log': 4.1.1 + '@probe.gl/stats': 4.1.1 '@types/offscreencanvas': 2019.7.3 '@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)': @@ -4673,30 +5272,32 @@ snapshots: '@luma.gl/core': 9.0.28 '@luma.gl/shadertools': 9.0.28(@luma.gl/core@9.0.28) '@math.gl/core': 4.1.0 - '@probe.gl/log': 4.1.0 - '@probe.gl/stats': 4.1.0 + '@probe.gl/log': 4.1.1 + '@probe.gl/stats': 4.1.1 - '@luma.gl/gltf@9.0.28(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))': + '@luma.gl/gltf@9.0.28(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))': dependencies: - '@loaders.gl/core': 4.3.3 - '@loaders.gl/textures': 4.3.3(@loaders.gl/core@4.3.3) + '@loaders.gl/core': 4.4.2 + '@loaders.gl/textures': 4.4.2(@loaders.gl/core@4.4.2) '@luma.gl/core': 9.0.28 '@luma.gl/engine': 9.0.28(@luma.gl/core@9.0.28) '@luma.gl/shadertools': 9.0.28(@luma.gl/core@9.0.28) '@math.gl/core': 4.1.0 + transitivePeerDependencies: + - '@75lb/nature' '@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28)': dependencies: '@luma.gl/core': 9.0.28 '@math.gl/core': 4.1.0 '@math.gl/types': 4.1.0 - wgsl_reflect: 1.2.0 + wgsl_reflect: 1.3.0 '@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28)': dependencies: '@luma.gl/constants': 9.0.28 '@luma.gl/core': 9.0.28 - '@probe.gl/env': 4.1.0 + '@probe.gl/env': 4.1.1 '@mapbox/martini@0.2.0': {} @@ -4706,7 +5307,7 @@ snapshots: dependencies: tilebelt: 1.0.1 - '@mapbox/tiny-sdf@2.0.6': {} + '@mapbox/tiny-sdf@2.2.0': {} '@mapbox/vector-tile@1.3.1': dependencies: @@ -4738,128 +5339,129 @@ snapshots: dependencies: '@math.gl/core': 4.1.0 - '@microsoft/api-extractor-model@7.32.2(@types/node@24.3.0)': + '@microsoft/api-extractor-model@7.33.8(@types/node@24.12.4)': dependencies: '@microsoft/tsdoc': 0.16.0 - '@microsoft/tsdoc-config': 0.18.0 - '@rushstack/node-core-library': 5.19.1(@types/node@24.3.0) + '@microsoft/tsdoc-config': 0.18.1 + '@rushstack/node-core-library': 5.23.1(@types/node@24.12.4) transitivePeerDependencies: - '@types/node' - '@microsoft/api-extractor@7.55.2(@types/node@24.3.0)': + '@microsoft/api-extractor@7.58.7(@types/node@24.12.4)': dependencies: - '@microsoft/api-extractor-model': 7.32.2(@types/node@24.3.0) + '@microsoft/api-extractor-model': 7.33.8(@types/node@24.12.4) '@microsoft/tsdoc': 0.16.0 - '@microsoft/tsdoc-config': 0.18.0 - '@rushstack/node-core-library': 5.19.1(@types/node@24.3.0) - '@rushstack/rig-package': 0.6.0 - '@rushstack/terminal': 0.19.5(@types/node@24.3.0) - '@rushstack/ts-command-line': 5.1.5(@types/node@24.3.0) - diff: 8.0.2 - lodash: 4.17.21 - minimatch: 10.0.3 - resolve: 1.22.10 - semver: 7.5.4 + '@microsoft/tsdoc-config': 0.18.1 + '@rushstack/node-core-library': 5.23.1(@types/node@24.12.4) + '@rushstack/rig-package': 0.7.3 + '@rushstack/terminal': 0.24.0(@types/node@24.12.4) + '@rushstack/ts-command-line': 5.3.9(@types/node@24.12.4) + diff: 8.0.4 + minimatch: 10.2.3 + resolve: 1.22.12 + semver: 7.7.4 source-map: 0.6.1 - typescript: 5.8.2 + typescript: 5.9.3 transitivePeerDependencies: - '@types/node' - '@microsoft/tsdoc-config@0.18.0': + '@microsoft/tsdoc-config@0.18.1': dependencies: '@microsoft/tsdoc': 0.16.0 - ajv: 8.12.0 + ajv: 8.18.0 jju: 1.4.0 - resolve: 1.22.10 + resolve: 1.22.12 '@microsoft/tsdoc@0.16.0': {} - '@mui/core-downloads-tracker@7.3.4': {} + '@mui/core-downloads-tracker@7.3.11': {} - '@mui/icons-material@7.3.4(@mui/material@7.3.4(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.18)(react@18.3.1)': + '@mui/icons-material@7.3.11(@mui/material@7.3.11(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.30)(react@18.3.1)': dependencies: - '@babel/runtime': 7.28.4 - '@mui/material': 7.3.4(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@babel/runtime': 7.29.7 + '@mui/material': 7.3.11(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.18 + '@types/react': 18.3.30 - '@mui/material@7.3.4(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@mui/material@7.3.11(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.28.4 - '@mui/core-downloads-tracker': 7.3.4 - '@mui/system': 7.3.3(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) - '@mui/types': 7.4.7(@types/react@18.3.18) - '@mui/utils': 7.3.3(@types/react@18.3.18)(react@18.3.1) + '@babel/runtime': 7.29.7 + '@mui/core-downloads-tracker': 7.3.11 + '@mui/system': 7.3.11(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1) + '@mui/types': 7.4.12(@types/react@18.3.30) + '@mui/utils': 7.3.11(@types/react@18.3.30)(react@18.3.1) '@popperjs/core': 2.11.8 - '@types/react-transition-group': 4.4.12(@types/react@18.3.18) + '@types/react-transition-group': 4.4.12(@types/react@18.3.30) clsx: 2.1.1 - csstype: 3.1.3 + csstype: 3.2.3 prop-types: 15.8.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-is: 19.2.0 + react-is: 19.2.7 react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) optionalDependencies: - '@emotion/react': 11.14.0(@types/react@18.3.18)(react@18.3.1) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 + '@emotion/react': 11.14.0(@types/react@18.3.30)(react@18.3.1) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1) + '@types/react': 18.3.30 - '@mui/private-theming@7.3.3(@types/react@18.3.18)(react@18.3.1)': + '@mui/private-theming@7.3.11(@types/react@18.3.30)(react@18.3.1)': dependencies: - '@babel/runtime': 7.28.4 - '@mui/utils': 7.3.3(@types/react@18.3.18)(react@18.3.1) + '@babel/runtime': 7.29.7 + '@mui/utils': 7.3.11(@types/react@18.3.30)(react@18.3.1) prop-types: 15.8.1 react: 18.3.1 optionalDependencies: - '@types/react': 18.3.18 + '@types/react': 18.3.30 - '@mui/styled-engine@7.3.3(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1)': + '@mui/styled-engine@7.3.10(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.7 '@emotion/cache': 11.14.0 '@emotion/serialize': 1.3.3 '@emotion/sheet': 1.4.0 - csstype: 3.1.3 + csstype: 3.2.3 prop-types: 15.8.1 react: 18.3.1 optionalDependencies: - '@emotion/react': 11.14.0(@types/react@18.3.18)(react@18.3.1) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) + '@emotion/react': 11.14.0(@types/react@18.3.30)(react@18.3.1) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1) - '@mui/system@7.3.3(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1)': + '@mui/system@7.3.11(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1)': dependencies: - '@babel/runtime': 7.28.4 - '@mui/private-theming': 7.3.3(@types/react@18.3.18)(react@18.3.1) - '@mui/styled-engine': 7.3.3(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1))(react@18.3.1) - '@mui/types': 7.4.7(@types/react@18.3.18) - '@mui/utils': 7.3.3(@types/react@18.3.18)(react@18.3.1) + '@babel/runtime': 7.29.7 + '@mui/private-theming': 7.3.11(@types/react@18.3.30)(react@18.3.1) + '@mui/styled-engine': 7.3.10(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1))(react@18.3.1) + '@mui/types': 7.4.12(@types/react@18.3.30) + '@mui/utils': 7.3.11(@types/react@18.3.30)(react@18.3.1) clsx: 2.1.1 - csstype: 3.1.3 + csstype: 3.2.3 prop-types: 15.8.1 react: 18.3.1 optionalDependencies: - '@emotion/react': 11.14.0(@types/react@18.3.18)(react@18.3.1) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) - '@types/react': 18.3.18 + '@emotion/react': 11.14.0(@types/react@18.3.30)(react@18.3.1) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.30)(react@18.3.1))(@types/react@18.3.30)(react@18.3.1) + '@types/react': 18.3.30 - '@mui/types@7.4.7(@types/react@18.3.18)': + '@mui/types@7.4.12(@types/react@18.3.30)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.7 optionalDependencies: - '@types/react': 18.3.18 + '@types/react': 18.3.30 - '@mui/utils@7.3.3(@types/react@18.3.18)(react@18.3.1)': + '@mui/utils@7.3.11(@types/react@18.3.30)(react@18.3.1)': dependencies: - '@babel/runtime': 7.28.4 - '@mui/types': 7.4.7(@types/react@18.3.18) + '@babel/runtime': 7.29.7 + '@mui/types': 7.4.12(@types/react@18.3.30) '@types/prop-types': 15.7.15 clsx: 2.1.1 prop-types: 15.8.1 react: 18.3.1 - react-is: 19.2.0 + react-is: 19.2.7 optionalDependencies: - '@types/react': 18.3.18 + '@types/react': 18.3.30 + + '@nodable/entities@2.1.1': {} '@octokit/auth-token@6.0.0': {} @@ -4867,20 +5469,20 @@ snapshots: dependencies: '@octokit/auth-token': 6.0.0 '@octokit/graphql': 9.0.3 - '@octokit/request': 10.0.6 - '@octokit/request-error': 7.0.2 + '@octokit/request': 10.0.10 + '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 before-after-hook: 4.0.0 universal-user-agent: 7.0.3 - '@octokit/endpoint@11.0.2': + '@octokit/endpoint@11.0.3': dependencies: '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 '@octokit/graphql@9.0.3': dependencies: - '@octokit/request': 10.0.6 + '@octokit/request': 10.0.10 '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 @@ -4891,10 +5493,10 @@ snapshots: '@octokit/core': 7.0.6 '@octokit/types': 16.0.0 - '@octokit/plugin-retry@8.0.3(@octokit/core@7.0.6)': + '@octokit/plugin-retry@8.1.0(@octokit/core@7.0.6)': dependencies: '@octokit/core': 7.0.6 - '@octokit/request-error': 7.0.2 + '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 bottleneck: 2.19.5 @@ -4904,16 +5506,17 @@ snapshots: '@octokit/types': 16.0.0 bottleneck: 2.19.5 - '@octokit/request-error@7.0.2': + '@octokit/request-error@7.1.0': dependencies: '@octokit/types': 16.0.0 - '@octokit/request@10.0.6': + '@octokit/request@10.0.10': dependencies: - '@octokit/endpoint': 11.0.2 - '@octokit/request-error': 7.0.2 + '@octokit/endpoint': 11.0.3 + '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 - fast-content-type-parse: 3.0.0 + content-type: 2.0.0 + json-with-bigint: 3.5.8 universal-user-agent: 7.0.3 '@octokit/types@16.0.0': @@ -4922,7 +5525,7 @@ snapshots: '@open-wc/dedupe-mixin@1.4.0': {} - '@petamoriken/float16@3.9.2': {} + '@petamoriken/float16@3.9.3': {} '@pnpm/config.env-replace@1.1.0': {} @@ -4930,7 +5533,7 @@ snapshots: dependencies: graceful-fs: 4.2.10 - '@pnpm/npm-conf@2.3.1': + '@pnpm/npm-conf@3.0.2': dependencies: '@pnpm/config.env-replace': 1.1.0 '@pnpm/network.ca-file': 1.0.2 @@ -4942,115 +5545,132 @@ snapshots: '@popperjs/core@2.11.8': {} - '@probe.gl/env@4.1.0': {} + '@probe.gl/env@4.1.1': {} - '@probe.gl/log@4.1.0': + '@probe.gl/log@4.1.1': dependencies: - '@probe.gl/env': 4.1.0 + '@probe.gl/env': 4.1.1 - '@probe.gl/stats@4.1.0': {} + '@probe.gl/stats@4.1.1': {} - '@rollup/pluginutils@5.3.0(rollup@4.40.1)': + '@rolldown/pluginutils@1.0.0-beta.27': {} + + '@rollup/pluginutils@5.4.0(rollup@4.61.0)': dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.9 estree-walker: 2.0.2 - picomatch: 4.0.3 + picomatch: 4.0.4 optionalDependencies: - rollup: 4.40.1 + rollup: 4.61.0 + + '@rollup/rollup-android-arm-eabi@4.61.0': + optional: true + + '@rollup/rollup-android-arm64@4.61.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.61.0': + optional: true - '@rollup/rollup-android-arm-eabi@4.40.1': + '@rollup/rollup-darwin-x64@4.61.0': optional: true - '@rollup/rollup-android-arm64@4.40.1': + '@rollup/rollup-freebsd-arm64@4.61.0': optional: true - '@rollup/rollup-darwin-arm64@4.40.1': + '@rollup/rollup-freebsd-x64@4.61.0': optional: true - '@rollup/rollup-darwin-x64@4.40.1': + '@rollup/rollup-linux-arm-gnueabihf@4.61.0': optional: true - '@rollup/rollup-freebsd-arm64@4.40.1': + '@rollup/rollup-linux-arm-musleabihf@4.61.0': optional: true - '@rollup/rollup-freebsd-x64@4.40.1': + '@rollup/rollup-linux-arm64-gnu@4.61.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.40.1': + '@rollup/rollup-linux-arm64-musl@4.61.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.40.1': + '@rollup/rollup-linux-loong64-gnu@4.61.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.40.1': + '@rollup/rollup-linux-loong64-musl@4.61.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.40.1': + '@rollup/rollup-linux-ppc64-gnu@4.61.0': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.40.1': + '@rollup/rollup-linux-ppc64-musl@4.61.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.40.1': + '@rollup/rollup-linux-riscv64-gnu@4.61.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.40.1': + '@rollup/rollup-linux-riscv64-musl@4.61.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.40.1': + '@rollup/rollup-linux-s390x-gnu@4.61.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.40.1': + '@rollup/rollup-linux-x64-gnu@4.61.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.40.1': + '@rollup/rollup-linux-x64-musl@4.61.0': optional: true - '@rollup/rollup-linux-x64-musl@4.40.1': + '@rollup/rollup-openbsd-x64@4.61.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.40.1': + '@rollup/rollup-openharmony-arm64@4.61.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.40.1': + '@rollup/rollup-win32-arm64-msvc@4.61.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.40.1': + '@rollup/rollup-win32-ia32-msvc@4.61.0': optional: true - '@rushstack/node-core-library@5.19.1(@types/node@24.3.0)': + '@rollup/rollup-win32-x64-gnu@4.61.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.61.0': + optional: true + + '@rushstack/node-core-library@5.23.1(@types/node@24.12.4)': dependencies: - ajv: 8.13.0 - ajv-draft-04: 1.0.0(ajv@8.13.0) - ajv-formats: 3.0.1(ajv@8.13.0) - fs-extra: 11.3.2 + ajv: 8.18.0 + ajv-draft-04: 1.0.0(ajv@8.18.0) + ajv-formats: 3.0.1(ajv@8.18.0) + fs-extra: 11.3.5 import-lazy: 4.0.0 jju: 1.4.0 - resolve: 1.22.10 - semver: 7.5.4 + resolve: 1.22.12 + semver: 7.7.4 optionalDependencies: - '@types/node': 24.3.0 + '@types/node': 24.12.4 - '@rushstack/problem-matcher@0.1.1(@types/node@24.3.0)': + '@rushstack/problem-matcher@0.2.1(@types/node@24.12.4)': optionalDependencies: - '@types/node': 24.3.0 + '@types/node': 24.12.4 - '@rushstack/rig-package@0.6.0': + '@rushstack/rig-package@0.7.3': dependencies: - resolve: 1.22.10 - strip-json-comments: 3.1.1 + jju: 1.4.0 + resolve: 1.22.12 - '@rushstack/terminal@0.19.5(@types/node@24.3.0)': + '@rushstack/terminal@0.24.0(@types/node@24.12.4)': dependencies: - '@rushstack/node-core-library': 5.19.1(@types/node@24.3.0) - '@rushstack/problem-matcher': 0.1.1(@types/node@24.3.0) + '@rushstack/node-core-library': 5.23.1(@types/node@24.12.4) + '@rushstack/problem-matcher': 0.2.1(@types/node@24.12.4) supports-color: 8.1.1 optionalDependencies: - '@types/node': 24.3.0 + '@types/node': 24.12.4 - '@rushstack/ts-command-line@5.1.5(@types/node@24.3.0)': + '@rushstack/ts-command-line@5.3.9(@types/node@24.12.4)': dependencies: - '@rushstack/terminal': 0.19.5(@types/node@24.3.0) + '@rushstack/terminal': 0.24.0(@types/node@24.12.4) '@types/argparse': 1.0.38 argparse: 1.0.10 string-argv: 0.3.2 @@ -5059,25 +5679,25 @@ snapshots: '@sec-ant/readable-stream@0.4.1': {} - '@semantic-release/changelog@6.0.3(semantic-release@25.0.2(typescript@5.8.2))': + '@semantic-release/changelog@6.0.3(semantic-release@25.0.3(typescript@5.9.3))': dependencies: '@semantic-release/error': 3.0.0 aggregate-error: 3.1.0 - fs-extra: 11.3.2 - lodash: 4.17.21 - semantic-release: 25.0.2(typescript@5.8.2) + fs-extra: 11.3.5 + lodash: 4.18.1 + semantic-release: 25.0.3(typescript@5.9.3) - '@semantic-release/commit-analyzer@13.0.1(semantic-release@25.0.2(typescript@5.8.2))': + '@semantic-release/commit-analyzer@13.0.1(semantic-release@25.0.3(typescript@5.9.3))': dependencies: - conventional-changelog-angular: 8.1.0 - conventional-changelog-writer: 8.2.0 + conventional-changelog-angular: 8.3.1 + conventional-changelog-writer: 8.4.0 conventional-commits-filter: 5.0.0 - conventional-commits-parser: 6.2.1 - debug: 4.4.0 + conventional-commits-parser: 6.4.0 + debug: 4.4.3 import-from-esm: 2.0.0 - lodash-es: 4.17.21 + lodash-es: 4.18.1 micromatch: 4.0.8 - semantic-release: 25.0.2(typescript@5.8.2) + semantic-release: 25.0.3(typescript@5.9.3) transitivePeerDependencies: - supports-color @@ -5085,101 +5705,105 @@ snapshots: '@semantic-release/error@4.0.0': {} - '@semantic-release/exec@7.1.0(semantic-release@25.0.2(typescript@5.8.2))': + '@semantic-release/exec@7.1.0(semantic-release@25.0.3(typescript@5.9.3))': dependencies: '@semantic-release/error': 4.0.0 aggregate-error: 3.1.0 - debug: 4.4.0 - execa: 9.6.0 - lodash-es: 4.17.21 + debug: 4.4.3 + execa: 9.6.1 + lodash-es: 4.18.1 parse-json: 8.3.0 - semantic-release: 25.0.2(typescript@5.8.2) + semantic-release: 25.0.3(typescript@5.9.3) transitivePeerDependencies: - supports-color - '@semantic-release/git@10.0.1(semantic-release@25.0.2(typescript@5.8.2))': + '@semantic-release/git@10.0.1(semantic-release@25.0.3(typescript@5.9.3))': dependencies: '@semantic-release/error': 3.0.0 aggregate-error: 3.1.0 - debug: 4.4.0 + debug: 4.4.3 dir-glob: 3.0.1 execa: 5.1.1 - lodash: 4.17.21 + lodash: 4.18.1 micromatch: 4.0.8 p-reduce: 2.1.0 - semantic-release: 25.0.2(typescript@5.8.2) + semantic-release: 25.0.3(typescript@5.9.3) transitivePeerDependencies: - supports-color - '@semantic-release/github@12.0.2(semantic-release@25.0.2(typescript@5.8.2))': + '@semantic-release/github@12.0.8(semantic-release@25.0.3(typescript@5.9.3))': dependencies: '@octokit/core': 7.0.6 '@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.6) - '@octokit/plugin-retry': 8.0.3(@octokit/core@7.0.6) + '@octokit/plugin-retry': 8.1.0(@octokit/core@7.0.6) '@octokit/plugin-throttling': 11.0.3(@octokit/core@7.0.6) '@semantic-release/error': 4.0.0 aggregate-error: 5.0.0 - debug: 4.4.0 + debug: 4.4.3 dir-glob: 3.0.1 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - issue-parser: 7.0.1 - lodash-es: 4.17.21 + http-proxy-agent: 9.0.0 + https-proxy-agent: 9.0.0 + issue-parser: 7.0.2 + lodash-es: 4.18.1 mime: 4.1.0 p-filter: 4.1.0 - semantic-release: 25.0.2(typescript@5.8.2) - tinyglobby: 0.2.15 - undici: 7.16.0 + semantic-release: 25.0.3(typescript@5.9.3) + tinyglobby: 0.2.17 + undici: 7.27.0 url-join: 5.0.0 transitivePeerDependencies: - supports-color - '@semantic-release/npm@13.1.1(semantic-release@25.0.2(typescript@5.8.2))': + '@semantic-release/npm@13.1.5(semantic-release@25.0.3(typescript@5.9.3))': dependencies: - '@actions/core': 1.11.1 + '@actions/core': 3.0.1 '@semantic-release/error': 4.0.0 aggregate-error: 5.0.0 env-ci: 11.2.0 - execa: 9.6.0 - fs-extra: 11.3.2 - lodash-es: 4.17.21 + execa: 9.6.1 + fs-extra: 11.3.5 + lodash-es: 4.18.1 nerf-dart: 1.0.0 - normalize-url: 8.1.0 - npm: 11.6.2 + normalize-url: 9.0.1 + npm: 11.16.0 rc: 1.2.8 - read-pkg: 9.0.1 - registry-auth-token: 5.1.0 - semantic-release: 25.0.2(typescript@5.8.2) - semver: 7.7.3 - tempy: 3.1.0 + read-pkg: 10.1.0 + registry-auth-token: 5.1.1 + semantic-release: 25.0.3(typescript@5.9.3) + semver: 7.8.1 + tempy: 3.2.0 - '@semantic-release/release-notes-generator@14.1.0(semantic-release@25.0.2(typescript@5.8.2))': + '@semantic-release/release-notes-generator@14.1.1(semantic-release@25.0.3(typescript@5.9.3))': dependencies: - conventional-changelog-angular: 8.1.0 - conventional-changelog-writer: 8.2.0 + conventional-changelog-angular: 8.3.1 + conventional-changelog-writer: 8.4.0 conventional-commits-filter: 5.0.0 - conventional-commits-parser: 6.2.1 - debug: 4.4.0 - get-stream: 7.0.1 + conventional-commits-parser: 6.4.0 + debug: 4.4.3 import-from-esm: 2.0.0 - into-stream: 7.0.0 - lodash-es: 4.17.21 + lodash-es: 4.18.1 read-package-up: 11.0.0 - semantic-release: 25.0.2(typescript@5.8.2) + semantic-release: 25.0.3(typescript@5.9.3) transitivePeerDependencies: - supports-color + '@simple-libs/stream-utils@1.2.0': {} + '@sindresorhus/is@4.6.0': {} '@sindresorhus/merge-streams@4.0.0': {} - '@standard-schema/spec@1.0.0': {} + '@standard-schema/spec@1.1.0': {} + + '@swc/helpers@0.5.23': + dependencies: + tslib: 2.8.1 - '@tanstack/query-core@5.90.20': {} + '@tanstack/query-core@5.101.0': {} - '@tanstack/react-query@5.90.21(react@18.3.1)': + '@tanstack/react-query@5.101.0(react@18.3.1)': dependencies: - '@tanstack/query-core': 5.90.20 + '@tanstack/query-core': 5.101.0 react: 18.3.1 '@turf/boolean-clockwise@5.1.5': @@ -5213,59 +5837,189 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.26.9 - '@babel/types': 7.26.9 - '@types/babel__generator': 7.6.8 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.6 + '@types/babel__traverse': 7.28.0 - '@types/babel__generator@7.6.8': + '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.29.7 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 - '@types/babel__traverse@7.20.6': + '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.29.7 - '@types/brotli@1.3.4': + '@types/brotli@1.3.5': dependencies: - '@types/node': 24.3.0 + '@types/node': 24.12.4 + optional: true '@types/chai@5.2.3': dependencies: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 + '@types/command-line-args@5.2.3': {} + + '@types/command-line-usage@5.0.4': {} + '@types/crypto-js@4.2.2': {} - '@types/d3-array@3.2.1': {} + '@types/d3-array@3.2.2': {} + + '@types/d3-axis@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-brush@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-chord@3.0.6': {} '@types/d3-color@1.4.5': {} + '@types/d3-color@3.1.3': {} + + '@types/d3-contour@3.0.6': + dependencies: + '@types/d3-array': 3.2.2 + '@types/geojson': 7946.0.16 + + '@types/d3-delaunay@6.0.4': {} + + '@types/d3-dispatch@3.0.7': {} + + '@types/d3-drag@3.0.7': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-dsv@3.0.7': {} + + '@types/d3-ease@3.0.2': {} + + '@types/d3-fetch@3.0.7': + dependencies: + '@types/d3-dsv': 3.0.7 + + '@types/d3-force@3.0.10': {} + + '@types/d3-format@3.0.4': {} + + '@types/d3-geo@3.1.0': + dependencies: + '@types/geojson': 7946.0.16 + + '@types/d3-hierarchy@3.1.1': {} + + '@types/d3-interpolate@3.0.4': + dependencies: + '@types/d3-color': 3.1.3 + + '@types/d3-path@1.0.11': {} + + '@types/d3-path@3.1.1': {} + + '@types/d3-polygon@3.0.2': {} + + '@types/d3-quadtree@3.0.6': {} + + '@types/d3-random@3.0.3': {} + + '@types/d3-sankey@0.11.2': + dependencies: + '@types/d3-shape': 1.3.12 + + '@types/d3-scale-chromatic@3.1.0': {} + '@types/d3-scale@3.3.5': dependencies: '@types/d3-time': 2.1.4 + '@types/d3-scale@4.0.9': + dependencies: + '@types/d3-time': 3.0.4 + + '@types/d3-selection@3.0.11': {} + + '@types/d3-shape@1.3.12': + dependencies: + '@types/d3-path': 1.0.11 + + '@types/d3-shape@3.1.8': + dependencies: + '@types/d3-path': 3.1.1 + + '@types/d3-time-format@4.0.3': {} + '@types/d3-time@2.1.4': {} + '@types/d3-time@3.0.4': {} + + '@types/d3-timer@3.0.2': {} + + '@types/d3-transition@3.0.9': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-zoom@3.0.8': + dependencies: + '@types/d3-interpolate': 3.0.4 + '@types/d3-selection': 3.0.11 + + '@types/d3@7.4.3': + dependencies: + '@types/d3-array': 3.2.2 + '@types/d3-axis': 3.0.6 + '@types/d3-brush': 3.0.6 + '@types/d3-chord': 3.0.6 + '@types/d3-color': 3.1.3 + '@types/d3-contour': 3.0.6 + '@types/d3-delaunay': 6.0.4 + '@types/d3-dispatch': 3.0.7 + '@types/d3-drag': 3.0.7 + '@types/d3-dsv': 3.0.7 + '@types/d3-ease': 3.0.2 + '@types/d3-fetch': 3.0.7 + '@types/d3-force': 3.0.10 + '@types/d3-format': 3.0.4 + '@types/d3-geo': 3.1.0 + '@types/d3-hierarchy': 3.1.1 + '@types/d3-interpolate': 3.0.4 + '@types/d3-path': 3.1.1 + '@types/d3-polygon': 3.0.2 + '@types/d3-quadtree': 3.0.6 + '@types/d3-random': 3.0.3 + '@types/d3-scale': 4.0.9 + '@types/d3-scale-chromatic': 3.1.0 + '@types/d3-selection': 3.0.11 + '@types/d3-shape': 3.1.8 + '@types/d3-time': 3.0.4 + '@types/d3-time-format': 4.0.3 + '@types/d3-timer': 3.0.2 + '@types/d3-transition': 3.0.9 + '@types/d3-zoom': 3.0.8 + '@types/deep-eql@4.0.2': {} - '@types/estree@1.0.7': {} + '@types/estree@1.0.9': {} '@types/geojson@7946.0.16': {} - '@types/google.maps@3.58.1': {} + '@types/google.maps@3.65.0': {} '@types/hammerjs@2.0.46': {} - '@types/node@24.3.0': + '@types/node@24.12.4': dependencies: - undici-types: 7.10.0 + undici-types: 7.16.0 '@types/normalize-package-data@2.4.4': {} @@ -5275,147 +6029,151 @@ snapshots: '@types/parse-json@4.0.2': {} - '@types/prop-types@15.7.14': {} + '@types/polylabel@1.1.3': {} '@types/prop-types@15.7.15': {} - '@types/react-dom@18.3.5(@types/react@18.3.18)': + '@types/react-dom@18.3.7(@types/react@18.3.30)': dependencies: - '@types/react': 18.3.18 + '@types/react': 18.3.30 - '@types/react-transition-group@4.4.12(@types/react@18.3.18)': + '@types/react-transition-group@4.4.12(@types/react@18.3.30)': dependencies: - '@types/react': 18.3.18 + '@types/react': 18.3.30 - '@types/react@18.3.18': + '@types/react@18.3.30': dependencies: - '@types/prop-types': 15.7.14 - csstype: 3.1.3 + '@types/prop-types': 15.7.15 + csstype: 3.2.3 '@types/sortablejs@1.15.9': {} + '@types/svg-arc-to-cubic-bezier@3.2.3': {} + '@types/trusted-types@2.0.7': {} - '@vaadin/a11y-base@24.6.11': + '@vaadin/a11y-base@24.9.15': dependencies: '@open-wc/dedupe-mixin': 1.4.0 '@polymer/polymer': 3.5.2 - '@vaadin/component-base': 24.6.11 - lit: 3.3.2 + '@vaadin/component-base': 24.9.15 + lit: 3.3.3 - '@vaadin/checkbox@24.6.11': + '@vaadin/checkbox@24.9.15': dependencies: '@open-wc/dedupe-mixin': 1.4.0 '@polymer/polymer': 3.5.2 - '@vaadin/a11y-base': 24.6.11 - '@vaadin/component-base': 24.6.11 - '@vaadin/field-base': 24.6.11 - '@vaadin/vaadin-lumo-styles': 24.6.11 - '@vaadin/vaadin-material-styles': 24.6.11 - '@vaadin/vaadin-themable-mixin': 24.6.11 - lit: 3.3.2 + '@vaadin/a11y-base': 24.9.15 + '@vaadin/component-base': 24.9.15 + '@vaadin/field-base': 24.9.15 + '@vaadin/vaadin-lumo-styles': 24.9.15 + '@vaadin/vaadin-material-styles': 24.9.15 + '@vaadin/vaadin-themable-mixin': 24.9.15 + lit: 3.3.3 - '@vaadin/component-base@24.6.11': + '@vaadin/component-base@24.9.15': dependencies: '@open-wc/dedupe-mixin': 1.4.0 '@polymer/polymer': 3.5.2 '@vaadin/vaadin-development-mode-detector': 2.0.7 '@vaadin/vaadin-usage-statistics': 2.1.3 - lit: 3.3.2 + lit: 3.3.3 - '@vaadin/field-base@24.6.11': + '@vaadin/field-base@24.9.15': dependencies: '@open-wc/dedupe-mixin': 1.4.0 '@polymer/polymer': 3.5.2 - '@vaadin/a11y-base': 24.6.11 - '@vaadin/component-base': 24.6.11 - lit: 3.3.2 + '@vaadin/a11y-base': 24.9.15 + '@vaadin/component-base': 24.9.15 + lit: 3.3.3 - '@vaadin/grid@24.6.11': + '@vaadin/grid@24.9.15': dependencies: '@open-wc/dedupe-mixin': 1.4.0 '@polymer/polymer': 3.5.2 - '@vaadin/a11y-base': 24.6.11 - '@vaadin/checkbox': 24.6.11 - '@vaadin/component-base': 24.6.11 - '@vaadin/lit-renderer': 24.6.11 - '@vaadin/text-field': 24.6.11 - '@vaadin/vaadin-lumo-styles': 24.6.11 - '@vaadin/vaadin-material-styles': 24.6.11 - '@vaadin/vaadin-themable-mixin': 24.6.11 - lit: 3.3.2 - - '@vaadin/icon@24.6.11': + '@vaadin/a11y-base': 24.9.15 + '@vaadin/checkbox': 24.9.15 + '@vaadin/component-base': 24.9.15 + '@vaadin/lit-renderer': 24.9.15 + '@vaadin/text-field': 24.9.15 + '@vaadin/vaadin-lumo-styles': 24.9.15 + '@vaadin/vaadin-material-styles': 24.9.15 + '@vaadin/vaadin-themable-mixin': 24.9.15 + lit: 3.3.3 + + '@vaadin/icon@24.9.15': dependencies: '@open-wc/dedupe-mixin': 1.4.0 '@polymer/polymer': 3.5.2 - '@vaadin/component-base': 24.6.11 - '@vaadin/vaadin-lumo-styles': 24.6.11 - '@vaadin/vaadin-themable-mixin': 24.6.11 - lit: 3.3.2 + '@vaadin/component-base': 24.9.15 + '@vaadin/vaadin-lumo-styles': 24.9.15 + '@vaadin/vaadin-themable-mixin': 24.9.15 + lit: 3.3.3 - '@vaadin/input-container@24.6.11': + '@vaadin/input-container@24.9.15': dependencies: '@polymer/polymer': 3.5.2 - '@vaadin/component-base': 24.6.11 - '@vaadin/vaadin-lumo-styles': 24.6.11 - '@vaadin/vaadin-material-styles': 24.6.11 - '@vaadin/vaadin-themable-mixin': 24.6.11 - lit: 3.3.2 + '@vaadin/component-base': 24.9.15 + '@vaadin/vaadin-lumo-styles': 24.9.15 + '@vaadin/vaadin-material-styles': 24.9.15 + '@vaadin/vaadin-themable-mixin': 24.9.15 + lit: 3.3.3 - '@vaadin/lit-renderer@24.6.11': + '@vaadin/lit-renderer@24.9.15': dependencies: - lit: 3.3.2 + lit: 3.3.3 - '@vaadin/text-field@24.6.11': + '@vaadin/text-field@24.9.15': dependencies: '@open-wc/dedupe-mixin': 1.4.0 '@polymer/polymer': 3.5.2 - '@vaadin/a11y-base': 24.6.11 - '@vaadin/component-base': 24.6.11 - '@vaadin/field-base': 24.6.11 - '@vaadin/input-container': 24.6.11 - '@vaadin/vaadin-lumo-styles': 24.6.11 - '@vaadin/vaadin-material-styles': 24.6.11 - '@vaadin/vaadin-themable-mixin': 24.6.11 - lit: 3.3.2 + '@vaadin/a11y-base': 24.9.15 + '@vaadin/component-base': 24.9.15 + '@vaadin/field-base': 24.9.15 + '@vaadin/input-container': 24.9.15 + '@vaadin/vaadin-lumo-styles': 24.9.15 + '@vaadin/vaadin-material-styles': 24.9.15 + '@vaadin/vaadin-themable-mixin': 24.9.15 + lit: 3.3.3 '@vaadin/vaadin-development-mode-detector@2.0.7': {} - '@vaadin/vaadin-lumo-styles@24.6.11': + '@vaadin/vaadin-lumo-styles@24.9.15': dependencies: '@polymer/polymer': 3.5.2 - '@vaadin/component-base': 24.6.11 - '@vaadin/icon': 24.6.11 - '@vaadin/vaadin-themable-mixin': 24.6.11 + '@vaadin/component-base': 24.9.15 + '@vaadin/icon': 24.9.15 + '@vaadin/vaadin-themable-mixin': 24.9.15 - '@vaadin/vaadin-material-styles@24.6.11': + '@vaadin/vaadin-material-styles@24.9.15': dependencies: '@polymer/polymer': 3.5.2 - '@vaadin/component-base': 24.6.11 - '@vaadin/vaadin-themable-mixin': 24.6.11 + '@vaadin/component-base': 24.9.15 + '@vaadin/vaadin-themable-mixin': 24.9.15 - '@vaadin/vaadin-themable-mixin@24.6.11': + '@vaadin/vaadin-themable-mixin@24.9.15': dependencies: '@open-wc/dedupe-mixin': 1.4.0 - lit: 3.3.2 + lit: 3.3.3 + style-observer: 0.0.8 '@vaadin/vaadin-usage-statistics@2.1.3': dependencies: '@vaadin/vaadin-development-mode-detector': 2.0.7 - '@vitejs/plugin-react@4.3.4(vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2))': + '@vitejs/plugin-react@4.7.0(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0))': dependencies: - '@babel/core': 7.26.9 - '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.9) - '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.9) + '@babel/core': 7.29.7 + '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7) + '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 - react-refresh: 0.14.2 - vite: 6.2.7(@types/node@24.3.0)(yaml@2.8.2) + react-refresh: 0.17.0 + vite: 6.4.3(@types/node@24.12.4)(yaml@2.9.0) transitivePeerDependencies: - supports-color - '@vitest/coverage-v8@4.0.15(vitest@4.0.15(@types/node@24.3.0)(yaml@2.8.2))': + '@vitest/coverage-v8@4.0.15(vitest@4.1.8)': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.0.15 @@ -5424,109 +6182,124 @@ snapshots: istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 istanbul-reports: 3.2.0 - magicast: 0.5.2 + magicast: 0.5.3 obug: 2.1.1 std-env: 3.10.0 - tinyrainbow: 3.0.3 - vitest: 4.0.15(@types/node@24.3.0)(yaml@2.8.2) + tinyrainbow: 3.1.0 + vitest: 4.1.8(@types/node@24.12.4)(@vitest/coverage-v8@4.0.15)(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)) transitivePeerDependencies: - supports-color - '@vitest/expect@3.2.4': + '@vitest/expect@3.2.6': dependencies: '@types/chai': 5.2.3 - '@vitest/spy': 3.2.4 - '@vitest/utils': 3.2.4 + '@vitest/spy': 3.2.6 + '@vitest/utils': 3.2.6 chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/expect@4.0.15': + '@vitest/expect@4.1.8': dependencies: - '@standard-schema/spec': 1.0.0 + '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.0.15 - '@vitest/utils': 4.0.15 - chai: 6.2.1 - tinyrainbow: 3.0.3 + '@vitest/spy': 4.1.8 + '@vitest/utils': 4.1.8 + chai: 6.2.2 + tinyrainbow: 3.1.0 - '@vitest/mocker@3.2.4(vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2))': + '@vitest/mocker@3.2.6(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0))': dependencies: - '@vitest/spy': 3.2.4 + '@vitest/spy': 3.2.6 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 6.2.7(@types/node@24.3.0)(yaml@2.8.2) + vite: 6.4.3(@types/node@24.12.4)(yaml@2.9.0) - '@vitest/mocker@4.0.15(vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2))': + '@vitest/mocker@4.1.8(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0))': dependencies: - '@vitest/spy': 4.0.15 + '@vitest/spy': 4.1.8 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 6.2.7(@types/node@24.3.0)(yaml@2.8.2) + vite: 6.4.3(@types/node@24.12.4)(yaml@2.9.0) - '@vitest/pretty-format@3.2.4': + '@vitest/pretty-format@3.2.6': dependencies: tinyrainbow: 2.0.0 '@vitest/pretty-format@4.0.15': dependencies: - tinyrainbow: 3.0.3 + tinyrainbow: 3.1.0 + + '@vitest/pretty-format@4.1.8': + dependencies: + tinyrainbow: 3.1.0 - '@vitest/runner@3.2.4': + '@vitest/runner@3.2.6': dependencies: - '@vitest/utils': 3.2.4 + '@vitest/utils': 3.2.6 pathe: 2.0.3 strip-literal: 3.1.0 - '@vitest/runner@4.0.15': + '@vitest/runner@4.1.8': dependencies: - '@vitest/utils': 4.0.15 + '@vitest/utils': 4.1.8 pathe: 2.0.3 - '@vitest/snapshot@3.2.4': + '@vitest/snapshot@3.2.6': dependencies: - '@vitest/pretty-format': 3.2.4 + '@vitest/pretty-format': 3.2.6 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/snapshot@4.0.15': + '@vitest/snapshot@4.1.8': dependencies: - '@vitest/pretty-format': 4.0.15 + '@vitest/pretty-format': 4.1.8 + '@vitest/utils': 4.1.8 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@3.2.4': + '@vitest/spy@3.2.6': dependencies: tinyspy: 4.0.4 - '@vitest/spy@4.0.15': {} + '@vitest/spy@4.1.8': {} - '@vitest/utils@3.2.4': + '@vitest/utils@3.2.6': dependencies: - '@vitest/pretty-format': 3.2.4 + '@vitest/pretty-format': 3.2.6 loupe: 3.2.1 tinyrainbow: 2.0.0 '@vitest/utils@4.0.15': dependencies: '@vitest/pretty-format': 4.0.15 - tinyrainbow: 3.0.3 + tinyrainbow: 3.1.0 + + '@vitest/utils@4.1.8': + dependencies: + '@vitest/pretty-format': 4.1.8 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 '@vivjs/constants@0.17.2': dependencies: '@luma.gl/constants': 9.0.28 - '@vivjs/extensions@0.17.2(@deck.gl/core@9.0.41)': + '@vivjs/constants@0.17.3': + dependencies: + '@luma.gl/constants': 9.0.28 + + '@vivjs/extensions@0.17.3(@deck.gl/core@9.0.41)': dependencies: '@deck.gl/core': 9.0.41 - '@vivjs/constants': 0.17.2 + '@vivjs/constants': 0.17.3 - '@vivjs/layers@0.17.2(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28))': + '@vivjs/layers@0.17.3(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28))': dependencies: '@deck.gl/core': 9.0.41 - '@deck.gl/geo-layers': 9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) - '@deck.gl/layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@deck.gl/geo-layers': 9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@deck.gl/layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) '@luma.gl/constants': 9.0.28 '@luma.gl/core': 9.0.28 '@luma.gl/engine': 9.0.28(@luma.gl/core@9.0.28) @@ -5534,10 +6307,10 @@ snapshots: '@luma.gl/webgl': 9.0.28(@luma.gl/core@9.0.28) '@math.gl/core': 4.1.0 '@math.gl/culling': 4.1.0 - '@vivjs/constants': 0.17.2 - '@vivjs/extensions': 0.17.2(@deck.gl/core@9.0.41) - '@vivjs/loaders': 0.17.2(patch_hash=auxsjwuajoz3k5rha2oxpwrlfm) - '@vivjs/types': 0.17.2 + '@vivjs/constants': 0.17.3 + '@vivjs/extensions': 0.17.3(@deck.gl/core@9.0.41) + '@vivjs/loaders': 0.17.3 + '@vivjs/types': 0.17.3 '@vivjs/loaders@0.17.2(patch_hash=auxsjwuajoz3k5rha2oxpwrlfm)': dependencies: @@ -5546,19 +6319,33 @@ snapshots: lzw-tiff-decoder: 0.1.1 quickselect: 2.0.0 zarr: 0.6.3 - zod: 3.24.2 + zod: 3.25.76 + + '@vivjs/loaders@0.17.3': + dependencies: + '@vivjs/types': 0.17.3 + geotiff: 2.1.3 + lzw-tiff-decoder: 0.1.1 + quickselect: 2.0.0 + zarr: 0.6.3 + zod: 3.25.76 '@vivjs/types@0.17.2': dependencies: '@vivjs/constants': 0.17.2 math.gl: 4.1.0 - '@vivjs/viewers@0.17.2(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/react@9.0.41(@deck.gl/core@9.0.41)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28))(react@18.3.1)': + '@vivjs/types@0.17.3': + dependencies: + '@vivjs/constants': 0.17.3 + math.gl: 4.1.0 + + '@vivjs/viewers@0.17.3(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/react@9.0.41(@deck.gl/core@9.0.41)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28))(react@18.3.1)': dependencies: '@deck.gl/react': 9.0.41(@deck.gl/core@9.0.41)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@vivjs/constants': 0.17.2 - '@vivjs/extensions': 0.17.2(@deck.gl/core@9.0.41) - '@vivjs/views': 0.17.2(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28)) + '@vivjs/constants': 0.17.3 + '@vivjs/extensions': 0.17.3(@deck.gl/core@9.0.41) + '@vivjs/views': 0.17.3(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28)) fast-deep-equal: 3.1.3 react: 18.3.1 transitivePeerDependencies: @@ -5571,13 +6358,13 @@ snapshots: - '@luma.gl/shadertools' - '@luma.gl/webgl' - '@vivjs/views@0.17.2(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28))': + '@vivjs/views@0.17.3(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28))': dependencies: '@deck.gl/core': 9.0.41 - '@deck.gl/layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@deck.gl/layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) '@math.gl/core': 4.1.0 - '@vivjs/layers': 0.17.2(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28)) - '@vivjs/loaders': 0.17.2(patch_hash=auxsjwuajoz3k5rha2oxpwrlfm) + '@vivjs/layers': 0.17.3(@deck.gl/core@9.0.41)(@deck.gl/geo-layers@9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/constants@9.0.28)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/shadertools@9.0.28(@luma.gl/core@9.0.28))(@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28)) + '@vivjs/loaders': 0.17.3 math.gl: 4.1.0 transitivePeerDependencies: - '@deck.gl/geo-layers' @@ -5587,50 +6374,50 @@ snapshots: - '@luma.gl/shadertools' - '@luma.gl/webgl' - '@volar/language-core@2.4.26': + '@volar/language-core@2.4.28': dependencies: - '@volar/source-map': 2.4.26 + '@volar/source-map': 2.4.28 - '@volar/source-map@2.4.26': {} + '@volar/source-map@2.4.28': {} - '@volar/typescript@2.4.26': + '@volar/typescript@2.4.28': dependencies: - '@volar/language-core': 2.4.26 + '@volar/language-core': 2.4.28 path-browserify: 1.0.1 vscode-uri: 3.1.0 - '@vue/compiler-core@3.5.25': + '@vue/compiler-core@3.5.35': dependencies: - '@babel/parser': 7.28.5 - '@vue/shared': 3.5.25 - entities: 4.5.0 + '@babel/parser': 7.29.7 + '@vue/shared': 3.5.35 + entities: 7.0.1 estree-walker: 2.0.2 source-map-js: 1.2.1 - '@vue/compiler-dom@3.5.25': + '@vue/compiler-dom@3.5.35': dependencies: - '@vue/compiler-core': 3.5.25 - '@vue/shared': 3.5.25 + '@vue/compiler-core': 3.5.35 + '@vue/shared': 3.5.35 '@vue/compiler-vue2@2.7.16': dependencies: de-indent: 1.0.2 he: 1.2.0 - '@vue/language-core@2.2.0(typescript@5.8.2)': + '@vue/language-core@2.2.0(typescript@5.9.3)': dependencies: - '@volar/language-core': 2.4.26 - '@vue/compiler-dom': 3.5.25 + '@volar/language-core': 2.4.28 + '@vue/compiler-dom': 3.5.35 '@vue/compiler-vue2': 2.7.16 - '@vue/shared': 3.5.25 + '@vue/shared': 3.5.35 alien-signals: 0.4.14 - minimatch: 9.0.5 + minimatch: 9.0.9 muggle-string: 0.4.1 path-browserify: 1.0.1 optionalDependencies: - typescript: 5.8.2 + typescript: 5.9.3 - '@vue/shared@3.5.25': {} + '@vue/shared@3.5.35': {} '@webcomponents/shadycss@1.11.2': {} @@ -5639,11 +6426,11 @@ snapshots: reference-spec-reader: 0.2.0 unzipit: 1.4.3 - '@zip.js/zip.js@2.7.73': {} + '@zip.js/zip.js@2.8.26': {} - acorn@8.15.0: {} + acorn@8.16.0: {} - agent-base@7.1.4: {} + agent-base@9.0.0: {} aggregate-error@3.1.0: dependencies: @@ -5655,31 +6442,24 @@ snapshots: clean-stack: 5.3.0 indent-string: 5.0.0 - ajv-draft-04@1.0.0(ajv@8.13.0): + ajv-draft-04@1.0.0(ajv@8.18.0): optionalDependencies: - ajv: 8.13.0 + ajv: 8.18.0 - ajv-formats@3.0.1(ajv@8.13.0): + ajv-formats@3.0.1(ajv@8.18.0): optionalDependencies: - ajv: 8.13.0 - - ajv@8.12.0: - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 + ajv: 8.18.0 - ajv@8.13.0: + ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 + fast-uri: 3.1.2 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - uri-js: 4.4.1 alien-signals@0.4.14: {} - ansi-escapes@7.2.0: + ansi-escapes@7.3.0: dependencies: environment: 1.1.0 @@ -5699,6 +6479,20 @@ snapshots: any-promise@1.3.0: {} + apache-arrow@21.1.0: + dependencies: + '@swc/helpers': 0.5.23 + '@types/command-line-args': 5.2.3 + '@types/command-line-usage': 5.0.4 + '@types/node': 24.12.4 + command-line-args: 6.0.2 + command-line-usage: 7.0.4 + flatbuffers: 25.9.23 + json-bignum: 0.0.3 + tslib: 2.8.1 + transitivePeerDependencies: + - '@75lb/nature' + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -5707,6 +6501,8 @@ snapshots: argv-formatter@1.0.0: {} + array-back@6.2.3: {} + array-ify@1.0.0: {} assertion-error@2.0.1: {} @@ -5719,23 +6515,32 @@ snapshots: babel-plugin-macros@3.1.0: dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.7 cosmiconfig: 7.1.0 - resolve: 1.22.10 + resolve: 1.22.12 balanced-match@1.0.2: {} - base64-js@1.5.1: - optional: true + balanced-match@4.0.4: {} + + base64-js@1.3.1: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.10.33: {} before-after-hook@4.0.0: {} bottleneck@2.19.5: {} - brace-expansion@2.0.2: + brace-expansion@2.1.1: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.6: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -5743,22 +6548,43 @@ snapshots: brotli@1.3.3: dependencies: base64-js: 1.5.1 - optional: true - browserslist@4.24.4: + browserify-zlib@0.2.0: dependencies: - caniuse-lite: 1.0.30001703 - electron-to-chromium: 1.5.114 - node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.24.4) + pako: 1.0.11 + + browserslist@4.28.2: + dependencies: + baseline-browser-mapping: 2.10.33 + caniuse-lite: 1.0.30001793 + electron-to-chromium: 1.5.366 + node-releases: 2.0.47 + update-browserslist-db: 1.2.3(browserslist@4.28.2) buf-compare@1.0.1: {} cac@6.7.14: {} + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.9: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + callsites@3.1.0: {} - caniuse-lite@1.0.30001703: {} + caniuse-lite@1.0.30001793: {} cartocolor@5.0.2: dependencies: @@ -5772,7 +6598,11 @@ snapshots: loupe: 3.2.1 pathval: 2.0.1 - chai@6.2.1: {} + chai@6.2.2: {} + + chalk-template@0.4.0: + dependencies: + chalk: 4.1.2 chalk@2.4.2: dependencies: @@ -5823,9 +6653,11 @@ snapshots: cliui@9.0.1: dependencies: string-width: 7.2.0 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 wrap-ansi: 9.0.2 + clone@1.0.4: {} + clsx@1.2.1: {} clsx@2.1.1: {} @@ -5859,8 +6691,24 @@ snapshots: colorbrewer@1.5.6: {} + command-line-args@6.0.2: + dependencies: + array-back: 6.2.3 + find-replace: 5.0.2 + lodash.camelcase: 4.3.0 + typical: 7.3.0 + + command-line-usage@7.0.4: + dependencies: + array-back: 6.2.3 + chalk-template: 0.4.0 + table-layout: 4.1.1 + typical: 7.3.0 + commander@2.20.3: {} + commander@7.2.0: {} + compare-func@2.0.0: dependencies: array-ify: 1.0.0 @@ -5868,34 +6716,38 @@ snapshots: compare-versions@6.1.1: {} - composed-offset-position@0.0.6(@floating-ui/utils@0.2.10): + composed-offset-position@0.0.6(@floating-ui/utils@0.2.11): dependencies: - '@floating-ui/utils': 0.2.10 + '@floating-ui/utils': 0.2.11 confbox@0.1.8: {} - confbox@0.2.2: {} + confbox@0.2.4: {} config-chain@1.1.13: dependencies: ini: 1.3.8 proto-list: 1.2.4 - conventional-changelog-angular@8.1.0: + content-type@2.0.0: {} + + conventional-changelog-angular@8.3.1: dependencies: compare-func: 2.0.0 - conventional-changelog-writer@8.2.0: + conventional-changelog-writer@8.4.0: dependencies: + '@simple-libs/stream-utils': 1.2.0 conventional-commits-filter: 5.0.0 - handlebars: 4.7.8 + handlebars: 4.7.9 meow: 13.2.0 - semver: 7.7.3 + semver: 7.8.1 conventional-commits-filter@5.0.0: {} - conventional-commits-parser@6.2.1: + conventional-commits-parser@6.4.0: dependencies: + '@simple-libs/stream-utils': 1.2.0 meow: 13.2.0 convert-hrtime@5.0.0: {} @@ -5917,16 +6769,16 @@ snapshots: import-fresh: 3.3.1 parse-json: 5.2.0 path-type: 4.0.0 - yaml: 1.10.2 + yaml: 1.10.3 - cosmiconfig@9.0.0(typescript@5.8.2): + cosmiconfig@9.0.1(typescript@5.9.3): dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 - js-yaml: 4.1.0 + js-yaml: 4.2.0 parse-json: 5.2.0 optionalDependencies: - typescript: 5.8.2 + typescript: 5.9.3 cross-spawn@7.0.6: dependencies: @@ -5936,36 +6788,129 @@ snapshots: crypt@0.0.2: {} + crypto-js@4.2.0: {} + crypto-random-string@4.0.0: dependencies: type-fest: 1.4.0 cssfilter@0.0.10: {} - csstype@3.1.3: {} + csstype@3.2.3: {} + + d3-array@2.12.1: + dependencies: + internmap: 1.0.1 d3-array@3.2.4: dependencies: internmap: 2.0.3 + d3-axis@3.0.0: {} + + d3-brush@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3-chord@3.0.1: + dependencies: + d3-path: 3.1.0 + d3-color@3.1.0: {} - d3-format@3.1.0: {} + d3-contour@4.0.2: + dependencies: + d3-array: 3.2.4 + + d3-delaunay@6.0.4: + dependencies: + delaunator: 5.1.0 + + d3-dispatch@2.0.0: {} + + d3-dispatch@3.0.1: {} + + d3-drag@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + + d3-dsv@3.0.1: + dependencies: + commander: 7.2.0 + iconv-lite: 0.6.3 + rw: 1.3.3 + + d3-ease@3.0.1: {} + + d3-fetch@3.0.1: + dependencies: + d3-dsv: 3.0.1 + + d3-force@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + + d3-format@3.1.2: {} + + d3-geo@3.1.1: + dependencies: + d3-array: 3.2.4 d3-hexbin@0.2.2: {} + d3-hierarchy@3.1.2: {} + d3-interpolate@3.0.1: dependencies: d3-color: 3.1.0 + d3-path@1.0.9: {} + + d3-path@3.1.0: {} + + d3-polygon@2.0.0: {} + + d3-polygon@3.0.1: {} + + d3-quadtree@3.0.1: {} + + d3-random@3.0.1: {} + + d3-sankey@0.12.3: + dependencies: + d3-array: 2.12.1 + d3-shape: 1.3.7 + + d3-scale-chromatic@3.1.0: + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + d3-scale@4.0.2: dependencies: d3-array: 3.2.4 - d3-format: 3.1.0 + d3-format: 3.1.2 d3-interpolate: 3.0.1 d3-time: 3.1.0 d3-time-format: 4.1.0 + d3-selection@3.0.0: {} + + d3-shape@1.3.7: + dependencies: + d3-path: 1.0.9 + + d3-shape@3.2.0: + dependencies: + d3-path: 3.1.0 + d3-time-format@4.1.0: dependencies: d3-time: 3.1.0 @@ -5974,48 +6919,143 @@ snapshots: dependencies: d3-array: 3.2.4 - de-indent@1.0.2: {} + d3-timer@2.0.0: {} + + d3-timer@3.0.1: {} - debug@4.4.0: + d3-transition@3.0.1(d3-selection@3.0.0): dependencies: - ms: 2.1.3 + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + + d3-voronoi-map@2.1.1: + dependencies: + d3-dispatch: 2.0.0 + d3-polygon: 2.0.0 + d3-timer: 2.0.0 + d3-weighted-voronoi: 1.1.3 + + d3-voronoi-treemap@1.1.2: + dependencies: + d3-voronoi-map: 2.1.1 + + d3-weighted-voronoi@1.1.3: + dependencies: + d3-array: 2.12.1 + d3-polygon: 2.0.0 + + d3-zoom@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3@7.9.0: + dependencies: + d3-array: 3.2.4 + d3-axis: 3.0.0 + d3-brush: 3.0.0 + d3-chord: 3.0.1 + d3-color: 3.1.0 + d3-contour: 4.0.2 + d3-delaunay: 6.0.4 + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-dsv: 3.0.1 + d3-ease: 3.0.1 + d3-fetch: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.2 + d3-geo: 3.1.1 + d3-hierarchy: 3.1.2 + d3-interpolate: 3.0.1 + d3-path: 3.1.0 + d3-polygon: 3.0.1 + d3-quadtree: 3.0.1 + d3-random: 3.0.1 + d3-scale: 4.0.2 + d3-scale-chromatic: 3.1.0 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + d3-timer: 3.0.1 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-zoom: 3.0.0 + + de-indent@1.0.2: {} debug@4.4.3: dependencies: ms: 2.1.3 - deck.gl@9.0.41(@arcgis/core@4.32.8(@lit/context@1.1.6))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + deck.gl@9.0.41(@arcgis/core@4.34.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@deck.gl/aggregation-layers': 9.0.41(@deck.gl/core@9.0.41)(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) - '@deck.gl/arcgis': 9.0.41(@arcgis/core@4.32.8(@lit/context@1.1.6))(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) - '@deck.gl/carto': 9.0.41(m67uvbolj56khq5wgiv5vk2uge) + '@deck.gl/aggregation-layers': 9.0.41(@deck.gl/core@9.0.41)(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@deck.gl/arcgis': 9.0.41(@arcgis/core@4.34.8)(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@deck.gl/carto': 9.0.41(h3geslv24d6m33k2qxfmttsmcm) '@deck.gl/core': 9.0.41 '@deck.gl/extensions': 9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) - '@deck.gl/geo-layers': 9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@deck.gl/geo-layers': 9.0.41(@deck.gl/core@9.0.41)(@deck.gl/extensions@9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@deck.gl/mesh-layers@9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)))(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) '@deck.gl/google-maps': 9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28) '@deck.gl/json': 9.0.41(@deck.gl/core@9.0.41) - '@deck.gl/layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@deck.gl/layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) '@deck.gl/mapbox': 9.0.41(@deck.gl/core@9.0.41)(@luma.gl/core@9.0.28) - '@deck.gl/mesh-layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.3.3)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) + '@deck.gl/mesh-layers': 9.0.41(@deck.gl/core@9.0.41)(@loaders.gl/core@4.4.2)(@luma.gl/core@9.0.28)(@luma.gl/engine@9.0.28(@luma.gl/core@9.0.28)) '@deck.gl/react': 9.0.41(@deck.gl/core@9.0.41)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@deck.gl/widgets': 9.0.41(@deck.gl/core@9.0.41) - '@loaders.gl/core': 4.3.3 + '@loaders.gl/core': 4.4.2 '@luma.gl/core': 9.0.28 '@luma.gl/engine': 9.0.28(@luma.gl/core@9.0.28) optionalDependencies: - '@arcgis/core': 4.32.8(@lit/context@1.1.6) + '@arcgis/core': 4.34.8 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + transitivePeerDependencies: + - '@75lb/nature' deep-eql@5.0.2: {} + deep-equal@1.1.2: + dependencies: + is-arguments: 1.2.0 + is-date-object: 1.1.0 + is-regex: 1.2.1 + object-is: 1.1.6 + object-keys: 1.1.1 + regexp.prototype.flags: 1.5.4 + deep-extend@0.6.0: {} deep-strict-equal@0.2.0: dependencies: core-assert: 0.2.1 - diff@8.0.2: {} + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + delaunator@5.1.0: + dependencies: + robust-predicates: 3.0.3 + + dfa@1.2.0: {} + + diff@8.0.4: {} dir-glob@3.0.1: dependencies: @@ -6023,8 +7063,8 @@ snapshots: dom-helpers@5.2.1: dependencies: - '@babel/runtime': 7.28.4 - csstype: 3.1.3 + '@babel/runtime': 7.29.7 + csstype: 3.2.3 dot-prop@5.3.0: dependencies: @@ -6032,13 +7072,19 @@ snapshots: draco3d@1.5.7: {} + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + duplexer2@0.1.4: dependencies: readable-stream: 2.3.8 earcut@2.2.4: {} - electron-to-chromium@1.5.114: {} + electron-to-chromium@1.5.366: {} emoji-regex@10.6.0: {} @@ -6046,7 +7092,7 @@ snapshots: emojilib@2.4.0: {} - entities@4.5.0: {} + entities@7.0.1: {} env-ci@11.2.0: dependencies: @@ -6061,37 +7107,48 @@ snapshots: dependencies: is-arrayish: 0.2.1 + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + es-module-lexer@1.7.0: {} - es-toolkit@1.44.0: {} + es-module-lexer@2.1.0: {} - esbuild@0.25.3: + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-toolkit@1.47.0: {} + + esbuild@0.25.12: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.3 - '@esbuild/android-arm': 0.25.3 - '@esbuild/android-arm64': 0.25.3 - '@esbuild/android-x64': 0.25.3 - '@esbuild/darwin-arm64': 0.25.3 - '@esbuild/darwin-x64': 0.25.3 - '@esbuild/freebsd-arm64': 0.25.3 - '@esbuild/freebsd-x64': 0.25.3 - '@esbuild/linux-arm': 0.25.3 - '@esbuild/linux-arm64': 0.25.3 - '@esbuild/linux-ia32': 0.25.3 - '@esbuild/linux-loong64': 0.25.3 - '@esbuild/linux-mips64el': 0.25.3 - '@esbuild/linux-ppc64': 0.25.3 - '@esbuild/linux-riscv64': 0.25.3 - '@esbuild/linux-s390x': 0.25.3 - '@esbuild/linux-x64': 0.25.3 - '@esbuild/netbsd-arm64': 0.25.3 - '@esbuild/netbsd-x64': 0.25.3 - '@esbuild/openbsd-arm64': 0.25.3 - '@esbuild/openbsd-x64': 0.25.3 - '@esbuild/sunos-x64': 0.25.3 - '@esbuild/win32-arm64': 0.25.3 - '@esbuild/win32-ia32': 0.25.3 - '@esbuild/win32-x64': 0.25.3 + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 escalade@3.2.0: {} @@ -6107,9 +7164,9 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.9 - eventemitter3@5.0.1: {} + eventemitter3@5.0.4: {} execa@5.1.1: dependencies: @@ -6135,7 +7192,7 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 - execa@9.6.0: + execa@9.6.1: dependencies: '@sindresorhus/merge-streams': 4.0.0 cross-spawn: 7.0.6 @@ -6154,21 +7211,30 @@ snapshots: exsolve@1.0.8: {} - fast-content-type-parse@3.0.0: {} - fast-deep-equal@3.1.3: {} - fast-xml-parser@4.5.3: + fast-uri@3.1.2: {} + + fast-xml-builder@1.2.0: dependencies: - strnum: 1.1.2 + path-expression-matcher: 1.5.0 + xml-naming: 0.1.0 - fdir@6.5.0(picomatch@4.0.3): + fast-xml-parser@5.8.0: + dependencies: + '@nodable/entities': 2.1.1 + fast-xml-builder: 1.2.0 + path-expression-matcher: 1.5.0 + strnum: 2.3.0 + xml-naming: 0.1.0 + + fdir@6.5.0(picomatch@4.0.4): optionalDependencies: - picomatch: 4.0.3 + picomatch: 4.0.4 fflate@0.7.4: {} - fflate@0.8.2: {} + fflate@0.8.3: {} figures@2.0.0: dependencies: @@ -6182,6 +7248,8 @@ snapshots: dependencies: to-regex-range: 5.0.1 + find-replace@5.0.2: {} + find-root@1.1.0: {} find-up-simple@1.0.1: {} @@ -6195,19 +7263,18 @@ snapshots: semver-regex: 4.0.5 super-regex: 1.1.0 + flatbuffers@25.9.23: {} + + flatpickr@4.6.13: {} + focus-trap@7.8.0: dependencies: tabbable: 6.4.0 - from2@2.3.0: - dependencies: - inherits: 2.0.4 - readable-stream: 2.3.8 - - fs-extra@11.3.2: + fs-extra@11.3.5: dependencies: graceful-fs: 4.2.11 - jsonfile: 6.2.0 + jsonfile: 6.2.1 universalify: 2.0.1 fsevents@2.3.3: @@ -6217,26 +7284,44 @@ snapshots: function-timeout@1.0.2: {} + functions-have-names@1.2.3: {} + gensync@1.0.0-beta.2: {} geotiff@2.1.3: dependencies: - '@petamoriken/float16': 3.9.2 + '@petamoriken/float16': 3.9.3 lerc: 3.0.0 pako: 2.1.0 - parse-headers: 2.0.5 + parse-headers: 2.0.6 quick-lru: 6.1.2 web-worker: 1.5.0 - xml-utils: 1.10.1 + xml-utils: 1.10.2 zstddec: 0.1.0 get-caller-file@2.0.5: {} - get-east-asian-width@1.4.0: {} + get-east-asian-width@1.6.0: {} - get-stream@6.0.1: {} + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 - get-stream@7.0.1: {} + get-stream@6.0.1: {} get-stream@8.0.1: {} @@ -6254,23 +7339,23 @@ snapshots: through2: 2.0.5 traverse: 0.6.8 - gl-matrix@3.4.3: {} - - globals@11.12.0: {} + gl-matrix@3.4.4: {} - goober@2.1.18(csstype@3.1.3): + goober@2.1.19(csstype@3.2.3): dependencies: - csstype: 3.1.3 + csstype: 3.2.3 + + gopd@1.2.0: {} graceful-fs@4.2.10: {} graceful-fs@4.2.11: {} - h3-js@4.1.0: {} + h3-js@4.4.0: {} hammerjs@2.0.8: {} - handlebars@4.7.8: + handlebars@4.7.9: dependencies: minimist: 1.2.8 neo-async: 2.6.2 @@ -6283,7 +7368,17 @@ snapshots: has-flag@4.0.0: {} - hasown@2.0.2: + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.4: dependencies: function-bind: 1.1.2 @@ -6301,23 +7396,23 @@ snapshots: dependencies: lru-cache: 10.4.3 - hosted-git-info@9.0.2: + hosted-git-info@9.0.3: dependencies: - lru-cache: 11.2.2 + lru-cache: 11.5.1 html-escaper@2.0.2: {} - http-proxy-agent@7.0.2: + http-proxy-agent@9.0.0: dependencies: - agent-base: 7.1.4 - debug: 4.4.0 + agent-base: 9.0.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color - https-proxy-agent@7.0.6: + https-proxy-agent@9.0.0: dependencies: - agent-base: 7.1.4 - debug: 4.4.0 + agent-base: 9.0.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -6327,7 +7422,15 @@ snapshots: human-signals@8.0.1: {} - hyparquet@1.25.6: {} + hyparquet@1.26.0: {} + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.7.2: + dependencies: + safer-buffer: 2.1.2 ieee754@1.2.1: {} @@ -6342,7 +7445,7 @@ snapshots: import-from-esm@2.0.0: dependencies: - debug: 4.4.0 + debug: 4.4.3 import-meta-resolve: 4.2.0 transitivePeerDependencies: - supports-color @@ -6365,20 +7468,27 @@ snapshots: dependencies: '@interactjs/types': 1.10.27 + internmap@1.0.1: {} + internmap@2.0.3: {} - into-stream@7.0.0: + is-arguments@1.2.0: dependencies: - from2: 2.3.0 - p-is-promise: 3.0.0 + call-bound: 1.0.4 + has-tostringtag: 1.0.2 is-arrayish@0.2.1: {} is-buffer@1.1.6: {} - is-core-module@2.16.1: + is-core-module@2.16.2: + dependencies: + hasown: 2.0.4 + + is-date-object@1.1.0: dependencies: - hasown: 2.0.2 + call-bound: 1.0.4 + has-tostringtag: 1.0.2 is-error@2.2.2: {} @@ -6390,6 +7500,13 @@ snapshots: is-plain-obj@4.1.0: {} + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + is-stream@2.0.1: {} is-stream@3.0.0: {} @@ -6402,7 +7519,7 @@ snapshots: isexe@2.0.0: {} - issue-parser@7.0.1: + issue-parser@7.0.2: dependencies: lodash.capitalize: 4.2.1 lodash.escaperegexp: 4.1.2 @@ -6420,8 +7537,8 @@ snapshots: istanbul-lib-source-maps@5.0.6: dependencies: - '@jridgewell/trace-mapping': 0.3.25 - debug: 4.4.0 + '@jridgewell/trace-mapping': 0.3.31 + debug: 4.4.3 istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color @@ -6435,12 +7552,14 @@ snapshots: jju@1.4.0: {} - jotai@1.13.1(@babel/core@7.26.9)(@babel/template@7.26.9)(react@18.3.1): + jotai@1.13.1(@babel/core@7.29.7)(@babel/template@7.29.7)(react@18.3.1): dependencies: react: 18.3.1 optionalDependencies: - '@babel/core': 7.26.9 - '@babel/template': 7.26.9 + '@babel/core': 7.29.7 + '@babel/template': 7.29.7 + + jpeg-exif@1.1.4: {} js-tokens@10.0.0: {} @@ -6448,7 +7567,7 @@ snapshots: js-tokens@9.0.1: {} - js-yaml@4.1.0: + js-yaml@4.2.0: dependencies: argparse: 2.0.1 @@ -6456,15 +7575,19 @@ snapshots: jsesc@3.1.0: {} + json-bignum@0.0.3: {} + json-parse-better-errors@1.0.2: {} json-parse-even-better-errors@2.3.1: {} json-schema-traverse@1.0.0: {} + json-with-bigint@3.5.8: {} + json5@2.2.3: {} - jsonfile@6.2.0: + jsonfile@6.2.1: dependencies: universalify: 2.0.1 optionalDependencies: @@ -6493,19 +7616,19 @@ snapshots: lit-element@4.2.2: dependencies: - '@lit-labs/ssr-dom-shim': 1.5.1 + '@lit-labs/ssr-dom-shim': 1.6.0 '@lit/reactive-element': 2.1.2 - lit-html: 3.3.2 + lit-html: 3.3.3 - lit-html@3.3.2: + lit-html@3.3.3: dependencies: '@types/trusted-types': 2.0.7 - lit@3.3.2: + lit@3.3.3: dependencies: '@lit/reactive-element': 2.1.2 lit-element: 4.2.2 - lit-html: 3.3.2 + lit-html: 3.3.3 load-json-file@4.0.0: dependencies: @@ -6514,10 +7637,10 @@ snapshots: pify: 3.0.0 strip-bom: 3.0.0 - local-pkg@1.1.2: + local-pkg@1.2.1: dependencies: - mlly: 1.8.0 - pkg-types: 2.3.0 + mlly: 1.8.2 + pkg-types: 2.3.1 quansync: 0.2.11 locate-path@2.0.0: @@ -6525,7 +7648,9 @@ snapshots: p-locate: 2.0.0 path-exists: 3.0.0 - lodash-es@4.17.21: {} + lodash-es@4.18.1: {} + + lodash.camelcase@4.3.0: {} lodash.capitalize@4.2.1: {} @@ -6537,11 +7662,11 @@ snapshots: lodash.uniqby@4.7.0: {} - lodash@4.17.21: {} + lodash@4.18.1: {} long@3.2.0: {} - long@5.3.1: {} + long@5.3.2: {} loose-envify@1.4.0: dependencies: @@ -6551,48 +7676,42 @@ snapshots: lru-cache@10.4.3: {} - lru-cache@11.2.2: {} + lru-cache@11.5.1: {} lru-cache@5.1.1: dependencies: yallist: 3.1.1 - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - - luxon@3.5.0: {} + luxon@3.7.2: {} lz4js@0.2.0: optional: true - lzo-wasm@0.0.4: {} - lzw-tiff-decoder@0.1.1: {} magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - magicast@0.5.2: + magicast@0.5.3: dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 source-map-js: 1.2.1 - make-asynchronous@1.0.1: + make-asynchronous@1.1.0: dependencies: p-event: 6.0.1 type-fest: 4.41.0 - web-worker: 1.2.0 + web-worker: 1.5.0 make-dir@4.0.0: dependencies: - semver: 7.7.3 + semver: 7.8.1 marked-terminal@7.3.0(marked@15.0.12): dependencies: - ansi-escapes: 7.2.0 + ansi-escapes: 7.3.0 ansi-regex: 6.2.2 chalk: 5.6.2 cli-highlight: 2.1.11 @@ -6603,6 +7722,12 @@ snapshots: marked@15.0.12: {} + marked@16.3.0: {} + + markerjs2@2.32.7: {} + + math-intrinsics@1.1.0: {} + math.gl@4.1.0: dependencies: '@math.gl/core': 4.1.0 @@ -6620,7 +7745,7 @@ snapshots: micromatch@4.0.8: dependencies: braces: 3.0.3 - picomatch: 2.3.1 + picomatch: 2.3.2 mime@4.1.0: {} @@ -6628,13 +7753,13 @@ snapshots: mimic-fn@4.0.0: {} - minimatch@10.0.3: + minimatch@10.2.3: dependencies: - '@isaacs/brace-expansion': 5.0.0 + brace-expansion: 5.0.6 - minimatch@9.0.5: + minimatch@9.0.9: dependencies: - brace-expansion: 2.0.2 + brace-expansion: 2.1.1 minimist@1.2.8: {} @@ -6643,14 +7768,14 @@ snapshots: '@types/hammerjs': 2.0.46 hammerjs: 2.0.8 - mlly@1.8.0: + mlly@1.8.2: dependencies: - acorn: 8.15.0 + acorn: 8.16.0 pathe: 2.0.3 pkg-types: 1.3.1 - ufo: 1.6.1 + ufo: 1.6.4 - moment-timezone@0.5.47: + moment-timezone@0.5.48: dependencies: moment: 2.30.1 @@ -6666,7 +7791,7 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nanoid@3.3.11: {} + nanoid@3.3.12: {} neo-async@2.6.2: {} @@ -6679,26 +7804,26 @@ snapshots: emojilib: 2.4.0 skin-tone: 2.0.0 - node-releases@2.0.19: {} + node-releases@2.0.47: {} normalize-package-data@6.0.2: dependencies: hosted-git-info: 7.0.2 - semver: 7.7.3 + semver: 7.8.1 validate-npm-package-license: 3.0.4 normalize-package-data@8.0.0: dependencies: - hosted-git-info: 9.0.2 - semver: 7.7.3 + hosted-git-info: 9.0.3 + semver: 7.8.1 validate-npm-package-license: 3.0.4 - normalize-url@8.1.0: {} + normalize-url@9.0.1: {} - notistack@3.0.2(csstype@3.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + notistack@3.0.2(csstype@3.2.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: clsx: 1.2.1 - goober: 2.1.18(csstype@3.1.3) + goober: 2.1.19(csstype@3.2.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: @@ -6717,16 +7842,23 @@ snapshots: path-key: 4.0.0 unicorn-magic: 0.3.0 - npm@11.6.2: {} + npm@11.16.0: {} numcodecs@0.2.2: {} numcodecs@0.3.2: dependencies: - fflate: 0.8.2 + fflate: 0.8.3 object-assign@4.1.1: {} + object-is@1.1.6: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + + object-keys@1.1.1: {} + obug@2.1.1: {} onetime@5.1.2: @@ -6745,9 +7877,7 @@ snapshots: p-filter@4.1.0: dependencies: - p-map: 7.0.3 - - p-is-promise@3.0.0: {} + p-map: 7.0.4 p-limit@1.3.0: dependencies: @@ -6757,11 +7887,11 @@ snapshots: dependencies: p-limit: 1.3.0 - p-map@7.0.3: {} + p-map@7.0.4: {} p-queue@7.4.1: dependencies: - eventemitter3: 5.0.1 + eventemitter3: 5.0.4 p-timeout: 5.1.0 p-reduce@2.1.0: {} @@ -6774,6 +7904,8 @@ snapshots: p-try@1.0.0: {} + pako@0.2.9: {} + pako@1.0.11: {} pako@2.1.0: {} @@ -6782,7 +7914,7 @@ snapshots: dependencies: callsites: 3.1.0 - parse-headers@2.0.5: {} + parse-headers@2.0.6: {} parse-json@4.0.0: dependencies: @@ -6791,14 +7923,14 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.26.2 + '@babel/code-frame': 7.29.7 error-ex: 1.3.4 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 parse-json@8.3.0: dependencies: - '@babel/code-frame': 7.26.2 + '@babel/code-frame': 7.29.7 index-to-position: 1.2.0 type-fest: 4.41.0 @@ -6816,6 +7948,8 @@ snapshots: path-exists@3.0.0: {} + path-expression-matcher@1.5.0: {} + path-key@3.1.1: {} path-key@4.0.0: {} @@ -6833,11 +7967,18 @@ snapshots: ieee754: 1.2.1 resolve-protobuf-schema: 2.1.0 + pdfmake@0.2.23: + dependencies: + '@foliojs-fork/linebreak': 1.1.2 + '@foliojs-fork/pdfkit': 0.15.3 + iconv-lite: 0.7.2 + xmldoc: 2.0.3 + picocolors@1.1.1: {} - picomatch@2.3.1: {} + picomatch@2.3.2: {} - picomatch@4.0.3: {} + picomatch@4.0.4: {} pify@3.0.0: {} @@ -6849,22 +7990,30 @@ snapshots: pkg-types@1.3.1: dependencies: confbox: 0.1.8 - mlly: 1.8.0 + mlly: 1.8.2 pathe: 2.0.3 - pkg-types@2.3.0: + pkg-types@2.3.1: dependencies: - confbox: 0.2.2 + confbox: 0.2.4 exsolve: 1.0.8 pathe: 2.0.3 - postcss@8.5.3: + png-js@1.1.0: dependencies: - nanoid: 3.3.11 + browserify-zlib: 0.2.0 + + polylabel@1.1.0: + dependencies: + tinyqueue: 2.0.3 + + postcss@8.5.15: + dependencies: + nanoid: 3.3.12 picocolors: 1.1.1 source-map-js: 1.2.1 - preact@10.26.4: {} + preact@10.29.2: {} pretty-ms@9.3.0: dependencies: @@ -6880,9 +8029,7 @@ snapshots: proto-list@1.2.4: {} - protocol-buffers-schema@3.6.0: {} - - punycode@2.3.1: {} + protocol-buffers-schema@3.6.1: {} quadbin@0.2.0: dependencies: @@ -6892,7 +8039,7 @@ snapshots: quick-lru@6.1.2: {} - quick-lru@7.0.0: {} + quick-lru@7.3.0: {} quickselect@2.0.0: {} @@ -6913,13 +8060,13 @@ snapshots: react-is@18.3.1: {} - react-is@19.2.0: {} + react-is@19.2.7: {} - react-refresh@0.14.2: {} + react-refresh@0.17.0: {} react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.7 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -6944,16 +8091,16 @@ snapshots: read-package-up@12.0.0: dependencies: find-up-simple: 1.0.1 - read-pkg: 10.0.0 - type-fest: 5.2.0 + read-pkg: 10.1.0 + type-fest: 5.7.0 - read-pkg@10.0.0: + read-pkg@10.1.0: dependencies: '@types/normalize-package-data': 2.4.4 normalize-package-data: 8.0.0 parse-json: 8.3.0 - type-fest: 5.2.0 - unicorn-magic: 0.3.0 + type-fest: 5.7.0 + unicorn-magic: 0.4.0 read-pkg@9.0.1: dependencies: @@ -6975,9 +8122,18 @@ snapshots: reference-spec-reader@0.2.0: {} - registry-auth-token@5.1.0: + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + registry-auth-token@5.1.1: dependencies: - '@pnpm/npm-conf': 2.3.1 + '@pnpm/npm-conf': 3.0.2 require-directory@2.1.1: {} @@ -6989,66 +8145,82 @@ snapshots: resolve-protobuf-schema@2.1.0: dependencies: - protocol-buffers-schema: 3.6.0 + protocol-buffers-schema: 3.6.1 - resolve@1.22.10: + resolve@1.22.12: dependencies: - is-core-module: 2.16.1 + es-errors: 1.3.0 + is-core-module: 2.16.2 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - rollup@4.40.1: + robust-predicates@3.0.3: {} + + rollup@4.61.0: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.9 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.40.1 - '@rollup/rollup-android-arm64': 4.40.1 - '@rollup/rollup-darwin-arm64': 4.40.1 - '@rollup/rollup-darwin-x64': 4.40.1 - '@rollup/rollup-freebsd-arm64': 4.40.1 - '@rollup/rollup-freebsd-x64': 4.40.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.40.1 - '@rollup/rollup-linux-arm-musleabihf': 4.40.1 - '@rollup/rollup-linux-arm64-gnu': 4.40.1 - '@rollup/rollup-linux-arm64-musl': 4.40.1 - '@rollup/rollup-linux-loongarch64-gnu': 4.40.1 - '@rollup/rollup-linux-powerpc64le-gnu': 4.40.1 - '@rollup/rollup-linux-riscv64-gnu': 4.40.1 - '@rollup/rollup-linux-riscv64-musl': 4.40.1 - '@rollup/rollup-linux-s390x-gnu': 4.40.1 - '@rollup/rollup-linux-x64-gnu': 4.40.1 - '@rollup/rollup-linux-x64-musl': 4.40.1 - '@rollup/rollup-win32-arm64-msvc': 4.40.1 - '@rollup/rollup-win32-ia32-msvc': 4.40.1 - '@rollup/rollup-win32-x64-msvc': 4.40.1 + '@rollup/rollup-android-arm-eabi': 4.61.0 + '@rollup/rollup-android-arm64': 4.61.0 + '@rollup/rollup-darwin-arm64': 4.61.0 + '@rollup/rollup-darwin-x64': 4.61.0 + '@rollup/rollup-freebsd-arm64': 4.61.0 + '@rollup/rollup-freebsd-x64': 4.61.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.61.0 + '@rollup/rollup-linux-arm-musleabihf': 4.61.0 + '@rollup/rollup-linux-arm64-gnu': 4.61.0 + '@rollup/rollup-linux-arm64-musl': 4.61.0 + '@rollup/rollup-linux-loong64-gnu': 4.61.0 + '@rollup/rollup-linux-loong64-musl': 4.61.0 + '@rollup/rollup-linux-ppc64-gnu': 4.61.0 + '@rollup/rollup-linux-ppc64-musl': 4.61.0 + '@rollup/rollup-linux-riscv64-gnu': 4.61.0 + '@rollup/rollup-linux-riscv64-musl': 4.61.0 + '@rollup/rollup-linux-s390x-gnu': 4.61.0 + '@rollup/rollup-linux-x64-gnu': 4.61.0 + '@rollup/rollup-linux-x64-musl': 4.61.0 + '@rollup/rollup-openbsd-x64': 4.61.0 + '@rollup/rollup-openharmony-arm64': 4.61.0 + '@rollup/rollup-win32-arm64-msvc': 4.61.0 + '@rollup/rollup-win32-ia32-msvc': 4.61.0 + '@rollup/rollup-win32-x64-gnu': 4.61.0 + '@rollup/rollup-win32-x64-msvc': 4.61.0 fsevents: 2.3.3 + rw@1.3.3: {} + safe-buffer@5.1.2: {} + safer-buffer@2.1.2: {} + + sax@1.6.0: {} + scheduler@0.23.2: dependencies: loose-envify: 1.4.0 - semantic-release@25.0.2(typescript@5.8.2): + seedrandom@3.0.5: {} + + semantic-release@25.0.3(typescript@5.9.3): dependencies: - '@semantic-release/commit-analyzer': 13.0.1(semantic-release@25.0.2(typescript@5.8.2)) + '@semantic-release/commit-analyzer': 13.0.1(semantic-release@25.0.3(typescript@5.9.3)) '@semantic-release/error': 4.0.0 - '@semantic-release/github': 12.0.2(semantic-release@25.0.2(typescript@5.8.2)) - '@semantic-release/npm': 13.1.1(semantic-release@25.0.2(typescript@5.8.2)) - '@semantic-release/release-notes-generator': 14.1.0(semantic-release@25.0.2(typescript@5.8.2)) + '@semantic-release/github': 12.0.8(semantic-release@25.0.3(typescript@5.9.3)) + '@semantic-release/npm': 13.1.5(semantic-release@25.0.3(typescript@5.9.3)) + '@semantic-release/release-notes-generator': 14.1.1(semantic-release@25.0.3(typescript@5.9.3)) aggregate-error: 5.0.0 - cosmiconfig: 9.0.0(typescript@5.8.2) - debug: 4.4.0 + cosmiconfig: 9.0.1(typescript@5.9.3) + debug: 4.4.3 env-ci: 11.2.0 - execa: 9.6.0 + execa: 9.6.1 figures: 6.1.0 find-versions: 6.0.0 get-stream: 6.0.1 git-log-parser: 1.2.1 hook-std: 4.0.0 - hosted-git-info: 9.0.2 + hosted-git-info: 9.0.3 import-from-esm: 2.0.0 - lodash-es: 4.17.21 + lodash-es: 4.18.1 marked: 15.0.12 marked-terminal: 7.3.0(marked@15.0.12) micromatch: 4.0.8 @@ -7056,27 +8228,36 @@ snapshots: p-reduce: 3.0.0 read-package-up: 12.0.0 resolve-from: 5.0.0 - semver: 7.7.3 - semver-diff: 5.0.0 + semver: 7.8.1 signale: 1.4.0 yargs: 18.0.0 transitivePeerDependencies: - supports-color - typescript - semver-diff@5.0.0: - dependencies: - semver: 7.7.3 - semver-regex@4.0.5: {} semver@6.3.1: {} - semver@7.5.4: + semver@7.7.4: {} + + semver@7.8.1: {} + + set-function-length@1.2.2: dependencies: - lru-cache: 6.0.0 + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 - semver@7.7.3: {} + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 setimmediate@1.0.5: {} @@ -7117,16 +8298,16 @@ snapshots: spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.22 + spdx-license-ids: 3.0.23 spdx-exceptions@2.5.0: {} spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.22 + spdx-license-ids: 3.0.23 - spdx-license-ids@3.0.22: {} + spdx-license-ids@3.0.23: {} split2@1.0.0: dependencies: @@ -7138,6 +8319,8 @@ snapshots: std-env@3.10.0: {} + std-env@4.1.0: {} + stream-combiner2@1.1.1: dependencies: duplexer2: 0.1.4 @@ -7154,8 +8337,8 @@ snapshots: string-width@7.2.0: dependencies: emoji-regex: 10.6.0 - get-east-asian-width: 1.4.0 - strip-ansi: 7.1.2 + get-east-asian-width: 1.6.0 + strip-ansi: 7.2.0 string_decoder@1.1.1: dependencies: @@ -7165,7 +8348,7 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.2: + strip-ansi@7.2.0: dependencies: ansi-regex: 6.2.2 @@ -7179,20 +8362,20 @@ snapshots: strip-json-comments@2.0.1: {} - strip-json-comments@3.1.1: {} - strip-literal@3.1.0: dependencies: js-tokens: 9.0.1 - strnum@1.1.2: {} + strnum@2.3.0: {} + + style-observer@0.0.8: {} stylis@4.2.0: {} super-regex@1.1.0: dependencies: function-timeout: 1.0.2 - make-asynchronous: 1.0.1 + make-asynchronous: 1.1.0 time-span: 5.1.0 supports-color@5.5.0: @@ -7214,13 +8397,20 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + svg-arc-to-cubic-bezier@3.2.0: {} + tabbable@6.4.0: {} + table-layout@4.1.1: + dependencies: + array-back: 6.2.3 + wordwrapjs: 5.1.1 + tagged-tag@1.0.0: {} temp-dir@3.0.0: {} - tempy@3.1.0: + tempy@3.2.0: dependencies: is-stream: 3.0.0 temp-dir: 3.0.0 @@ -7253,22 +8443,26 @@ snapshots: timezone-groups@0.10.4: {} + tiny-inflate@1.0.3: {} + tinybench@2.9.0: {} tinyexec@0.3.2: {} - tinyexec@1.0.2: {} + tinyexec@1.2.4: {} - tinyglobby@0.2.15: + tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 tinypool@1.1.1: {} + tinyqueue@2.0.3: {} + tinyrainbow@2.0.0: {} - tinyrainbow@3.0.3: {} + tinyrainbow@3.1.0: {} tinyspy@4.0.4: {} @@ -7288,31 +8482,43 @@ snapshots: type-fest@4.41.0: {} - type-fest@5.2.0: + type-fest@5.7.0: dependencies: tagged-tag: 1.0.0 - typescript@5.8.2: {} + typescript@5.9.3: {} + + typical@7.3.0: {} - ufo@1.6.1: {} + ufo@1.6.4: {} uglify-js@3.19.3: optional: true - undici-types@7.10.0: {} + undici-types@7.16.0: {} - undici@5.29.0: - dependencies: - '@fastify/busboy': 2.1.1 + undici@6.26.0: {} - undici@7.16.0: {} + undici@7.27.0: {} unicode-emoji-modifier-base@1.0.0: {} + unicode-properties@1.4.1: + dependencies: + base64-js: 1.5.1 + unicode-trie: 2.0.0 + + unicode-trie@2.0.0: + dependencies: + pako: 0.2.9 + tiny-inflate: 1.0.3 + unicorn-magic@0.1.0: {} unicorn-magic@0.3.0: {} + unicorn-magic@0.4.0: {} + unique-string@3.0.0: dependencies: crypto-random-string: 4.0.0 @@ -7325,16 +8531,12 @@ snapshots: dependencies: uzip-module: 1.0.3 - update-browserslist-db@1.1.3(browserslist@4.24.4): + update-browserslist-db@1.2.3(browserslist@4.28.2): dependencies: - browserslist: 4.24.4 + browserslist: 4.28.2 escalade: 3.2.0 picocolors: 1.1.1 - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - url-join@5.0.0: {} util-deprecate@1.0.2: {} @@ -7346,13 +8548,13 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - vite-node@3.2.4(@types/node@24.3.0)(yaml@2.8.2): + vite-node@3.2.4(@types/node@24.12.4)(yaml@2.9.0): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.2.7(@types/node@24.3.0)(yaml@2.8.2) + vite: 6.4.3(@types/node@24.12.4)(yaml@2.9.0) transitivePeerDependencies: - '@types/node' - jiti @@ -7367,62 +8569,65 @@ snapshots: - tsx - yaml - vite-plugin-dts@4.5.4(@types/node@24.3.0)(rollup@4.40.1)(typescript@5.8.2)(vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2)): + vite-plugin-dts@4.5.4(@types/node@24.12.4)(rollup@4.61.0)(typescript@5.9.3)(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)): dependencies: - '@microsoft/api-extractor': 7.55.2(@types/node@24.3.0) - '@rollup/pluginutils': 5.3.0(rollup@4.40.1) - '@volar/typescript': 2.4.26 - '@vue/language-core': 2.2.0(typescript@5.8.2) + '@microsoft/api-extractor': 7.58.7(@types/node@24.12.4) + '@rollup/pluginutils': 5.4.0(rollup@4.61.0) + '@volar/typescript': 2.4.28 + '@vue/language-core': 2.2.0(typescript@5.9.3) compare-versions: 6.1.1 - debug: 4.4.0 + debug: 4.4.3 kolorist: 1.8.0 - local-pkg: 1.1.2 + local-pkg: 1.2.1 magic-string: 0.30.21 - typescript: 5.8.2 + typescript: 5.9.3 optionalDependencies: - vite: 6.2.7(@types/node@24.3.0)(yaml@2.8.2) + vite: 6.4.3(@types/node@24.12.4)(yaml@2.9.0) transitivePeerDependencies: - '@types/node' - rollup - supports-color - vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2): + vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0): dependencies: - esbuild: 0.25.3 - postcss: 8.5.3 - rollup: 4.40.1 + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + postcss: 8.5.15 + rollup: 4.61.0 + tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 24.3.0 + '@types/node': 24.12.4 fsevents: 2.3.3 - yaml: 2.8.2 + yaml: 2.9.0 - vitest@3.2.4(@types/node@24.3.0)(yaml@2.8.2): + vitest@3.2.6(@types/node@24.12.4)(yaml@2.9.0): dependencies: '@types/chai': 5.2.3 - '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2)) - '@vitest/pretty-format': 3.2.4 - '@vitest/runner': 3.2.4 - '@vitest/snapshot': 3.2.4 - '@vitest/spy': 3.2.4 - '@vitest/utils': 3.2.4 + '@vitest/expect': 3.2.6 + '@vitest/mocker': 3.2.6(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)) + '@vitest/pretty-format': 3.2.6 + '@vitest/runner': 3.2.6 + '@vitest/snapshot': 3.2.6 + '@vitest/spy': 3.2.6 + '@vitest/utils': 3.2.6 chai: 5.3.3 debug: 4.4.3 expect-type: 1.3.0 magic-string: 0.30.21 pathe: 2.0.3 - picomatch: 4.0.3 + picomatch: 4.0.4 std-env: 3.10.0 tinybench: 2.9.0 tinyexec: 0.3.2 - tinyglobby: 0.2.15 + tinyglobby: 0.2.17 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.2.7(@types/node@24.3.0)(yaml@2.8.2) - vite-node: 3.2.4(@types/node@24.3.0)(yaml@2.8.2) + vite: 6.4.3(@types/node@24.12.4)(yaml@2.9.0) + vite-node: 3.2.4(@types/node@24.12.4)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 24.3.0 + '@types/node': 24.12.4 transitivePeerDependencies: - jiti - less @@ -7437,50 +8642,39 @@ snapshots: - tsx - yaml - vitest@4.0.15(@types/node@24.3.0)(yaml@2.8.2): + vitest@4.1.8(@types/node@24.12.4)(@vitest/coverage-v8@4.0.15)(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)): dependencies: - '@vitest/expect': 4.0.15 - '@vitest/mocker': 4.0.15(vite@6.2.7(@types/node@24.3.0)(yaml@2.8.2)) - '@vitest/pretty-format': 4.0.15 - '@vitest/runner': 4.0.15 - '@vitest/snapshot': 4.0.15 - '@vitest/spy': 4.0.15 - '@vitest/utils': 4.0.15 - es-module-lexer: 1.7.0 + '@vitest/expect': 4.1.8 + '@vitest/mocker': 4.1.8(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.8 + '@vitest/runner': 4.1.8 + '@vitest/snapshot': 4.1.8 + '@vitest/spy': 4.1.8 + '@vitest/utils': 4.1.8 + es-module-lexer: 2.1.0 expect-type: 1.3.0 magic-string: 0.30.21 obug: 2.1.1 pathe: 2.0.3 - picomatch: 4.0.3 - std-env: 3.10.0 + picomatch: 4.0.4 + std-env: 4.1.0 tinybench: 2.9.0 - tinyexec: 1.0.2 - tinyglobby: 0.2.15 - tinyrainbow: 3.0.3 - vite: 6.2.7(@types/node@24.3.0)(yaml@2.8.2) + tinyexec: 1.2.4 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.0 + vite: 6.4.3(@types/node@24.12.4)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 24.3.0 + '@types/node': 24.12.4 + '@vitest/coverage-v8': 4.0.15(vitest@4.1.8) transitivePeerDependencies: - - jiti - - less - - lightningcss - msw - - sass - - sass-embedded - - stylus - - sugarss - - terser - - tsx - - yaml vscode-uri@3.1.0: {} - web-worker@1.2.0: {} - web-worker@1.5.0: {} - wgsl_reflect@1.2.0: {} + wgsl_reflect@1.3.0: {} which@2.0.2: dependencies: @@ -7493,6 +8687,8 @@ snapshots: wordwrap@1.0.0: {} + wordwrapjs@5.1.1: {} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -7503,9 +8699,15 @@ snapshots: dependencies: ansi-styles: 6.2.3 string-width: 7.2.0 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 + + xml-naming@0.1.0: {} - xml-utils@1.10.1: {} + xml-utils@1.10.2: {} + + xmldoc@2.0.3: + dependencies: + sax: 1.6.0 xss@1.0.13: dependencies: @@ -7518,11 +8720,9 @@ snapshots: yallist@3.1.1: {} - yallist@4.0.0: {} - - yaml@1.10.2: {} + yaml@1.10.3: {} - yaml@2.8.2: {} + yaml@2.9.0: {} yargs-parser@20.2.9: {} @@ -7559,7 +8759,7 @@ snapshots: '@zarrita/storage': 0.1.4 numcodecs: 0.3.2 - zod@3.24.2: {} + zod@3.25.76: {} zstd-codec@0.1.5: optional: true diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 9ec4eafa..10b8ef9d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,6 +1,6 @@ packages: - 'viewer' - - 'sites/*' - 'anndata-zarr' - 'roi-selector' + - 'sites/*' diff --git a/sites/app/src/App.tsx b/sites/app/src/App.tsx index 173cf25e..e014ddf3 100644 --- a/sites/app/src/App.tsx +++ b/sites/app/src/App.tsx @@ -47,13 +47,14 @@ export default function App() { } }, []); - const { sources, viewState, enableRoi } = React.useMemo(() => { + const { sources, viewState, enableRoi, tableURLs } = React.useMemo(() => { const url = new URL(urlString); const { searchParams } = url; return { sources: searchParams.getAll("source"), viewState: parseViewStateFromUrl(), enableRoi: searchParams.get("roi") === "1", + tableURLs: searchParams.getAll("anndata").map((v) => (v ? { url: v } : null)) }; }, [urlString]); @@ -84,32 +85,18 @@ export default function App() { }); }, []); - //const anndataControllers = React.useMemo(() => { - // return sources.map((_s, i) => { - // if (!anndatas?.[i]?.url) return null; - // return ( - // selectCallback(colorData, i)} - // /> - // ); - // }); - //}, [anndatas, sources, selectCallback]); - - // - // - // - //
{anndataControllers}
- // - //
- //
- // ---- Viewer state (received from Vizarr via callback) ---- + const anndataControllers = React.useMemo(() => { + return sources.map((_s, i) => { + if (!tableURLs?.[i]?.url) return null; + return ( + selectCallback(colorData, i)} + /> + ); + }); + }, [tableURLs, sources, selectCallback]); const [viewerInfo, setViewerInfo] = React.useState(null); @@ -131,28 +118,36 @@ export default function App() { }); return (
- - {enableRoi && viewerInfo && ( - - )} - -
+ + + +
{anndataControllers}
+ + + {enableRoi && viewerInfo && ( + + )} + +
+
+ ); } diff --git a/viewer/package.json b/viewer/package.json index 3d45143a..a19ff172 100644 --- a/viewer/package.json +++ b/viewer/package.json @@ -5,7 +5,9 @@ "main": "dist/biongff-vizarr.cjs.js", "module": "dist/biongff-vizarr.es.js", "types": "dist/index.d.ts", - "files": ["dist"], + "files": [ + "dist" + ], "exports": { ".": { "types": "./dist/index.d.ts", @@ -26,6 +28,7 @@ "@deck.gl/layers": "~9.0.0", "@hms-dbmi/viv": "~0.17.2", "@vivjs/types": "~0.17.0", + "@vivjs/loaders": "0.17.2", "@zarrita/storage": "0.1.4", "deck.gl": "~9.0.0", "jotai": "^1.0.0", From 99ba3f1ddf5f3bb871f15d9758b0d8d602a087bb Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Sat, 6 Jun 2026 09:18:58 +0100 Subject: [PATCH 13/26] Table TS config --- anndata-zarr/package.json | 4 +- .../src/components/AnndataController.tsx | 33 ++++ anndata-zarr/src/components/FeatureSelect.tsx | 108 +++++++++++ anndata-zarr/src/components/Legend.tsx | 25 +++ anndata-zarr/src/components/ObsSelect.tsx | 143 +++++++++++++++ anndata-zarr/src/hooks.ts | 104 +++++++++++ anndata-zarr/src/provider.tsx | 9 + anndata-zarr/src/utils.ts | 170 ++++++++++++++++++ anndata-zarr/tsconfig.json | 16 ++ anndata-zarr/types.ts | 8 + anndata-zarr/vite.config.js | 4 +- package.json | 2 +- pnpm-lock.yaml | 6 + 13 files changed, 628 insertions(+), 4 deletions(-) create mode 100644 anndata-zarr/src/components/AnndataController.tsx create mode 100644 anndata-zarr/src/components/FeatureSelect.tsx create mode 100644 anndata-zarr/src/components/Legend.tsx create mode 100644 anndata-zarr/src/components/ObsSelect.tsx create mode 100644 anndata-zarr/src/hooks.ts create mode 100644 anndata-zarr/src/provider.tsx create mode 100644 anndata-zarr/src/utils.ts create mode 100644 anndata-zarr/tsconfig.json create mode 100644 anndata-zarr/types.ts diff --git a/anndata-zarr/package.json b/anndata-zarr/package.json index 76e01e7d..c99ac8a8 100644 --- a/anndata-zarr/package.json +++ b/anndata-zarr/package.json @@ -40,7 +40,9 @@ }, "devDependencies": { "@vitejs/plugin-react": "^4.3.3", + "typescript": "^5.8.2", "vite": "^6.2.3", - "vitest": "^3.0.8" + "vitest": "^3.0.8", + "vite-plugin-dts": "^4.5.4" } } diff --git a/anndata-zarr/src/components/AnndataController.tsx b/anndata-zarr/src/components/AnndataController.tsx new file mode 100644 index 00000000..5ea26f92 --- /dev/null +++ b/anndata-zarr/src/components/AnndataController.tsx @@ -0,0 +1,33 @@ +import React, { useState } from "react"; + +import Box from "@mui/material/Box"; +import Stack from "@mui/material/Stack"; + +import { FeatureSelect } from "./FeatureSelect"; +import { ObsSelect } from "./ObsSelect"; + +export const AnndataController = ({ adata, callback = () => {} }) => { + const [feature, setFeature] = useState(null); + const [obsCol, setObsCol] = useState(null); + + const handleFeatureSelect = (f) => { + setFeature(f); + setObsCol(null); + }; + + const handleObsSelect = (o) => { + setObsCol(o); + setFeature(null); + }; + + return ( + + + + + + + + + ); +}; diff --git a/anndata-zarr/src/components/FeatureSelect.tsx b/anndata-zarr/src/components/FeatureSelect.tsx new file mode 100644 index 00000000..6614f23e --- /dev/null +++ b/anndata-zarr/src/components/FeatureSelect.tsx @@ -0,0 +1,108 @@ +import React, { useEffect, useMemo, useState } from "react"; + +import Box from "@mui/material/Box"; +import ListItem from "@mui/material/ListItem"; +import ListItemButton from "@mui/material/ListItemButton"; +import ListItemText from "@mui/material/ListItemText"; +import Stack from "@mui/material/Stack"; +import TextField from "@mui/material/TextField"; +import { List } from "react-window"; + +import { useAnndataColors, useAnndataFeatures } from "../hooks"; +import { Legend } from "./Legend"; + +const RowComponent = ({ index, items, style, onSelect, selectedIndex }) => { + return ( + + onSelect({ index: items[index].matrixIndex })} + selected={items[index].matrixIndex === selectedIndex} + > + + + + ); +}; + +export const FeatureSelect = ({ adata, feature, onSelect, callback = () => {} }) => { + const [searchTerm, setSearchTerm] = useState(""); + + const { data, isLoading, serverError } = useAnndataFeatures(adata); + const colorData = useAnndataColors( + { + ...adata, + matrixProps: { + feature: feature, + }, + }, + { enabled: !!feature }, + ); + + useEffect(() => { + if (colorData?.serverError) { + callback(null); + return; + } + if (!colorData?.isLoading && colorData?.data) { + callback(colorData.data.colors); + } + }, [colorData, callback]); + + const items = useMemo(() => { + if (!data) return []; + const allItems = data.map((name, index) => ({ + name, + matrixIndex: index, + })); + if (!searchTerm) return allItems; + return allItems.filter((item) => item.name.toLowerCase().includes(searchTerm.toLowerCase())); + }, [data, searchTerm]); + + const legend = useMemo(() => { + if (colorData?.serverError || colorData?.isLoading || !colorData?.data) { + return null; + } + const { min, max, colorscale } = colorData.data; + return ; + }, [colorData.data, colorData?.isLoading, colorData?.serverError]); + + if (isLoading) { + return <>; + } + if (serverError) { + return
Error loading features
; + } + return ( + + + setSearchTerm(e.target.value)} + /> + + {!!feature && legend} + + + ); +}; diff --git a/anndata-zarr/src/components/Legend.tsx b/anndata-zarr/src/components/Legend.tsx new file mode 100644 index 00000000..0320e54a --- /dev/null +++ b/anndata-zarr/src/components/Legend.tsx @@ -0,0 +1,25 @@ +import React, { useMemo } from "react"; + +import _ from "lodash"; + +import { getColor } from "../utils"; + +export const Legend = ({ min, max, colorscale }) => { + const spanList = useMemo(() => { + return _.range(100).map((i) => { + const color = getColor({ value: i / 100, colorscale }); + return ; + }); + }, [colorscale]); + + return ( +
+
+ {spanList} + {min.toFixed(2)} + {((min + max) / 2).toFixed(2)} + {max.toFixed(2)} +
+
+ ); +}; diff --git a/anndata-zarr/src/components/ObsSelect.tsx b/anndata-zarr/src/components/ObsSelect.tsx new file mode 100644 index 00000000..747f3862 --- /dev/null +++ b/anndata-zarr/src/components/ObsSelect.tsx @@ -0,0 +1,143 @@ +import React, { useEffect, useMemo, useState } from "react"; + +import ExpandLess from "@mui/icons-material/ExpandLess"; +import ExpandMore from "@mui/icons-material/ExpandMore"; +import Alert from "@mui/material/Alert"; +import Box from "@mui/material/Box"; +import Collapse from "@mui/material/Collapse"; +import Divider from "@mui/material/Divider"; +import FormControl from "@mui/material/FormControl"; +import FormControlLabel from "@mui/material/FormControlLabel"; +import List from "@mui/material/List"; +import ListItem from "@mui/material/ListItem"; +import ListItemIcon from "@mui/material/ListItemIcon"; +import ListItemText from "@mui/material/ListItemText"; +import Radio from "@mui/material/Radio"; +import RadioGroup from "@mui/material/RadioGroup"; +import Stack from "@mui/material/Stack"; + +import { COLORSCALES } from "../constants/colorscales"; +import { useAnndataColors, useAnndataObs } from "../hooks"; +import { getColor } from "../utils"; +import { Legend } from "./Legend"; + +// @TODO: fix styling (width) +const CategoricalCol = ({ col, showColor = false }) => { + const [open, setOpen] = useState(false); + const { categories } = col; + + return ( + + setOpen(!open)} sx={{ display: "flex", alignItems: "center", cursor: "pointer" }}> + e.stopPropagation()} />} + label={col.name} + key={col.name} + value={col.name} + /> + {open ? : } + + + {categories.length > 100 && ( + + Truncated to 100 categories + + )} + + {categories.slice(0, 100).map((cat, i) => ( + + {showColor && ( + + + + )} + + + ))} + + + + ); +}; + +const NumericalCol = ({ col }) => { + return } label={col.name} key={col.name} value={col.name} />; +}; + +export const ObsSelect = ({ adata, obsCol, onSelect, callback = () => {} }) => { + const { data, isLoading, serverError } = useAnndataObs(adata); + const colorData = useAnndataColors( + { + ...adata, + matrixProps: { + obs: { col: obsCol }, + }, + }, + { + enabled: !!obsCol, + }, + ); + + useEffect(() => { + if (colorData?.serverError) { + callback(null); + return; + } + if (!colorData?.isLoading && colorData?.data) { + callback(colorData.data.colors); + } + }, [colorData, callback]); + + const legend = useMemo(() => { + if (colorData?.serverError || colorData?.isLoading || !colorData?.data) { + return null; + } + const { min, max, colorscale, categories } = colorData.data; + if (categories) { + return null; + } + return ; + }, [colorData.data, colorData?.isLoading, colorData?.serverError]); + + if (isLoading) { + return <>; + } + if (serverError) { + return
Error loading obs
; + } + return ( + + + Observations + + + onSelect(e.target.value)}> + Categorical + {data.categorical.map((col) => ( + + ))} + Numerical + {data.numerical.map((col) => ( + + ))} + + + + {!!obsCol && legend} + + + ); +}; diff --git a/anndata-zarr/src/hooks.ts b/anndata-zarr/src/hooks.ts new file mode 100644 index 00000000..10a7fc77 --- /dev/null +++ b/anndata-zarr/src/hooks.ts @@ -0,0 +1,104 @@ +import { useCallback } from "react"; + +import { useQueries, useQuery } from "@tanstack/react-query"; +import _ from "lodash"; + +import { COLORSCALES } from "./constants/colorscales"; +import { fetchDataFromZarr, getColors, getObs, getVarNames, getZarrPath } from "./utils"; + +const getAnndataColors = async (url, matrixProps, colorProps) => { + let zarrData; + try { + const zarrPath = await getZarrPath(url, matrixProps); + zarrData = await fetchDataFromZarr(zarrPath.url, zarrPath.path, zarrPath.s); + } catch (error) { + console.error(error); + return null; + } + if (!zarrData) return null; + + const { categories } = zarrData; + + const max = categories ? categories.length - 1 : colorProps?.max || _.max(zarrData.data); + const min = categories ? 0 : colorProps?.min || _.min(zarrData.data); + const colorscale = categories ? COLORSCALES.Accent : colorProps?.colorscale; + const colors = getColors({ + data: zarrData.data, + max, + min, + colorProps: { ...colorProps, colorscale }, + categories, + }) + return { + colors: colors, + max, + min, + ...(categories ? { categories } : {}), + colorscale, + }; +}; + +export const useAnndataColors = (adata = { url: null }, opts = {}) => { + const { + data = null, + isLoading = false, + serverError = null, + } = useQuery({ + queryKey: ["anndataColor", adata.url, adata.matrixProps, adata.colorProps], + queryFn: () => getAnndataColors(adata.url, adata.matrixProps, adata.colorProps), + ...opts, + }); + + return { data, isLoading, serverError }; +}; + +export const useAnndatasColors = (adatas = [], opts = {}) => { + const combine = useCallback((results) => { + return { + data: results.map((result) => result.data), + isLoading: results.some((result) => result.isLoading), + serverError: results.find((result) => result.error), + }; + }, []); + + const { + data = null, + isLoading = false, + serverError = null, + } = useQueries({ + queries: adatas.map(({ url, matrixProps, colorProps }) => ({ + queryKey: ["anndataColor", url, matrixProps, colorProps], + queryFn: () => getAnndataColors(url, matrixProps, colorProps), + })), + ...opts, + combine, + }); + + return { data, isLoading, serverError }; +}; + +export const useAnndataFeatures = (adata = { url: null, namesCol: null }) => { + const { + data = null, + isLoading = false, + serverError = null, + } = useQuery({ + queryKey: ["anndataFeatures", adata.url, adata.namesCol], + queryFn: () => getVarNames(adata.url, adata.namesCol), + }); + + return { data, isLoading, serverError }; +}; + +export const useAnndataObs = (adata = { url: null }) => { + const { + data = null, + isLoading = false, + serverError = null, + } = useQuery({ + queryKey: ["anndataObs", adata.url], + queryFn: () => getObs(adata.url), + }); + + return { data, isLoading, serverError }; +}; diff --git a/anndata-zarr/src/provider.tsx b/anndata-zarr/src/provider.tsx new file mode 100644 index 00000000..c250d401 --- /dev/null +++ b/anndata-zarr/src/provider.tsx @@ -0,0 +1,9 @@ +import React from "react"; + +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; + +const queryClient = new QueryClient(); + +export function AnndataProvider({ children }) { + return {children}; +} diff --git a/anndata-zarr/src/utils.ts b/anndata-zarr/src/utils.ts new file mode 100644 index 00000000..3e206c43 --- /dev/null +++ b/anndata-zarr/src/utils.ts @@ -0,0 +1,170 @@ +import _ from "lodash"; +import { FetchStore, get, open } from "zarrita"; + +import { COLORSCALES } from "./constants/colorscales"; + +export const fetchDataFromZarr = async (url, path, s) => { + try { + const store = new FetchStore(url); + const node = await open(store, { kind: "group" }); + + const dataNode = await open(node.resolve(path)); + let result; + if (dataNode.attrs?.["encoding-type"] === "array" && dataNode.dtype === "bool") { + const boolData = await get(dataNode, s); + result = { + data: Array.from(boolData.data), + categories: ["false", "true"], + }; + } else if (dataNode.attrs?.["encoding-type"] === "array" || dataNode.attrs?.["encoding-type"] === "string-array") { + result = await get(dataNode, s); + } else if (dataNode.attrs?.["encoding-type"] === "categorical") { + const categoriesArr = await open(dataNode.resolve("categories"), { + kind: "array", + }); + const codesArr = await open(dataNode.resolve("codes"), { kind: "array" }); + const { data: categories } = await get(categoriesArr); + const { data } = await get(codesArr, s); + result = { data, categories }; + } else { + throw new Error("Unsupported encoding-type"); + } + + return result; + } catch (error) { + // biome-ignore lint/complexity/noUselessCatch: @TODO: better error handling + throw error; + } +}; + +export const getVarNames = async (url, namesCol = "_index") => { + try { + const store = new FetchStore(url); + const node = await open(store, { kind: "group" }); + + const arr = await open(node.resolve(`var/${namesCol}`, { kind: "array" })); + const varNames = (await get(arr)).data; + return varNames; + } catch (error) { + console.error(error); + return []; + } +}; + +export const getObs = async (url) => { + try { + const store = new FetchStore(url); + const node = await open(store, { kind: "group" }); + + const cols = (await open(node.resolve("obs", { kind: "group" }))).attrs?.["column-order"]; + const obs = { categorical: [], numerical: [] }; + for (const col of cols) { + const dataNode = await open(node.resolve(`obs/${col}`)); + const { "encoding-type": encodingType } = dataNode.attrs || {}; + if (encodingType === "categorical") { + const categoriesArr = await open(dataNode.resolve("categories"), { + kind: "array", + }); + const { data: categories } = await get(categoriesArr); + obs.categorical.push({ name: col, categories }); + } else if (encodingType === "array") { + if (dataNode.dtype === "bool") { + obs.categorical.push({ name: col, categories: ["false", "true"] }); + } else { + obs.numerical.push({ name: col }); + } + } + } + return obs; + } catch (error) { + console.error(error); + return []; + } +}; + +export const getVarIndex = async (url, varId, namesCol = "_index") => { + try { + const store = new FetchStore(url); + const node = await open(store, { kind: "group" }); + + const arr = await open(node.resolve(`var/${namesCol}`, { kind: "array" })); + const varNames = (await get(arr)).data; + const varIndex = varNames.findIndex((name) => name === varId); + return varIndex; + } catch (error) { + return -1; + } +}; + +export const getZarrPath = async (url, matrixProps) => { + const { feature, obs } = matrixProps; + if (feature) { + if (feature.index !== undefined && feature.index !== null) { + return { url, path: "X", s: [null, feature.index] }; + } + if (feature.name) { + return { + url, + path: "X", + s: [null, await getVarIndex(url, feature.name, feature.namesCol)], + }; + } + } + + if (obs) { + return { + url, + path: `obs/${obs.col}`, + s: null, + }; + } + + throw new Error("No feature or obs in matrixProps"); +}; + +const parseHexColor = (color) => { + const r = Number.parseInt(color?.substring(1, 3), 16); + const g = Number.parseInt(color?.substring(3, 5), 16); + const b = Number.parseInt(color?.substring(5, 7), 16); + + return [r, g, b]; +}; + +const interpolateColor = (color1, color2, factor) => { + const [r1, g1, b1] = parseHexColor(color1); + const [r2, g2, b2] = parseHexColor(color2); + + const r = Math.round(r1 + factor * (r2 - r1)); + const g = Math.round(g1 + factor * (g2 - g1)); + const b = Math.round(b1 + factor * (b2 - b1)); + + return [r, g, b]; +}; + +const computeColor = (colormap, value) => { + if (!colormap || Number.isNaN(value)) { + return [0, 0, 0, 255]; + } + if (value <= 0) { + return parseHexColor(colormap[0]); + } + if (value >= 1) { + return parseHexColor(colormap[colormap.length - 1]); + } + const index1 = Math.floor(value * (colormap.length - 1)); + const index2 = Math.ceil(value * (colormap.length - 1)); + const factor = (value * (colormap.length - 1)) % 1; + return interpolateColor(colormap[index1], colormap[index2], factor); +}; + +export const getColor = ({ value, colorscale = COLORSCALES.Viridis }) => { + return [...computeColor(colorscale, value), 255]; +}; + +export const getColors = ({ data, max, min, colorProps, categories }) => { + return _.map(data, (v, i) => ({ + labelValue: i + 1, + rgba: getColor({ value: (v - min) / (max - min), ...colorProps }), + value: categories ? (categories[v] ?? v) : v, + })); +}; diff --git a/anndata-zarr/tsconfig.json b/anndata-zarr/tsconfig.json new file mode 100644 index 00000000..32e07458 --- /dev/null +++ b/anndata-zarr/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "esnext", + "target": "esnext", + "moduleResolution": "bundler", + "noEmit": true, + "strict": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "verbatimModuleSyntax": true, + "jsx": "preserve", + "types": [ + "vite/client" + ] + } +} diff --git a/anndata-zarr/types.ts b/anndata-zarr/types.ts new file mode 100644 index 00000000..e0025c92 --- /dev/null +++ b/anndata-zarr/types.ts @@ -0,0 +1,8 @@ + + + +type LabelColourMap = { + labelId: number, + colour: [number, number, number, number] + value: number +} diff --git a/anndata-zarr/vite.config.js b/anndata-zarr/vite.config.js index deb993fe..789b956f 100644 --- a/anndata-zarr/vite.config.js +++ b/anndata-zarr/vite.config.js @@ -1,11 +1,11 @@ import path from "node:path"; - +import dts from "vite-plugin-dts"; import react from "@vitejs/plugin-react"; import { defineConfig } from "vite"; // https://vite.dev/config/ export default defineConfig({ - plugins: [react()], + plugins: [react(), dts({ rollupTypes: true, tsconfigPath: "./tsconfig.json" })], build: { // outDir: path.resolve(__dirname, '../dist'), lib: { diff --git a/package.json b/package.json index 321ff7d1..e25bd0e3 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "dev": "pnpm --filter app dev", "lint": "biome ci", "fix": "biome check --write", - "check": "pnpm build:viewer && pnpm build:roi-selector && pnpm -r run check", + "check": "pnpm build:viewer && pnpm build:anndata-zarr && pnpm build:roi-selector && pnpm -r run check", "build:viewer": "pnpm --filter vizarr build", "build:roi-selector": "pnpm --filter @biongff/roi-selector build", "build:app": "pnpm --filter app build", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a9220aaa..561869fd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -104,9 +104,15 @@ importers: '@vitejs/plugin-react': specifier: ^4.3.3 version: 4.7.0(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)) + typescript: + specifier: ^5.8.2 + version: 5.9.3 vite: specifier: ^6.2.3 version: 6.4.3(@types/node@24.12.4)(yaml@2.9.0) + vite-plugin-dts: + specifier: ^4.5.4 + version: 4.5.4(@types/node@24.12.4)(rollup@4.61.0)(typescript@5.9.3)(vite@6.4.3(@types/node@24.12.4)(yaml@2.9.0)) vitest: specifier: ^3.0.8 version: 3.2.6(@types/node@24.12.4)(yaml@2.9.0) From 1ea1a084c23490d284b170cb6ef515361d64ac40 Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Mon, 8 Jun 2026 13:26:32 +0100 Subject: [PATCH 14/26] Adding types --- anndata-zarr/package.json | 9 +- .../src/components/AnndataController.jsx | 33 --- .../src/components/AnndataController.tsx | 9 +- anndata-zarr/src/components/FeatureSelect.jsx | 108 ---------- anndata-zarr/src/components/FeatureSelect.tsx | 2 +- anndata-zarr/src/components/Legend.jsx | 25 --- anndata-zarr/src/components/ObsSelect.jsx | 143 ------------- anndata-zarr/src/components/ObsSelect.tsx | 6 +- .../{colorscales.js => colorscales.ts} | 0 anndata-zarr/src/hooks.js | 160 --------------- anndata-zarr/src/hooks.ts | 86 +++++--- anndata-zarr/src/{index.js => index.ts} | 0 anndata-zarr/src/provider.jsx | 9 - .../src/{table-loader.js => table-loader.ts} | 0 anndata-zarr/src/utils.js | 170 --------------- anndata-zarr/src/utils.ts | 193 ++++++++++++------ anndata-zarr/tests/expected_colours.json | 1 + anndata-zarr/tests/test.test.ts | 22 ++ 18 files changed, 227 insertions(+), 749 deletions(-) delete mode 100644 anndata-zarr/src/components/AnndataController.jsx delete mode 100644 anndata-zarr/src/components/FeatureSelect.jsx delete mode 100644 anndata-zarr/src/components/Legend.jsx delete mode 100644 anndata-zarr/src/components/ObsSelect.jsx rename anndata-zarr/src/constants/{colorscales.js => colorscales.ts} (100%) delete mode 100644 anndata-zarr/src/hooks.js rename anndata-zarr/src/{index.js => index.ts} (100%) delete mode 100644 anndata-zarr/src/provider.jsx rename anndata-zarr/src/{table-loader.js => table-loader.ts} (100%) delete mode 100644 anndata-zarr/src/utils.js create mode 100644 anndata-zarr/tests/expected_colours.json create mode 100644 anndata-zarr/tests/test.test.ts diff --git a/anndata-zarr/package.json b/anndata-zarr/package.json index c99ac8a8..cc74671f 100644 --- a/anndata-zarr/package.json +++ b/anndata-zarr/package.json @@ -25,10 +25,13 @@ }, "dependencies": { "@tanstack/react-query": "^5.85.3", + "@types/lodash": "^4.17.24", "hyparquet": "^1.25.6", "lodash": "^4.17.21", "react-window": "^2.0.2", - "zarrita": "0.5.0" + "yaml": "^2.8.2", + "zarrita": "0.5.0", + "zod": "^4.4.3" }, "peerDependencies": { "@emotion/react": "^11.14.0", @@ -42,7 +45,7 @@ "@vitejs/plugin-react": "^4.3.3", "typescript": "^5.8.2", "vite": "^6.2.3", - "vitest": "^3.0.8", - "vite-plugin-dts": "^4.5.4" + "vite-plugin-dts": "^4.5.4", + "vitest": "^3.0.8" } } diff --git a/anndata-zarr/src/components/AnndataController.jsx b/anndata-zarr/src/components/AnndataController.jsx deleted file mode 100644 index 5ea26f92..00000000 --- a/anndata-zarr/src/components/AnndataController.jsx +++ /dev/null @@ -1,33 +0,0 @@ -import React, { useState } from "react"; - -import Box from "@mui/material/Box"; -import Stack from "@mui/material/Stack"; - -import { FeatureSelect } from "./FeatureSelect"; -import { ObsSelect } from "./ObsSelect"; - -export const AnndataController = ({ adata, callback = () => {} }) => { - const [feature, setFeature] = useState(null); - const [obsCol, setObsCol] = useState(null); - - const handleFeatureSelect = (f) => { - setFeature(f); - setObsCol(null); - }; - - const handleObsSelect = (o) => { - setObsCol(o); - setFeature(null); - }; - - return ( - - - - - - - - - ); -}; diff --git a/anndata-zarr/src/components/AnndataController.tsx b/anndata-zarr/src/components/AnndataController.tsx index 5ea26f92..07f84ba5 100644 --- a/anndata-zarr/src/components/AnndataController.tsx +++ b/anndata-zarr/src/components/AnndataController.tsx @@ -6,10 +6,10 @@ import Stack from "@mui/material/Stack"; import { FeatureSelect } from "./FeatureSelect"; import { ObsSelect } from "./ObsSelect"; -export const AnndataController = ({ adata, callback = () => {} }) => { +export const AnndataController = ({ adata, callback = () => { } }) => { const [feature, setFeature] = useState(null); const [obsCol, setObsCol] = useState(null); - + console.log("RENDERING FeatureSelect with ", adata) const handleFeatureSelect = (f) => { setFeature(f); setObsCol(null); @@ -19,14 +19,13 @@ export const AnndataController = ({ adata, callback = () => {} }) => { setObsCol(o); setFeature(null); }; - return ( - + - + ); diff --git a/anndata-zarr/src/components/FeatureSelect.jsx b/anndata-zarr/src/components/FeatureSelect.jsx deleted file mode 100644 index 6614f23e..00000000 --- a/anndata-zarr/src/components/FeatureSelect.jsx +++ /dev/null @@ -1,108 +0,0 @@ -import React, { useEffect, useMemo, useState } from "react"; - -import Box from "@mui/material/Box"; -import ListItem from "@mui/material/ListItem"; -import ListItemButton from "@mui/material/ListItemButton"; -import ListItemText from "@mui/material/ListItemText"; -import Stack from "@mui/material/Stack"; -import TextField from "@mui/material/TextField"; -import { List } from "react-window"; - -import { useAnndataColors, useAnndataFeatures } from "../hooks"; -import { Legend } from "./Legend"; - -const RowComponent = ({ index, items, style, onSelect, selectedIndex }) => { - return ( - - onSelect({ index: items[index].matrixIndex })} - selected={items[index].matrixIndex === selectedIndex} - > - - - - ); -}; - -export const FeatureSelect = ({ adata, feature, onSelect, callback = () => {} }) => { - const [searchTerm, setSearchTerm] = useState(""); - - const { data, isLoading, serverError } = useAnndataFeatures(adata); - const colorData = useAnndataColors( - { - ...adata, - matrixProps: { - feature: feature, - }, - }, - { enabled: !!feature }, - ); - - useEffect(() => { - if (colorData?.serverError) { - callback(null); - return; - } - if (!colorData?.isLoading && colorData?.data) { - callback(colorData.data.colors); - } - }, [colorData, callback]); - - const items = useMemo(() => { - if (!data) return []; - const allItems = data.map((name, index) => ({ - name, - matrixIndex: index, - })); - if (!searchTerm) return allItems; - return allItems.filter((item) => item.name.toLowerCase().includes(searchTerm.toLowerCase())); - }, [data, searchTerm]); - - const legend = useMemo(() => { - if (colorData?.serverError || colorData?.isLoading || !colorData?.data) { - return null; - } - const { min, max, colorscale } = colorData.data; - return ; - }, [colorData.data, colorData?.isLoading, colorData?.serverError]); - - if (isLoading) { - return <>; - } - if (serverError) { - return
Error loading features
; - } - return ( - - - setSearchTerm(e.target.value)} - /> - - {!!feature && legend} - - - ); -}; diff --git a/anndata-zarr/src/components/FeatureSelect.tsx b/anndata-zarr/src/components/FeatureSelect.tsx index 6614f23e..c940dd7e 100644 --- a/anndata-zarr/src/components/FeatureSelect.tsx +++ b/anndata-zarr/src/components/FeatureSelect.tsx @@ -25,7 +25,7 @@ const RowComponent = ({ index, items, style, onSelect, selectedIndex }) => { ); }; -export const FeatureSelect = ({ adata, feature, onSelect, callback = () => {} }) => { +export const FeatureSelect = ({ adata, feature, onSelect, callback = () => { } }) => { const [searchTerm, setSearchTerm] = useState(""); const { data, isLoading, serverError } = useAnndataFeatures(adata); diff --git a/anndata-zarr/src/components/Legend.jsx b/anndata-zarr/src/components/Legend.jsx deleted file mode 100644 index 0320e54a..00000000 --- a/anndata-zarr/src/components/Legend.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import React, { useMemo } from "react"; - -import _ from "lodash"; - -import { getColor } from "../utils"; - -export const Legend = ({ min, max, colorscale }) => { - const spanList = useMemo(() => { - return _.range(100).map((i) => { - const color = getColor({ value: i / 100, colorscale }); - return ; - }); - }, [colorscale]); - - return ( -
-
- {spanList} - {min.toFixed(2)} - {((min + max) / 2).toFixed(2)} - {max.toFixed(2)} -
-
- ); -}; diff --git a/anndata-zarr/src/components/ObsSelect.jsx b/anndata-zarr/src/components/ObsSelect.jsx deleted file mode 100644 index 747f3862..00000000 --- a/anndata-zarr/src/components/ObsSelect.jsx +++ /dev/null @@ -1,143 +0,0 @@ -import React, { useEffect, useMemo, useState } from "react"; - -import ExpandLess from "@mui/icons-material/ExpandLess"; -import ExpandMore from "@mui/icons-material/ExpandMore"; -import Alert from "@mui/material/Alert"; -import Box from "@mui/material/Box"; -import Collapse from "@mui/material/Collapse"; -import Divider from "@mui/material/Divider"; -import FormControl from "@mui/material/FormControl"; -import FormControlLabel from "@mui/material/FormControlLabel"; -import List from "@mui/material/List"; -import ListItem from "@mui/material/ListItem"; -import ListItemIcon from "@mui/material/ListItemIcon"; -import ListItemText from "@mui/material/ListItemText"; -import Radio from "@mui/material/Radio"; -import RadioGroup from "@mui/material/RadioGroup"; -import Stack from "@mui/material/Stack"; - -import { COLORSCALES } from "../constants/colorscales"; -import { useAnndataColors, useAnndataObs } from "../hooks"; -import { getColor } from "../utils"; -import { Legend } from "./Legend"; - -// @TODO: fix styling (width) -const CategoricalCol = ({ col, showColor = false }) => { - const [open, setOpen] = useState(false); - const { categories } = col; - - return ( - - setOpen(!open)} sx={{ display: "flex", alignItems: "center", cursor: "pointer" }}> - e.stopPropagation()} />} - label={col.name} - key={col.name} - value={col.name} - /> - {open ? : } - - - {categories.length > 100 && ( - - Truncated to 100 categories - - )} - - {categories.slice(0, 100).map((cat, i) => ( - - {showColor && ( - - - - )} - - - ))} - - - - ); -}; - -const NumericalCol = ({ col }) => { - return } label={col.name} key={col.name} value={col.name} />; -}; - -export const ObsSelect = ({ adata, obsCol, onSelect, callback = () => {} }) => { - const { data, isLoading, serverError } = useAnndataObs(adata); - const colorData = useAnndataColors( - { - ...adata, - matrixProps: { - obs: { col: obsCol }, - }, - }, - { - enabled: !!obsCol, - }, - ); - - useEffect(() => { - if (colorData?.serverError) { - callback(null); - return; - } - if (!colorData?.isLoading && colorData?.data) { - callback(colorData.data.colors); - } - }, [colorData, callback]); - - const legend = useMemo(() => { - if (colorData?.serverError || colorData?.isLoading || !colorData?.data) { - return null; - } - const { min, max, colorscale, categories } = colorData.data; - if (categories) { - return null; - } - return ; - }, [colorData.data, colorData?.isLoading, colorData?.serverError]); - - if (isLoading) { - return <>; - } - if (serverError) { - return
Error loading obs
; - } - return ( - - - Observations - - - onSelect(e.target.value)}> - Categorical - {data.categorical.map((col) => ( - - ))} - Numerical - {data.numerical.map((col) => ( - - ))} - - - - {!!obsCol && legend} - - - ); -}; diff --git a/anndata-zarr/src/components/ObsSelect.tsx b/anndata-zarr/src/components/ObsSelect.tsx index 747f3862..725c23c1 100644 --- a/anndata-zarr/src/components/ObsSelect.tsx +++ b/anndata-zarr/src/components/ObsSelect.tsx @@ -70,7 +70,7 @@ const NumericalCol = ({ col }) => { return } label={col.name} key={col.name} value={col.name} />; }; -export const ObsSelect = ({ adata, obsCol, onSelect, callback = () => {} }) => { +export const ObsSelect = ({ adata, obsCol, onSelect, callback = () => { } }) => { const { data, isLoading, serverError } = useAnndataObs(adata); const colorData = useAnndataColors( { @@ -126,11 +126,11 @@ export const ObsSelect = ({ adata, obsCol, onSelect, callback = () => {} }) => { onSelect(e.target.value)}> Categorical - {data.categorical.map((col) => ( + {data.filter((obs) => 'categories' in obs).map((col) => ( ))} Numerical - {data.numerical.map((col) => ( + {data.filter((obs) => !('categories' in obs)).map((col) => ( ))} diff --git a/anndata-zarr/src/constants/colorscales.js b/anndata-zarr/src/constants/colorscales.ts similarity index 100% rename from anndata-zarr/src/constants/colorscales.js rename to anndata-zarr/src/constants/colorscales.ts diff --git a/anndata-zarr/src/hooks.js b/anndata-zarr/src/hooks.js deleted file mode 100644 index 038f0379..00000000 --- a/anndata-zarr/src/hooks.js +++ /dev/null @@ -1,160 +0,0 @@ -import { useCallback } from "react"; - -import { useQueries, useQuery } from "@tanstack/react-query"; -import _ from "lodash"; - -import { COLORSCALES } from "./constants/colorscales"; -import { fetchDataFromZarr, getColors, getObs, getVarNames, getZarrPath } from "./utils"; -import { - getTableData, - getFeatureNamesFromTable, - getObsFromTable, - getFeatureDataFromTable, - getColumnDataFromTable, -} from "./table-loader"; - -// --------------------------------------------------------------------------- -// Backend-aware data fetching functions -// --------------------------------------------------------------------------- - -async function getFeatureNames(url, namesCol) { - const { meta, data } = await getTableData(url); - if (meta.backend === "anndata") { - return getVarNames(url, namesCol); - } - return getFeatureNamesFromTable(data, meta.indexKey, meta); -} - -async function getObsColumns(url) { - const { meta, data } = await getTableData(url); - if (meta.backend === "anndata") { - return getObs(url); - } - return getObsFromTable(data, meta.indexKey, meta); -} - -function computeColorResult(columnData, colorProps) { - if (!columnData) return null; - const { categories } = columnData; - // Convert BigInt data (from int64 zarr arrays or parquet) to Number - let data = columnData.data; - if (data?.length > 0 && typeof data[0] === "bigint") { - data = Array.from(data, Number); - } - const max = categories ? categories.length - 1 : Number(colorProps?.max || _.max(data)); - const min = categories ? 0 : Number(colorProps?.min || _.min(data)); - const colorscale = categories ? COLORSCALES.Accent : colorProps?.colorscale; - return { - colors: getColors({ - data, - max, - min, - colorProps: { ...colorProps, colorscale }, - categories, - }), - max, - min, - ...(categories ? { categories } : {}), - colorscale, - }; -} - -async function getColorData(url, matrixProps, colorProps) { - const { meta, data } = await getTableData(url); - - let columnData; - if (meta.backend === "anndata") { - try { - const zarrPath = await getZarrPath(url, matrixProps); - columnData = await fetchDataFromZarr(zarrPath.url, zarrPath.path, zarrPath.s); - } catch (error) { - console.error(error); - return null; - } - } else { - const { feature, obs } = matrixProps || {}; - try { - if (feature?.index !== undefined && feature?.index !== null) { - columnData = getFeatureDataFromTable(data, feature.index, meta.indexKey, meta); - } else if (feature?.name) { - columnData = getColumnDataFromTable(data, feature.name); - } else if (obs?.col) { - columnData = getColumnDataFromTable(data, obs.col); - } - } catch (error) { - console.error(error); - return null; - } - } - - return computeColorResult(columnData, colorProps); -} - -// --------------------------------------------------------------------------- -// Hooks -// --------------------------------------------------------------------------- - -export const useAnndataColors = (adata = { url: null }, opts = {}) => { - const { - data = null, - isLoading = false, - serverError = null, - } = useQuery({ - queryKey: ["tableColor", adata.url, adata.matrixProps, adata.colorProps], - queryFn: () => getColorData(adata.url, adata.matrixProps, adata.colorProps), - ...opts, - }); - - return { data, isLoading, serverError }; -}; - -export const useAnndatasColors = (adatas = [], opts = {}) => { - const combine = useCallback((results) => { - return { - data: results.map((result) => result.data), - isLoading: results.some((result) => result.isLoading), - serverError: results.find((result) => result.error), - }; - }, []); - - const { - data = null, - isLoading = false, - serverError = null, - } = useQueries({ - queries: adatas.map(({ url, matrixProps, colorProps }) => ({ - queryKey: ["tableColor", url, matrixProps, colorProps], - queryFn: () => getColorData(url, matrixProps, colorProps), - })), - ...opts, - combine, - }); - - return { data, isLoading, serverError }; -}; - -export const useAnndataFeatures = (adata = { url: null, namesCol: null }) => { - const { - data = null, - isLoading = false, - serverError = null, - } = useQuery({ - queryKey: ["tableFeatures", adata.url, adata.namesCol], - queryFn: () => getFeatureNames(adata.url, adata.namesCol), - }); - - return { data, isLoading, serverError }; -}; - -export const useAnndataObs = (adata = { url: null }) => { - const { - data = null, - isLoading = false, - serverError = null, - } = useQuery({ - queryKey: ["tableObs", adata.url], - queryFn: () => getObsColumns(adata.url), - }); - - return { data, isLoading, serverError }; -}; diff --git a/anndata-zarr/src/hooks.ts b/anndata-zarr/src/hooks.ts index 10a7fc77..6d026ba2 100644 --- a/anndata-zarr/src/hooks.ts +++ b/anndata-zarr/src/hooks.ts @@ -1,12 +1,51 @@ import { useCallback } from "react"; -import { useQueries, useQuery } from "@tanstack/react-query"; +import { useQueries, useQuery, type UseQueryResult } from "@tanstack/react-query"; import _ from "lodash"; +import { z } from 'zod'; + import { COLORSCALES } from "./constants/colorscales"; import { fetchDataFromZarr, getColors, getObs, getVarNames, getZarrPath } from "./utils"; -const getAnndataColors = async (url, matrixProps, colorProps) => { +export interface Feature { + index?: number, + name?: string, + namesCol?: string +} + +export interface MatrixProps { + feature?: { + index?: number, + name?: string, + namesCol?: string + }, + obs?: { + col: number + } +} + +export interface ColourProps { + min: number, + max: number, + colorscale: string[] +} + +interface AnndataQueryParams { + url: URL, + matrixProps?: MatrixProps, + colorProps?: ColourProps +} + +export interface AnndataURL { + url: URL, + namesCol: string + +} + + + +export const getAnndataColors = async (url: URL, matrixProps: MatrixProps, colorProps?: ColourProps) => { let zarrData; try { const zarrPath = await getZarrPath(url, matrixProps); @@ -16,9 +55,7 @@ const getAnndataColors = async (url, matrixProps, colorProps) => { return null; } if (!zarrData) return null; - - const { categories } = zarrData; - + const { categories } = zarrData const max = categories ? categories.length - 1 : colorProps?.max || _.max(zarrData.data); const min = categories ? 0 : colorProps?.min || _.min(zarrData.data); const colorscale = categories ? COLORSCALES.Accent : colorProps?.colorscale; @@ -38,22 +75,18 @@ const getAnndataColors = async (url, matrixProps, colorProps) => { }; }; -export const useAnndataColors = (adata = { url: null }, opts = {}) => { - const { - data = null, - isLoading = false, - serverError = null, - } = useQuery({ - queryKey: ["anndataColor", adata.url, adata.matrixProps, adata.colorProps], - queryFn: () => getAnndataColors(adata.url, adata.matrixProps, adata.colorProps), +export const useAnndataColors = (anndataQueryParams: AnndataQueryParams, opts = {}) => { + const result = useQuery({ + queryKey: ["anndataColor", anndataQueryParams.url, anndataQueryParams.matrixProps, anndataQueryParams.colorProps], + queryFn: () => getAnndataColors(anndataQueryParams.url, anndataQueryParams.matrixProps, anndataQueryParams.colorProps), ...opts, }); - return { data, isLoading, serverError }; + return result; }; export const useAnndatasColors = (adatas = [], opts = {}) => { - const combine = useCallback((results) => { + const combine = useCallback((results: UseQueryResult[]) => { return { data: results.map((result) => result.data), isLoading: results.some((result) => result.isLoading), @@ -77,28 +110,19 @@ export const useAnndatasColors = (adatas = [], opts = {}) => { return { data, isLoading, serverError }; }; -export const useAnndataFeatures = (adata = { url: null, namesCol: null }) => { - const { - data = null, - isLoading = false, - serverError = null, - } = useQuery({ +export const useAnndataFeatures = (adata: AnndataURL) => { + const result = useQuery({ queryKey: ["anndataFeatures", adata.url, adata.namesCol], - queryFn: () => getVarNames(adata.url, adata.namesCol), + queryFn: () => getVarNames(adata.url), }); - return { data, isLoading, serverError }; + return result; }; -export const useAnndataObs = (adata = { url: null }) => { - const { - data = null, - isLoading = false, - serverError = null, - } = useQuery({ +export const useAnndataObs = (adata: AnndataURL) => { + const result = useQuery({ queryKey: ["anndataObs", adata.url], queryFn: () => getObs(adata.url), }); - - return { data, isLoading, serverError }; + return result; }; diff --git a/anndata-zarr/src/index.js b/anndata-zarr/src/index.ts similarity index 100% rename from anndata-zarr/src/index.js rename to anndata-zarr/src/index.ts diff --git a/anndata-zarr/src/provider.jsx b/anndata-zarr/src/provider.jsx deleted file mode 100644 index c250d401..00000000 --- a/anndata-zarr/src/provider.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from "react"; - -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; - -const queryClient = new QueryClient(); - -export function AnndataProvider({ children }) { - return {children}; -} diff --git a/anndata-zarr/src/table-loader.js b/anndata-zarr/src/table-loader.ts similarity index 100% rename from anndata-zarr/src/table-loader.js rename to anndata-zarr/src/table-loader.ts diff --git a/anndata-zarr/src/utils.js b/anndata-zarr/src/utils.js deleted file mode 100644 index 3e206c43..00000000 --- a/anndata-zarr/src/utils.js +++ /dev/null @@ -1,170 +0,0 @@ -import _ from "lodash"; -import { FetchStore, get, open } from "zarrita"; - -import { COLORSCALES } from "./constants/colorscales"; - -export const fetchDataFromZarr = async (url, path, s) => { - try { - const store = new FetchStore(url); - const node = await open(store, { kind: "group" }); - - const dataNode = await open(node.resolve(path)); - let result; - if (dataNode.attrs?.["encoding-type"] === "array" && dataNode.dtype === "bool") { - const boolData = await get(dataNode, s); - result = { - data: Array.from(boolData.data), - categories: ["false", "true"], - }; - } else if (dataNode.attrs?.["encoding-type"] === "array" || dataNode.attrs?.["encoding-type"] === "string-array") { - result = await get(dataNode, s); - } else if (dataNode.attrs?.["encoding-type"] === "categorical") { - const categoriesArr = await open(dataNode.resolve("categories"), { - kind: "array", - }); - const codesArr = await open(dataNode.resolve("codes"), { kind: "array" }); - const { data: categories } = await get(categoriesArr); - const { data } = await get(codesArr, s); - result = { data, categories }; - } else { - throw new Error("Unsupported encoding-type"); - } - - return result; - } catch (error) { - // biome-ignore lint/complexity/noUselessCatch: @TODO: better error handling - throw error; - } -}; - -export const getVarNames = async (url, namesCol = "_index") => { - try { - const store = new FetchStore(url); - const node = await open(store, { kind: "group" }); - - const arr = await open(node.resolve(`var/${namesCol}`, { kind: "array" })); - const varNames = (await get(arr)).data; - return varNames; - } catch (error) { - console.error(error); - return []; - } -}; - -export const getObs = async (url) => { - try { - const store = new FetchStore(url); - const node = await open(store, { kind: "group" }); - - const cols = (await open(node.resolve("obs", { kind: "group" }))).attrs?.["column-order"]; - const obs = { categorical: [], numerical: [] }; - for (const col of cols) { - const dataNode = await open(node.resolve(`obs/${col}`)); - const { "encoding-type": encodingType } = dataNode.attrs || {}; - if (encodingType === "categorical") { - const categoriesArr = await open(dataNode.resolve("categories"), { - kind: "array", - }); - const { data: categories } = await get(categoriesArr); - obs.categorical.push({ name: col, categories }); - } else if (encodingType === "array") { - if (dataNode.dtype === "bool") { - obs.categorical.push({ name: col, categories: ["false", "true"] }); - } else { - obs.numerical.push({ name: col }); - } - } - } - return obs; - } catch (error) { - console.error(error); - return []; - } -}; - -export const getVarIndex = async (url, varId, namesCol = "_index") => { - try { - const store = new FetchStore(url); - const node = await open(store, { kind: "group" }); - - const arr = await open(node.resolve(`var/${namesCol}`, { kind: "array" })); - const varNames = (await get(arr)).data; - const varIndex = varNames.findIndex((name) => name === varId); - return varIndex; - } catch (error) { - return -1; - } -}; - -export const getZarrPath = async (url, matrixProps) => { - const { feature, obs } = matrixProps; - if (feature) { - if (feature.index !== undefined && feature.index !== null) { - return { url, path: "X", s: [null, feature.index] }; - } - if (feature.name) { - return { - url, - path: "X", - s: [null, await getVarIndex(url, feature.name, feature.namesCol)], - }; - } - } - - if (obs) { - return { - url, - path: `obs/${obs.col}`, - s: null, - }; - } - - throw new Error("No feature or obs in matrixProps"); -}; - -const parseHexColor = (color) => { - const r = Number.parseInt(color?.substring(1, 3), 16); - const g = Number.parseInt(color?.substring(3, 5), 16); - const b = Number.parseInt(color?.substring(5, 7), 16); - - return [r, g, b]; -}; - -const interpolateColor = (color1, color2, factor) => { - const [r1, g1, b1] = parseHexColor(color1); - const [r2, g2, b2] = parseHexColor(color2); - - const r = Math.round(r1 + factor * (r2 - r1)); - const g = Math.round(g1 + factor * (g2 - g1)); - const b = Math.round(b1 + factor * (b2 - b1)); - - return [r, g, b]; -}; - -const computeColor = (colormap, value) => { - if (!colormap || Number.isNaN(value)) { - return [0, 0, 0, 255]; - } - if (value <= 0) { - return parseHexColor(colormap[0]); - } - if (value >= 1) { - return parseHexColor(colormap[colormap.length - 1]); - } - const index1 = Math.floor(value * (colormap.length - 1)); - const index2 = Math.ceil(value * (colormap.length - 1)); - const factor = (value * (colormap.length - 1)) % 1; - return interpolateColor(colormap[index1], colormap[index2], factor); -}; - -export const getColor = ({ value, colorscale = COLORSCALES.Viridis }) => { - return [...computeColor(colorscale, value), 255]; -}; - -export const getColors = ({ data, max, min, colorProps, categories }) => { - return _.map(data, (v, i) => ({ - labelValue: i + 1, - rgba: getColor({ value: (v - min) / (max - min), ...colorProps }), - value: categories ? (categories[v] ?? v) : v, - })); -}; diff --git a/anndata-zarr/src/utils.ts b/anndata-zarr/src/utils.ts index 3e206c43..2632cd35 100644 --- a/anndata-zarr/src/utils.ts +++ b/anndata-zarr/src/utils.ts @@ -1,93 +1,170 @@ import _ from "lodash"; -import { FetchStore, get, open } from "zarrita"; +import { FetchStore, get, open, Group, type Readable, type DataType, Array as ZarrArray, type Float64 } from "zarrita"; import { COLORSCALES } from "./constants/colorscales"; +import type { ColourProps, MatrixProps } from "./hooks"; +import type { URL } from "url"; +import { z } from 'zod'; -export const fetchDataFromZarr = async (url, path, s) => { +const AnndataZarrBaseAttributesSchema = z.object({ + 'encoding-type': z.enum(["anndata", "dataframe", "array", "categorical", "string-array"]), + 'encoding-version': z.string() +}) + +const AnndataZarrObsAttributesSchema = AnndataZarrBaseAttributesSchema.extend({ + 'column-order': z.array(z.string()), + '_index': z.string().optional() +}) + +const AnndataCategoriesSchema = z.array(z.string()) + + + +function resolveAnndataZarrObsAttributes(attrs: unknown): z.infer { + return AnndataZarrObsAttributesSchema.parse(attrs) +} + +function resolveAnndataZarrBaseAttributes(attrs: unknown): z.infer { + return AnndataZarrBaseAttributesSchema.parse(attrs) +} + + +async function fetchZarrGroup(url: URL): Promise> { + const store = new FetchStore(url) + return await open(store, { kind: "group" }) +} + +async function fetchZarrArray(url: URL, path: string): Promise> { + const store = new FetchStore(url) + return await open(store, { kind: "array" }) +} + + +const RawColourData = z.object({ + data: z.any(), + shape: z.array(z.number()), + stride: z.array(z.number()) +}) + +const RawCategoricalColourData = z.object({ + data: z.array(z.number()), + categories: z.array(z.string()) +}) + +const parseRawColourData = function (data: unknown): z.infer { + return RawColourData.parse(data) +} + +const parseRawCategoricalColourData = function (data: unknown): z.infer { + return RawCategoricalColourData.parse(data) +} + +export const fetchDataFromZarr = async (url: URL, path: string, s: []): Promise<{ data: number[], categories?: string[] }> => { try { - const store = new FetchStore(url); - const node = await open(store, { kind: "group" }); + const node = await fetchZarrGroup(url) + const dataNode = await open(node.resolve(path)) + const attrs = resolveAnndataZarrBaseAttributes(dataNode.attrs) - const dataNode = await open(node.resolve(path)); - let result; - if (dataNode.attrs?.["encoding-type"] === "array" && dataNode.dtype === "bool") { - const boolData = await get(dataNode, s); - result = { - data: Array.from(boolData.data), - categories: ["false", "true"], - }; - } else if (dataNode.attrs?.["encoding-type"] === "array" || dataNode.attrs?.["encoding-type"] === "string-array") { - result = await get(dataNode, s); - } else if (dataNode.attrs?.["encoding-type"] === "categorical") { - const categoriesArr = await open(dataNode.resolve("categories"), { - kind: "array", - }); - const codesArr = await open(dataNode.resolve("codes"), { kind: "array" }); - const { data: categories } = await get(categoriesArr); - const { data } = await get(codesArr, s); - result = { data, categories }; - } else { - throw new Error("Unsupported encoding-type"); + if (dataNode instanceof Group) { + if (attrs["encoding-type"] === "categorical") { + const categoriesArr = await open(dataNode.resolve("categories"), { + kind: "array", + }); + const codesArr = await open(dataNode.resolve("codes"), { kind: "array" }); + const categories = await get(categoriesArr); + const parsedCategories = parseRawColourData(categories) + const data = await get(codesArr, s); + const parsedData = parseRawColourData(data) + return { data: parsedData.data, categories: parsedCategories.data } + } + } else if (dataNode instanceof ZarrArray) { + if (attrs["encoding-type"] === "array" && dataNode.dtype === "bool") { + const boolData = await get(dataNode, s); + const parsedBoolData = parseRawColourData(boolData) + return { + data: Array.from(parsedBoolData.data), + categories: ["false", "true"], + }; + } else if (attrs["encoding-type"] === "array" || attrs["encoding-type"] === "string-array") { + return parseRawColourData(await get(dataNode, s)); + } } - return result; + return ({ data: [] }) + } catch (error) { // biome-ignore lint/complexity/noUselessCatch: @TODO: better error handling throw error; } }; -export const getVarNames = async (url, namesCol = "_index") => { +export const getVarNames = async (url: URL) => { try { const store = new FetchStore(url); const node = await open(store, { kind: "group" }); - - const arr = await open(node.resolve(`var/${namesCol}`, { kind: "array" })); - const varNames = (await get(arr)).data; + const varNode = await open(node.resolve('var')) + const parsedAttrs = AnndataZarrObsAttributesSchema.parse(varNode.attrs) + //To-do try default "_index" + const array = await open(node.resolve(`var/${parsedAttrs._index}`), { kind: "array" }); + const varNames = (await get(array)).data; return varNames; + } catch (error) { console.error(error); return []; } }; -export const getObs = async (url) => { +type Observation = { name: string, categories?: string[] } + +export const getObs = async (url: URL): Promise> => { try { const store = new FetchStore(url); const node = await open(store, { kind: "group" }); - const cols = (await open(node.resolve("obs", { kind: "group" }))).attrs?.["column-order"]; - const obs = { categorical: [], numerical: [] }; - for (const col of cols) { - const dataNode = await open(node.resolve(`obs/${col}`)); - const { "encoding-type": encodingType } = dataNode.attrs || {}; - if (encodingType === "categorical") { - const categoriesArr = await open(dataNode.resolve("categories"), { - kind: "array", - }); - const { data: categories } = await get(categoriesArr); - obs.categorical.push({ name: col, categories }); - } else if (encodingType === "array") { - if (dataNode.dtype === "bool") { - obs.categorical.push({ name: col, categories: ["false", "true"] }); - } else { - obs.numerical.push({ name: col }); + const obsNode = (await open(node.resolve("obs"), { kind: "group" })) + const attrs = resolveAnndataZarrObsAttributes(obsNode.attrs) + const cols = attrs["column-order"] + + const obs = await Promise.all( + cols.map(async (col) => { + const dataNode = await open(node.resolve(`obs/${col}`)); + const encodingType = dataNode.attrs['encoding-type'] || {}; + + if (dataNode instanceof ZarrArray) { + if (dataNode.dtype === 'bool') { + return ({ name: col, categories: ["false", "true"] }) + } + if (encodingType == 'array' || encodingType === 'string-array') { + return { name: col }; + } + + } else if (dataNode instanceof Group) { + const categoriesArr = await open(dataNode.resolve("categories"), { + kind: "array", + }); + const categories = await get(categoriesArr); + const parsedCategories = AnndataCategoriesSchema.parse(categories.data) + return { name: col, categories: parsedCategories } } - } - } - return obs; + + }) + ) + + return obs.filter((observation) => observation != undefined) + } catch (error) { console.error(error); return []; } }; -export const getVarIndex = async (url, varId, namesCol = "_index") => { +export const getVarIndex = async (url: URL, varId: string, namesCol = "_index") => { try { const store = new FetchStore(url); const node = await open(store, { kind: "group" }); - const arr = await open(node.resolve(`var/${namesCol}`, { kind: "array" })); + const arr = await open(node.resolve(`var/${namesCol}`), { kind: "array" }); const varNames = (await get(arr)).data; const varIndex = varNames.findIndex((name) => name === varId); return varIndex; @@ -96,7 +173,7 @@ export const getVarIndex = async (url, varId, namesCol = "_index") => { } }; -export const getZarrPath = async (url, matrixProps) => { +export const getZarrPath = async (url: URL, matrixProps: MatrixProps) => { const { feature, obs } = matrixProps; if (feature) { if (feature.index !== undefined && feature.index !== null) { @@ -122,7 +199,7 @@ export const getZarrPath = async (url, matrixProps) => { throw new Error("No feature or obs in matrixProps"); }; -const parseHexColor = (color) => { +const parseHexColor = (color: string) => { const r = Number.parseInt(color?.substring(1, 3), 16); const g = Number.parseInt(color?.substring(3, 5), 16); const b = Number.parseInt(color?.substring(5, 7), 16); @@ -130,7 +207,7 @@ const parseHexColor = (color) => { return [r, g, b]; }; -const interpolateColor = (color1, color2, factor) => { +const interpolateColor = (color1: string, color2: string, factor: number) => { const [r1, g1, b1] = parseHexColor(color1); const [r2, g2, b2] = parseHexColor(color2); @@ -141,7 +218,7 @@ const interpolateColor = (color1, color2, factor) => { return [r, g, b]; }; -const computeColor = (colormap, value) => { +const computeColor = (colormap: string[], value: number) => { if (!colormap || Number.isNaN(value)) { return [0, 0, 0, 255]; } @@ -157,12 +234,12 @@ const computeColor = (colormap, value) => { return interpolateColor(colormap[index1], colormap[index2], factor); }; -export const getColor = ({ value, colorscale = COLORSCALES.Viridis }) => { +export const getColor = ({ value, colorscale = COLORSCALES.Viridis }: { value: number, colorscale: string[] }) => { return [...computeColor(colorscale, value), 255]; }; -export const getColors = ({ data, max, min, colorProps, categories }) => { - return _.map(data, (v, i) => ({ +export const getColors = ({ data, max, min, colorProps, categories }: { data: number[], max: number, min: number, colorProps: ColourProps, categories?: string[] }) => { + return _.map(data, (v: number, i: number) => ({ labelValue: i + 1, rgba: getColor({ value: (v - min) / (max - min), ...colorProps }), value: categories ? (categories[v] ?? v) : v, diff --git a/anndata-zarr/tests/expected_colours.json b/anndata-zarr/tests/expected_colours.json new file mode 100644 index 00000000..91899a74 --- /dev/null +++ b/anndata-zarr/tests/expected_colours.json @@ -0,0 +1 @@ +{"colors":[{"labelValue":1,"rgba":[68,57,130,255],"value":0.1658300302601523},{"labelValue":2,"rgba":[34,143,140,255],"value":0.4891459405665751},{"labelValue":3,"rgba":[191,223,38,255],"value":0.8974329354849481},{"labelValue":4,"rgba":[69,8,91,255],"value":0.023533927427546897},{"labelValue":5,"rgba":[163,218,54,255],"value":0.8563984648832248},{"labelValue":6,"rgba":[222,227,27,255],"value":0.9432887992234683},{"labelValue":7,"rgba":[199,224,34,255],"value":0.9090499221056513},{"labelValue":8,"rgba":[110,206,89,255],"value":0.772540518883162},{"labelValue":9,"rgba":[164,218,54,255],"value":0.8577915438512621},{"labelValue":10,"rgba":[224,227,28,255],"value":0.9458883944319205},{"labelValue":11,"rgba":[67,60,132,255],"value":0.17752092088363824},{"labelValue":12,"rgba":[185,222,41,255],"value":0.888718367894147},{"labelValue":13,"rgba":[31,157,137,255],"value":0.5504706652423125},{"labelValue":14,"rgba":[187,222,40,255],"value":0.8912855692053849},{"labelValue":15,"rgba":[37,133,142,255],"value":0.45122083454421824},{"labelValue":16,"rgba":[69,53,128,255],"value":0.15447245437137225},{"labelValue":17,"rgba":[35,140,141,255],"value":0.48013174167796535},{"labelValue":18,"rgba":[69,9,92,255],"value":0.024812424216993034},{"labelValue":19,"rgba":[35,139,141,255],"value":0.4748136489032414},{"labelValue":20,"rgba":[241,229,33,255],"value":0.9753731220887473},{"labelValue":21,"rgba":[135,213,73,255],"value":0.813230676083472},{"labelValue":22,"rgba":[70,11,94,255],"value":0.030333847161120864},{"labelValue":23,"rgba":[63,73,136,255],"value":0.22004476431310427},{"labelValue":24,"rgba":[253,231,37,255],"value":0.9948084537223887},{"labelValue":25,"rgba":[42,121,142,255],"value":0.4005457376940761},{"labelValue":26,"rgba":[172,220,49,255],"value":0.8686849274738432},{"labelValue":27,"rgba":[89,199,101,255],"value":0.7362613877052966},{"labelValue":28,"rgba":[71,39,118,255],"value":0.10972745888698887},{"labelValue":29,"rgba":[36,135,141,255],"value":0.4582572201664642},{"labelValue":30,"rgba":[199,224,34,255],"value":0.9081289285441259},{"labelValue":31,"rgba":[71,19,102,255],"value":0.05310654963214745},{"labelValue":32,"rgba":[57,86,139,255],"value":0.26427251460612133},{"labelValue":33,"rgba":[51,98,141,255],"value":0.3098868831143512},{"labelValue":34,"rgba":[71,45,123,255],"value":0.12859385219192254},{"labelValue":35,"rgba":[71,38,117,255],"value":0.1060341064816438},{"labelValue":36,"rgba":[56,88,140,255],"value":0.273146979830608},{"labelValue":37,"rgba":[94,201,98,255],"value":0.7474387872660285},{"labelValue":38,"rgba":[79,195,106,255],"value":0.7168943965063371},{"labelValue":39,"rgba":[31,159,136,255],"value":0.5567800064876861},{"labelValue":40,"rgba":[118,208,84,255],"value":0.785358005462284},{"labelValue":41,"rgba":[181,221,44,255],"value":0.8820685615410931},{"labelValue":42,"rgba":[177,221,46,255],"value":0.8764131827619143},{"labelValue":43,"rgba":[69,6,89,255],"value":0.016894230930217247},{"labelValue":44,"rgba":[69,4,87,255],"value":0.011590410943970952},{"labelValue":45,"rgba":[76,194,108,255],"value":0.7116094880320885},{"labelValue":46,"rgba":[54,92,140,255],"value":0.2881044279476044},{"labelValue":47,"rgba":[213,226,27,255],"value":0.9282508060940267},{"labelValue":48,"rgba":[40,125,142,255],"value":0.4158803393647662},{"labelValue":49,"rgba":[66,64,134,255],"value":0.19045753449072},{"labelValue":50,"rgba":[45,112,142,255],"value":0.36713928055013845},{"labelValue":51,"rgba":[207,225,30,255],"value":0.9194919597647628},{"labelValue":52,"rgba":[56,89,140,255],"value":0.2772744211351149},{"labelValue":53,"rgba":[54,92,140,255],"value":0.2887579479880511},{"labelValue":54,"rgba":[56,89,140,255],"value":0.2767322711017376},{"labelValue":55,"rgba":[90,200,100,255],"value":0.739933093943506},{"labelValue":56,"rgba":[71,42,121,255],"value":0.11849387104612308},{"labelValue":57,"rgba":[37,132,142,255],"value":0.4465532692621863},{"labelValue":58,"rgba":[140,214,70,255],"value":0.8211443808344999},{"labelValue":59,"rgba":[32,162,135,255],"value":0.5709565352647414},{"labelValue":60,"rgba":[68,1,84,255],"value":0.0034096290176031108},{"labelValue":61,"rgba":[60,79,138,255],"value":0.24026647309570515}],"max":0.9948084537223887,"min":0.0034096290176031108} \ No newline at end of file diff --git a/anndata-zarr/tests/test.test.ts b/anndata-zarr/tests/test.test.ts new file mode 100644 index 00000000..70b6ee61 --- /dev/null +++ b/anndata-zarr/tests/test.test.ts @@ -0,0 +1,22 @@ +import { expect, test } from "vitest"; +import yaml from 'yaml'; +import fs from 'node:fs'; +import path from 'node:path'; +import expectedColours from './expected_colours.json' + +import { getAnndataColors } from "../src/hooks" + +const fixtures_path = path.resolve(path.join(__dirname, "..", "..", "fixtures")) + +test("Can get anndata colours", async () => { + const table = yaml.parse(fs.readFileSync(path.join(fixtures_path, "anndata_table.yaml"), 'utf-8')) + + const matrixProps = { + feature: { + index: 3 + } + } + const colours = await getAnndataColors(table.source, matrixProps) + + expect(colours).toEqual(expectedColours) +}) From 29d9fa5ef049ef89ba4d9be38fe24ef43c6b5813 Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Tue, 9 Jun 2026 15:42:19 +0100 Subject: [PATCH 15/26] Further refactoring --- anndata-zarr/src/anndata.ts | 222 ++++++++++++++++++ .../src/components/AnndataController.tsx | 71 +++++- anndata-zarr/src/components/FeatureSelect.tsx | 71 ++---- anndata-zarr/src/components/ObsSelect.tsx | 69 ++---- anndata-zarr/src/hooks.ts | 112 +++++---- anndata-zarr/src/index.ts | 2 +- anndata-zarr/src/utils.ts | 201 +--------------- anndata-zarr/src/zarr.ts | 24 ++ anndata-zarr/types.ts | 7 - 9 files changed, 425 insertions(+), 354 deletions(-) create mode 100644 anndata-zarr/src/anndata.ts create mode 100644 anndata-zarr/src/zarr.ts diff --git a/anndata-zarr/src/anndata.ts b/anndata-zarr/src/anndata.ts new file mode 100644 index 00000000..8f0c2b0e --- /dev/null +++ b/anndata-zarr/src/anndata.ts @@ -0,0 +1,222 @@ +import { z } from 'zod'; +import type { URL } from "url"; +import { FetchStore, open } from "zarrita"; +import { fetchZarrGroup, getData } from './zarr'; + +const OBSERVATION_NAMES_PATH = 'obs' +const FEATURE_NAMES_PATH = 'var' +const CATEGORY_NAMES_PATH = 'categories' +const CATEGORY_DATA_PATH = 'codes' +const VAR_NAMES_PATH = "_index" + +export interface Observation { name: string } +export interface CategoricalObservation extends Observation { + categories: string[] +} + +const ZarrAttrsSchema = z.object({ + 'encoding-type': z.enum(["anndata", "dataframe", "array", "categorical", "string-array"]), + 'encoding-version': z.string() +}) + +const ZarrObservationAttrsSchema = ZarrAttrsSchema.extend({ + 'column-order': z.array(z.string()), + '_index': z.string().optional() +}) + +const AnndataCategoriesSchema = z.array(z.string()) + +function parseZarrObservationAttrs(attrs: unknown): z.infer { + return ZarrObservationAttrsSchema.parse(attrs) +} + +function parseZarrAttrs(attrs: unknown): z.infer { + return ZarrAttrsSchema.parse(attrs) +} + +const IntegerArraySchema = z.array(z.number().int().or(z.nan())) + +const FloatArraySchema = z.array(z.number().or(z.nan())) + +const StringArraySchema = z.array(z.string()) + +const BooleanArraySchema = z.array(z.boolean()) + + +const parseIntegerArray = function (data: unknown): z.infer { + return IntegerArraySchema.parse(data) +} + +function parseFloatArray(data: unknown[]): z.infer { + return FloatArraySchema.parse(data) +} + +function parseStringArray(data: unknown[]): z.infer { + return StringArraySchema.parse(data) +} + +function parseBooleanArray(data: unknown[]): number[] { + const parsedData = BooleanArraySchema.parse(data) + return parsedData.map((value: boolean) => Number(value)) +} + +const getDataPath = function (encodingType: string): string | undefined { + if (encodingType === 'categorical') { + return CATEGORY_DATA_PATH + } + return '' +} +export const fetchDataFromZarr = async (url: URL, path: string, slice: (number | null)[] | undefined): Promise<{ data: number[], categories?: string[] }> => { + const root = await fetchZarrGroup(url) + const dataNodeOrGroup = await open(root.resolve(path)) + const attrs = parseZarrAttrs(dataNodeOrGroup.attrs) + const dataPath = `${path}/${getDataPath(attrs['encoding-type'])}` + const { data, dtype } = await getData(root, dataPath, slice) + if (dtype === 'bool') { + const parsedData = parseBooleanArray(data) + return { + data: parsedData, + categories: ['false', 'true'] + } + } + if (attrs['encoding-type'] === 'categorical') { + const parsedData = parseIntegerArray(data) + const categoryNamesPath = `${path}/${CATEGORY_NAMES_PATH}` + const categories = await getData(root, categoryNamesPath) + const categoryNames = parseStringArray(categories.data) + + return { + data: parsedData, + categories: categoryNames + } + } else if (attrs['encoding-type'] === 'array') { + const parsedData = parseFloatArray(data) + return ({ + data: parsedData + }) + } else if (attrs['encoding-type'] === 'string-array') { + const parsedData = parseStringArray(data) + return ({ + data: parsedData + }) + } + return ({ data: [] }) + +}; + +export const getFeatureNames = async (url: URL): Promise => { + try { + const root = await fetchZarrGroup(url); + + const node = await open(root.resolve(FEATURE_NAMES_PATH)) + const parsedAttrs = ZarrObservationAttrsSchema.parse(node.attrs) + const path = `${FEATURE_NAMES_PATH}/${parsedAttrs._index}` + const { data, dtype } = await getData(root, path) + return parseStringArray(data); + } catch (error) { + console.error(error); + return []; + } +}; + +function getObservationNamesPath(encodingType: string): string { + if (encodingType === 'categorical') { + return CATEGORY_NAMES_PATH + } + return '' +} + +export const getObservationNames = async (url: URL): Promise> => { + try { + const root = await fetchZarrGroup(url) + + const node = (await open(root.resolve(OBSERVATION_NAMES_PATH), { kind: "group" })) + console.log('Fetching observation names from attrs:', node.attrs) + const attrs = parseZarrObservationAttrs(node.attrs) + const cols = attrs["column-order"] + const obs = await Promise.all( + cols.map(async (col) => { + const dataNodeOrGroup = await open(root.resolve(`${OBSERVATION_NAMES_PATH}/${col}`)); + const parsedAttrs = ZarrAttrsSchema.parse(dataNodeOrGroup.attrs) + const dataPath = `${OBSERVATION_NAMES_PATH}/${col}/${getObservationNamesPath(parsedAttrs['encoding-type'])}` + const dataNode = await open(root.resolve(dataPath), { kind: 'array' }) + if (dataNode.dtype === 'bool') { + return ({ name: col, categories: ["false", "true"] }) + } + if (parsedAttrs['encoding-type'] == 'array' || parsedAttrs['encoding-type'] === 'string-array') { + return { name: col }; + } + const { data, dtype } = await getData(root, dataPath) + const parsedCategories = AnndataCategoriesSchema.parse(data) + return { name: col, categories: parsedCategories } + + }) + ) + return obs.filter((observation) => observation != undefined) + + } catch (error) { + console.error(error); + return []; + } +}; + +const ARRAY_PATH = 'X' + +export const getVarIndex = async (url: URL, varId: string, namesCol = VAR_NAMES_PATH) => { + const store = new FetchStore(url); + const node = await open(store, { kind: "group" }); + + const { data, dtype } = await getData(node, `${VAR_NAMES_PATH}/${namesCol}`) + + const varNames = parseStringArray(data); + const varIndex = varNames.findIndex((name: string) => name === varId); + debugger; + return varIndex; +}; + +export async function getFeatureDataPath(url: URL, index?: number, name?: string): Promise<{ path: string, slice: (number | null)[] }> { + if (index) { + return ({ + path: ARRAY_PATH, + slice: [null, index] + }) + } else if (name) { + return { + path: ARRAY_PATH, + slice: [null, await getVarIndex(url, name)] + } + } else { + throw new Error(`Index or name needed to determine feature data path`) + } +} + +export async function getObservationDataPath(name: string): Promise<{ path: string, slice: undefined }> { + return { + path: `${OBSERVATION_NAMES_PATH}/${name}`, + slice: undefined + } +} + +//export const getZarrDataPath = async (url: URL, name: string, type: string) => { +// if (type === 'feature') { +// if (feature.index !== undefined && feature.index !== null) { +// return { url, path: "X", s: [null, feature.index] }; +// } +// if (feature.name) { +// return { +// url, +// path: "X", +// s: [null, await getVarIndex(url, feature.name)], +// }; +// } +// } +// if (obs) { +// return { +// url, +// path: `obs/${obs.col}`, +// s: null, +// }; +// } +// +// throw new Error("No feature or obs in matrixProps"); +//}; diff --git a/anndata-zarr/src/components/AnndataController.tsx b/anndata-zarr/src/components/AnndataController.tsx index 07f84ba5..767df5e8 100644 --- a/anndata-zarr/src/components/AnndataController.tsx +++ b/anndata-zarr/src/components/AnndataController.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import Box from "@mui/material/Box"; import Stack from "@mui/material/Stack"; @@ -6,27 +6,74 @@ import Stack from "@mui/material/Stack"; import { FeatureSelect } from "./FeatureSelect"; import { ObsSelect } from "./ObsSelect"; -export const AnndataController = ({ adata, callback = () => { } }) => { - const [feature, setFeature] = useState(null); - const [obsCol, setObsCol] = useState(null); - console.log("RENDERING FeatureSelect with ", adata) - const handleFeatureSelect = (f) => { + +import { useAnndataColors, useAnndataFeatures, useAnndataObs, type Feature, type FeatureParams, type ObservationParams } from "../hooks"; +import type { Observation } from "../anndata"; + +interface ColourQueryParams { + name: string, + type: 'observation' | 'feature' +} + +function getFeatureParams(feature: Feature): FeatureParams { + return ( + { type: 'feature', params: feature } + ) +} + +function getObservationParams(observation: string): ObservationParams { + return ( + { type: 'observation', params: { name: observation } } + ) +} + +export const AnndataController = ({ adata, callback = () => { } }: { adata: string, callback: Function }) => { + const [feature, setFeature] = useState(undefined); + const [observation, setObservation] = useState(undefined) + const url = { url: new URL(adata) } + + const handleFeatureSelect = (f: Feature) => { setFeature(f); - setObsCol(null); + setObservation(undefined) }; - const handleObsSelect = (o) => { - setObsCol(o); - setFeature(null); + const handleObservationSelect = (o: string) => { + setObservation(o); + console.log('Setting observation to', o) + setFeature(undefined) }; + + + const features = useAnndataFeatures(url); + const observations = useAnndataObs(url); + + const param = feature ? getFeatureParams(feature) : (observation ? getObservationParams(observation) : undefined) + + const colorData = useAnndataColors(url.url, param, { enabled: !!param }) + + + const legendData = colorData.data && 'colorscale' in colorData.data ? colorData.data : undefined + + useEffect(() => { + if (colorData?.isError) { + callback(null); + return; + } + if (!colorData?.isLoading && colorData?.data) { + + callback(colorData.data.colors); + } + }, [colorData, callback]); + return ( - + {features.data && } - + {observations.data && } + ); }; diff --git a/anndata-zarr/src/components/FeatureSelect.tsx b/anndata-zarr/src/components/FeatureSelect.tsx index c940dd7e..d4710924 100644 --- a/anndata-zarr/src/components/FeatureSelect.tsx +++ b/anndata-zarr/src/components/FeatureSelect.tsx @@ -8,10 +8,10 @@ import Stack from "@mui/material/Stack"; import TextField from "@mui/material/TextField"; import { List } from "react-window"; -import { useAnndataColors, useAnndataFeatures } from "../hooks"; +import { type ColourProps, type Feature } from "../hooks"; import { Legend } from "./Legend"; -const RowComponent = ({ index, items, style, onSelect, selectedIndex }) => { +const RowComponent = ({ index, items, style, onSelect, selectedIndex }: { index: number, items: { matrixIndex: number, name: string }[], style: React.DetailedHTMLProps, HTMLStyleElement>, onSelect: Function, selectedIndex?: number }) => { return ( { ); }; -export const FeatureSelect = ({ adata, feature, onSelect, callback = () => { } }) => { +// List of features +// Currently selected feature to display +// onSelect to set feature + +export const FeatureSelect = ({ featureNames, selectedFeature, onFeatureSelect, legendData }: { featureNames: string[], selectedFeature?: Feature, onFeatureSelect: Function, legendData?: ColourProps }) => { const [searchTerm, setSearchTerm] = useState(""); - const { data, isLoading, serverError } = useAnndataFeatures(adata); - const colorData = useAnndataColors( - { - ...adata, - matrixProps: { - feature: feature, - }, - }, - { enabled: !!feature }, - ); - useEffect(() => { - if (colorData?.serverError) { - callback(null); - return; - } - if (!colorData?.isLoading && colorData?.data) { - callback(colorData.data.colors); + const allItems = featureNames.map((name: string, index: number) => { + return { + name: name, + matrixIndex: index } - }, [colorData, callback]); - - const items = useMemo(() => { - if (!data) return []; - const allItems = data.map((name, index) => ({ - name, - matrixIndex: index, - })); - if (!searchTerm) return allItems; - return allItems.filter((item) => item.name.toLowerCase().includes(searchTerm.toLowerCase())); - }, [data, searchTerm]); + }) const legend = useMemo(() => { - if (colorData?.serverError || colorData?.isLoading || !colorData?.data) { - return null; + if (legendData) { + return ; + } else { + return <> } - const { min, max, colorscale } = colorData.data; - return ; - }, [colorData.data, colorData?.isLoading, colorData?.serverError]); + }, [legendData]); + + - if (isLoading) { - return <>; - } - if (serverError) { - return
Error loading features
; - } return ( { } } /> - {!!feature && legend} + {legend}
); diff --git a/anndata-zarr/src/components/ObsSelect.tsx b/anndata-zarr/src/components/ObsSelect.tsx index 725c23c1..630a09ca 100644 --- a/anndata-zarr/src/components/ObsSelect.tsx +++ b/anndata-zarr/src/components/ObsSelect.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from "react"; +import React, { useMemo, useState } from "react"; import ExpandLess from "@mui/icons-material/ExpandLess"; import ExpandMore from "@mui/icons-material/ExpandMore"; @@ -17,12 +17,12 @@ import RadioGroup from "@mui/material/RadioGroup"; import Stack from "@mui/material/Stack"; import { COLORSCALES } from "../constants/colorscales"; -import { useAnndataColors, useAnndataObs } from "../hooks"; -import { getColor } from "../utils"; +import { type ColourProps } from "../hooks"; +import { getColor, type CategoricalObservation, type Observation } from "../utils"; import { Legend } from "./Legend"; // @TODO: fix styling (width) -const CategoricalCol = ({ col, showColor = false }) => { +const CategoricalCol = ({ col, showColor = false }: { col: CategoricalObservation, showColor: boolean }) => { const [open, setOpen] = useState(false); const { categories } = col; @@ -66,51 +66,28 @@ const CategoricalCol = ({ col, showColor = false }) => { ); }; -const NumericalCol = ({ col }) => { +const NumericalCol = ({ col }: { col: { name: string } }) => { return } label={col.name} key={col.name} value={col.name} />; }; +interface ObservationControlsProps { + observations: Observation[], + selectedObservation?: string, + onObservationSelect: Function, + legendData?: ColourProps +} -export const ObsSelect = ({ adata, obsCol, onSelect, callback = () => { } }) => { - const { data, isLoading, serverError } = useAnndataObs(adata); - const colorData = useAnndataColors( - { - ...adata, - matrixProps: { - obs: { col: obsCol }, - }, - }, - { - enabled: !!obsCol, - }, - ); +export const ObsSelect = ({ observations, selectedObservation, onObservationSelect, legendData }: ObservationControlsProps) => { - useEffect(() => { - if (colorData?.serverError) { - callback(null); - return; - } - if (!colorData?.isLoading && colorData?.data) { - callback(colorData.data.colors); - } - }, [colorData, callback]); const legend = useMemo(() => { - if (colorData?.serverError || colorData?.isLoading || !colorData?.data) { - return null; + if (legendData) { + return ; + } else { + <> } - const { min, max, colorscale, categories } = colorData.data; - if (categories) { - return null; - } - return ; - }, [colorData.data, colorData?.isLoading, colorData?.serverError]); + }, [legendData]); + - if (isLoading) { - return <>; - } - if (serverError) { - return
Error loading obs
; - } return ( { } }) => Observations - onSelect(e.target.value)}> + onObservationSelect(e.target.value)}> Categorical - {data.filter((obs) => 'categories' in obs).map((col) => ( - + {observations && observations.filter((obs) => 'categories' in obs).map((col) => ( + ))} Numerical - {data.filter((obs) => !('categories' in obs)).map((col) => ( + {observations && observations.filter((obs) => !('categories' in obs)).map((col) => ( ))} - {!!obsCol && legend} + {!!selectedObservation && legend}
); diff --git a/anndata-zarr/src/hooks.ts b/anndata-zarr/src/hooks.ts index 6d026ba2..353fb795 100644 --- a/anndata-zarr/src/hooks.ts +++ b/anndata-zarr/src/hooks.ts @@ -1,12 +1,10 @@ import { useCallback } from "react"; - import { useQueries, useQuery, type UseQueryResult } from "@tanstack/react-query"; import _ from "lodash"; -import { z } from 'zod'; - import { COLORSCALES } from "./constants/colorscales"; -import { fetchDataFromZarr, getColors, getObs, getVarNames, getZarrPath } from "./utils"; +import { getColors } from "./utils"; +import { fetchDataFromZarr, getObservationNames, getFeatureNames, getFeatureDataPath, getObservationDataPath, type Observation } from "./anndata"; export interface Feature { index?: number, @@ -21,67 +19,96 @@ export interface MatrixProps { namesCol?: string }, obs?: { - col: number + col?: string } } +interface LabelColourMap { + labelValue: number, + rgba: number[] + value: string | number +} + +interface ColourData { + colors: LabelColourMap[], + min: number, + max: number +} + export interface ColourProps { min: number, max: number, colorscale: string[] } -interface AnndataQueryParams { - url: URL, - matrixProps?: MatrixProps, - colorProps?: ColourProps -} export interface AnndataURL { url: URL, - namesCol: string +} +export interface FeatureParams { + type: 'feature', + params: Feature +} +export interface ObservationParams { + type: 'observation', + params: Observation } +export const getAnndataColors = async (url: URL, params: FeatureParams | ObservationParams | undefined, colorProps?: ColourProps): Promise => { + + if (typeof params === 'undefined') { + return (Promise.reject(new Error('Invalid params'))) + } + let path; + + if (params.type === 'feature') { + path = await getFeatureDataPath(url, params.params.index) + } else if (params.type === 'observation') { + path = await getObservationDataPath(params.params.name) + } else { + throw new Error('Unknown anndata parameter type') + } + const data = await fetchDataFromZarr(url, path.path, path.slice); + let min, max, colorscale, categories; + if ('categories' in data && data.categories) { + const categories = data.categories + max = categories.length - 1 + min = 0 + colorscale = COLORSCALES.Accent + + } else { + max = colorProps?.max || _.max(data.data) || 0 + min = colorProps?.min || _.min(data.data) || 0 + colorscale = colorProps?.colorscale || COLORSCALES.Accent -export const getAnndataColors = async (url: URL, matrixProps: MatrixProps, colorProps?: ColourProps) => { - let zarrData; - try { - const zarrPath = await getZarrPath(url, matrixProps); - zarrData = await fetchDataFromZarr(zarrPath.url, zarrPath.path, zarrPath.s); - } catch (error) { - console.error(error); - return null; } - if (!zarrData) return null; - const { categories } = zarrData - const max = categories ? categories.length - 1 : colorProps?.max || _.max(zarrData.data); - const min = categories ? 0 : colorProps?.min || _.min(zarrData.data); - const colorscale = categories ? COLORSCALES.Accent : colorProps?.colorscale; - const colors = getColors({ - data: zarrData.data, + + const colours = getColors({ + data: data.data, max, min, - colorProps: { ...colorProps, colorscale }, - categories, + colorscale: colorscale, + categories }) - return { - colors: colors, + return ({ + colors: colours, max, - min, - ...(categories ? { categories } : {}), - colorscale, - }; + min + }) + }; -export const useAnndataColors = (anndataQueryParams: AnndataQueryParams, opts = {}) => { + + +export const useAnndataColors = (url: URL, param: FeatureParams | ObservationParams | undefined, opts = {}): UseQueryResult => { + const result = useQuery({ - queryKey: ["anndataColor", anndataQueryParams.url, anndataQueryParams.matrixProps, anndataQueryParams.colorProps], - queryFn: () => getAnndataColors(anndataQueryParams.url, anndataQueryParams.matrixProps, anndataQueryParams.colorProps), + queryKey: ["anndataColor", url, param], + queryFn: () => getAnndataColors(url, param), ...opts, }); - return result; }; @@ -110,19 +137,18 @@ export const useAnndatasColors = (adatas = [], opts = {}) => { return { data, isLoading, serverError }; }; -export const useAnndataFeatures = (adata: AnndataURL) => { +export const useAnndataFeatures = (adata: AnndataURL): UseQueryResult => { const result = useQuery({ - queryKey: ["anndataFeatures", adata.url, adata.namesCol], - queryFn: () => getVarNames(adata.url), + queryKey: ["anndataFeatures", adata.url], + queryFn: () => getFeatureNames(adata.url), }); - return result; }; export const useAnndataObs = (adata: AnndataURL) => { const result = useQuery({ queryKey: ["anndataObs", adata.url], - queryFn: () => getObs(adata.url), + queryFn: () => getObservationNames(adata.url), }); return result; }; diff --git a/anndata-zarr/src/index.ts b/anndata-zarr/src/index.ts index 3e49b763..16c0aa80 100644 --- a/anndata-zarr/src/index.ts +++ b/anndata-zarr/src/index.ts @@ -1,6 +1,6 @@ import "./index.css"; -export { useAnndataColors } from "./hooks"; +//export { useAnndataColors } from "./hooks"; export { AnndataProvider } from "./provider"; export { COLORSCALES } from "./constants/colorscales"; export { FeatureSelect } from "./components/FeatureSelect"; diff --git a/anndata-zarr/src/utils.ts b/anndata-zarr/src/utils.ts index 2632cd35..ef118cb2 100644 --- a/anndata-zarr/src/utils.ts +++ b/anndata-zarr/src/utils.ts @@ -1,203 +1,8 @@ import _ from "lodash"; -import { FetchStore, get, open, Group, type Readable, type DataType, Array as ZarrArray, type Float64 } from "zarrita"; import { COLORSCALES } from "./constants/colorscales"; -import type { ColourProps, MatrixProps } from "./hooks"; -import type { URL } from "url"; -import { z } from 'zod'; +import { type ColourProps } from "./hooks"; -const AnndataZarrBaseAttributesSchema = z.object({ - 'encoding-type': z.enum(["anndata", "dataframe", "array", "categorical", "string-array"]), - 'encoding-version': z.string() -}) - -const AnndataZarrObsAttributesSchema = AnndataZarrBaseAttributesSchema.extend({ - 'column-order': z.array(z.string()), - '_index': z.string().optional() -}) - -const AnndataCategoriesSchema = z.array(z.string()) - - - -function resolveAnndataZarrObsAttributes(attrs: unknown): z.infer { - return AnndataZarrObsAttributesSchema.parse(attrs) -} - -function resolveAnndataZarrBaseAttributes(attrs: unknown): z.infer { - return AnndataZarrBaseAttributesSchema.parse(attrs) -} - - -async function fetchZarrGroup(url: URL): Promise> { - const store = new FetchStore(url) - return await open(store, { kind: "group" }) -} - -async function fetchZarrArray(url: URL, path: string): Promise> { - const store = new FetchStore(url) - return await open(store, { kind: "array" }) -} - - -const RawColourData = z.object({ - data: z.any(), - shape: z.array(z.number()), - stride: z.array(z.number()) -}) - -const RawCategoricalColourData = z.object({ - data: z.array(z.number()), - categories: z.array(z.string()) -}) - -const parseRawColourData = function (data: unknown): z.infer { - return RawColourData.parse(data) -} - -const parseRawCategoricalColourData = function (data: unknown): z.infer { - return RawCategoricalColourData.parse(data) -} - -export const fetchDataFromZarr = async (url: URL, path: string, s: []): Promise<{ data: number[], categories?: string[] }> => { - try { - const node = await fetchZarrGroup(url) - const dataNode = await open(node.resolve(path)) - const attrs = resolveAnndataZarrBaseAttributes(dataNode.attrs) - - if (dataNode instanceof Group) { - if (attrs["encoding-type"] === "categorical") { - const categoriesArr = await open(dataNode.resolve("categories"), { - kind: "array", - }); - const codesArr = await open(dataNode.resolve("codes"), { kind: "array" }); - const categories = await get(categoriesArr); - const parsedCategories = parseRawColourData(categories) - const data = await get(codesArr, s); - const parsedData = parseRawColourData(data) - return { data: parsedData.data, categories: parsedCategories.data } - } - } else if (dataNode instanceof ZarrArray) { - if (attrs["encoding-type"] === "array" && dataNode.dtype === "bool") { - const boolData = await get(dataNode, s); - const parsedBoolData = parseRawColourData(boolData) - return { - data: Array.from(parsedBoolData.data), - categories: ["false", "true"], - }; - } else if (attrs["encoding-type"] === "array" || attrs["encoding-type"] === "string-array") { - return parseRawColourData(await get(dataNode, s)); - } - } - - return ({ data: [] }) - - } catch (error) { - // biome-ignore lint/complexity/noUselessCatch: @TODO: better error handling - throw error; - } -}; - -export const getVarNames = async (url: URL) => { - try { - const store = new FetchStore(url); - const node = await open(store, { kind: "group" }); - const varNode = await open(node.resolve('var')) - const parsedAttrs = AnndataZarrObsAttributesSchema.parse(varNode.attrs) - //To-do try default "_index" - const array = await open(node.resolve(`var/${parsedAttrs._index}`), { kind: "array" }); - const varNames = (await get(array)).data; - return varNames; - - } catch (error) { - console.error(error); - return []; - } -}; - -type Observation = { name: string, categories?: string[] } - -export const getObs = async (url: URL): Promise> => { - try { - const store = new FetchStore(url); - const node = await open(store, { kind: "group" }); - - const obsNode = (await open(node.resolve("obs"), { kind: "group" })) - const attrs = resolveAnndataZarrObsAttributes(obsNode.attrs) - const cols = attrs["column-order"] - - const obs = await Promise.all( - cols.map(async (col) => { - const dataNode = await open(node.resolve(`obs/${col}`)); - const encodingType = dataNode.attrs['encoding-type'] || {}; - - if (dataNode instanceof ZarrArray) { - if (dataNode.dtype === 'bool') { - return ({ name: col, categories: ["false", "true"] }) - } - if (encodingType == 'array' || encodingType === 'string-array') { - return { name: col }; - } - - } else if (dataNode instanceof Group) { - const categoriesArr = await open(dataNode.resolve("categories"), { - kind: "array", - }); - const categories = await get(categoriesArr); - const parsedCategories = AnndataCategoriesSchema.parse(categories.data) - return { name: col, categories: parsedCategories } - } - - }) - ) - - return obs.filter((observation) => observation != undefined) - - } catch (error) { - console.error(error); - return []; - } -}; - -export const getVarIndex = async (url: URL, varId: string, namesCol = "_index") => { - try { - const store = new FetchStore(url); - const node = await open(store, { kind: "group" }); - - const arr = await open(node.resolve(`var/${namesCol}`), { kind: "array" }); - const varNames = (await get(arr)).data; - const varIndex = varNames.findIndex((name) => name === varId); - return varIndex; - } catch (error) { - return -1; - } -}; - -export const getZarrPath = async (url: URL, matrixProps: MatrixProps) => { - const { feature, obs } = matrixProps; - if (feature) { - if (feature.index !== undefined && feature.index !== null) { - return { url, path: "X", s: [null, feature.index] }; - } - if (feature.name) { - return { - url, - path: "X", - s: [null, await getVarIndex(url, feature.name, feature.namesCol)], - }; - } - } - - if (obs) { - return { - url, - path: `obs/${obs.col}`, - s: null, - }; - } - - throw new Error("No feature or obs in matrixProps"); -}; const parseHexColor = (color: string) => { const r = Number.parseInt(color?.substring(1, 3), 16); @@ -238,10 +43,10 @@ export const getColor = ({ value, colorscale = COLORSCALES.Viridis }: { value: n return [...computeColor(colorscale, value), 255]; }; -export const getColors = ({ data, max, min, colorProps, categories }: { data: number[], max: number, min: number, colorProps: ColourProps, categories?: string[] }) => { +export const getColors = ({ data, max, min, colorscale, categories }: { data: number[], max: number, min: number, colorscale: string[], categories?: string[] }) => { return _.map(data, (v: number, i: number) => ({ labelValue: i + 1, - rgba: getColor({ value: (v - min) / (max - min), ...colorProps }), + rgba: getColor({ value: (v - min) / (max - min), colorscale }), value: categories ? (categories[v] ?? v) : v, })); }; diff --git a/anndata-zarr/src/zarr.ts b/anndata-zarr/src/zarr.ts new file mode 100644 index 00000000..4dc508f1 --- /dev/null +++ b/anndata-zarr/src/zarr.ts @@ -0,0 +1,24 @@ +import { FetchStore, Group, type Readable, open, get } from "zarrita" +import { z } from "zod" + +const ZarrDataSchema = z.object({ + data: z.any() +}) + + +export async function fetchZarrGroup(url: URL): Promise> { + const store = new FetchStore(url) + return await open(store, { kind: "group" }) +} + +export async function getData(root: Group, path: string, slice?: (number | null)[]): Promise<{ data: unknown[], dtype: string }> { + const dataNode = await open(root.resolve(path), { kind: 'array' }) + const data = await get(dataNode, slice) + const parsedData = ZarrDataSchema.parse(data) + try { + const arrayData = Array.from(parsedData.data) + return { data: arrayData, dtype: dataNode.dtype } + } catch (error) { + throw new Error(`Could not parse Zarr array data at ${path}. Error: ${error}`) + } +} diff --git a/anndata-zarr/types.ts b/anndata-zarr/types.ts index e0025c92..8b137891 100644 --- a/anndata-zarr/types.ts +++ b/anndata-zarr/types.ts @@ -1,8 +1 @@ - - -type LabelColourMap = { - labelId: number, - colour: [number, number, number, number] - value: number -} From 61e954db2818f433dd0a5626786076f493f51c41 Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Tue, 9 Jun 2026 15:42:37 +0100 Subject: [PATCH 16/26] Cleanup --- fixtures/anndata_table.yaml | 1 + pnpm-lock.yaml | 19 +++++++++++++++++++ sites/app/src/App.tsx | 6 +++--- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 fixtures/anndata_table.yaml diff --git a/fixtures/anndata_table.yaml b/fixtures/anndata_table.yaml new file mode 100644 index 00000000..141cd55c --- /dev/null +++ b/fixtures/anndata_table.yaml @@ -0,0 +1 @@ +source: https://storage.googleapis.com/haniffalab/test/zarr/6001240_labels-anndata.zarr diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 561869fd..33688f77 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -82,6 +82,9 @@ importers: '@tanstack/react-query': specifier: ^5.85.3 version: 5.101.0(react@18.3.1) + '@types/lodash': + specifier: ^4.17.24 + version: 4.17.24 hyparquet: specifier: ^1.25.6 version: 1.26.0 @@ -97,9 +100,15 @@ importers: react-window: specifier: ^2.0.2 version: 2.2.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + yaml: + specifier: ^2.8.2 + version: 2.9.0 zarrita: specifier: 0.5.0 version: 0.5.0 + zod: + specifier: ^4.4.3 + version: 4.4.3 devDependencies: '@vitejs/plugin-react': specifier: ^4.3.3 @@ -1621,6 +1630,9 @@ packages: '@types/hammerjs@2.0.46': resolution: {integrity: sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==} + '@types/lodash@4.17.24': + resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==} + '@types/node@24.12.4': resolution: {integrity: sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==} @@ -4368,6 +4380,9 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + zstd-codec@0.1.5: resolution: {integrity: sha512-v3fyjpK8S/dpY/X5WxqTK3IoCnp/ZOLxn144GZVlNUjtwAchzrVo03h+oMATFhCIiJ5KTr4V3vDQQYz4RU684g==} @@ -6023,6 +6038,8 @@ snapshots: '@types/hammerjs@2.0.46': {} + '@types/lodash@4.17.24': {} + '@types/node@24.12.4': dependencies: undici-types: 7.16.0 @@ -8767,6 +8784,8 @@ snapshots: zod@3.25.76: {} + zod@4.4.3: {} + zstd-codec@0.1.5: optional: true diff --git a/sites/app/src/App.tsx b/sites/app/src/App.tsx index e014ddf3..7d1acf42 100644 --- a/sites/app/src/App.tsx +++ b/sites/app/src/App.tsx @@ -54,7 +54,7 @@ export default function App() { sources: searchParams.getAll("source"), viewState: parseViewStateFromUrl(), enableRoi: searchParams.get("roi") === "1", - tableURLs: searchParams.getAll("anndata").map((v) => (v ? { url: v } : null)) + tableURLs: searchParams.getAll("anndata") }; }, [urlString]); @@ -87,10 +87,10 @@ export default function App() { const anndataControllers = React.useMemo(() => { return sources.map((_s, i) => { - if (!tableURLs?.[i]?.url) return null; + if (!tableURLs?.[i]) return null; return ( selectCallback(colorData, i)} /> From 7c66b16649cac7beb0233113b0e8ff8cc5f35293 Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Wed, 10 Jun 2026 08:13:41 +0100 Subject: [PATCH 17/26] Refactoring --- anndata-zarr/src/anndata.ts | 23 ------------------- .../src/components/AnndataController.tsx | 7 ++---- anndata-zarr/src/components/Legend.tsx | 2 +- anndata-zarr/src/components/ObsSelect.tsx | 3 ++- anndata-zarr/src/hooks.ts | 11 +++++---- anndata-zarr/tests/test.test.ts | 7 +----- 6 files changed, 12 insertions(+), 41 deletions(-) diff --git a/anndata-zarr/src/anndata.ts b/anndata-zarr/src/anndata.ts index 8f0c2b0e..cef5a83a 100644 --- a/anndata-zarr/src/anndata.ts +++ b/anndata-zarr/src/anndata.ts @@ -197,26 +197,3 @@ export async function getObservationDataPath(name: string): Promise<{ path: stri } } -//export const getZarrDataPath = async (url: URL, name: string, type: string) => { -// if (type === 'feature') { -// if (feature.index !== undefined && feature.index !== null) { -// return { url, path: "X", s: [null, feature.index] }; -// } -// if (feature.name) { -// return { -// url, -// path: "X", -// s: [null, await getVarIndex(url, feature.name)], -// }; -// } -// } -// if (obs) { -// return { -// url, -// path: `obs/${obs.col}`, -// s: null, -// }; -// } -// -// throw new Error("No feature or obs in matrixProps"); -//}; diff --git a/anndata-zarr/src/components/AnndataController.tsx b/anndata-zarr/src/components/AnndataController.tsx index 767df5e8..974fb82f 100644 --- a/anndata-zarr/src/components/AnndataController.tsx +++ b/anndata-zarr/src/components/AnndataController.tsx @@ -51,9 +51,6 @@ export const AnndataController = ({ adata, callback = () => { } }: { adata: stri const colorData = useAnndataColors(url.url, param, { enabled: !!param }) - - const legendData = colorData.data && 'colorscale' in colorData.data ? colorData.data : undefined - useEffect(() => { if (colorData?.isError) { callback(null); @@ -68,10 +65,10 @@ export const AnndataController = ({ adata, callback = () => { } }: { adata: stri return ( - {features.data && } + {features.data && } - {observations.data && } + {observations.data && } diff --git a/anndata-zarr/src/components/Legend.tsx b/anndata-zarr/src/components/Legend.tsx index 0320e54a..9f7c5c39 100644 --- a/anndata-zarr/src/components/Legend.tsx +++ b/anndata-zarr/src/components/Legend.tsx @@ -4,7 +4,7 @@ import _ from "lodash"; import { getColor } from "../utils"; -export const Legend = ({ min, max, colorscale }) => { +export const Legend = ({ min, max, colorscale }: { min: number, max: number, colorscale: string[] }) => { const spanList = useMemo(() => { return _.range(100).map((i) => { const color = getColor({ value: i / 100, colorscale }); diff --git a/anndata-zarr/src/components/ObsSelect.tsx b/anndata-zarr/src/components/ObsSelect.tsx index 630a09ca..675adbc8 100644 --- a/anndata-zarr/src/components/ObsSelect.tsx +++ b/anndata-zarr/src/components/ObsSelect.tsx @@ -18,7 +18,8 @@ import Stack from "@mui/material/Stack"; import { COLORSCALES } from "../constants/colorscales"; import { type ColourProps } from "../hooks"; -import { getColor, type CategoricalObservation, type Observation } from "../utils"; +import { type CategoricalObservation, type Observation } from "../anndata"; +import { getColor } from "../utils"; import { Legend } from "./Legend"; // @TODO: fix styling (width) diff --git a/anndata-zarr/src/hooks.ts b/anndata-zarr/src/hooks.ts index 353fb795..16221f38 100644 --- a/anndata-zarr/src/hooks.ts +++ b/anndata-zarr/src/hooks.ts @@ -32,7 +32,9 @@ interface LabelColourMap { interface ColourData { colors: LabelColourMap[], min: number, - max: number + max: number, + categories?: string[], + colorscale: string[] } export interface ColourProps { @@ -76,8 +78,6 @@ export const getAnndataColors = async (url: URL, params: FeatureParams | Observa max = categories.length - 1 min = 0 colorscale = COLORSCALES.Accent - - } else { max = colorProps?.max || _.max(data.data) || 0 min = colorProps?.min || _.min(data.data) || 0 @@ -95,13 +95,14 @@ export const getAnndataColors = async (url: URL, params: FeatureParams | Observa return ({ colors: colours, max, - min + min, + categories, + colorscale }) }; - export const useAnndataColors = (url: URL, param: FeatureParams | ObservationParams | undefined, opts = {}): UseQueryResult => { const result = useQuery({ diff --git a/anndata-zarr/tests/test.test.ts b/anndata-zarr/tests/test.test.ts index 70b6ee61..43d543a9 100644 --- a/anndata-zarr/tests/test.test.ts +++ b/anndata-zarr/tests/test.test.ts @@ -11,12 +11,7 @@ const fixtures_path = path.resolve(path.join(__dirname, "..", "..", "fixtures")) test("Can get anndata colours", async () => { const table = yaml.parse(fs.readFileSync(path.join(fixtures_path, "anndata_table.yaml"), 'utf-8')) - const matrixProps = { - feature: { - index: 3 - } - } - const colours = await getAnndataColors(table.source, matrixProps) + const colours = await getAnndataColors(table.source, { type: 'feature', params: { index: 3 } }) expect(colours).toEqual(expectedColours) }) From fdec9f32f49efb95c5743ed13b9c160908ec795e Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Wed, 10 Jun 2026 13:45:49 +0100 Subject: [PATCH 18/26] Resolved typescript errors --- anndata-zarr/src/anndata.ts | 51 ++-- .../src/components/AnndataController.tsx | 58 ++-- anndata-zarr/src/components/FeatureSelect.tsx | 37 +-- anndata-zarr/src/components/ObsSelect.tsx | 29 +- anndata-zarr/src/hooks.ts | 67 +++-- anndata-zarr/src/provider.tsx | 2 +- anndata-zarr/src/table-loader.ts | 261 ------------------ anndata-zarr/src/utils.ts | 4 +- anndata-zarr/tests/test.test.ts | 2 +- 9 files changed, 140 insertions(+), 371 deletions(-) delete mode 100644 anndata-zarr/src/table-loader.ts diff --git a/anndata-zarr/src/anndata.ts b/anndata-zarr/src/anndata.ts index cef5a83a..26acfaa2 100644 --- a/anndata-zarr/src/anndata.ts +++ b/anndata-zarr/src/anndata.ts @@ -2,6 +2,7 @@ import { z } from 'zod'; import type { URL } from "url"; import { FetchStore, open } from "zarrita"; import { fetchZarrGroup, getData } from './zarr'; +import type { FeatureMetadata, ObservationMetadata, ObservationParams } from './hooks'; const OBSERVATION_NAMES_PATH = 'obs' const FEATURE_NAMES_PATH = 'var' @@ -94,17 +95,18 @@ export const fetchDataFromZarr = async (url: URL, path: string, slice: (number | return ({ data: parsedData }) - } else if (attrs['encoding-type'] === 'string-array') { - const parsedData = parseStringArray(data) - return ({ - data: parsedData - }) } return ({ data: [] }) }; -export const getFeatureNames = async (url: URL): Promise => { +export async function getLabels(url: URL): Promise<(FeatureMetadata | ObservationMetadata)[]> { + const featureNames = await getFeatureNames(url) + const observationNames = await getObservationNames(url) + return [...featureNames, ...observationNames] +} + +export const getFeatureNames = async (url: URL): Promise => { try { const root = await fetchZarrGroup(url); @@ -112,7 +114,16 @@ export const getFeatureNames = async (url: URL): Promise => { const parsedAttrs = ZarrObservationAttrsSchema.parse(node.attrs) const path = `${FEATURE_NAMES_PATH}/${parsedAttrs._index}` const { data, dtype } = await getData(root, path) - return parseStringArray(data); + + const parsedData = parseStringArray(data) + + return parsedData.map((name) => { + return { + type: 'feature', + labelIndex: name + } + }) + } catch (error) { console.error(error); return []; @@ -126,7 +137,7 @@ function getObservationNamesPath(encodingType: string): string { return '' } -export const getObservationNames = async (url: URL): Promise> => { +export const getObservationNames = async (url: URL): Promise> => { try { const root = await fetchZarrGroup(url) @@ -140,16 +151,24 @@ export const getObservationNames = async (url: URL): Promise> const parsedAttrs = ZarrAttrsSchema.parse(dataNodeOrGroup.attrs) const dataPath = `${OBSERVATION_NAMES_PATH}/${col}/${getObservationNamesPath(parsedAttrs['encoding-type'])}` const dataNode = await open(root.resolve(dataPath), { kind: 'array' }) + + const metadata: ObservationMetadata = { type: 'observation', labelIndex: col } if (dataNode.dtype === 'bool') { - return ({ name: col, categories: ["false", "true"] }) + metadata['categories'] = ['false', 'true'] + return metadata } - if (parsedAttrs['encoding-type'] == 'array' || parsedAttrs['encoding-type'] === 'string-array') { - return { name: col }; + + if (parsedAttrs['encoding-type'] == 'array') { + return metadata } - const { data, dtype } = await getData(root, dataPath) - const parsedCategories = AnndataCategoriesSchema.parse(data) - return { name: col, categories: parsedCategories } + if (parsedAttrs['encoding-type'] == 'categorical') { + const { data, dtype } = await getData(root, dataPath) + const parsedCategories = AnndataCategoriesSchema.parse(data) + metadata['categories'] = parsedCategories + return metadata + } + return undefined }) ) return obs.filter((observation) => observation != undefined) @@ -174,11 +193,11 @@ export const getVarIndex = async (url: URL, varId: string, namesCol = VAR_NAMES_ return varIndex; }; -export async function getFeatureDataPath(url: URL, index?: number, name?: string): Promise<{ path: string, slice: (number | null)[] }> { +export async function getFeatureDataPath(url: URL, index: string, name?: string): Promise<{ path: string, slice: (number | null)[] }> { if (index) { return ({ path: ARRAY_PATH, - slice: [null, index] + slice: [null, Number(index)] }) } else if (name) { return { diff --git a/anndata-zarr/src/components/AnndataController.tsx b/anndata-zarr/src/components/AnndataController.tsx index 974fb82f..8e66aff7 100644 --- a/anndata-zarr/src/components/AnndataController.tsx +++ b/anndata-zarr/src/components/AnndataController.tsx @@ -7,49 +7,31 @@ import { FeatureSelect } from "./FeatureSelect"; import { ObsSelect } from "./ObsSelect"; -import { useAnndataColors, useAnndataFeatures, useAnndataObs, type Feature, type FeatureParams, type ObservationParams } from "../hooks"; -import type { Observation } from "../anndata"; - -interface ColourQueryParams { - name: string, - type: 'observation' | 'feature' -} - -function getFeatureParams(feature: Feature): FeatureParams { - return ( - { type: 'feature', params: feature } - ) -} - -function getObservationParams(observation: string): ObservationParams { - return ( - { type: 'observation', params: { name: observation } } - ) -} +import { useAnndataColors, useTableLabels } from "../hooks"; +export type LabelType = 'observation' | 'feature' export const AnndataController = ({ adata, callback = () => { } }: { adata: string, callback: Function }) => { - const [feature, setFeature] = useState(undefined); - const [observation, setObservation] = useState(undefined) - const url = { url: new URL(adata) } + const [selectedLabel, setSelectedLabel] = useState<{ labelIndex: string, type: LabelType } | undefined>(undefined) - const handleFeatureSelect = (f: Feature) => { - setFeature(f); - setObservation(undefined) - }; - - const handleObservationSelect = (o: string) => { - setObservation(o); - console.log('Setting observation to', o) - setFeature(undefined) - }; + const url = { url: new URL(adata) } + function handleLabelSelect(labelIndex: string, labelType: 'feature' | 'observation') { + setSelectedLabel( + { + labelIndex: labelIndex, + type: labelType + } + ) + } - const features = useAnndataFeatures(url); - const observations = useAnndataObs(url); + const labels = useTableLabels(url.url) - const param = feature ? getFeatureParams(feature) : (observation ? getObservationParams(observation) : undefined) + //A necessary evil for now, I think in principle the UI should be more or less agnostic of whether it is an observation or a feature. + const selectedLabelDisplayData = labels.data && selectedLabel ? labels.data.filter((label) => label.labelIndex === selectedLabel.labelIndex)[0] : undefined + const selectedFeature = selectedLabelDisplayData?.type === 'feature' ? selectedLabelDisplayData.labelIndex : undefined + const selectedObservation = selectedLabelDisplayData?.type === 'observation' ? selectedLabelDisplayData.labelIndex : undefined - const colorData = useAnndataColors(url.url, param, { enabled: !!param }) + const colorData = useAnndataColors(url.url, selectedLabel, { enabled: !!selectedLabel }) useEffect(() => { if (colorData?.isError) { @@ -65,10 +47,10 @@ export const AnndataController = ({ adata, callback = () => { } }: { adata: stri return ( - {features.data && } + {labels.data && label.type === 'feature').map((metadata) => metadata.labelIndex)} selectedFeatureIndex={selectedFeature} onFeatureSelect={handleLabelSelect} legendData={selectedFeature ? colorData.data : undefined} />} - {observations.data && } + {labels.data && label.type === 'observation')} selectedObservation={selectedObservation} onObservationSelect={handleLabelSelect} legendData={selectedObservation ? colorData.data : undefined} />} diff --git a/anndata-zarr/src/components/FeatureSelect.tsx b/anndata-zarr/src/components/FeatureSelect.tsx index d4710924..4721dd88 100644 --- a/anndata-zarr/src/components/FeatureSelect.tsx +++ b/anndata-zarr/src/components/FeatureSelect.tsx @@ -16,7 +16,7 @@ const RowComponent = ({ index, items, style, onSelect, selectedIndex }: { index: onSelect({ index: items[index].matrixIndex })} + onClick={() => onSelect(items[index].name, 'feature')} selected={items[index].matrixIndex === selectedIndex} > @@ -24,32 +24,32 @@ const RowComponent = ({ index, items, style, onSelect, selectedIndex }: { index: ); }; - -// List of features -// Currently selected feature to display -// onSelect to set feature - -export const FeatureSelect = ({ featureNames, selectedFeature, onFeatureSelect, legendData }: { featureNames: string[], selectedFeature?: Feature, onFeatureSelect: Function, legendData?: ColourProps }) => { +export const FeatureSelect = ({ featureNames, selectedFeatureIndex, onFeatureSelect, legendData }: { featureNames: string[], selectedFeatureIndex?: string, onFeatureSelect: Function, legendData?: ColourProps }) => { const [searchTerm, setSearchTerm] = useState(""); - const allItems = featureNames.map((name: string, index: number) => { - return { - name: name, - matrixIndex: index + const items = useMemo(() => { + const allItems = featureNames.map((name: string, index: number) => { + return { + name: name, + matrixIndex: index + } + }) + if (!searchTerm) { + return allItems } - }) + return allItems.filter((item) => item.name.toLowerCase().includes(searchTerm.toLowerCase())); + + }, [featureNames, searchTerm]) const legend = useMemo(() => { - if (legendData) { + if (legendData && legendData.colorscale) { return ; } else { return <> } }, [legendData]); - - return ( {legend} diff --git a/anndata-zarr/src/components/ObsSelect.tsx b/anndata-zarr/src/components/ObsSelect.tsx index 675adbc8..9635dbcd 100644 --- a/anndata-zarr/src/components/ObsSelect.tsx +++ b/anndata-zarr/src/components/ObsSelect.tsx @@ -17,24 +17,23 @@ import RadioGroup from "@mui/material/RadioGroup"; import Stack from "@mui/material/Stack"; import { COLORSCALES } from "../constants/colorscales"; -import { type ColourProps } from "../hooks"; +import { type ColourProps, type ObservationMetadata } from "../hooks"; import { type CategoricalObservation, type Observation } from "../anndata"; import { getColor } from "../utils"; import { Legend } from "./Legend"; // @TODO: fix styling (width) -const CategoricalCol = ({ col, showColor = false }: { col: CategoricalObservation, showColor: boolean }) => { +const CategoricalCol = ({ name, categories, showColor = false }: { name: string, categories: string[], showColor: boolean }) => { const [open, setOpen] = useState(false); - const { categories } = col; return ( setOpen(!open)} sx={{ display: "flex", alignItems: "center", cursor: "pointer" }}> e.stopPropagation()} />} - label={col.name} - key={col.name} - value={col.name} + label={name} + key={name} + value={name} /> {open ? : } @@ -67,11 +66,11 @@ const CategoricalCol = ({ col, showColor = false }: { col: CategoricalObservatio ); }; -const NumericalCol = ({ col }: { col: { name: string } }) => { - return } label={col.name} key={col.name} value={col.name} />; +const NumericalCol = ({ name }: { name: string }) => { + return } label={name} key={name} value={name} />; }; interface ObservationControlsProps { - observations: Observation[], + observations: ObservationMetadata[], selectedObservation?: string, onObservationSelect: Function, legendData?: ColourProps @@ -81,7 +80,7 @@ export const ObsSelect = ({ observations, selectedObservation, onObservationSele const legend = useMemo(() => { - if (legendData) { + if (legendData && legendData.colorscale) { return ; } else { <> @@ -102,14 +101,14 @@ export const ObsSelect = ({ observations, selectedObservation, onObservationSele Observations - onObservationSelect(e.target.value)}> + onObservationSelect(e.target.value, 'observation')}> Categorical - {observations && observations.filter((obs) => 'categories' in obs).map((col) => ( - + {observations && observations.filter((obs) => 'categories' in obs).map((observation) => ( + ))} Numerical - {observations && observations.filter((obs) => !('categories' in obs)).map((col) => ( - + {observations && observations.filter((obs) => !('categories' in obs)).map((observation) => ( + ))} diff --git a/anndata-zarr/src/hooks.ts b/anndata-zarr/src/hooks.ts index 16221f38..06d2a096 100644 --- a/anndata-zarr/src/hooks.ts +++ b/anndata-zarr/src/hooks.ts @@ -4,10 +4,11 @@ import _ from "lodash"; import { COLORSCALES } from "./constants/colorscales"; import { getColors } from "./utils"; -import { fetchDataFromZarr, getObservationNames, getFeatureNames, getFeatureDataPath, getObservationDataPath, type Observation } from "./anndata"; +import { fetchDataFromZarr, getObservationNames, getFeatureNames, getFeatureDataPath, getObservationDataPath, getLabels } from "./anndata"; +import type { LabelType } from "./components/AnndataController"; export interface Feature { - index?: number, + index: string, name?: string, namesCol?: string } @@ -34,13 +35,13 @@ interface ColourData { min: number, max: number, categories?: string[], - colorscale: string[] + colorscale?: string[] } export interface ColourProps { min: number, max: number, - colorscale: string[] + colorscale?: string[] } @@ -50,24 +51,24 @@ export interface AnndataURL { export interface FeatureParams { type: 'feature', - params: Feature + index: number } export interface ObservationParams { type: 'observation', - params: Observation + index: string } -export const getAnndataColors = async (url: URL, params: FeatureParams | ObservationParams | undefined, colorProps?: ColourProps): Promise => { +export const getAnndataColors = async (url: URL, labelQueryParameters: LabelQueryParameters | undefined, colorProps?: ColourProps): Promise => { - if (typeof params === 'undefined') { + if (typeof labelQueryParameters === 'undefined') { return (Promise.reject(new Error('Invalid params'))) } let path; - if (params.type === 'feature') { - path = await getFeatureDataPath(url, params.params.index) - } else if (params.type === 'observation') { - path = await getObservationDataPath(params.params.name) + if (labelQueryParameters.type === 'feature') { + path = await getFeatureDataPath(url, labelQueryParameters.labelIndex) + } else if (labelQueryParameters.type === 'observation') { + path = await getObservationDataPath(labelQueryParameters.labelIndex) } else { throw new Error('Unknown anndata parameter type') } @@ -81,10 +82,9 @@ export const getAnndataColors = async (url: URL, params: FeatureParams | Observa } else { max = colorProps?.max || _.max(data.data) || 0 min = colorProps?.min || _.min(data.data) || 0 - colorscale = colorProps?.colorscale || COLORSCALES.Accent + colorscale = colorProps?.colorscale } - const colours = getColors({ data: data.data, max, @@ -102,12 +102,41 @@ export const getAnndataColors = async (url: URL, params: FeatureParams | Observa }; +type LabelQueryParameters = { + type: LabelType, + labelIndex: string +} + + + +export type FeatureMetadata = { + type: 'feature', + labelIndex: string, + categories?: string[] +} + +export type ObservationMetadata = { + type: 'observation', + labelIndex: string, + categories?: string[] +} + + +export function useTableLabels(url: URL): UseQueryResult<(FeatureMetadata | ObservationMetadata)[]> { + const labels = useQuery({ + queryKey: ["labels", url], + queryFn: () => getLabels(url), + }); + + return labels + +} -export const useAnndataColors = (url: URL, param: FeatureParams | ObservationParams | undefined, opts = {}): UseQueryResult => { +export const useAnndataColors = (url: URL, labelQueryParameters: LabelQueryParameters | undefined, opts = {}): UseQueryResult => { const result = useQuery({ - queryKey: ["anndataColor", url, param], - queryFn: () => getAnndataColors(url, param), + queryKey: ["anndataColor", url, labelQueryParameters], + queryFn: () => getAnndataColors(url, labelQueryParameters), ...opts, }); return result; @@ -138,7 +167,7 @@ export const useAnndatasColors = (adatas = [], opts = {}) => { return { data, isLoading, serverError }; }; -export const useAnndataFeatures = (adata: AnndataURL): UseQueryResult => { +export const useAnndataFeatures = (adata: AnndataURL): UseQueryResult => { const result = useQuery({ queryKey: ["anndataFeatures", adata.url], queryFn: () => getFeatureNames(adata.url), @@ -146,7 +175,7 @@ export const useAnndataFeatures = (adata: AnndataURL): UseQueryResult return result; }; -export const useAnndataObs = (adata: AnndataURL) => { +export const useAnndataObs = (adata: AnndataURL): UseQueryResult => { const result = useQuery({ queryKey: ["anndataObs", adata.url], queryFn: () => getObservationNames(adata.url), diff --git a/anndata-zarr/src/provider.tsx b/anndata-zarr/src/provider.tsx index c250d401..e4d3fb3a 100644 --- a/anndata-zarr/src/provider.tsx +++ b/anndata-zarr/src/provider.tsx @@ -4,6 +4,6 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; const queryClient = new QueryClient(); -export function AnndataProvider({ children }) { +export function AnndataProvider({ children }: { children: React.JSX.Element[] }) { return {children}; } diff --git a/anndata-zarr/src/table-loader.ts b/anndata-zarr/src/table-loader.ts deleted file mode 100644 index bd28c02c..00000000 --- a/anndata-zarr/src/table-loader.ts +++ /dev/null @@ -1,261 +0,0 @@ -/** - * Table loader for non-anndata backends (CSV, JSON, Parquet). - * Detects backend type from .zattrs and normalizes data into - * a column-oriented format compatible with the anndata-zarr hooks. - */ - -// Promise-based caches to deduplicate concurrent requests -const _metaPromises = new Map(); -const _tablePromises = new Map(); - -/** - * Detect table backend and metadata from .zattrs. - * Result is cached per URL. - */ -export function getTableMeta(url) { - if (!_metaPromises.has(url)) { - _metaPromises.set(url, _fetchTableMeta(url)); - } - return _metaPromises.get(url); -} - -async function _fetchTableMeta(url) { - const res = await fetch(`${url}/.zattrs`); - if (!res.ok) throw new Error(`Failed to load table metadata from ${url}`); - const attrs = await res.json(); - const backend = attrs.backend || (attrs["encoding-type"] === "anndata" ? "anndata" : "unknown"); - if (backend === "unknown") { - console.warn(`[anndata-zarr] Unrecognized table backend at ${url}. Expected one of: anndata, csv, json, parquet.`); - } else { - console.log(`[anndata-zarr] Detected table backend: ${backend} (${url})`); - } - return { - backend, - indexKey: attrs.index_key || attrs.instance_key || null, - categoricalColumns: attrs.categorical_columns || [], - measurementColumns: attrs.measurement_columns || [], - metadataColumns: attrs.metadata_columns || [], - }; -} - -/** - * Load and cache table metadata + data. - * For anndata backend, returns { meta, data: null }. - * For flat backends, returns { meta, data: { col: values[] } }. - */ -export function getTableData(url) { - if (!_tablePromises.has(url)) { - _tablePromises.set(url, _fetchTableData(url)); - } - return _tablePromises.get(url); -} - -async function _fetchTableData(url) { - let meta; - try { - meta = await getTableMeta(url); - } catch (error) { - console.error(`[anndata-zarr] Failed to load table metadata from ${url}:`, error); - throw error; - } - if (meta.backend === "anndata") { - return { meta, data: null }; - } - try { - const data = await _loadFlatTable(url, meta.backend); - return { meta, data }; - } catch (error) { - console.error(`[anndata-zarr] Failed to load ${meta.backend} table from ${url}:`, error); - throw error; - } -} - -// --------------------------------------------------------------------------- -// CSV parser -// --------------------------------------------------------------------------- - -function _parseCsvLine(line) { - const values = []; - let current = ""; - let inQuotes = false; - - for (let i = 0; i < line.length; i++) { - const char = line[i]; - if (inQuotes) { - if (char === '"') { - if (i + 1 < line.length && line[i + 1] === '"') { - current += '"'; - i++; - } else { - inQuotes = false; - } - } else { - current += char; - } - } else if (char === '"') { - inQuotes = true; - } else if (char === ",") { - values.push(current); - current = ""; - } else { - current += char; - } - } - values.push(current); - return values; -} - -function _parseCsv(text) { - const lines = text.trim().split("\n"); - if (lines.length === 0) return {}; - - const headers = _parseCsvLine(lines[0]); - const columns = {}; - for (const h of headers) columns[h] = []; - - for (let i = 1; i < lines.length; i++) { - if (!lines[i].trim()) continue; - const values = _parseCsvLine(lines[i]); - for (let j = 0; j < headers.length; j++) { - columns[headers[j]].push(values[j]); - } - } - - // Auto-detect and convert numeric columns - for (const key of Object.keys(columns)) { - const col = columns[key]; - if (col.length > 0 && col.every((v) => v !== "" && !Number.isNaN(Number(v)))) { - columns[key] = col.map(Number); - } - } - - return columns; -} - -// --------------------------------------------------------------------------- -// Backend-specific loaders -// --------------------------------------------------------------------------- - -async function _loadFlatTable(url, backend) { - switch (backend) { - case "csv": { - const res = await fetch(`${url}/table.csv`); - if (!res.ok) throw new Error(`Failed to load CSV from ${url}/table.csv`); - return _parseCsv(await res.text()); - } - case "json": { - const res = await fetch(`${url}/table/.zattrs`); - if (!res.ok) throw new Error(`Failed to load JSON from ${url}/table/.zattrs`); - return await res.json(); - } - case "parquet": { - const { parquetMetadata, parquetRead } = await import("hyparquet"); - const res = await fetch(`${url}/table.parquet`); - if (!res.ok) throw new Error(`Failed to load parquet from ${url}/table.parquet`); - const buffer = await res.arrayBuffer(); - - const metadata = parquetMetadata(buffer); - const columnNames = metadata.schema.slice(1).map((s) => s.name); - const columns = {}; - for (const name of columnNames) columns[name] = []; - - await parquetRead({ - file: buffer, - metadata, - onComplete: (rows) => { - for (const row of rows) { - for (let i = 0; i < columnNames.length; i++) { - columns[columnNames[i]].push(row[i]); - } - } - }, - }); - - return columns; - } - default: - console.error(`[anndata-zarr] Unsupported table backend: "${backend}". Supported: csv, json, parquet.`); - throw new Error(`Unsupported table backend: ${backend}`); - } -} - -// --------------------------------------------------------------------------- -// Data extraction from flat (column-oriented) tables -// --------------------------------------------------------------------------- - -/** - * Get feature (numeric column) names from flat table data. - * Uses measurement_columns from metadata if available, otherwise infers - * from column data types. - */ -export function getFeatureNamesFromTable(tableData, indexKey, meta = {}) { - if (meta.measurementColumns?.length > 0) { - return meta.measurementColumns.filter((key) => key in tableData); - } - return Object.keys(tableData).filter((key) => { - if (key === indexKey) return false; - const col = tableData[key]; - return col.length > 0 && (typeof col[0] === "number" || typeof col[0] === "bigint"); - }); -} - -/** - * Get observation metadata columns from flat table data. - * Returns { categorical: [{name, categories}], numerical: [] } matching - * the shape returned by getObs() for anndata. - */ -export function getObsFromTable(tableData, indexKey, meta = {}) { - const featureNames = new Set(getFeatureNamesFromTable(tableData, indexKey, meta)); - const obs = { categorical: [], numerical: [] }; - for (const [key, values] of Object.entries(tableData)) { - if (key === indexKey) continue; - if (featureNames.has(key)) continue; - const isCategorical = - meta.categoricalColumns?.length > 0 - ? meta.categoricalColumns.includes(key) - : values.length > 0 && typeof values[0] === "string"; - if (isCategorical) { - const categories = [...new Set(values)].map(String); - obs.categorical.push({ name: key, categories }); - } else if (values.length > 0 && (typeof values[0] === "number" || typeof values[0] === "bigint")) { - obs.numerical.push({ name: key }); - } - } - return obs; -} - -/** - * Get a single column's data, applying categorical encoding for string columns. - * Returns { data: number[] } or { data: number[], categories: string[] }. - */ -export function getColumnDataFromTable(tableData, colName) { - const values = tableData[colName]; - if (!values) throw new Error(`Column "${colName}" not found in table`); - - if (values.length > 0 && typeof values[0] === "string") { - const categories = [...new Set(values)]; - const categoryMap = new Map(categories.map((c, i) => [c, i])); - return { data: values.map((v) => categoryMap.get(v)), categories }; - } - // Convert BigInt values (e.g. from parquet int64) to Number - if (values.length > 0 && typeof values[0] === "bigint") { - return { data: values.map(Number) }; - } - return { data: values }; -} - -/** - * Get feature data by matrix index from a flat table. - */ -export function getFeatureDataFromTable(tableData, featureIndex, indexKey, meta = {}) { - const featureNames = getFeatureNamesFromTable(tableData, indexKey, meta); - if (featureIndex < 0 || featureIndex >= featureNames.length) { - throw new Error(`Feature index ${featureIndex} out of range (0-${featureNames.length - 1})`); - } - const values = tableData[featureNames[featureIndex]]; - // Convert BigInt values (e.g. from parquet int64) to Number - if (values.length > 0 && typeof values[0] === "bigint") { - return { data: values.map(Number) }; - } - return { data: values }; -} diff --git a/anndata-zarr/src/utils.ts b/anndata-zarr/src/utils.ts index ef118cb2..886b2239 100644 --- a/anndata-zarr/src/utils.ts +++ b/anndata-zarr/src/utils.ts @@ -39,11 +39,11 @@ const computeColor = (colormap: string[], value: number) => { return interpolateColor(colormap[index1], colormap[index2], factor); }; -export const getColor = ({ value, colorscale = COLORSCALES.Viridis }: { value: number, colorscale: string[] }) => { +export const getColor = ({ value, colorscale = COLORSCALES.Viridis }: { value: number, colorscale?: string[] }) => { return [...computeColor(colorscale, value), 255]; }; -export const getColors = ({ data, max, min, colorscale, categories }: { data: number[], max: number, min: number, colorscale: string[], categories?: string[] }) => { +export const getColors = ({ data, max, min, colorscale, categories }: { data: number[], max: number, min: number, colorscale?: string[], categories?: string[] }) => { return _.map(data, (v: number, i: number) => ({ labelValue: i + 1, rgba: getColor({ value: (v - min) / (max - min), colorscale }), diff --git a/anndata-zarr/tests/test.test.ts b/anndata-zarr/tests/test.test.ts index 43d543a9..8b0b8b00 100644 --- a/anndata-zarr/tests/test.test.ts +++ b/anndata-zarr/tests/test.test.ts @@ -11,7 +11,7 @@ const fixtures_path = path.resolve(path.join(__dirname, "..", "..", "fixtures")) test("Can get anndata colours", async () => { const table = yaml.parse(fs.readFileSync(path.join(fixtures_path, "anndata_table.yaml"), 'utf-8')) - const colours = await getAnndataColors(table.source, { type: 'feature', params: { index: 3 } }) + const colours = await getAnndataColors(table.source, { type: 'feature', labelIndex: '3' }) expect(colours).toEqual(expectedColours) }) From b404424b19a87a52411ea6d4caef4f625882ade5 Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Tue, 16 Jun 2026 08:05:28 +0100 Subject: [PATCH 19/26] Linting --- anndata-zarr/src/anndata.ts | 243 +++++++++--------- .../src/components/AnndataController.tsx | 67 +++-- anndata-zarr/src/components/FeatureSelect.tsx | 49 ++-- anndata-zarr/src/components/Legend.tsx | 2 +- anndata-zarr/src/components/ObsSelect.tsx | 63 +++-- anndata-zarr/src/hooks.ts | 161 ++++++------ anndata-zarr/src/provider.tsx | 2 +- anndata-zarr/src/utils.ts | 24 +- anndata-zarr/src/zarr.ts | 31 ++- anndata-zarr/tests/expected_colours.json | 68 ++++- anndata-zarr/tests/test.test.ts | 20 +- anndata-zarr/tsconfig.json | 4 +- anndata-zarr/types.ts | 1 - anndata-zarr/vite.config.js | 2 +- sites/app/src/App.tsx | 11 +- sites/app/vite.config.js | 10 +- viewer/src/components/VizarrViewer.tsx | 9 +- 17 files changed, 456 insertions(+), 311 deletions(-) diff --git a/anndata-zarr/src/anndata.ts b/anndata-zarr/src/anndata.ts index 26acfaa2..ab600d31 100644 --- a/anndata-zarr/src/anndata.ts +++ b/anndata-zarr/src/anndata.ts @@ -1,129 +1,131 @@ -import { z } from 'zod'; -import type { URL } from "url"; +import type { URL } from "node:url"; import { FetchStore, open } from "zarrita"; -import { fetchZarrGroup, getData } from './zarr'; -import type { FeatureMetadata, ObservationMetadata, ObservationParams } from './hooks'; - -const OBSERVATION_NAMES_PATH = 'obs' -const FEATURE_NAMES_PATH = 'var' -const CATEGORY_NAMES_PATH = 'categories' -const CATEGORY_DATA_PATH = 'codes' -const VAR_NAMES_PATH = "_index" - -export interface Observation { name: string } +import { z } from "zod"; +import type { FeatureMetadata, ObservationMetadata, ObservationParams } from "./hooks"; +import { fetchZarrGroup, getData } from "./zarr"; + +const OBSERVATION_NAMES_PATH = "obs"; +const FEATURE_NAMES_PATH = "var"; +const CATEGORY_NAMES_PATH = "categories"; +const CATEGORY_DATA_PATH = "codes"; +const VAR_NAMES_PATH = "_index"; + +export interface Observation { + name: string; +} export interface CategoricalObservation extends Observation { - categories: string[] + categories: string[]; } const ZarrAttrsSchema = z.object({ - 'encoding-type': z.enum(["anndata", "dataframe", "array", "categorical", "string-array"]), - 'encoding-version': z.string() -}) + "encoding-type": z.enum(["anndata", "dataframe", "array", "categorical", "string-array"]), + "encoding-version": z.string(), +}); const ZarrObservationAttrsSchema = ZarrAttrsSchema.extend({ - 'column-order': z.array(z.string()), - '_index': z.string().optional() -}) + "column-order": z.array(z.string()), + _index: z.string().optional(), +}); -const AnndataCategoriesSchema = z.array(z.string()) +const AnndataCategoriesSchema = z.array(z.string()); function parseZarrObservationAttrs(attrs: unknown): z.infer { - return ZarrObservationAttrsSchema.parse(attrs) + return ZarrObservationAttrsSchema.parse(attrs); } function parseZarrAttrs(attrs: unknown): z.infer { - return ZarrAttrsSchema.parse(attrs) + return ZarrAttrsSchema.parse(attrs); } -const IntegerArraySchema = z.array(z.number().int().or(z.nan())) +const IntegerArraySchema = z.array(z.number().int().or(z.nan())); -const FloatArraySchema = z.array(z.number().or(z.nan())) +const FloatArraySchema = z.array(z.number().or(z.nan())); -const StringArraySchema = z.array(z.string()) +const StringArraySchema = z.array(z.string()); -const BooleanArraySchema = z.array(z.boolean()) +const BooleanArraySchema = z.array(z.boolean()); - -const parseIntegerArray = function (data: unknown): z.infer { - return IntegerArraySchema.parse(data) -} +const parseIntegerArray = (data: unknown): z.infer => IntegerArraySchema.parse(data); function parseFloatArray(data: unknown[]): z.infer { - return FloatArraySchema.parse(data) + return FloatArraySchema.parse(data); } function parseStringArray(data: unknown[]): z.infer { - return StringArraySchema.parse(data) + return StringArraySchema.parse(data); } function parseBooleanArray(data: unknown[]): number[] { - const parsedData = BooleanArraySchema.parse(data) - return parsedData.map((value: boolean) => Number(value)) + const parsedData = BooleanArraySchema.parse(data); + return parsedData.map((value: boolean) => Number(value)); } -const getDataPath = function (encodingType: string): string | undefined { - if (encodingType === 'categorical') { - return CATEGORY_DATA_PATH +const getDataPath = (encodingType: string): string | undefined => { + if (encodingType === "categorical") { + return CATEGORY_DATA_PATH; } - return '' -} -export const fetchDataFromZarr = async (url: URL, path: string, slice: (number | null)[] | undefined): Promise<{ data: number[], categories?: string[] }> => { - const root = await fetchZarrGroup(url) - const dataNodeOrGroup = await open(root.resolve(path)) - const attrs = parseZarrAttrs(dataNodeOrGroup.attrs) - const dataPath = `${path}/${getDataPath(attrs['encoding-type'])}` - const { data, dtype } = await getData(root, dataPath, slice) - if (dtype === 'bool') { - const parsedData = parseBooleanArray(data) + return ""; +}; +export const fetchDataFromZarr = async ( + url: URL, + path: string, + slice: (number | null)[] | undefined, +): Promise<{ data: number[]; categories?: string[] }> => { + const root = await fetchZarrGroup(url); + const dataNodeOrGroup = await open(root.resolve(path)); + const attrs = parseZarrAttrs(dataNodeOrGroup.attrs); + const dataPath = `${path}/${getDataPath(attrs["encoding-type"])}`; + const { data, dtype } = await getData(root, dataPath, slice); + if (dtype === "bool") { + const parsedData = parseBooleanArray(data); return { data: parsedData, - categories: ['false', 'true'] - } + categories: ["false", "true"], + }; } - if (attrs['encoding-type'] === 'categorical') { - const parsedData = parseIntegerArray(data) - const categoryNamesPath = `${path}/${CATEGORY_NAMES_PATH}` - const categories = await getData(root, categoryNamesPath) - const categoryNames = parseStringArray(categories.data) + if (attrs["encoding-type"] === "categorical") { + const parsedData = parseIntegerArray(data); + const categoryNamesPath = `${path}/${CATEGORY_NAMES_PATH}`; + const categories = await getData(root, categoryNamesPath); + const categoryNames = parseStringArray(categories.data); return { data: parsedData, - categories: categoryNames - } - } else if (attrs['encoding-type'] === 'array') { - const parsedData = parseFloatArray(data) - return ({ - data: parsedData - }) + categories: categoryNames, + }; } - return ({ data: [] }) - + if (attrs["encoding-type"] === "array") { + const parsedData = parseFloatArray(data); + return { + data: parsedData, + }; + } + return { data: [] }; }; export async function getLabels(url: URL): Promise<(FeatureMetadata | ObservationMetadata)[]> { - const featureNames = await getFeatureNames(url) - const observationNames = await getObservationNames(url) - return [...featureNames, ...observationNames] + const featureNames = await getFeatureNames(url); + const observationNames = await getObservationNames(url); + return [...featureNames, ...observationNames]; } export const getFeatureNames = async (url: URL): Promise => { try { const root = await fetchZarrGroup(url); - const node = await open(root.resolve(FEATURE_NAMES_PATH)) - const parsedAttrs = ZarrObservationAttrsSchema.parse(node.attrs) - const path = `${FEATURE_NAMES_PATH}/${parsedAttrs._index}` - const { data, dtype } = await getData(root, path) + const node = await open(root.resolve(FEATURE_NAMES_PATH)); + const parsedAttrs = ZarrObservationAttrsSchema.parse(node.attrs); + const path = `${FEATURE_NAMES_PATH}/${parsedAttrs._index}`; + const { data, dtype } = await getData(root, path); - const parsedData = parseStringArray(data) + const parsedData = parseStringArray(data); return parsedData.map((name) => { return { - type: 'feature', - labelIndex: name - } - }) - + type: "feature", + labelIndex: name, + }; + }); } catch (error) { console.error(error); return []; @@ -131,88 +133,89 @@ export const getFeatureNames = async (url: URL): Promise => { }; function getObservationNamesPath(encodingType: string): string { - if (encodingType === 'categorical') { - return CATEGORY_NAMES_PATH + if (encodingType === "categorical") { + return CATEGORY_NAMES_PATH; } - return '' + return ""; } export const getObservationNames = async (url: URL): Promise> => { try { - const root = await fetchZarrGroup(url) + const root = await fetchZarrGroup(url); - const node = (await open(root.resolve(OBSERVATION_NAMES_PATH), { kind: "group" })) - console.log('Fetching observation names from attrs:', node.attrs) - const attrs = parseZarrObservationAttrs(node.attrs) - const cols = attrs["column-order"] + const node = await open(root.resolve(OBSERVATION_NAMES_PATH), { kind: "group" }); + console.log("Fetching observation names from attrs:", node.attrs); + const attrs = parseZarrObservationAttrs(node.attrs); + const cols = attrs["column-order"]; const obs = await Promise.all( cols.map(async (col) => { const dataNodeOrGroup = await open(root.resolve(`${OBSERVATION_NAMES_PATH}/${col}`)); - const parsedAttrs = ZarrAttrsSchema.parse(dataNodeOrGroup.attrs) - const dataPath = `${OBSERVATION_NAMES_PATH}/${col}/${getObservationNamesPath(parsedAttrs['encoding-type'])}` - const dataNode = await open(root.resolve(dataPath), { kind: 'array' }) - - const metadata: ObservationMetadata = { type: 'observation', labelIndex: col } - if (dataNode.dtype === 'bool') { - metadata['categories'] = ['false', 'true'] - return metadata + const parsedAttrs = ZarrAttrsSchema.parse(dataNodeOrGroup.attrs); + const dataPath = `${OBSERVATION_NAMES_PATH}/${col}/${getObservationNamesPath(parsedAttrs["encoding-type"])}`; + const dataNode = await open(root.resolve(dataPath), { kind: "array" }); + + const metadata: ObservationMetadata = { type: "observation", labelIndex: col }; + if (dataNode.dtype === "bool") { + metadata.categories = ["false", "true"]; + return metadata; } - if (parsedAttrs['encoding-type'] == 'array') { - return metadata + if (parsedAttrs["encoding-type"] === "array") { + return metadata; } - if (parsedAttrs['encoding-type'] == 'categorical') { - const { data, dtype } = await getData(root, dataPath) - const parsedCategories = AnndataCategoriesSchema.parse(data) - metadata['categories'] = parsedCategories - return metadata + if (parsedAttrs["encoding-type"] === "categorical") { + const { data, dtype } = await getData(root, dataPath); + const parsedCategories = AnndataCategoriesSchema.parse(data); + metadata.categories = parsedCategories; + return metadata; } - return undefined - }) - ) - return obs.filter((observation) => observation != undefined) - + return undefined; + }), + ); + return obs.filter((observation) => observation !== undefined); } catch (error) { console.error(error); return []; } }; -const ARRAY_PATH = 'X' +const ARRAY_PATH = "X"; export const getVarIndex = async (url: URL, varId: string, namesCol = VAR_NAMES_PATH) => { const store = new FetchStore(url); const node = await open(store, { kind: "group" }); - const { data, dtype } = await getData(node, `${VAR_NAMES_PATH}/${namesCol}`) + const { data, dtype } = await getData(node, `${VAR_NAMES_PATH}/${namesCol}`); const varNames = parseStringArray(data); const varIndex = varNames.findIndex((name: string) => name === varId); - debugger; return varIndex; }; -export async function getFeatureDataPath(url: URL, index: string, name?: string): Promise<{ path: string, slice: (number | null)[] }> { +export async function getFeatureDataPath( + url: URL, + index: string, + name?: string, +): Promise<{ path: string; slice: (number | null)[] }> { if (index) { - return ({ + return { path: ARRAY_PATH, - slice: [null, Number(index)] - }) - } else if (name) { + slice: [null, Number(index)], + }; + } + if (name) { return { path: ARRAY_PATH, - slice: [null, await getVarIndex(url, name)] - } - } else { - throw new Error(`Index or name needed to determine feature data path`) + slice: [null, await getVarIndex(url, name)], + }; } + throw new Error("Index or name needed to determine feature data path"); } -export async function getObservationDataPath(name: string): Promise<{ path: string, slice: undefined }> { +export async function getObservationDataPath(name: string): Promise<{ path: string; slice: undefined }> { return { path: `${OBSERVATION_NAMES_PATH}/${name}`, - slice: undefined - } + slice: undefined, + }; } - diff --git a/anndata-zarr/src/components/AnndataController.tsx b/anndata-zarr/src/components/AnndataController.tsx index 8e66aff7..eaf4b40b 100644 --- a/anndata-zarr/src/components/AnndataController.tsx +++ b/anndata-zarr/src/components/AnndataController.tsx @@ -6,32 +6,43 @@ import Stack from "@mui/material/Stack"; import { FeatureSelect } from "./FeatureSelect"; import { ObsSelect } from "./ObsSelect"; - import { useAnndataColors, useTableLabels } from "../hooks"; -export type LabelType = 'observation' | 'feature' +export type LabelType = "observation" | "feature"; + +export type labelColor = { + labelValue: number; + rgba: [r: number, g: number, b: number, a: number]; + value?: string | number | null; +}; -export const AnndataController = ({ adata, callback = () => { } }: { adata: string, callback: Function }) => { - const [selectedLabel, setSelectedLabel] = useState<{ labelIndex: string, type: LabelType } | undefined>(undefined) +export const AnndataController = ({ + adata, + callback = () => {}, +}: { adata: string; callback: (colorData: labelColor[] | null) => void }) => { + const [selectedLabel, setSelectedLabel] = useState<{ labelIndex: string; type: LabelType } | undefined>(undefined); - const url = { url: new URL(adata) } + const url = { url: new URL(adata) }; - function handleLabelSelect(labelIndex: string, labelType: 'feature' | 'observation') { - setSelectedLabel( - { - labelIndex: labelIndex, - type: labelType - } - ) + function handleLabelSelect(labelIndex: string, labelType: "feature" | "observation") { + setSelectedLabel({ + labelIndex: labelIndex, + type: labelType, + }); } - const labels = useTableLabels(url.url) + const labels = useTableLabels(url.url); //A necessary evil for now, I think in principle the UI should be more or less agnostic of whether it is an observation or a feature. - const selectedLabelDisplayData = labels.data && selectedLabel ? labels.data.filter((label) => label.labelIndex === selectedLabel.labelIndex)[0] : undefined - const selectedFeature = selectedLabelDisplayData?.type === 'feature' ? selectedLabelDisplayData.labelIndex : undefined - const selectedObservation = selectedLabelDisplayData?.type === 'observation' ? selectedLabelDisplayData.labelIndex : undefined + const selectedLabelDisplayData = + labels.data && selectedLabel + ? labels.data.filter((label) => label.labelIndex === selectedLabel.labelIndex)[0] + : undefined; + const selectedFeature = + selectedLabelDisplayData?.type === "feature" ? selectedLabelDisplayData.labelIndex : undefined; + const selectedObservation = + selectedLabelDisplayData?.type === "observation" ? selectedLabelDisplayData.labelIndex : undefined; - const colorData = useAnndataColors(url.url, selectedLabel, { enabled: !!selectedLabel }) + const colorData = useAnndataColors(url.url, selectedLabel, { enabled: !!selectedLabel }); useEffect(() => { if (colorData?.isError) { @@ -39,7 +50,6 @@ export const AnndataController = ({ adata, callback = () => { } }: { adata: stri return; } if (!colorData?.isLoading && colorData?.data) { - callback(colorData.data.colors); } }, [colorData, callback]); @@ -47,12 +57,27 @@ export const AnndataController = ({ adata, callback = () => { } }: { adata: stri return ( - {labels.data && label.type === 'feature').map((metadata) => metadata.labelIndex)} selectedFeatureIndex={selectedFeature} onFeatureSelect={handleLabelSelect} legendData={selectedFeature ? colorData.data : undefined} />} + {labels.data && ( + label.type === "feature") + .map((metadata) => metadata.labelIndex)} + selectedFeatureIndex={selectedFeature} + onFeatureSelect={handleLabelSelect} + legendData={selectedFeature ? colorData.data : undefined} + /> + )} - {labels.data && label.type === 'observation')} selectedObservation={selectedObservation} onObservationSelect={handleLabelSelect} legendData={selectedObservation ? colorData.data : undefined} />} + {labels.data && ( + label.type === "observation")} + selectedObservation={selectedObservation} + onObservationSelect={handleLabelSelect} + legendData={selectedObservation ? colorData.data : undefined} + /> + )} - ); }; diff --git a/anndata-zarr/src/components/FeatureSelect.tsx b/anndata-zarr/src/components/FeatureSelect.tsx index 4721dd88..c68c6df2 100644 --- a/anndata-zarr/src/components/FeatureSelect.tsx +++ b/anndata-zarr/src/components/FeatureSelect.tsx @@ -1,4 +1,5 @@ -import React, { useEffect, useMemo, useState } from "react"; +import type React from "react"; +import { useEffect, useMemo, useState } from "react"; import Box from "@mui/material/Box"; import ListItem from "@mui/material/ListItem"; @@ -8,15 +9,27 @@ import Stack from "@mui/material/Stack"; import TextField from "@mui/material/TextField"; import { List } from "react-window"; -import { type ColourProps, type Feature } from "../hooks"; +import type { ColourProps, Feature } from "../hooks"; import { Legend } from "./Legend"; -const RowComponent = ({ index, items, style, onSelect, selectedIndex }: { index: number, items: { matrixIndex: number, name: string }[], style: React.DetailedHTMLProps, HTMLStyleElement>, onSelect: Function, selectedIndex?: number }) => { +const RowComponent = ({ + index, + items, + style, + onSelect, + selectedIndex, +}: { + index: number; + items: { matrixIndex: number; name: string }[]; + style: React.DetailedHTMLProps, HTMLStyleElement>; + onSelect: (labelIndex: string, labelType: "observation" | "feature") => void; + selectedIndex?: number; +}) => { return ( onSelect(items[index].name, 'feature')} + onClick={() => onSelect(items[index].name, "feature")} selected={items[index].matrixIndex === selectedIndex} > @@ -24,29 +37,35 @@ const RowComponent = ({ index, items, style, onSelect, selectedIndex }: { index: ); }; -export const FeatureSelect = ({ featureNames, selectedFeatureIndex, onFeatureSelect, legendData }: { featureNames: string[], selectedFeatureIndex?: string, onFeatureSelect: Function, legendData?: ColourProps }) => { +export const FeatureSelect = ({ + featureNames, + selectedFeatureIndex, + onFeatureSelect, + legendData, +}: { + featureNames: string[]; + selectedFeatureIndex?: string; + onFeatureSelect: (labelIndex: string, labelType: "observation" | "feature") => void; + legendData?: ColourProps; +}) => { const [searchTerm, setSearchTerm] = useState(""); - const items = useMemo(() => { const allItems = featureNames.map((name: string, index: number) => { return { name: name, - matrixIndex: index - } - }) + matrixIndex: index, + }; + }); if (!searchTerm) { - return allItems + return allItems; } return allItems.filter((item) => item.name.toLowerCase().includes(searchTerm.toLowerCase())); - - }, [featureNames, searchTerm]) + }, [featureNames, searchTerm]); const legend = useMemo(() => { - if (legendData && legendData.colorscale) { + if (legendData?.colorscale) { return ; - } else { - return <> } }, [legendData]); diff --git a/anndata-zarr/src/components/Legend.tsx b/anndata-zarr/src/components/Legend.tsx index 9f7c5c39..0ebfb249 100644 --- a/anndata-zarr/src/components/Legend.tsx +++ b/anndata-zarr/src/components/Legend.tsx @@ -4,7 +4,7 @@ import _ from "lodash"; import { getColor } from "../utils"; -export const Legend = ({ min, max, colorscale }: { min: number, max: number, colorscale: string[] }) => { +export const Legend = ({ min, max, colorscale }: { min: number; max: number; colorscale: string[] }) => { const spanList = useMemo(() => { return _.range(100).map((i) => { const color = getColor({ value: i / 100, colorscale }); diff --git a/anndata-zarr/src/components/ObsSelect.tsx b/anndata-zarr/src/components/ObsSelect.tsx index 9635dbcd..6627c010 100644 --- a/anndata-zarr/src/components/ObsSelect.tsx +++ b/anndata-zarr/src/components/ObsSelect.tsx @@ -16,14 +16,18 @@ import Radio from "@mui/material/Radio"; import RadioGroup from "@mui/material/RadioGroup"; import Stack from "@mui/material/Stack"; +import type { CategoricalObservation, Observation } from "../anndata"; import { COLORSCALES } from "../constants/colorscales"; -import { type ColourProps, type ObservationMetadata } from "../hooks"; -import { type CategoricalObservation, type Observation } from "../anndata"; +import type { ColourProps, ObservationMetadata } from "../hooks"; import { getColor } from "../utils"; import { Legend } from "./Legend"; // @TODO: fix styling (width) -const CategoricalCol = ({ name, categories, showColor = false }: { name: string, categories: string[], showColor: boolean }) => { +const CategoricalCol = ({ + name, + categories, + showColor = false, +}: { name: string; categories: string[]; showColor: boolean }) => { const [open, setOpen] = useState(false); return ( @@ -52,7 +56,10 @@ const CategoricalCol = ({ name, categories, showColor = false }: { name: string, sx={{ width: 10, height: 10, - bgcolor: `rgba(${getColor({ value: i / (categories.length - 1), colorscale: COLORSCALES.Accent })})`, + bgcolor: `rgba(${getColor({ + value: i / (categories.length - 1), + colorscale: COLORSCALES.Accent, + })})`, }} /> @@ -70,24 +77,24 @@ const NumericalCol = ({ name }: { name: string }) => { return } label={name} key={name} value={name} />; }; interface ObservationControlsProps { - observations: ObservationMetadata[], - selectedObservation?: string, - onObservationSelect: Function, - legendData?: ColourProps + observations: ObservationMetadata[]; + selectedObservation?: string; + onObservationSelect: (labelIndex: string, labelType: "observation" | "feature") => void; + legendData?: ColourProps; } -export const ObsSelect = ({ observations, selectedObservation, onObservationSelect, legendData }: ObservationControlsProps) => { - - +export const ObsSelect = ({ + observations, + selectedObservation, + onObservationSelect, + legendData, +}: ObservationControlsProps) => { const legend = useMemo(() => { - if (legendData && legendData.colorscale) { + if (legendData?.colorscale) { return ; - } else { - <> } }, [legendData]); - return ( - onObservationSelect(e.target.value, 'observation')}> + onObservationSelect(e.target.value, "observation")} + > Categorical - {observations && observations.filter((obs) => 'categories' in obs).map((observation) => ( - - ))} + {observations + ?.filter((obs) => "categories" in obs) + .map((observation) => ( + + ))} Numerical - {observations && observations.filter((obs) => !('categories' in obs)).map((observation) => ( - - ))} + {observations + ?.filter((obs) => !("categories" in obs)) + .map((observation) => ( + + ))} diff --git a/anndata-zarr/src/hooks.ts b/anndata-zarr/src/hooks.ts index 06d2a096..c0372f08 100644 --- a/anndata-zarr/src/hooks.ts +++ b/anndata-zarr/src/hooks.ts @@ -1,126 +1,133 @@ -import { useCallback } from "react"; -import { useQueries, useQuery, type UseQueryResult } from "@tanstack/react-query"; +import { type UseQueryResult, useQueries, useQuery } from "@tanstack/react-query"; import _ from "lodash"; +import { useCallback } from "react"; +import type { argv0 } from "node:process"; +import { + fetchDataFromZarr, + getFeatureDataPath, + getFeatureNames, + getLabels, + getObservationDataPath, + getObservationNames, +} from "./anndata"; +import type { LabelType, labelColor } from "./components/AnndataController"; import { COLORSCALES } from "./constants/colorscales"; import { getColors } from "./utils"; -import { fetchDataFromZarr, getObservationNames, getFeatureNames, getFeatureDataPath, getObservationDataPath, getLabels } from "./anndata"; -import type { LabelType } from "./components/AnndataController"; export interface Feature { - index: string, - name?: string, - namesCol?: string + index: string; + name?: string; + namesCol?: string; } export interface MatrixProps { feature?: { - index?: number, - name?: string, - namesCol?: string - }, + index?: number; + name?: string; + namesCol?: string; + }; obs?: { - col?: string - } -} - -interface LabelColourMap { - labelValue: number, - rgba: number[] - value: string | number + col?: string; + }; } interface ColourData { - colors: LabelColourMap[], - min: number, - max: number, - categories?: string[], - colorscale?: string[] + colors: labelColor[]; + min: number; + max: number; + categories?: string[]; + colorscale?: string[]; } export interface ColourProps { - min: number, - max: number, - colorscale?: string[] + min: number; + max: number; + colorscale?: string[]; } - export interface AnndataURL { - url: URL, + url: URL; } export interface FeatureParams { - type: 'feature', - index: number + type: "feature"; + index: number; } export interface ObservationParams { - type: 'observation', - index: string + type: "observation"; + index: string; } -export const getAnndataColors = async (url: URL, labelQueryParameters: LabelQueryParameters | undefined, colorProps?: ColourProps): Promise => { +export const getAnndataColors = async ( + url: URL, + labelQueryParameters: LabelQueryParameters | undefined, + colorProps?: ColourProps, +): Promise => { + //Basically to satisfy typescript, this function should never be called with undefined query parameters. + if (typeof labelQueryParameters === "undefined") { + return Promise.reject(new Error("Invalid params")); + } - if (typeof labelQueryParameters === 'undefined') { - return (Promise.reject(new Error('Invalid params'))) + if (labelQueryParameters.type !== "feature" && labelQueryParameters.type !== "observation") { + throw new Error("Unknown table parameter type: ", labelQueryParameters.type); } - let path; - if (labelQueryParameters.type === 'feature') { - path = await getFeatureDataPath(url, labelQueryParameters.labelIndex) - } else if (labelQueryParameters.type === 'observation') { - path = await getObservationDataPath(labelQueryParameters.labelIndex) + let path: { path: string; slice: undefined | (number | null)[] }; + + if (labelQueryParameters.type === "feature") { + path = await getFeatureDataPath(url, labelQueryParameters.labelIndex); } else { - throw new Error('Unknown anndata parameter type') + path = await getObservationDataPath(labelQueryParameters.labelIndex); } const data = await fetchDataFromZarr(url, path.path, path.slice); - let min, max, colorscale, categories; - if ('categories' in data && data.categories) { - const categories = data.categories - max = categories.length - 1 - min = 0 - colorscale = COLORSCALES.Accent + let min = 0; + let max = 0; + + let colorscale: string[] | undefined; + let categories: string[] | undefined; + if ("categories" in data && data.categories) { + const categories = data.categories; + max = categories.length - 1; + min = 0; + colorscale = COLORSCALES.Accent; } else { - max = colorProps?.max || _.max(data.data) || 0 - min = colorProps?.min || _.min(data.data) || 0 - colorscale = colorProps?.colorscale - + max = colorProps?.max || _.max(data.data) || 0; + min = colorProps?.min || _.min(data.data) || 0; + colorscale = colorProps?.colorscale; } const colours = getColors({ data: data.data, max, min, colorscale: colorscale, - categories - }) - return ({ + categories, + }); + return { colors: colours, max, min, categories, - colorscale - }) - + colorscale, + }; }; type LabelQueryParameters = { - type: LabelType, - labelIndex: string -} - - + type: LabelType; + labelIndex: string; +}; export type FeatureMetadata = { - type: 'feature', - labelIndex: string, - categories?: string[] -} + type: "feature"; + labelIndex: string; + categories?: string[]; +}; export type ObservationMetadata = { - type: 'observation', - labelIndex: string, - categories?: string[] -} - + type: "observation"; + labelIndex: string; + categories?: string[]; +}; export function useTableLabels(url: URL): UseQueryResult<(FeatureMetadata | ObservationMetadata)[]> { const labels = useQuery({ @@ -128,12 +135,14 @@ export function useTableLabels(url: URL): UseQueryResult<(FeatureMetadata | Obse queryFn: () => getLabels(url), }); - return labels - + return labels; } -export const useAnndataColors = (url: URL, labelQueryParameters: LabelQueryParameters | undefined, opts = {}): UseQueryResult => { - +export const useAnndataColors = ( + url: URL, + labelQueryParameters: LabelQueryParameters | undefined, + opts = {}, +): UseQueryResult => { const result = useQuery({ queryKey: ["anndataColor", url, labelQueryParameters], queryFn: () => getAnndataColors(url, labelQueryParameters), diff --git a/anndata-zarr/src/provider.tsx b/anndata-zarr/src/provider.tsx index e4d3fb3a..ffe16326 100644 --- a/anndata-zarr/src/provider.tsx +++ b/anndata-zarr/src/provider.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import type React from "react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; diff --git a/anndata-zarr/src/utils.ts b/anndata-zarr/src/utils.ts index 886b2239..62055daa 100644 --- a/anndata-zarr/src/utils.ts +++ b/anndata-zarr/src/utils.ts @@ -1,10 +1,9 @@ import _ from "lodash"; +import type { labelColor } from "./components/AnndataController"; import { COLORSCALES } from "./constants/colorscales"; -import { type ColourProps } from "./hooks"; - -const parseHexColor = (color: string) => { +const parseHexColor = (color: string): [r: number, g: number, b: number] => { const r = Number.parseInt(color?.substring(1, 3), 16); const g = Number.parseInt(color?.substring(3, 5), 16); const b = Number.parseInt(color?.substring(5, 7), 16); @@ -12,7 +11,7 @@ const parseHexColor = (color: string) => { return [r, g, b]; }; -const interpolateColor = (color1: string, color2: string, factor: number) => { +const interpolateColor = (color1: string, color2: string, factor: number): [r: number, g: number, b: number] => { const [r1, g1, b1] = parseHexColor(color1); const [r2, g2, b2] = parseHexColor(color2); @@ -23,9 +22,9 @@ const interpolateColor = (color1: string, color2: string, factor: number) => { return [r, g, b]; }; -const computeColor = (colormap: string[], value: number) => { +const computeColor = (colormap: string[], value: number): [r: number, g: number, b: number] => { if (!colormap || Number.isNaN(value)) { - return [0, 0, 0, 255]; + return [0, 0, 0]; } if (value <= 0) { return parseHexColor(colormap[0]); @@ -39,11 +38,20 @@ const computeColor = (colormap: string[], value: number) => { return interpolateColor(colormap[index1], colormap[index2], factor); }; -export const getColor = ({ value, colorscale = COLORSCALES.Viridis }: { value: number, colorscale?: string[] }) => { +export const getColor = ({ + value, + colorscale = COLORSCALES.Viridis, +}: { value: number; colorscale?: string[] }): [r: number, g: number, b: number, a: number] => { return [...computeColor(colorscale, value), 255]; }; -export const getColors = ({ data, max, min, colorscale, categories }: { data: number[], max: number, min: number, colorscale?: string[], categories?: string[] }) => { +export const getColors = ({ + data, + max, + min, + colorscale, + categories, +}: { data: number[]; max: number; min: number; colorscale?: string[]; categories?: string[] }): labelColor[] => { return _.map(data, (v: number, i: number) => ({ labelValue: i + 1, rgba: getColor({ value: (v - min) / (max - min), colorscale }), diff --git a/anndata-zarr/src/zarr.ts b/anndata-zarr/src/zarr.ts index 4dc508f1..7c2811f9 100644 --- a/anndata-zarr/src/zarr.ts +++ b/anndata-zarr/src/zarr.ts @@ -1,24 +1,27 @@ -import { FetchStore, Group, type Readable, open, get } from "zarrita" -import { z } from "zod" +import { FetchStore, type Group, type Readable, get, open } from "zarrita"; +import { z } from "zod"; const ZarrDataSchema = z.object({ - data: z.any() -}) - + data: z.any(), +}); export async function fetchZarrGroup(url: URL): Promise> { - const store = new FetchStore(url) - return await open(store, { kind: "group" }) + const store = new FetchStore(url); + return await open(store, { kind: "group" }); } -export async function getData(root: Group, path: string, slice?: (number | null)[]): Promise<{ data: unknown[], dtype: string }> { - const dataNode = await open(root.resolve(path), { kind: 'array' }) - const data = await get(dataNode, slice) - const parsedData = ZarrDataSchema.parse(data) +export async function getData( + root: Group, + path: string, + slice?: (number | null)[], +): Promise<{ data: unknown[]; dtype: string }> { + const dataNode = await open(root.resolve(path), { kind: "array" }); + const data = await get(dataNode, slice); + const parsedData = ZarrDataSchema.parse(data); try { - const arrayData = Array.from(parsedData.data) - return { data: arrayData, dtype: dataNode.dtype } + const arrayData = Array.from(parsedData.data); + return { data: arrayData, dtype: dataNode.dtype }; } catch (error) { - throw new Error(`Could not parse Zarr array data at ${path}. Error: ${error}`) + throw new Error(`Could not parse Zarr array data at ${path}. Error: ${error}`); } } diff --git a/anndata-zarr/tests/expected_colours.json b/anndata-zarr/tests/expected_colours.json index 91899a74..fe68a5eb 100644 --- a/anndata-zarr/tests/expected_colours.json +++ b/anndata-zarr/tests/expected_colours.json @@ -1 +1,67 @@ -{"colors":[{"labelValue":1,"rgba":[68,57,130,255],"value":0.1658300302601523},{"labelValue":2,"rgba":[34,143,140,255],"value":0.4891459405665751},{"labelValue":3,"rgba":[191,223,38,255],"value":0.8974329354849481},{"labelValue":4,"rgba":[69,8,91,255],"value":0.023533927427546897},{"labelValue":5,"rgba":[163,218,54,255],"value":0.8563984648832248},{"labelValue":6,"rgba":[222,227,27,255],"value":0.9432887992234683},{"labelValue":7,"rgba":[199,224,34,255],"value":0.9090499221056513},{"labelValue":8,"rgba":[110,206,89,255],"value":0.772540518883162},{"labelValue":9,"rgba":[164,218,54,255],"value":0.8577915438512621},{"labelValue":10,"rgba":[224,227,28,255],"value":0.9458883944319205},{"labelValue":11,"rgba":[67,60,132,255],"value":0.17752092088363824},{"labelValue":12,"rgba":[185,222,41,255],"value":0.888718367894147},{"labelValue":13,"rgba":[31,157,137,255],"value":0.5504706652423125},{"labelValue":14,"rgba":[187,222,40,255],"value":0.8912855692053849},{"labelValue":15,"rgba":[37,133,142,255],"value":0.45122083454421824},{"labelValue":16,"rgba":[69,53,128,255],"value":0.15447245437137225},{"labelValue":17,"rgba":[35,140,141,255],"value":0.48013174167796535},{"labelValue":18,"rgba":[69,9,92,255],"value":0.024812424216993034},{"labelValue":19,"rgba":[35,139,141,255],"value":0.4748136489032414},{"labelValue":20,"rgba":[241,229,33,255],"value":0.9753731220887473},{"labelValue":21,"rgba":[135,213,73,255],"value":0.813230676083472},{"labelValue":22,"rgba":[70,11,94,255],"value":0.030333847161120864},{"labelValue":23,"rgba":[63,73,136,255],"value":0.22004476431310427},{"labelValue":24,"rgba":[253,231,37,255],"value":0.9948084537223887},{"labelValue":25,"rgba":[42,121,142,255],"value":0.4005457376940761},{"labelValue":26,"rgba":[172,220,49,255],"value":0.8686849274738432},{"labelValue":27,"rgba":[89,199,101,255],"value":0.7362613877052966},{"labelValue":28,"rgba":[71,39,118,255],"value":0.10972745888698887},{"labelValue":29,"rgba":[36,135,141,255],"value":0.4582572201664642},{"labelValue":30,"rgba":[199,224,34,255],"value":0.9081289285441259},{"labelValue":31,"rgba":[71,19,102,255],"value":0.05310654963214745},{"labelValue":32,"rgba":[57,86,139,255],"value":0.26427251460612133},{"labelValue":33,"rgba":[51,98,141,255],"value":0.3098868831143512},{"labelValue":34,"rgba":[71,45,123,255],"value":0.12859385219192254},{"labelValue":35,"rgba":[71,38,117,255],"value":0.1060341064816438},{"labelValue":36,"rgba":[56,88,140,255],"value":0.273146979830608},{"labelValue":37,"rgba":[94,201,98,255],"value":0.7474387872660285},{"labelValue":38,"rgba":[79,195,106,255],"value":0.7168943965063371},{"labelValue":39,"rgba":[31,159,136,255],"value":0.5567800064876861},{"labelValue":40,"rgba":[118,208,84,255],"value":0.785358005462284},{"labelValue":41,"rgba":[181,221,44,255],"value":0.8820685615410931},{"labelValue":42,"rgba":[177,221,46,255],"value":0.8764131827619143},{"labelValue":43,"rgba":[69,6,89,255],"value":0.016894230930217247},{"labelValue":44,"rgba":[69,4,87,255],"value":0.011590410943970952},{"labelValue":45,"rgba":[76,194,108,255],"value":0.7116094880320885},{"labelValue":46,"rgba":[54,92,140,255],"value":0.2881044279476044},{"labelValue":47,"rgba":[213,226,27,255],"value":0.9282508060940267},{"labelValue":48,"rgba":[40,125,142,255],"value":0.4158803393647662},{"labelValue":49,"rgba":[66,64,134,255],"value":0.19045753449072},{"labelValue":50,"rgba":[45,112,142,255],"value":0.36713928055013845},{"labelValue":51,"rgba":[207,225,30,255],"value":0.9194919597647628},{"labelValue":52,"rgba":[56,89,140,255],"value":0.2772744211351149},{"labelValue":53,"rgba":[54,92,140,255],"value":0.2887579479880511},{"labelValue":54,"rgba":[56,89,140,255],"value":0.2767322711017376},{"labelValue":55,"rgba":[90,200,100,255],"value":0.739933093943506},{"labelValue":56,"rgba":[71,42,121,255],"value":0.11849387104612308},{"labelValue":57,"rgba":[37,132,142,255],"value":0.4465532692621863},{"labelValue":58,"rgba":[140,214,70,255],"value":0.8211443808344999},{"labelValue":59,"rgba":[32,162,135,255],"value":0.5709565352647414},{"labelValue":60,"rgba":[68,1,84,255],"value":0.0034096290176031108},{"labelValue":61,"rgba":[60,79,138,255],"value":0.24026647309570515}],"max":0.9948084537223887,"min":0.0034096290176031108} \ No newline at end of file +{ + "colors": [ + { "labelValue": 1, "rgba": [68, 57, 130, 255], "value": 0.1658300302601523 }, + { "labelValue": 2, "rgba": [34, 143, 140, 255], "value": 0.4891459405665751 }, + { "labelValue": 3, "rgba": [191, 223, 38, 255], "value": 0.8974329354849481 }, + { "labelValue": 4, "rgba": [69, 8, 91, 255], "value": 0.023533927427546897 }, + { "labelValue": 5, "rgba": [163, 218, 54, 255], "value": 0.8563984648832248 }, + { "labelValue": 6, "rgba": [222, 227, 27, 255], "value": 0.9432887992234683 }, + { "labelValue": 7, "rgba": [199, 224, 34, 255], "value": 0.9090499221056513 }, + { "labelValue": 8, "rgba": [110, 206, 89, 255], "value": 0.772540518883162 }, + { "labelValue": 9, "rgba": [164, 218, 54, 255], "value": 0.8577915438512621 }, + { "labelValue": 10, "rgba": [224, 227, 28, 255], "value": 0.9458883944319205 }, + { "labelValue": 11, "rgba": [67, 60, 132, 255], "value": 0.17752092088363824 }, + { "labelValue": 12, "rgba": [185, 222, 41, 255], "value": 0.888718367894147 }, + { "labelValue": 13, "rgba": [31, 157, 137, 255], "value": 0.5504706652423125 }, + { "labelValue": 14, "rgba": [187, 222, 40, 255], "value": 0.8912855692053849 }, + { "labelValue": 15, "rgba": [37, 133, 142, 255], "value": 0.45122083454421824 }, + { "labelValue": 16, "rgba": [69, 53, 128, 255], "value": 0.15447245437137225 }, + { "labelValue": 17, "rgba": [35, 140, 141, 255], "value": 0.48013174167796535 }, + { "labelValue": 18, "rgba": [69, 9, 92, 255], "value": 0.024812424216993034 }, + { "labelValue": 19, "rgba": [35, 139, 141, 255], "value": 0.4748136489032414 }, + { "labelValue": 20, "rgba": [241, 229, 33, 255], "value": 0.9753731220887473 }, + { "labelValue": 21, "rgba": [135, 213, 73, 255], "value": 0.813230676083472 }, + { "labelValue": 22, "rgba": [70, 11, 94, 255], "value": 0.030333847161120864 }, + { "labelValue": 23, "rgba": [63, 73, 136, 255], "value": 0.22004476431310427 }, + { "labelValue": 24, "rgba": [253, 231, 37, 255], "value": 0.9948084537223887 }, + { "labelValue": 25, "rgba": [42, 121, 142, 255], "value": 0.4005457376940761 }, + { "labelValue": 26, "rgba": [172, 220, 49, 255], "value": 0.8686849274738432 }, + { "labelValue": 27, "rgba": [89, 199, 101, 255], "value": 0.7362613877052966 }, + { "labelValue": 28, "rgba": [71, 39, 118, 255], "value": 0.10972745888698887 }, + { "labelValue": 29, "rgba": [36, 135, 141, 255], "value": 0.4582572201664642 }, + { "labelValue": 30, "rgba": [199, 224, 34, 255], "value": 0.9081289285441259 }, + { "labelValue": 31, "rgba": [71, 19, 102, 255], "value": 0.05310654963214745 }, + { "labelValue": 32, "rgba": [57, 86, 139, 255], "value": 0.26427251460612133 }, + { "labelValue": 33, "rgba": [51, 98, 141, 255], "value": 0.3098868831143512 }, + { "labelValue": 34, "rgba": [71, 45, 123, 255], "value": 0.12859385219192254 }, + { "labelValue": 35, "rgba": [71, 38, 117, 255], "value": 0.1060341064816438 }, + { "labelValue": 36, "rgba": [56, 88, 140, 255], "value": 0.273146979830608 }, + { "labelValue": 37, "rgba": [94, 201, 98, 255], "value": 0.7474387872660285 }, + { "labelValue": 38, "rgba": [79, 195, 106, 255], "value": 0.7168943965063371 }, + { "labelValue": 39, "rgba": [31, 159, 136, 255], "value": 0.5567800064876861 }, + { "labelValue": 40, "rgba": [118, 208, 84, 255], "value": 0.785358005462284 }, + { "labelValue": 41, "rgba": [181, 221, 44, 255], "value": 0.8820685615410931 }, + { "labelValue": 42, "rgba": [177, 221, 46, 255], "value": 0.8764131827619143 }, + { "labelValue": 43, "rgba": [69, 6, 89, 255], "value": 0.016894230930217247 }, + { "labelValue": 44, "rgba": [69, 4, 87, 255], "value": 0.011590410943970952 }, + { "labelValue": 45, "rgba": [76, 194, 108, 255], "value": 0.7116094880320885 }, + { "labelValue": 46, "rgba": [54, 92, 140, 255], "value": 0.2881044279476044 }, + { "labelValue": 47, "rgba": [213, 226, 27, 255], "value": 0.9282508060940267 }, + { "labelValue": 48, "rgba": [40, 125, 142, 255], "value": 0.4158803393647662 }, + { "labelValue": 49, "rgba": [66, 64, 134, 255], "value": 0.19045753449072 }, + { "labelValue": 50, "rgba": [45, 112, 142, 255], "value": 0.36713928055013845 }, + { "labelValue": 51, "rgba": [207, 225, 30, 255], "value": 0.9194919597647628 }, + { "labelValue": 52, "rgba": [56, 89, 140, 255], "value": 0.2772744211351149 }, + { "labelValue": 53, "rgba": [54, 92, 140, 255], "value": 0.2887579479880511 }, + { "labelValue": 54, "rgba": [56, 89, 140, 255], "value": 0.2767322711017376 }, + { "labelValue": 55, "rgba": [90, 200, 100, 255], "value": 0.739933093943506 }, + { "labelValue": 56, "rgba": [71, 42, 121, 255], "value": 0.11849387104612308 }, + { "labelValue": 57, "rgba": [37, 132, 142, 255], "value": 0.4465532692621863 }, + { "labelValue": 58, "rgba": [140, 214, 70, 255], "value": 0.8211443808344999 }, + { "labelValue": 59, "rgba": [32, 162, 135, 255], "value": 0.5709565352647414 }, + { "labelValue": 60, "rgba": [68, 1, 84, 255], "value": 0.0034096290176031108 }, + { "labelValue": 61, "rgba": [60, 79, 138, 255], "value": 0.24026647309570515 } + ], + "max": 0.9948084537223887, + "min": 0.0034096290176031108 +} diff --git a/anndata-zarr/tests/test.test.ts b/anndata-zarr/tests/test.test.ts index 8b0b8b00..3adf321b 100644 --- a/anndata-zarr/tests/test.test.ts +++ b/anndata-zarr/tests/test.test.ts @@ -1,17 +1,17 @@ +import fs from "node:fs"; +import path from "node:path"; import { expect, test } from "vitest"; -import yaml from 'yaml'; -import fs from 'node:fs'; -import path from 'node:path'; -import expectedColours from './expected_colours.json' +import yaml from "yaml"; +import expectedColours from "./expected_colours.json"; -import { getAnndataColors } from "../src/hooks" +import { getAnndataColors } from "../src/hooks"; -const fixtures_path = path.resolve(path.join(__dirname, "..", "..", "fixtures")) +const fixtures_path = path.resolve(path.join(__dirname, "..", "..", "fixtures")); test("Can get anndata colours", async () => { - const table = yaml.parse(fs.readFileSync(path.join(fixtures_path, "anndata_table.yaml"), 'utf-8')) + const table = yaml.parse(fs.readFileSync(path.join(fixtures_path, "anndata_table.yaml"), "utf-8")); - const colours = await getAnndataColors(table.source, { type: 'feature', labelIndex: '3' }) + const colours = await getAnndataColors(table.source, { type: "feature", labelIndex: "3" }); - expect(colours).toEqual(expectedColours) -}) + expect(colours).toEqual(expectedColours); +}); diff --git a/anndata-zarr/tsconfig.json b/anndata-zarr/tsconfig.json index 32e07458..62b84831 100644 --- a/anndata-zarr/tsconfig.json +++ b/anndata-zarr/tsconfig.json @@ -9,8 +9,6 @@ "forceConsistentCasingInFileNames": true, "verbatimModuleSyntax": true, "jsx": "preserve", - "types": [ - "vite/client" - ] + "types": ["vite/client"] } } diff --git a/anndata-zarr/types.ts b/anndata-zarr/types.ts index 8b137891..e69de29b 100644 --- a/anndata-zarr/types.ts +++ b/anndata-zarr/types.ts @@ -1 +0,0 @@ - diff --git a/anndata-zarr/vite.config.js b/anndata-zarr/vite.config.js index 789b956f..056ed352 100644 --- a/anndata-zarr/vite.config.js +++ b/anndata-zarr/vite.config.js @@ -1,7 +1,7 @@ import path from "node:path"; -import dts from "vite-plugin-dts"; import react from "@vitejs/plugin-react"; import { defineConfig } from "vite"; +import dts from "vite-plugin-dts"; // https://vite.dev/config/ export default defineConfig({ diff --git a/sites/app/src/App.tsx b/sites/app/src/App.tsx index 7d1acf42..d2e9629a 100644 --- a/sites/app/src/App.tsx +++ b/sites/app/src/App.tsx @@ -3,10 +3,10 @@ import { type ViewState, Vizarr, type labelColor } from "@biongff/vizarr"; //@ts-ignore //No types provided by anndata-zarr plugin import { AnndataController, AnndataProvider } from "@biongff/anndata-zarr"; -import CssBaseline from "@mui/material/CssBaseline"; -import { ThemeProvider, createTheme } from "@mui/material/styles"; import { RoiSelector, useRoiDeckExtension } from "@biongff/roi-selector"; import type { PendingRoi, RoiDrawState, SavedRoi, ViewerInfo } from "@biongff/roi-selector"; +import CssBaseline from "@mui/material/CssBaseline"; +import { ThemeProvider, createTheme } from "@mui/material/styles"; import debounce from "just-debounce-it"; import * as React from "react"; @@ -54,12 +54,10 @@ export default function App() { sources: searchParams.getAll("source"), viewState: parseViewStateFromUrl(), enableRoi: searchParams.get("roi") === "1", - tableURLs: searchParams.getAll("anndata") + tableURLs: searchParams.getAll("anndata"), }; }, [urlString]); - - const [colors, setColors] = React.useState((): labelColor[][] => Array(sources.length).fill([])); // Debounced viewState change handler @@ -133,7 +131,6 @@ export default function App() { onPluginHover={enableRoi ? onHover : undefined} labelColours={colors} > - {enableRoi && viewerInfo && ( - + ); } diff --git a/sites/app/vite.config.js b/sites/app/vite.config.js index 75650142..5f717eab 100644 --- a/sites/app/vite.config.js +++ b/sites/app/vite.config.js @@ -9,11 +9,11 @@ export default defineConfig(({ mode }) => ({ alias: { ...(mode === "development" ? { - "@biongff/vizarr": path.resolve(__dirname, "../../viewer/src/index.tsx"), - "@biongff/anndata-zarr/dist/anndata-zarr.css": path.resolve(__dirname, "../../anndata-zarr/src/index.css"), - "@biongff/anndata-zarr": path.resolve(__dirname, "../../anndata-zarr/src/index.js"), - "@biongff/roi-selector": path.resolve(__dirname, "../../roi-selector/src/index.tsx"), - } + "@biongff/vizarr": path.resolve(__dirname, "../../viewer/src/index.tsx"), + "@biongff/anndata-zarr/dist/anndata-zarr.css": path.resolve(__dirname, "../../anndata-zarr/src/index.css"), + "@biongff/anndata-zarr": path.resolve(__dirname, "../../anndata-zarr/src/index.js"), + "@biongff/roi-selector": path.resolve(__dirname, "../../roi-selector/src/index.tsx"), + } : {}), }, }, diff --git a/viewer/src/components/VizarrViewer.tsx b/viewer/src/components/VizarrViewer.tsx index 69901f64..5332fc4e 100644 --- a/viewer/src/components/VizarrViewer.tsx +++ b/viewer/src/components/VizarrViewer.tsx @@ -5,10 +5,10 @@ import type { Layer } from "deck.gl"; import { type PrimitiveAtom, Provider, atom, useAtomValue, useSetAtom } from "jotai"; import React, { useId } from "react"; import { getSourceDataError, sourceDataValid, writeUserErrorMessage } from "../error"; -import { loadSources } from "../io"; -import type { OmeColor } from "../layers/label-layer"; import { ViewStateContext, useViewState } from "../hooks"; +import { loadSources } from "../io"; import { createSourceData } from "../io"; +import type { OmeColor } from "../layers/label-layer"; import { type ImageLayerConfig, type ViewState, @@ -106,8 +106,7 @@ function ViewerBridge({ setViewState: stableSetViewState, setZSlice, setTSlice, - } - + }; onViewerStateChange?.({ sourceUrl: sourceUrls[0] ?? "", @@ -128,7 +127,7 @@ function ViewerBridge({ // stableSetViewState, setZSlice, setTSlice, - onViewerStateChange + onViewerStateChange, ]); return ( From 1edce3d75b18e3c9d9bf36f9131390b84368e43c Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Wed, 1 Jul 2026 09:09:35 +0100 Subject: [PATCH 20/26] fix: infinite re-render caused by synchronisation of viewer and roi plugin --- roi-selector/src/RoiSelector.tsx | 16 +++++++----- roi-selector/src/state.ts | 2 +- viewer/src/components/VizarrViewer.tsx | 34 +------------------------- 3 files changed, 12 insertions(+), 40 deletions(-) diff --git a/roi-selector/src/RoiSelector.tsx b/roi-selector/src/RoiSelector.tsx index 2fa3da8f..61c28848 100644 --- a/roi-selector/src/RoiSelector.tsx +++ b/roi-selector/src/RoiSelector.tsx @@ -101,12 +101,16 @@ function RoiSelector({ const availW = Math.max(viewport.width - 2 * padding, 1); const availH = Math.max(viewport.height - 2 * padding, 1); const zoom = Math.log2(Math.min(availW / roiWidth, availH / roiHeight)); - setViewState({ - zoom, - target: [(bounds.min.x + bounds.max.x) / 2, (bounds.min.y + bounds.max.y) / 2], - width: viewport.width, - height: viewport.height, - }); + + if (setViewState) { + setViewState({ + zoom, + target: [(bounds.min.x + bounds.max.x) / 2, (bounds.min.y + bounds.max.y) / 2], + width: viewport.width, + height: viewport.height, + }); + } + if (hasZAxis && zInfo && bounds.min.z !== undefined && bounds.max.z !== undefined) { // Only jump Z if the current slice is outside the ROI's Z range. if (zInfo.zValue < bounds.min.z || zInfo.zValue > bounds.max.z) { diff --git a/roi-selector/src/state.ts b/roi-selector/src/state.ts index e40e8d22..89519aa0 100644 --- a/roi-selector/src/state.ts +++ b/roi-selector/src/state.ts @@ -245,7 +245,7 @@ export interface ViewerInfo { zInfo: { zValue: number; zMax: number } | null; tInfo: { tValue: number; tMax: number } | null; viewport: { width: number; height: number } | null; - setViewState: (vs: { zoom: number; target: [number, number]; width: number; height: number }) => void; + setViewState?: (vs: { zoom: number; target: [number, number]; width: number; height: number }) => void; setZSlice: (z: number) => void; setTSlice: (t: number) => void; } diff --git a/viewer/src/components/VizarrViewer.tsx b/viewer/src/components/VizarrViewer.tsx index 5332fc4e..9ca049bd 100644 --- a/viewer/src/components/VizarrViewer.tsx +++ b/viewer/src/components/VizarrViewer.tsx @@ -37,7 +37,6 @@ export interface ViewerInfo { zInfo: { zValue: number; zMax: number } | null; tInfo: { tValue: number; tMax: number } | null; viewport: ViewportSize | null; - setViewState: (vs: ViewState) => void; setZSlice: (z: number) => void; setTSlice: (t: number) => void; } @@ -83,52 +82,21 @@ function ViewerBridge({ const zInfo = useAtomValue(currentZInfoAtom); const tInfo = useAtomValue(currentTInfoAtom); const viewport = useAtomValue(viewportAtom); - const [, setViewState] = useViewState(); - const setZSlice = useSetAtom(setZSliceAtom); const setTSlice = useSetAtom(setTSliceAtom); - const stableSetViewState = React.useCallback( - (vs: ViewState) => { - setViewState(vs); - }, - [setViewState], - ); - // Notify host application when viewer state changes React.useEffect(() => { - const change = { - sourceUrl: sourceUrls[0] ?? "", - imageBounds, - zInfo, - tInfo, - viewport, - setViewState: stableSetViewState, - setZSlice, - setTSlice, - }; - onViewerStateChange?.({ sourceUrl: sourceUrls[0] ?? "", imageBounds, zInfo, tInfo, viewport, - setViewState: stableSetViewState, setZSlice, setTSlice, }); - }, [ - sourceUrls, - imageBounds, - zInfo, - tInfo, - viewport, - // stableSetViewState, - setZSlice, - setTSlice, - onViewerStateChange, - ]); + }, [sourceUrls, imageBounds, zInfo, tInfo, viewport, setZSlice, setTSlice, onViewerStateChange]); return ( <> From 3531d2124b2026ad82502e2ac342a57ad3a6be2f Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Fri, 3 Jul 2026 08:48:43 +0100 Subject: [PATCH 21/26] Prevent erroneous upgrade of transitive dependency --- pnpm-lock.yaml | 8 ++++---- viewer/package.json | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 33688f77..0ee5a256 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4286,8 +4286,8 @@ packages: web-worker@1.5.0: resolution: {integrity: sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==} - wgsl_reflect@1.3.0: - resolution: {integrity: sha512-liK+dXfDMQUrr8QcZhZi75EFD4us4VhsIT218YMkKZr8aDExc7A5znDpfmf7IxM3nIooFPCKAnK9u8WY5XizAw==} + wgsl_reflect@1.2.0: + resolution: {integrity: sha512-bDYcmWfbg4WsrBmPv6lsyjqXx02r8dkNAzR77OCNqIcR8snO4aNSBTjir9zqgR7rLnw6PaisiZxtCitSCIUlnQ==} which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} @@ -5312,7 +5312,7 @@ snapshots: '@luma.gl/core': 9.0.28 '@math.gl/core': 4.1.0 '@math.gl/types': 4.1.0 - wgsl_reflect: 1.3.0 + wgsl_reflect: 1.2.0 '@luma.gl/webgl@9.0.28(@luma.gl/core@9.0.28)': dependencies: @@ -8697,7 +8697,7 @@ snapshots: web-worker@1.5.0: {} - wgsl_reflect@1.3.0: {} + wgsl_reflect@1.2.0: {} which@2.0.2: dependencies: diff --git a/viewer/package.json b/viewer/package.json index a19ff172..02d0901d 100644 --- a/viewer/package.json +++ b/viewer/package.json @@ -58,6 +58,7 @@ "vite-plugin-dts": "^4.5.4" }, "overrides": { - "react-is": "^18.3.1" + "react-is": "^18.3.1", + "wgsl_reflect": "1.2.0" } } From 3fa8e2349a487163001cea2bbb02a6ceffd60819 Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Fri, 3 Jul 2026 10:31:08 +0100 Subject: [PATCH 22/26] Speculative fix for workflow error --- anndata-zarr/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/anndata-zarr/package.json b/anndata-zarr/package.json index cc74671f..3e1fce12 100644 --- a/anndata-zarr/package.json +++ b/anndata-zarr/package.json @@ -31,14 +31,14 @@ "react-window": "^2.0.2", "yaml": "^2.8.2", "zarrita": "0.5.0", - "zod": "^4.4.3" + "zod": "^4.4.3", + "react": "^18.2.0" }, "peerDependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", "@mui/icons-material": "^7.2.0", "@mui/material": "^7.2.0", - "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { From 2d5cea7a732142ab4ed3e06776b1ff2d773c4cc5 Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Mon, 6 Jul 2026 13:37:27 +0100 Subject: [PATCH 23/26] Changes to table plugin config --- anndata-zarr/tsconfig.json | 4 +++- anndata-zarr/vite.config.js | 2 +- sites/app/src/App.tsx | 2 -- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/anndata-zarr/tsconfig.json b/anndata-zarr/tsconfig.json index 62b84831..32e07458 100644 --- a/anndata-zarr/tsconfig.json +++ b/anndata-zarr/tsconfig.json @@ -9,6 +9,8 @@ "forceConsistentCasingInFileNames": true, "verbatimModuleSyntax": true, "jsx": "preserve", - "types": ["vite/client"] + "types": [ + "vite/client" + ] } } diff --git a/anndata-zarr/vite.config.js b/anndata-zarr/vite.config.js index 056ed352..4600f212 100644 --- a/anndata-zarr/vite.config.js +++ b/anndata-zarr/vite.config.js @@ -9,7 +9,7 @@ export default defineConfig({ build: { // outDir: path.resolve(__dirname, '../dist'), lib: { - entry: path.resolve(__dirname, "src/index.js"), + entry: path.resolve(__dirname, "src/index.ts"), name: "BiongffAnndataZarr", formats: ["es", "cjs"], fileName: (format) => `biongff-anndata-zarr.${format}.js`, diff --git a/sites/app/src/App.tsx b/sites/app/src/App.tsx index d2e9629a..a4477fa7 100644 --- a/sites/app/src/App.tsx +++ b/sites/app/src/App.tsx @@ -1,7 +1,5 @@ import { type ViewState, Vizarr, type labelColor } from "@biongff/vizarr"; -//@ts-ignore -//No types provided by anndata-zarr plugin import { AnndataController, AnndataProvider } from "@biongff/anndata-zarr"; import { RoiSelector, useRoiDeckExtension } from "@biongff/roi-selector"; import type { PendingRoi, RoiDrawState, SavedRoi, ViewerInfo } from "@biongff/roi-selector"; From 4b6213397ef149226e0944919269fcc75c773a96 Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Tue, 7 Jul 2026 11:30:08 +0100 Subject: [PATCH 24/26] Resolve type conflict between viewer and table plugin --- anndata-zarr/src/components/AnndataController.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/anndata-zarr/src/components/AnndataController.tsx b/anndata-zarr/src/components/AnndataController.tsx index eaf4b40b..6f81465c 100644 --- a/anndata-zarr/src/components/AnndataController.tsx +++ b/anndata-zarr/src/components/AnndataController.tsx @@ -17,8 +17,8 @@ export type labelColor = { export const AnndataController = ({ adata, - callback = () => {}, -}: { adata: string; callback: (colorData: labelColor[] | null) => void }) => { + callback = () => { }, +}: { adata: string; callback: (colorData: labelColor[]) => void }) => { const [selectedLabel, setSelectedLabel] = useState<{ labelIndex: string; type: LabelType } | undefined>(undefined); const url = { url: new URL(adata) }; @@ -46,7 +46,7 @@ export const AnndataController = ({ useEffect(() => { if (colorData?.isError) { - callback(null); + callback([]); return; } if (!colorData?.isLoading && colorData?.data) { From 63f2ffc68386fa09fdb56474010ae498e72e02df Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Tue, 7 Jul 2026 11:34:12 +0100 Subject: [PATCH 25/26] Linting --- anndata-zarr/src/components/AnndataController.tsx | 2 +- anndata-zarr/tsconfig.json | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/anndata-zarr/src/components/AnndataController.tsx b/anndata-zarr/src/components/AnndataController.tsx index 6f81465c..c7017461 100644 --- a/anndata-zarr/src/components/AnndataController.tsx +++ b/anndata-zarr/src/components/AnndataController.tsx @@ -17,7 +17,7 @@ export type labelColor = { export const AnndataController = ({ adata, - callback = () => { }, + callback = () => {}, }: { adata: string; callback: (colorData: labelColor[]) => void }) => { const [selectedLabel, setSelectedLabel] = useState<{ labelIndex: string; type: LabelType } | undefined>(undefined); diff --git a/anndata-zarr/tsconfig.json b/anndata-zarr/tsconfig.json index 32e07458..62b84831 100644 --- a/anndata-zarr/tsconfig.json +++ b/anndata-zarr/tsconfig.json @@ -9,8 +9,6 @@ "forceConsistentCasingInFileNames": true, "verbatimModuleSyntax": true, "jsx": "preserve", - "types": [ - "vite/client" - ] + "types": ["vite/client"] } } From afe0b52f9cded393d2d4f41f5ab12ac76f89ad70 Mon Sep 17 00:00:00 2001 From: Alex Surtees Date: Tue, 7 Jul 2026 11:46:45 +0100 Subject: [PATCH 26/26] Add vitest config --- vitest.config.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 vitest.config.ts diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 00000000..5c6ccb4b --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,10 @@ +// vitest.config.ts +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + // Glob pattern to include all package configs or directories + projects: ["anndata-zarr", "viewer", "roi-selector"], + testTimeout: 10000, + }, +});