1
0
mirror of https://github.com/checktheroads/hyperglass synced 2024-05-11 05:55:08 +00:00

continue typescript & chakra v1 migrations [skip ci]

This commit is contained in:
checktheroads
2020-11-29 18:26:42 -07:00
parent e823c3416b
commit a2a7f3407b
41 changed files with 340 additions and 336 deletions

View File

@@ -1,73 +0,0 @@
import * as React from 'react';
import { forwardRef } from 'react';
import { Button, useColorMode } from '@chakra-ui/core';
const Sun = ({ color, size = '1.5rem', ...props }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
style={{
height: size,
width: size,
}}
strokeWidth={0}
stroke="currentColor"
fill="currentColor"
{...props}>
<path
d="M256 32a224 224 0 00-161.393 69.035h323.045A224 224 0 00256 32zM79.148 118.965a224 224 0 00-16.976 25.16H449.74a224 224 0 00-16.699-25.16H79.148zm-27.222 45.16A224 224 0 0043.3 186.25h425.271a224 224 0 00-8.586-22.125H51.926zM36.783 210.25a224 224 0 00-3.02 19.125h444.368a224 224 0 00-3.113-19.125H36.783zm-4.752 45.125A224 224 0 0032 256a224 224 0 00.64 16.5h446.534A224 224 0 00480 256a224 224 0 00-.021-.625H32.03zm4.67 45.125a224 224 0 003.395 15.125h431.578a224 224 0 003.861-15.125H36.701zm14.307 45.125a224 224 0 006.017 13.125H454.82a224 224 0 006.342-13.125H51.008zm26.316 45.125a224 224 0 009.04 11.125H425.86a224 224 0 008.727-11.125H77.324zm45.62 45.125A224 224 0 00136.247 445h239.89a224 224 0 0012.936-9.125h-266.13z"
fill={color || 'currentColor'}
/>
</svg>
);
const Moon = ({ color, size = '1.5rem', ...props }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
style={{
height: size,
width: size,
}}
strokeWidth={0}
stroke="currentColor"
fill="currentColor"
{...props}>
<path
d="M14.53 10.53a7 7 0 01-9.058-9.058A7.003 7.003 0 008 15a7.002 7.002 0 006.53-4.47z"
fill={color || 'currentColor'}
fillRule="evenodd"
clipRule="evenodd"
/>
</svg>
);
const iconMap = { dark: Moon, light: Sun };
const outlineColor = { dark: 'primary.300', light: 'primary.600' };
export const ColorModeToggle = forwardRef((props, ref) => {
const { colorMode, toggleColorMode } = useColorMode();
const Icon = iconMap[colorMode];
const label = `Switch to ${colorMode === 'light' ? 'dark' : 'light'} mode`;
return (
<Button
ref={ref}
aria-label={label}
title={label}
onClick={toggleColorMode}
variant="ghost"
borderWidth="1px"
borderColor="transparent"
_hover={{
backgroundColor: 'unset',
borderColor: outlineColor[colorMode],
}}
color="current"
px={4}
{...props}>
<Icon />
</Button>
);
});

View File

@@ -1,55 +0,0 @@
import * as React from 'react';
import { Flex, FormControl, FormLabel, FormErrorMessage, useColorMode } from '@chakra-ui/core';
const labelColor = { dark: 'whiteAlpha.700', light: 'blackAlpha.700' };
export const FormField = ({
label,
name,
error,
hiddenLabels,
helpIcon,
targetInfo,
setTarget,
labelAddOn,
fieldAddOn,
children,
...props
}) => {
const { colorMode } = useColorMode();
return (
<FormControl
as={Flex}
flexDirection="column"
flex={['1 0 100%', '1 0 100%', '1 0 33.33%', '1 0 33.33%']}
w="100%"
maxW="100%"
mx={2}
my={[2, 2, 4, 4]}
isInvalid={error && error.message}
{...props}>
<FormLabel
htmlFor={name}
color={labelColor[colorMode]}
pl={1}
opacity={hiddenLabels ? 0 : null}
display="flex"
alignItems="center"
justifyContent="space-between"
pr={0}>
{label}
{labelAddOn || null}
</FormLabel>
{children}
{fieldAddOn && (
<Flex justifyContent="flex-end" pt={3}>
{fieldAddOn}
</Flex>
)}
<FormErrorMessage opacity={hiddenLabels ? 0 : null}>
{error && error.message}
</FormErrorMessage>
</FormControl>
);
};

