implement react-if

This commit is contained in:
thatmattlove 2021-12-17 21:44:35 -07:00
parent c8663d7029
commit 196fb43ea7
18 changed files with 189 additions and 149 deletions

View file

@ -1,6 +1,6 @@
import { chakra, Text } from '@chakra-ui/react';
import ReactCountdown, { zeroPad } from 'react-countdown';
import { If } from '~/components';
import { If, Then, Else } from 'react-if';
import { useColorValue } from '~/context';
import type { TCountdown, TRenderer } from './types';
@ -12,19 +12,19 @@ const Renderer = (props: TRenderer): JSX.Element => {
hours !== 0 && time.unshift(zeroPad(hours));
const bg = useColorValue('black', 'white');
return (
<>
<If c={completed}>
<If condition={completed}>
<Then>
<Text fontSize="xs" />
</If>
<If c={!completed}>
</Then>
<Else>
<Text fontSize="xs" color="gray.500">
{text}
<chakra.span fontSize="xs" color={bg}>
{time.join(':')}
</chakra.span>
</Text>
</If>
</>
</Else>
</If>
);
};

View file

@ -1,6 +1,7 @@
import { forwardRef } from 'react';
import { Button, Tooltip } from '@chakra-ui/react';
import { DynamicIcon, If } from '~/components';
import { Switch, Case } from 'react-if';
import { DynamicIcon } from '~/components';
import { useColorMode, useColorValue, useBreakpointValue } from '~/context';
import { useOpposingColor } from '~/hooks';
@ -29,12 +30,14 @@ export const ColorModeToggle = forwardRef<HTMLButtonElement, TColorModeToggle>(
onClick={toggleColorMode}
{...rest}
>
<If c={colorMode === 'light'}>
<DynamicIcon icon={{ hi: 'HiMoon' }} boxSize={size} />
</If>
<If c={colorMode === 'dark'}>
<DynamicIcon icon={{ hi: 'HiSun' }} boxSize={size} />
</If>
<Switch>
<Case condition={colorMode === 'light'}>
<DynamicIcon icon={{ hi: 'HiMoon' }} boxSize={size} />
</Case>
<Case condition={colorMode === 'dark'}>
<DynamicIcon icon={{ hi: 'HiSun' }} boxSize={size} />
</Case>
</Switch>
</Button>
</Tooltip>
);

View file

@ -1,6 +1,7 @@
import { useMemo } from 'react';
import { Flex, HStack, useToken } from '@chakra-ui/react';
import { DynamicIcon, If } from '~/components';
import { If, Then } from 'react-if';
import { DynamicIcon } from '~/components';
import { useConfig, useMobile, useColorValue, useBreakpointValue } from '~/context';
import { useStrf } from '~/hooks';
import { FooterButton } from './button';
@ -82,13 +83,15 @@ export const Footer = (): JSX.Element => {
);
}
})}
<If c={web.credit.enable}>
<FooterButton
key="credit"
side="right"
content={content.credit}
title={<DynamicIcon icon={{ fi: 'FiCode' }} boxSize={size} />}
/>
<If condition={web.credit.enable}>
<Then>
<FooterButton
key="credit"
side="right"
content={content.credit}
title={<DynamicIcon icon={{ fi: 'FiCode' }} boxSize={size} />}
/>
</Then>
</If>
<ColorModeToggle size={size} />
</HStack>

View file

@ -1,7 +1,7 @@
import { useMemo } from 'react';
import { Flex, FormControl, FormLabel, FormErrorMessage } from '@chakra-ui/react';
import { useFormContext } from 'react-hook-form';
import { If } from '~/components';
import { If, Then } from 'react-if';
import { useColorValue } from '~/context';
import { useBooleanValue } from '~/hooks';
@ -33,8 +33,8 @@ export const FormField = (props: TField): JSX.Element => {
w="100%"
maxW="100%"
flexDir="column"
isInvalid={error !== null}
my={{ base: 2, lg: 4 }}
isInvalid={error !== null}
{...rest}
>
<FormLabel
@ -43,19 +43,23 @@ export const FormField = (props: TField): JSX.Element => {
htmlFor={name}
display="flex"
opacity={opacity}
fontWeight="bold"
alignItems="center"
justifyContent="space-between"
fontWeight="bold"
color={error !== null ? errorColor : labelColor}
>
{label}
<If c={typeof labelAddOn !== 'undefined'}>{labelAddOn}</If>
<If condition={typeof labelAddOn !== 'undefined'}>
<Then>{labelAddOn}</Then>
</If>
</FormLabel>
{children}
<If c={typeof fieldAddOn !== 'undefined'}>
<Flex justify="flex-end" pt={3}>
{fieldAddOn}
</Flex>
<If condition={typeof fieldAddOn !== 'undefined'}>
<Then>
<Flex justify="flex-end" pt={3}>
{fieldAddOn}
</Flex>
</Then>
</If>
<FormErrorMessage opacity={opacity}>{error?.message}</FormErrorMessage>
</FormControl>

View file

@ -1,7 +1,8 @@
import { useMemo } from 'react';
import { Input, InputGroup, InputRightElement, Text } from '@chakra-ui/react';
import { components } from 'react-select';
import { If, Select } from '~/components';
import { If, Then, Else } from 'react-if';
import { Select } from '~/components';
import { isSingleValue } from '~/components/select';
import { useColorValue } from '~/context';
import { useDirective, useFormState } from '~/hooks';
@ -68,37 +69,39 @@ export const QueryTarget = (props: TQueryTarget): JSX.Element => {
return (
<>
<input {...register('queryTarget')} hidden readOnly value={form.queryTarget} />
<If c={directive !== null && isSelectDirective(directive)}>
<Select<OptionWithDescription, false>
name={name}
options={options}
components={{ Option }}
onChange={handleSelectChange}
/>
</If>
<If c={directive === null || !isSelectDirective(directive)}>
<InputGroup size="lg">
<Input
bg={bg}
color={color}
borderRadius="md"
borderColor={border}
value={displayTarget}
aria-label={placeholder}
placeholder={placeholder}
name="queryTargetDisplay"
onChange={handleInputChange}
_placeholder={{ color: placeholderColor }}
<If condition={directive !== null && isSelectDirective(directive)}>
<Then>
<Select<OptionWithDescription, false>
name={name}
options={options}
components={{ Option }}
onChange={handleSelectChange}
/>
<InputRightElement w="max-content" pr={2}>
<UserIP
setTarget={(target: string) => {
setTarget({ display: target });
onChange({ field: name, value: target });
}}
</Then>
<Else>
<InputGroup size="lg">
<Input
bg={bg}
color={color}
borderRadius="md"
borderColor={border}
value={displayTarget}
aria-label={placeholder}
placeholder={placeholder}
name="queryTargetDisplay"
onChange={handleInputChange}
_placeholder={{ color: placeholderColor }}
/>
</InputRightElement>
</InputGroup>
<InputRightElement w="max-content" pr={2}>
<UserIP
setTarget={(target: string) => {
setTarget({ display: target });
onChange({ field: name, value: target });
}}
/>
</InputRightElement>
</InputGroup>
</Else>
</If>
</>
);

View file

@ -9,7 +9,8 @@ import {
ModalContent,
ModalCloseButton,
} from '@chakra-ui/react';
import { If, Markdown } from '~/components';
import { If, Then } from 'react-if';
import { Markdown } from '~/components';
import { useConfig, useColorValue } from '~/context';
import { useGreeting, useOpposingColor } from '~/hooks';
@ -47,8 +48,10 @@ export const Greeting = (props: TGreeting): JSX.Element => {
{...props}
>
<ModalHeader>{web.greeting.title}</ModalHeader>
<If c={!web.greeting.required}>
<ModalCloseButton />
<If condition={!web.greeting.required}>
<Then>
<ModalCloseButton />
</Then>
</If>
<ModalBody>
<Markdown content={content.greeting} />

View file

@ -1,7 +1,7 @@
import { Flex, Button, VStack } from '@chakra-ui/react';
import { motion } from 'framer-motion';
import { isSafari } from 'react-device-detect';
import { If } from '~/components';
import { Switch, Case } from 'react-if';
import { useConfig, useMobile } from '~/context';
import { useBooleanValue, useFormState } from '~/hooks';
import { SubtitleOnly } from './subtitleOnly';
@ -141,18 +141,20 @@ export const Title = (props: TTitle): JSX.Element => {
_focus={{ boxShadow: 'none' }}
_hover={{ textDecoration: 'none' }}
>
<If c={titleMode === 'text_only'}>
<TextOnly />
</If>
<If c={titleMode === 'logo_only'}>
<LogoOnly />
</If>
<If c={titleMode === 'logo_subtitle'}>
<LogoSubtitle />
</If>
<If c={titleMode === 'all'}>
<All />
</If>
<Switch>
<Case condition={titleMode === 'text_only'}>
<TextOnly />
</Case>
<Case condition={titleMode === 'logo_only'}>
<LogoOnly />
</Case>
<Case condition={titleMode === 'logo_subtitle'}>
<LogoSubtitle />
</Case>
<Case condition={titleMode === 'all'}>
<All />
</Case>
</Switch>
</Button>
</Flex>
);

View file

@ -1,7 +1,8 @@
import { useCallback, useRef } from 'react';
import { Flex } from '@chakra-ui/react';
import { isSafari } from 'react-device-detect';
import { If, Debugger, Greeting, Footer, Header } from '~/components';
import { If, Then } from 'react-if';
import { Debugger, Greeting, Footer, Header } from '~/components';
import { useConfig } from '~/context';
import { useFormState } from '~/hooks';
import { ResetButton } from './resetButton';
@ -51,8 +52,10 @@ export const Frame = (props: TFrame): JSX.Element => {
{...props}
/>
<Footer />
<If c={developerMode}>
<Debugger />
<If condition={developerMode}>
<Then>
<Debugger />
</Then>
</If>
<ResetButton developerMode={developerMode} resetForm={handleReset} />
</Flex>

View file

@ -17,7 +17,8 @@ import {
Checkbox as ChakraCheckbox,
ListItem as ChakraListItem,
} from '@chakra-ui/react';
import { CodeBlock as CustomCodeBlock, If } from '~/components';
import { If, Then, Else } from 'react-if';
import { CodeBlock as CustomCodeBlock } from '~/components';
import { useColorValue } from '~/context';
import type {
@ -62,14 +63,14 @@ export const Checkbox = (props: TCheckbox & MDProps): JSX.Element => {
export const List = (props: TList): JSX.Element => {
const { ordered, ...rest } = props;
return (
<>
<If c={ordered}>
<If condition={ordered}>
<Then>
<OrderedList {...rest} />
</If>
<If c={!ordered}>
</Then>
<Else>
<UnorderedList {...rest} />
</If>
</>
</Else>
</If>
);
};
@ -144,14 +145,14 @@ export const TableHead = (props: TableHeadProps): JSX.Element => (
export const TableCell = (props: TTableData): JSX.Element => {
const { isHeader, ...rest } = props;
return (
<>
<If c={isHeader}>
<If condition={isHeader}>
<Then>
<Th {...clean<TableCellProps>(rest)} />
</If>
<If c={!isHeader}>
</Then>
<Else>
<Td {...clean<TableCellProps>(rest)} />
</If>
</>
</Else>
</If>
);
};

View file

@ -3,7 +3,8 @@ import { Text, Box, Tooltip, Menu, MenuButton, MenuList, Link } from '@chakra-ui
import dayjs from 'dayjs';
import relativeTimePlugin from 'dayjs/plugin/relativeTime';
import utcPlugin from 'dayjs/plugin/utc';
import { If, DynamicIcon } from '~/components';
import { If, Then, Else } from 'react-if';
import { DynamicIcon } from '~/components';
import { useConfig, useColorValue } from '~/context';
import { useOpposingColor } from '~/hooks';
@ -33,14 +34,14 @@ export const Active = (props: TActive): JSX.Element => {
const { isActive } = props;
const color = useColorValue(['gray.500', 'green.500'], ['whiteAlpha.300', 'blackAlpha.500']);
return (
<>
<If c={isActive}>
<If condition={isActive}>
<Then>
<DynamicIcon color={color[+isActive]} icon={{ fa: 'FaCheckCircle' }} />
</If>
<If c={!isActive}>
</Then>
<Else>
<DynamicIcon color={color[+isActive]} icon={{ md: 'MdCancel' }} />
</If>
</>
</Else>
</If>
);
};
@ -113,15 +114,15 @@ export const Communities = (props: TCommunities): JSX.Element => {
const bg = useColorValue('white', 'gray.900');
const color = useOpposingColor(bg);
return (
<>
<If c={communities.length === 0}>
<If condition={communities.length === 0}>
<Then>
<Tooltip placement="right" hasArrow label={web.text.noCommunities}>
<Link>
<DynamicIcon icon={{ bs: 'BsQuestionCircleFill' }} />
</Link>
</Tooltip>
</If>
<If c={communities.length !== 0}>
</Then>
<Else>
<Menu preventOverflow>
<MenuButton>
<DynamicIcon icon={{ cg: 'CgMoreO' }} />
@ -141,8 +142,8 @@ export const Communities = (props: TCommunities): JSX.Element => {
{communities.join('\n')}
</MenuList>
</Menu>
</If>
</>
</Else>
</If>
);
};

View file

@ -15,7 +15,8 @@ import {
import { motion } from 'framer-motion';
import startCase from 'lodash/startCase';
import isEqual from 'react-fast-compare';
import { BGPTable, Countdown, DynamicIcon, If, Path, TextOutput } from '~/components';
import { If, Then, Else } from 'react-if';
import { BGPTable, Countdown, DynamicIcon, Path, TextOutput } from '~/components';
import { useColorValue, useConfig, useMobile } from '~/context';
import { useStrf, useLGQuery, useTableToString, useFormState, useDevice } from '~/hooks';
import { isStructuredOutput, isStringOutput } from '~/types';
@ -254,17 +255,24 @@ const _Result: React.ForwardRefRenderFunction<HTMLDivElement, ResultProps> = (
flex="1 0 auto"
justifyContent={{ base: 'flex-start', lg: 'flex-end' }}
>
<If c={cache.showText && !isError && isCached}>
<If c={!isMobile}>
<Countdown timeout={cache.timeout} text={web.text.cachePrefix} />
</If>
<Tooltip hasArrow label={cacheLabel} placement="top">
<Box>
<DynamicIcon icon={{ bs: 'BsLightningFill' }} color={color} />
</Box>
</Tooltip>
<If c={isMobile}>
<Countdown timeout={cache.timeout} text={web.text.cachePrefix} />
<If condition={cache.showText && !isError && isCached}>
<If condition={isMobile}>
<Then>
<Countdown timeout={cache.timeout} text={web.text.cachePrefix} />
<Tooltip hasArrow label={cacheLabel} placement="top">
<Box>
<DynamicIcon icon={{ bs: 'BsLightningFill' }} color={color} />
</Box>
</Tooltip>
</Then>
<Else>
<Tooltip hasArrow label={cacheLabel} placement="top">
<Box>
<DynamicIcon icon={{ bs: 'BsLightningFill' }} color={color} />
</Box>
</Tooltip>
<Countdown timeout={cache.timeout} text={web.text.cachePrefix} />
</Else>
</If>
</If>
</HStack>

View file

@ -14,7 +14,8 @@ import {
PopoverCloseButton,
} from '@chakra-ui/react';
import { useFormContext } from 'react-hook-form';
import { DynamicIcon, If, ResolvedTarget } from '~/components';
import { If, Then, Else } from 'react-if';
import { DynamicIcon, ResolvedTarget } from '~/components';
import { useMobile, useColorValue } from '~/context';
import { useFormState } from '~/hooks';
@ -113,17 +114,17 @@ export const SubmitButton = (props: SubmitButtonProps): JSX.Element => {
}
return (
<>
<If c={isMobile}>
<If condition={isMobile}>
<Then>
<MSubmitButton isOpen={resolvedIsOpen} onClose={handleClose}>
<SubmitIcon isLoading={loading} {...props} />
</MSubmitButton>
</If>
<If c={!isMobile}>
</Then>
<Else>
<DSubmitButton isOpen={resolvedIsOpen} onClose={handleClose}>
<SubmitIcon isLoading={loading} {...props} />
</DSubmitButton>
</If>
</>
</Else>
</If>
);
};

View file

@ -2,8 +2,9 @@
/* eslint react/jsx-key: 0 */
import { Flex, Text } from '@chakra-ui/react';
import { usePagination, useSortBy, useTable } from 'react-table';
import { If, Then, Else } from 'react-if';
import { useMobile } from '~/context';
import { CardBody, CardFooter, CardHeader, DynamicIcon, If } from '~/components';
import { CardBody, CardFooter, CardHeader, DynamicIcon } from '~/components';
import { TableMain } from './table';
import { TableCell } from './cell';
import { TableHead } from './head';
@ -89,15 +90,19 @@ export const Table = (props: TTable): JSX.Element => {
<Text fontSize="sm" fontWeight="bold" display="inline-block">
{column.render('Header')}
</Text>
<If c={column.isSorted}>
<If c={typeof column.isSortedDesc !== 'undefined'}>
<DynamicIcon icon={{ fa: 'FaChevronDown' }} boxSize={4} ml={1} />
</If>
<If c={!column.isSortedDesc}>
<DynamicIcon icon={{ fa: 'FaChevronRight' }} boxSize={4} ml={1} />
</If>
<If condition={column.isSorted}>
<Then>
<If condition={column.isSortedDesc}>
<Then>
<DynamicIcon icon={{ fa: 'FaChevronDown' }} boxSize={4} ml={1} />
</Then>
<Else>
<DynamicIcon icon={{ fa: 'FaChevronRight' }} boxSize={4} ml={1} />
</Else>
</If>
</Then>
<Else>{''}</Else>
</If>
<If c={!column.isSorted}>{''}</If>
</TableCell>
))}
</TableRow>

View file

@ -1,6 +0,0 @@
import type { TIf } from './types';
export const If: React.FC<TIf> = (props: TIf) => {
const { c, children } = props;
return c ? <>{children}</> : null;
};

View file

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

View file

@ -39,6 +39,7 @@
"react-ga": "^3.3.0",
"react-hook-form": "^7.21.0",
"react-icons": "^4.3.1",
"react-if": "^4.1.1",
"react-markdown": "^5.0.3",
"react-query": "^3.16.0",
"react-select": "^5.2.1",

View file

@ -1,5 +1,6 @@
import dynamic from 'next/dynamic';
import { Meta, Loading, If, LoadError } from '~/components';
import { Switch, Case, Default } from 'react-if';
import { Meta, Loading, LoadError } from '~/components';
import { HyperglassProvider } from '~/context';
import { useHyperglassConfig } from '~/hooks';
@ -14,20 +15,23 @@ const Index: NextPage = () => {
useHyperglassConfig();
return (
<>
<If c={isLoadingInitial}>
<Switch>
<Case condition={isLoadingInitial}>
<Loading />
</If>
<If c={showError}>
</Case>
<Case condition={showError}>
<LoadError error={error!} retry={refetch} inProgress={isLoading} />
</If>
<If c={ready}>
</Case>
<Case condition={ready}>
<HyperglassProvider config={data!}>
<Meta />
<Layout />
</HyperglassProvider>
</If>
</>
</Case>
<Default>
<LoadError error={error!} retry={refetch} inProgress={isLoading} />
</Default>
</Switch>
);
};

View file

@ -6961,6 +6961,11 @@ react-icons@^4.3.1:
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.3.1.tgz#2fa92aebbbc71f43d2db2ed1aed07361124e91ca"
integrity sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==
react-if@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/react-if/-/react-if-4.1.1.tgz#48404d7e7f9ce18ee26b5d80baa6e26883bfb128"
integrity sha512-frzHswesRqVVJ2XcGRoLyTvlB2yneib4R/FCqTG8AqBQnFdLNhqNODfzEA84EQZ0XwBAVe82Oe567kxaVmwj5w==
react-is@17.0.2, "react-is@^16.12.0 || ^17.0.0", react-is@^17.0.1, react-is@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"