[web] Search related refactoring - Part x/x (#3224)

This commit is contained in:
Manav Rathi
2024-09-11 10:57:31 +05:30
committed by GitHub
8 changed files with 370 additions and 446 deletions

View File

@@ -1,7 +1,11 @@
import { assertionFailed } from "@/base/assert";
import { useIsMobileWidth } from "@/base/hooks";
import { FileType } from "@/media/file-type";
import { PeopleList } from "@/new/photos/components/PeopleList";
import { isMLEnabled } from "@/new/photos/services/ml";
import {
isMLSupported,
mlStatusSnapshot,
mlStatusSubscribe,
} from "@/new/photos/services/ml";
import type {
City,
SearchDateComponents,
@@ -12,7 +16,6 @@ import {
ClipSearchScores,
SearchOption,
SearchQuery,
Suggestion,
SuggestionType,
} from "@/new/photos/services/search/types";
import { labelForSuggestionType } from "@/new/photos/services/search/ui";
@@ -20,7 +23,6 @@ import type { LocationTag } from "@/new/photos/services/user-entity";
import { EnteFile } from "@/new/photos/types/file";
import {
FreeFlowText,
Row,
SpaceBetweenFlex,
} from "@ente/shared/components/Container";
import CalendarIcon from "@mui/icons-material/CalendarMonth";
@@ -49,22 +51,18 @@ import {
useMemo,
useRef,
useState,
useSyncExternalStore,
} from "react";
import {
components as SelectComponents,
type ControlProps,
type InputActionMeta,
type InputProps,
type MenuProps,
type OptionProps,
type SelectInstance,
type StylesConfig,
} from "react-select";
import AsyncSelect from "react-select/async";
import {
getAutoCompleteSuggestions,
getDefaultOptions,
} from "services/searchService";
import { getAutoCompleteSuggestions } from "services/searchService";
import { Collection } from "types/collection";
interface SearchBarProps {
@@ -139,23 +137,15 @@ const SearchInput: React.FC<SearchInputProps> = ({
// The currently selected option.
const [value, setValue] = useState<SearchOption | undefined>();
// The contents of the input field associated with the select.
const [query, setQuery] = useState("");
// The default options shown in the select menu when nothing has been typed.
const [defaultOptions, setDefaultOptions] = useState([]);
const [inputValue, setInputValue] = useState("");
useEffect(() => {
search(value);
}, [value]);
useEffect(() => {
refreshDefaultOptions();
const t = setInterval(() => refreshDefaultOptions(), 2000);
return () => clearInterval(t);
}, []);
const handleChange = (value: SearchOption) => {
setValue(value);
setQuery(value?.label);
setInputValue(value?.label);
// The Select has a blurInputOnSelect prop, but that makes the input
// field lose focus, not the entire menu (e.g. when pressing twice).
//
@@ -166,14 +156,10 @@ const SearchInput: React.FC<SearchInputProps> = ({
const handleInputChange = (value: string, actionMeta: InputActionMeta) => {
if (actionMeta.action === "input-change") {
setQuery(value);
setInputValue(value);
}
};
const refreshDefaultOptions = async () => {
setDefaultOptions(await getDefaultOptions());
};
const resetSearch = () => {
if (isOpen) {
appContext.startLoading();
@@ -183,7 +169,7 @@ const SearchInput: React.FC<SearchInputProps> = ({
}, 10);
setIsOpen(false);
setValue(null);
setQuery("");
setInputValue("");
}
};
@@ -219,7 +205,7 @@ const SearchInput: React.FC<SearchInputProps> = ({
case SuggestionType.COLLECTION:
search = { collection: selectedOption.value as number };
setValue(null);
setQuery("");
setInputValue("");
break;
case SuggestionType.FILE_NAME:
search = { files: selectedOption.value as number[] };
@@ -242,38 +228,34 @@ const SearchInput: React.FC<SearchInputProps> = ({
});
};
// TODO: HACK as AsyncSelect does not support default options reloading on focus/click
// unwanted side effect: placeholder is not shown on focus/click
// https://github.com/JedWatson/react-select/issues/1879
// for correct fix AsyncSelect can be extended to support default options reloading on focus/click
const handleOnFocus = () => {
refreshDefaultOptions();
const handleSelectCGroup = (value: SearchOption) => {
// Dismiss the search menu.
selectRef.current?.blur();
setValue(value);
};
const components = useMemo(
() => ({ Option, Control, Menu: CustomMenu, Input: Input }),
[],
);
const components = useMemo(() => ({ Option, Control, Input }), []);
return (
<SearchInputWrapper>
<AsyncSelect
ref={selectRef}
value={value}
// @ts-expect-error Type of the Menu is not what Select expects
components={components}
placeholder={t("search_hint")}
loadOptions={getOptions}
onChange={handleChange}
onFocus={handleOnFocus}
isMulti={false}
isClearable
escapeClearsValue
inputValue={query}
inputValue={inputValue}
onInputChange={handleInputChange}
styles={SelectStyles}
defaultOptions={isMLEnabled() ? defaultOptions : []}
noOptionsMessage={() => null}
noOptionsMessage={({ inputValue }) =>
shouldShowEmptyState(inputValue) ? (
<EmptyState onSelectCGroup={handleSelectCGroup} />
) : null
}
/>
{isOpen && (
@@ -299,7 +281,8 @@ const SelectStyles: StylesConfig<SearchOption, false> = {
container: (style) => ({ ...style, flex: 1 }),
control: (style, { isFocused }) => ({
...style,
backgroundColor: "rgba(255, 255, 255, 0.1)",
// Give a solid background color.
backgroundColor: "rgb(26, 26, 26)",
borderColor: isFocused ? "#1DB954" : "transparent",
boxShadow: "none",
":hover": {
@@ -310,8 +293,11 @@ const SelectStyles: StylesConfig<SearchOption, false> = {
input: (styles) => ({ ...styles, color: "#fff" }),
menu: (style) => ({
...style,
// Suppress the default margin at the top.
marginTop: "1px",
backgroundColor: "#1b1b1b",
// Same background color as the control (must be solid, otherwise the
// content behind the menu shows through).
backgroundColor: "rgb(26, 26, 26)",
}),
option: (style, { isFocused }) => ({
...style,
@@ -327,14 +313,15 @@ const SelectStyles: StylesConfig<SearchOption, false> = {
display: "none",
},
}),
dropdownIndicator: (style) => ({ ...style, display: "none" }),
indicatorSeparator: (style) => ({ ...style, display: "none" }),
clearIndicator: (style) => ({ ...style, display: "none" }),
placeholder: (style) => ({
...style,
color: "rgba(255, 255, 255, 0.7)",
whiteSpace: "nowrap",
}),
// Hide some things we don't need.
dropdownIndicator: (style) => ({ ...style, display: "none" }),
indicatorSeparator: (style) => ({ ...style, display: "none" }),
clearIndicator: (style) => ({ ...style, display: "none" }),
};
const Control = ({ children, ...props }: ControlProps<SearchOption, false>) => (
@@ -379,6 +366,165 @@ const iconForOptionType = (type: SuggestionType | undefined) => {
}
};
/**
* A preflight check for whether or not we should show the EmptyState.
*
* react-select seems to only suppress showing anything at all in the menu if we
* return `null` from the function passed to `noOptionsMessage`. Returning
* `false`, or returning `null` from the EmptyState itself doesn't work and
* causes a empty div to be shown instead.
*/
const shouldShowEmptyState = (inputValue: string) => {
// Don't show empty state if the user has entered search input.
if (inputValue) return false;
// Don't show empty state if there is no ML related information.
if (!isMLSupported) return false;
const status = isMLSupported && mlStatusSnapshot();
if (!status || status.phase == "disabled") return false;
// Show it otherwise.
return true;
};
interface EmptyStateProps {
/** Called when the user selects a cgroup shown in the empty state view. */
onSelectCGroup: (value: SearchOption) => void;
}
/**
* The view shown in the menu area when the user has not typed anything in the
* search box.
*/
const EmptyState: React.FC<EmptyStateProps> = () => {
const mlStatus = useSyncExternalStore(mlStatusSubscribe, mlStatusSnapshot);
if (!mlStatus || mlStatus.phase == "disabled") {
assertionFailed();
return <></>;
}
let label: string;
switch (mlStatus.phase) {
case "scheduled":
label = t("indexing_scheduled");
break;
case "indexing":
label = t("indexing_photos", mlStatus);
break;
case "fetching":
label = t("indexing_fetching", mlStatus);
break;
case "clustering":
label = t("indexing_people", mlStatus);
break;
case "done":
label = t("indexing_done", mlStatus);
break;
}
return (
<Box>
<Typography variant="mini" sx={{ textAlign: "left" }}>
{label}
</Typography>
</Box>
);
// TODO-Cluster
// const options = props.selectProps.options as SearchOption[];
// const peopleSuggestions = options.filter(
// (o) => o.type === SuggestionType.PERSON,
// );
// const people = peopleSuggestions.map((o) => o.value as SearchPerson);
// return (
// <SelectComponents.Menu {...props}>
// <Box my={1}>
// {isMLEnabled() &&
// indexStatus &&
// (people && people.length > 0 ? (
// <Box>
// <Legend>{t("people")}</Legend>
// </Box>
// ) : (
// <Box height={6} />
// ))}
// {isMLEnabled() && indexStatus && (
// <Box>
// <Caption>{indexStatusSuggestion.label}</Caption>
// </Box>
// )}
// {people && people.length > 0 && (
// <Row> // "@ente/shared/components/Container"
// <PeopleList // @/new/photos/components/PeopleList
// people={people}
// maxRows={2}
// onSelect={(_, index) => {
// }}
// />
// </Row>
// )}
// </Box>
// {props.children}
// </SelectComponents.Menu>
// );
};
// TODO-Cluster
// const Legend = styled("span")`
// font-size: 20px;
// color: #ddd;
// display: inline;
// padding: 0px 12px;
// `;
/*
TODO: Cluster
export async function getAllPeopleSuggestion(): Promise<Array<Suggestion>> {
try {
const people = await getAllPeople(200);
return people.map((person) => ({
label: person.name,
type: SuggestionType.PERSON,
value: person,
hide: true,
}));
} catch (e) {
log.error("getAllPeopleSuggestion failed", e);
return [];
}
}
async function getAllPeople(limit: number = undefined) {
return (await wipSearchPersons()).slice(0, limit);
// TODO-Clustetr
// if (done) return [];
// done = true;
// if (process.env.NEXT_PUBLIC_ENTE_WIP_CL_FETCH) {
// await syncCGroups();
// const people = await clusterGroups();
// log.debug(() => ["people", { people }]);
// }
// let people: Array<SearchPerson> = []; // await mlIDbStorage.getAllPeople();
// people = await wipCluster();
// // await mlPeopleStore.iterate<Person, void>((person) => {
// // people.push(person);
// // });
// people = people ?? [];
// const result = people
// .sort((p1, p2) => p2.files.length - p1.files.length)
// .slice(0, limit);
// // log.debug(() => ["getAllPeople", result]);
// return result;
}
*/
const Option: React.FC<OptionProps<SearchOption, false>> = (props) => (
<SelectComponents.Option {...props}>
<LabelWithInfo data={props.data} />
@@ -387,116 +533,40 @@ const Option: React.FC<OptionProps<SearchOption, false>> = (props) => (
const LabelWithInfo = ({ data }: { data: SearchOption }) => {
return (
!data.hide && (
<>
<Box className="main" px={2} py={1}>
<Typography variant="mini" mb={1}>
{labelForSuggestionType(data.type)}
</Typography>
<SpaceBetweenFlex>
<Box mr={1}>
<FreeFlowText>
<Typography fontWeight={"bold"}>
{data.label}
</Typography>
</FreeFlowText>
<Typography color="text.muted">
{t("photos_count", { count: data.fileCount })}
<>
<Box className="main" px={2} py={1}>
<Typography variant="mini" mb={1}>
{labelForSuggestionType(data.type)}
</Typography>
<SpaceBetweenFlex>
<Box mr={1}>
<FreeFlowText>
<Typography fontWeight={"bold"}>
{data.label}
</Typography>
</Box>
<Stack direction={"row"} spacing={1}>
{data.previewFiles.map((file) => (
<CollectionCard
key={file.id}
coverFile={file}
onClick={() => null}
collectionTile={ResultPreviewTile}
/>
))}
</Stack>
</SpaceBetweenFlex>
</Box>
<Divider sx={{ mx: 2, my: 1 }} />
</>
)
);
};
type CustomMenuProps = MenuProps<SearchOption, false> & {
selectRef: React.RefObject<SelectInstance>;
// Cannot call it setValue since the menu itself already has that.
setSelectedValue: (value: SearchOption) => void;
};
const CustomMenu: React.FC<CustomMenuProps> = ({
selectRef,
setSelectedValue,
...props
}) => {
// Need to cast here, otherwise the react-select types think selectProps can
// also be something that supports multiple selection groups.
const options = props.selectProps.options as SearchOption[];
const peopleSuggestions = options.filter(
(o) => o.type === SuggestionType.PERSON,
);
const people = peopleSuggestions.map((o) => o.value as SearchPerson);
const indexStatusSuggestion = options.filter(
(o) => o.type === SuggestionType.INDEX_STATUS,
)[0] as Suggestion;
const indexStatus = indexStatusSuggestion?.value;
return (
<SelectComponents.Menu {...props}>
<Box my={1}>
{isMLEnabled() &&
indexStatus &&
(people && people.length > 0 ? (
<Box>
<Legend>{t("people")}</Legend>
</Box>
) : (
<Box height={6} />
))}
{isMLEnabled() && indexStatus && (
<Box>
<Caption>{indexStatusSuggestion.label}</Caption>
</FreeFlowText>
<Typography color="text.muted">
{t("photos_count", { count: data.fileCount })}
</Typography>
</Box>
)}
{people && people.length > 0 && (
<Row>
<PeopleList
people={people}
maxRows={2}
onSelect={(_, index) => {
selectRef.current?.blur();
setSelectedValue(peopleSuggestions[index]);
}}
/>
</Row>
)}
<Stack direction={"row"} spacing={1}>
{data.previewFiles.map((file) => (
<CollectionCard
key={file.id}
coverFile={file}
onClick={() => null}
collectionTile={ResultPreviewTile}
/>
))}
</Stack>
</SpaceBetweenFlex>
</Box>
{props.children}
</SelectComponents.Menu>
<Divider sx={{ mx: 2, my: 1 }} />
</>
);
};
const Legend = styled("span")`
font-size: 20px;
color: #ddd;
display: inline;
padding: 0px 12px;
`;
const Caption = styled("span")`
font-size: 12px;
display: inline;
padding: 0px 12px;
`;
// A custom input for react-select that is always visible. This is a roundabout
// hack the existing code used to display the search string when showing the
// results page; likely there should be a better way.

View File

@@ -1,10 +1,5 @@
import log from "@/base/log";
import { FileType } from "@/media/file-type";
import {
isMLSupported,
mlStatusSnapshot,
wipSearchPersons,
} from "@/new/photos/services/ml";
import { createSearchQuery, search } from "@/new/photos/services/search";
import type {
SearchDateComponents,
@@ -20,19 +15,9 @@ import {
} from "@/new/photos/services/search/types";
import type { LocationTag } from "@/new/photos/services/user-entity";
import { EnteFile } from "@/new/photos/types/file";
import { t } from "i18next";
import { Collection } from "types/collection";
import { getUniqueFiles } from "utils/file";
// Suggestions shown in the search dropdown's empty state, i.e. when the user
// selects the search bar but does not provide any input.
export const getDefaultOptions = async () => {
return [
await getMLStatusSuggestion(),
...(await convertSuggestionsToOptions(await getAllPeopleSuggestion())),
].filter((t) => !!t);
};
// Suggestions shown in the search dropdown when the user has typed something.
export const getAutoCompleteSuggestions =
(files: EnteFile[], collections: Collection[]) =>
@@ -87,55 +72,6 @@ async function convertSuggestionsToOptions(
return previewImageAppendedOptions;
}
export async function getAllPeopleSuggestion(): Promise<Array<Suggestion>> {
try {
const people = await getAllPeople(200);
return people.map((person) => ({
label: person.name,
type: SuggestionType.PERSON,
value: person,
hide: true,
}));
} catch (e) {
log.error("getAllPeopleSuggestion failed", e);
return [];
}
}
export async function getMLStatusSuggestion(): Promise<Suggestion> {
if (!isMLSupported) return undefined;
const status = mlStatusSnapshot();
if (!status || status.phase == "disabled") return undefined;
let label: string;
switch (status.phase) {
case "scheduled":
label = t("indexing_scheduled");
break;
case "indexing":
label = t("indexing_photos", status);
break;
case "fetching":
label = t("indexing_fetching", status);
break;
case "clustering":
label = t("indexing_people", status);
break;
case "done":
label = t("indexing_done", status);
break;
}
return {
label,
type: SuggestionType.INDEX_STATUS,
value: status,
hide: true,
};
}
function getCollectionSuggestion(
searchPhrase: string,
collections: Collection[],
@@ -237,29 +173,3 @@ function convertSuggestionToSearchQuery(option: Suggestion): SearchQuery {
return { clip: option.value as ClipSearchScores };
}
}
async function getAllPeople(limit: number = undefined) {
return (await wipSearchPersons()).slice(0, limit);
// TODO-Clustetr
// if (done) return [];
// done = true;
// if (process.env.NEXT_PUBLIC_ENTE_WIP_CL_FETCH) {
// await syncCGroups();
// const people = await clusterGroups();
// log.debug(() => ["people", { people }]);
// }
// let people: Array<SearchPerson> = []; // await mlIDbStorage.getAllPeople();
// people = await wipCluster();
// // await mlPeopleStore.iterate<Person, void>((person) => {
// // people.push(person);
// // });
// people = people ?? [];
// const result = people
// .sort((p1, p2) => p2.files.length - p1.files.length)
// .slice(0, limit);
// // log.debug(() => ["getAllPeople", result]);
// return result;
}

View File

@@ -33,8 +33,9 @@
"preview:staff": "yarn workspace staff preview"
},
"resolutions": {
"@emotion/cache": "11.11.0",
"@emotion/react": "11.11.3"
"@emotion/cache": "11.13.1",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0"
},
"devDependencies": {
"concurrently": "^8.2.2",

View File

@@ -4,8 +4,12 @@ import log from "./log";
/**
* If running in a dev build, throw an exception with the given message.
* Otherwise log it as a warning.
*
* @param message An optional message to use for the failure. If not provided,
* then a generic one is used.
*/
export const assertionFailed = (message: string) => {
export const assertionFailed = (message?: string) => {
message = message ?? "Assertion failed";
if (isDevBuild) throw new Error(message);
log.warn(message);
};

View File

@@ -3,21 +3,21 @@
"version": "0.0.0",
"private": true,
"dependencies": {
"@emotion/react": "11.11.3",
"@emotion/styled": "^11.11.5",
"@mui/icons-material": "^5.16",
"@mui/material": "^5.16",
"comlink": "^4.4",
"get-user-locale": "^2.3",
"i18next": "^23.11",
"i18next-resources-to-backend": "^1.2",
"is-electron": "^2.2",
"@emotion/react": "11.13.3",
"@emotion/styled": "^11.13.0",
"@mui/icons-material": "^5.16.6",
"@mui/material": "^5.16.6",
"comlink": "^4.4.1",
"get-user-locale": "^2.3.2",
"i18next": "^23.15.1",
"i18next-resources-to-backend": "^1.2.1",
"is-electron": "^2.2.2",
"libsodium-wrappers-sumo": "^0.7.15",
"nanoid": "^5.0.7",
"next": "^14.2",
"react": "^18",
"react-dom": "^18",
"react-i18next": "^14"
"react-i18next": "^15.0.1"
},
"devDependencies": {
"@/build-config": "*",

View File

@@ -5,7 +5,6 @@
import type { Location } from "@/base/types";
import { FileType } from "@/media/file-type";
import type { MLStatus } from "@/new/photos/services/ml";
import type { EnteFile } from "@/new/photos/types/file";
import type { LocationTag } from "../user-entity";
@@ -106,7 +105,6 @@ export enum SuggestionType {
COLLECTION = "COLLECTION",
FILE_NAME = "FILE_NAME",
PERSON = "PERSON",
INDEX_STATUS = "INDEX_STATUS",
FILE_CAPTION = "FILE_CAPTION",
FILE_TYPE = "FILE_TYPE",
CLIP = "CLIP",
@@ -120,12 +118,10 @@ export interface Suggestion {
| SearchDateComponents
| number[]
| SearchPerson
| MLStatus
| LocationTag
| City
| FileType
| ClipSearchScores;
hide?: boolean;
}
export interface SearchQuery {

View File

@@ -18,8 +18,6 @@ export const labelForSuggestionType = (type: SuggestionType) => {
return t("file_name");
case SuggestionType.PERSON:
return t("person");
case SuggestionType.INDEX_STATUS:
throw new Error("Not a displayable key");
case SuggestionType.FILE_CAPTION:
return t("description");
case SuggestionType.FILE_TYPE:

View File

@@ -204,6 +204,13 @@
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.24.8":
version "7.25.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.6.tgz#9afc3289f7184d8d7f98b099884c26317b9264d2"
integrity sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.25.0":
version "7.25.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb"
@@ -250,16 +257,16 @@
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
"@emotion/babel-plugin@^11.11.0":
version "11.11.0"
resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c"
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"
@@ -267,95 +274,95 @@
source-map "^0.5.7"
stylis "4.2.0"
"@emotion/cache@11.11.0", "@emotion/cache@^11.11.0", "@emotion/cache@^11.4.0":
version "11.11.0"
resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff"
integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==
"@emotion/cache@11.13.1", "@emotion/cache@^11.11.0", "@emotion/cache@^11.13.0", "@emotion/cache@^11.4.0":
version "11.13.1"
resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.13.1.tgz#fecfc54d51810beebf05bf2a161271a1a91895d7"
integrity sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==
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.9.1":
version "0.9.1"
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43"
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.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz#d4175076679c6a26faa92b03bb786f9e52612337"
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.3", "@emotion/react@^11.8.1":
version "11.11.3"
resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.3.tgz#96b855dc40a2a55f52a72f518a41db4f69c31a25"
integrity sha512-Cnn0kuq4DoONOMcnoVsTOR8E+AdnKFf//6kUWc4LCdnxj31pZWn7rIULd6Y7/Js1PiPHzn7SKCM9vB/jBni8eA==
"@emotion/react@11.13.3", "@emotion/react@^11.13.3", "@emotion/react@^11.8.1":
version "11.13.3"
resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.13.3.tgz#a69d0de2a23f5b48e0acf210416638010e4bd2e4"
integrity sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==
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.1"
"@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.yarnpkg.com/@emotion/serialize/-/serialize-1.1.4.tgz#fc8f6d80c492cfa08801d544a05331d1cc7cd451"
integrity sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==
"@emotion/serialize@^1.2.0", "@emotion/serialize@^1.3.0", "@emotion/serialize@^1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.1.tgz#490b660178f43d2de8e92b278b51079d726c05c3"
integrity sha512-dEPNKzBPU+vFPGa+z3axPRn8XVDetYORmDC0wAiej+TNcOZE70ZMJa0X7JdeoM6q/nWTMZeLpN/fTnD9o8MQBA==
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.10.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.yarnpkg.com/@emotion/styled/-/styled-11.11.5.tgz#0c5c8febef9d86e8a926e663b2e5488705545dfb"
integrity sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==
"@emotion/styled@^11.13.0":
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/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.8.1":
version "0.8.1"
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3"
integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==
"@emotion/unitless@^0.10.0":
version "0.10.0"
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.10.0.tgz#2af2f7c7e5150f497bdabd848ce7b218a27cf745"
integrity sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==
"@emotion/use-insertion-effect-with-fallbacks@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz#08de79f54eb3406f9daaf77c76e35313da963963"
integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==
"@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/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==
"@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==
"@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"
@@ -511,14 +518,6 @@
dependencies:
"@floating-ui/utils" "^0.2.4"
"@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==
dependencies:
"@floating-ui/core" "^1.6.0"
"@floating-ui/utils" "^0.2.4"
"@floating-ui/dom@^1.0.1":
version "1.6.10"
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.10.tgz#b74c32f34a50336c86dcf1f1c845cf3a39e26d6f"
@@ -527,13 +526,6 @@
"@floating-ui/core" "^1.6.0"
"@floating-ui/utils" "^0.2.7"
"@floating-ui/react-dom@^2.0.8":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.1.tgz#cca58b6b04fc92b4c39288252e285e0422291fb0"
integrity sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==
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"
@@ -607,58 +599,36 @@
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"
"@mui/base@5.0.0-beta.40":
version "5.0.0-beta.40"
resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.40.tgz#1f8a782f1fbf3f84a961e954c8176b187de3dae2"
integrity sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==
"@mui/core-downloads-tracker@^5.16.7":
version "5.16.7"
resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.7.tgz#182a325a520f7ebd75de051fceabfc0314cfd004"
integrity sha512-RtsCt4Geed2/v74sbihWzzRs+HsIQCfclHeORh5Ynu2fS4icIKozcSubwuG7vtzq2uW3fOR1zITSP84TNt2GoQ==
"@mui/icons-material@^5.16.6":
version "5.16.7"
resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.16.7.tgz#e27f901af792065efc9f3d75d74a66af7529a10a"
integrity sha512-UrGwDJCXEszbDI7yV047BYU5A28eGJ79keTCP4cc74WyncuVrnurlmIRxaHL8YK+LI1Kzq+/JM52IAkNnv4u+Q==
dependencies:
"@babel/runtime" "^7.23.9"
"@floating-ui/react-dom" "^2.0.8"
"@mui/types" "^7.2.14"
"@mui/utils" "^5.15.14"
"@mui/material@^5.16.6":
version "5.16.7"
resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.16.7.tgz#6e814e2eefdaf065a769cecf549c3569e107a50b"
integrity sha512-cwwVQxBhK60OIOqZOVLFt55t01zmarKJiJUWbk0+8s/Ix5IaUzAShqlJchxsIQ4mSrWqgcKCCXKtIlG5H+/Jmg==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/core-downloads-tracker" "^5.16.7"
"@mui/system" "^5.16.7"
"@mui/types" "^7.2.15"
"@mui/utils" "^5.16.6"
"@popperjs/core" "^2.11.8"
clsx "^2.1.0"
prop-types "^15.8.1"
"@mui/core-downloads-tracker@^5.16.0":
version "5.16.0"
resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.0.tgz#50153c698e321793c83a0283d8d7a9dc5d43858a"
integrity sha512-8SLffXYPRVpcZx5QzxNE8fytTqzp+IuU3deZbQWg/vSaTlDpR5YVrQ4qQtXTi5cRdhOufV5INylmwlKK+//nPw==
"@mui/icons-material@^5.16":
version "5.16.0"
resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.16.0.tgz#5269fda922fe5e6db3577ec497e8b987195606ef"
integrity sha512-6ISoOhkp9w5gD0PEW9JklrcbyARDkFWNTBdwXZ1Oy5IGlyu9B0zG0hnUIe4H17IaF1Vgj6C8VI+v4tkSdK0veg==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/material@^5.16":
version "5.16.0"
resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.16.0.tgz#2ef4f52ae773574fc0a681f25705f376f5cd13f7"
integrity sha512-DbR1NckTLpjt9Zut9EGQ70th86HfN0BYQgyYro6aXQrNfjzSwe3BJS1AyBQ5mJ7TdL6YVRqohfukxj9JlqZZUg==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/base" "5.0.0-beta.40"
"@mui/core-downloads-tracker" "^5.16.0"
"@mui/system" "^5.16.0"
"@mui/types" "^7.2.14"
"@mui/utils" "^5.16.0"
"@types/react-transition-group" "^4.4.10"
clsx "^2.1.0"
csstype "^3.1.3"
prop-types "^15.8.1"
react-is "^18.2.0"
react-is "^18.3.1"
react-transition-group "^4.4.5"
"@mui/private-theming@^5.16.0":
version "5.16.0"
resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.16.0.tgz#c1abfd3e0d9c95459048240ef4209dc7f25dc949"
integrity sha512-sYpubkO1MZOnxNyVOClrPNOTs0MfuRVVnAvCeMaOaXt6GimgQbnUcshYv2pSr6PFj+Mqzdff/FYOBceK8u5QgA==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/utils" "^5.16.0"
prop-types "^15.8.1"
"@mui/private-theming@^5.16.6":
version "5.16.6"
resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.16.6.tgz#547671e7ae3f86b68d1289a0b90af04dfcc1c8c9"
@@ -668,16 +638,6 @@
"@mui/utils" "^5.16.6"
prop-types "^15.8.1"
"@mui/styled-engine@^5.15.14":
version "5.15.14"
resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.15.14.tgz#168b154c4327fa4ccc1933a498331d53f61c0de2"
integrity sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==
dependencies:
"@babel/runtime" "^7.23.9"
"@emotion/cache" "^11.11.0"
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/styled-engine@^5.16.6":
version "5.16.6"
resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.16.6.tgz#60110c106dd482dfdb7e2aa94fd6490a0a3f8852"
@@ -688,20 +648,6 @@
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/system@^5.16.0":
version "5.16.0"
resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.16.0.tgz#e5b4cfbdfbc0ee9859f6b168e8b07d750303b7a0"
integrity sha512-9YbkC2m3+pNumAvubYv+ijLtog6puJ0fJ6rYfzfLCM47pWrw3m+30nXNM8zMgDaKL6vpfWJcCXm+LPaWBpy7sw==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/private-theming" "^5.16.0"
"@mui/styled-engine" "^5.15.14"
"@mui/types" "^7.2.14"
"@mui/utils" "^5.16.0"
clsx "^2.1.0"
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/system@^5.16.5":
version "5.16.6"
resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.16.6.tgz#2dabe63d2e45816ce611c40d6e3f79b9c2ccbcd7"
@@ -716,26 +662,25 @@
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/types@^7.2.14":
version "7.2.14"
resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.14.tgz#8a02ac129b70f3d82f2f9b76ded2c8d48e3fc8c9"
integrity sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==
"@mui/system@^5.16.7":
version "5.16.7"
resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.16.7.tgz#4583ca5bf3b38942e02c15a1e622ba869ac51393"
integrity sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/private-theming" "^5.16.6"
"@mui/styled-engine" "^5.16.6"
"@mui/types" "^7.2.15"
"@mui/utils" "^5.16.6"
clsx "^2.1.0"
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/types@^7.2.15":
version "7.2.15"
resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.15.tgz#dadd232fe9a70be0d526630675dff3b110f30b53"
integrity sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==
"@mui/utils@^5.15.14", "@mui/utils@^5.16.0":
version "5.16.0"
resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.16.0.tgz#3963127d9a619c251e5be1aef9adab0e89d3e7df"
integrity sha512-kLLi5J1xY+mwtUlMb8Ubdxf4qFAA1+U7WPBvjM/qQ4CIwLCohNb0sHo1oYPufjSIH/Z9+dhVxD7dJlfGjd1AVA==
dependencies:
"@babel/runtime" "^7.23.9"
"@types/prop-types" "^15.7.11"
prop-types "^15.8.1"
react-is "^18.2.0"
"@mui/utils@^5.16.5", "@mui/utils@^5.16.6":
version "5.16.6"
resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.16.6.tgz#905875bbc58d3dcc24531c3314a6807aba22a711"
@@ -1094,7 +1039,7 @@
resolved "https://registry.yarnpkg.com/@types/photoswipe/-/photoswipe-4.1.6.tgz#41d1e0a54c1b27628688e8abf9b95baab472a247"
integrity sha512-6kN4KYjNF4sg79fSwZ46s4Pron4+YJxoW0DQOcHveUZc/3cWd8Q4B9OLlDmEYw9iI6fODU8kyyq8ZBy+8F/+zQ==
"@types/prop-types@*", "@types/prop-types@^15.7.11", "@types/prop-types@^15.7.12":
"@types/prop-types@*", "@types/prop-types@^15.7.12":
version "15.7.12"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6"
integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==
@@ -1728,7 +1673,7 @@ combined-stream@^1.0.8:
dependencies:
delayed-stream "~1.0.0"
comlink@^4.4:
comlink@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/comlink/-/comlink-4.4.1.tgz#e568b8e86410b809e8600eb2cf40c189371ef981"
integrity sha512-+1dlx0aY5Jo1vHy/tSsIGpSkN4tS9rZSW8FIhG0JH/crs9wwweswIo/POr451r7bZww3hFbPAKnTpimzL/mm4Q==
@@ -2709,7 +2654,7 @@ get-tsconfig@^4.5.0:
dependencies:
resolve-pkg-maps "^1.0.0"
get-user-locale@^2.3:
get-user-locale@^2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/get-user-locale/-/get-user-locale-2.3.2.tgz#d37ae6e670c2b57d23a96fb4d91e04b2059d52cf"
integrity sha512-O2GWvQkhnbDoWFUJfaBlDIKUEdND8ATpBXD6KXcbhxlfktyD/d8w6mkzM/IlQEqGZAMz/PW6j6Hv53BiigKLUQ==
@@ -2919,17 +2864,17 @@ html-parse-stringify@^3.0.1:
dependencies:
void-elements "3.1.0"
i18next-resources-to-backend@^1.2:
i18next-resources-to-backend@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/i18next-resources-to-backend/-/i18next-resources-to-backend-1.2.1.tgz#fded121e63e3139ce839c9901b9449dbbea7351d"
integrity sha512-okHbVA+HZ7n1/76MsfhPqDou0fptl2dAlhRDu2ideXloRRduzHsqDOznJBef+R3DFZnbvWoBW+KxJ7fnFjd6Yw==
dependencies:
"@babel/runtime" "^7.23.2"
i18next@^23.11:
version "23.11.5"
resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.11.5.tgz#d71eb717a7e65498d87d0594f2664237f9e361ef"
integrity sha512-41pvpVbW9rhZPk5xjCX2TPJi2861LEig/YRhUkY+1FQ2IQPS0bKUDYnEqY8XPPbB48h1uIwLnP9iiEfuSl20CA==
i18next@^23.15.1:
version "23.15.1"
resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.15.1.tgz#c50de337bf12ca5195e697cc0fbe5f32304871d9"
integrity sha512-wB4abZ3uK7EWodYisHl/asf8UYEhrI/vj/8aoSsrj/ZDxj4/UXPOa1KvFt1Fq5hkUHquNqwFlDprmjZ8iySgYA==
dependencies:
"@babel/runtime" "^7.23.2"
@@ -3061,7 +3006,7 @@ is-date-object@^1.0.1, is-date-object@^1.0.5:
dependencies:
has-tostringtag "^1.0.0"
is-electron@^2.2:
is-electron@^2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/is-electron/-/is-electron-2.2.2.tgz#3778902a2044d76de98036f5dc58089ac4d80bb9"
integrity sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==
@@ -3965,12 +3910,12 @@ react-fast-compare@^2.0.1:
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
react-i18next@^14:
version "14.1.2"
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-14.1.2.tgz#cd57a755f25a32a5fcc3dbe546cf3cc62b4f3ebd"
integrity sha512-FSIcJy6oauJbGEXfhUgVeLzvWBhIBIS+/9c6Lj4niwKZyGaGb4V4vUbATXSlsHJDXXB+ociNxqFNiFuV1gmoqg==
react-i18next@^15.0.1:
version "15.0.1"
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.0.1.tgz#fc662d93829ecb39683fe2757a47ebfbc5c912a0"
integrity sha512-NwxLqNM6CLbeGA9xPsjits0EnXdKgCRSS6cgkgOdNcPXqL+1fYNl8fBg1wmnnHvFy812Bt4IWTPE9zjoPmFj3w==
dependencies:
"@babel/runtime" "^7.23.9"
"@babel/runtime" "^7.24.8"
html-parse-stringify "^3.0.1"
react-is@^16.13.1, react-is@^16.7.0:
@@ -3978,7 +3923,7 @@ react-is@^16.13.1, react-is@^16.7.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^18.2.0, react-is@^18.3.1:
react-is@^18.3.1:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==