View File

@@ -1,67 +0,0 @@
import * as React from 'react';
import {
Button,
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalFooter,
ModalBody,
ModalCloseButton,
useColorMode,
useDisclosure,
} from '@chakra-ui/core';
import { Markdown } from 'app/components';
import { motion } from 'framer-motion';
const bg = { light: 'white', dark: 'black' };
const color = { light: 'black', dark: 'white' };
const AnimatedModalContent = motion.custom(ModalContent);
const AnimatedModalOverlay = motion.custom(ModalOverlay);
export const Greeting = ({ greetingConfig, content, onClickThrough }) => {
const { isOpen, onOpen, onClose } = useDisclosure(true);
const { colorMode } = useColorMode();
const handleClick = () => {
onClickThrough(true);
onClose();
};
return (
<Modal
onClose={handleClick}
isOpen={isOpen}
size="full"
isCentered
closeOnOverlayClick={!greetingConfig.required}
closeOnEsc={!greetingConfig.required}>
<AnimatedModalOverlay
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.3, delay: 0.7 }}
/>
<AnimatedModalContent
initial={{ scale: 0.5, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ duration: 0.3, delay: 0.7 }}
bg={bg[colorMode]}
color={color[colorMode]}
py={4}
borderRadius="md"
maxW={['95%', '75%', '75%', '75%']}>
<ModalHeader>{greetingConfig.title}</ModalHeader>
{!greetingConfig.required && <ModalCloseButton />}
<ModalBody>
<Markdown content={content} />
</ModalBody>
<ModalFooter>
<Button variantColor="primary" onClick={handleClick}>
{greetingConfig.button}
</Button>
</ModalFooter>
</AnimatedModalContent>
</Modal>
);
};

View File

@@ -1,58 +0,0 @@
import * as React from 'react';
import { useRef } from 'react';
import { Flex, useColorMode } from '@chakra-ui/core';
import { useConfig, useHyperglassState } from 'app/context';
import { Debugger, Greeting, Footer, Header } from 'app/components';
const bg = { light: 'white', dark: 'black' };
const color = { light: 'black', dark: 'white' };
export const Layout = ({ children }) => {
const config = useConfig();
const { colorMode } = useColorMode();
const { greetingAck, setGreetingAck, setSubmitting, setFormData } = useHyperglassState();
const containerRef = useRef(null);
const resetForm = () => {
containerRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' });
setSubmitting(false);
setFormData({});
};
return (
<>
<Flex
w="100%"
ref={containerRef}
minHeight="100vh"
bg={bg[colorMode]}
flexDirection="column"
color={color[colorMode]}>
<Flex px={2} flex="0 1 auto" flexDirection="column">
<Header resetForm={resetForm} />
</Flex>
<Flex
px={2}
py={0}
w="100%"
as="main"
flex="1 1 auto"
textAlign="center"
alignItems="center"
justifyContent="start"
flexDirection="column">
{children}
</Flex>
<Footer />
{config.developer_mode && <Debugger />}
</Flex>
{config.web.greeting.enable && !greetingAck && (
<Greeting
greetingConfig={config.web.greeting}
content={config.content.greeting}
onClickThrough={setGreetingAck}
/>
)}
</>
);
};

View File

@@ -1,10 +0,0 @@
import * as React from 'react';
import { Button, Icon, Tooltip } from '@chakra-ui/core';
export const RequeryButton = ({ requery, bg = 'secondary', ...props }) => (
<Tooltip hasArrow label="Reload Query" placement="top">
<Button mx={1} as="a" size="sm" zIndex="1" variantColor={bg} onClick={requery} {...props}>
<Icon size="16px" name="repeat" />
</Button>
</Tooltip>
);

View File

@@ -1 +1,2 @@
export * from './animated';
export * from './if';

View File

