forked from mirrors/thatmattlove-hyperglass
refactor and restructure ui components
This commit is contained in:
parent
9a04ef1dfc
commit
227da64c9a
53 changed files with 200 additions and 136 deletions
|
|
@ -13,7 +13,7 @@ import {
|
|||
ModalCloseButton,
|
||||
} from '@chakra-ui/react';
|
||||
import { useConfig, useColorValue, useBreakpointValue } from '~/context';
|
||||
import { CodeBlock, DynamicIcon } from '~/components';
|
||||
import { CodeBlock, DynamicIcon } from '~/elements';
|
||||
import { useHyperglassConfig } from '~/hooks';
|
||||
|
||||
import type { UseDisclosureReturn } from '@chakra-ui/react';
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ import {
|
|||
useDisclosure,
|
||||
ModalCloseButton,
|
||||
} from '@chakra-ui/react';
|
||||
import { DynamicIcon, Markdown } from '~/components';
|
||||
import { useColorValue } from '~/context';
|
||||
import { DynamicIcon, Markdown } from '~/elements';
|
||||
|
||||
import type { ModalContentProps } from '@chakra-ui/react';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useMemo } from 'react';
|
||||
import { Button, Menu, MenuButton, MenuList } from '@chakra-ui/react';
|
||||
import { Markdown } from '~/components';
|
||||
import { useColorValue, useBreakpointValue, useConfig } from '~/context';
|
||||
import { Markdown } from '~/elements';
|
||||
import { useOpposingColor, useStrf } from '~/hooks';
|
||||
|
||||
import type { MenuListProps } from '@chakra-ui/react';
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { forwardRef } from 'react';
|
||||
import { Button, Tooltip } from '@chakra-ui/react';
|
||||
import { Switch, Case } from 'react-if';
|
||||
import { DynamicIcon } from '~/components';
|
||||
import { useColorMode, useColorValue, useBreakpointValue } from '~/context';
|
||||
import { DynamicIcon } from '~/elements';
|
||||
import { useOpposingColor } from '~/hooks';
|
||||
|
||||
import type { ButtonProps } from '@chakra-ui/react';
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { useMemo } from 'react';
|
||||
import { Flex, HStack, useToken } from '@chakra-ui/react';
|
||||
import { If, Then } from 'react-if';
|
||||
import { DynamicIcon } from '~/components';
|
||||
import { useConfig, useMobile, useColorValue, useBreakpointValue } from '~/context';
|
||||
import { DynamicIcon } from '~/elements';
|
||||
import { useStrf } from '~/hooks';
|
||||
import { FooterButton } from './button';
|
||||
import { ColorModeToggle } from './color-mode';
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {
|
|||
ModalCloseButton,
|
||||
} from '@chakra-ui/react';
|
||||
import { If, Then } from 'react-if';
|
||||
import { Markdown } from '~/components';
|
||||
import { Markdown } from '~/elements';
|
||||
import { useConfig, useColorValue } from '~/context';
|
||||
import { useGreeting, useOpposingColor } from '~/hooks';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Flex, ScaleFade } from '@chakra-ui/react';
|
||||
import { motionChakra } from '~/components';
|
||||
import { useBreakpointValue } from '~/context';
|
||||
import { motionChakra } from '~/elements';
|
||||
import { useBooleanValue, useFormInteractive } from '~/hooks';
|
||||
import { Title } from './title';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,24 +1,19 @@
|
|||
export * from './animated';
|
||||
export * from './card';
|
||||
export * from './code-block';
|
||||
export * from './countdown';
|
||||
export * from './custom';
|
||||
/**
|
||||
* The components directory contains React components that handle logic.
|
||||
*
|
||||
* Generally, components that call hooks or reference configuration, or API types should be in
|
||||
* components.
|
||||
*/
|
||||
|
||||
export * from './debugger';
|
||||
export * from './directive-info-modal';
|
||||
export * from './dynamic-icon';
|
||||
export * from './favicon';
|
||||
export * from './footer';
|
||||
export * from './form-field';
|
||||
export * from './form-row';
|
||||
export * from './greeting';
|
||||
export * from './header';
|
||||
export * from './label';
|
||||
export * from './layout';
|
||||
export * from './load-error';
|
||||
export * from './loading';
|
||||
export * from './location-card';
|
||||
export * from './looking-glass-form';
|
||||
export * from './markdown';
|
||||
export * from './meta';
|
||||
export * from './output';
|
||||
export * from './path';
|
||||
|
|
@ -26,6 +21,7 @@ export * from './prompt';
|
|||
export * from './query-location';
|
||||
export * from './query-target';
|
||||
export * from './query-type';
|
||||
export * from './reset-button';
|
||||
export * from './resolved-target';
|
||||
export * from './results';
|
||||
export * from './select';
|
||||
|
|
|
|||
|
|
@ -1,18 +1,29 @@
|
|||
import { useCallback, useRef } from 'react';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { isSafari } from 'react-device-detect';
|
||||
import { If, Then } from 'react-if';
|
||||
import { Debugger, Greeting, Footer, Header } from '~/components';
|
||||
import { Debugger, Greeting, Footer, Header, ResetButton } from '~/components';
|
||||
import { useConfig } from '~/context';
|
||||
import { motionChakra } from '~/elements';
|
||||
import { useFormState } from '~/hooks';
|
||||
import { ResetButton } from './reset-button';
|
||||
|
||||
import type { FlexProps } from '@chakra-ui/react';
|
||||
|
||||
const AnimatedFlex = motion(Flex);
|
||||
const Main = motionChakra('main', {
|
||||
baseStyle: {
|
||||
px: 4,
|
||||
py: 0,
|
||||
w: '100%',
|
||||
display: 'flex',
|
||||
flex: '1 1 auto',
|
||||
flexDir: 'column',
|
||||
textAlign: 'center',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'start',
|
||||
},
|
||||
});
|
||||
|
||||
export const Frame = (props: FlexProps): JSX.Element => {
|
||||
export const Layout = (props: FlexProps): JSX.Element => {
|
||||
const { developerMode } = useConfig();
|
||||
const { setStatus, reset } = useFormState(
|
||||
useCallback(({ setStatus, reset }) => ({ setStatus, reset }), []),
|
||||
|
|
@ -42,24 +53,15 @@ export const Frame = (props: FlexProps): JSX.Element => {
|
|||
minHeight={isSafari ? '-webkit-fill-available' : '100vh'}
|
||||
>
|
||||
<Header />
|
||||
<AnimatedFlex
|
||||
<Main
|
||||
layout
|
||||
px={4}
|
||||
py={0}
|
||||
w="100%"
|
||||
as="main"
|
||||
flex="1 1 auto"
|
||||
flexDir="column"
|
||||
textAlign="center"
|
||||
alignItems="center"
|
||||
justifyContent="start"
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
exit={{ opacity: 0, x: -300 }}
|
||||
initial={{ opacity: 0, y: 300 }}
|
||||
>
|
||||
{props.children}
|
||||
</AnimatedFlex>
|
||||
</Main>
|
||||
<Footer />
|
||||
<If condition={developerMode}>
|
||||
<Then>
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
export * from './frame';
|
||||
export * from './layout';
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
import { AnimatePresence } from 'framer-motion';
|
||||
import { LookingGlassForm, Results } from '~/components';
|
||||
import { useView } from '~/hooks';
|
||||
import { Frame } from './frame';
|
||||
|
||||
export const Layout = (): JSX.Element => {
|
||||
const view = useView();
|
||||
return (
|
||||
<Frame>
|
||||
{view === 'results' ? (
|
||||
<Results />
|
||||
) : (
|
||||
<AnimatePresence>
|
||||
<LookingGlassForm />
|
||||
</AnimatePresence>
|
||||
)}
|
||||
</Frame>
|
||||
);
|
||||
};
|
||||
|
|
@ -5,7 +5,6 @@ import { FormProvider, useForm } from 'react-hook-form';
|
|||
import { vestResolver } from '@hookform/resolvers/vest';
|
||||
import vest, { test, enforce } from 'vest';
|
||||
import {
|
||||
FormRow,
|
||||
FormField,
|
||||
DirectiveInfoModal,
|
||||
QueryType,
|
||||
|
|
@ -14,6 +13,7 @@ import {
|
|||
QueryLocation,
|
||||
} from '~/components';
|
||||
import { useConfig } from '~/context';
|
||||
import { FormRow } from '~/elements';
|
||||
import { useStrf, useGreeting, useDevice, useFormState } from '~/hooks';
|
||||
import { isString, isQueryField, Directive } from '~/types';
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import dayjs from 'dayjs';
|
|||
import relativeTimePlugin from 'dayjs/plugin/relativeTime';
|
||||
import utcPlugin from 'dayjs/plugin/utc';
|
||||
import { If, Then, Else } from 'react-if';
|
||||
import { DynamicIcon } from '~/components';
|
||||
import { useConfig, useColorValue } from '~/context';
|
||||
import { DynamicIcon } from '~/elements';
|
||||
import { useOpposingColor } from '~/hooks';
|
||||
|
||||
import type { TextProps } from '@chakra-ui/react';
|
||||
|
|
|
|||
|
|
@ -45,13 +45,7 @@ const _Highlighted = (props: HighlightedProps): JSX.Element => {
|
|||
times++;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{result.map(r => (
|
||||
<>{r}</>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
return <>{result}</>;
|
||||
};
|
||||
|
||||
export const Highlighted = memo(_Highlighted, isEqual);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { ButtonGroup, IconButton } from '@chakra-ui/react';
|
||||
import { useZoomPanHelper } from 'react-flow-renderer';
|
||||
import { DynamicIcon } from '~/components';
|
||||
import { DynamicIcon } from '~/elements';
|
||||
|
||||
export const Controls = (): JSX.Element => {
|
||||
const { fitView, zoomIn, zoomOut } = useZoomPanHelper();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Button, Tooltip } from '@chakra-ui/react';
|
||||
import { DynamicIcon } from '~/components';
|
||||
import { DynamicIcon } from '~/elements';
|
||||
|
||||
interface PathButtonProps {
|
||||
onOpen(): void;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Flex, IconButton } from '@chakra-ui/react';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import { AnimatedDiv, DynamicIcon } from '~/components';
|
||||
import { useColorValue } from '~/context';
|
||||
import { AnimatedDiv, DynamicIcon } from '~/elements';
|
||||
import { useOpposingColor, useFormState } from '~/hooks';
|
||||
|
||||
import type { FlexProps } from '@chakra-ui/react';
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { useMemo } from 'react';
|
||||
import { Button, Stack, Text, VStack } from '@chakra-ui/react';
|
||||
import { DynamicIcon } from '~/components';
|
||||
import { useConfig, useColorValue } from '~/context';
|
||||
import { DynamicIcon } from '~/elements';
|
||||
import { useStrf, useDNSQuery, useFormState } from '~/hooks';
|
||||
|
||||
import type { DnsOverHttps } from '~/types';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Button, Tooltip, useClipboard } from '@chakra-ui/react';
|
||||
import { DynamicIcon } from '~/components';
|
||||
import { DynamicIcon } from '~/elements';
|
||||
|
||||
import type { ButtonProps } from '@chakra-ui/react';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useEffect } from 'react';
|
||||
import { Accordion } from '@chakra-ui/react';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import { AnimatedDiv } from '~/components';
|
||||
import { AnimatedDiv } from '~/elements';
|
||||
import { useFormState } from '~/hooks';
|
||||
import { Result } from './individual';
|
||||
import { Tags } from './tags';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useMemo } from 'react';
|
||||
import { AccordionIcon, Box, Spinner, HStack, Text, Tooltip } from '@chakra-ui/react';
|
||||
import { DynamicIcon } from '~/components';
|
||||
import { useConfig, useColorValue } from '~/context';
|
||||
import { DynamicIcon } from '~/elements';
|
||||
import { useOpposingColor, useStrf } from '~/hooks';
|
||||
|
||||
import type { ErrorLevels } from '~/types';
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ import { motion } from 'framer-motion';
|
|||
import startCase from 'lodash/startCase';
|
||||
import isEqual from 'react-fast-compare';
|
||||
import { If, Then, Else } from 'react-if';
|
||||
import { BGPTable, Countdown, DynamicIcon, Path, TextOutput } from '~/components';
|
||||
import { BGPTable, Path, TextOutput } from '~/components';
|
||||
import { useColorValue, useConfig, useMobile } from '~/context';
|
||||
import { Countdown, DynamicIcon } from '~/elements';
|
||||
import { useStrf, useLGQuery, useTableToString, useFormState, useDevice } from '~/hooks';
|
||||
import { isStructuredOutput, isStringOutput } from '~/types';
|
||||
import { isStackError, isFetchError, isLGError, isLGOutputOrError } from './guards';
|
||||
|
|
@ -227,8 +228,8 @@ const _Result: React.ForwardRefRenderFunction<HTMLDivElement, ResultProps> = (
|
|||
>
|
||||
<Box>
|
||||
<Flex direction="column" flex="1 0 auto" maxW={error ? '100%' : undefined}>
|
||||
{!isError && typeof data !== 'undefined' ? (
|
||||
<>
|
||||
<If condition={!isError && typeof data !== 'undefined'}>
|
||||
<Then>
|
||||
{isStructuredOutput(data) && data.level === 'success' && tableComponent ? (
|
||||
<BGPTable>{data.output}</BGPTable>
|
||||
) : isStringOutput(data) && data.level === 'success' && !tableComponent ? (
|
||||
|
|
@ -242,12 +243,13 @@ const _Result: React.ForwardRefRenderFunction<HTMLDivElement, ResultProps> = (
|
|||
<FormattedError message={errorMsg} keywords={errorKeywords} />
|
||||
</Alert>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<Alert rounded="lg" my={2} py={4} status={errorLevel} variant="solid">
|
||||
<FormattedError message={errorMsg} keywords={errorKeywords} />
|
||||
</Alert>
|
||||
)}
|
||||
</Then>
|
||||
<Else>
|
||||
<Alert rounded="lg" my={2} py={4} status={errorLevel} variant="solid">
|
||||
<FormattedError message={errorMsg} keywords={errorKeywords} />
|
||||
</Alert>
|
||||
</Else>
|
||||
</If>
|
||||
</Flex>
|
||||
</Box>
|
||||
|
||||
|
|
@ -260,24 +262,26 @@ const _Result: React.ForwardRefRenderFunction<HTMLDivElement, ResultProps> = (
|
|||
justifyContent={{ base: 'flex-start', lg: 'flex-end' }}
|
||||
>
|
||||
<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>
|
||||
<Then>
|
||||
<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>
|
||||
</Then>
|
||||
</If>
|
||||
</HStack>
|
||||
</Flex>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { forwardRef } from 'react';
|
||||
import { Button, Tooltip } from '@chakra-ui/react';
|
||||
import { DynamicIcon } from '~/components';
|
||||
import { DynamicIcon } from '~/elements';
|
||||
|
||||
import type { ButtonProps } from '@chakra-ui/react';
|
||||
import type { UseQueryResult } from 'react-query';
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { useMemo } from 'react';
|
||||
import { Box, Stack, useToken } from '@chakra-ui/react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { Label } from '~/components';
|
||||
import { useConfig, useBreakpointValue } from '~/context';
|
||||
import { Label } from '~/elements';
|
||||
import { useFormState } from '~/hooks';
|
||||
|
||||
import type { Transition } from 'framer-motion';
|
||||
|
|
|
|||
|
|
@ -15,8 +15,9 @@ import {
|
|||
} from '@chakra-ui/react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import { If, Then, Else } from 'react-if';
|
||||
import { DynamicIcon, ResolvedTarget } from '~/components';
|
||||
import { ResolvedTarget } from '~/components';
|
||||
import { useMobile, useColorValue } from '~/context';
|
||||
import { DynamicIcon } from '~/elements';
|
||||
import { useFormState } from '~/hooks';
|
||||
|
||||
import type { IconButtonProps } from '@chakra-ui/react';
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ 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 } from '~/components';
|
||||
import { CardBody, CardFooter, CardHeader, DynamicIcon } from '~/elements';
|
||||
import { TableMain } from './table';
|
||||
import { TableCell } from './cell';
|
||||
import { TableHead } from './head';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { useMemo } from 'react';
|
||||
import { Button, Stack, Text, VStack, useDisclosure } from '@chakra-ui/react';
|
||||
import { DynamicIcon, Prompt } from '~/components';
|
||||
import { Prompt } from '~/components';
|
||||
import { useConfig, useColorValue } from '~/context';
|
||||
import { DynamicIcon } from '~/elements';
|
||||
import { useStrf, useWtf } from '~/hooks';
|
||||
|
||||
interface UserIPProps {
|
||||
|
|
|
|||
21
hyperglass/ui/elements/index.ts
Normal file
21
hyperglass/ui/elements/index.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* The elements directory contains React components that are stateless and contain no logic or
|
||||
* references to configuration.
|
||||
*
|
||||
* Generally, elements should not call non-theme-related hooks, rely on context, or reference
|
||||
* configuration/API types.
|
||||
*/
|
||||
|
||||
export * from './animated';
|
||||
export * from './card';
|
||||
export * from './code-block';
|
||||
export * from './countdown';
|
||||
export * from './custom';
|
||||
export * from './dynamic-icon';
|
||||
export * from './favicon';
|
||||
export * from './form-row';
|
||||
export * from './label';
|
||||
export * from './load-error';
|
||||
export * from './loading';
|
||||
export * from './markdown';
|
||||
export * from './no-config';
|
||||
|
|
@ -7,7 +7,7 @@ import {
|
|||
AlertTitle,
|
||||
AlertDescription,
|
||||
} from '@chakra-ui/react';
|
||||
import { NoConfig } from './no-config';
|
||||
import { NoConfig } from '~/elements';
|
||||
|
||||
import type { CenterProps } from '@chakra-ui/react';
|
||||
import type { ConfigLoadError } from '~/util';
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { Spinner } from '@chakra-ui/react';
|
||||
import { NoConfig } from './no-config';
|
||||
import { NoConfig } from '~/elements';
|
||||
|
||||
export const Loading = (): JSX.Element => {
|
||||
return (
|
||||
|
|
@ -18,7 +18,7 @@ import {
|
|||
ListItem as ChakraListItem,
|
||||
} from '@chakra-ui/react';
|
||||
import { If, Then, Else } from 'react-if';
|
||||
import { CodeBlock as CustomCodeBlock } from '~/components';
|
||||
import { CodeBlock as CustomCodeBlock } from '~/elements';
|
||||
import { useColorValue } from '~/context';
|
||||
|
||||
import type {
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
export * from './theme-hooks';
|
||||
export * from './useASNDetail';
|
||||
export * from './useBooleanValue';
|
||||
export * from './useDevice';
|
||||
|
|
|
|||
34
hyperglass/ui/hooks/theme-hooks.ts
Normal file
34
hyperglass/ui/hooks/theme-hooks.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import {
|
||||
useBreakpointValue,
|
||||
useTheme as useChakraTheme,
|
||||
useColorModeValue,
|
||||
useToken,
|
||||
} from '@chakra-ui/react';
|
||||
import type { Theme } from '~/types';
|
||||
|
||||
export {
|
||||
useBreakpointValue,
|
||||
useColorMode,
|
||||
useColorModeValue as useColorValue,
|
||||
useToken,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
/**
|
||||
* Determine if device is mobile or desktop based on Chakra UI theme breakpoints.
|
||||
*/
|
||||
export const useMobile = (): boolean =>
|
||||
useBreakpointValue<boolean>({ base: true, md: true, lg: false, xl: false }) ?? true;
|
||||
|
||||
/**
|
||||
* Get the current theme object.
|
||||
*/
|
||||
export const useTheme = (): Theme.Full => useChakraTheme();
|
||||
|
||||
/**
|
||||
* Convenience function to combine Chakra UI's useToken & useColorModeValue.
|
||||
*/
|
||||
export const useColorToken = <L extends string, D extends string>(
|
||||
token: keyof Theme.Full,
|
||||
light: L,
|
||||
dark: D,
|
||||
): L | D => useColorModeValue<L, D>(useToken(token, light), useToken(token, dark));
|
||||
|
|
@ -1,15 +1,45 @@
|
|||
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||
import { Switch, Case, Default } from 'react-if';
|
||||
import { Meta, Layout } from '~/components';
|
||||
import { HyperglassProvider } from '~/context';
|
||||
import { LoadError, Loading } from '~/elements';
|
||||
import { useHyperglassConfig } from '~/hooks';
|
||||
|
||||
import type { AppProps } from 'next/app';
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
const App = (props: AppProps): JSX.Element => {
|
||||
const AppComponent = (props: AppProps) => {
|
||||
const { Component, pageProps } = props;
|
||||
const { data, error, isLoading, ready, refetch, showError, isLoadingInitial } =
|
||||
useHyperglassConfig();
|
||||
return (
|
||||
<Switch>
|
||||
<Case condition={isLoadingInitial}>
|
||||
<Loading />
|
||||
</Case>
|
||||
<Case condition={showError}>
|
||||
<LoadError error={error!} retry={refetch} inProgress={isLoading} />
|
||||
</Case>
|
||||
<Case condition={ready}>
|
||||
<HyperglassProvider config={data!}>
|
||||
<Meta />
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
</HyperglassProvider>
|
||||
</Case>
|
||||
<Default>
|
||||
<LoadError error={error!} retry={refetch} inProgress={isLoading} />
|
||||
</Default>
|
||||
</Switch>
|
||||
);
|
||||
};
|
||||
|
||||
const App = (props: AppProps): JSX.Element => {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<Component {...pageProps} />
|
||||
<AppComponent {...props} />
|
||||
</QueryClientProvider>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import fs from 'fs';
|
||||
import Document, { Html, Head, Main, NextScript } from 'next/document';
|
||||
import { Favicon, CustomJavascript, CustomHtml } from '~/components';
|
||||
import { CustomJavascript, CustomHtml, Favicon } from '~/elements';
|
||||
import favicons from '../favicon-formats';
|
||||
|
||||
import type { DocumentContext, DocumentInitialProps } from 'next/document';
|
||||
|
|
|
|||
|
|
@ -1,37 +1,36 @@
|
|||
import dynamic from 'next/dynamic';
|
||||
import { Switch, Case, Default } from 'react-if';
|
||||
import { Meta, Loading, LoadError } from '~/components';
|
||||
import { HyperglassProvider } from '~/context';
|
||||
import { useHyperglassConfig } from '~/hooks';
|
||||
import { If, Then, Else } from 'react-if';
|
||||
import { Loading } from '~/elements';
|
||||
import { useView } from '~/hooks';
|
||||
|
||||
import type { NextPage } from 'next';
|
||||
import type { AnimatePresenceProps } from 'framer-motion';
|
||||
|
||||
const Layout = dynamic<Dict>(() => import('~/components').then(i => i.Layout), {
|
||||
const AnimatePresence = dynamic<AnimatePresenceProps>(() =>
|
||||
import('framer-motion').then(i => i.AnimatePresence),
|
||||
);
|
||||
|
||||
const LookingGlassForm = dynamic<Dict>(() => import('~/components').then(i => i.LookingGlassForm), {
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const Results = dynamic<Dict>(() => import('~/components').then(i => i.Results), {
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const Index: NextPage = () => {
|
||||
const { data, error, isLoading, ready, refetch, showError, isLoadingInitial } =
|
||||
useHyperglassConfig();
|
||||
|
||||
const view = useView();
|
||||
return (
|
||||
<Switch>
|
||||
<Case condition={isLoadingInitial}>
|
||||
<Loading />
|
||||
</Case>
|
||||
<Case condition={showError}>
|
||||
<LoadError error={error!} retry={refetch} inProgress={isLoading} />
|
||||
</Case>
|
||||
<Case condition={ready}>
|
||||
<HyperglassProvider config={data!}>
|
||||
<Meta />
|
||||
<Layout />
|
||||
</HyperglassProvider>
|
||||
</Case>
|
||||
<Default>
|
||||
<LoadError error={error!} retry={refetch} inProgress={isLoading} />
|
||||
</Default>
|
||||
</Switch>
|
||||
<If condition={view === 'results'}>
|
||||
<Then>
|
||||
<Results />
|
||||
</Then>
|
||||
<Else>
|
||||
<AnimatePresence>
|
||||
<LookingGlassForm />
|
||||
</AnimatePresence>
|
||||
</Else>
|
||||
</If>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
"~/components/*": ["components/*"],
|
||||
"~/context": ["context/index"],
|
||||
"~/context/*": ["context/*"],
|
||||
"~/elements": ["elements/index"],
|
||||
"~/elements/*": ["elements/*"],
|
||||
"~/hooks": ["hooks/index"],
|
||||
"~/hooks/*": ["hooks/*"],
|
||||
"~/state": ["state/index"],
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export function isStringOutput(data: unknown): data is StringQueryResponse {
|
|||
* Determine if a form field name is a valid form key name.
|
||||
*/
|
||||
export function isQueryField(field: string): field is keyof FormData {
|
||||
return ['queryLocation', 'queryType', 'queryGroup', 'queryTarget'].includes(field);
|
||||
return ['queryLocation', 'queryType', 'queryTarget'].includes(field);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue