Compare commits

...
2 Commits
Author SHA1 Message Date
Matthew Russell 84e82321b8 wip: fix me - move to ui toolkit 2023-02-19 00:50:09 -08:00
Matthew Russell 5e3cfbe8b4 feat: make composable navigation 2023-02-19 00:37:50 -08:00
11 changed files with 831 additions and 16 deletions
+33 -3
View File
@@ -1,13 +1,21 @@
import { Link } from 'react-router-dom';
import { NetworkSwitcher } from '@vegaprotocol/environment';
import { useEffect, useState } from 'react';
import { TOP_LEVEL_ROUTES } from '../../routes/routes';
import { TOP_LEVEL_ROUTES, TOKEN_DROPDOWN_ROUTES } from '../../routes/routes';
import { useTranslation } from 'react-i18next';
import logoWhiteText from '../../images/logo-white-text.png';
import logoBlackText from '../../images/logo-black-text.png';
import debounce from 'lodash/debounce';
import { NavDrawer } from './nav-draw';
import { Nav as ToolkitNav } from '@vegaprotocol/ui-toolkit';
import {
Nav as ToolkitNav,
Navbar,
NavigationContent,
NavigationItem,
NavigationLink,
NavigationList,
NavigationTrigger,
} from '@vegaprotocol/ui-toolkit';
import { AppNavLink } from './nav-link';
import { NavDropDown } from './nav-dropdown';
@@ -41,7 +49,28 @@ export const Nav = ({ navbarTheme = 'inherit' }: NavbarProps) => {
const { t } = useTranslation();
const isYellow = navbarTheme === 'yellow';
return (
<Navbar>
<NavigationList>
{TOP_LEVEL_ROUTES.map((r) => (
<NavigationItem key={r.path}>
<NavigationLink path={r.path}>{t(r.name)}</NavigationLink>
</NavigationItem>
))}
<NavigationItem>
<NavigationTrigger>{t('Token')}</NavigationTrigger>
<NavigationContent backText={t('Token')}>
{TOKEN_DROPDOWN_ROUTES.map((r) => (
<NavigationItem>
<NavigationLink path={r.path}>{r.name}</NavigationLink>
</NavigationItem>
))}
</NavigationContent>
</NavigationItem>
</NavigationList>
</Navbar>
);
/*
return (
<ToolkitNav
navbarTheme={navbarTheme}
@@ -78,4 +107,5 @@ export const Nav = ({ navbarTheme = 'inherit' }: NavbarProps) => {
)}
</ToolkitNav>
);
*/
};
+1 -1
View File
@@ -35,7 +35,7 @@ export const TOP_LEVEL_ROUTES = [
export const TOKEN_DROPDOWN_ROUTES = [
{
name: 'Token',
name: 'Information',
path: Routes.TOKEN,
},
{
+1 -1
View File
@@ -1 +1 @@
export * from './navbar';
export * from './navbar2';
+1 -1
View File
@@ -185,7 +185,7 @@ interface AppNavLinkProps {
onClick?: () => void;
}
const AppNavLink = ({
export const AppNavLink = ({
name,
path,
navbarTheme,
+295
View File
@@ -0,0 +1,295 @@
import { NavLink } from 'react-router-dom';
import { Vega } from '../icons/vega';
import { create } from 'zustand';
import * as NavigationMenu from '@radix-ui/react-navigation-menu';
import type { ReactNode } from 'react';
import * as Dialog from '@radix-ui/react-dialog';
import { Icon, ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
import { NetworkSwitcher } from '@vegaprotocol/environment';
import classNames from 'classnames';
import { VegaWalletConnectButton } from '../vega-wallet-connect-button';
import { animated, useTransition, useSpring, config } from 'react-spring';
const BREAKPOINT = 760;
const useNav = create<{
drawerOpen: boolean;
value: string;
update: (state: Partial<{ drawerOpen: boolean; value: string }>) => void;
}>((set) => ({
drawerOpen: false,
value: '',
update: (state) => set(state),
}));
export const Navbar = ({ children }: { children: ReactNode }) => {
return (
<div className="px-4 border-b border-vega-light-200 dark:border-vega-dark-200">
<div className="flex items-center gap-2">
<div className="py-3 mr-4">
<Vega />
</div>
{window.innerWidth > BREAKPOINT ? (
<Menu>{children}</Menu>
) : (
<Drawer>{children}</Drawer>
)}
</div>
</div>
);
};
const Menu = ({ children }: { children: ReactNode }) => {
const { value, update } = useNav();
return (
<>
<div className="mr-4">
<NetworkSwitcher />
</div>
<NavigationMenu.Root
value={value}
onValueChange={(value) => update({ value })}
className="relative self-end"
>
{children}
</NavigationMenu.Root>
<div className="flex items-center gap-2 ml-auto">
<VegaWalletConnectButton />
<ThemeSwitcher />
</div>
</>
);
};
const Drawer = ({ children }: { children: ReactNode }) => {
const { drawerOpen, value, update } = useNav();
const transition = useTransition(drawerOpen, {
from: { opacity: 0, transform: 'translateX(100%)' },
enter: { opacity: 1, transform: 'translateX(0%)' },
leave: { opacity: 0, transform: 'translateX(100%)' },
config: {
...config.default,
duration: 200,
},
});
return (
<>
<div className="ml-auto">
<MenuButton open={false} onClick={() => update({ drawerOpen: true })} />
</div>
<Dialog.Root
open={drawerOpen}
onOpenChange={(open) => update({ drawerOpen: open })}
>
<Dialog.Portal forceMount={true}>
{transition((styles, isOpen) => {
return isOpen ? (
<>
<Dialog.Overlay
forceMount={true}
asChild={true}
className="fixed inset-0 bg-black/50"
>
<animated.div style={{ opacity: styles.opacity }} />
</Dialog.Overlay>
<Dialog.Content
forceMount={true}
asChild={true}
className="absolute top-0 right-0 py-4 px-6 w-10/12 border-l border-vega-dark-200 h-screen bg-white dark:bg-black text-black dark:text-white"
>
<animated.div style={{ transform: styles.transform }}>
<div className="absolute top-3 right-3">
<MenuButton
open={true}
onClick={() => update({ drawerOpen: false })}
/>
</div>
<div className="pt-10">
<div className="pb-6 mb-6 border-b border-vega-dark-200">
<NetworkSwitcher />
</div>
<NavigationMenu.Root
value={value}
onValueChange={(value) => update({ value })}
>
{children}
<NavigationMenu.Viewport className="absolute w-full h-full top-0 left-0 bg-black" />
</NavigationMenu.Root>
<div className="pt-6 mt-6 border-t border-vega-dark-200">
<ThemeSwitcher />
</div>
</div>
</animated.div>
</Dialog.Content>
</>
) : null;
})}
</Dialog.Portal>
</Dialog.Root>
</>
);
};
export const NavigationList = ({ children }: { children: ReactNode }) => {
return (
<NavigationMenu.List className="flex flex-col md:flex-row gap-2">
{children}
</NavigationMenu.List>
);
};
export const NavigationItem = ({ children }: { children: ReactNode }) => {
return (
<NavigationMenu.Item className="relative mb-4 md:mb-0 last:mb-0 md:mr-4 last:mr-0 whitespace-nowrap">
{children}
</NavigationMenu.Item>
);
};
export const NavigationLink = ({
children,
path,
}: {
children: ReactNode;
path: string;
}) => {
const update = useNav((store) => store.update);
const borderClasses = classNames(
'absolute h-[2px] w-full bottom-[-1px] left-0',
'bg-black dark:bg-vega-yellow'
);
return (
<NavigationMenu.Link
asChild={true}
onClick={() => update({ drawerOpen: false, value: '' })}
>
<NavLink to={path} className="inline-block md:pt-2 text-lg">
{({ isActive }) => {
const linkTextClasses = classNames('hover:text-white', {
'text-white': isActive,
'text-vega-dark-300': !isActive,
});
return (
<span className="block relative pb-1 md:pb-2">
<span className={linkTextClasses}>{children}</span>
{isActive && <span className={borderClasses} />}
</span>
);
}}
</NavLink>
</NavigationMenu.Link>
);
};
export const NavigationTrigger = ({ children }: { children: ReactNode }) => {
// eslint-disable-next-line
const preventHover = (event: any) => {
const e = event as Event;
if (window.innerWidth < BREAKPOINT) e.preventDefault();
};
return (
<NavigationMenu.Trigger
onPointerMove={preventHover}
onPointerLeave={preventHover}
onPointerEnter={preventHover}
className="w-full flex items-center justify-between text-vega-dark-300 hover:text-white text-lg md:py-2"
>
{children}
<span className="md:rotate-90 md:ml-3">
<Icon name="arrow-right" size={3} />
</span>
</NavigationMenu.Trigger>
);
};
export const NavigationContent = ({
children,
backText,
}: {
children: ReactNode;
backText: string;
}) => {
return (
<NavigationMenu.Content>
<NavigationContentWrapper backText={backText}>
{children}
</NavigationContentWrapper>
</NavigationMenu.Content>
);
};
const NavigationContentWrapper = ({
backText,
children,
}: {
backText: string;
children: ReactNode;
}) => {
const drawerConfig = {
from: { transform: 'translateX(100%)' },
to: { transform: 'translateX(0%)' },
config: {
...config,
duration: 200,
},
};
const menuConfig = {
from: { opacity: 0, transform: 'translateY(40px)' },
to: { opacity: 1, transform: 'translateY(0)' },
config: {
...config,
duration: 100,
},
};
const styles = useSpring(
window.innerWidth > BREAKPOINT ? menuConfig : drawerConfig
);
return (
<animated.div
style={styles}
className="pt-20 md:py-2 px-4 z-30 md:absolute md:mt-3 md:border border-vega-dark-200 bg-black dark:md:bg-vega-dark-100 md:rounded-xl"
>
<div className="flex items-center md:hidden mb-6 text-vega-dark-300 hover:text-white">
<Icon name="arrow-left" size={3} />
<span className="ml-2">{backText}</span>
</div>
<ul className="md:min-w-[250px]">{children}</ul>
</animated.div>
);
};
const MenuButton = ({
open,
onClick,
}: {
open: boolean;
onClick: () => void;
}) => (
<button
className={classNames(
'flex flex-col justify-around gap-3 p-2 relative z-30 h-[34px]',
{
'z-50': open,
}
)}
onClick={onClick}
data-testid="button-menu-drawer"
>
<div
className={classNames('w-[26px] h-[2px] transition-all', {
'translate-y-0 rotate-0 bg-white': !open,
// 'bg-black': !drawerOpen && navbarTheme === 'yellow',
'translate-y-[7.5px] rotate-45 bg-black dark:bg-white': open,
})}
/>
<div
className={classNames('w-[26px] h-[2px] transition-all', {
'translate-y-0 rotate-0 bg-white': !open,
// 'bg-black': !drawerOpen && navbarTheme === 'yellow',
'-translate-y-[7.5px] -rotate-45 bg-black dark:bg-white': open,
})}
/>
</button>
);
+81 -5
View File
@@ -1,6 +1,13 @@
import Head from 'next/head';
import type { AppProps } from 'next/app';
import { Navbar } from '../components/navbar';
import {
Navbar,
NavigationContent,
NavigationItem,
NavigationLink,
NavigationList,
NavigationTrigger,
} from '../components/navbar';
import { t } from '@vegaprotocol/react-helpers';
import {
useEagerConnect as useVegaEagerConnect,
@@ -28,12 +35,19 @@ import { Footer } from '../components/footer';
import { useMemo, useState } from 'react';
import DialogsContainer from './dialogs-container';
import ToastsManager from './toasts-manager';
import { HashRouter, useLocation, useSearchParams } from 'react-router-dom';
import {
HashRouter,
Link,
NavLink,
useLocation,
useSearchParams,
} from 'react-router-dom';
import { Connectors } from '../lib/vega-connectors';
import { ViewingBanner } from '../components/viewing-banner';
import { Banner } from '../components/banner';
import classNames from 'classnames';
import { AppLoader } from '../components/app-loader';
import { Links, Routes } from './client-router';
const DEFAULT_TITLE = t('Welcome to Vega trading!');
@@ -68,6 +82,12 @@ const TransactionsHandler = () => {
};
function AppBody({ Component }: AppProps) {
const { marketId } = useGlobalStore((store) => ({
marketId: store.marketId,
}));
const tradingPath = marketId
? Links[Routes.MARKET](marketId)
: Links[Routes.MARKET]();
const location = useLocation();
const { VEGA_ENV } = useEnvironment();
@@ -84,10 +104,66 @@ function AppBody({ Component }: AppProps) {
</Head>
<Title />
<div className={gridClasses}>
<Navbar
navbarTheme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'dark'}
/>
<Banner />
<Navbar
// navbarTheme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'dark'}
>
<NavigationList>
<NavigationItem>
<NavigationLink path={Links[Routes.MARKETS]()}>
Markets
</NavigationLink>
</NavigationItem>
<NavigationItem>
<NavigationLink path={tradingPath}>Trading</NavigationLink>
</NavigationItem>
<NavigationItem>
<NavigationLink path={Links[Routes.PORTFOLIO]()}>
Portfolio
</NavigationLink>
</NavigationItem>
<NavigationItem>
<NavigationTrigger>Dropdown</NavigationTrigger>
<NavigationContent backText="Token">
<NavigationItem>
<NavigationLink path={tradingPath}>Trading</NavigationLink>
</NavigationItem>
<NavigationItem>
<NavigationLink path={Links[Routes.PORTFOLIO]()}>
Portfolio
</NavigationLink>
</NavigationItem>
<NavigationItem>
<NavigationLink path="https://google.com">
Redeem Vested Tokens
</NavigationLink>
</NavigationItem>
</NavigationContent>
</NavigationItem>
<NavigationItem>
<NavigationTrigger>Another</NavigationTrigger>
<NavigationContent backText="Another">
<NavigationItem>
<NavigationLink path="https://google.com">Foo</NavigationLink>
</NavigationItem>
<NavigationItem>
<NavigationLink path="https://google.com">Bar</NavigationLink>
</NavigationItem>
<NavigationItem>
<NavigationLink path="https://google.com">Quz</NavigationLink>
</NavigationItem>
</NavigationContent>
</NavigationItem>
</NavigationList>
</Navbar>
<ViewingBanner />
<main data-testid={location.pathname}>
<Component />
+10 -5
View File
@@ -8,10 +8,10 @@ export const useNodeHealth = () => {
const url = useEnvironment((store) => store.VEGA_URL);
const headerStore = useHeaderStore();
const headers = url ? headerStore[url] : undefined;
const { data, error, loading, stopPolling } = useStatisticsQuery({
pollInterval: 1000,
fetchPolicy: 'no-cache',
});
const { data, error, loading, startPolling, stopPolling } =
useStatisticsQuery({
fetchPolicy: 'no-cache',
});
const blockDiff = useMemo(() => {
if (!data?.statistics.blockHeight) {
@@ -28,8 +28,13 @@ export const useNodeHealth = () => {
useEffect(() => {
if (error) {
stopPolling();
return;
}
}, [error, stopPolling]);
if (!('Cypress' in window)) {
startPolling(1000);
}
}, [error, startPolling, stopPolling]);
return {
error,
@@ -1 +1,2 @@
export * from './nav';
export * from './nav2';
+287
View File
@@ -0,0 +1,287 @@
import { NavLink } from 'react-router-dom';
import { create } from 'zustand';
import * as NavigationMenu from '@radix-ui/react-navigation-menu';
import type { ReactNode } from 'react';
import * as Dialog from '@radix-ui/react-dialog';
import { Icon, ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
import { NetworkSwitcher } from '@vegaprotocol/environment';
import classNames from 'classnames';
import { animated, useTransition, useSpring, config } from 'react-spring';
const BREAKPOINT = 760;
const useNav = create<{
drawerOpen: boolean;
value: string;
update: (state: Partial<{ drawerOpen: boolean; value: string }>) => void;
}>((set) => ({
drawerOpen: false,
value: '',
update: (state) => set(state),
}));
export const Navbar = ({ children }: { children: ReactNode }) => {
return (
<div className="px-4 border-b border-vega-light-200 dark:border-vega-dark-200">
<div className="flex items-center gap-2">
<div className="py-3 mr-4">THE ICON</div>
{window.innerWidth > BREAKPOINT ? (
<Menu>{children}</Menu>
) : (
<Drawer>{children}</Drawer>
)}
</div>
</div>
);
};
const Menu = ({ children }: { children: ReactNode }) => {
const { value, update } = useNav();
return (
<>
<div className="mr-4">
<NetworkSwitcher />
</div>
<NavigationMenu.Root
value={value}
onValueChange={(value) => update({ value })}
className="relative self-end"
>
{children}
</NavigationMenu.Root>
<div className="flex items-center gap-2 ml-auto">
<ThemeSwitcher />
</div>
</>
);
};
const Drawer = ({ children }: { children: ReactNode }) => {
const { drawerOpen, value, update } = useNav();
const transition = useTransition(drawerOpen, {
from: { opacity: 0, transform: 'translateX(100%)' },
enter: { opacity: 1, transform: 'translateX(0%)' },
leave: { opacity: 0, transform: 'translateX(100%)' },
config: {
...config.default,
duration: 200,
},
});
return (
<>
<div className="ml-auto">
<MenuButton open={false} onClick={() => update({ drawerOpen: true })} />
</div>
<Dialog.Root
open={drawerOpen}
onOpenChange={(open) => update({ drawerOpen: open })}
>
<Dialog.Portal forceMount={true}>
{transition((styles, isOpen) => {
return isOpen ? (
<>
<Dialog.Overlay
forceMount={true}
asChild={true}
className="fixed inset-0 bg-black/50"
>
<animated.div style={{ opacity: styles.opacity }} />
</Dialog.Overlay>
<Dialog.Content
forceMount={true}
asChild={true}
className="absolute top-0 right-0 py-4 px-6 w-10/12 border-l border-vega-dark-200 h-screen bg-white dark:bg-black text-black dark:text-white"
>
<animated.div style={{ transform: styles.transform }}>
<div className="absolute top-3 right-3">
<MenuButton
open={true}
onClick={() => update({ drawerOpen: false })}
/>
</div>
<div className="pt-10">
<div className="pb-6 mb-6 border-b border-vega-dark-200">
<NetworkSwitcher />
</div>
<NavigationMenu.Root
value={value}
onValueChange={(value) => update({ value })}
>
{children}
<NavigationMenu.Viewport className="absolute w-full h-full top-0 left-0 bg-black" />
</NavigationMenu.Root>
<div className="pt-6 mt-6 border-t border-vega-dark-200">
<ThemeSwitcher />
</div>
</div>
</animated.div>
</Dialog.Content>
</>
) : null;
})}
</Dialog.Portal>
</Dialog.Root>
</>
);
};
export const NavigationList = ({ children }: { children: ReactNode }) => {
return (
<NavigationMenu.List className="flex flex-col md:flex-row gap-2">
{children}
</NavigationMenu.List>
);
};
export const NavigationItem = ({ children }: { children: ReactNode }) => {
return (
<NavigationMenu.Item className="relative mb-4 md:mb-0 last:mb-0 md:mr-4 last:mr-0 whitespace-nowrap">
{children}
</NavigationMenu.Item>
);
};
export const NavigationLink = ({
children,
path,
}: {
children: ReactNode;
path: string;
}) => {
const update = useNav((store) => store.update);
const borderClasses = classNames(
'absolute h-[2px] w-full bottom-[-1px] left-0',
'bg-black dark:bg-vega-yellow'
);
return (
<NavigationMenu.Link
asChild={true}
onClick={() => update({ drawerOpen: false, value: '' })}
>
<NavLink to={path} className="inline-block md:pt-2 text-lg">
{({ isActive }) => {
const linkTextClasses = classNames('hover:text-white', {
'text-white': isActive,
'text-vega-dark-300': !isActive,
});
return (
<span className="block relative pb-1 md:pb-2">
<span className={linkTextClasses}>{children}</span>
{isActive && <span className={borderClasses} />}
</span>
);
}}
</NavLink>
</NavigationMenu.Link>
);
};
export const NavigationTrigger = ({ children }: { children: ReactNode }) => {
// eslint-disable-next-line
const preventHover = (event: any) => {
const e = event as Event;
if (window.innerWidth < BREAKPOINT) e.preventDefault();
};
return (
<NavigationMenu.Trigger
onPointerMove={preventHover}
onPointerLeave={preventHover}
onPointerEnter={preventHover}
className="w-full flex items-center justify-between text-vega-dark-300 hover:text-white text-lg md:py-2"
>
{children}
<span className="md:rotate-90 md:ml-3">
<Icon name="arrow-right" size={3} />
</span>
</NavigationMenu.Trigger>
);
};
export const NavigationContent = ({
children,
backText,
}: {
children: ReactNode;
backText: string;
}) => {
return (
<NavigationMenu.Content>
<NavigationContentWrapper backText={backText}>
{children}
</NavigationContentWrapper>
</NavigationMenu.Content>
);
};
const NavigationContentWrapper = ({
backText,
children,
}: {
backText: string;
children: ReactNode;
}) => {
const drawerConfig = {
from: { transform: 'translateX(100%)' },
to: { transform: 'translateX(0%)' },
config: {
...config,
duration: 200,
},
};
const menuConfig = {
from: { opacity: 0, transform: 'translateY(40px)' },
to: { opacity: 1, transform: 'translateY(0)' },
config: {
...config,
duration: 100,
},
};
const styles = useSpring(
window.innerWidth > BREAKPOINT ? menuConfig : drawerConfig
);
return (
<animated.div
style={styles}
className="pt-20 md:py-2 px-4 z-30 md:absolute md:mt-3 md:border border-vega-dark-200 bg-black dark:md:bg-vega-dark-100 md:rounded-xl"
>
<div className="flex items-center md:hidden mb-6 text-vega-dark-300 hover:text-white">
<Icon name="arrow-left" size={3} />
<span className="ml-2">{backText}</span>
</div>
<ul className="md:min-w-[250px]">{children}</ul>
</animated.div>
);
};
const MenuButton = ({
open,
onClick,
}: {
open: boolean;
onClick: () => void;
}) => (
<button
className={classNames(
'flex flex-col justify-around gap-3 p-2 relative h-[34px]'
)}
onClick={onClick}
data-testid="button-menu-drawer"
>
<div
className={classNames('w-[26px] h-[2px] transition-all', {
'translate-y-0 rotate-0 bg-white': !open,
// 'bg-black': !drawerOpen && navbarTheme === 'yellow',
'translate-y-[7.5px] rotate-45 bg-black dark:bg-white': open,
})}
/>
<div
className={classNames('w-[26px] h-[2px] transition-all', {
'translate-y-0 rotate-0 bg-white': !open,
// 'bg-black': !drawerOpen && navbarTheme === 'yellow',
'-translate-y-[7.5px] -rotate-45 bg-black dark:bg-white': open,
})}
/>
</button>
);
+2
View File
@@ -27,6 +27,7 @@
"@radix-ui/react-dialog": "^1.0.2",
"@radix-ui/react-dropdown-menu": "^2.0.2",
"@radix-ui/react-icons": "^1.1.1",
"@radix-ui/react-navigation-menu": "^1.1.1",
"@radix-ui/react-popover": "^1.0.3",
"@radix-ui/react-radio-group": "^1.1.1",
"@radix-ui/react-select": "^1.2.0",
@@ -73,6 +74,7 @@
"react-i18next": "^11.11.4",
"react-intersection-observer": "^9.2.2",
"react-router-dom": "6.3.0",
"react-spring": "^9.6.1",
"react-syntax-highlighter": "^15.4.5",
"react-use-websocket": "^3.0.0",
"react-virtualized-auto-sizer": "^1.0.6",
+119
View File
@@ -4323,6 +4323,27 @@
aria-hidden "^1.1.1"
react-remove-scroll "2.5.5"
"@radix-ui/react-navigation-menu@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.1.1.tgz#84f24d90e6448a0c83d3431c6eefbea73dc7522e"
integrity sha512-Khgf+LwqYfUpbFAHcFPDMj6ZrWxnwCgC96liLYwE48x9YJbXGlutOWzZaSzrgl82xS+PwoPLQunfDe/i4ZITRA==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "1.0.0"
"@radix-ui/react-collection" "1.0.1"
"@radix-ui/react-compose-refs" "1.0.0"
"@radix-ui/react-context" "1.0.0"
"@radix-ui/react-direction" "1.0.0"
"@radix-ui/react-dismissable-layer" "1.0.2"
"@radix-ui/react-id" "1.0.0"
"@radix-ui/react-presence" "1.0.0"
"@radix-ui/react-primitive" "1.0.1"
"@radix-ui/react-use-callback-ref" "1.0.0"
"@radix-ui/react-use-controllable-state" "1.0.0"
"@radix-ui/react-use-layout-effect" "1.0.0"
"@radix-ui/react-use-previous" "1.0.0"
"@radix-ui/react-visually-hidden" "1.0.1"
"@radix-ui/react-popover@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.0.3.tgz#65ae2ee1fca2d7fd750308549eb8e0857c6160fe"
@@ -4576,6 +4597,92 @@
dependencies:
"@babel/runtime" "^7.13.10"
"@react-spring/animated@~9.6.1":
version "9.6.1"
resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.6.1.tgz#ccc626d847cbe346f5f8815d0928183c647eb425"
integrity sha512-ls/rJBrAqiAYozjLo5EPPLLOb1LM0lNVQcXODTC1SMtS6DbuBCPaKco5svFUQFMP2dso3O+qcC4k9FsKc0KxMQ==
dependencies:
"@react-spring/shared" "~9.6.1"
"@react-spring/types" "~9.6.1"
"@react-spring/core@~9.6.1":
version "9.6.1"
resolved "https://registry.yarnpkg.com/@react-spring/core/-/core-9.6.1.tgz#ebe07c20682b360b06af116ea24e2b609e778c10"
integrity sha512-3HAAinAyCPessyQNNXe5W0OHzRfa8Yo5P748paPcmMowZ/4sMfaZ2ZB6e5x5khQI8NusOHj8nquoutd6FRY5WQ==
dependencies:
"@react-spring/animated" "~9.6.1"
"@react-spring/rafz" "~9.6.1"
"@react-spring/shared" "~9.6.1"
"@react-spring/types" "~9.6.1"
"@react-spring/konva@~9.6.1":
version "9.6.1"
resolved "https://registry.yarnpkg.com/@react-spring/konva/-/konva-9.6.1.tgz#66e63da0e9681e42395e995402a7e73ba6892461"
integrity sha512-MevnU+tnG1LPsmMRpfJfevfLtI0ObIvrwYc+Xg+kmYJe00vwMRSdulQOztKANKalFXBewwk72XrQCeRLXFaUIg==
dependencies:
"@react-spring/animated" "~9.6.1"
"@react-spring/core" "~9.6.1"
"@react-spring/shared" "~9.6.1"
"@react-spring/types" "~9.6.1"
"@react-spring/native@~9.6.1":
version "9.6.1"
resolved "https://registry.yarnpkg.com/@react-spring/native/-/native-9.6.1.tgz#b66e237f2faaa4f88569d5a03b6fb0136bcdf2b9"
integrity sha512-ZIfSytxFGLw4gYOb8gsmwG0+JZYxuM/Y1XPCXCkhuoMn+RmOYrr0kQ4gLczbmf+TRxth7OT1c8vBYz0+SCGcIQ==
dependencies:
"@react-spring/animated" "~9.6.1"
"@react-spring/core" "~9.6.1"
"@react-spring/shared" "~9.6.1"
"@react-spring/types" "~9.6.1"
"@react-spring/rafz@~9.6.1":
version "9.6.1"
resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.6.1.tgz#d71aafb92b78b24e4ff84639f52745afc285c38d"
integrity sha512-v6qbgNRpztJFFfSE3e2W1Uz+g8KnIBs6SmzCzcVVF61GdGfGOuBrbjIcp+nUz301awVmREKi4eMQb2Ab2gGgyQ==
"@react-spring/shared@~9.6.1":
version "9.6.1"
resolved "https://registry.yarnpkg.com/@react-spring/shared/-/shared-9.6.1.tgz#4e2e4296910656c02bd9fd54c559702bc836ac4e"
integrity sha512-PBFBXabxFEuF8enNLkVqMC9h5uLRBo6GQhRMQT/nRTnemVENimgRd+0ZT4yFnAQ0AxWNiJfX3qux+bW2LbG6Bw==
dependencies:
"@react-spring/rafz" "~9.6.1"
"@react-spring/types" "~9.6.1"
"@react-spring/three@~9.6.1":
version "9.6.1"
resolved "https://registry.yarnpkg.com/@react-spring/three/-/three-9.6.1.tgz#095fcd1dc6509127c33c14486d88289b89baeb9d"
integrity sha512-Tyw2YhZPKJAX3t2FcqvpLRb71CyTe1GvT3V+i+xJzfALgpk10uPGdGaQQ5Xrzmok1340DAeg2pR/MCfaW7b8AA==
dependencies:
"@react-spring/animated" "~9.6.1"
"@react-spring/core" "~9.6.1"
"@react-spring/shared" "~9.6.1"
"@react-spring/types" "~9.6.1"
"@react-spring/types@~9.6.1":
version "9.6.1"
resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.6.1.tgz#913d3a68c5cbc1124fdb18eff919432f7b6abdde"
integrity sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q==
"@react-spring/web@~9.6.1":
version "9.6.1"
resolved "https://registry.yarnpkg.com/@react-spring/web/-/web-9.6.1.tgz#3e4c03b724d2b545dc2fa2649eb6109318ab9178"
integrity sha512-X2zR6q2Z+FjsWfGAmAXlQaoUHbPmfuCaXpuM6TcwXPpLE1ZD4A1eys/wpXboFQmDkjnrlTmKvpVna1MjWpZ5Hw==
dependencies:
"@react-spring/animated" "~9.6.1"
"@react-spring/core" "~9.6.1"
"@react-spring/shared" "~9.6.1"
"@react-spring/types" "~9.6.1"
"@react-spring/zdog@~9.6.1":
version "9.6.1"
resolved "https://registry.yarnpkg.com/@react-spring/zdog/-/zdog-9.6.1.tgz#5292c374e23e3846db3eb9d7557ed5a7bb40dada"
integrity sha512-0jSGm2OFW/+/+4dkRp46KzEkcLVfzV2k6DO1om0dLDtQ4q6FpX4dmDTlRc7Apzin6VtfQONMFIGITtbqoS28MQ==
dependencies:
"@react-spring/animated" "~9.6.1"
"@react-spring/core" "~9.6.1"
"@react-spring/shared" "~9.6.1"
"@react-spring/types" "~9.6.1"
"@repeaterjs/repeater@^3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.4.tgz#a04d63f4d1bf5540a41b01a921c9a7fddc3bd1ca"
@@ -19261,6 +19368,18 @@ react-smooth@^2.0.1:
fast-equals "^2.0.0"
react-transition-group "2.9.0"
react-spring@^9.6.1:
version "9.6.1"
resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-9.6.1.tgz#e715b2fa523c1a3acfdcf1aaa93e081620b8cc8e"
integrity sha512-BeP80R4SLb1bZHW/Q62nECoScHw/fH+jzGkD7dc892HNGa+lbGIJXURc6U7N8JfZ8peEO46nPxR57aUMuYzquQ==
dependencies:
"@react-spring/core" "~9.6.1"
"@react-spring/konva" "~9.6.1"
"@react-spring/native" "~9.6.1"
"@react-spring/three" "~9.6.1"
"@react-spring/web" "~9.6.1"
"@react-spring/zdog" "~9.6.1"
react-style-singleton@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4"