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

continue typescript & chakra-ui 1.0 migrations

This commit is contained in:
checktheroads
2020-10-19 08:17:10 -07:00
parent 49183bd3a6
commit da1e39cfd6
19 changed files with 240 additions and 168 deletions

View File

@@ -1,26 +1,26 @@
import * as React from 'react';
import { useState } from 'react';
import { Flex, useColorMode } from '@chakra-ui/core';
import { Box, Flex } from '@chakra-ui/core';
import { FiCode } from '@meronex/icons/fi';
import { GoLinkExternal } from '@meronex/icons/go';
import format from 'string-format';
import { useConfig } from 'app/context';
import stringFormat from 'string-format';
import { useConfig, useColorValue } from '~/context';
import { FooterButton } from './FooterButton';
import { FooterContent } from './FooterContent';
format.extend(String.prototype, {});
const footerBg = { light: 'blackAlpha.50', dark: 'whiteAlpha.100' };
const footerColor = { light: 'black', dark: 'white' };
const contentBorder = { light: 'blackAlpha.100', dark: 'whiteAlpha.200' };
import type { TFooterItems } from './types';
export const Footer = () => {
const config = useConfig();
const { colorMode } = useColorMode();
const [helpVisible, showHelp] = useState(false);
const [termsVisible, showTerms] = useState(false);
const [creditVisible, showCredit] = useState(false);
const handleCollapse = i => {
const footerBg = useColorValue('blackAlpha.50', 'whiteAlpha.100');
const footerColor = useColorValue('black', 'white');
const contentBorder = useColorValue('blackAlpha.100', 'whiteAlpha.200');
const handleCollapse = (i: TFooterItems) => {
if (i === 'help') {
showTerms(false);
showCredit(false);
@@ -35,18 +35,19 @@ export const Footer = () => {
showTerms(!termsVisible);
}
};
const extUrl = config.web.external_link.url.includes('{primary_asn}')
? config.web.external_link.url.format({ primary_asn: config.primary_asn })
? stringFormat(config.web.external_link.url, { primary_asn: config.primary_asn })
: config.web.external_link.url || '/';
return (
<>
{config.web.help_menu.enable && (
<FooterContent
isOpen={helpVisible}
content={config.content.help_menu}
title={config.web.help_menu.title}
bg={footerBg[colorMode]}
borderColor={contentBorder[colorMode]}
bg={footerBg}
borderColor={contentBorder}
side="left"
/>
)}
@@ -54,9 +55,8 @@ export const Footer = () => {
<FooterContent
isOpen={termsVisible}
content={config.content.terms}
title={config.web.terms.title}
bg={footerBg[colorMode]}
borderColor={contentBorder[colorMode]}
bg={footerBg}
borderColor={contentBorder}
side="left"
/>
)}
@@ -64,9 +64,8 @@ export const Footer = () => {
<FooterContent
isOpen={creditVisible}
content={config.content.credit}
title={config.web.credit.title}
bg={footerBg[colorMode]}
borderColor={contentBorder[colorMode]}
bg={footerBg}
borderColor={contentBorder}
side="right"
/>
)}
@@ -78,8 +77,8 @@ export const Footer = () => {
flexWrap="wrap"
textAlign="center"
alignItems="center"
bg={footerBg[colorMode]}
color={footerColor[colorMode]}
bg={footerBg}
color={footerColor}
justifyContent="space-between">
{config.web.terms.enable && (
<FooterButton
@@ -115,13 +114,11 @@ export const Footer = () => {
)}
{config.web.external_link.enable && (
<FooterButton
as="a"
href={extUrl}
side="right"
aria-label={config.web.external_link.title}
target="_blank"
rel="noopener noreferrer"
variant="ghost"
rightIcon={GoLinkExternal}
rightIcon={<Box as={GoLinkExternal} />}
size="xs">
{config.web.external_link.title}
</FooterButton>

View File

@@ -1,26 +0,0 @@
import * as React from 'react';
import { Button, Flex } from '@chakra-ui/core';
import { motion } from 'framer-motion';
const AnimatedFlex = motion.custom(Flex);
export const FooterButton = React.forwardRef(({ onClick, side, children, ...props }, ref) => {
return (
<AnimatedFlex
p={0}
w="auto"
ref={ref}
flexGrow={0}
float={side}
flexShrink={0}
maxWidth="100%"
flexBasis="auto"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.6 }}>
<Button size="xs" variant="ghost" onClick={onClick} {...props}>
{children}
</Button>
</AnimatedFlex>
);
});

View File

@@ -0,0 +1,32 @@
import * as React from 'react';
import { Button, Flex, FlexProps } from '@chakra-ui/core';
import { withAnimation } from '~/components';
import type { IFooterButton } from './types';
const AnimatedFlex = withAnimation<FlexProps>(Flex);
export const FooterButton = (props: IFooterButton) => {
const { side, href, ...rest } = props;
let buttonProps = Object();
if (typeof href !== 'undefined') {
buttonProps = { href, as: 'a', target: '_blank', rel: 'noopener noreferrer' };
}
return (
<AnimatedFlex
p={0}
w="auto"
flexGrow={0}
float={side}
flexShrink={0}
maxWidth="100%"
flexBasis="auto"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.6 }}>
<Button size="xs" variant="ghost" {...buttonProps} {...rest} />
</AnimatedFlex>
);
};

View File

@@ -1,27 +0,0 @@
import * as React from 'react';
import { forwardRef } from 'react';
import { Box, Collapse } from '@chakra-ui/core';
import { Markdown } from 'app/components/Markdown';
export const FooterContent = forwardRef(
({ isOpen = false, content, side = 'left', title, ...props }, ref) => {
return (
<Collapse
px={6}
py={4}
w="auto"
ref={ref}
borderBottom="1px"
display="flex"
maxWidth="100%"
isOpen={isOpen}
flexBasis="auto"
justifyContent={side === 'left' ? 'flex-start' : 'flex-end'}
{...props}>
<Box textAlign={side}>
<Markdown content={content} />
</Box>
</Collapse>
);
},
);

View File

@@ -0,0 +1,27 @@
import * as React from 'react';
import { forwardRef } from 'react';
import { Box, Collapse } from '@chakra-ui/core';
import { Markdown } from '~/components';
import type { IFooterContent } from './types';
export const FooterContent = (props: IFooterContent) => {
const { isOpen = false, content, side = 'left', children: _, ...rest } = props;
return (
<Collapse
px={6}
py={4}
w="auto"
borderBottom="1px"
display="flex"
maxWidth="100%"
isOpen={isOpen}
flexBasis="auto"
justifyContent={side === 'left' ? 'flex-start' : 'flex-end'}
{...rest}>
<Box textAlign={side}>
<Markdown content={content} />
</Box>
</Collapse>
);
};

View File

@@ -0,0 +1,17 @@
import type { FlexProps, ButtonProps, CollapseProps } from '@chakra-ui/core';
type TFooterSide = 'left' | 'right';
export interface IFooterButton extends ButtonProps {
side: TFooterSide;
href?: string;
}
export interface IFooterContent extends Omit<CollapseProps, 'children'> {
isOpen: boolean;
content: string;
side: TFooterSide;
children?: undefined;
}
export type TFooterItems = 'help' | 'credit' | 'terms';

View File

@@ -1,60 +0,0 @@
import * as React from 'react';
import {
Checkbox as ChakraCheckbox,
Divider as ChakraDivider,
Code as ChakraCode,
Heading as ChakraHeading,
Link as ChakraLink,
List as ChakraList,
ListItem as ChakraListItem,
Text as ChakraText,
} from '@chakra-ui/core';
import { TableCell, TableHeader, Table as ChakraTable } from './MDTable';
import { CodeBlock as CustomCodeBlock } from 'app/components';
export const Checkbox = ({ checked, children }) => (
<ChakraCheckbox isChecked={checked}>{children}</ChakraCheckbox>
);
export const List = ({ ordered, children }) => (
<ChakraList as={ordered ? 'ol' : 'ul'}>{children}</ChakraList>
);
export const ListItem = ({ checked, children }) =>
checked ? (
<Checkbox checked={checked}>{children}</Checkbox>
) : (
<ChakraListItem>{children}</ChakraListItem>
);
export const Heading = ({ level, children }) => {
const levelMap = {
1: { as: 'h1', size: 'lg', fontWeight: 'bold' },
2: { as: 'h2', size: 'lg', fontWeight: 'normal' },
3: { as: 'h3', size: 'lg', fontWeight: 'bold' },
4: { as: 'h4', size: 'md', fontWeight: 'normal' },
5: { as: 'h5', size: 'md', fontWeight: 'bold' },
6: { as: 'h6', size: 'sm', fontWeight: 'bold' },
};
return <ChakraHeading {...levelMap[level]}>{children}</ChakraHeading>;
};
export const Link = ({ children, ...props }) => (
<ChakraLink isExternal {...props}>
{children}
</ChakraLink>
);
export const CodeBlock = ({ value }) => <CustomCodeBlock>{value}</CustomCodeBlock>;
export const TableData = ({ isHeader, children, ...props }) => {
const Component = isHeader ? TableHeader : TableCell;
return <Component {...props}>{children}</Component>;
};
export const Paragraph = props => <ChakraText {...props} />;
export const InlineCode = props => <ChakraCode {...props} />;
export const Divider = props => <ChakraDivider {...props} />;
export const Table = props => <ChakraTable {...props} />;

View File

@@ -0,0 +1,63 @@
import * as React from 'react';
import {
Checkbox as ChakraCheckbox,
Divider as ChakraDivider,
Code as ChakraCode,
Heading as ChakraHeading,
Link as ChakraLink,
ListItem as ChakraListItem,
Text as ChakraText,
UnorderedList,
OrderedList,
} from '@chakra-ui/core';
import { TableCell, TableHeader, Table as ChakraTable } from './MDTable';
import { CodeBlock as CustomCodeBlock } from '~/components';
import type { BoxProps, TextProps, CodeProps, DividerProps, LinkProps } from '@chakra-ui/core';
import type { ICheckbox, IList, IHeading, ICodeBlock, ITableData } from './types';
export const Checkbox = (props: ICheckbox) => {
const { checked, ...rest } = props;
return <ChakraCheckbox isChecked={checked} {...rest} />;
};
export const List = (props: IList) => {
const { ordered, ...rest } = props;
const Component = ordered ? OrderedList : UnorderedList;
return <Component {...rest} />;
};
export const ListItem = (props: ICheckbox) => {
const { checked, ...rest } = props;
return checked ? <Checkbox checked={checked} {...rest} /> : <ChakraListItem {...rest} />;
};
export const Heading = (props: IHeading) => {
const { level, ...rest } = props;
const levelMap = {
1: { as: 'h1', size: 'lg', fontWeight: 'bold' },
2: { as: 'h2', size: 'lg', fontWeight: 'normal' },
3: { as: 'h3', size: 'lg', fontWeight: 'bold' },
4: { as: 'h4', size: 'md', fontWeight: 'normal' },
5: { as: 'h5', size: 'md', fontWeight: 'bold' },
6: { as: 'h6', size: 'sm', fontWeight: 'bold' },
};
return <ChakraHeading {...levelMap[level]} {...rest} />;
};
export const Link = (props: LinkProps) => <ChakraLink isExternal {...props} />;
export const CodeBlock = (props: ICodeBlock) => <CustomCodeBlock>{props.value}</CustomCodeBlock>;
export const TableData = (props: ITableData) => {
const { isHeader, ...rest } = props;
const Component = isHeader ? TableHeader : TableCell;
return <Component {...rest} />;
};
export const Paragraph = (props: TextProps) => <ChakraText {...props} />;
export const InlineCode = (props: CodeProps) => <ChakraCode {...props} />;
export const Divider = (props: DividerProps) => <ChakraDivider {...props} />;
export const Table = (props: BoxProps) => <ChakraTable {...props} />;

View File

@@ -1,24 +0,0 @@
import * as React from 'react';
import { Box, useColorMode } from '@chakra-ui/core';
export const Table = props => <Box as="table" textAlign="left" mt={4} width="full" {...props} />;
const bg = { light: 'blackAlpha.50', dark: 'whiteAlpha.50' };
export const TableHeader = props => {
const { colorMode } = useColorMode();
return <Box as="th" bg={bg[colorMode]} fontWeight="semibold" p={2} fontSize="sm" {...props} />;
};
export const TableCell = ({ isHeader = false, ...props }) => (
<Box
as={isHeader ? 'th' : 'td'}
p={2}
borderTopWidth="1px"
borderColor="inherit"
fontSize="sm"
whiteSpace="normal"
{...props}
/>
);

View File

@@ -0,0 +1,29 @@
import * as React from 'react';
import { Box } from '@chakra-ui/core';
import { useColorValue } from '~/context';
import type { BoxProps } from '@chakra-ui/core';
import type { ITableData } from './types';
export const Table = (props: BoxProps) => (
<Box as="table" textAlign="left" mt={4} width="full" {...props} />
);
export const TableHeader = (props: BoxProps) => {
const bg = useColorValue('blackAlpha.50', 'whiteAlpha.50');
return <Box as="th" bg={bg} fontWeight="semibold" p={2} fontSize="sm" {...props} />;
};
export const TableCell = (props: ITableData) => {
const { isHeader = false, ...rest } = props;
return (
<Box
as={isHeader ? 'th' : 'td'}
p={2}
borderTopWidth="1px"
borderColor="inherit"
fontSize="sm"
whiteSpace="normal"
{...rest}
/>
);
};

View File

@@ -1,5 +1,4 @@
import * as React from 'react';
import { forwardRef } from 'react';
import ReactMarkdown from 'react-markdown';
import {
List,
@@ -14,6 +13,8 @@ import {
Table,
} from './MDComponents';
import type { IMarkdown } from './types';
const mdComponents = {
paragraph: Paragraph,
link: Link,
@@ -27,6 +28,6 @@ const mdComponents = {
tableCell: TableData,
};
export const Markdown = forwardRef(({ content }, ref) => (
<ReactMarkdown ref={ref} renderers={mdComponents} source={content} />
));
export const Markdown = (props: IMarkdown) => (
<ReactMarkdown renderers={mdComponents} source={props.content} />
);

View File

@@ -0,0 +1,24 @@
import type { ReactNode } from 'react';
import type { BoxProps, CheckboxProps, HeadingProps } from '@chakra-ui/core';
export interface IMarkdown {
content: string;
}
export interface ICheckbox extends CheckboxProps {
checked: boolean;
}
export interface IList {
ordered: boolean;
children?: ReactNode;
}
export interface IHeading extends HeadingProps {
level: 1 | 2 | 3 | 4 | 5 | 6;
}
export interface ICodeBlock {
value: ReactNode;
}
export interface ITableData extends BoxProps {
isHeader: boolean;
}

View File

@@ -33,3 +33,4 @@ export * from './SubmitButton';
export * from './Table';
export * from './TextOutput';
export * from './Title';
export * from './withAnimation';

View File

@@ -0,0 +1,5 @@
import { motion } from 'framer-motion';
export function withAnimation<P>(Component: React.FunctionComponent) {
return motion.custom<Omit<P, 'transition'>>(Component);
}

View File

@@ -1 +1,8 @@
type Dict<T = string> = { [k: string]: T };
import type { MotionProps } from 'framer-motion';
type Dict<T = string> = Record<string, T>;
type ReactRef<T = HTMLElement> = MutableRefObject<T>;
type Animated<T> = Omit<T, keyof MotionProps> &
Omit<MotionProps, keyof T> & { transition?: MotionProps['transition'] };

View File

@@ -42,6 +42,7 @@
"devDependencies": {
"@types/node": "^14.11.10",
"@types/react-select": "^3.0.22",
"@types/string-format": "^2.0.0",
"@typescript-eslint/eslint-plugin": "^2.24.0",
"@typescript-eslint/parser": "^2.24.0",
"@upstatement/eslint-config": "^0.4.3",

View File

@@ -1966,6 +1966,11 @@
"@types/prop-types" "*"
csstype "^3.0.2"
"@types/string-format@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@types/string-format/-/string-format-2.0.0.tgz#c1588f507be7b8ef5eb5074a41e48e4538f3f6d5"
integrity sha512-mMwtmgN0ureESnJ3SuMM4W9lsi4CgOxs43YxNo14SDHgzJ+OPYO3yM7nOTJTh8x5YICseBdtrySUbvxnpb+NYQ==
"@types/tinycolor2@1.4.2":
version "1.4.2"
resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.2.tgz#721ca5c5d1a2988b4a886e35c2ffc5735b6afbdf"