@@ -0,0 +1,44 @@
import { forwardRef } from 'react';
import dynamic from 'next/dynamic';
import { Button, Icon } from '@chakra-ui/react';
import { If } from '~/components';
import { useColorMode, useColorValue } from '~/context';
import type { TColorModeToggle } from './types';
const Sun = dynamic<MeronexIcon>(() => import('@meronex/icons/hi').then(i => i.HiSun));
const Moon = dynamic<MeronexIcon>(() => import('@meronex/icons/hi').then(i => i.HiMoon));
const outlineColor = { dark: 'primary.300', light: 'primary.600' };
export const ColorModeToggle = forwardRef<HTMLButtonElement, TColorModeToggle>((props, ref) => {
const { size = '1.5rem', ...rest } = props;
const { colorMode, toggleColorMode } = useColorMode();
const label = useColorValue('Switch to dark mode', 'Switch to light mode');
return (
<Button
ref={ref}
aria-label={label}
title={label}
onClick={toggleColorMode}
variant="ghost"
borderWidth="1px"
borderColor="transparent"
_hover={{
backgroundColor: 'unset',
borderColor: outlineColor[colorMode],
}}
color="currentColor"
px={4}
{...rest}>
<If c={colorMode === 'light'}>
<Icon as={Moon} boxSize={size} />
</If>
<If c={colorMode === 'dark'}>
<Icon as={Sun} boxSize={size} />
</If>
</Button>
);
});

View File

@@ -0,0 +1,5 @@
export * from './colorMode';
export * from './copy';
export * from './requery';
export * from './reset';
export * from './submit';

View File

@@ -0,0 +1,17 @@
import dynamic from 'next/dynamic';
import { Button, Icon, Tooltip } from '@chakra-ui/react';
import type { TRequeryButton } from './types';
const Repeat = dynamic<MeronexIcon>(() => import('@meronex/icons/fi').then(i => i.FiRepeat));
export const RequeryButton = (props: TRequeryButton) => {
const { requery, bg = 'secondary', ...rest } = props;
return (
<Tooltip hasArrow label="Reload Query" placement="top">
<Button mx={1} as="a" size="sm" zIndex="1" variantColor={bg} onClick={requery} {...rest}>
<Icon as={Repeat} boxSize="16px" />
</Button>
</Tooltip>
);
};

View File

