diff --git a/applications/visualizer/api/openapi.json b/applications/visualizer/api/openapi.json index 15f3638d..90d68f86 100644 --- a/applications/visualizer/api/openapi.json +++ b/applications/visualizer/api/openapi.json @@ -411,6 +411,13 @@ "title": "Id", "type": "string" }, + "neuron3DUrl": { + "title": "Neuron3Durl", + "type": "string" + }, + "emData": { + "$ref": "#/components/schemas/EMData" + }, "collection": { "maxLength": 20, "title": "Collection", @@ -452,6 +459,8 @@ }, "required": [ "id", + "neuron3DUrl", + "emData", "collection", "name", "description", @@ -462,6 +471,39 @@ "title": "Dataset", "type": "object" }, + "EMData": { + "properties": { + "min_zoom": { + "title": "Min Zoom", + "type": "integer" + }, + "max_zoom": { + "title": "Max Zoom", + "type": "integer" + }, + "nb_slices": { + "title": "Nb Slices", + "type": "integer" + }, + "resource_url": { + "title": "Resource Url", + "type": "string" + }, + "segmentation_url": { + "title": "Segmentation Url", + "type": "string" + } + }, + "required": [ + "min_zoom", + "max_zoom", + "nb_slices", + "resource_url", + "segmentation_url" + ], + "title": "EMData", + "type": "object" + }, "ErrorMessage": { "properties": { "detail": { @@ -488,6 +530,10 @@ "title": "Datasetids", "type": "array" }, + "model3DUrl": { + "title": "Model3Durl", + "type": "string" + }, "nclass": { "maxLength": 30, "title": "Nclass", @@ -522,6 +568,7 @@ "required": [ "name", "datasetIds", + "model3DUrl", "nclass", "neurotransmitter", "type" diff --git a/applications/visualizer/api/openapi.yaml b/applications/visualizer/api/openapi.yaml index a5bc1bc3..9171cbf8 100644 --- a/applications/visualizer/api/openapi.yaml +++ b/applications/visualizer/api/openapi.yaml @@ -46,6 +46,8 @@ components: description: title: Description type: string + emData: + $ref: '#/components/schemas/EMData' id: title: Id type: string @@ -53,6 +55,9 @@ components: maxLength: 50 title: Name type: string + neuron3DUrl: + title: Neuron3Durl + type: string time: title: Time type: number @@ -65,6 +70,8 @@ components: type: number required: - id + - neuron3DUrl + - emData - collection - name - description @@ -73,6 +80,31 @@ components: - type title: Dataset type: object + EMData: + properties: + max_zoom: + title: Max Zoom + type: integer + min_zoom: + title: Min Zoom + type: integer + nb_slices: + title: Nb Slices + type: integer + resource_url: + title: Resource Url + type: string + segmentation_url: + title: Segmentation Url + type: string + required: + - min_zoom + - max_zoom + - nb_slices + - resource_url + - segmentation_url + title: EMData + type: object ErrorMessage: properties: detail: @@ -110,6 +142,9 @@ components: default: false title: Intail type: boolean + model3DUrl: + title: Model3Durl + type: string name: title: Name type: string @@ -128,6 +163,7 @@ components: required: - name - datasetIds + - model3DUrl - nclass - neurotransmitter - type diff --git a/applications/visualizer/backend/api/api.py b/applications/visualizer/backend/api/api.py index 5015339e..bcb601d9 100644 --- a/applications/visualizer/backend/api/api.py +++ b/applications/visualizer/backend/api/api.py @@ -1,15 +1,14 @@ from collections import defaultdict -from typing import Optional +from typing import Iterable, Optional -from django.http import HttpResponse from ninja import NinjaAPI, Router, Schema, Query from ninja.pagination import paginate, PageNumberPagination from django.shortcuts import aget_object_or_404 -from django.db.models import Q, F, Value, CharField, Func, OuterRef +from django.db.models import Q from django.db.models.manager import BaseManager -from django.db.models.functions import Coalesce, Concat +from django.conf import settings -from .schemas import Dataset, Neuron, Connection +from .schemas import Dataset, EMData, Neuron, Connection from .models import ( Dataset as DatasetModel, Neuron as NeuronModel, @@ -50,6 +49,27 @@ def api_operation(self, *args, **kwargs): # ) +def annotate_dataset(datasets: Iterable[DatasetModel]): + for dataset in datasets: + dataset_id = dataset.id + dataset.neuron3D_url = ( # type: ignore + settings.DATASET_NEURON_REPRESENTATION_3D_URL_FORMAT.format( + dataset=dataset_id + ) + ) + dataset.em_data = EMData( # type: ignore + min_zoom=0, + max_zoom=0, + nb_slices=0, + # resource_url=settings.DATASET_EMDATA_URL_FORMAT.format(dataset=dataset_id), + # segmentation_url=settings.DATASET_EMDATA_SEGMENTATION_URL_FORMAT.format( + # dataset=dataset_id + # ), + resource_url=settings.DATASET_EMDATA_URL_FORMAT, + segmentation_url=settings.DATASET_EMDATA_SEGMENTATION_URL_FORMAT, + ) + + @api.get("/datasets", response=list[Dataset], tags=["datasets"]) async def get_datasets(request, ids: Optional[list[str]] = Query(None)): """Returns all datasets or a filtered list based on provided IDs""" @@ -57,6 +77,8 @@ async def get_datasets(request, ids: Optional[list[str]] = Query(None)): datasets = await to_list(DatasetModel.objects.filter(id__in=ids)) else: datasets = await to_list(DatasetModel.objects.all()) + + annotate_dataset(datasets) return datasets @@ -82,10 +104,12 @@ async def get_datasets(request, ids: Optional[list[str]] = Query(None)): ) async def get_dataset(request, dataset: str): """Returns a specific dataset""" - return await aget_object_or_404(DatasetModel, id=dataset) + obj = await aget_object_or_404(DatasetModel, id=dataset) + annotate_dataset((obj,)) + return obj -def annotate_neurons_w_dataset_ids(neurons: BaseManager[NeuronModel]) -> None: +def annotate_neurons(neurons: BaseManager[NeuronModel]) -> None: """Queries the datasets ids for each neuron.""" neuron_names = neurons.values_list("name", flat=True).distinct() pre = ( @@ -104,15 +128,18 @@ def annotate_neurons_w_dataset_ids(neurons: BaseManager[NeuronModel]) -> None: for neuron, dataset in pre.union(post): neurons_dataset_ids[neuron].add(dataset) + # Add dataset ids and 3D representation path for neuron in neurons: - neuron.dataset_ids = neurons_dataset_ids[neuron.name] # type: ignore + name = neuron.name + neuron.dataset_ids = neurons_dataset_ids[name] # type: ignore + neuron.model3D_url = settings.NEURON_REPRESENTATION_3D_URL_FORMAT.format(name=name) # type: ignore def neurons_from_datasets( neurons: BaseManager[NeuronModel], dataset_ids: list[str] ) -> BaseManager[NeuronModel]: """Filters neurons belonging to specific datasets.""" - return neurons.filter( + neurons = neurons.filter( Q( name__in=ConnectionModel.objects.filter( dataset__id__in=dataset_ids @@ -124,6 +151,7 @@ def neurons_from_datasets( ).values_list("post", flat=True) ) ) + return neurons @api.get( @@ -134,7 +162,8 @@ def neurons_from_datasets( def get_dataset_neurons(request, dataset: str): """Returns all the neurons of a dedicated dataset""" neurons = neurons_from_datasets(NeuronModel.objects, [dataset]) - annotate_neurons_w_dataset_ids(neurons) + annotate_neurons(neurons) + return neurons @@ -144,17 +173,14 @@ def search_cells( name: Optional[str] = Query(None), dataset_ids: Optional[list[str]] = Query(None), ): - neurons = NeuronModel.objects + neurons = NeuronModel.objects.all() if name: neurons = neurons.filter(name__istartswith=name) if dataset_ids: neurons = neurons_from_datasets(neurons, dataset_ids) - else: - neurons = neurons.all() - - annotate_neurons_w_dataset_ids(neurons) + annotate_neurons(neurons) return neurons @@ -163,15 +189,12 @@ def search_cells( @paginate(PageNumberPagination, page_size=50) # BUG: this is not being applied def get_all_cells(request, dataset_ids: Optional[list[str]] = Query(None)): """Returns all the cells (neurons) from the DB""" - neurons = NeuronModel.objects + neurons = NeuronModel.objects.all() if dataset_ids: neurons = neurons_from_datasets(neurons, dataset_ids) - else: - neurons = neurons.all() - - annotate_neurons_w_dataset_ids(neurons) + annotate_neurons(neurons) return neurons diff --git a/applications/visualizer/backend/api/schemas.py b/applications/visualizer/backend/api/schemas.py index 8124c08c..65e77b39 100644 --- a/applications/visualizer/backend/api/schemas.py +++ b/applications/visualizer/backend/api/schemas.py @@ -1,3 +1,5 @@ +from django.conf import settings + from ninja import ModelSchema, Schema from .models import ( Dataset as DatasetModel, @@ -19,8 +21,24 @@ class Config(Schema.Config): populate_by_name = True +class Artifact(Schema): ... + + +class Model3D(Artifact): ... + + +class EMData(Artifact): + min_zoom: int + max_zoom: int + nb_slices: int + resource_url: str + segmentation_url: str + + class Dataset(ModelSchema, BilingualSchema): id: str + neuron3D_url: str + em_data: EMData class Meta: model = DatasetModel @@ -38,6 +56,7 @@ class Meta: class Neuron(ModelSchema, BilingualSchema): name: str dataset_ids: list[str] + model3D_url: str class Meta: model = NeuronModel diff --git a/applications/visualizer/backend/openapi/openapi.json b/applications/visualizer/backend/openapi/openapi.json index 15f3638d..90d68f86 100644 --- a/applications/visualizer/backend/openapi/openapi.json +++ b/applications/visualizer/backend/openapi/openapi.json @@ -411,6 +411,13 @@ "title": "Id", "type": "string" }, + "neuron3DUrl": { + "title": "Neuron3Durl", + "type": "string" + }, + "emData": { + "$ref": "#/components/schemas/EMData" + }, "collection": { "maxLength": 20, "title": "Collection", @@ -452,6 +459,8 @@ }, "required": [ "id", + "neuron3DUrl", + "emData", "collection", "name", "description", @@ -462,6 +471,39 @@ "title": "Dataset", "type": "object" }, + "EMData": { + "properties": { + "min_zoom": { + "title": "Min Zoom", + "type": "integer" + }, + "max_zoom": { + "title": "Max Zoom", + "type": "integer" + }, + "nb_slices": { + "title": "Nb Slices", + "type": "integer" + }, + "resource_url": { + "title": "Resource Url", + "type": "string" + }, + "segmentation_url": { + "title": "Segmentation Url", + "type": "string" + } + }, + "required": [ + "min_zoom", + "max_zoom", + "nb_slices", + "resource_url", + "segmentation_url" + ], + "title": "EMData", + "type": "object" + }, "ErrorMessage": { "properties": { "detail": { @@ -488,6 +530,10 @@ "title": "Datasetids", "type": "array" }, + "model3DUrl": { + "title": "Model3Durl", + "type": "string" + }, "nclass": { "maxLength": 30, "title": "Nclass", @@ -522,6 +568,7 @@ "required": [ "name", "datasetIds", + "model3DUrl", "nclass", "neurotransmitter", "type" diff --git a/applications/visualizer/backend/requirements.txt b/applications/visualizer/backend/requirements.txt index fcbfde50..dcad7ec7 100644 --- a/applications/visualizer/backend/requirements.txt +++ b/applications/visualizer/backend/requirements.txt @@ -3,4 +3,5 @@ django-cors-headers==4.3.1 django-ninja==1.2.2 uvicorn==0.29.0 ruamel.yaml==0.18.6 -psycopg[binary]==3.1.18 \ No newline at end of file +psycopg[binary]==3.1.18 +Pillow==10.4.0 diff --git a/applications/visualizer/backend/visualizer/settings/__init__.py b/applications/visualizer/backend/visualizer/settings/__init__.py index c1008c70..a87c1815 100644 --- a/applications/visualizer/backend/visualizer/settings/__init__.py +++ b/applications/visualizer/backend/visualizer/settings/__init__.py @@ -1,4 +1,3 @@ -import os from .common import * diff --git a/applications/visualizer/backend/visualizer/settings/common.py b/applications/visualizer/backend/visualizer/settings/common.py index be375610..d29bc555 100644 --- a/applications/visualizer/backend/visualizer/settings/common.py +++ b/applications/visualizer/backend/visualizer/settings/common.py @@ -125,7 +125,7 @@ # # *********************************************************************** # from cloudharness_django.settings import * -# add the local apps +# add the local apps to get access to new custom management commands INSTALLED_APPS += ["api"] # # override django admin base template with a local template @@ -144,3 +144,19 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" NINJA_PAGINATION_PER_PAGE = 100 + +# Fragments for various artifacts +# In this format: {var} is changed by the backend, while the first {{var}} is something that will be changed by the frontend +# NEURON_REPRESENTATION_3D_URL_FORMAT = "resources/{{dataset}}/3d-model/{name}" +# DATASET_NEURON_REPRESENTATION_3D_URL_FORMAT = "resources/{dataset}/3d-model/{{name}}" +# DATASET_EMDATA_URL_FORMAT = "resources/{dataset}/em-data/tiles/{{index}}" +# DATASET_EMDATA_SEGMENTATION_URL_FORMAT = "resources/{dataset}/em-data/segmentation/{{index}}" + + +NEURON_REPRESENTATION_3D_URL_FORMAT = "resources/{{dataset}}/3d-model/{name}" +DATASET_NEURON_REPRESENTATION_3D_URL_FORMAT = "resources/{dataset}/3d-model/{{name}}" +# DATASET_EMDATA_URL_FORMAT = ( +# f"resources/sem-adult/catmaid-tiles/{{index}}/{{x}}_{{y}}_{{z}}.jpg" +# ) +DATASET_EMDATA_URL_FORMAT = f"resources/{{index}}/{{x}}_{{y}}_{{z}}.jpg" +DATASET_EMDATA_SEGMENTATION_URL_FORMAT = f"resources/sem-adult/segmentation-mip0/Dataset8_segmentation_withsoma_Mona_updated_20230127.vsseg_export_s{{index}}.json" diff --git a/applications/visualizer/backend/visualizer/urls.py b/applications/visualizer/backend/visualizer/urls.py index d085b2aa..f2632025 100644 --- a/applications/visualizer/backend/visualizer/urls.py +++ b/applications/visualizer/backend/visualizer/urls.py @@ -21,12 +21,17 @@ from django.conf.urls.static import static from api.api import api -from .views import index, access_bucket_artifact +from .views import index, access_bucket_artifact, get_tile urlpatterns = [ path("admin/", admin.site.urls), path("api/", api.urls), *static(settings.STATIC_URL, document_root=settings.STATIC_ROOT), + re_path( + r"resources/(?P\d+)/(?P\d+)_(?P\d+)_(?P\d+).jpg", + get_tile, + name="em_resources", + ), re_path(r"resources/(?P.+)", access_bucket_artifact, name="resources"), re_path(r"(?P.*)", index, name="index"), ] diff --git a/applications/visualizer/backend/visualizer/views.py b/applications/visualizer/backend/visualizer/views.py index 7b7ac7b8..3e65b6ef 100644 --- a/applications/visualizer/backend/visualizer/views.py +++ b/applications/visualizer/backend/visualizer/views.py @@ -1,18 +1,21 @@ +import io import mimetypes from pathlib import Path from django.conf import settings -from django.http import FileResponse, HttpResponseRedirect +from django.http import FileResponse, HttpResponseRedirect, Http404, HttpResponse from django.shortcuts import redirect from django.urls import reverse from django.utils._os import safe_join +from PIL import Image + def view_404(request, exception=None): return HttpResponseRedirect(reverse("index")) -def index(request, path=""): +def index(request, path="", already_asked=False): if path == "": path = "index.html" fullpath = Path(safe_join(settings.STATIC_ROOT, "www", path)) @@ -21,11 +24,34 @@ def index(request, path=""): try: fullpath.open("rb") except FileNotFoundError: - return index(request, "") # index.html + if already_asked: + # This is here to avoid recursive loop in local dev + return HttpResponse(content=f"Page {path} cannot be found :(", status=404) + return index(request, "", already_asked=True) # index.html return FileResponse(fullpath.open("rb"), content_type=content_type) -def access_bucket_artifact(request, path): +TILE_SIZE = 512 # Should be computed +BLACK_TILE = Image.new("RGB", (TILE_SIZE, TILE_SIZE)) +BLACK_TILE_BUFFER = io.BytesIO() +BLACK_TILE.save(BLACK_TILE_BUFFER, format="JPEG") +MAX_ZOOM = 6 # Should be set + + +def get_tile(request, slice, x, y, zoom): + path = ( + Path("sem-adult") + / "catmaid-tiles" + / f"{slice}" + / f"{y}_{x}_{MAX_ZOOM - int(zoom)}.jpg" + ) + + return access_bucket_artifact( + request, path, unavaiable_page=BLACK_TILE_BUFFER.getbuffer() + ) + + +def access_bucket_artifact(request, path, unavaiable_page=None): resource_folder = Path(settings.GCS_BUCKET_URL) if resource_folder.exists(): full_path = resource_folder / path @@ -34,6 +60,8 @@ def access_bucket_artifact(request, path): try: return FileResponse(full_path.open("rb"), content_type=content_type) except FileNotFoundError: + if unavaiable_page: + return FileResponse(unavaiable_page, content_type=content_type) return index(request, "") # index.html - return redirect(f"{settings.GCS_BUCKET_URL}/{path}") + return redirect(f"{settings.GCS_BUCKET_URL}/{path}", permanent=True) diff --git a/applications/visualizer/frontend/package.json b/applications/visualizer/frontend/package.json index 4078cf7b..68dea0a4 100644 --- a/applications/visualizer/frontend/package.json +++ b/applications/visualizer/frontend/package.json @@ -12,7 +12,7 @@ "lint-fix": "biome lint --write .", "generate-client": "openapi --input ../backend/openapi/openapi.json --output ./src/rest --useOptions --useUnionTypes --client xhr", "start": "DOMAIN=http://localhost:8000 vite", - "start:dev": "DOMAIN=https://visualizer.celegans.metacell.us vite", + "start:dev": "DOMAIN=https://celegans.dev.metacell.us vite", "start:local": "DOMAIN=http://visualizer.celegans.local vite" }, "dependencies": { @@ -27,12 +27,11 @@ "@react-three/drei": "^9.105.4", "@react-three/fiber": "^8.16.2", "@reduxjs/toolkit": "^2.2.3", - "@types/cytoscape": "^3.21.1", - "@types/three": "^0.166.0", - "cytoscape": "^3.29.2", + "cytoscape": "^3.30.2", "cytoscape-dagre": "^2.5.0", "cytoscape-fcose": "^2.2.0", "file-saver": "^2.0.5", + "ol": "^9.1.0", "react": "^18.3.1", "react-color": "^2.19.3", "react-dom": "^18.3.1", @@ -41,12 +40,14 @@ }, "devDependencies": { "@biomejs/biome": "1.8.3", - "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@types/cytoscape": "^3.21.5", + "@types/three": "^0.166.0", "@vitejs/plugin-react": "^4.2.1", "openapi-typescript-codegen": "^0.29.0", "sass": "^1.75.0", "typescript": "^5.2.2", - "vite": "^5.2.0" + "vite": "^5.4.0" } } diff --git a/applications/visualizer/frontend/src/App.css b/applications/visualizer/frontend/src/App.css index 0cf1e1e2..54d71849 100644 --- a/applications/visualizer/frontend/src/App.css +++ b/applications/visualizer/frontend/src/App.css @@ -6,5 +6,5 @@ display: flex; flex-direction: column; height: 100vh; - overflow: hidden; + overflow: auto; } diff --git a/applications/visualizer/frontend/src/App.tsx b/applications/visualizer/frontend/src/App.tsx index 5077ec5c..e85ea373 100644 --- a/applications/visualizer/frontend/src/App.tsx +++ b/applications/visualizer/frontend/src/App.tsx @@ -3,33 +3,54 @@ import { ThemeProvider } from "@mui/material/styles"; import { Provider } from "react-redux"; import theme from "./theme/index.tsx"; import "./App.css"; +import React from "react"; import AppLauncher from "./components/AppLauncher.tsx"; +import Layout from "./components/ViewerContainer/Layout.tsx"; import WorkspaceComponent from "./components/WorkspaceComponent.tsx"; +import CompareWrapper from "./components/wrappers/Compare.tsx"; +import DefaultWrapper from "./components/wrappers/Default.tsx"; import { useGlobalContext } from "./contexts/GlobalContext.tsx"; import { ViewMode } from "./models"; function App() { const { workspaces, currentWorkspaceId, viewMode, selectedWorkspacesIds } = useGlobalContext(); + const [sidebarOpen, setSidebarOpen] = React.useState(true); const hasLaunched = currentWorkspaceId !== undefined; + const renderCompareMode = (workspaceIds: string[]) => ( + + {workspaceIds.map((id) => ( + + + + ))} + + ); + + const renderDefaultMode = (currentWorkspaceId: string) => ( + + + + + + ); + + const renderWorkspaces = () => { + if (viewMode === ViewMode.Compare) { + return renderCompareMode(Array.from(selectedWorkspacesIds)); + } + return renderDefaultMode(currentWorkspaceId as string); + }; + return ( <> {hasLaunched ? ( - {viewMode === ViewMode.Compare ? ( - Array.from(selectedWorkspacesIds).map((id) => ( - - - - )) - ) : ( - - - - )} + + {renderWorkspaces()} ) : ( diff --git a/applications/visualizer/frontend/src/components/AppLauncher.tsx b/applications/visualizer/frontend/src/components/AppLauncher.tsx index be2a10bb..4c1a966b 100644 --- a/applications/visualizer/frontend/src/components/AppLauncher.tsx +++ b/applications/visualizer/frontend/src/components/AppLauncher.tsx @@ -3,24 +3,24 @@ import footerImage from "../assets/summary-neurons.png"; import { useGlobalContext } from "../contexts/GlobalContext.tsx"; import { parseURLParams } from "../helpers/parseURLHelper.ts"; import { TEMPLATE_ACTIVE_DATASETS, TEMPLATE_ACTIVE_NEURONS } from "../settings/templateWorkspaceSettings.ts"; - function AppLauncher() { - const { workspaces, createWorkspace, setCurrentWorkspace } = useGlobalContext(); + const { workspaces, createWorkspace, setCurrentWorkspace, setSelectedWorkspacesIds } = useGlobalContext(); const handleTemplateClick = async () => { const workspaceId = `workspace-${Date.now()}`; const workspaceName = `Template Workspace ${Object.keys(workspaces).length + 1}`; - createWorkspace(workspaceId, workspaceName, new Set(TEMPLATE_ACTIVE_DATASETS), new Set(TEMPLATE_ACTIVE_NEURONS)); setCurrentWorkspace(workspaceId); + setSelectedWorkspacesIds(new Set([workspaceId])); }; const handleBlankClick = () => { const workspaceId = `workspace-${Date.now()}`; const workspaceName = `Workspace ${Object.keys(workspaces).length + 1}`; - createWorkspace(workspaceId, workspaceName); + createWorkspace(workspaceId, workspaceName, new Set(TEMPLATE_ACTIVE_DATASETS)); setCurrentWorkspace(workspaceId); + setSelectedWorkspacesIds(new Set([workspaceId])); }; const handlePasteUrlClick = () => { @@ -29,7 +29,6 @@ function AppLauncher() { const parsedParams = parseURLParams(exampleURL); console.log(parsedParams); }; - return ( <> diff --git a/applications/visualizer/frontend/src/components/CreateNewWorkspaceDialog.tsx b/applications/visualizer/frontend/src/components/CreateNewWorkspaceDialog.tsx new file mode 100644 index 00000000..89c8155d --- /dev/null +++ b/applications/visualizer/frontend/src/components/CreateNewWorkspaceDialog.tsx @@ -0,0 +1,177 @@ +import { Box, Button, FormLabel, IconButton, TextField, Typography } from "@mui/material"; +import { debounce } from "lodash"; +import { useCallback, useState } from "react"; +import { v4 as uuidv4 } from "uuid"; +import { useGlobalContext } from "../contexts/GlobalContext.tsx"; +import { CaretIcon, CheckIcon, CloseIcon } from "../icons"; +import { type Dataset, type Neuron, NeuronsService } from "../rest"; +import { vars as colors } from "../theme/variables.ts"; +import CustomAutocomplete from "./CustomAutocomplete.tsx"; +import CustomDialog from "./CustomDialog.tsx"; + +const CreateNewWorkspaceDialog = ({ onCloseCreateWorkspace, showCreateWorkspaceDialog, isCompareMode, title, subTitle, submitButtonText }) => { + const [neurons, setNeurons] = useState([]); + const { workspaces, datasets, createWorkspace, setSelectedWorkspacesIds } = useGlobalContext(); + const [searchedNeuron, setSearchedNeuron] = useState(""); + const [formValues, setFormValues] = useState<{ + workspaceName: string; + selectedDatasets: Dataset[]; + selectedNeurons: Neuron[]; + }>({ + workspaceName: "", + selectedDatasets: [], + selectedNeurons: [], + }); + + const [errorMessage, setErrorMessage] = useState(""); + + const workspaceFieldName = "workspaceName"; + const fetchNeurons = async (name, datasetsIds) => { + try { + const Ids = datasetsIds.map((dataset) => dataset.id); + const response = await NeuronsService.searchCells({ + name: name, + datasetIds: Ids, + }); + setNeurons(response); + } catch (error) { + console.error("Failed to fetch datasets", error); + } + }; + + const debouncedFetchNeurons = useCallback(debounce(fetchNeurons, 300), []); + const onSearchNeurons = (value) => { + setSearchedNeuron(value); + debouncedFetchNeurons(value, formValues.selectedDatasets); + }; + const handleInputChange = (event) => { + const { name, value } = event.target; + setFormValues({ ...formValues, [name]: value }); + if (name === workspaceFieldName && errorMessage) { + setErrorMessage(""); + } + }; + + const handleDatasetChange = (value) => { + setFormValues({ ...formValues, selectedDatasets: value }); + debouncedFetchNeurons(searchedNeuron, value); + }; + + const handleNeuronChange = (value) => { + setFormValues({ ...formValues, selectedNeurons: value }); + }; + + const isWorkspaceNameDuplicate = (name) => { + return Object.values(workspaces).some((workspace) => workspace.name === name); + }; + + const handleSubmit = () => { + if (!formValues.workspaceName.trim()) { + setErrorMessage("Workspace name is required!"); + return; + } + + if (isWorkspaceNameDuplicate(formValues.workspaceName.trim())) { + setErrorMessage("Workspace name already exists!"); + return; + } + + const randomNumber = uuidv4().replace(/\D/g, "").substring(0, 13); + const newWorkspaceId = `workspace-${randomNumber}`; + const activeNeurons = new Set(formValues.selectedNeurons.map((neuron) => neuron.name)); + const activeDatasets = new Set(formValues.selectedDatasets.map((dataset) => dataset.id)); + createWorkspace(newWorkspaceId, formValues.workspaceName, activeDatasets, activeNeurons); + + if (isCompareMode) { + const updatedWorkspaces = new Set([...Object.keys(workspaces), newWorkspaceId]); + setSelectedWorkspacesIds(updatedWorkspaces); + } + onCloseCreateWorkspace(); + }; + const datasetsArray = Object.values(datasets); + + return ( + + + {subTitle && {subTitle}} + + + Workspace name (REQUIRED) + + + + + + Datasets + option.name} + renderOption={(props, option) => ( +
  • + + {option.name} +
  • + )} + placeholder="Start typing to search" + id="grouped-demo" + popupIcon={} + ChipProps={{ + deleteIcon: ( + + + + ), + }} + value={formValues.selectedDatasets} + onChange={handleDatasetChange} + /> +
    + + Neurons + option.name} + renderOption={(props, option) => ( +
  • + + {option.name} +
  • + )} + onInputChange={onSearchNeurons} + placeholder="Start typing to search" + className="secondary" + id="tags-standard" + popupIcon={} + disabled={formValues.selectedDatasets.length === 0} + ChipProps={{ + deleteIcon: ( + + + + ), + }} + clearIcon={false} + value={formValues.selectedNeurons} + onChange={handleNeuronChange} + /> +
    +
    + + + +
    + ); +}; + +export default CreateNewWorkspaceDialog; diff --git a/applications/visualizer/frontend/src/components/CustomAutocomplete.tsx b/applications/visualizer/frontend/src/components/CustomAutocomplete.tsx index 4730ba65..bfda7929 100644 --- a/applications/visualizer/frontend/src/components/CustomAutocomplete.tsx +++ b/applications/visualizer/frontend/src/components/CustomAutocomplete.tsx @@ -15,10 +15,14 @@ interface CustomAutocompleteProps { id: string; multiple?: boolean; popupIcon: React.ReactNode; - clearIcon?: React.ReactNode; // Change to React.ReactNode to be consistent with popupIcon + clearIcon?: React.ReactNode; ChipProps?: ChipProps; sx?: SxProps; componentsProps?: AutocompleteProps["componentsProps"]; + value?: any; + onChange: (v) => void; + disabled?: boolean; + onInputChange?: (v) => void; } const CommonAutocomplete = ({ @@ -35,13 +39,24 @@ const CommonAutocomplete = ({ clearIcon, ChipProps, sx = {}, + value, componentsProps = {}, + onChange, + disabled = false, + onInputChange, }: CustomAutocompleteProps) => { + // @ts-ignore return ( { + event.preventDefault(); + onChange(value); + }} clearIcon={clearIcon} options={options} popupIcon={popupIcon} @@ -50,7 +65,7 @@ const CommonAutocomplete = ({ groupBy={groupBy} renderGroup={renderGroup} renderOption={renderOption} - renderInput={(params) => } + renderInput={(params) => onInputChange(e.target.value)} />} sx={sx} componentsProps={componentsProps} /> diff --git a/applications/visualizer/frontend/src/components/CustomDialog.tsx b/applications/visualizer/frontend/src/components/CustomDialog.tsx new file mode 100644 index 00000000..01286630 --- /dev/null +++ b/applications/visualizer/frontend/src/components/CustomDialog.tsx @@ -0,0 +1,38 @@ +import { Box, Dialog, IconButton, Typography } from "@mui/material"; +import type React from "react"; +import { CloseIcon } from "../icons"; +import { vars } from "../theme/variables.ts"; + +const { gray100 } = vars; +interface CustomDialogProps { + onClose: () => void; + showModal: boolean; + title: string; + children: React.ReactNode; +} + +const CustomDialog = ({ onClose, showModal, title, children }: CustomDialogProps) => { + return ( + + + {title} + + + + + {children} + + ); +}; + +export default CustomDialog; diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/ColorPicker.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/ColorPicker.tsx index 14db4d44..b2dbaf61 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/ColorPicker.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/ColorPicker.tsx @@ -1,4 +1,4 @@ -import Box from "@mui/material/Box"; +import { Box } from "@mui/material"; import ChromePicker from "react-color"; const ColorPicker = ({ selectedColor, onChange }) => { diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/CompareWorkspaceDialog.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/CompareWorkspaceDialog.tsx deleted file mode 100644 index 40daec1b..00000000 --- a/applications/visualizer/frontend/src/components/ViewerContainer/CompareWorkspaceDialog.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import { Box, Button, Dialog, FormLabel, IconButton, TextField, Typography } from "@mui/material"; -import { useEffect, useState } from "react"; -import { CaretIcon, CheckIcon, CloseIcon } from "../../icons"; -import { type Dataset, type Neuron, NeuronsService } from "../../rest"; -import { vars as colors } from "../../theme/variables.ts"; -import CustomAutocomplete from "../CustomAutocomplete.tsx"; - -interface CompareWorkspaceDialogProps { - onClose: () => void; - showModal: boolean; - datasets: Dataset[]; -} - -const CompareWorkspaceDialog = ({ onClose, showModal, datasets }: CompareWorkspaceDialogProps) => { - const [neurons, setNeurons] = useState([]); - - const fetchNeurons = async () => { - try { - const response = await NeuronsService.getAllCells({ page: 1 }); - setNeurons(response.items); - } catch (error) { - console.error("Failed to fetch datasets", error); - } - }; - - useEffect(() => { - fetchNeurons(); - }, []); - - return ( - - - New workspace configuration - - - - - - - To start comparing, create workspace by configuring datasets and neurons you would want in the new workspace or start with an empty workspace. - - - Workspace name - - - - - Datasets - - options={datasets} - getOptionLabel={(option) => option.name} - renderOption={(props, option) => ( -
  • - - {option.name} -
  • - )} - placeholder="Start typing to search" - id="grouped-demo" - popupIcon={} - ChipProps={{ - deleteIcon: ( - - - - ), - }} - /> -
    - - - Neurons - - options={neurons} - getOptionLabel={(option) => option.name} - renderOption={(props, option) => ( -
  • - - {option.name} -
  • - )} - placeholder="Start typing to search" - className="secondary" - id="tags-standard" - popupIcon={} - ChipProps={{ - deleteIcon: ( - - - - ), - }} - clearIcon={false} - /> -
    -
    - - - - - -
    - ); -}; - -export default CompareWorkspaceDialog; diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/CustomEntitiesDropdown.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/CustomEntitiesDropdown.tsx index be94bdea..051327e8 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/CustomEntitiesDropdown.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/CustomEntitiesDropdown.tsx @@ -1,9 +1,11 @@ -import type React from "react"; -import { useState } from "react"; -import { Box, Typography, Popper, TextField, InputAdornment, ClickAwayListener } from "@mui/material"; -import SearchIcon from "@mui/icons-material/Search"; import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; +import SearchIcon from "@mui/icons-material/Search"; +import { Box, InputAdornment, Popper, TextField, Typography } from "@mui/material"; +import type React from "react"; +import { useEffect, useRef, useState } from "react"; +import { CheckIcon } from "../../icons"; import { vars } from "../../theme/variables.ts"; +import type { EnhancedNeuron } from "../../models/models.ts"; const { gray50, brand600 } = vars; @@ -20,188 +22,204 @@ type Option = { interface CustomEntitiesDropdownProps { options: Option[]; - onSelect: (option: Option) => void; + activeNeurons: Set; + onNeuronClick?: (neuron: Option) => void; + onSearchNeurons?: (value: string) => void; + setNeurons?: (neurons: Record) => void; + availableNeurons: Record; } -const CustomEntitiesDropdown: React.FC = ({ options, onSelect }) => { +const CustomEntitiesDropdown = ({ options, activeNeurons, onNeuronClick, onSearchNeurons, setNeurons, availableNeurons }: CustomEntitiesDropdownProps) => { const [anchorEl, setAnchorEl] = useState(null); const [hoveredOption, setHoveredOption] = useState
    + + ); }; diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx index 6bad2aaf..9da39502 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/CustomListItem.tsx @@ -1,17 +1,39 @@ +import { Add as AddIcon, DeleteOutlined as DeleteOutlinedIcon, HelpOutline as HelpOutlineIcon } from "@mui/icons-material"; +import { Box, FormControlLabel, IconButton, Stack, Tooltip, Typography } from "@mui/material"; import { useState } from "react"; -import { Box, Stack, Typography, IconButton, Tooltip, FormControlLabel } from "@mui/material"; -import { HelpOutline as HelpOutlineIcon, DeleteOutlined as DeleteOutlinedIcon, Add as AddIcon } from "@mui/icons-material"; +import { vars } from "../../theme/variables.ts"; import CustomSwitch from "./CustomSwitch"; import PickerWrapper from "./PickerWrapper"; -import { vars } from "../../theme/variables.ts"; const { gray600, gray400B, gray500, gray50, error700 } = vars; -const CustomListItem = ({ data, showTooltip = true, listType, showExtraActions = false, onSwitchChange }) => { +interface CustomListItemProps { + data: { + id: string; + label: string; + checked: boolean; + helpText?: string; + description?: string; + }; + showTooltip?: boolean; + listType: string; + showExtraActions?: boolean; + onSwitchChange?: (id: string, checked: boolean) => void; + onDelete?: (id: string) => void; + deleteTooltipTitle?: string; +} +const CustomListItem = ({ + data, + showTooltip = true, + listType, + showExtraActions = false, + onSwitchChange, + onDelete, + deleteTooltipTitle, +}: CustomListItemProps) => { const [anchorEl, setAnchorEl] = useState(null); const [open, setOpen] = useState(false); const [selectedColor, setSelectedColor] = useState("#9FEE9A"); const [itemHovered, setItemHovered] = useState(false); - const isNeurons = listType === "neurons"; const handleSwitchChange = (_: React.ChangeEvent, checked: boolean) => { @@ -44,6 +66,13 @@ const CustomListItem = ({ data, showTooltip = true, listType, showExtraActions = setItemHovered(false); }; + const handleDeleteNeuron = (event) => { + event.stopPropagation(); + if (onDelete) { + onDelete(data.id); + } + }; + return ( <> - + diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/CustomSwitch.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/CustomSwitch.tsx index 9cbf4256..8fc8fda7 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/CustomSwitch.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/CustomSwitch.tsx @@ -17,18 +17,12 @@ interface CustomSwitchProps { } const CustomSwitch: React.FC = ({ width, height, thumbDimension, checkedPosition, checked, onChange, showTooltip, disabled }) => { - const handleChange = (event: React.ChangeEvent) => { - if (onChange) { - onChange(event, event.target.checked); - } - }; - return ( ({ marginRight: ".5rem", diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/DataSets.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/DataSets.tsx index 2fbcd6ce..0bd2a3dc 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/DataSets.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/DataSets.tsx @@ -1,30 +1,33 @@ -import { Box, Stack, Typography, MenuItem, FormControl, IconButton, Select } from "@mui/material"; -import { vars } from "../../theme/variables.ts"; -import CustomEntitiesDropdown from "./CustomEntitiesDropdown.tsx"; -import CustomListItem from "./CustomListItem.tsx"; +import { CloseOutlined, LayersOutlined } from "@mui/icons-material"; import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; -import FilterListIcon from "@mui/icons-material/FilterList"; +import SearchIcon from "@mui/icons-material/Search"; +import { Box, FormControl, IconButton, InputAdornment, Menu, MenuItem, Snackbar, Stack, TextField, Typography } from "@mui/material"; +import Select from "@mui/material/Select"; +import React, { useEffect, useMemo, useState } from "react"; import { useGlobalContext } from "../../contexts/GlobalContext.tsx"; +import { CheckIcon } from "../../icons"; import type { Dataset } from "../../rest"; +import { vars } from "../../theme/variables.ts"; +import CustomListItem from "./CustomListItem.tsx"; -const { gray900, gray500, gray400 } = vars; +const { gray900, gray500, gray400, gray100, gray600 } = vars; // Categorize datasets based on their visualTime const categorizeDatasets = (datasets: Dataset[]) => { const categories = { - "Development stage 1": [], - "Development stage 2": [], - "Development stage 3": [], + L1: [], + L2: [], + L3: [], Adult: [], }; datasets.forEach((dataset) => { if (dataset.visualTime >= 0 && dataset.visualTime < 10) { - categories["Development stage 1"].push(dataset); + categories["L1"].push(dataset); } else if (dataset.visualTime >= 10 && dataset.visualTime < 20) { - categories["Development stage 2"].push(dataset); + categories["L2"].push(dataset); } else if (dataset.visualTime >= 20 && dataset.visualTime < 30) { - categories["Development stage 3"].push(dataset); + categories["L3"].push(dataset); } else if (dataset.visualTime >= 30) { categories["Adult"].push(dataset); } @@ -42,59 +45,219 @@ const mapDatasetToListItem = (dataset: Dataset, isActive: boolean) => ({ helpText: dataset.collection, }); -const DataSets = () => { +const DataSets = ({ children }) => { const { datasets, workspaces, currentWorkspaceId } = useGlobalContext(); const currentWorkspace = workspaces[currentWorkspaceId]; const activeDatasets = currentWorkspace.activeDatasets; - // Categorize the datasets - const categorizedDatasets = categorizeDatasets(datasets); + const categorizedDatasets = categorizeDatasets(Object.values(datasets)); + + const [searchInput, setSearchInput] = useState(""); + const [filteredDatasets, setFilteredDatasets] = useState(categorizedDatasets); + const [filterGroupsValue, setFilterGroupsValue] = useState("All"); + + const activeDatasetsList = useMemo(() => Object.values(datasets).filter((dataset) => activeDatasets[dataset.id]), [datasets, activeDatasets]); + + const [filterActiveDatasets, setFilterActiveDatasets] = useState(activeDatasetsList); + + const [selectedType, setSelectedType] = useState(null); - // Handle activation and deactivation of datasets + const [showAlert, setShowAlert] = useState(false); + + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + + const handleMenuOpen = (event) => { + setAnchorEl(event.currentTarget); + }; + + const handleMenuClose = () => { + setAnchorEl(null); + }; const handleSwitchChange = async (datasetId: string, checked: boolean) => { - const dataset = datasets.find((ds) => ds.id === datasetId); + const dataset = Object.values(datasets).find((ds) => ds.id === datasetId); if (!dataset) return; if (checked) { await currentWorkspace.activateDataset(dataset); } else { + if (activeDatasetsList?.length === 1) { + setShowAlert(true); + return; + } await currentWorkspace.deactivateDataset(dataset.id); } }; + const handleSearchChange = (event) => { + const inputValue = event.target.value.toLowerCase(); + setSearchInput(inputValue); + + const filteredCategories = { + L1: [], + L2: [], + L3: [], + Adult: [], + }; + + for (const [category, datasets] of Object.entries(categorizedDatasets)) { + filteredCategories[category] = datasets.filter((dataset) => dataset.name.toLowerCase().includes(inputValue)); + } + + const filteredActiveList = inputValue ? activeDatasetsList.filter((dataset) => dataset.name.toLowerCase().includes(inputValue)) : activeDatasetsList; + + setFilteredDatasets(filteredCategories); + setFilterActiveDatasets(filteredActiveList); + }; + + const onSelectGroupChange = (e) => { + const selectedGroup = e.target.value; + setFilterGroupsValue(selectedGroup); + + if (selectedGroup === "All") { + setFilteredDatasets(categorizedDatasets); + setFilterActiveDatasets(activeDatasetsList); + } else { + const activeGroup = categorizedDatasets[selectedGroup]; + // @ts-ignore + setFilteredDatasets({ + [`${selectedGroup}`]: activeGroup, + }); + + const filteredActive = activeDatasetsList.filter((dataset) => { + return activeGroup.some((catDataset) => catDataset.id === dataset.id); + }); + setFilterActiveDatasets(filteredActive); + } + }; + + const getDatasetsTypes = (datasets: { [key: string]: Dataset }) => { + const types = new Set(); + Object.values(datasets).forEach((dataset) => { + if (dataset.type) { + types.add(dataset.type); + } + }); + return Array.from(types); + }; + + const handleTypeSelect = (type: string) => { + const newSelectedType = selectedType === type ? null : type; + setSelectedType(newSelectedType); + + const filteredCategories = { + L1: [], + L2: [], + L3: [], + Adult: [], + }; + + for (const [category, datasets] of Object.entries(categorizedDatasets)) { + filteredCategories[category] = datasets.filter((dataset) => newSelectedType === null || dataset.type === newSelectedType); + } + + const filteredActiveList = activeDatasetsList.filter((dataset) => newSelectedType === null || dataset.type === newSelectedType); + + setFilteredDatasets(filteredCategories); + setFilterActiveDatasets(filteredActiveList); + }; + + useEffect(() => { + if (filterGroupsValue === "All") { + setFilterActiveDatasets(activeDatasetsList); + } else { + const activeGroup = categorizedDatasets[filterGroupsValue]; + const filteredActive = activeGroup.filter((dataset) => activeDatasets[dataset.id]); + setFilterActiveDatasets(filteredActive); + } + }, [activeDatasetsList, filterGroupsValue]); + + const datasetsTypes = getDatasetsTypes(datasets); + + const action = ( + + setShowAlert(false)} + sx={{ + "&:hover": { + backgroundColor: "transparent", + }, + }} + > + + + + ); + return ( Datasets + Toggle on and off to view datasets on the workspace. This will affect all viewers. - {}} /> + {children} + + + + ), + }} + sx={{ + mb: "1rem", + "& .MuiOutlinedInput-root": { + padding: "1rem 2rem 1rem 0.75rem", + borderRadius: 0, + "&.Mui-focused .MuiOutlinedInput-notchedOutline": { + borderColor: gray100, + boxShadow: "none", + }, + "& .MuiInputBase-input": { + color: gray600, + fontWeight: 500, + }, + "& .MuiOutlinedInput-notchedOutline": { + borderLeft: "none", + borderRight: "none", + }, + }, + }} + /> + - - + + + + {datasetsTypes.map((type, i) => ( + handleTypeSelect(type)}> + + + + + {type} + + + ))} + { overflow: "auto", }} > - {Object.entries(categorizedDatasets).map(([category, datasets], index) => ( - - - {category} - - - {datasets.map((dataset) => ( - + + + {filterActiveDatasets.length > 0 && ( + + + Active Datasets + + + {filterActiveDatasets.map((dataset) => ( + + ))} + + + )} + + {/* Filtered Datasets Group */} + {Object.entries(filteredDatasets) + .filter(([_, datasets]) => datasets.length > 0) // Filter out empty categories + .map(([category, datasets], index) => ( + + + {category} + + + {datasets.map((dataset) => ( + + ))} + + ))} - - - ))} + + + setShowAlert(false)} + anchorOrigin={{ vertical: "top", horizontal: "center" }} + message={"You have to have at least 1 active dataset."} + action={action} + autoHideDuration={6000} + /> ); }; diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/Header.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/Header.tsx index 60f98bea..4a1aa667 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/Header.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/Header.tsx @@ -1,10 +1,12 @@ import { AppBar, Box, Button, ButtonGroup, IconButton, Menu, MenuItem, Toolbar, Tooltip, Typography } from "@mui/material"; import type { Theme } from "@mui/material/styles"; -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { useGlobalContext } from "../../contexts/GlobalContext.tsx"; import { CiteIcon, ConnectionsIcon, ContactIcon, ContributeIcon, DataSourceIcon, DownloadIcon, MoreOptionsIcon, TourIcon } from "../../icons"; +import { ViewMode } from "../../models"; import { vars } from "../../theme/variables.ts"; -import CompareWorkspaceDialog from "./CompareWorkspaceDialog.tsx"; +import CreateNewWorkspaceDialog from "../CreateNewWorkspaceDialog.tsx"; + const { gray100 } = vars; const MENU_ARR = [ @@ -87,8 +89,9 @@ const Header = ({ const [active, setActive] = useState(0); const [showModal, setShowModal] = useState(false); const [anchorEl, setAnchorEl] = React.useState(null); + const { workspaces, setSelectedWorkspacesIds, setViewMode, selectedWorkspacesIds, viewMode, setCurrentWorkspace } = useGlobalContext(); + const open = Boolean(anchorEl); - const { datasets } = useGlobalContext(); const handleClick = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; @@ -96,23 +99,41 @@ const Header = ({ setAnchorEl(null); }; - const onClick = (index: number) => { + const updateActiveState = (index: number) => { setActive(index); - switch (index) { - case 1: + if (index === 1) { + if (Object.keys(workspaces).length >= 2) { + const selectedWorkspaces = new Set(Object.keys(workspaces).slice(0, 2)); + setSelectedWorkspacesIds(selectedWorkspaces); + } else { setShowModal(true); - break; - default: - setShowModal(false); + } + } else { + const selectedWorkspaces = new Set(Object.keys(workspaces).slice(0, 1)); + setSelectedWorkspacesIds(selectedWorkspaces); + setCurrentWorkspace(Array.from(selectedWorkspaces)[0]); } }; + const onClick = (_: React.MouseEvent, index: number) => { + updateActiveState(index); + }; const onClose = () => { setShowModal(false); - setActive(0); + const newIndex = Array.from(selectedWorkspacesIds).length >= 2 ? 1 : 0; + setActive(newIndex); }; + useEffect(() => { + const newIndex = Array.from(selectedWorkspacesIds).length >= 2 ? 1 : 0; + setActive(newIndex); + if (newIndex === 0) { + setViewMode(ViewMode.Default); + } else { + setViewMode(ViewMode.Compare); + } + }, [selectedWorkspacesIds]); return ( <> { return ( - @@ -164,9 +185,11 @@ const Header = ({ - + {viewMode === ViewMode.Default && ( + + )} - - + {showModal && ( + + )} ); }; diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/Layout.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/Layout.tsx index a9d08dd7..0851083b 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/Layout.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/Layout.tsx @@ -1,4 +1,3 @@ -import CssBaseline from "@mui/material/CssBaseline"; import Header from "./Header.tsx"; import Sidebar from "./Sidebar.tsx"; @@ -13,7 +12,6 @@ const Layout = ({ }) => { return ( <> -
    diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx index 6b3f0b33..ba766c77 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/Neurons.tsx @@ -1,86 +1,146 @@ -import { Box, IconButton, Stack, Typography, Tooltip } from "@mui/material"; +import AddIcon from "@mui/icons-material/Add"; +import { Box, IconButton, Stack, Typography } from "@mui/material"; +import Tooltip from "@mui/material/Tooltip"; +import { debounce } from "lodash"; +import { useCallback, useState } from "react"; +import { useGlobalContext } from "../../contexts/GlobalContext.tsx"; +import type { Neuron } from "../../rest"; +import { NeuronsService } from "../../rest"; import { vars } from "../../theme/variables.ts"; import CustomEntitiesDropdown from "./CustomEntitiesDropdown.tsx"; import CustomListItem from "./CustomListItem.tsx"; -import AddIcon from "@mui/icons-material/Add"; -import { useGlobalContext } from "../../contexts/GlobalContext.tsx"; +import type { EnhancedNeuron } from "../../models/models.ts"; const { gray900, gray500 } = vars; +const mapNeuronsToListItem = (neuron: string, isActive: boolean) => ({ + id: neuron, + label: neuron, + checked: isActive, +}); +const mapNeuronsAvailableNeuronsToOptions = (neuron: Neuron) => ({ + id: neuron.name, + label: neuron.name, + content: [], +}); -const Neurons = () => { - const { workspaces, currentWorkspaceId } = useGlobalContext(); +const Neurons = ({ children }) => { + const { workspaces, datasets, currentWorkspaceId } = useGlobalContext(); const currentWorkspace = workspaces[currentWorkspaceId]; const activeNeurons = currentWorkspace.activeNeurons; + const recentNeurons = Object.values(currentWorkspace.availableNeurons).filter((neuron) => neuron.isInteractant); const availableNeurons = currentWorkspace.availableNeurons; - // Transform available neurons to options for CustomEntitiesDropdown - const neuronOptions = Object.values(availableNeurons).map((neuron) => ({ - id: neuron.name, - label: neuron.name, - content: [ - { title: "Class", value: neuron.nclass }, - { title: "Neurotransmitter", value: neuron.neurotransmitter }, - { title: "Type", value: neuron.type }, - ], - })); + const [neurons, setNeurons] = useState(availableNeurons); - // Transform active neurons data to the format expected by CustomListItem - const neuronList = activeNeurons - ? Array.from(activeNeurons).map((neuronName) => { - const neuron = availableNeurons[neuronName]; - return { - id: neuron.name, - label: neuron.name, - checked: true, - }; - }) - : []; + const handleSwitchChange = async (neuronId: string, checked: boolean) => { + const neuron = availableNeurons[neuronId]; - // Handle activation and deactivation of neurons - const handleSwitchChange = (neuronName: string, checked: boolean) => { - const neuron = availableNeurons[neuronName]; if (!neuron) return; - if (checked) { - currentWorkspace.activateNeuron(neuron); + await currentWorkspace.activateNeuron(neuron); } else { - currentWorkspace.deactivateNeuron(neuronName); + await currentWorkspace.deactivateNeuron(neuronId); } }; - // Handle neuron selection from CustomEntitiesDropdown - const handleNeuronSelect = (option) => { + const onNeuronClick = (option) => { const neuron = availableNeurons[option.id]; - if (neuron) { + if (neuron && !activeNeurons.has(option.id)) { currentWorkspace.activateNeuron(neuron); + } else { + currentWorkspace.deleteNeuron(option.id); + } + }; + const handleDeleteNeuron = (neuronId: string) => { + currentWorkspace.deleteNeuron(neuronId); + }; + + const fetchNeurons = async (name: string, datasetsIds: { id: string }[]) => { + try { + const ids = datasetsIds.map((dataset) => dataset.id); + const response = await NeuronsService.searchCells({ name: name, datasetIds: ids }); + + // Convert the object to a Record + const neuronsRecord = Object.entries(response).reduce((acc: Record, [_, neuron]: [string, EnhancedNeuron]) => { + acc[neuron.name] = neuron; + return acc; + }, {}); + + setNeurons(neuronsRecord); + } catch (error) { + console.error("Failed to fetch datasets", error); } }; + const debouncedFetchNeurons = useCallback(debounce(fetchNeurons, 300), []); + + const onSearchNeurons = (value) => { + const datasetsIds = Object.keys(datasets); + debouncedFetchNeurons(value, datasetsIds); + }; + + const autoCompleteOptions = Object.values(neurons).map((neuron: Neuron) => mapNeuronsAvailableNeuronsToOptions(neuron)); + return ( - + Neurons + Search for the neurons and add it to your workspace. This will affect all viewers. - - + {children} + + - Active neurons + All Neurons - + - {neuronList.map((item) => ( - + {Array.from(recentNeurons).map((neuron) => ( + ))} diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/Sidebar.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/Sidebar.tsx index 4ae7a835..c6094bd7 100644 --- a/applications/visualizer/frontend/src/components/ViewerContainer/Sidebar.tsx +++ b/applications/visualizer/frontend/src/components/ViewerContainer/Sidebar.tsx @@ -1,11 +1,14 @@ -import { Box, Drawer, Stack } from "@mui/material"; +import { Box, Divider, Drawer, Stack } from "@mui/material"; import IconButton from "@mui/material/IconButton"; import type { CSSObject, Theme } from "@mui/material/styles"; -import { useState } from "react"; +import React, { useState } from "react"; +import { useGlobalContext } from "../../contexts/GlobalContext.tsx"; import { DataSetsIcon, NeuronsIcon, SidebarExpandIcon } from "../../icons"; +import { ViewMode } from "../../models"; import { vars } from "../../theme/variables.ts"; import DataSets from "./DataSets.tsx"; import Neurons from "./Neurons.tsx"; +import WorkspaceSelector from "./WorkspaceSelector"; const { gray100, white, gray200, gray50, buttonShadow } = vars; @@ -76,7 +79,24 @@ const Sidebar = ({ drawerHeight: string; drawerWidth: string; }) => { + const { setCurrentWorkspace, viewMode } = useGlobalContext(); + const [content, setContent] = useState("dataSets"); + + const [anchorElWorkspace, setAnchorElWorkspace] = React.useState(null); + const openWorkspace = Boolean(anchorElWorkspace); + + const handleClickWorkspace = (event: React.MouseEvent) => { + setAnchorElWorkspace(event.currentTarget); + }; + const handleCloseWorkspace = () => { + setAnchorElWorkspace(null); + }; + + const onClickWorkspace = (workspace) => { + setCurrentWorkspace(workspace.id); + }; + const handleDrawerOpen = () => { setSidebarOpen(true); }; @@ -88,6 +108,7 @@ const Sidebar = ({ const handleToggleContent = (_, type) => { setContent(type); }; + return ( @@ -151,7 +172,41 @@ const Sidebar = ({ - {sidebarOpen && <>{content === "dataSets" ? : }} + {sidebarOpen && ( + <> + {content === "dataSets" ? ( + + {viewMode === ViewMode.Compare && ( + <> + + + + )} + + ) : ( + + {viewMode === ViewMode.Compare && ( + <> + + + + )} + + )} + + )} ); diff --git a/applications/visualizer/frontend/src/components/ViewerContainer/WorkspaceSelector.tsx b/applications/visualizer/frontend/src/components/ViewerContainer/WorkspaceSelector.tsx new file mode 100644 index 00000000..8407d309 --- /dev/null +++ b/applications/visualizer/frontend/src/components/ViewerContainer/WorkspaceSelector.tsx @@ -0,0 +1,95 @@ +import { Box, Button, Menu, MenuItem, Typography } from "@mui/material"; +import type React from "react"; +import { useGlobalContext } from "../../contexts/GlobalContext.tsx"; +import { CheckIcon, DownIcon } from "../../icons"; +import { vars } from "../../theme/variables.ts"; + +const { gray500, gray50, brand600 } = vars; + +interface WorkspaceSelectorProps { + anchorElWorkspace: null | HTMLElement; + openWorkspace: boolean; + handleClickWorkspace: (event: React.MouseEvent) => void; + handleCloseWorkspace: () => void; + onClickWorkspace: (workspace: any) => void; +} + +const WorkspaceSelector: React.FC = ({ + anchorElWorkspace, + openWorkspace, + handleClickWorkspace, + handleCloseWorkspace, + onClickWorkspace, +}) => { + const { workspaces, currentWorkspaceId } = useGlobalContext(); + const currentWorkspace = workspaces[currentWorkspaceId]; + + return ( + + + You’re making changes to + + + + + + {Object.values(workspaces).map((workspace) => ( + onClickWorkspace(workspace)} + sx={{ + justifyContent: "space-between", + backgroundColor: "transparent !important", + }} + > + + + + + {workspace.name} + + + ))} + + + + ); +}; + +export default WorkspaceSelector; diff --git a/applications/visualizer/frontend/src/components/ViewerSettings.tsx b/applications/visualizer/frontend/src/components/ViewerSettings.tsx index 798dba66..40890b18 100644 --- a/applications/visualizer/frontend/src/components/ViewerSettings.tsx +++ b/applications/visualizer/frontend/src/components/ViewerSettings.tsx @@ -1,5 +1,11 @@ +import { updateWidget } from "@metacell/geppetto-meta-client/common/layout/actions"; +import { WidgetStatus } from "@metacell/geppetto-meta-client/common/layout/model"; import { Box, Divider, Drawer, FormControlLabel, FormGroup, IconButton, Typography } from "@mui/material"; -import { CloseIcon, LinkIcon } from "../icons/index.tsx"; +import { useDispatch } from "react-redux"; +import { useGlobalContext } from "../contexts/GlobalContext.tsx"; +import { CloseIcon, LinkIcon } from "../icons"; +import { emDataViewerWidget, threeDViewerWidget, twoDViewerWidget } from "../layout-manager/widgets.ts"; +import { ViewerType } from "../models/models.ts"; import { vars } from "../theme/variables.ts"; import CustomSwitch from "./ViewerContainer/CustomSwitch.tsx"; @@ -32,7 +38,11 @@ const SyncViewersData = [ }, ]; -const ViewersList = ["Connectivity graph", "3D viewer", "EM viewer"]; +const viewers = { + [ViewerType.Graph]: twoDViewerWidget(), + [ViewerType.ThreeD]: threeDViewerWidget(), + [ViewerType.EM]: emDataViewerWidget(), +}; const textStyles = { ...secondaryTypographyStyles, fontWeight: 500, flex: 1 }; const buttonStyle = { @@ -40,6 +50,25 @@ const buttonStyle = { }; const ViewerSettings = ({ open, toggleDrawer }) => { + const dispatch = useDispatch(); + const currentWorkspace = useGlobalContext().getCurrentWorkspace(); + + const handleToggle = (e, viewer) => { + const status = e.target.checked ? WidgetStatus.ACTIVE : WidgetStatus.MINIMIZED; + const selectedViewer = viewers[viewer]; + const selectedViewerFunction = viewers[viewer]; + if (selectedViewerFunction) { + const viewerConfig = { ...selectedViewer, status }; + dispatch(updateWidget(viewerConfig)); + currentWorkspace.changeViewerVisibility(viewer, e.target.checked); + } else { + return; + } + }; + const handleChangeSynchronizations = (_, index, status) => { + currentWorkspace.updateViewerSynchronizationStatus(index, !status); + }; + return ( { }, }} > - {ViewersList?.map((viewer) => { - return ( - } - key={`viewer-${viewer}`} - label={ - - {viewer} graph - - } - /> - ); - })} + {Object.keys(currentWorkspace?.viewers)?.map((viewer) => ( + handleToggle(e, viewer)} + /> + } + key={`viewer-${viewer}`} + label={ + + {viewer} + + } + /> + ))} @@ -128,17 +164,19 @@ const ViewerSettings = ({ open, toggleDrawer }) => { Sync viewers - {SyncViewersData?.map((data, index) => { - return ( - - {data.primaryText} - - - - {data.secondaryText} - - ); - })} + {SyncViewersData?.map((data, index) => ( + + {data.primaryText} + handleChangeSynchronizations(e, index, currentWorkspace?.synchronizations[index])} + > + + + {data.secondaryText} + + ))} diff --git a/applications/visualizer/frontend/src/components/WorkspaceComponent.tsx b/applications/visualizer/frontend/src/components/WorkspaceComponent.tsx index 714e067e..12105cf1 100644 --- a/applications/visualizer/frontend/src/components/WorkspaceComponent.tsx +++ b/applications/visualizer/frontend/src/components/WorkspaceComponent.tsx @@ -1,20 +1,23 @@ -import { addWidget } from "@metacell/geppetto-meta-client/common/layout/actions"; -import { Box, Button, CircularProgress, CssBaseline, Divider, IconButton, Menu, MenuItem, Typography } from "@mui/material"; -import { ThemeProvider } from "@mui/material/styles"; +import { addWidget, updateWidget } from "@metacell/geppetto-meta-client/common/layout/actions"; +import { Box, Button, CircularProgress, Divider, IconButton, Menu, MenuItem, Typography } from "@mui/material"; import React, { Suspense, useEffect, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import "@metacell/geppetto-meta-ui/flex-layout/style/light.scss"; +import { WidgetStatus } from "@metacell/geppetto-meta-client/common/layout/model"; +import { DeleteOutlined } from "@mui/icons-material"; import { useGlobalContext } from "../contexts/GlobalContext.tsx"; -import type { RootState } from "../layout-manager/layoutManagerFactory.ts"; -import { threeDViewerWidget, twoDViewerWidget } from "../layout-manager/widgets.ts"; -import theme from "../theme"; -import Layout from "./ViewerContainer/Layout.tsx"; - import { AddIcon, CheckIcon, DownIcon, DownloadIcon, LinkIcon, ViewerSettings as ViewerSettingsIcon } from "../icons/index.tsx"; +import { setWorkspaceId } from "../layout-manager/actions.ts"; +import type { RootState } from "../layout-manager/layoutManagerFactory.ts"; +import { emDataViewerWidget, threeDViewerWidget, twoDViewerWidget } from "../layout-manager/widgets.ts"; +import type { Workspace } from "../models"; +import { ViewMode } from "../models"; +import { ViewerType } from "../models/models.ts"; import { vars } from "../theme/variables.ts"; +import CreateNewWorkspaceDialog from "./CreateNewWorkspaceDialog.tsx"; import ViewerSettings from "./ViewerSettings.tsx"; -const { gray100, white } = vars; +const { gray100, white, orange700 } = vars; const LoadingComponent = () => ( ( ); -function WorkspaceComponent() { +function WorkspaceComponent({ sidebarOpen }) { const dispatch = useDispatch(); - const { workspaces } = useGlobalContext(); + const { workspaces, setCurrentWorkspace, removeWorkspace, selectedWorkspacesIds, setSelectedWorkspacesIds, setAllWorkspaces, setViewMode, viewMode } = + useGlobalContext(); const workspaceId = useSelector((state: RootState) => state.workspaceId); const [LayoutComponent, setLayoutComponent] = useState(() => LoadingComponent); - const [sidebarOpen, setSidebarOpen] = React.useState(true); const [open, setOpen] = React.useState(false); - + const [showCreateWorkspaceDialog, setShowCreateWorkspaceDialog] = React.useState(false); + const [hoveredWorkspaceId, setHoveredWorkspaceId] = useState(null); const toggleDrawer = (newOpen) => () => { setOpen(newOpen); }; - - const workspace = workspaces[workspaceId]; - - useEffect(() => { - if (workspace.layoutManager) { - setLayoutComponent(() => workspace.layoutManager.getComponent()); - } - }, [workspace.layoutManager]); - - useEffect(() => { - dispatch(addWidget(threeDViewerWidget())); - dispatch(addWidget(twoDViewerWidget())); - }, [LayoutComponent, dispatch]); + const currentWorkspace = workspaces[workspaceId]; + const [workspace, setWorkspace] = useState(currentWorkspace); const [anchorElWorkspace, setAnchorElWorkspace] = React.useState(null); const openWorkspace = Boolean(anchorElWorkspace); @@ -64,106 +57,249 @@ function WorkspaceComponent() { setAnchorElWorkspace(null); }; + const onCreateWorkspaceClick = () => { + setShowCreateWorkspaceDialog(true); + }; + + const onCloseCreateWorkspace = () => { + setShowCreateWorkspaceDialog(false); + }; + + const onClickWorkspace = (workspace) => { + let updatedIds = Array.from(selectedWorkspacesIds); + const index = updatedIds.indexOf(workspaceId); + + updatedIds = updateIds(updatedIds, index, workspace.id, viewMode); + + const newSelectedWorkspacesIds = new Set(updatedIds); + setCurrentWorkspace(workspace.id); + setWorkspace(workspaces[workspace.id]); + setSelectedWorkspacesIds(newSelectedWorkspacesIds); + + // change the ordering of workspaces to put the selected on the top + const selectedWorkspaces = Object.values(workspaces).filter((workspace) => newSelectedWorkspacesIds.has(workspace.id)); + const unselectedWorkspaces = Object.values(workspaces).filter((workspace) => !newSelectedWorkspacesIds.has(workspace.id)); + + const sortedWorkspaces = [...selectedWorkspaces, ...unselectedWorkspaces]; + const sortedWorkspacesRecord = sortedWorkspaces.reduce( + (acc, workspace) => { + acc[workspace.id] = workspace; + return acc; + }, + {} as Record, + ); + + setAllWorkspaces(sortedWorkspacesRecord); + }; + + const updateIds = (ids, index, id, viewMode) => { + if (index !== -1) { + ids[index] = id; + } else { + if (viewMode === ViewMode.Compare) { + ids.push(id); + } else { + ids = [id]; + } + } + return ids; + }; + const handleMouseEnter = (workspaceId) => { + setHoveredWorkspaceId(workspaceId); + }; + + const handleMouseLeave = () => { + setHoveredWorkspaceId(null); + }; + + const onDeleteWorkspace = (e, workspaceId) => { + e.preventDefault(); + e.stopPropagation(); + + const workspaceKeys = Object.keys(workspaces); + const workspaceIndex = workspaceKeys.indexOf(workspaceId); + + let workspaceIdToView; + + if (workspaceKeys.length === 2) { + workspaceIdToView = workspaceKeys.find((id) => id !== workspaceId); + const updatedWorkspace = workspaces[workspaceIdToView]; + setCurrentWorkspace(workspaceIdToView); + setWorkspace(updatedWorkspace); + setAllWorkspaces({ + ...workspaces, + [workspaceIdToView]: updatedWorkspace, + }); + setViewMode(ViewMode.Default); + } else { + workspaceIdToView = workspaceKeys[(workspaceIndex + 1) % workspaceKeys.length]; + if (workspace.id === workspaceId) { + setCurrentWorkspace(workspaceIdToView); + } + } + + const newSelectedWorkspacesIds = new Set(selectedWorkspacesIds); + newSelectedWorkspacesIds.delete(workspaceId); + + setSelectedWorkspacesIds(newSelectedWorkspacesIds); + removeWorkspace(workspaceId); + }; + + const workspacesLength = Object.keys(workspaces).length; + + useEffect(() => { + if (workspace.layoutManager) { + setLayoutComponent(() => workspace.layoutManager.getComponent()); + } + }, [workspace.id, workspace.layoutManager]); + + useEffect(() => { + if (workspace.id) { + dispatch(addWidget(threeDViewerWidget())); + dispatch(addWidget(twoDViewerWidget())); + dispatch(addWidget(emDataViewerWidget())); + + const updateWidgetStatus = (widget, viewerStatus) => { + const status = viewerStatus ? WidgetStatus.ACTIVE : WidgetStatus.MINIMIZED; + if (widget.status !== status) { + dispatch(updateWidget({ ...widget, status })); + } + }; + + updateWidgetStatus(threeDViewerWidget(), workspace.viewers[ViewerType.ThreeD]); + updateWidgetStatus(twoDViewerWidget(), workspace.viewers[ViewerType.Graph]); + updateWidgetStatus(emDataViewerWidget(), workspace.viewers[ViewerType.EM]); + } + }, [workspace.id, workspace.viewers, dispatch, LayoutComponent]); + + useEffect(() => { + dispatch(setWorkspaceId(workspace.id)); + }, [workspace.id]); + return ( - <> - - - }> + }> + + - - - - - - - + + + + + - - - {"Workspaces"} - - - - New workspace - - - {"Workspaces"} + + + + New workspace + + + + {Object.values(workspaces).map((workspace) => ( + onClickWorkspace(workspace)} + onMouseEnter={() => handleMouseEnter(workspace.id)} + onMouseLeave={handleMouseLeave} sx={{ - "& .MuiMenuItem-root": { - "&:not(.Mui-selected) svg": { - visibility: "hidden", - }, - }, + justifyContent: "space-between", + backgroundColor: "transparent !important", }} > - - - Workspace 1 - - - - Workspace 2 - - - - - - - - - - - - + + + + + {workspace.name} + + {hoveredWorkspaceId === workspace.id && workspacesLength > 1 && ( + onDeleteWorkspace(e, workspace.id)}> + + + )} + + ))} - - - - - + + + + + + + + + + + + + + - - - + + {showCreateWorkspaceDialog && ( + + )} + + ); } diff --git a/applications/visualizer/frontend/src/components/viewers/EM/EMStackTilesViewer.tsx b/applications/visualizer/frontend/src/components/viewers/EM/EMStackTilesViewer.tsx new file mode 100644 index 00000000..259cf1ea --- /dev/null +++ b/applications/visualizer/frontend/src/components/viewers/EM/EMStackTilesViewer.tsx @@ -0,0 +1,337 @@ +import { Box } from "@mui/material"; +import "ol/ol.css"; +import { type Feature, Map, View } from "ol"; +import type { FeatureLike } from "ol/Feature"; +import ScaleLine from "ol/control/ScaleLine"; +import { shiftKeyOnly } from "ol/events/condition"; +import { getCenter } from "ol/extent"; +import GeoJSON from "ol/format/GeoJSON"; +import { MouseWheelZoom, defaults as defaultInteractions } from "ol/interaction.js"; +import TileLayer from "ol/layer/Tile"; +import VectorLayer from "ol/layer/Vector"; +import { Projection } from "ol/proj"; +import { XYZ } from "ol/source"; +import VectorSource from "ol/source/Vector"; +import Fill from "ol/style/Fill"; +import Stroke from "ol/style/Stroke"; +import Style from "ol/style/Style"; +import Text from "ol/style/Text"; +import { TileGrid } from "ol/tilegrid"; +import { useEffect, useRef } from "react"; +import { useGlobalContext } from "../../../contexts/GlobalContext.tsx"; +import { SlidingRing } from "../../../helpers/slidingRing"; +import { getEMDataURL, getSegmentationURL } from "../../../models/models.ts"; +import type { Dataset } from "../../../rest/index.ts"; +import SceneControls from "./SceneControls.tsx"; + +// type EMStackViewerParameters = { +// dataset: Dataset; +// }; + +// const width = 42496 / 2; +// const height = 22528 / 2; +const width = 19968; +const height = 11008; + +// const extent = [0, -height, width, 0]; +const extent = [0, 0, width, height]; + +const projection = new Projection({ + code: "pixel", + units: "pixels", + extent: extent, + metersPerUnit: 2e-9, // 2 nm voxels +}); + +const tilegrid = new TileGrid({ + extent: extent, + tileSize: 512, + resolutions: [0.5, 1, 2, 4, 8, 16, 32].reverse(), +}); + +const getFeatureStyle = (feature: FeatureLike) => { + const opacity = 0.2; + const [r, g, b] = feature.get("color"); + const rgbaColor = `rgba(${r}, ${g}, ${b}, ${opacity})`; + + return new Style({ + stroke: new Stroke({ + color: [r, g, b], + width: 2, + }), + fill: new Fill({ + color: rgbaColor, + }), + }); +}; + +const resetStyle = (feature: Feature) => { + feature.setStyle(getFeatureStyle(feature)); +}; + +const setHighlightStyle = (feature: Feature) => { + const opacity = 0.5; + const [r, g, b] = feature.get("color"); + const rgbaColor = `rgba(${r}, ${g}, ${b}, ${opacity})`; + + const style = new Style({ + stroke: new Stroke({ + color: [r, g, b], + width: 4, + }), + fill: new Fill({ + color: rgbaColor, + }), + text: new Text({ + text: feature.get("name"), + scale: 2, + }), + }); + + feature.setStyle(style); +}; + +const newEMLayer = (dataset: Dataset, slice: number): TileLayer => { + return new TileLayer({ + source: new XYZ({ + tileGrid: tilegrid, + // url: `emdata/${slice}/{x}_{y}_{z}.jpg`, + url: getEMDataURL(dataset, slice), + projection: projection, + }), + zIndex: 0, + }); +}; + +const newSegLayer = (dataset: Dataset, slice: number) => { + return new VectorLayer({ + source: new VectorSource({ + // url: `segdata/${slice}`, + url: getSegmentationURL(dataset, slice), + format: new GeoJSON(), + }), + style: getFeatureStyle, + zIndex: 1, + }); +}; + +// const EMStackViewer = ({ dataset }: EMStackViewerParameters) => { +const EMStackViewer = () => { + const currentWorkspace = useGlobalContext().getCurrentWorkspace(); + + // We take the first active dataset at the moment (will change later) + const firstActiveDataset = Object.values(currentWorkspace.activeDatasets)?.[0]; + const minSlice = 0; + const maxSlice = 714; + const startSlice = 537; + const ringSize = 11; + + const mapRef = useRef(null); + const currSegLayer = useRef | null>(null); + const clickedFeature = useRef(null); + + // const debugLayer = new TileLayer({ + // source: new TileDebug({ + // projection: projection, + // tileGrid: tilegrid, + // }), + // }); + + const scale = new ScaleLine({ + units: "metric", + }); + + const interactions = defaultInteractions({ + mouseWheelZoom: false, + }).extend([ + new MouseWheelZoom({ + condition: shiftKeyOnly, + }), + ]); + + useEffect(() => { + if (mapRef.current) { + return; + } + + const map = new Map({ + target: "emviewer", + layers: [], + view: new View({ + projection: projection, + center: getCenter(extent), + extent: extent, + zoom: 1, + minZoom: 1, // mitigates blanc tiles on reset view (EM layer doesn't have tiles at zoom 0) + maxZoom: 5, + resolutions: tilegrid.getResolutions(), + }), + controls: [scale], + interactions: interactions, + }); + + const ringEM = new SlidingRing({ + cacheSize: ringSize, + startAt: startSlice, + extent: [minSlice, maxSlice], + onPush: (slice) => { + const layer = newEMLayer(firstActiveDataset, slice); + layer.setOpacity(0); + map.addLayer(layer); + return layer; + }, + onSelected: (_, layer) => { + layer.setOpacity(1); + }, + onUnselected: (_, layer) => { + layer.setOpacity(0); + }, + onEvict: (_, layer) => { + map.removeLayer(layer); + }, + }); + + const ringSeg = new SlidingRing({ + cacheSize: ringSize, + startAt: startSlice, + extent: [minSlice, maxSlice], + onPush: (slice) => { + const layer = newSegLayer(firstActiveDataset, slice); + layer.setOpacity(0); + map.addLayer(layer); + return layer; + }, + onSelected: (_, layer) => { + layer.setOpacity(1); + currSegLayer.current = layer; + }, + onUnselected: (_, layer) => { + layer.setOpacity(0); + }, + onEvict: (_, layer) => { + map.removeLayer(layer); + }, + }); + + map.on("click", (evt) => { + if (!currSegLayer.current) return; + + const features = currSegLayer.current.getSource().getFeaturesAtCoordinate(evt.coordinate); + if (features.length === 0) return; + + const feature = features[0]; + if (clickedFeature.current) { + resetStyle(clickedFeature.current); + } + + if (feature) { + setHighlightStyle(feature as Feature); + clickedFeature.current = feature as Feature; + console.log("Feature", feature.get("name"), feature); + } + }); + + map.getTargetElement().addEventListener("wheel", (e) => { + if (e.shiftKey) { + return; + } + + e.preventDefault(); + const scrollUp = e.deltaY < 0; + + if (scrollUp) { + ringEM.next(); + ringSeg.next(); + } else { + ringEM.prev(); + ringSeg.prev(); + } + }); + + mapRef.current = map; + + return () => map.setTarget(null); + }, []); + + const onControlZoomIn = () => { + if (!mapRef.current) return; + mapRef.current.getView().adjustZoom(1); + }; + + const onControlZoomOut = () => { + if (!mapRef.current) return; + mapRef.current.getView().adjustZoom(-1); + }; + + const onResetView = () => { + if (!mapRef.current) return; + const view = mapRef.current.getView(); + const center = getCenter(extent); + view.setCenter(center); + view.setZoom(1); + }; + + const onPrint = () => { + if (!mapRef.current) return; + mapRef.current.once("rendercomplete", () => { + printEMView(mapRef.current); + }); + mapRef.current.renderSync(); + }; + + return ( + + +
    + + ); +}; + +export default EMStackViewer; + +function printEMView(map: Map) { + const mapCanvas = document.createElement("canvas"); + + const size = map.getSize(); + mapCanvas.width = size[0]; + mapCanvas.height = size[1]; + + const mapContext = mapCanvas.getContext("2d"); + + Array.prototype.forEach.call(map.getViewport().querySelectorAll(".ol-layer canvas, canvas.ol-layer"), (canvas) => { + if (canvas.width > 0) { + const opacity = canvas.parentNode.style.opacity || canvas.style.opacity; + mapContext.globalAlpha = opacity === "" ? 1 : Number(opacity); + let matrix; + const transform = canvas.style.transform; + if (transform) { + // Get the transform parameters from the style's transform matrix + matrix = transform + .match(/^matrix\(([^\(]*)\)$/)[1] + .split(",") + .map(Number); + } else { + matrix = [Number.parseFloat(canvas.style.width) / canvas.width, 0, 0, Number.parseFloat(canvas.style.height) / canvas.height, 0, 0]; + } + // Apply the transform to the export map context + CanvasRenderingContext2D.prototype.setTransform.apply(mapContext, matrix); + const backgroundColor = canvas.parentNode.style.backgroundColor; + if (backgroundColor) { + mapContext.fillStyle = backgroundColor; + mapContext.fillRect(0, 0, canvas.width, canvas.height); + } + mapContext.drawImage(canvas, 0, 0); + } + }); + + mapContext.globalAlpha = 1; + mapContext.setTransform(1, 0, 0, 1, 0, 0); + + const link = document.createElement("a"); + link.href = mapCanvas.toDataURL(); + link.download = "em.png"; // TODO: define a better name + link.style.display = "none"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); +} diff --git a/applications/visualizer/frontend/src/components/viewers/EM/SceneControls.tsx b/applications/visualizer/frontend/src/components/viewers/EM/SceneControls.tsx new file mode 100644 index 00000000..c43a7d81 --- /dev/null +++ b/applications/visualizer/frontend/src/components/viewers/EM/SceneControls.tsx @@ -0,0 +1,63 @@ +import { FileDownloadOutlined, HomeOutlined, TextsmsOutlined } from "@mui/icons-material"; +import ZoomInIcon from "@mui/icons-material/ZoomIn"; +import ZoomOutIcon from "@mui/icons-material/ZoomOut"; +import { Box, Divider, IconButton } from "@mui/material"; +import Tooltip from "@mui/material/Tooltip"; + +interface ScaleControlsHandlers { + onZoomIn: () => void; + onResetView: () => void; + onZoomOut: () => void; + onPrint: () => void; +} + +function SceneControls({ onZoomIn, onResetView, onZoomOut, onPrint }: ScaleControlsHandlers) { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default SceneControls; diff --git a/applications/visualizer/frontend/src/components/viewers/ThreeD/ThreeDViewer.tsx b/applications/visualizer/frontend/src/components/viewers/ThreeD/ThreeDViewer.tsx index 69300911..90004df9 100644 --- a/applications/visualizer/frontend/src/components/viewers/ThreeD/ThreeDViewer.tsx +++ b/applications/visualizer/frontend/src/components/viewers/ThreeD/ThreeDViewer.tsx @@ -14,8 +14,10 @@ import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import { IconButton, Typography } from "@mui/material"; import { CameraControls, PerspectiveCamera } from "@react-three/drei"; import { Canvas } from "@react-three/fiber"; +import { useSelector } from "react-redux"; import { useGlobalContext } from "../../../contexts/GlobalContext.tsx"; import { CheckIcon, CloseIcon } from "../../../icons"; +import type { RootState } from "../../../layout-manager/layoutManagerFactory.ts"; import { vars } from "../../../theme/variables.ts"; import CustomAutocomplete from "../../CustomAutocomplete.tsx"; import Gizmo from "./Gizmo.tsx"; @@ -41,8 +43,9 @@ function ThreeDViewer() { const [showSynapses, setShowSynapses] = useState(true); const [instances, setInstances] = useState([]); const [isWireframe, setIsWireframe] = useState(false); - const activeDatasets = Object.values(useGlobalContext().getCurrentWorkspace().activateDataset); - + const currentWorkspaceId = useSelector((state: RootState) => state.workspaceId); + const { workspaces } = useGlobalContext(); + const currentWorkspace = workspaces[currentWorkspaceId]; const cameraControlRef = useRef(null); useEffect(() => { @@ -50,13 +53,13 @@ function ThreeDViewer() { setInstances([ { id: "nerve_ring", - url: "nervering-SEM_adult.stl", + url: "resources/nervering-SEM_adult.stl", color: "white", opacity: 0.5, }, { id: "adal_sem", - url: "ADAL-SEM_adult.stl", + url: "resources/ADAL-SEM_adult.stl", color: "blue", opacity: 1, }, @@ -64,11 +67,14 @@ function ThreeDViewer() { } }, [showNeurons, showSynapses]); + const dataSets = Object.values(currentWorkspace.activeDatasets); + return ( <> console.log(e)} getOptionLabel={(option: Dataset) => option.name} renderOption={(props, option) => (
  • diff --git a/applications/visualizer/frontend/src/components/wrappers/Compare.tsx b/applications/visualizer/frontend/src/components/wrappers/Compare.tsx new file mode 100644 index 00000000..68118a57 --- /dev/null +++ b/applications/visualizer/frontend/src/components/wrappers/Compare.tsx @@ -0,0 +1,90 @@ +import { AppBar, Button, CircularProgress, CssBaseline, IconButton, Toolbar } from "@mui/material"; +import { type Theme, ThemeProvider } from "@mui/material/styles"; +import { Suspense } from "react"; +import "@metacell/geppetto-meta-ui/flex-layout/style/light.scss"; +import { Box } from "@mui/system"; +import { DownloadIcon, LinkIcon } from "../../icons"; +import theme from "../../theme"; +import { vars } from "../../theme/variables.ts"; +const { gray100 } = vars; + +const drawerWidth = "22.31299rem"; +const drawerHeight = "3.5rem"; +function CompareWrapper({ children, sidebarOpen }) { + return ( + <> + + + }> + + ({ + height: drawerHeight, + marginTop: drawerHeight, + transition: theme.transitions.create(["width", "margin"], { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.leavingScreen, + }), + "& .MuiToolbar-root": { + height: drawerHeight, + minHeight: drawerHeight, + padding: "0 .75rem !important", + }, + ...(!sidebarOpen && { + "& .MuiToolbar-root": { + marginLeft: "3.5rem", + height: drawerHeight, + minHeight: drawerHeight, + padding: "0 .75rem !important", + }, + }), + ...(sidebarOpen && { + width: `calc(100% - ${drawerWidth})`, + transition: theme.transitions.create(["width", "margin"], { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.enteringScreen, + }), + }), + })} + > + + + + + + + + + + + + + + + {children} + + + + + ); +} + +export default CompareWrapper; diff --git a/applications/visualizer/frontend/src/components/wrappers/Default.tsx b/applications/visualizer/frontend/src/components/wrappers/Default.tsx new file mode 100644 index 00000000..9f11fb8a --- /dev/null +++ b/applications/visualizer/frontend/src/components/wrappers/Default.tsx @@ -0,0 +1,18 @@ +import { CircularProgress, CssBaseline } from "@mui/material"; +import { ThemeProvider } from "@mui/material/styles"; +import { Suspense } from "react"; +import "@metacell/geppetto-meta-ui/flex-layout/style/light.scss"; +import theme from "../../theme"; + +function DefaultWrapper({ children }) { + return ( + <> + + + }>{children} + + + ); +} + +export default DefaultWrapper; diff --git a/applications/visualizer/frontend/src/contexts/GlobalContext.tsx b/applications/visualizer/frontend/src/contexts/GlobalContext.tsx index cf0e9e9e..d034feb6 100644 --- a/applications/visualizer/frontend/src/contexts/GlobalContext.tsx +++ b/applications/visualizer/frontend/src/contexts/GlobalContext.tsx @@ -15,8 +15,9 @@ export interface GlobalContextType { setCurrentWorkspace: (workspaceId: string) => void; getCurrentWorkspace: () => Workspace; setSelectedWorkspacesIds: (workspaceId: Set) => void; - datasets: Array; + datasets: Record; fetchDatasets: () => void; + setAllWorkspaces: (workspaces: Record) => void; } interface GlobalContextProviderProps { @@ -30,9 +31,19 @@ export const GlobalContextProvider: React.FC = ({ ch const [currentWorkspaceId, setCurrentWorkspaceId] = useState(undefined); const [viewMode, setViewMode] = useState(ViewMode.Default); const [selectedWorkspacesIds, setSelectedWorkspacesIds] = useState>(new Set()); - const [datasets, setDatasets] = useState>([]); + const [datasets, setDatasets] = useState>({}); - const createWorkspace = (id: string, name: string, activeDatasets: Set, activeNeurons: Set) => { + const createWorkspace = (id: string, name: string, activeDatasetKeys: Set, activeNeurons: Set) => { + // Convert the activeDatasetKeys into a Record + const activeDatasets: Record = {}; + + activeDatasetKeys.forEach((key) => { + if (datasets[key]) { + activeDatasets[key] = datasets[key]; + } + }); + + // Create a new workspace using the activeDatasets record const newWorkspace = new Workspace(id, name, activeDatasets, activeNeurons, updateWorkspace); setWorkspaces((prev) => ({ ...prev, [id]: newWorkspace })); }; @@ -44,6 +55,10 @@ export const GlobalContextProvider: React.FC = ({ ch })); }; + const setAllWorkspaces = (workspaces: Record) => { + // New function implementation + setWorkspaces(workspaces); + }; const removeWorkspace = (workspaceId: string) => { const updatedWorkspaces = { ...workspaces }; delete updatedWorkspaces[workspaceId]; @@ -57,11 +72,34 @@ export const GlobalContextProvider: React.FC = ({ ch const getCurrentWorkspace = () => { return workspaces[currentWorkspaceId]; }; - + const getGlobalContext = () => ({ + workspaces, + currentWorkspaceId, + getCurrentWorkspace, + createWorkspace, + updateWorkspace, + removeWorkspace, + setCurrentWorkspace, + viewMode, + setViewMode, + selectedWorkspacesIds, + setSelectedWorkspacesIds, + fetchDatasets, + datasets, + setAllWorkspaces, + }); const fetchDatasets = async () => { try { const response = await DatasetsService.getDatasets({}); - setDatasets(response); + const datasetsRecord = response.reduce( + (acc, dataset) => { + acc[dataset.id] = dataset; + return acc; + }, + {} as Record, + ); + + setDatasets(datasetsRecord); } catch (error) { console.error("Failed to fetch datasets", error); } @@ -71,29 +109,8 @@ export const GlobalContextProvider: React.FC = ({ ch fetchDatasets(); }, []); - return ( - - {children} - - ); + return {children}; }; - export const useGlobalContext = () => { const context = useContext(GlobalContext); if (context === undefined) { diff --git a/applications/visualizer/frontend/src/helpers/slidingRing.ts b/applications/visualizer/frontend/src/helpers/slidingRing.ts new file mode 100644 index 00000000..6c5352c5 --- /dev/null +++ b/applications/visualizer/frontend/src/helpers/slidingRing.ts @@ -0,0 +1,198 @@ +export interface SlidingRingCb { + onPush: (n: number) => T; // called any time a new object is pushed into the ring + onSelected: (n: number, o: T) => void; // called when the selected object changes + onUnselected: (n: number, o: T) => void; // called when an object is unselected + onEvict: (n: number, o: T) => void; // called when an object is evicted from the ring +} + +export interface SlidingRingOptions extends SlidingRingCb { + cacheSize: number; + startAt: number; + extent: [number, number]; +} + +/** + * A Sliding Ring is a fixed size ring buffer that maintains in memory + * a window in to an extent of sequenced values. + * + * With a cacheSize of 5, it will maintain in memory 2 elements before + * and after startAt element, e.g with an extent of [0, 714] and a startAt + * of 300, it will maintain in memory [298, 299, 300, 301, 302]. + * ^ ^ ^ + * tail selected head + * + * Advancing in to the next element (301), 298 will be evicted and 303 will + * be put in its place, keeping in memory [303, 299, 300, 301, 302] + * ^ ^ ^ + * head tail selected + * + * Going back on the previous element follows the same logic. + */ +export class SlidingRing { + private extent: [number, number]; + + private ring: Array<{ + n: number; // position within extent + o: T; + }>; + + private pos: number; // current buffer position + private tail: number; // buffer tail + private head: number; // buffer head + + private cb: SlidingRingCb; + + constructor(options: SlidingRingOptions) { + if (options.cacheSize < 3) { + throw Error("cache should be greater that 3"); + } + + const [min, max] = options.extent; + + if (min >= max) { + throw Error("extent should be [min,max], where min < max"); + } + + if (options.startAt > max || options.startAt < min) { + throw Error("startAt must be within extent"); + } + + const extentSize = max - min; + if (extentSize < 3) { + throw Error("extent size is too small, should be greater than 3"); + } + + if (extentSize < options.cacheSize) { + options.cacheSize = max - min; + } + + this.ring = new Array(options.cacheSize); + this.extent = options.extent; + + this.cb = { + onPush: options.onPush, + onSelected: options.onSelected, + onUnselected: options.onUnselected, + onEvict: options.onEvict, + }; + + // initialize ring + const halfSize = Math.floor(this.ring.length / 2); + let tailN = options.startAt - halfSize; + let headN = options.startAt + halfSize; + + // the ring may start near the extent + // this account for that adjustment + if (tailN < min) tailN = min; + if (headN > max) { + headN = max; + tailN = headN - this.ring.length - 1; + } + + // populate the ring + for (let i = 0; i < this.ring.length; i++) { + const n = tailN + i; + const o = this.cb.onPush(n); + + this.ring[i] = { n, o }; + } + + this.pos = options.startAt - tailN; + this.tail = 0; + this.head = this.ring.length - 1; + + this.cb.onSelected(options.startAt, this.ring[this.pos].o); + } + + next() { + const [_, max] = this.extent; + const nextN = this.ring[this.pos].n + 1; + if (nextN > max) return; + + // update selected + const nextPos = (this.pos + this.ring.length + 1) % this.ring.length; + this.cb.onSelected(this.ring[nextPos].n, this.ring[nextPos].o); + this.cb.onUnselected(this.ring[this.pos].n, this.ring[this.pos].o); + + // update sliding window + const nextHeadN = this.ring[this.head].n + 1; + const halfSize = Math.floor(this.ring.length / 2); // TODO: to avoid calc should we save as class property? + const canSlideFurther = nextN - this.ring[this.tail].n > halfSize; + + if (nextHeadN <= max && canSlideFurther) { + const tail = this.ring[this.tail]; + this.cb.onEvict(tail.n, tail.o); + + this.ring[this.tail] = { + n: nextHeadN, + o: this.cb.onPush(nextHeadN), + }; + + this.head = this.tail; + this.tail = (this.tail + this.ring.length + 1) % this.ring.length; + } + + this.pos = nextPos; + } + + prev() { + const [min, _] = this.extent; + const prevN = this.ring[this.pos].n - 1; + if (prevN < min) return; + + // update selected + const prevPos = (this.pos + this.ring.length - 1) % this.ring.length; + this.cb.onSelected(this.ring[prevPos].n, this.ring[prevPos].o); + this.cb.onUnselected(this.ring[this.pos].n, this.ring[this.pos].o); + + // update sliding window + const nextTailN = this.ring[this.tail].n - 1; + const halfSize = Math.floor(this.ring.length / 2); // TODO: to avoid calc should we save as class property? + const canSlideBackwards = this.ring[this.head].n - prevN > halfSize; + + if (nextTailN >= min && canSlideBackwards) { + const head = this.ring[this.head]; + this.cb.onEvict(head.n, head.o); + + this.ring[this.head] = { + n: nextTailN, + o: this.cb.onPush(nextTailN), + }; + + this.tail = this.head; + this.head = (this.tail + this.ring.length - 1) % this.ring.length; + } + + this.pos = prevPos; + } + + debug() { + let text = "["; + + for (let i = 0; i < this.ring.length; i++) { + if (this.ring[i] === undefined) { + // should not happen + text = text.concat("?"); + continue; + } + + switch (true) { + case i === this.pos: + text = text.concat("*"); + break; + case i === this.tail: + text = text.concat("-"); + break; + case i === this.head: + text = text.concat("+"); + break; + } + + text = text.concat(`${this.ring[i].n}`); + if (i !== this.ring.length - 1) text = text.concat(", "); + } + text = text.concat("]"); + + console.debug(text); + } +} diff --git a/applications/visualizer/frontend/src/helpers/workspaceHelper.ts b/applications/visualizer/frontend/src/helpers/workspaceHelper.ts index e8e4e50e..d10687d3 100644 --- a/applications/visualizer/frontend/src/helpers/workspaceHelper.ts +++ b/applications/visualizer/frontend/src/helpers/workspaceHelper.ts @@ -1,13 +1,12 @@ -import { type Dataset, DatasetsService } from "../rest"; +import type { Dataset } from "../rest"; -export async function fetchDatasets(datasetIds: Set): Promise> { - const datasetIdsArray = Array.from(datasetIds || []); - const datasets = await DatasetsService.getDatasets({ - ids: datasetIdsArray.length > 0 ? datasetIdsArray : undefined, - }); - - return datasets.reduce((acc, dataset) => { - acc[dataset.id] = dataset; - return acc; - }, {}); -} +export const getWorkspaceActiveDatasets = (datasets: Record, datasetIds: Set): Record => { + const datasetsArray = Object.values(datasets).filter((dataset) => datasetIds.has(dataset.id)); + return datasetsArray.reduce( + (acc, dataset) => { + acc[dataset.id] = dataset; + return acc; + }, + {} as Record, + ); +}; diff --git a/applications/visualizer/frontend/src/icons/index.tsx b/applications/visualizer/frontend/src/icons/index.tsx index f2ea7e8b..7fcd56a8 100644 --- a/applications/visualizer/frontend/src/icons/index.tsx +++ b/applications/visualizer/frontend/src/icons/index.tsx @@ -139,9 +139,9 @@ export const LinkIcon = ({ fill = "#757570" }) => ( ); -export const DownIcon = () => ( +export const DownIcon = ({ color }: { color?: string }) => ( - + ); diff --git a/applications/visualizer/frontend/src/layout-manager/actions.ts b/applications/visualizer/frontend/src/layout-manager/actions.ts new file mode 100644 index 00000000..b6f592bd --- /dev/null +++ b/applications/visualizer/frontend/src/layout-manager/actions.ts @@ -0,0 +1,6 @@ +import { SET_WORKSPACE_ID } from "./actionsTypes.ts"; + +export const setWorkspaceId = (workspaceId) => ({ + type: SET_WORKSPACE_ID, + payload: workspaceId, +}); diff --git a/applications/visualizer/frontend/src/layout-manager/actionsTypes.ts b/applications/visualizer/frontend/src/layout-manager/actionsTypes.ts new file mode 100644 index 00000000..ac9e5065 --- /dev/null +++ b/applications/visualizer/frontend/src/layout-manager/actionsTypes.ts @@ -0,0 +1 @@ +export const SET_WORKSPACE_ID = "SET_WORKSPACE_ID"; diff --git a/applications/visualizer/frontend/src/layout-manager/componentMap.ts b/applications/visualizer/frontend/src/layout-manager/componentMap.ts index cf8c1f9d..ec46ab81 100644 --- a/applications/visualizer/frontend/src/layout-manager/componentMap.ts +++ b/applications/visualizer/frontend/src/layout-manager/componentMap.ts @@ -1,3 +1,4 @@ +import EMViewer from "../components/viewers/EM/EMStackTilesViewer.tsx"; import ThreeDViewer from "../components/viewers/ThreeD/ThreeDViewer.tsx"; import TwoDViewer from "../components/viewers/TwoD/TwoDViewer.tsx"; import { widgetIds } from "./widgets.ts"; @@ -5,6 +6,7 @@ import { widgetIds } from "./widgets.ts"; const componentMap = { [widgetIds.threeDViewer]: ThreeDViewer, [widgetIds.twoDViewer]: TwoDViewer, + [widgetIds.emDataViewer]: EMViewer, }; export default componentMap; diff --git a/applications/visualizer/frontend/src/layout-manager/layout.ts b/applications/visualizer/frontend/src/layout-manager/layout.ts index b1889ae4..3862f707 100644 --- a/applications/visualizer/frontend/src/layout-manager/layout.ts +++ b/applications/visualizer/frontend/src/layout-manager/layout.ts @@ -1,12 +1,24 @@ export default { global: { sideBorders: 8, - tabSetHeaderHeight: 26, - tabSetTabStripHeight: 26, + tabSetHeaderHeight: 28, + tabSetTabStripHeight: 28, enableEdgeDock: false, - borderBarSize: 0, - tabEnableDrag: true, + borderBarSize: 1, + borderEnableDrop: false, }, + borders: [ + { + type: "border", + location: "bottom", + size: 1, + barSize: 1, + enableDrop: false, + config: { + isMinimizedPanel: true, + }, + }, + ], layout: { type: "row", id: "root", @@ -35,6 +47,13 @@ export default { enableDeleteWhenEmpty: false, children: [], }, + { + type: "tabset", + weight: 100, + id: "bottomPanel", + enableDeleteWhenEmpty: false, + children: [], + }, ], }, ], diff --git a/applications/visualizer/frontend/src/layout-manager/layoutManagerFactory.ts b/applications/visualizer/frontend/src/layout-manager/layoutManagerFactory.ts index f6730d6d..ed16b9a6 100644 --- a/applications/visualizer/frontend/src/layout-manager/layoutManagerFactory.ts +++ b/applications/visualizer/frontend/src/layout-manager/layoutManagerFactory.ts @@ -5,6 +5,7 @@ import geppettoClientReducer, { clientInitialState, type ClientState } from "@me import { type LayoutState, layout, layoutInitialState, widgets } from "@metacell/geppetto-meta-client/common/reducer/geppettoLayout"; import { reducerDecorator } from "@metacell/geppetto-meta-client/common/reducer/reducerDecorator"; import { type Action, type Reducer, combineReducers, configureStore } from "@reduxjs/toolkit"; +import { SET_WORKSPACE_ID } from "./actionsTypes.ts"; import componentMap from "./componentMap.ts"; import baseLayout from "./layout.ts"; @@ -18,7 +19,7 @@ export interface RootState { const workspaceReducer = (state = "", action) => { switch (action.type) { - case "SET_WORKSPACE_ID": + case SET_WORKSPACE_ID: return action.payload; default: return state; diff --git a/applications/visualizer/frontend/src/layout-manager/widgets.ts b/applications/visualizer/frontend/src/layout-manager/widgets.ts index e066078a..89b929af 100644 --- a/applications/visualizer/frontend/src/layout-manager/widgets.ts +++ b/applications/visualizer/frontend/src/layout-manager/widgets.ts @@ -3,22 +3,31 @@ import { WidgetStatus } from "@metacell/geppetto-meta-client/common/layout/model export const widgetIds = { threeDViewer: "threeDViewer", twoDViewer: "twoDViewer", + emDataViewer: "emDataViewer", }; - -export const threeDViewerWidget = () => ({ +export const threeDViewerWidget = (status = WidgetStatus.ACTIVE) => ({ id: widgetIds.threeDViewer, name: "3D Viewer", component: widgetIds.threeDViewer, panelName: "rightPanel", enableClose: false, - status: WidgetStatus.ACTIVE, + status, }); -export const twoDViewerWidget = () => ({ +export const twoDViewerWidget = (status = WidgetStatus.ACTIVE) => ({ id: widgetIds.twoDViewer, name: "Connectivity Graph", component: widgetIds.twoDViewer, panelName: "leftPanel", enableClose: false, + status, +}); + +export const emDataViewerWidget = () => ({ + id: widgetIds.emDataViewer, + name: "EM Data", + component: widgetIds.emDataViewer, + panelName: "bottomPanel", + enableClose: false, status: WidgetStatus.ACTIVE, }); diff --git a/applications/visualizer/frontend/src/models/models.ts b/applications/visualizer/frontend/src/models/models.ts index c529a8d1..680d707b 100644 --- a/applications/visualizer/frontend/src/models/models.ts +++ b/applications/visualizer/frontend/src/models/models.ts @@ -1,5 +1,5 @@ -import type { Neuron } from "../rest"; import type { Position } from "cytoscape"; +import type { Dataset, Neuron } from "../rest"; export enum ViewMode { Default = "Default", @@ -28,6 +28,7 @@ export interface NeuronGroup { export interface EnhancedNeuron extends Neuron { viewerData: ViewerData; + isInteractant: boolean; } export interface GraphViewerData { @@ -41,3 +42,23 @@ export interface ViewerData { [ViewerType.EM]?: any; // Define specific data for EM viewer if needed [ViewerType.InstanceDetails]?: any; // Define specific data for Instance Details viewer if needed } + +const buildUrlFromFormat = (s: string, param: string) => { + return s.replace(s.match("{[^}]+}")?.[0], param); +}; + +export function getNeuronUrlForDataset(neuron: Neuron, datasetId: string) { + return buildUrlFromFormat(neuron.model3DUrl, datasetId); +} + +export function getNeuronURL(dataset: Dataset, neuronName: string) { + return buildUrlFromFormat(dataset.neuron3DUrl, neuronName); +} + +export function getSegmentationURL(dataset: Dataset, sliceIndex: number) { + return buildUrlFromFormat(dataset.emData.segmentation_url, sliceIndex?.toString()); +} + +export function getEMDataURL(dataset: Dataset, sliceIndex: number) { + return buildUrlFromFormat(dataset.emData.resource_url, sliceIndex?.toString()); +} diff --git a/applications/visualizer/frontend/src/models/workspace.ts b/applications/visualizer/frontend/src/models/workspace.ts index 448c5c78..9123a6eb 100644 --- a/applications/visualizer/frontend/src/models/workspace.ts +++ b/applications/visualizer/frontend/src/models/workspace.ts @@ -1,10 +1,9 @@ -import { produce, immerable } from "immer"; +import type { LayoutManager } from "@metacell/geppetto-meta-client/common/layout/LayoutManager"; import type { configureStore } from "@reduxjs/toolkit"; -import { type EnhancedNeuron, type NeuronGroup, ViewerSynchronizationPair, ViewerType } from "./models"; +import { immerable, produce } from "immer"; import getLayoutManagerAndStore from "../layout-manager/layoutManagerFactory"; -import { type Dataset, DatasetsService, type Neuron } from "../rest"; -import { fetchDatasets } from "../helpers/workspaceHelper"; -import type { LayoutManager } from "@metacell/geppetto-meta-client/common/layout/LayoutManager"; +import { type Dataset, type Neuron, NeuronsService } from "../rest"; +import { type EnhancedNeuron, type NeuronGroup, ViewerSynchronizationPair, ViewerType } from "./models"; export class Workspace { [immerable] = true; @@ -26,15 +25,15 @@ export class Workspace { layoutManager: LayoutManager; updateContext: (workspace: Workspace) => void; - constructor(id: string, name: string, datasetIds: Set, activeNeurons: Set, updateContext: (workspace: Workspace) => void) { + constructor(id: string, name: string, activeDatasets: Record, activeNeurons: Set, updateContext: (workspace: Workspace) => void) { this.id = id; this.name = name; - this.activeDatasets = {}; + this.activeDatasets = activeDatasets; this.availableNeurons = {}; this.activeNeurons = activeNeurons || new Set(); this.selectedNeurons = new Set(); this.viewers = { - [ViewerType.Graph]: true, + [ViewerType.Graph]: false, [ViewerType.ThreeD]: true, [ViewerType.EM]: false, [ViewerType.InstanceDetails]: false, @@ -51,13 +50,18 @@ export class Workspace { this.store = store; this.updateContext = updateContext; - this._initializeActiveDatasets(datasetIds); + this._initializeAvailableNeurons(); } activateNeuron(neuron: Neuron): void { const updated = produce(this, (draft: Workspace) => { draft.activeNeurons.add(neuron.name); + // Set isInteractant to true if the neuron exists in availableNeurons + if (draft.availableNeurons[neuron.name]) { + draft.availableNeurons[neuron.name].isInteractant = true; + } }); + this.updateContext(updated); } @@ -68,6 +72,19 @@ export class Workspace { this.updateContext(updated); } + deleteNeuron(neuronId: string): void { + const updated = produce(this, (draft: Workspace) => { + // Remove the neuron from activeNeurons + draft.activeNeurons.delete(neuronId); + + // Set isInteractant to false if the neuron exists in availableNeurons + if (draft.availableNeurons[neuronId]) { + draft.availableNeurons[neuronId].isInteractant = false; + } + }); + this.updateContext(updated); + } + async activateDataset(dataset: Dataset): Promise { const updated: Workspace = produce(this, (draft: Workspace) => { draft.activeDatasets[dataset.id] = dataset; @@ -148,28 +165,16 @@ export class Workspace { this.updateContext(updated); } - customUpdate(updateFunction: (draft: Workspace) => void): void { - const updated = produce(this, updateFunction); - this.updateContext(updated); - } - - async _initializeActiveDatasets(datasetIds: Set) { - if (!datasetIds) { - return; - } - const datasets = await fetchDatasets(datasetIds); - const updated: Workspace = produce(this, (draft: Workspace) => { - draft.activeDatasets = datasets; - }); - const updatedWithNeurons = await this._getAvailableNeurons(updated); + async _initializeAvailableNeurons() { + const updatedWithNeurons = await this._getAvailableNeurons(this); this.updateContext(updatedWithNeurons); } async _getAvailableNeurons(updatedWorkspace: Workspace): Promise { try { - const neuronPromises = Object.keys(updatedWorkspace.activeDatasets).map((datasetId) => DatasetsService.getDatasetNeurons({ dataset: datasetId })); + const datasetIds = Object.keys(updatedWorkspace.activeDatasets); + const neuronArrays = await NeuronsService.searchCells({ datasetIds }); - const neuronArrays = await Promise.all(neuronPromises); const uniqueNeurons = new Set(); // Flatten and deduplicate neurons @@ -182,18 +187,22 @@ export class Workspace { return produce(updatedWorkspace, (draft: Workspace) => { draft.availableNeurons = {}; for (const neuron of uniqueNeurons) { + const previousNeuron = draft.availableNeurons[neuron.name]; + const enhancedNeuron: EnhancedNeuron = { ...neuron, viewerData: { [ViewerType.Graph]: { - defaultPosition: null, - visibility: false, + defaultPosition: previousNeuron?.viewerData[ViewerType.Graph]?.defaultPosition || null, + visibility: previousNeuron?.viewerData[ViewerType.Graph]?.visibility || false, }, - [ViewerType.ThreeD]: {}, - [ViewerType.EM]: {}, - [ViewerType.InstanceDetails]: {}, + [ViewerType.ThreeD]: previousNeuron?.viewerData[ViewerType.ThreeD] || {}, + [ViewerType.EM]: previousNeuron?.viewerData[ViewerType.EM] || {}, + [ViewerType.InstanceDetails]: previousNeuron?.viewerData[ViewerType.InstanceDetails] || {}, }, + isInteractant: previousNeuron?.isInteractant ?? draft.activeNeurons.has(neuron.name), }; + draft.availableNeurons[neuron.name] = enhancedNeuron; } }); @@ -202,4 +211,9 @@ export class Workspace { return updatedWorkspace; } } + + customUpdate(updateFunction: (draft: Workspace) => void): void { + const updated = produce(this, updateFunction); + this.updateContext(updated); + } } diff --git a/applications/visualizer/frontend/src/rest/index.ts b/applications/visualizer/frontend/src/rest/index.ts index 6c3c26cd..80ec494c 100644 --- a/applications/visualizer/frontend/src/rest/index.ts +++ b/applications/visualizer/frontend/src/rest/index.ts @@ -9,6 +9,7 @@ export type { OpenAPIConfig } from './core/OpenAPI'; export type { Connection } from './models/Connection'; export type { Dataset } from './models/Dataset'; +export type { EMData } from './models/EMData'; export type { ErrorMessage } from './models/ErrorMessage'; export type { Input } from './models/Input'; export type { Neuron } from './models/Neuron'; diff --git a/applications/visualizer/frontend/src/rest/models/Dataset.ts b/applications/visualizer/frontend/src/rest/models/Dataset.ts index 977e5c09..1aa97be5 100644 --- a/applications/visualizer/frontend/src/rest/models/Dataset.ts +++ b/applications/visualizer/frontend/src/rest/models/Dataset.ts @@ -2,8 +2,11 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ +import type { EMData } from './EMData'; export type Dataset = { id: string; + neuron3DUrl: string; + emData: EMData; collection: string; name: string; description: string; diff --git a/applications/visualizer/frontend/src/rest/models/EMData.ts b/applications/visualizer/frontend/src/rest/models/EMData.ts new file mode 100644 index 00000000..99e18057 --- /dev/null +++ b/applications/visualizer/frontend/src/rest/models/EMData.ts @@ -0,0 +1,12 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type EMData = { + min_zoom: number; + max_zoom: number; + nb_slices: number; + resource_url: string; + segmentation_url: string; +}; + diff --git a/applications/visualizer/frontend/src/rest/models/Neuron.ts b/applications/visualizer/frontend/src/rest/models/Neuron.ts index 976f30fe..7fcaa049 100644 --- a/applications/visualizer/frontend/src/rest/models/Neuron.ts +++ b/applications/visualizer/frontend/src/rest/models/Neuron.ts @@ -3,8 +3,10 @@ /* tslint:disable */ /* eslint-disable */ export type Neuron = { + id: string; name: string; datasetIds: Array; + model3DUrl: string; nclass: string; neurotransmitter: string; type: string; diff --git a/applications/visualizer/frontend/src/settings/templateWorkspaceSettings.ts b/applications/visualizer/frontend/src/settings/templateWorkspaceSettings.ts index 1423785f..2afe725a 100644 --- a/applications/visualizer/frontend/src/settings/templateWorkspaceSettings.ts +++ b/applications/visualizer/frontend/src/settings/templateWorkspaceSettings.ts @@ -1,2 +1,2 @@ -export const TEMPLATE_ACTIVE_DATASETS = ["white_1986_jsh", "white_1986_n2u"]; -export const TEMPLATE_ACTIVE_NEURONS = ["AIY", "ASEL"]; +export const TEMPLATE_ACTIVE_DATASETS = ["witvliet_2020_7", "witvliet_2020_8"]; +export const TEMPLATE_ACTIVE_NEURONS = ["ASEL", "AIYR"]; diff --git a/applications/visualizer/frontend/src/theme/index.tsx b/applications/visualizer/frontend/src/theme/index.tsx index 53796dd1..81a9ecce 100644 --- a/applications/visualizer/frontend/src/theme/index.tsx +++ b/applications/visualizer/frontend/src/theme/index.tsx @@ -36,6 +36,7 @@ const { brand500, brand300, brand200, + gray900, } = vars; const theme = createTheme({ @@ -304,6 +305,11 @@ const theme = createTheme({ "&:focus": { outline: 0, }, + "&.Mui-disabled": { + background: gray100, + color: gray400, + borderColor: gray200, + }, }, }, }, @@ -363,7 +369,6 @@ const theme = createTheme({ MuiList: { styleOverrides: { root: { - // maxHeight: '12.5rem', maxHeight: "100%", "& > div + div": { marginTop: "0.25rem", @@ -373,6 +378,12 @@ const theme = createTheme({ gap: "0.25rem", borderTop: `0.0625rem solid ${gray100}`, }, + + "& .MuiMenuItem-root": { + "&.Mui-disabled": { + background: "transparent", + }, + }, }, }, }, @@ -470,7 +481,7 @@ const theme = createTheme({ borderRadius: "0.375rem", gap: "0.5rem", - "&:not(:first-child)": { + "&:not(:first-of-type)": { marginTop: "0.25rem", }, @@ -1008,6 +1019,64 @@ const theme = createTheme({ }, }, }, + MuiInputBase: { + styleOverrides: { + root: { + borderRight: 0, + borderLeft: 0, + borderRadius: 0, + padding: "0.5rem 0.875rem", + borderColor: gray100, + "&.Mui-focused": { + "& .MuiOutlinedInput-notchedOutline": { + borderWidth: 0, + background: `transparent !important`, + boxShadow: "none !important", + borderColor: `${gray100} !important`, + }, + }, + + "& .MuiInputBase-input": { + padding: "0", + height: "1.25rem", + }, + + "& .MuiSvgIcon-root": { + color: `${gray400B}`, + }, + + "&:has( .Mui-disabled)": { + backgroundColor: gray100, + + "& .MuiOutlinedInput-notchedOutline": { + borderColor: `${gray100} !important`, + }, + }, + }, + }, + }, + MuiSnackbarContent: { + styleOverrides: { + root: { + "&.MuiPaper-root": { + height: "fit-content !important", + backgroundColor: gray900, + borderRadius: "0.5rem", + fontSize: "0.75rem", + fontWeight: 600, + padding: "0.5rem 0.75rem", + }, + }, + action: { + "& .MuiButtonBase-root": { + "& .MuiSvgIcon-root": { + color: "white", + fontWeight: 600, + }, + }, + }, + }, + }, }, }); diff --git a/applications/visualizer/frontend/vite.config.ts b/applications/visualizer/frontend/vite.config.ts index 245a3edd..c181b411 100644 --- a/applications/visualizer/frontend/vite.config.ts +++ b/applications/visualizer/frontend/vite.config.ts @@ -9,6 +9,9 @@ const defaultConfig = { build: { sourcemap: !process.env.NO_SOURCEMAP, }, + optimizeDeps: { + include: ["@mui/material", "@emotion/react", "@emotion/styled", "@mui/material/Tooltip"], + }, // publicDir: 'src/assets', }; @@ -20,7 +23,7 @@ export default defineConfig(({ command, mode }) => { const port = process.env.PORT || PORT; const theDomain = process.env.DOMAIN || "http://localhost:8000"; - const replaceHost = (uri: string, appName: string) => (uri.includes("visualizer") && uri.replace("visualizer", appName + "." + theDomain)) || uri; + const replaceHost = (uri: string, appName: string) => (uri.includes("visualizer") && uri.replace("visualizer", `${appName}.${theDomain}`)) || uri; return { ...defaultConfig, @@ -36,6 +39,11 @@ export default defineConfig(({ command, mode }) => { changeOrigin: isDev, secure: !isDev, }, + "/resources": { + target: replaceHost(theDomain, "visualizer"), + changeOrigin: isDev, + secure: !isDev, + }, }, }, }; diff --git a/applications/visualizer/frontend/yarn.lock b/applications/visualizer/frontend/yarn.lock index bc276931..ea6c8545 100644 --- a/applications/visualizer/frontend/yarn.lock +++ b/applications/visualizer/frontend/yarn.lock @@ -2,239 +2,230 @@ # yarn lockfile v1 -"@aashutoshrathi/word-wrap@^1.2.3": - version "1.2.6" - resolved "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz" - integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== - "@ampproject/remapping@^2.2.0": version "2.3.0" - resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== dependencies: "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" "@apidevtools/json-schema-ref-parser@^11.5.4": - version "11.5.5" - resolved "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.5.5.tgz" - integrity sha512-hv/aXDILyroHioVW27etFMV+IX6FyNn41YwbeGIAt5h/7fUTQvHI5w3ols8qYAT8aQt3kzexq5ZwxFDxNHIhdQ== + version "11.6.4" + resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.6.4.tgz#0f3e02302f646471d621a8850e6a346d63c8ebd4" + integrity sha512-9K6xOqeevacvweLGik6LnZCb1fBtCOSIWQs8d096XGeqoLKC33UVMGz9+77Gw44KvbH4pKcQPWo4ZpxkXYj05w== dependencies: "@jsdevtools/ono" "^7.1.3" "@types/json-schema" "^7.0.15" js-yaml "^4.1.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2": - version "7.24.2" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz" - integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== dependencies: - "@babel/highlight" "^7.24.2" + "@babel/highlight" "^7.24.7" picocolors "^1.0.0" -"@babel/compat-data@^7.23.5": - version "7.24.4" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz" - integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ== +"@babel/compat-data@^7.24.8": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.9.tgz#53eee4e68f1c1d0282aa0eb05ddb02d033fc43a0" + integrity sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng== -"@babel/core@^7.23.5": - version "7.24.4" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz" - integrity sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg== +"@babel/core@^7.24.5": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.9.tgz#dc07c9d307162c97fa9484ea997ade65841c7c82" + integrity sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.2" - "@babel/generator" "^7.24.4" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.24.4" - "@babel/parser" "^7.24.4" - "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.1" - "@babel/types" "^7.24.0" + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.9" + "@babel/helper-compilation-targets" "^7.24.8" + "@babel/helper-module-transforms" "^7.24.9" + "@babel/helpers" "^7.24.8" + "@babel/parser" "^7.24.8" + "@babel/template" "^7.24.7" + "@babel/traverse" "^7.24.8" + "@babel/types" "^7.24.9" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.24.1", "@babel/generator@^7.24.4": - version "7.24.4" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz" - integrity sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw== +"@babel/generator@^7.24.8", "@babel/generator@^7.24.9": + version "7.24.10" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.10.tgz#a4ab681ec2a78bbb9ba22a3941195e28a81d8e76" + integrity sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg== dependencies: - "@babel/types" "^7.24.0" + "@babel/types" "^7.24.9" "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" -"@babel/helper-compilation-targets@^7.23.6": - version "7.23.6" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz" - integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== +"@babel/helper-compilation-targets@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz#b607c3161cd9d1744977d4f97139572fe778c271" + integrity sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw== dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-validator-option" "^7.23.5" - browserslist "^4.22.2" + "@babel/compat-data" "^7.24.8" + "@babel/helper-validator-option" "^7.24.8" + browserslist "^4.23.1" lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.22.15": - version "7.24.3" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz" - integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg== - dependencies: - "@babel/types" "^7.24.0" - -"@babel/helper-module-transforms@^7.23.3": - version "7.23.3" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz" - integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/helper-validator-identifier" "^7.22.20" - -"@babel/helper-plugin-utils@^7.24.0": - version "7.24.0" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz" - integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== - -"@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.23.4": - version "7.24.1" - resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz" - integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-option@^7.23.5": - version "7.23.5" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz" - integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== - -"@babel/helpers@^7.24.4": - version "7.24.4" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz" - integrity sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw== - dependencies: - "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.1" - "@babel/types" "^7.24.0" - -"@babel/highlight@^7.24.2": - version "7.24.2" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz" - integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" +"@babel/helper-environment-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" + integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-function-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz#75f1e1725742f39ac6584ee0b16d94513da38dd2" + integrity sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA== + dependencies: + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-hoist-variables@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz#b4ede1cde2fd89436397f30dc9376ee06b0f25ee" + integrity sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" + integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-module-transforms@^7.24.9": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz#e13d26306b89eea569180868e652e7f514de9d29" + integrity sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" + +"@babel/helper-plugin-utils@^7.24.7": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz#94ee67e8ec0e5d44ea7baeb51e571bd26af07878" + integrity sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg== + +"@babel/helper-simple-access@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" + integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-split-export-declaration@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz#83949436890e07fa3d6873c61a96e3bbf692d856" + integrity sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-string-parser@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" + integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== + +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + +"@babel/helper-validator-option@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" + integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q== + +"@babel/helpers@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.8.tgz#2820d64d5d6686cca8789dd15b074cd862795873" + integrity sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ== + dependencies: + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.8" + +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" chalk "^2.4.2" js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.24.0", "@babel/parser@^7.24.1", "@babel/parser@^7.24.4": - version "7.24.4" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz" - integrity sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg== +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.24.7", "@babel/parser@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.8.tgz#58a4dbbcad7eb1d48930524a3fd93d93e9084c6f" + integrity sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w== -"@babel/plugin-transform-react-jsx-self@^7.23.3": - version "7.24.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.1.tgz" - integrity sha512-kDJgnPujTmAZ/9q2CN4m2/lRsUUPDvsG3+tSHWUJIzMGTt5U/b/fwWd3RO3n+5mjLrsBrVa5eKFRVSQbi3dF1w== +"@babel/plugin-transform-react-jsx-self@^7.24.5": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz#66bff0248ea0b549972e733516ffad577477bdab" + integrity sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-react-jsx-source@^7.23.3": - version "7.24.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.1.tgz" - integrity sha512-1v202n7aUq4uXAieRTKcwPzNyphlCuqHHDcdSNc+vdhoTEZcFMh+L5yZuCmGaIO7bs1nJUNfHB89TZyoL48xNA== +"@babel/plugin-transform-react-jsx-source@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz#1198aab2548ad19582013815c938d3ebd8291ee3" + integrity sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/runtime@^7.11.2", "@babel/runtime@^7.17.8", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": +"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.9", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.24.8" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.8.tgz#5d958c3827b13cc6d05e038c07fb2e5e3420d82e" integrity sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA== dependencies: regenerator-runtime "^0.14.0" -"@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.18.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.8.3", "@babel/runtime@^7.9.2": - version "7.24.4" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz" - integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA== +"@babel/template@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315" + integrity sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig== dependencies: - regenerator-runtime "^0.14.0" + "@babel/code-frame" "^7.24.7" + "@babel/parser" "^7.24.7" + "@babel/types" "^7.24.7" -"@babel/template@^7.22.15", "@babel/template@^7.24.0": - version "7.24.0" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz" - integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/parser" "^7.24.0" - "@babel/types" "^7.24.0" - -"@babel/traverse@^7.24.1": - version "7.24.1" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz" - integrity sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ== - dependencies: - "@babel/code-frame" "^7.24.1" - "@babel/generator" "^7.24.1" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.24.1" - "@babel/types" "^7.24.0" +"@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.8.tgz#6c14ed5232b7549df3371d820fbd9abfcd7dfab7" + integrity sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.8" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-hoist-variables" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/parser" "^7.24.8" + "@babel/types" "^7.24.8" debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.24.0": - version "7.24.0" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz" - integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w== +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.24.9": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.9.tgz#228ce953d7b0d16646e755acf204f4cf3d08cc73" + integrity sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ== dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" + "@babel/helper-string-parser" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" "@biomejs/biome@1.8.3": @@ -291,16 +282,16 @@ resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-x64/-/cli-win32-x64-1.8.3.tgz#6a9dc5a4e13357277da43c015cd5cdc374035448" integrity sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg== -"@emotion/babel-plugin@^11.11.0": - version "11.11.0" - resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz" - integrity sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ== +"@emotion/babel-plugin@^11.12.0": + version "11.12.0" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz#7b43debb250c313101b3f885eba634f1d723fcc2" + integrity sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw== dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/runtime" "^7.18.3" - "@emotion/hash" "^0.9.1" - "@emotion/memoize" "^0.8.1" - "@emotion/serialize" "^1.1.2" + "@emotion/hash" "^0.9.2" + "@emotion/memoize" "^0.9.0" + "@emotion/serialize" "^1.2.0" babel-plugin-macros "^3.1.0" convert-source-map "^1.5.0" escape-string-regexp "^4.0.0" @@ -308,262 +299,230 @@ source-map "^0.5.7" stylis "4.2.0" -"@emotion/cache@^11.11.0": - version "11.11.0" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff" - integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ== +"@emotion/cache@^11.11.0", "@emotion/cache@^11.13.0": + version "11.13.0" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.13.0.tgz#8f51748b8116691dee0408b08ad758b8d246b097" + integrity sha512-hPV345J/tH0Cwk2wnU/3PBzORQ9HeX+kQSbwI+jslzpRCHE6fSGTohswksA/Ensr8znPzwfzKZCmAM9Lmlhp7g== dependencies: - "@emotion/memoize" "^0.8.1" - "@emotion/sheet" "^1.2.2" - "@emotion/utils" "^1.2.1" - "@emotion/weak-memoize" "^0.3.1" + "@emotion/memoize" "^0.9.0" + "@emotion/sheet" "^1.4.0" + "@emotion/utils" "^1.4.0" + "@emotion/weak-memoize" "^0.4.0" stylis "4.2.0" "@emotion/hash@^0.8.0": version "0.8.0" - resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== -"@emotion/hash@^0.9.1": - version "0.9.1" - resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz" - integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== +"@emotion/hash@^0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b" + integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g== -"@emotion/is-prop-valid@^1.2.2": - version "1.2.2" - resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz" - integrity sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw== +"@emotion/is-prop-valid@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz#bd84ba972195e8a2d42462387581560ef780e4e2" + integrity sha512-SHetuSLvJDzuNbOdtPVbq6yMMMlLoW5Q94uDqJZqy50gcmAjxFkVqmzqSGEFq9gT2iMuIeKV1PXVWmvUhuZLlQ== dependencies: - "@emotion/memoize" "^0.8.1" + "@emotion/memoize" "^0.9.0" -"@emotion/memoize@^0.8.1": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" - integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== +"@emotion/memoize@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102" + integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ== "@emotion/react@^11.11.4": - version "11.11.4" - resolved "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz" - integrity sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw== + version "11.13.0" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.13.0.tgz#a9ebf827b98220255e5760dac89fa2d38ca7b43d" + integrity sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ== dependencies: "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.11.0" - "@emotion/cache" "^11.11.0" - "@emotion/serialize" "^1.1.3" - "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" - "@emotion/utils" "^1.2.1" - "@emotion/weak-memoize" "^0.3.1" + "@emotion/babel-plugin" "^11.12.0" + "@emotion/cache" "^11.13.0" + "@emotion/serialize" "^1.3.0" + "@emotion/use-insertion-effect-with-fallbacks" "^1.1.0" + "@emotion/utils" "^1.4.0" + "@emotion/weak-memoize" "^0.4.0" hoist-non-react-statics "^3.3.1" -"@emotion/serialize@^1.1.2", "@emotion/serialize@^1.1.3", "@emotion/serialize@^1.1.4": - version "1.1.4" - resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz" - integrity sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ== +"@emotion/serialize@^1.2.0", "@emotion/serialize@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.0.tgz#e07cadfc967a4e7816e0c3ffaff4c6ce05cb598d" + integrity sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA== dependencies: - "@emotion/hash" "^0.9.1" - "@emotion/memoize" "^0.8.1" - "@emotion/unitless" "^0.8.1" - "@emotion/utils" "^1.2.1" + "@emotion/hash" "^0.9.2" + "@emotion/memoize" "^0.9.0" + "@emotion/unitless" "^0.9.0" + "@emotion/utils" "^1.4.0" csstype "^3.0.2" -"@emotion/sheet@^1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec" - integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA== +"@emotion/sheet@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.4.0.tgz#c9299c34d248bc26e82563735f78953d2efca83c" + integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg== "@emotion/styled@^11.11.5": - version "11.11.5" - resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz" - integrity sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ== + version "11.13.0" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.13.0.tgz#633fd700db701472c7a5dbef54d6f9834e9fb190" + integrity sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA== dependencies: "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.11.0" - "@emotion/is-prop-valid" "^1.2.2" - "@emotion/serialize" "^1.1.4" - "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" - "@emotion/utils" "^1.2.1" - -"@emotion/unitless@^0.8.1": - version "0.8.1" - resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz" - integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ== - -"@emotion/use-insertion-effect-with-fallbacks@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz" - integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw== + "@emotion/babel-plugin" "^11.12.0" + "@emotion/is-prop-valid" "^1.3.0" + "@emotion/serialize" "^1.3.0" + "@emotion/use-insertion-effect-with-fallbacks" "^1.1.0" + "@emotion/utils" "^1.4.0" + +"@emotion/unitless@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.9.0.tgz#8e5548f072bd67b8271877e51c0f95c76a66cbe2" + integrity sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ== + +"@emotion/use-insertion-effect-with-fallbacks@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz#1a818a0b2c481efba0cf34e5ab1e0cb2dcb9dfaf" + integrity sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw== -"@emotion/utils@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4" - integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg== - -"@emotion/weak-memoize@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" - integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== - -"@esbuild/aix-ppc64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537" - integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g== - -"@esbuild/android-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9" - integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg== - -"@esbuild/android-arm@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995" - integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w== - -"@esbuild/android-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98" - integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg== - -"@esbuild/darwin-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb" - integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA== - -"@esbuild/darwin-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0" - integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA== - -"@esbuild/freebsd-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911" - integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw== - -"@esbuild/freebsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c" - integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw== - -"@esbuild/linux-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5" - integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A== - -"@esbuild/linux-arm@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c" - integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg== - -"@esbuild/linux-ia32@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa" - integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig== - -"@esbuild/linux-loong64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5" - integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ== - -"@esbuild/linux-mips64el@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa" - integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA== - -"@esbuild/linux-ppc64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20" - integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg== - -"@esbuild/linux-riscv64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300" - integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg== - -"@esbuild/linux-s390x@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685" - integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ== - -"@esbuild/linux-x64@0.20.2": - version "0.20.2" - resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz" - integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw== - -"@esbuild/netbsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6" - integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ== - -"@esbuild/openbsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf" - integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ== - -"@esbuild/sunos-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f" - integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w== - -"@esbuild/win32-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90" - integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ== - -"@esbuild/win32-ia32@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23" - integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ== - -"@esbuild/win32-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc" - integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ== - -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": - version "4.4.0" - resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== - dependencies: - eslint-visitor-keys "^3.3.0" - -"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": - version "4.10.0" - resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz" - integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== - -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" +"@emotion/utils@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.0.tgz#262f1d02aaedb2ec91c83a0955dd47822ad5fbdd" + integrity sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ== -"@eslint/js@8.57.0": - version "8.57.0" - resolved "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz" - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== +"@emotion/weak-memoize@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz#5e13fac887f08c44f76b0ccaf3370eb00fec9bb6" + integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg== + +"@esbuild/aix-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" + integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + +"@esbuild/android-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" + integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== + +"@esbuild/darwin-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== + +"@esbuild/darwin-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" + integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== + +"@esbuild/freebsd-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" + integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== + +"@esbuild/freebsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" + integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== + +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + +"@esbuild/linux-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" + integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== + +"@esbuild/linux-loong64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" + integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== + +"@esbuild/linux-mips64el@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" + integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== + +"@esbuild/linux-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" + integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== + +"@esbuild/linux-riscv64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" + integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== + +"@esbuild/linux-s390x@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" + integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== + +"@esbuild/linux-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" + integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + +"@esbuild/netbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" + integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== + +"@esbuild/openbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" + integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== + +"@esbuild/sunos-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" + integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== + +"@esbuild/win32-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" + integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== + +"@esbuild/win32-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" + integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== + +"@esbuild/win32-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" + integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== "@floating-ui/core@^1.6.0": - version "1.6.4" - resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.4.tgz#0140cf5091c8dee602bff9da5ab330840ff91df6" - integrity sha512-a4IowK4QkXl4SCWTGUR0INAfEOX3wtsYw3rKK5InQEHMGObkR8Xk44qYQD9P4r6HHw0iIfK6GUKECmY8sTkqRA== + version "1.6.5" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.5.tgz#102335cac0d22035b04d70ca5ff092d2d1a26f2b" + integrity sha512-8GrTWmoFhm5BsMZOTHeGD2/0FLKLQQHvO/ZmQga4tKempYRLz8aqJGqXVuQgisnMObq2YZ2SgkwctN1LOOxcqA== dependencies: - "@floating-ui/utils" "^0.2.4" + "@floating-ui/utils" "^0.2.5" "@floating-ui/dom@^1.0.0": - version "1.6.7" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.7.tgz#85d22f731fcc5b209db504478fb1df5116a83015" - integrity sha512-wmVfPG5o2xnKDU4jx/m4w5qva9FWHcnZ8BvzEe90D/RpwsJaTAVYPEPdQ8sbr/N8zZTAHlZUTQdqg8ZUbzHmng== + version "1.6.8" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.8.tgz#45e20532b6d8a061b356a4fb336022cf2609754d" + integrity sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q== dependencies: "@floating-ui/core" "^1.6.0" - "@floating-ui/utils" "^0.2.4" + "@floating-ui/utils" "^0.2.5" "@floating-ui/react-dom@^2.0.8": version "2.1.1" @@ -572,38 +531,19 @@ dependencies: "@floating-ui/dom" "^1.0.0" -"@floating-ui/utils@^0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.4.tgz#1d459cee5031893a08a0e064c406ad2130cced7c" - integrity sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA== - -"@humanwhocodes/config-array@^0.11.14": - version "0.11.14" - resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== - dependencies: - "@humanwhocodes/object-schema" "^2.0.2" - debug "^4.3.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.3" - resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz" - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@floating-ui/utils@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.5.tgz#105c37d9d9620ce69b7f692a20c821bf1ad2cbf9" + integrity sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ== "@icons/material@^0.2.4": version "0.2.4" - resolved "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz" + resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw== "@jridgewell/gen-mapping@^0.3.5": version "0.3.5" - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== dependencies: "@jridgewell/set-array" "^1.2.1" @@ -612,22 +552,22 @@ "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== "@jridgewell/set-array@^1.2.1": version "1.2.1" - resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== dependencies: "@jridgewell/resolve-uri" "^3.1.0" @@ -635,12 +575,12 @@ "@jsdevtools/ono@^7.1.3": version "7.1.3" - resolved "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz" + resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== "@material-ui/core@^4.1.3": version "4.12.4" - resolved "https://registry.npmjs.org/@material-ui/core/-/core-4.12.4.tgz" + resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.12.4.tgz#4ac17488e8fcaf55eb6a7f5efb2a131e10138a73" integrity sha512-tr7xekNlM9LjA6pagJmL8QCgZXaubWUwkJnoYcMKd4gw/t4XiyvnTkjdGrUVicyB2BsdaAv1tvow45bPM4sSwQ== dependencies: "@babel/runtime" "^7.4.4" @@ -658,7 +598,7 @@ "@material-ui/styles@^4.11.5": version "4.11.5" - resolved "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.5.tgz" + resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.11.5.tgz#19f84457df3aafd956ac863dbe156b1d88e2bbfb" integrity sha512-o/41ot5JJiUsIETME9wVLAJrmIWL3j0R0Bj2kCOLbSfqEkKf0fmaPt+5vtblUh5eXr2S+J/8J3DaCb10+CzPGA== dependencies: "@babel/runtime" "^7.4.4" @@ -680,7 +620,7 @@ "@material-ui/system@^4.12.2": version "4.12.2" - resolved "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz" + resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.12.2.tgz#f5c389adf3fce4146edd489bf4082d461d86aa8b" integrity sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw== dependencies: "@babel/runtime" "^7.4.4" @@ -690,12 +630,12 @@ "@material-ui/types@5.1.0": version "5.1.0" - resolved "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz" + resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-5.1.0.tgz#efa1c7a0b0eaa4c7c87ac0390445f0f88b0d88f2" integrity sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A== "@material-ui/utils@^4.11.3": version "4.11.3" - resolved "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz" + resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-4.11.3.tgz#232bd86c4ea81dab714f21edad70b7fdf0253942" integrity sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg== dependencies: "@babel/runtime" "^7.4.4" @@ -709,7 +649,7 @@ "@metacell/geppetto-meta-client@^1.2.8": version "1.2.8" - resolved "https://registry.npmjs.org/@metacell/geppetto-meta-client/-/geppetto-meta-client-1.2.8.tgz" + resolved "https://registry.yarnpkg.com/@metacell/geppetto-meta-client/-/geppetto-meta-client-1.2.8.tgz#84c3b791288452f987cb3a1e56a47c9a8952bd59" integrity sha512-pDORhlNYv5HILPaGPuJGFV5xLgvdtrtHklBfTW3jMfBAzbXO5qxRyslfpES2VxdcFGONW5Gr6KCbRWBmm2My+g== dependencies: "@material-ui/core" "^4.1.3" @@ -722,12 +662,12 @@ "@metacell/geppetto-meta-core@^1.2.8": version "1.2.8" - resolved "https://registry.npmjs.org/@metacell/geppetto-meta-core/-/geppetto-meta-core-1.2.8.tgz" + resolved "https://registry.yarnpkg.com/@metacell/geppetto-meta-core/-/geppetto-meta-core-1.2.8.tgz#34e991feb099bb63d3737b7f8495df5b8b1f3425" integrity sha512-1AMhQLw3+3YFufG2YUsgsxi3YGZx94VKloXq5aENZo5ZLW+aLvlSAUcRUl68LUPt/Axd+6xc1R7qGNOghv7Irw== "@metacell/geppetto-meta-ui@^1.2.8": version "1.2.8" - resolved "https://registry.npmjs.org/@metacell/geppetto-meta-ui/-/geppetto-meta-ui-1.2.8.tgz" + resolved "https://registry.yarnpkg.com/@metacell/geppetto-meta-ui/-/geppetto-meta-ui-1.2.8.tgz#3a6b34e561de88e88b892ae8bc80a32cc2e4b2a1" integrity sha512-wiC7GiJZWp66wUG4jIGcP1wieAi4fEtyncpEcNjwssuURSddixFnCkH0dSX5KwJ3PjDbHEyco6/M6nG+DYFJlw== "@monogrid/gainmap-js@^3.0.5": @@ -829,26 +769,10 @@ prop-types "^15.8.1" react-is "^18.3.1" -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" +"@petamoriken/float16@^3.4.7": + version "3.8.7" + resolved "https://registry.yarnpkg.com/@petamoriken/float16/-/float16-3.8.7.tgz#16073fb1b9867eaa5b254573484d09100700aaa4" + integrity sha512-/Ri4xDDpe12NT6Ex/DRgHzLlobiQXEW/hmG08w1wj/YU7hLemk97c+zHQFp0iZQ9r7YqgLEXZR2sls4HxBf9NA== "@popperjs/core@^2.11.8": version "2.11.8" @@ -902,9 +826,9 @@ integrity sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q== "@react-three/drei@^9.105.4": - version "9.108.4" - resolved "https://registry.yarnpkg.com/@react-three/drei/-/drei-9.108.4.tgz#d3eb3cedc35df8523b99467a84af52250b724960" - integrity sha512-YyPVG7+np6G8CJRVVdEfgK+bou7cvp8v9R7k4NSHsoi5EokFPG03tkCjniRiz5SzQyN+E8kCiMogI9oZaop5+g== + version "9.109.2" + resolved "https://registry.yarnpkg.com/@react-three/drei/-/drei-9.109.2.tgz#37e79924550614d7e3db32c5d115188c4e3f01af" + integrity sha512-oUbfjiyPQeQch4Mi3jZvFKigMlc97/xvazxyjPBCGa8RP8cHZJl187eZI9Ha1WwkVaX80DfgN7bYAWXS4ywxmw== dependencies: "@babel/runtime" "^7.11.2" "@mediapipe/tasks-vision" "0.10.8" @@ -957,85 +881,85 @@ redux-thunk "^3.1.0" reselect "^5.1.0" -"@rollup/rollup-android-arm-eabi@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.3.tgz#bddf05c3387d02fac04b6b86b3a779337edfed75" - integrity sha512-X9alQ3XM6I9IlSlmC8ddAvMSyG1WuHk5oUnXGw+yUBs3BFoTizmG1La/Gr8fVJvDWAq+zlYTZ9DBgrlKRVY06g== - -"@rollup/rollup-android-arm64@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.3.tgz#b26bd09de58704c0a45e3375b76796f6eda825e4" - integrity sha512-eQK5JIi+POhFpzk+LnjKIy4Ks+pwJ+NXmPxOCSvOKSNRPONzKuUvWE+P9JxGZVxrtzm6BAYMaL50FFuPe0oWMQ== - -"@rollup/rollup-darwin-arm64@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.3.tgz#c5f3fd1aa285b6d33dda6e3f3ca395f8c37fd5ca" - integrity sha512-Od4vE6f6CTT53yM1jgcLqNfItTsLt5zE46fdPaEmeFHvPs5SjZYlLpHrSiHEKR1+HdRfxuzXHjDOIxQyC3ptBA== - -"@rollup/rollup-darwin-x64@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.3.tgz#8e4673734d7dc9d68f6d48e81246055cda0e840f" - integrity sha512-0IMAO21axJeNIrvS9lSe/PGthc8ZUS+zC53O0VhF5gMxfmcKAP4ESkKOCwEi6u2asUrt4mQv2rjY8QseIEb1aw== - -"@rollup/rollup-linux-arm-gnueabihf@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.3.tgz#53ed38eb13b58ababdb55a7f66f0538a7f85dcba" - integrity sha512-ge2DC7tHRHa3caVEoSbPRJpq7azhG+xYsd6u2MEnJ6XzPSzQsTKyXvh6iWjXRf7Rt9ykIUWHtl0Uz3T6yXPpKw== - -"@rollup/rollup-linux-arm-musleabihf@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.14.3.tgz#0706ee38330e267a5c9326956820f009cfb21fcd" - integrity sha512-ljcuiDI4V3ySuc7eSk4lQ9wU8J8r8KrOUvB2U+TtK0TiW6OFDmJ+DdIjjwZHIw9CNxzbmXY39wwpzYuFDwNXuw== - -"@rollup/rollup-linux-arm64-gnu@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.3.tgz#426fce7b8b242ac5abd48a10a5020f5a468c6cb4" - integrity sha512-Eci2us9VTHm1eSyn5/eEpaC7eP/mp5n46gTRB3Aar3BgSvDQGJZuicyq6TsH4HngNBgVqC5sDYxOzTExSU+NjA== - -"@rollup/rollup-linux-arm64-musl@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.3.tgz#65bf944530d759b50d7ffd00dfbdf4125a43406f" - integrity sha512-UrBoMLCq4E92/LCqlh+blpqMz5h1tJttPIniwUgOFJyjWI1qrtrDhhpHPuFxULlUmjFHfloWdixtDhSxJt5iKw== - -"@rollup/rollup-linux-powerpc64le-gnu@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.3.tgz#494ba3b31095e9a45df9c3f646d21400fb631a95" - integrity sha512-5aRjvsS8q1nWN8AoRfrq5+9IflC3P1leMoy4r2WjXyFqf3qcqsxRCfxtZIV58tCxd+Yv7WELPcO9mY9aeQyAmw== - -"@rollup/rollup-linux-riscv64-gnu@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.3.tgz#8b88ed0a40724cce04aa15374ebe5ba4092d679f" - integrity sha512-sk/Qh1j2/RJSX7FhEpJn8n0ndxy/uf0kI/9Zc4b1ELhqULVdTfN6HL31CDaTChiBAOgLcsJ1sgVZjWv8XNEsAQ== - -"@rollup/rollup-linux-s390x-gnu@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.3.tgz#09c9e5ec57a0f6ec3551272c860bb9a04b96d70f" - integrity sha512-jOO/PEaDitOmY9TgkxF/TQIjXySQe5KVYB57H/8LRP/ux0ZoO8cSHCX17asMSv3ruwslXW/TLBcxyaUzGRHcqg== - -"@rollup/rollup-linux-x64-gnu@4.14.3": - version "4.14.3" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.3.tgz" - integrity sha512-8ybV4Xjy59xLMyWo3GCfEGqtKV5M5gCSrZlxkPGvEPCGDLNla7v48S662HSGwRd6/2cSneMQWiv+QzcttLrrOA== - -"@rollup/rollup-linux-x64-musl@4.14.3": - version "4.14.3" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.3.tgz" - integrity sha512-s+xf1I46trOY10OqAtZ5Rm6lzHre/UiLA1J2uOhCFXWkbZrJRkYBPO6FhvGfHmdtQ3Bx793MNa7LvoWFAm93bg== - -"@rollup/rollup-win32-arm64-msvc@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.3.tgz#a648122389d23a7543b261fba082e65fefefe4f6" - integrity sha512-+4h2WrGOYsOumDQ5S2sYNyhVfrue+9tc9XcLWLh+Kw3UOxAvrfOrSMFon60KspcDdytkNDh7K2Vs6eMaYImAZg== - -"@rollup/rollup-win32-ia32-msvc@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.3.tgz#34727b5c7953c35fc6e1ae4f770ad3a2025f8e03" - integrity sha512-T1l7y/bCeL/kUwh9OD4PQT4aM7Bq43vX05htPJJ46RTI4r5KNt6qJRzAfNfM+OYMNEVBWQzR2Gyk+FXLZfogGw== - -"@rollup/rollup-win32-x64-msvc@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.3.tgz#5b2fb4d8cd44c05deef8a7b0e6deb9ccb8939d18" - integrity sha512-/BypzV0H1y1HzgYpxqRaXGBRqfodgoBBCcsrujT6QRcakDQdfU+Lq9PENPh5jB4I44YWq+0C2eHsHya+nZY1sA== +"@rollup/rollup-android-arm-eabi@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.0.tgz#3d9fd50164b94964f5de68c3c4ce61933b3a338d" + integrity sha512-JlPfZ/C7yn5S5p0yKk7uhHTTnFlvTgLetl2VxqE518QgyM7C9bSfFTYvB/Q/ftkq0RIPY4ySxTz+/wKJ/dXC0w== + +"@rollup/rollup-android-arm64@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.0.tgz#e1a6d4bca2eb08c84fd996a4bf896ce4b6f4014c" + integrity sha512-RDxUSY8D1tWYfn00DDi5myxKgOk6RvWPxhmWexcICt/MEC6yEMr4HNCu1sXXYLw8iAsg0D44NuU+qNq7zVWCrw== + +"@rollup/rollup-darwin-arm64@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.0.tgz#0a3fffea69489a24a96079af414b0be78df8abbc" + integrity sha512-emvKHL4B15x6nlNTBMtIaC9tLPRpeA5jMvRLXVbl/W9Ie7HhkrE7KQjvgS9uxgatL1HmHWDXk5TTS4IaNJxbAA== + +"@rollup/rollup-darwin-x64@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.0.tgz#13fbdb15f58f090871b0ffff047ece06ad6ad74c" + integrity sha512-fO28cWA1dC57qCd+D0rfLC4VPbh6EOJXrreBmFLWPGI9dpMlER2YwSPZzSGfq11XgcEpPukPTfEVFtw2q2nYJg== + +"@rollup/rollup-linux-arm-gnueabihf@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.0.tgz#e9d9219ddf6f6e946e2ee322198af12466d2c868" + integrity sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw== + +"@rollup/rollup-linux-arm-musleabihf@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.0.tgz#4ba804a00b5e793196a622f6977e05f23e01f59a" + integrity sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ== + +"@rollup/rollup-linux-arm64-gnu@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.0.tgz#d871e3f41de759a6db27fc99235b782ba47c15cc" + integrity sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug== + +"@rollup/rollup-linux-arm64-musl@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.0.tgz#6e63f7ad4cc51bd2c693a2826fd279de9eaa05b5" + integrity sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ== + +"@rollup/rollup-linux-powerpc64le-gnu@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.0.tgz#1540b284d91c440bc9fa7a1714cfb71a5597e94d" + integrity sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ== + +"@rollup/rollup-linux-riscv64-gnu@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.0.tgz#70ae58103b5bc7ba2e2235738b51d97022c8ef92" + integrity sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg== + +"@rollup/rollup-linux-s390x-gnu@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.0.tgz#579ca5f271421a961d3c73d221202c79e02ff03a" + integrity sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA== + +"@rollup/rollup-linux-x64-gnu@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.0.tgz#f0282d761b8b4e7b92b236813475248e37231849" + integrity sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA== + +"@rollup/rollup-linux-x64-musl@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.0.tgz#65da807ac66c505ad14b76f1e5976006cb67dd5f" + integrity sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A== + +"@rollup/rollup-win32-arm64-msvc@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.0.tgz#1eed24b91f421c2eea8bb7ca8889ba0c867e1780" + integrity sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg== + +"@rollup/rollup-win32-ia32-msvc@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.0.tgz#1ed93c9cdc84e185359797a686f4d1576afcea58" + integrity sha512-xItlIAZZaiG/u0wooGzRsx11rokP4qyc/79LkAOdznGRAbOFc+SfEdfUOszG1odsHNgwippUJavag/+W/Etc6Q== + +"@rollup/rollup-win32-x64-msvc@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.0.tgz#baf9b65023ea2ecc5e6ec68f787a0fecfd8ee84c" + integrity sha512-xNo5fV5ycvCCKqiZcpB65VMR11NJB+StnxHz20jdqRAktfdfzhgjTiJ2doTDQE/7dqGaV5I7ZGqKpgph6lCIag== "@tweenjs/tween.js@~23.1.1", "@tweenjs/tween.js@~23.1.2": version "23.1.2" @@ -1044,7 +968,7 @@ "@types/babel__core@^7.20.5": version "7.20.5" - resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== dependencies: "@babel/parser" "^7.20.7" @@ -1055,30 +979,30 @@ "@types/babel__generator@*": version "7.6.8" - resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== dependencies: "@babel/types" "^7.0.0" "@types/babel__template@*": version "7.4.4" - resolved "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" "@types/babel__traverse@*": - version "7.20.5" - resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz" - integrity sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ== + version "7.20.6" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" + integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== dependencies: "@babel/types" "^7.20.7" -"@types/cytoscape@^3.21.1": - version "3.21.1" - resolved "https://registry.npmjs.org/@types/cytoscape/-/cytoscape-3.21.1.tgz" - integrity sha512-vBC2w0ciULoay50QnSScFg9Yu/9gimyor3vb4b4gEEI+4Ccfu/AH7gA+YKAcFIvo1mgKVhXaewNxw3zC80cXoA== +"@types/cytoscape@^3.21.5": + version "3.21.5" + resolved "https://registry.yarnpkg.com/@types/cytoscape/-/cytoscape-3.21.5.tgz#43ea460b2809ff424225377f270750f674c27f75" + integrity sha512-fzYT3vqY5J4gxVXDOsCgDpm0ZdU8bQq+wCv0ucS0MSTtvQdjs3lcb2VetJiUSAd4WBgouqizI+JT1f8Yc6eY7Q== "@types/draco3d@^1.4.0": version "1.4.10" @@ -1087,12 +1011,12 @@ "@types/estree@1.0.5": version "1.0.5" - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== "@types/hoist-non-react-statics@^3.3.0": version "3.3.5" - resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz#dab7867ef789d87e2b4b0003c9d65c49cc44a494" integrity sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg== dependencies: "@types/react" "*" @@ -1100,7 +1024,7 @@ "@types/json-schema@^7.0.15": version "7.0.15" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/offscreencanvas@^2019.6.4": @@ -1110,7 +1034,7 @@ "@types/parse-json@^4.0.0": version "4.0.2" - resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== "@types/prop-types@*", "@types/prop-types@^15.7.12": @@ -1118,10 +1042,10 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== -"@types/react-dom@^18.2.22": - version "18.2.25" - resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.25.tgz" - integrity sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA== +"@types/react-dom@^18.3.0": + version "18.3.0" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0" + integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg== dependencies: "@types/react" "*" @@ -1141,7 +1065,7 @@ "@types/react-redux@^7.1.20": version "7.1.33" - resolved "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.33.tgz" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.33.tgz#53c5564f03f1ded90904e3c90f77e4bd4dc20b15" integrity sha512-NF8m5AjWCkert+fosDsN3hAlHzpjSiXlVy9EgQEmLoBhaNXbmyeGs/aj5dQzKuF+/q+S7JQagorGDW8pJ28Hmg== dependencies: "@types/hoist-non-react-statics" "^3.3.0" @@ -1151,12 +1075,12 @@ "@types/react-transition-group@^4.2.0", "@types/react-transition-group@^4.4.10": version "4.4.10" - resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.10.tgz#6ee71127bdab1f18f11ad8fb3322c6da27c327ac" integrity sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q== dependencies: "@types/react" "*" -"@types/react@*": +"@types/react@*", "@types/react@^18.3.3": version "18.3.3" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f" integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== @@ -1164,19 +1088,6 @@ "@types/prop-types" "*" csstype "^3.0.2" -"@types/react@^18.2.66": - version "18.2.79" - resolved "https://registry.npmjs.org/@types/react/-/react-18.2.79.tgz" - integrity sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w== - dependencies: - "@types/prop-types" "*" - csstype "^3.0.2" - -"@types/semver@^7.5.8": - version "7.5.8" - resolved "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz" - integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== - "@types/stats.js@*": version "0.17.3" resolved "https://registry.yarnpkg.com/@types/stats.js/-/stats.js-0.17.3.tgz#705446e12ce0fad618557dd88236f51148b7a935" @@ -1214,97 +1125,6 @@ resolved "https://registry.yarnpkg.com/@types/webxr/-/webxr-0.5.19.tgz#463a27bc06ff1c0a0c997e86b48bf24c5f50a4af" integrity sha512-4hxA+NwohSgImdTSlPXEqDqqFktNgmTXQ05ff1uWam05tNGroCMp4G+4XVl6qWm1p7GQ/9oD41kAYsSssF6Mzw== -"@typescript-eslint/eslint-plugin@^7.2.0": - version "7.7.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.0.tgz" - integrity sha512-GJWR0YnfrKnsRoluVO3PRb9r5aMZriiMMM/RHj5nnTrBy1/wIgk76XCtCKcnXGjpZQJQRFtGV9/0JJ6n30uwpQ== - dependencies: - "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "7.7.0" - "@typescript-eslint/type-utils" "7.7.0" - "@typescript-eslint/utils" "7.7.0" - "@typescript-eslint/visitor-keys" "7.7.0" - debug "^4.3.4" - graphemer "^1.4.0" - ignore "^5.3.1" - natural-compare "^1.4.0" - semver "^7.6.0" - ts-api-utils "^1.3.0" - -"@typescript-eslint/parser@^7.2.0": - version "7.7.0" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.7.0.tgz" - integrity sha512-fNcDm3wSwVM8QYL4HKVBggdIPAy9Q41vcvC/GtDobw3c4ndVT3K6cqudUmjHPw8EAp4ufax0o58/xvWaP2FmTg== - dependencies: - "@typescript-eslint/scope-manager" "7.7.0" - "@typescript-eslint/types" "7.7.0" - "@typescript-eslint/typescript-estree" "7.7.0" - "@typescript-eslint/visitor-keys" "7.7.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@7.7.0": - version "7.7.0" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.0.tgz" - integrity sha512-/8INDn0YLInbe9Wt7dK4cXLDYp0fNHP5xKLHvZl3mOT5X17rK/YShXaiNmorl+/U4VKCVIjJnx4Ri5b0y+HClw== - dependencies: - "@typescript-eslint/types" "7.7.0" - "@typescript-eslint/visitor-keys" "7.7.0" - -"@typescript-eslint/type-utils@7.7.0": - version "7.7.0" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.7.0.tgz" - integrity sha512-bOp3ejoRYrhAlnT/bozNQi3nio9tIgv3U5C0mVDdZC7cpcQEDZXvq8inrHYghLVwuNABRqrMW5tzAv88Vy77Sg== - dependencies: - "@typescript-eslint/typescript-estree" "7.7.0" - "@typescript-eslint/utils" "7.7.0" - debug "^4.3.4" - ts-api-utils "^1.3.0" - -"@typescript-eslint/types@7.7.0": - version "7.7.0" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.0.tgz" - integrity sha512-G01YPZ1Bd2hn+KPpIbrAhEWOn5lQBrjxkzHkWvP6NucMXFtfXoevK82hzQdpfuQYuhkvFDeQYbzXCjR1z9Z03w== - -"@typescript-eslint/typescript-estree@7.7.0": - version "7.7.0" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.0.tgz" - integrity sha512-8p71HQPE6CbxIBy2kWHqM1KGrC07pk6RJn40n0DSc6bMOBBREZxSDJ+BmRzc8B5OdaMh1ty3mkuWRg4sCFiDQQ== - dependencies: - "@typescript-eslint/types" "7.7.0" - "@typescript-eslint/visitor-keys" "7.7.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "^9.0.4" - semver "^7.6.0" - ts-api-utils "^1.3.0" - -"@typescript-eslint/utils@7.7.0": - version "7.7.0" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.7.0.tgz" - integrity sha512-LKGAXMPQs8U/zMRFXDZOzmMKgFv3COlxUQ+2NMPhbqgVm6R1w+nU1i4836Pmxu9jZAuIeyySNrN/6Rc657ggig== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.15" - "@types/semver" "^7.5.8" - "@typescript-eslint/scope-manager" "7.7.0" - "@typescript-eslint/types" "7.7.0" - "@typescript-eslint/typescript-estree" "7.7.0" - semver "^7.6.0" - -"@typescript-eslint/visitor-keys@7.7.0": - version "7.7.0" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.0.tgz" - integrity sha512-h0WHOj8MhdhY8YWkzIF30R379y0NqyOHExI9N9KCzvmu05EgG4FumeYa3ccfKUSphyWkWQE1ybVrgz/Pbam6YA== - dependencies: - "@typescript-eslint/types" "7.7.0" - eslint-visitor-keys "^3.4.3" - -"@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== - "@use-gesture/core@10.3.1": version "10.3.1" resolved "https://registry.yarnpkg.com/@use-gesture/core/-/core-10.3.1.tgz#976c9421e905f0079d49822cfd5c2e56b808fc56" @@ -1318,58 +1138,26 @@ "@use-gesture/core" "10.3.1" "@vitejs/plugin-react@^4.2.1": - version "4.2.1" - resolved "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz" - integrity sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ== + version "4.3.1" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz#d0be6594051ded8957df555ff07a991fb618b48e" + integrity sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg== dependencies: - "@babel/core" "^7.23.5" - "@babel/plugin-transform-react-jsx-self" "^7.23.3" - "@babel/plugin-transform-react-jsx-source" "^7.23.3" + "@babel/core" "^7.24.5" + "@babel/plugin-transform-react-jsx-self" "^7.24.5" + "@babel/plugin-transform-react-jsx-source" "^7.24.1" "@types/babel__core" "^7.20.5" - react-refresh "^0.14.0" - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.9.0: - version "8.11.3" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - -ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + react-refresh "^0.14.2" ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - anymatch@~3.1.2: version "3.1.3" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" @@ -1377,28 +1165,18 @@ anymatch@~3.1.2: argparse@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - babel-plugin-macros@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== dependencies: "@babel/runtime" "^7.12.5" cosmiconfig "^7.0.0" resolve "^1.19.0" -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -1413,40 +1191,25 @@ bidi-js@^1.0.2: binary-extensions@^2.0.0: version "2.3.0" - resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== +braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" -browserslist@^4.22.2: - version "4.23.0" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz" - integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== +browserslist@^4.23.1: + version "4.23.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.2.tgz#244fe803641f1c19c28c48c4b6ec9736eb3d32ed" + integrity sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA== dependencies: - caniuse-lite "^1.0.30001587" - electron-to-chromium "^1.4.668" + caniuse-lite "^1.0.30001640" + electron-to-chromium "^1.4.820" node-releases "^2.0.14" - update-browserslist-db "^1.0.13" + update-browserslist-db "^1.1.0" buffer@^6.0.3: version "6.0.3" @@ -1458,12 +1221,12 @@ buffer@^6.0.3: callsites@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase@^6.3.0: version "6.3.0" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== camera-controls@^2.4.2: @@ -1471,31 +1234,23 @@ camera-controls@^2.4.2: resolved "https://registry.yarnpkg.com/camera-controls/-/camera-controls-2.8.5.tgz#9d7e39cf17172c62fc4a79346b972c3408d0ea35" integrity sha512-7VTwRk7Nu1nRKsY7bEt9HVBfKt8DETvzyYhLN4OW26OByBayMDB5fUaNcPI+z++vG23RH5yqn6ZRhZcgLQy2rA== -caniuse-lite@^1.0.30001587: - version "1.0.30001611" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001611.tgz" - integrity sha512-19NuN1/3PjA3QI8Eki55N8my4LzfkMCRLgCVfrl/slbSAchQfV0+GwjPrK3rq37As4UCLlM/DHajbKkAqbv92Q== +caniuse-lite@^1.0.30001640: + version "1.0.30001643" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz#9c004caef315de9452ab970c3da71085f8241dbd" + integrity sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg== chalk@^2.4.2: version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: - version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - "chokidar@>=3.0.0 <4.0.0": version "3.6.0" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== dependencies: anymatch "~3.1.2" @@ -1510,12 +1265,12 @@ chalk@^4.0.0: classnames@^2.2.5: version "2.5.1" - resolved "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== clsx@^1.0.4: version "1.2.1" - resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== clsx@^2.1.0, clsx@^2.1.1: @@ -1525,58 +1280,66 @@ clsx@^2.1.0, clsx@^2.1.1: color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - color-name@1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-2.0.0.tgz#03ff6b1b5aec9bb3cf1ed82400c2790dfcd01d2d" + integrity sha512-SbtvAMWvASO5TE2QP07jHBMXKafgdZz8Vrsrn96fiL+O92/FN/PLARzUW5sKt013fjAprK2d2iCn2hk2Xb5oow== -commander@^12.0.0: - version "12.0.0" - resolved "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz" - integrity sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA== +color-parse@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/color-parse/-/color-parse-2.0.2.tgz#37b46930424924060988edf25b24e6ffb4a1dc3f" + integrity sha512-eCtOz5w5ttWIUcaKLiktF+DxZO1R9KLNY/xhbV6CkhM7sR3GhVghmt6X6yOnzeaM24po+Z9/S1apbXMwA3Iepw== + dependencies: + color-name "^2.0.0" -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +color-rgba@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/color-rgba/-/color-rgba-3.0.0.tgz#77090bdcdb2951c1735e20099ddd50401675375b" + integrity sha512-PPwZYkEY3M2THEHHV6Y95sGUie77S7X8v+h1r6LSAPF3/LL2xJ8duUXSrkic31Nzc4odPwHgUbiX/XuTYzQHQg== + dependencies: + color-parse "^2.0.0" + color-space "^2.0.0" + +color-space@^2.0.0, color-space@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-space/-/color-space-2.0.1.tgz#da39871175baf4a5785ba519397df04b8d67e0fa" + integrity sha512-nKqUYlo0vZATVOFHY810BSYjmCARrG7e5R3UE3CQlyjJTvv5kSSmPG1kzm/oDyyqjehM+lW1RnEt9It9GNa5JA== + +commander@^12.0.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== convert-source-map@^1.5.0: version "1.9.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== convert-source-map@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== cose-base@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/cose-base/-/cose-base-2.2.0.tgz#1c395c35b6e10bb83f9769ca8b817d614add5c01" integrity sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g== dependencies: layout-base "^2.0.0" cosmiconfig@^7.0.0: version "7.1.0" - resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== dependencies: "@types/parse-json" "^4.0.0" @@ -1592,9 +1355,9 @@ cross-env@^7.0.3: dependencies: cross-spawn "^7.0.1" -cross-spawn@^7.0.1, cross-spawn@^7.0.2: +cross-spawn@^7.0.1: version "7.0.3" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" @@ -1603,7 +1366,7 @@ cross-spawn@^7.0.1, cross-spawn@^7.0.2: css-vendor@^2.0.8: version "2.0.8" - resolved "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz" + resolved "https://registry.yarnpkg.com/css-vendor/-/css-vendor-2.0.8.tgz#e47f91d3bd3117d49180a3c935e62e3d9f7f449d" integrity sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ== dependencies: "@babel/runtime" "^7.8.3" @@ -1611,7 +1374,7 @@ css-vendor@^2.0.8: csstype@^2.5.2: version "2.6.21" - resolved "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e" integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w== csstype@^3.0.2, csstype@^3.1.3: @@ -1621,26 +1384,26 @@ csstype@^3.0.2, csstype@^3.1.3: cytoscape-dagre@^2.5.0: version "2.5.0" - resolved "https://registry.npmjs.org/cytoscape-dagre/-/cytoscape-dagre-2.5.0.tgz" + resolved "https://registry.yarnpkg.com/cytoscape-dagre/-/cytoscape-dagre-2.5.0.tgz#47d9835ab64dd0b596d9c94731f070282f82fc5a" integrity sha512-VG2Knemmshop4kh5fpLO27rYcyUaaDkRw+6PiX4bstpB+QFt0p2oauMrsjVbUamGWQ6YNavh7x2em2uZlzV44g== dependencies: dagre "^0.8.5" cytoscape-fcose@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz#e4d6f6490df4fab58ae9cea9e5c3ab8d7472f471" integrity sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ== dependencies: cose-base "^2.2.0" -cytoscape@^3.29.2: - version "3.29.2" - resolved "https://registry.npmjs.org/cytoscape/-/cytoscape-3.29.2.tgz" - integrity sha512-2G1ycU28Nh7OHT9rkXRLpCDP30MKH1dXJORZuBhtEhEW7pKwgPi77ImqlCWinouyE1PNepIOGZBOrE84DG7LyQ== +cytoscape@^3.30.2: + version "3.30.2" + resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.30.2.tgz#94149707fb6547a55e3b44f03ffe232706212161" + integrity sha512-oICxQsjW8uSaRmn4UK/jkczKOqTrVqt5/1WL0POiJUT2EKNc9STM4hYFHv917yu55aTBMFNRzymlJhVAiWPCxw== dagre@^0.8.5: version "0.8.5" - resolved "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz" + resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee" integrity sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw== dependencies: graphlib "^2.1.8" @@ -1651,39 +1414,20 @@ debounce@^1.2.1: resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== -debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== +debug@^4.1.0, debug@^4.3.1: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== dependencies: ms "2.1.2" -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - detect-gpu@^5.0.28: - version "5.0.39" - resolved "https://registry.yarnpkg.com/detect-gpu/-/detect-gpu-5.0.39.tgz#9ce549af9b45654683e3bc34a0f87e74e7a99728" - integrity sha512-qs+7gnNNxsH4RN1IPpQieU2XNO+RhgemuaRhcawiUug6oXb0Glup90H1YGSjslPO30Sw0E4yfjRoGtSEURwVPQ== + version "5.0.40" + resolved "https://registry.yarnpkg.com/detect-gpu/-/detect-gpu-5.0.40.tgz#626d41aa55341858ab547c260726a4afbac7dd95" + integrity sha512-5v4jDN/ERdZZitD29UiLjV9Q9+lDfw2OhEJACIqnvdWulVZCy2K6EwonZ/VKyo4YMqvSIzGIDmojX3jGL3dLpA== dependencies: webgl-constants "^1.1.1" -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - dom-helpers@^5.0.1: version "5.2.1" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" @@ -1697,195 +1441,67 @@ draco3d@^1.4.1: resolved "https://registry.yarnpkg.com/draco3d/-/draco3d-1.5.7.tgz#94f9bce293eb8920c159dc91a4ce9124a9e899e0" integrity sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ== -electron-to-chromium@^1.4.668: - version "1.4.742" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.742.tgz" - integrity sha512-EhE+z1d5RNytAq/qnGAxPR+ie3UzKbv7qqQc0wnEbOh+KDUplgfzkGSCy9d78B+S+nVNTS42BabHXB6Ni+Ud4w== +earcut@^2.2.3: + version "2.2.4" + resolved "https://registry.yarnpkg.com/earcut/-/earcut-2.2.4.tgz#6d02fd4d68160c114825d06890a92ecaae60343a" + integrity sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ== + +electron-to-chromium@^1.4.820: + version "1.5.0" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.0.tgz#0d3123a9f09189b9c7ab4b5d6848d71b3c1fd0e8" + integrity sha512-Vb3xHHYnLseK8vlMJQKJYXJ++t4u1/qJ3vykuVrVjvdiOEhYyT1AuP4x03G8EnPmYvYOhe9T+dADTmthjRQMkA== error-ex@^1.3.1: version "1.3.2" - resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" -esbuild@^0.20.1: - version "0.20.2" - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz" - integrity sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g== +esbuild@^0.21.3: + version "0.21.5" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" + integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== optionalDependencies: - "@esbuild/aix-ppc64" "0.20.2" - "@esbuild/android-arm" "0.20.2" - "@esbuild/android-arm64" "0.20.2" - "@esbuild/android-x64" "0.20.2" - "@esbuild/darwin-arm64" "0.20.2" - "@esbuild/darwin-x64" "0.20.2" - "@esbuild/freebsd-arm64" "0.20.2" - "@esbuild/freebsd-x64" "0.20.2" - "@esbuild/linux-arm" "0.20.2" - "@esbuild/linux-arm64" "0.20.2" - "@esbuild/linux-ia32" "0.20.2" - "@esbuild/linux-loong64" "0.20.2" - "@esbuild/linux-mips64el" "0.20.2" - "@esbuild/linux-ppc64" "0.20.2" - "@esbuild/linux-riscv64" "0.20.2" - "@esbuild/linux-s390x" "0.20.2" - "@esbuild/linux-x64" "0.20.2" - "@esbuild/netbsd-x64" "0.20.2" - "@esbuild/openbsd-x64" "0.20.2" - "@esbuild/sunos-x64" "0.20.2" - "@esbuild/win32-arm64" "0.20.2" - "@esbuild/win32-ia32" "0.20.2" - "@esbuild/win32-x64" "0.20.2" - -escalade@^3.1.1: + "@esbuild/aix-ppc64" "0.21.5" + "@esbuild/android-arm" "0.21.5" + "@esbuild/android-arm64" "0.21.5" + "@esbuild/android-x64" "0.21.5" + "@esbuild/darwin-arm64" "0.21.5" + "@esbuild/darwin-x64" "0.21.5" + "@esbuild/freebsd-arm64" "0.21.5" + "@esbuild/freebsd-x64" "0.21.5" + "@esbuild/linux-arm" "0.21.5" + "@esbuild/linux-arm64" "0.21.5" + "@esbuild/linux-ia32" "0.21.5" + "@esbuild/linux-loong64" "0.21.5" + "@esbuild/linux-mips64el" "0.21.5" + "@esbuild/linux-ppc64" "0.21.5" + "@esbuild/linux-riscv64" "0.21.5" + "@esbuild/linux-s390x" "0.21.5" + "@esbuild/linux-x64" "0.21.5" + "@esbuild/netbsd-x64" "0.21.5" + "@esbuild/openbsd-x64" "0.21.5" + "@esbuild/sunos-x64" "0.21.5" + "@esbuild/win32-arm64" "0.21.5" + "@esbuild/win32-ia32" "0.21.5" + "@esbuild/win32-x64" "0.21.5" + +escalade@^3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-plugin-react-hooks@^4.6.0: - version "4.6.0" - resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz" - integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== - -eslint-plugin-react-refresh@^0.4.6: - version "0.4.6" - resolved "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.6.tgz" - integrity sha512-NjGXdm7zgcKRkKMua34qVO9doI7VOxZ6ancSvBELJSSoX97jyndXcSoa8XBh69JoB31dNz3EEzlMcizZl7LaMA== - -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint@^8.57.0: - version "8.57.0" - resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz" - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.0" - "@humanwhocodes/config-array" "^0.11.14" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - -esquery@^1.4.2: - version "1.5.0" - resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.9: - version "3.3.2" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fastq@^1.6.0: - version "1.17.1" - resolved "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz" - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== - dependencies: - reusify "^1.0.4" - fflate@^0.6.9: version "0.6.10" resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.6.10.tgz#5f40f9659205936a2d18abf88b2e7781662b6d43" @@ -1896,66 +1512,32 @@ fflate@~0.8.2: resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - file-saver@^2.0.5: version "2.0.5" - resolved "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38" integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA== -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" find-root@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" - -flatted@^3.2.9: - version "3.3.1" - resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz" - integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== - fs-extra@^11.2.0: version "11.2.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" universalify "^2.0.0" -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" @@ -1963,64 +1545,40 @@ fsevents@~2.3.2, fsevents@~2.3.3: function-bind@^1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -glob-parent@^5.1.2, glob-parent@~5.1.2: +geotiff@^2.0.7: + version "2.1.3" + resolved "https://registry.yarnpkg.com/geotiff/-/geotiff-2.1.3.tgz#993f40f2aa6aa65fb1e0451d86dd22ca8e66910c" + integrity sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA== + dependencies: + "@petamoriken/float16" "^3.4.7" + lerc "^3.0.0" + pako "^2.0.4" + parse-headers "^2.0.2" + quick-lru "^6.1.1" + web-worker "^1.2.0" + xml-utils "^1.0.2" + zstddec "^0.1.0" + +glob-parent@~5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@^7.1.3: - version "7.2.3" - resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - globals@^11.1.0: version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - glsl-noise@^0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/glsl-noise/-/glsl-noise-0.0.0.tgz#367745f3a33382c0eeec4cb54b7e99cfc1d7670b" @@ -2028,24 +1586,19 @@ glsl-noise@^0.0.0: graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.11" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - graphlib@^2.1.8: version "2.1.8" - resolved "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz" + resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da" integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A== dependencies: lodash "^4.17.15" handlebars@^4.7.8: version "4.7.8" - resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== dependencies: minimist "^1.2.5" @@ -2057,17 +1610,12 @@ handlebars@^4.7.8: has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -hasown@^2.0.0: +hasown@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" @@ -2079,26 +1627,21 @@ hls.js@1.3.5: hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" - resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== dependencies: react-is "^16.7.0" hyphenate-style-name@^1.0.3: - version "1.0.4" - resolved "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz" - integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== + version "1.1.0" + resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz#1797bf50369588b47b72ca6d5e65374607cf4436" + integrity sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw== -ieee754@^1.2.1: +ieee754@^1.1.12, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore@^5.2.0, ignore@^5.3.1: - version "5.3.1" - resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== - immediate@~3.0.5: version "3.0.6" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" @@ -2110,82 +1653,59 @@ immer@^10.0.3: integrity sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw== immutable@^4.0.0: - version "4.3.5" - resolved "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz" - integrity sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw== + version "4.3.7" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" + integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== import-fresh@^3.2.1: version "3.3.0" - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - is-arrayish@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + version "2.15.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.0.tgz#71c72ec5442ace7e76b306e9d48db361f22699ea" + integrity sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA== dependencies: - hasown "^2.0.0" + hasown "^2.0.2" is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: +is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.3" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-in-browser@^1.0.2, is-in-browser@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz" + resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835" integrity sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g== is-number@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - is-promise@^2.1.0: version "2.2.2" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" @@ -2205,49 +1725,34 @@ its-fine@^1.0.6: "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - json-parse-even-better-errors@^2.3.0: version "2.3.1" - resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - json5@^2.2.3: version "2.2.3" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonfile@^6.0.1: version "6.1.0" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== dependencies: universalify "^2.0.0" @@ -2256,7 +1761,7 @@ jsonfile@^6.0.1: jss-plugin-camel-case@^10.5.1: version "10.10.0" - resolved "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.10.0.tgz" + resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.10.0.tgz#27ea159bab67eb4837fa0260204eb7925d4daa1c" integrity sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw== dependencies: "@babel/runtime" "^7.3.1" @@ -2265,7 +1770,7 @@ jss-plugin-camel-case@^10.5.1: jss-plugin-default-unit@^10.5.1: version "10.10.0" - resolved "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.10.0.tgz" + resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.10.0.tgz#db3925cf6a07f8e1dd459549d9c8aadff9804293" integrity sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ== dependencies: "@babel/runtime" "^7.3.1" @@ -2273,7 +1778,7 @@ jss-plugin-default-unit@^10.5.1: jss-plugin-global@^10.5.1: version "10.10.0" - resolved "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.10.0.tgz" + resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.10.0.tgz#1c55d3c35821fab67a538a38918292fc9c567efd" integrity sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A== dependencies: "@babel/runtime" "^7.3.1" @@ -2281,7 +1786,7 @@ jss-plugin-global@^10.5.1: jss-plugin-nested@^10.5.1: version "10.10.0" - resolved "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.10.0.tgz" + resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.10.0.tgz#db872ed8925688806e77f1fc87f6e62264513219" integrity sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA== dependencies: "@babel/runtime" "^7.3.1" @@ -2290,7 +1795,7 @@ jss-plugin-nested@^10.5.1: jss-plugin-props-sort@^10.5.1: version "10.10.0" - resolved "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.10.0.tgz" + resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.10.0.tgz#67f4dd4c70830c126f4ec49b4b37ccddb680a5d7" integrity sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg== dependencies: "@babel/runtime" "^7.3.1" @@ -2298,7 +1803,7 @@ jss-plugin-props-sort@^10.5.1: jss-plugin-rule-value-function@^10.5.1: version "10.10.0" - resolved "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.10.0.tgz" + resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.10.0.tgz#7d99e3229e78a3712f78ba50ab342e881d26a24b" integrity sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g== dependencies: "@babel/runtime" "^7.3.1" @@ -2307,7 +1812,7 @@ jss-plugin-rule-value-function@^10.5.1: jss-plugin-vendor-prefixer@^10.5.1: version "10.10.0" - resolved "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.10.0.tgz" + resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.10.0.tgz#c01428ef5a89f2b128ec0af87a314d0c767931c7" integrity sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg== dependencies: "@babel/runtime" "^7.3.1" @@ -2316,7 +1821,7 @@ jss-plugin-vendor-prefixer@^10.5.1: jss@10.10.0, jss@^10.5.1: version "10.10.0" - resolved "https://registry.npmjs.org/jss/-/jss-10.10.0.tgz" + resolved "https://registry.yarnpkg.com/jss/-/jss-10.10.0.tgz#a75cc85b0108c7ac8c7b7d296c520a3e4fbc6ccc" integrity sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw== dependencies: "@babel/runtime" "^7.3.1" @@ -2324,25 +1829,15 @@ jss@10.10.0, jss@^10.5.1: is-in-browser "^1.1.3" tiny-warning "^1.0.2" -keyv@^4.5.3: - version "4.5.4" - resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - layout-base@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/layout-base/-/layout-base-2.0.1.tgz#d0337913586c90f9c2c075292069f5c2da5dd285" integrity sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg== -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" +lerc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lerc/-/lerc-3.0.0.tgz#36f36fbd4ba46f0abf4833799fff2e7d6865f5cb" + integrity sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww== lie@^3.0.2: version "3.3.0" @@ -2353,29 +1848,17 @@ lie@^3.0.2: lines-and-columns@^1.1.6: version "1.2.4" - resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - lodash-es@^4.17.15: version "4.17.21" - resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - lodash@^4.0.1, lodash@^4.17.15: version "4.17.21" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== loose-envify@^1.1.0, loose-envify@^1.4.0: @@ -2387,18 +1870,11 @@ loose-envify@^1.1.0, loose-envify@^1.4.0: lru-cache@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - maath@^0.10.7: version "0.10.8" resolved "https://registry.yarnpkg.com/maath/-/maath-0.10.8.tgz#cf647544430141bf6982da6e878abb6c4b804e24" @@ -2406,14 +1882,9 @@ maath@^0.10.7: material-colors@^1.2.1: version "1.2.6" - resolved "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz" + resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46" integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg== -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - meshline@^3.1.6: version "3.3.1" resolved "https://registry.yarnpkg.com/meshline/-/meshline-3.3.1.tgz#20decfd5cdd25c8469e862ddf0ab1ad167759734" @@ -2424,61 +1895,34 @@ meshoptimizer@~0.18.1: resolved "https://registry.yarnpkg.com/meshoptimizer/-/meshoptimizer-0.18.1.tgz#cdb90907f30a7b5b1190facd3b7ee6b7087797d8" integrity sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw== -micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^9.0.4: - version "9.0.4" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz" - integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== - dependencies: - brace-expansion "^2.0.1" - minimist@^1.2.5: version "1.2.8" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== ms@2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== nanoid@^3.3.7: version "3.3.7" - resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - neo-async@^2.6.2: version "2.6.2" - resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== object-assign@^4.1.1: @@ -2486,16 +1930,21 @@ object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -once@^1.3.0: - version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== +ol@^9.1.0: + version "9.2.4" + resolved "https://registry.yarnpkg.com/ol/-/ol-9.2.4.tgz#07dcefdceb66ddbde13089bca136f4d4852b772b" + integrity sha512-bsbu4ObaAlbELMIZWnYEvX4Z9jO+OyCBshtODhDKmqYTPEfnKOX3RieCr97tpJkqWTZvyV4tS9UQDvHoCdxS+A== dependencies: - wrappy "1" + color-rgba "^3.0.0" + color-space "^2.0.1" + earcut "^2.2.3" + geotiff "^2.0.7" + pbf "3.2.1" + rbush "^3.0.1" openapi-typescript-codegen@^0.29.0: version "0.29.0" - resolved "https://registry.npmjs.org/openapi-typescript-codegen/-/openapi-typescript-codegen-0.29.0.tgz" + resolved "https://registry.yarnpkg.com/openapi-typescript-codegen/-/openapi-typescript-codegen-0.29.0.tgz#e98a1daa223ccdeb1cc51b2e2dc11bafae6fe746" integrity sha512-/wC42PkD0LGjDTEULa/XiWQbv4E9NwLjwLjsaJ/62yOsoYhwvmBR31kPttn1DzQ2OlGe5stACcF/EIkZk43M6w== dependencies: "@apidevtools/json-schema-ref-parser" "^11.5.4" @@ -2504,47 +1953,31 @@ openapi-typescript-codegen@^0.29.0: fs-extra "^11.2.0" handlebars "^4.7.8" -optionator@^0.9.3: - version "0.9.3" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz" - integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== - dependencies: - "@aashutoshrathi/word-wrap" "^1.2.3" - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - pako@^1.0.3: version "1.0.11" - resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== +pako@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" + integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== + parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" +parse-headers@^2.0.2: + version "2.0.5" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9" + integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA== + parse-json@^5.0.0: version "5.2.0" - resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== dependencies: "@babel/code-frame" "^7.0.0" @@ -2552,16 +1985,6 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -2569,36 +1992,44 @@ path-key@^3.1.0: path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-type@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +pbf@3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/pbf/-/pbf-3.2.1.tgz#b4c1b9e72af966cd82c6531691115cc0409ffe2a" + integrity sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ== + dependencies: + ieee754 "^1.1.12" + resolve-protobuf-schema "^2.1.0" -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: +picocolors@^1.0.0, picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + +picomatch@^2.0.4, picomatch@^2.2.1: version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== popper.js@1.16.1-lts: version "1.16.1-lts" - resolved "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz" + resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05" integrity sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA== -postcss@^8.4.38: - version "8.4.38" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz" - integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== +postcss@^8.4.40: + version "8.4.41" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.41.tgz#d6104d3ba272d882fe18fc07d15dc2da62fa2681" + integrity sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ== dependencies: nanoid "^3.3.7" - picocolors "^1.0.0" + picocolors "^1.0.1" source-map-js "^1.2.0" potpack@^1.0.1: @@ -2606,11 +2037,6 @@ potpack@^1.0.1: resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.2.tgz#23b99e64eb74f5741ffe7656b5b5c4ddce8dfc14" integrity sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ== -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - promise-worker-transferable@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/promise-worker-transferable/-/promise-worker-transferable-1.0.4.tgz#2c72861ba053e5ae42b487b4a83b1ed3ae3786e8" @@ -2621,31 +2047,43 @@ promise-worker-transferable@^1.0.4: prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" - resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== dependencies: loose-envify "^1.4.0" object-assign "^4.1.1" react-is "^16.13.1" -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== +protocol-buffers-schema@^3.3.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz#77bc75a48b2ff142c1ad5b5b90c94cd0fa2efd03" + integrity sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw== -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quick-lru@^6.1.1: + version "6.1.2" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-6.1.2.tgz#e9a90524108629be35287d0b864e7ad6ceb3659e" + integrity sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ== + +quickselect@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-2.0.0.tgz#f19680a486a5eefb581303e023e98faaf25dd018" + integrity sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw== + +rbush@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/rbush/-/rbush-3.0.1.tgz#5fafa8a79b3b9afdfe5008403a720cc1de882ecf" + integrity sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w== + dependencies: + quickselect "^2.0.0" re-resizable@4.5.1: version "4.5.1" - resolved "https://registry.npmjs.org/re-resizable/-/re-resizable-4.5.1.tgz" + resolved "https://registry.yarnpkg.com/re-resizable/-/re-resizable-4.5.1.tgz#4688e8311ea4b70d558f7aebb3168a25926e62d9" integrity sha512-amjlp4IuTSHs4XG1bP5WbAgBDIZitODKIsqcpZsNhEBYYEidol0dlP4S9zHiN3iu6Tff4WfYuruihLgN7RJeQw== react-color@^2.19.3: version "2.19.3" - resolved "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz" + resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.19.3.tgz#ec6c6b4568312a3c6a18420ab0472e146aa5683d" integrity sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA== dependencies: "@icons/material" "^0.2.4" @@ -2673,7 +2111,7 @@ react-dom@^18.3.1: react-draggable@^3.0.5: version "3.3.2" - resolved "https://registry.npmjs.org/react-draggable/-/react-draggable-3.3.2.tgz" + resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-3.3.2.tgz#966ef1d90f2387af3c2d8bd3516f601ea42ca359" integrity sha512-oaz8a6enjbPtx5qb0oDWxtDNuybOylvto1QLydsXgKmwT7e3GXC2eMVDwEMIUYJIFqVG72XpOv673UuuAq6LhA== dependencies: classnames "^2.2.5" @@ -2681,12 +2119,12 @@ react-draggable@^3.0.5: react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" - resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== "react-is@^16.8.0 || ^17.0.0", react-is@^17.0.2: version "17.0.2" - resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== react-is@^18.3.1: @@ -2704,7 +2142,7 @@ react-reconciler@^0.27.0: react-redux@^7.2.3: version "7.2.9" - resolved "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.9.tgz#09488fbb9416a4efe3735b7235055442b042481d" integrity sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ== dependencies: "@babel/runtime" "^7.15.4" @@ -2722,14 +2160,14 @@ react-redux@^9.1.1: "@types/use-sync-external-store" "^0.0.3" use-sync-external-store "^1.0.0" -react-refresh@^0.14.0: - version "0.14.0" - resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz" - integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ== +react-refresh@^0.14.2: + version "0.14.2" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" + integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== react-rnd@^7.3.0: version "7.4.3" - resolved "https://registry.npmjs.org/react-rnd/-/react-rnd-7.4.3.tgz" + resolved "https://registry.yarnpkg.com/react-rnd/-/react-rnd-7.4.3.tgz#76adc591fd78f543a66cc63595d0002599d1d408" integrity sha512-TLQ35nqXup7rC63qAETebbO6Znilr20CroTTeAdlYu8nvRSwB7BrmPKZhHB2GgeiSucOoeCyAA9pHPhbMpEd/Q== dependencies: re-resizable "4.5.1" @@ -2737,7 +2175,7 @@ react-rnd@^7.3.0: react-transition-group@^4.4.0, react-transition-group@^4.4.5: version "4.4.5" - resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== dependencies: "@babel/runtime" "^7.5.5" @@ -2754,7 +2192,7 @@ react-use-measure@^2.1.1: react@^17.0.2: version "17.0.2" - resolved "https://registry.npmjs.org/react/-/react-17.0.2.tgz" + resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== dependencies: loose-envify "^1.1.0" @@ -2769,14 +2207,14 @@ react@^18.3.1: reactcss@^1.2.0: version "1.2.3" - resolved "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz" + resolved "https://registry.yarnpkg.com/reactcss/-/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd" integrity sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A== dependencies: lodash "^4.0.1" readdirp@~3.6.0: version "3.6.0" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== dependencies: picomatch "^2.2.1" @@ -2788,7 +2226,7 @@ redux-thunk@^3.1.0: redux@^4.0.0, redux@^4.1.0: version "4.2.1" - resolved "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== dependencies: "@babel/runtime" "^7.9.2" @@ -2815,66 +2253,54 @@ reselect@^5.1.0: resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve-protobuf-schema@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz#9ca9a9e69cf192bbdaf1006ec1973948aa4a3758" + integrity sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ== + dependencies: + protocol-buffers-schema "^3.3.1" + resolve@^1.19.0: version "1.22.8" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== dependencies: is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - rollup@^4.13.0: - version "4.14.3" - resolved "https://registry.npmjs.org/rollup/-/rollup-4.14.3.tgz" - integrity sha512-ag5tTQKYsj1bhrFC9+OEWqb5O6VYgtQDO9hPDBMmIbePwhfSr+ExlcU741t8Dhw5DkPCQf6noz0jb36D6W9/hw== + version "4.19.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.19.0.tgz#83b08cc0b2bc38c26c194cb7f2cdabd84a2a8c02" + integrity sha512-5r7EYSQIowHsK4eTZ0Y81qpZuJz+MUuYeqmmYmRMl1nwhdmbiYqt5jwzf6u7wyOzJgYqtCRMtVRKOtHANBz7rA== dependencies: "@types/estree" "1.0.5" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.14.3" - "@rollup/rollup-android-arm64" "4.14.3" - "@rollup/rollup-darwin-arm64" "4.14.3" - "@rollup/rollup-darwin-x64" "4.14.3" - "@rollup/rollup-linux-arm-gnueabihf" "4.14.3" - "@rollup/rollup-linux-arm-musleabihf" "4.14.3" - "@rollup/rollup-linux-arm64-gnu" "4.14.3" - "@rollup/rollup-linux-arm64-musl" "4.14.3" - "@rollup/rollup-linux-powerpc64le-gnu" "4.14.3" - "@rollup/rollup-linux-riscv64-gnu" "4.14.3" - "@rollup/rollup-linux-s390x-gnu" "4.14.3" - "@rollup/rollup-linux-x64-gnu" "4.14.3" - "@rollup/rollup-linux-x64-musl" "4.14.3" - "@rollup/rollup-win32-arm64-msvc" "4.14.3" - "@rollup/rollup-win32-ia32-msvc" "4.14.3" - "@rollup/rollup-win32-x64-msvc" "4.14.3" + "@rollup/rollup-android-arm-eabi" "4.19.0" + "@rollup/rollup-android-arm64" "4.19.0" + "@rollup/rollup-darwin-arm64" "4.19.0" + "@rollup/rollup-darwin-x64" "4.19.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.19.0" + "@rollup/rollup-linux-arm-musleabihf" "4.19.0" + "@rollup/rollup-linux-arm64-gnu" "4.19.0" + "@rollup/rollup-linux-arm64-musl" "4.19.0" + "@rollup/rollup-linux-powerpc64le-gnu" "4.19.0" + "@rollup/rollup-linux-riscv64-gnu" "4.19.0" + "@rollup/rollup-linux-s390x-gnu" "4.19.0" + "@rollup/rollup-linux-x64-gnu" "4.19.0" + "@rollup/rollup-linux-x64-musl" "4.19.0" + "@rollup/rollup-win32-arm64-msvc" "4.19.0" + "@rollup/rollup-win32-ia32-msvc" "4.19.0" + "@rollup/rollup-win32-x64-msvc" "4.19.0" fsevents "~2.3.2" -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - sass@^1.75.0: - version "1.75.0" - resolved "https://registry.npmjs.org/sass/-/sass-1.75.0.tgz" - integrity sha512-ShMYi3WkrDWxExyxSZPst4/okE9ts46xZmJDSawJQrnte7M1V9fScVB+uNXOVKRBt0PggHOwoZcn8mYX4trnBw== + version "1.77.8" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.8.tgz#9f18b449ea401759ef7ec1752a16373e296b52bd" + integrity sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ== dependencies: chokidar ">=3.0.0 <4.0.0" immutable "^4.0.0" @@ -2896,16 +2322,9 @@ scheduler@^0.23.2: semver@^6.3.1: version "6.3.1" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.6.0: - version "7.6.0" - resolved "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz" - integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== - dependencies: - lru-cache "^6.0.0" - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -2918,24 +2337,19 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - "source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== source-map@^0.5.7: version "0.5.7" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== source-map@^0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== stats-gl@^2.0.0: @@ -2950,18 +2364,6 @@ stats.js@^0.17.0: resolved "https://registry.yarnpkg.com/stats.js/-/stats.js-0.17.0.tgz#b1c3dc46d94498b578b7fd3985b81ace7131cc7d" integrity sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw== -strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - stylis@4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" @@ -2969,21 +2371,14 @@ stylis@4.2.0: supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== suspend-react@^0.1.3: @@ -2991,11 +2386,6 @@ suspend-react@^0.1.3: resolved "https://registry.yarnpkg.com/suspend-react/-/suspend-react-0.1.3.tgz#a52f49d21cfae9a2fb70bd0c68413d3f9d90768e" integrity sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ== -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - three-mesh-bvh@^0.7.0: version "0.7.6" resolved "https://registry.yarnpkg.com/three-mesh-bvh/-/three-mesh-bvh-0.7.6.tgz#6764b39475bdba9450ad3a4065492678ee537272" @@ -3020,22 +2410,22 @@ three@^0.166.1: tiny-warning@^1.0.2: version "1.0.3" - resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== tinycolor2@^1.4.1: version "1.6.0" - resolved "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz" + resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw== to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" @@ -3060,11 +2450,6 @@ troika-worker-utils@^0.49.0: resolved "https://registry.yarnpkg.com/troika-worker-utils/-/troika-worker-utils-0.49.0.tgz#e5e200a09d2e0e4eb9fe818a83effa912e2ec4b4" integrity sha512-1xZHoJrG0HFfCvT/iyN41DvI/nRykiBtHqFkGaGgJwq5iXfIZFBiPPEHFpPpgyKM3Oo5ITHXP5wM2TNQszYdVg== -ts-api-utils@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz" - integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== - tunnel-rat@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/tunnel-rat/-/tunnel-rat-0.1.2.tgz#1717efbc474ea2d8aa05a91622457a6e201c0aeb" @@ -3072,56 +2457,37 @@ tunnel-rat@^0.1.2: dependencies: zustand "^4.3.2" -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - typescript@^5.2.2: - version "5.4.5" - resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz" - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== + version "5.5.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" + integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== uglify-js@^3.1.4: - version "3.17.4" - resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz" - integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== + version "3.19.0" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.0.tgz#6d45f1cad2c54117fa2fabd87fc2713a83e3bf7b" + integrity sha512-wNKHUY2hYYkf6oSFfhwwiHo4WCHzHmzcXsqXYTN9ja3iApYIFbb2U6ics9hBcYLHcYGQoAlwnZlTrf3oF+BL/Q== universalify@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== +update-browserslist-db@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== dependencies: - punycode "^2.1.0" + escalade "^3.1.2" + picocolors "^1.0.1" url-join@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== use-sync-external-store@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== use-sync-external-store@^1.0.0: @@ -3139,17 +2505,22 @@ uuid@^9.0.1: resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== -vite@^5.2.0: - version "5.2.9" - resolved "https://registry.npmjs.org/vite/-/vite-5.2.9.tgz" - integrity sha512-uOQWfuZBlc6Y3W/DTuQ1Sr+oIXWvqljLvS881SVmAj00d5RdgShLcuXWxseWPd4HXwiYBFW/vXHfKFeqj9uQnw== +vite@^5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.0.tgz#11dca8a961369ba8b5cae42d068c7ad684d5370f" + integrity sha512-5xokfMX0PIiwCMCMb9ZJcMyh5wbBun0zUzKib+L65vAZ8GY9ePZMXxFrHbr/Kyll2+LSCY7xtERPpxkBDKngwg== dependencies: - esbuild "^0.20.1" - postcss "^8.4.38" + esbuild "^0.21.3" + postcss "^8.4.40" rollup "^4.13.0" optionalDependencies: fsevents "~2.3.3" +web-worker@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.3.0.tgz#e5f2df5c7fe356755a5fb8f8410d4312627e6776" + integrity sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA== + webgl-constants@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/webgl-constants/-/webgl-constants-1.1.1.tgz#f9633ee87fea56647a60b9ce735cbdfb891c6855" @@ -3169,33 +2540,28 @@ which@^2.0.1: wordwrap@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -wrappy@1: - version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +xml-utils@^1.0.2: + version "1.10.1" + resolved "https://registry.yarnpkg.com/xml-utils/-/xml-utils-1.10.1.tgz#fa0c9b38545760532d4cf89003f90c3b24e7200f" + integrity sha512-Dn6vJ1Z9v1tepSjvnCpwk5QqwIPcEFKdgnjqfYOABv1ngSofuAhtlugcUC3ehS1OHdgDWSG6C5mvj+Qm15udTQ== yallist@^3.0.2: version "3.1.1" - resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - yaml@^1.10.0: version "1.10.2" - resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yocto-queue@^0.1.0: +zstddec@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + resolved "https://registry.yarnpkg.com/zstddec/-/zstddec-0.1.0.tgz#7050f3f0e0c3978562d0c566b3e5a427d2bad7ec" + integrity sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg== zustand@^3.7.1: version "3.7.2" diff --git a/extraction/requirements.txt b/extraction/requirements.txt new file mode 100644 index 00000000..12dfb876 --- /dev/null +++ b/extraction/requirements.txt @@ -0,0 +1,5 @@ +diplib==3.5.1 +geojson==3.1.0 +geojson-rewind==1.1.0 +numpy==2.0.0 +tqdm==4.66.4 diff --git a/extraction/segmentation-extraction.py b/extraction/segmentation-extraction.py new file mode 100644 index 00000000..97457862 --- /dev/null +++ b/extraction/segmentation-extraction.py @@ -0,0 +1,215 @@ +from argparse import ArgumentParser +import diplib as dip +from time import time +from pathlib import Path +import geojson +from geojson import FeatureCollection, Feature, MultiPolygon +from geojson_rewind import rewind +import numpy as np +from dataclasses import dataclass, fields as dataclass_fields +from tqdm import tqdm + + +# @dataclass +# class Color(object): +# rgb: tuple[int] +# red: int +# green: int +# blue: int +# pattern: int + + +@dataclass +class LUTEntry(object): + nr: int + # flags: int + color1: list[int] + color2: list[int] + # anchor: list[int] + # parentnr: int + # childnr: int + # prevnr: int + # nextnr: int + # collapsednr: int + bbox1: list[int] + bbox2: list[int] + name: str + + +def extract_headers(metadata_path: Path): + headers = [] + marker = "% Columns:" + with metadata_path.open("r") as f: + for line in f: + if line.startswith(marker): + headers = [s.lower() for s in line[len(marker) :].split()] + return headers + + +def parse_entries(metadata_path: Path): + fields = extract_headers(metadata_path) + entries = {} + with metadata_path.open("r") as f: + for line in f: + if line.startswith("%") or not line.strip(): + continue + entry = parse_entry(line, fields) + entries[entry.nr] = entry + return entries + + +def parse_entry(line, fields): + name_start = line.index('"') + values = line[:name_start].split() + values = [int(v) for v in values] + preformat = {k: v for k, v in zip(fields, values)} + sub_line = line[name_start + 1 :] + preformat["name"] = sub_line[: sub_line.index('"')] + preformat["bbox1"] = [preformat["bboxx1"], preformat["bboxy1"], preformat["bboxz1"]] + preformat["bbox2"] = [preformat["bboxx2"], preformat["bboxy2"], preformat["bboxz2"]] + preformat["color1"] = (preformat["red1"], preformat["green1"], preformat["blue1"]) + preformat["color2"] = (preformat["red2"], preformat["green2"], preformat["blue2"]) + + dc_fields = [field.name for field in dataclass_fields(LUTEntry)] + return LUTEntry(**{k: v for k, v in preformat.items() if k in dc_fields}) + + +def extract( + img_path, + metadata_entries, + overwrite=False, + write_json=True, + write_img=False, + print=print, +): + result_json_path = img_path.parent / f"{img_path.stem}.json" + if not overwrite and result_json_path.exists(): + print(f"JSON position {result_json_path} already exist, skipping") + return + + t = time() + + print(f"= Position extraction and LUT parsing for {img_path}") + dimg = dip.ImageRead(f"{img_path}") # Reads the image using diplib + + # Gets the chaincodes (8-connected chain codes) + code_chains = dip.GetImageChainCodes(dimg) + res_contours = {} + res_coords = {} + + i = 0 + masked = np.array(dimg) # original image progressively masked + mask = np.zeros_like(dimg).astype(bool) # progressive mask + + # While the 8-connected algo finds code chains + while code_chains: + # Register the values discovered + print(f" * Iteration {i} for {[c.objectID for c in code_chains]}") + for chain in code_chains: + # Extract the polygon and transform it in a list + polygon = list(chain.Polygon().Simplify()) + polygon.append(polygon[0]) # Last element = first to be geojson compliant + res_contours.setdefault(chain.objectID, []).append(polygon) + + # Also store the coords + # (not used right now, will be later for 3D surface reconstruction) + # 3D reconstruction candidates are "vedo", or "open3D" (used in first SOW in Natus) + # for a dedicated region number, the coordinates for each slice will be stacked + # to form a 3D cloud of points using rolling-ball, marching cube or poisson reconstruction + res_coords.setdefault(chain.objectID, []).append(list(chain.Coordinates())) + + # Construct the mask of the element to remove using the bounding box + ((a, b), (c, d)) = chain.BoundingBox() + mask[b : d + 1, a : c + 1] |= masked[b : d + 1, a : c + 1] == chain.objectID + + # Once all elements have been registered for a first application of the 8-connected algo + # We apply the mask, consequently removing the elements that we already registered + # and we start again the process (8-connected algo + polygon extraction). + # This is to overcome a limitation: + # * diplib, discover properly 1 shape per label. If the number repeats in another + # shape (i.e: there is multiple closed shapes with the same label), only 1 shape will + # be discovered. + masked = np.where(mask, 0, masked) + dimg = dip.Image(masked) + code_chains = dip.GetImageChainCodes(dimg) + i += 1 + print(f" * Labels polygon extraction: {time() - t}s") + + shape = dimg.Size(0), dimg.Size(1) + if write_img: + from PIL import Image + + Image.MAX_IMAGE_PIXELS = None + result_img_path = img_path.parent / f"{img_path.stem}-colored-seg.png" + cpy = Image.new("RGB", shape) + + print(f" ** Writing result img in {result_img_path}") + for v, zones in res_coords.items(): + for zone in zones: + for x, y in zone: + cpy.putpixel((x, y), metadata_entries[v].color1) + cpy.save(result_img_path) + + def flip_y(x, y, image_height): + return (x, image_height - y) + + if write_json: + features = [ + Feature( + geometry=MultiPolygon([[zone] for zone in zones]), + properties={ + "region_number": nr, + "color": metadata_entries[nr].color1, + "name": metadata_entries[nr].name, + }, + ) + for nr, zones in res_contours.items() + ] + fc = FeatureCollection(features) + geojson.utils.map_tuples( + lambda coord: flip_y(*coord, image_height=shape[1]), fc + ) + + result_json_path.write_text(rewind(geojson.dumps(fc))) + print(f" ** JSON saved as {result_json_path}\n") + + +if __name__ == "__main__": + parser = ArgumentParser(description="Extract positions from segmentation file") + parser.add_argument( + "-i", + "--img-path", + help="Path of a segmentation image or the folder containing the segmentation images", + required=True, + ) + parser.add_argument( + "-l", "--lut", help="Path towards the look-up table", required=True + ) + parser.add_argument( + "--no-json", help="Disable JSON file output", action="store_true" + ) + parser.add_argument( + "--write-img", help="Write the result in an img format", action="store_true" + ) + parser.add_argument( + "--overwrite", help="Force JSON/img production", action="store_true" + ) + args = vars(parser.parse_args()) + + metadata_path = Path(args["lut"]) + segmentation_folder = Path(args["img_path"]) + files = ( + list(segmentation_folder.glob("*.png")) + if segmentation_folder.is_dir() + else [segmentation_folder] + ) + for file in tqdm(files): + tqdm.write(f"Extracting segments from {file}") + extract( + file, + parse_entries(metadata_path), + overwrite=args["overwrite"], + write_img=args["write_img"], + write_json=not args["no_json"], + print=tqdm.write, + ) diff --git a/format-ingestion.md b/format-ingestion.md new file mode 100644 index 00000000..f3ae3613 --- /dev/null +++ b/format-ingestion.md @@ -0,0 +1,121 @@ +# Format of data ingested in the database + +The management script is able to ingest data represented in a JSON format. +Different files are necessary: + +* `neurons.json` that encodes the information about the neurons in general +* `datasets.json` that encodes the information about the different datasets +* `connections/xxx.json` that encodes the different connections for dedicated datasets +* `annotations/xxx.json` that encodes annotatinos for different zones of the anatomy + +Those files are automatically exported from third-party tool and shouldn't be edited manually. + +## Format of `neurons.json` + +This file defines a list of JSON object as root structure: + +```json +[ + { + ... // definition of neuron 1 + }, + ..., + { + ... // definition of neuron N + } +] +``` + +Each JSON object represents a neuron with this schema: + +```json +{ + "inhead": int, // int used as bool, is the neuron part of the head or not + "name": string, // name of the neuron, can be same as classes, or L or R of classes + "emb": int, // int used as bool + "nt": string, // neurotransmitter type + "intail": int, // int used as bool + "classes": string, // general name of the neuron + "typ": string // type of the neuron: "i" => , TODO fillme +} +``` + + +## Format of `datasets.json` + +This file defines a list of JSON object as root structure. + +```json +[ + { + ... // definition of dataset 1 + }, + ..., + { + ... // definition of dataset N + } +] +``` + +Each JSON object represents a specific dataset with this schema: + +```json +{ + "id": string // unique ID for the dataset + "name": string // display name of the dataset + "type": string // type of dataset: "complete" or "head" + "time": int // time of the dataset + "visualTime": int // visualTime of the dataset + "description": string // description of the dataset + "axes": [ // OPTIONAL: different axes and their representation, not used but can appear in the file + ... + ] +} +``` + +## Format of `connections/xxx.json` + +The `connections` directory encodes the information about the different connections by dataset. +Each file in this directory is named after the `id` of a dataset present in the `datasets.json` file, e.g.: a dataset defined using the `id` `white_1986_jsh` will defines each of the connections of the dataset in the file `connections/white_1986_jsh.json`. + +Each of those files is a list of JSON object where each of the JSON objects encodes different connections between different neurons. +The schema is the following: + +```json +{ + "ids": [ ... ], // a list of int, where each int represents the ID of the neurons involved in this connection + "post": string, // the name of a neuron as defined in "neurons.json" + "post_tid": [ ... ], // a list of int where each int represents the ID of a post synapse for a dedicated post neuron + "pre": string, // the name of a neuron as defined in "neurons.json" + "pre_tid": [ ... ], // a list of int where each int represents the ID of a pre synapse for a dedicated pre neuron + "syn": [ ... ], // a list of int where each int represents the weight of a post or pre synapses (indice matches the neuron in pre/post_tid) + "typ": int // the type of connection ("electrical" or "chemical") +} +``` + +For each of those objects: `ids`, `post_tid`, `pre_tid` and `syn` need to have the same number of elements. + +## Format of `annotations/xxx.json` + +The `annotations` directory encodes annotations about the different part (`head` or `complete`) following the naming convention `part.annotations.json`, e.g.: the annotations for the `head` are located in `annotations/head.annotations.json`. + +Each of those files is a JSON object that defines categories as keys and a list of neurons couples as values. +Here is the schema for the `head.annotations.json` file (the `complete.annotations.json` file, while existing, is an empty JSON object). + +```json +{ + "increase": [ // the type of annotation + [ + string, // pre, the ID/name of a neuron from "neurons.json" + string // post, the ID/name of the other neuron from "neurons.json" that is part of the couple + ] + ] +} +``` + +The types of annotations can be `increase`, `variable`, `postembryonic`, `decrease` or `stable` + +### Note: + +The existing repository contains a `trajectories` folder with a set of JSON files. +Those files are not ingested anymore, they are part of a legacy system.