@@ -1,5 +1,12 @@
import { BoxProps } from '@chakra-ui/react';
import type { BoxProps, ButtonProps } from '@chakra-ui/react';
export interface TCopyButton extends ButtonProps {
copyValue: string;
}
export interface TColorModeToggle extends ButtonProps {
size?: string;
}
export type TButtonSizeMap = {
xs: BoxProps;
sm: BoxProps;
@@ -15,3 +22,7 @@ export interface TSubmitButton extends BoxProps {
size: keyof TButtonSizeMap;
loadingText: string;
}
export interface TRequeryButton extends ButtonProps {
requery(): void;
}

View File

@@ -1 +0,0 @@
export * from './copyButton';

View File

@@ -1,5 +0,0 @@
import type { ButtonProps } from '@chakra-ui/react';
export interface TCopyButton extends ButtonProps {
copyValue: string;
}

View File

@@ -1,55 +1,48 @@
import * as React from 'react';
import {
Button,
Tag,
Modal,
Stack,
Button,
useTheme,
ModalBody,
ModalHeader,
ModalOverlay,
ModalContent,
ModalHeader,
ModalBody,
ModalCloseButton,
Stack,
Tag,
useDisclosure,
useColorMode,
useTheme,
} from '@chakra-ui/core';
import { useConfig, useMedia } from 'app/context';
import { CodeBlock } from 'app/components';
const prettyMediaSize = {
sm: 'SMALL',
md: 'MEDIUM',
lg: 'LARGE',
xl: 'X-LARGE',
};
useDisclosure,
ModalCloseButton,
} from '@chakra-ui/react';
import { useConfig, useColorValue, useBreakpointValue } from '~/context';
import { CodeBlock } from '~/components';
export const Debugger = () => {
const { isOpen: configOpen, onOpen: onConfigOpen, onClose: configClose } = useDisclosure();
const { isOpen: themeOpen, onOpen: onThemeOpen, onClose: themeClose } = useDisclosure();
const { colorMode } = useColorMode();
const config = useConfig();
const theme = useTheme();
const bg = { light: 'white', dark: 'black' };
const color = { light: 'black', dark: 'white' };
const { colorMode } = useColorMode();
const { mediaSize } = useMedia();
const borderColor = { light: 'gray.100', dark: 'gray.600' };
const bg = useColorValue('white', 'black');
const color = useColorValue('black', 'white');
const borderColor = useColorValue('gray.100', 'gray.600');
const mediaSize =
useBreakpointValue({ base: 'SMALL', md: 'MEDIUM', lg: 'LARGE', xl: 'X-LARGE' }) ?? 'UNKNOWN';
return (
<>
<Stack
borderWidth="1px"
borderColor={borderColor[colorMode]}
py={4}
px={4}
isInline
position="relative"
left={0}
right={0}
bottom={0}
justifyContent="center"
maxW="100%"
zIndex={1000}
maxW="100%">
borderWidth="1px"
position="relative"
justifyContent="center"
borderColor={borderColor}>
<Tag variantColor="gray">{colorMode.toUpperCase()}</Tag>
<Tag variantColor="teal">{prettyMediaSize[mediaSize]}</Tag>
<Tag variantColor="teal">{mediaSize}</Tag>
<Button size="sm" variantColor="cyan" onClick={onConfigOpen}>
View Config
</Button>
@@ -59,12 +52,7 @@ export const Debugger = () => {
</Stack>
<Modal isOpen={configOpen} onClose={configClose} size="full">
<ModalOverlay />
<ModalContent
bg={bg[colorMode]}
color={color[colorMode]}
py={4}
borderRadius="md"
maxW="90%">
<ModalContent bg={bg} color={color} py={4} borderRadius="md" maxW="90%">
<ModalHeader>Loaded Configuration</ModalHeader>
<ModalCloseButton />
<ModalBody>
@@ -74,12 +62,7 @@ export const Debugger = () => {
</Modal>
<Modal isOpen={themeOpen} onClose={themeClose} size="full">
<ModalOverlay />
<ModalContent
bg={bg[colorMode]}
color={color[colorMode]}
py={4}
borderRadius="md"
maxW="90%">
<ModalContent bg={bg} color={color} py={4} borderRadius="md" maxW="90%">
<ModalHeader>Loaded Theme</ModalHeader>
<ModalCloseButton />
<ModalBody>

View File

@@ -0,0 +1,44 @@
import { Flex, FormControl, FormLabel, FormErrorMessage } from '@chakra-ui/react';
import { If } from '~/components';
import { useColorValue } from '~/context';
import { useBooleanValue } from '~/hooks';
import { TField } from './types';
export const FormField = (props: TField) => {
const { label, name, error, hiddenLabels, labelAddOn, fieldAddOn, children, ...rest } = props;
const labelColor = useColorValue('blackAlpha.700', 'whiteAlpha.700');
const opacity = useBooleanValue(hiddenLabels, 0, undefined);
return (
<FormControl
mx={2}
d="flex"
w="100%"
maxW="100%"
flexDir="column"
my={{ base: 2, lg: 4 }}
isInvalid={typeof error !== 'undefined'}
flex={{ base: '1 0 100%', lg: '1 0 33.33%' }}
{...rest}>
<FormLabel
pl={1}
pr={0}
htmlFor={name}
display="flex"
opacity={opacity}
color={labelColor}
alignItems="center"
justifyContent="space-between">
{label}
<If c={typeof labelAddOn !== 'undefined'}>{labelAddOn}</If>
</FormLabel>
{children}
<If c={typeof fieldAddOn !== 'undefined'}>
<Flex justify="flex-end" pt={3}>
{fieldAddOn}
</Flex>
</If>
<FormErrorMessage opacity={opacity}>{error && error.message}</FormErrorMessage>
</FormControl>
);
};

View File

@@ -0,0 +1 @@
export * from './field';

View File

@@ -0,0 +1,11 @@
import type { FormControlProps } from '@chakra-ui/react';
import type { FieldError } from 'react-hook-form';
export interface TField extends FormControlProps {
name: string;
label: string;
error?: FieldError;
hiddenLabels: boolean;
labelAddOn?: React.ReactNode;
fieldAddOn?: React.ReactNode;
}

View File

@@ -0,0 +1,62 @@
import {
Modal,
Button,
ModalBody,
ModalHeader,
ModalFooter,
ModalOverlay,
ModalContent,
useDisclosure,
ModalCloseButton,
} from '@chakra-ui/react';
import { If, Markdown } from '~/components';
import { useConfig, useColorValue } from '~/context';
import type { TGreeting } from './types';
export const Greeting = (props: TGreeting) => {
const { onClickThrough, ...rest } = props;
const { web, content } = useConfig();
const { isOpen, onClose } = useDisclosure();
const bg = useColorValue('white', 'black');
const color = useColorValue('black', 'white');
function handleClick(): void {
onClickThrough();
onClose();
return;
}
return (
<Modal
isCentered
size="full"
isOpen={isOpen}
onClose={handleClick}
closeOnEsc={!web.greeting.required}
closeOnOverlayClick={!web.greeting.required}>
<ModalOverlay />
<ModalContent
py={4}
bg={bg}
color={color}
borderRadius="md"
maxW={{ base: '95%', md: '75%' }}
{...rest}>
<ModalHeader>{web.greeting.title}</ModalHeader>
<If c={!web.greeting.required}>
<ModalCloseButton />
</If>
<ModalBody>
<Markdown content={content.greeting} />
</ModalBody>
<ModalFooter>
<Button colorScheme="primary" onClick={handleClick}>
{web.greeting.button}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
};

View File

@@ -0,0 +1 @@
export * from './greeting';

View File

@@ -0,0 +1,5 @@
import { BoxProps } from '@chakra-ui/react';
export interface TGreeting extends BoxProps {
onClickThrough(): void;
}

View File

@@ -1,35 +1,29 @@
export * from './animated';
export * from './bgpTable';
export * from './buttons';
export * from './card';
export * from './ChakraSelect';
export * from './codeBlock';
export * from './ColorModeToggle';
export * from './CommunitySelect';
export * from './copyButton';
export * from './countdown';
export * from './Debugger';
export * from './debugger';
export * from './footer';
export * from './FormField';
export * from './Greeting';
export * from './form';
export * from './greeting';
export * from './header';
export * from './HelpModal';
export * from './HyperglassForm';
export * from './label';
export * from './Layout';
export * from './layout';
export * from './loading';
export * from './LookingGlass';
export * from './markdown';
export * from './meta';
export * from './output';
export * from './QueryLocation';
export * from './QueryTarget';
export * from './QueryType';
export * from './QueryVrf';
export * from './RequeryButton';
export * from './resetButton';
export * from './ResolvedTarget';
export * from './results';
export * from './submitButton';
export * from './table';
export * from './textOutput';
export * from './Title';
export * from './util';

View File

@@ -0,0 +1,58 @@
import { useRef } from 'react';
import { Flex } from '@chakra-ui/react';
import { useConfig, useColorValue, useGlobalState } from '~/context';
import { If, Debugger, Greeting, Footer, Header } from '~/components';
import { useGreeting } from '~/hooks';
export const Layout: React.FC = props => {
const { web, developer_mode } = useConfig();
const { isSubmitting, formData } = useGlobalState();
const [greetingAck, setGreetingAck] = useGreeting();
const bg = useColorValue('white', 'black');
const color = useColorValue('black', 'white');
const containerRef = useRef<HTMLDivElement>({} as HTMLDivElement);
function resetForm(): void {
containerRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' });
isSubmitting.set(false);
formData.set({ query_location: [], query_target: '', query_type: '', query_vrf: '' });
return;
}
return (
<>
<Flex
bg={bg}
w="100%"
color={color}
minHeight="100vh"
ref={containerRef}
flexDirection="column">
<Flex px={2} flex="0 1 auto" flexDirection="column">
<Header resetForm={resetForm} />
</Flex>
<Flex
px={2}
py={0}
w="100%"
as="main"
align="center"
flex="1 1 auto"
justify="start"
flexDir="column"
textAlign="center"
{...props}
/>
<Footer />
<If c={developer_mode}>
<Debugger />
</If>
</Flex>
<If c={web.greeting.enable && !greetingAck}>
<Greeting onClickThrough={setGreetingAck} />
</If>
</>
);
};

View File

@@ -1 +1,2 @@
export * from './table';
export * from './text';

View File

@@ -1,6 +1,10 @@
import type { FlexProps, TextProps } from '@chakra-ui/react';
import type { BoxProps, FlexProps, TextProps } from '@chakra-ui/react';
import type { CellProps } from 'react-table';
export interface TTextOutput extends Omit<BoxProps, 'children'> {
children: string;
}
export interface TActive {
isActive: boolean;
}

View File

@@ -1 +0,0 @@
export * from './submitButton';

View File

@@ -1 +0,0 @@
export * from './textOutput';

View File

@@ -1,5 +0,0 @@
import type { BoxProps } from '@chakra-ui/react';
export interface TTextOutput extends Omit<BoxProps, 'children'> {
children: string;
}

View File

@@ -34,4 +34,8 @@ export const useMobile = (): boolean =>
export const useColorToken = (light: string, dark: string): ValueOf<ITheme['colors']> =>
useColorModeValue(useToken('colors', light), useToken('colors', dark));
export { useColorModeValue as useColorValue, useBreakpointValue } from '@chakra-ui/react';
export {
useColorMode,
useBreakpointValue,
useColorModeValue as useColorValue,
} from '@chakra-ui/react';

View File

@@ -1,5 +1,6 @@
export * from './useStrf';
export * from './useBooleanValue';
export * from './useGreeting';
export * from './useOpposingColor';
export * from './useTableToString';
export * from './useSessionStorage';
export * from './useStrf';
export * from './useTableToString';

View File

@@ -6,3 +6,5 @@ export interface TOpposingOptions {
export interface TStringTableData extends Omit<TQueryResponse, 'output'> {
output: TStructuredResponse;
}
export type TUseGreetingReturn = [boolean, () => void];

View File

@@ -0,0 +1,18 @@
import { useState } from '@hookstate/core';
import { Persistence } from '@hookstate/persistence';
import type { TUseGreetingReturn } from './types';
export function useGreeting(): TUseGreetingReturn {
const state = useState<boolean>(false);
state.attach(Persistence('plugin-persisted-data-key'));
function setAck(): void {
if (!state.get()) {
state.set(true);
}
return;
}
return [state.value, setAck];
}

View File

@@ -19,6 +19,7 @@
"@emotion/react": "^11.1.1",
"@emotion/styled": "^11.0.0",
"@hookstate/core": "^3.0.1",
"@hookstate/persistence": "^3.0.0",
"@meronex/icons": "^4.0.0",
"add": "^2.0.6",
"axios": "^0.19.2",

View File

@@ -42,11 +42,18 @@ export interface IConfigWebText {
rpki_unverified: string;
}
export interface TConfigGreeting {
enable: boolean;
title: string;
button: string;
required: boolean;
}
export interface IConfigWeb {
credit: { enable: boolean };
dns_provider: { name: string; url: string };
external_link: { enable: boolean; title: string; url: string };
greeting: { enable: boolean; title: string; button: string; required: boolean };
greeting: TConfigGreeting;
help_menu: { enable: boolean; title: string };
logo: { width: string; height: string | null; light_format: string; dark_format: string };
terms: { enable: boolean; title: string };

View File

@@ -1790,6 +1790,11 @@
resolved "https://registry.yarnpkg.com/@hookstate/core/-/core-3.0.1.tgz#dc46ea71e3bf0ab5c2dc024029c9210ed12fbb84"
integrity sha512-buRie83l3FYPLCuaBE68puE3XS19r2O+jwC/kH2ikIW7ww8AavndR3MspzMMkNpq2zL8pZtIcpiWJBbn4Uq2Vw==
"@hookstate/persistence@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@hookstate/persistence/-/persistence-3.0.0.tgz#973b30d3a3bb1b29f4f59b1afe0d914e71a23882"
integrity sha512-xiN22IW0Wjw/uTV1OEUpTtqB8DAJyRobYR3+iv1TyMf72o98KpaZqQrLPvXkfrjlZac5s052BypjpkttX/Cmhw==
"@meronex/icons@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@meronex/icons/-/icons-4.0.0.tgz#26e089a8a4ec176a5b6778fd54fcdd25b4746c67"