diff --git a/hyperglass/ui/components/BGPTable.js b/hyperglass/ui/components/BGPTable.js index dd20a2f..f293c20 100644 --- a/hyperglass/ui/components/BGPTable.js +++ b/hyperglass/ui/components/BGPTable.js @@ -218,8 +218,6 @@ const Cell = ({ data, rawData, longestASN }) => { const BGPTable = ({ children: data, ...props }) => { const config = useConfig(); const columns = makeColumns(config.parsed_data_fields); - // const allASN = data.routes.map(r => r.as_path).flat(); - // const asLength = longestASNLength(allASN); return ( @@ -235,6 +233,4 @@ const BGPTable = ({ children: data, ...props }) => { ); }; -BGPTable.displayName = "BGPTable"; - export default BGPTable; diff --git a/hyperglass/ui/components/CacheTimeout.js b/hyperglass/ui/components/CacheTimeout.js index 4c37beb..72d5a07 100644 --- a/hyperglass/ui/components/CacheTimeout.js +++ b/hyperglass/ui/components/CacheTimeout.js @@ -5,37 +5,35 @@ import { Text, useColorMode } from "@chakra-ui/core"; const bg = { dark: "white", light: "black" }; const Renderer = ({ hours, minutes, seconds, completed, props }) => { - if (completed) { - return ; - } else { - let time = [zeroPad(seconds)]; - minutes !== 0 && time.unshift(zeroPad(minutes)); - hours !== 0 && time.unshift(zeroPad(hours)); - return ( - - {props.text} - - {time.join(":")} - - - ); - } + if (completed) { + return ; + } else { + let time = [zeroPad(seconds)]; + minutes !== 0 && time.unshift(zeroPad(minutes)); + hours !== 0 && time.unshift(zeroPad(hours)); + return ( + + {props.text} + + {time.join(":")} + + + ); + } }; const CacheTimeout = ({ timeout, text }) => { - const then = timeout * 1000; - const { colorMode } = useColorMode(); - return ( - - ); + const then = timeout * 1000; + const { colorMode } = useColorMode(); + return ( + + ); }; -CacheTimeout.displayName = "CacheTimeout"; - export default CacheTimeout; diff --git a/hyperglass/ui/components/Card/CardBody.js b/hyperglass/ui/components/Card/CardBody.js index a6c35e2..e7c7334 100644 --- a/hyperglass/ui/components/Card/CardBody.js +++ b/hyperglass/ui/components/Card/CardBody.js @@ -4,7 +4,7 @@ import { Flex, useColorMode } from "@chakra-ui/core"; const bg = { light: "white", dark: "original.dark" }; const color = { light: "original.dark", dark: "white" }; -const CardBody = ({ onClick = () => false, children, ...props }) => { +export const CardBody = ({ onClick = () => false, children, ...props }) => { const { colorMode } = useColorMode(); return ( false, children, ...props }) => { ); }; - -CardBody.displayName = "CardBody"; - -export default CardBody; diff --git a/hyperglass/ui/components/Card/CardFooter.js b/hyperglass/ui/components/Card/CardFooter.js index edf6c4e..3bddeb2 100644 --- a/hyperglass/ui/components/Card/CardFooter.js +++ b/hyperglass/ui/components/Card/CardFooter.js @@ -1,25 +1,19 @@ import * as React from "react"; import { Flex } from "@chakra-ui/core"; -const CardFooter = ({ children, ...props }) => { - return ( - - {children} - - ); -}; - -CardFooter.displayName = "CardFooter"; - -export default CardFooter; +export const CardFooter = ({ children, ...props }) => ( + + {children} + +); diff --git a/hyperglass/ui/components/Card/CardHeader.js b/hyperglass/ui/components/Card/CardHeader.js index 75627b7..66a8952 100644 --- a/hyperglass/ui/components/Card/CardHeader.js +++ b/hyperglass/ui/components/Card/CardHeader.js @@ -3,7 +3,7 @@ import { Flex, Text, useColorMode } from "@chakra-ui/core"; const bg = { light: "blackAlpha.50", dark: "whiteAlpha.100" }; -const CardHeader = ({ children, ...props }) => { +export const CardHeader = ({ children, ...props }) => { const { colorMode } = useColorMode(); return ( { ); }; - -CardHeader.displayName = "CardHeader"; - -export default CardHeader; diff --git a/hyperglass/ui/components/Card/index.js b/hyperglass/ui/components/Card/index.js index 58e18ce..805d90d 100644 --- a/hyperglass/ui/components/Card/index.js +++ b/hyperglass/ui/components/Card/index.js @@ -1,5 +1,3 @@ -import CardBody from "./CardBody"; -import CardFooter from "./CardFooter"; -import CardHeader from "./CardHeader"; - -export { CardBody, CardFooter, CardHeader }; +export { CardBody } from "./CardBody"; +export { CardFooter } from "./CardFooter"; +export { CardHeader } from "./CardHeader"; diff --git a/hyperglass/ui/components/ChakraSelect.js b/hyperglass/ui/components/ChakraSelect.js index 93ff37f..296b08a 100644 --- a/hyperglass/ui/components/ChakraSelect.js +++ b/hyperglass/ui/components/ChakraSelect.js @@ -203,5 +203,4 @@ const ChakraSelect = React.forwardRef( } ); -ChakraSelect.displayName = "ChakraSelect"; export default ChakraSelect; diff --git a/hyperglass/ui/components/CodeBlock.js b/hyperglass/ui/components/CodeBlock.js index 22534d5..8572194 100644 --- a/hyperglass/ui/components/CodeBlock.js +++ b/hyperglass/ui/components/CodeBlock.js @@ -1,26 +1,25 @@ -import React from "react"; -import { Box, useColorMode, useTheme } from "@chakra-ui/core"; +import * as React from "react"; +import { Box, useColorMode } from "@chakra-ui/core"; export default ({ children }) => { - const { colorMode } = useColorMode(); - const theme = useTheme(); - const bg = { dark: theme.colors.gray[800], light: theme.colors.blackAlpha[100] }; - const color = { dark: theme.colors.white, light: theme.colors.black }; - return ( - - {children} - - ); + const { colorMode } = useColorMode(); + const bg = { dark: "gray.800", light: "blackAlpha.100" }; + const color = { dark: "white", light: "black" }; + return ( + + {children} + + ); }; diff --git a/hyperglass/ui/components/CommunitySelect.js b/hyperglass/ui/components/CommunitySelect.js index e085f14..321f6d4 100644 --- a/hyperglass/ui/components/CommunitySelect.js +++ b/hyperglass/ui/components/CommunitySelect.js @@ -4,38 +4,46 @@ import { Text } from "@chakra-ui/core"; import { components } from "react-select"; import ChakraSelect from "~/components/ChakraSelect"; -const CommunitySelect = ({ name, communities, onChange, register, unregister }) => { - const communitySelections = communities.map((c) => { - return { value: c.community, label: c.display_name, description: c.description }; - }); - const Option = ({ label, data, ...props }) => { - return ( - - {label} - - {data.description} - - - ); +const CommunitySelect = ({ + name, + communities, + onChange, + register, + unregister +}) => { + const communitySelections = communities.map(c => { + return { + value: c.community, + label: c.display_name, + description: c.description }; - useEffect(() => { - register({ name }); - return () => unregister(name); - }, [name, register, unregister]); + }); + const Option = ({ label, data, ...props }) => { return ( - { - onChange({ field: name, value: e.value || "" }); - }} - options={communitySelections} - components={{ Option }} - /> + + {label} + + {data.description} + + ); + }; + useEffect(() => { + register({ name }); + return () => unregister(name); + }, [name, register, unregister]); + return ( + { + onChange({ field: name, value: e.value || "" }); + }} + options={communitySelections} + components={{ Option }} + /> + ); }; -CommunitySelect.displayName = "CommunitySelect"; - export default CommunitySelect; diff --git a/hyperglass/ui/components/CopyButton.js b/hyperglass/ui/components/CopyButton.js index 28ad79a..ca7a319 100644 --- a/hyperglass/ui/components/CopyButton.js +++ b/hyperglass/ui/components/CopyButton.js @@ -1,21 +1,27 @@ -import React from "react"; +import * as React from "react"; import { Button, Icon, Tooltip, useClipboard } from "@chakra-ui/core"; -export default ({ bg = "secondary", copyValue, ...props }) => { - const { onCopy, hasCopied } = useClipboard(copyValue); - return ( - - - - ); +const CopyButton = ({ bg = "secondary", copyValue, ...props }) => { + const { onCopy, hasCopied } = useClipboard(copyValue); + return ( + + + + ); }; + +export default CopyButton; diff --git a/hyperglass/ui/components/Debugger.js b/hyperglass/ui/components/Debugger.js index a407c56..d7fd669 100644 --- a/hyperglass/ui/components/Debugger.js +++ b/hyperglass/ui/components/Debugger.js @@ -1,94 +1,106 @@ -import React from "react"; +import * as React from "react"; import { - Button, - Modal, - ModalOverlay, - ModalContent, - ModalHeader, - ModalBody, - ModalCloseButton, - Stack, - Tag, - useDisclosure, - useColorMode, - useTheme, + Button, + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + ModalBody, + ModalCloseButton, + Stack, + Tag, + useDisclosure, + useColorMode, + useTheme } from "@chakra-ui/core"; import useConfig from "~/components/HyperglassProvider"; import useMedia from "~/components/MediaProvider"; import CodeBlock from "~/components/CodeBlock"; -const prettyMediaSize = { sm: "SMALL", md: "MEDIUM", lg: "LARGE", xl: "X-LARGE" }; - -const Debugger = () => { - const { isOpen: configOpen, onOpen: onConfigOpen, onClose: configClose } = useDisclosure(); - const { isOpen: themeOpen, onOpen: onThemeOpen, onClose: themeClose } = useDisclosure(); - 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" }; - return ( - <> - - {colorMode.toUpperCase()} - {prettyMediaSize[mediaSize]} - - - - - - - Loaded Configuration - - - {JSON.stringify(config, null, 4)} - - - - - - - Loaded Theme - - - {JSON.stringify(theme, null, 4)} - - - - - ); +const prettyMediaSize = { + sm: "SMALL", + md: "MEDIUM", + lg: "LARGE", + xl: "X-LARGE" +}; + +const Debugger = () => { + const { + isOpen: configOpen, + onOpen: onConfigOpen, + onClose: configClose + } = useDisclosure(); + const { + isOpen: themeOpen, + onOpen: onThemeOpen, + onClose: themeClose + } = useDisclosure(); + 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" }; + return ( + <> + + {colorMode.toUpperCase()} + {prettyMediaSize[mediaSize]} + + + + + + + Loaded Configuration + + + {JSON.stringify(config, null, 4)} + + + + + + + Loaded Theme + + + {JSON.stringify(theme, null, 4)} + + + + + ); }; -Debugger.displayName = "Debugger"; export default Debugger; diff --git a/hyperglass/ui/components/Footer.js b/hyperglass/ui/components/Footer/Footer.js similarity index 86% rename from hyperglass/ui/components/Footer.js rename to hyperglass/ui/components/Footer/Footer.js index e86d54b..8f2d3e1 100644 --- a/hyperglass/ui/components/Footer.js +++ b/hyperglass/ui/components/Footer/Footer.js @@ -1,33 +1,25 @@ -import React, { useState } from "react"; -import { Flex, useColorMode, useTheme } from "@chakra-ui/core"; +import * as React from "react"; +import { useState } from "react"; +import { Flex, useColorMode } from "@chakra-ui/core"; import { FiCode } from "react-icons/fi"; import { GoLinkExternal } from "react-icons/go"; import format from "string-format"; import useConfig from "~/components/HyperglassProvider"; -import FooterButton from "~/components/FooterButton"; -import FooterContent from "~/components/FooterContent"; +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" }; + const Footer = () => { - const theme = useTheme(); const config = useConfig(); const { colorMode } = useColorMode(); - const footerBg = { - light: theme.colors.blackAlpha[50], - dark: theme.colors.whiteAlpha[100] - }; - const footerColor = { light: theme.colors.black, dark: theme.colors.white }; - const contentBorder = { - light: theme.colors.blackAlpha[100], - dark: theme.colors.whiteAlpha[200] - }; const [helpVisible, showHelp] = useState(false); const [termsVisible, showTerms] = useState(false); const [creditVisible, showCredit] = useState(false); - const extUrl = config.web.external_link.url.includes("{primary_asn}") - ? config.web.external_link.url.format({ primary_asn: config.primary_asn }) - : config.web.external_link.url || "/"; const handleCollapse = i => { if (i === "help") { showTerms(false); @@ -43,6 +35,9 @@ 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 }) + : config.web.external_link.url || "/"; return ( <> {config.web.help_menu.enable && ( @@ -141,5 +136,4 @@ const Footer = () => { ); }; -Footer.displayName = "Footer"; export default Footer; diff --git a/hyperglass/ui/components/FooterButton.js b/hyperglass/ui/components/Footer/FooterButton.js similarity index 91% rename from hyperglass/ui/components/FooterButton.js rename to hyperglass/ui/components/Footer/FooterButton.js index 51a410f..24f2d2b 100644 --- a/hyperglass/ui/components/FooterButton.js +++ b/hyperglass/ui/components/Footer/FooterButton.js @@ -1,4 +1,4 @@ -import React from "react"; +import * as React from "react"; import { Button, Flex } from "@chakra-ui/core"; import { motion } from "framer-motion"; @@ -28,5 +28,4 @@ const FooterButton = React.forwardRef( } ); -FooterButton.displayName = "FooterButton"; export default FooterButton; diff --git a/hyperglass/ui/components/Footer/FooterContent.js b/hyperglass/ui/components/Footer/FooterContent.js new file mode 100644 index 0000000..fd4789e --- /dev/null +++ b/hyperglass/ui/components/Footer/FooterContent.js @@ -0,0 +1,30 @@ +import * as React from "react"; +import { forwardRef } from "react"; +import { Box, Collapse } from "@chakra-ui/core"; +import MarkDown from "~/components/MarkDown"; + +const FooterContent = forwardRef( + ({ isOpen = false, content, side = "left", title, ...props }, ref) => { + return ( + + + + + + ); + } +); + +export default FooterContent; diff --git a/hyperglass/ui/components/Footer/index.js b/hyperglass/ui/components/Footer/index.js new file mode 100644 index 0000000..ccb5e78 --- /dev/null +++ b/hyperglass/ui/components/Footer/index.js @@ -0,0 +1,2 @@ +import Footer from "./Footer"; +export default Footer; diff --git a/hyperglass/ui/components/FooterContent.js b/hyperglass/ui/components/FooterContent.js deleted file mode 100644 index 3ba17d5..0000000 --- a/hyperglass/ui/components/FooterContent.js +++ /dev/null @@ -1,27 +0,0 @@ -import React from "react"; -import { Box, Collapse } from "@chakra-ui/core"; -import MarkDown from "~/components/MarkDown"; - -export default React.forwardRef( - ({ isOpen = false, content, side = "left", title, ...props }, ref) => { - return ( - - - - - - ); - } -); diff --git a/hyperglass/ui/components/FormField.js b/hyperglass/ui/components/FormField.js index d5f3201..1cbb462 100644 --- a/hyperglass/ui/components/FormField.js +++ b/hyperglass/ui/components/FormField.js @@ -1,4 +1,4 @@ -import React from "react"; +import * as React from "react"; import { Flex, FormControl, @@ -7,7 +7,9 @@ import { useColorMode } from "@chakra-ui/core"; -export default ({ +const labelColor = { dark: "whiteAlpha.700", light: "blackAlpha.700" }; + +const FormField = ({ label, name, error, @@ -21,7 +23,7 @@ export default ({ ...props }) => { const { colorMode } = useColorMode(); - const labelColor = { dark: "whiteAlpha.700", light: "blackAlpha.700" }; + return ( ); }; + +export default FormField; diff --git a/hyperglass/ui/components/Greeting.js b/hyperglass/ui/components/Greeting.js index d4405c7..7f810f5 100644 --- a/hyperglass/ui/components/Greeting.js +++ b/hyperglass/ui/components/Greeting.js @@ -1,15 +1,15 @@ import * as React from "react"; import { - Button, - Modal, - ModalOverlay, - ModalContent, - ModalHeader, - ModalFooter, - ModalBody, - ModalCloseButton, - useColorMode, - useDisclosure, + Button, + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + ModalFooter, + ModalBody, + ModalCloseButton, + useColorMode, + useDisclosure } from "@chakra-ui/core"; import MarkDown from "~/components/MarkDown"; import { motion } from "framer-motion"; @@ -21,53 +21,51 @@ const AnimatedModalContent = motion.custom(ModalContent); const AnimatedModalOverlay = motion.custom(ModalOverlay); const Greeting = ({ greetingConfig, content, onClickThrough }) => { - const { isOpen, onOpen, onClose } = useDisclosure(true); - const { colorMode } = useColorMode(); + const { isOpen, onOpen, onClose } = useDisclosure(true); + const { colorMode } = useColorMode(); - const handleClick = () => { - onClickThrough(true); - onClose(); - }; + const handleClick = () => { + onClickThrough(true); + onClose(); + }; - return ( - - - - {greetingConfig.title} - {!greetingConfig.required && } - - - - - - - - - ); + return ( + + + + {greetingConfig.title} + {!greetingConfig.required && } + + + + + + + + + ); }; -Greeting.displayName = "Greeting"; - export default Greeting; diff --git a/hyperglass/ui/components/Header.js b/hyperglass/ui/components/Header.js index 064882e..8ecda36 100644 --- a/hyperglass/ui/components/Header.js +++ b/hyperglass/ui/components/Header.js @@ -1,4 +1,4 @@ -import React from "react"; +import * as React from "react"; import { Flex, useColorMode } from "@chakra-ui/core"; import { motion, AnimatePresence } from "framer-motion"; import ResetButton from "~/components/ResetButton"; @@ -33,12 +33,7 @@ const titleVariants = { } }; -const icon = { light: "moon", dark: "sun" }; const bg = { light: "white", dark: "black" }; -const colorSwitch = { - dark: "Switch to light mode", - light: "Switch to dark mode" -}; const headerTransition = { type: "spring", ease: "anticipate", @@ -107,7 +102,6 @@ const Header = ({ layoutRef, ...props }) => { } variants={titleVariants[mediaSize]} justifyContent={titleJustify[isSubmitting]} - mb={[null, isSubmitting ? "auto" : null]} mt={[null, isSubmitting ? null : "auto"]} maxW={widthMap[web.text.title_mode]} flex="1 0 0" @@ -168,6 +162,4 @@ const Header = ({ layoutRef, ...props }) => { ); }; -Header.displayName = "Header"; - export default Header; diff --git a/hyperglass/ui/components/HelpModal.js b/hyperglass/ui/components/HelpModal.js index 3911259..02d1ee4 100644 --- a/hyperglass/ui/components/HelpModal.js +++ b/hyperglass/ui/components/HelpModal.js @@ -1,63 +1,73 @@ -import React from "react"; +import * as React from "react"; import { - IconButton, - Modal, - ModalOverlay, - ModalContent, - ModalHeader, - ModalBody, - ModalCloseButton, - useDisclosure, - useColorMode, - useTheme + IconButton, + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + ModalBody, + ModalCloseButton, + useDisclosure, + useColorMode, + useTheme } from "@chakra-ui/core"; import { motion, AnimatePresence } from "framer-motion"; import MarkDown from "~/components/MarkDown"; const AnimatedIcon = motion.custom(IconButton); -export default ({ item, name }) => { - const { isOpen, onOpen, onClose } = useDisclosure(); - const theme = useTheme(); - const { colorMode } = useColorMode(); - const bg = { light: theme.colors.white, dark: theme.colors.dark }; - const color = { light: theme.colors.black, dark: theme.colors.white }; - const iconColor = { light: theme.colors.primary[500], dark: theme.colors.primary[300] }; - return ( - <> - - - - - - - {item.params.title} - - - - - - - - ); +const HelpModal = ({ item, name }) => { + const { isOpen, onOpen, onClose } = useDisclosure(); + const { colors } = useTheme(); + const { colorMode } = useColorMode(); + const bg = { light: "whiteFaded.50", dark: "blackFaded.800" }; + const color = { light: "black", dark: "white" }; + const iconColor = { + light: colors.primary[500], + dark: colors.primary[300] + }; + return ( + <> + + + + + + + {item.params.title} + + + + + + + + ); }; + +export default HelpModal; diff --git a/hyperglass/ui/components/HyperglassForm.js b/hyperglass/ui/components/HyperglassForm.js index 7ff6570..69cf1bf 100644 --- a/hyperglass/ui/components/HyperglassForm.js +++ b/hyperglass/ui/components/HyperglassForm.js @@ -1,5 +1,5 @@ import * as React from "react"; -import { useState, useEffect } from "react"; +import { forwardRef, useState, useEffect } from "react"; import { Box, Flex } from "@chakra-ui/core"; import { useForm } from "react-hook-form"; import lodash from "lodash"; @@ -53,7 +53,7 @@ const FormRow = ({ children, ...props }) => ( ); -const HyperglassForm = React.forwardRef( +const HyperglassForm = forwardRef( ( { isSubmitting, @@ -164,6 +164,8 @@ const HyperglassForm = React.forwardRef( Object.keys(errors).length >= 1 && console.error(errors); return ( -
- - + + - - - + + + } + > + - } + /> + + + + {availVrfs.length > 1 && ( + - - - - {availVrfs.length > 1 && ( - - - - )} - - ) - } - > - {queryType === "bgp_community" && - config.queries.bgp_community.mode === "select" ? ( - - ) : ( - - )} - - - - - - - -
+ ) + } + > + {queryType === "bgp_community" && + config.queries.bgp_community.mode === "select" ? ( + + ) : ( + + )} + + + + + + +
); } ); -HyperglassForm.displayName = "HyperglassForm"; export default HyperglassForm; diff --git a/hyperglass/ui/components/HyperglassProvider.js b/hyperglass/ui/components/HyperglassProvider.js index 858ca04..9694ff0 100644 --- a/hyperglass/ui/components/HyperglassProvider.js +++ b/hyperglass/ui/components/HyperglassProvider.js @@ -22,16 +22,16 @@ export const HyperglassProvider = ({ config, children }) => { const userTheme = value && makeTheme(value.web.theme); const theme = value ? userTheme : defaultTheme; return ( - - - - - + + + + + {children} - - - - + + + + ); }; diff --git a/hyperglass/ui/components/Label.js b/hyperglass/ui/components/Label.js index 1cab54d..b91654f 100644 --- a/hyperglass/ui/components/Label.js +++ b/hyperglass/ui/components/Label.js @@ -1,62 +1,62 @@ -import React from "react"; -import { Flex, useColorMode, useTheme } from "@chakra-ui/core"; +import * as React from "react"; +import { forwardRef } from "react"; +import { Flex, useColorMode } from "@chakra-ui/core"; -export default React.forwardRef( - ({ value, label, labelColor, valueBg, valueColor, ...props }, ref) => { - const theme = useTheme(); - const { colorMode } = useColorMode(); - const _labelColor = { dark: "whiteAlpha.700", light: "blackAlpha.700" }; - const _valueBg = { light: theme.colors.primary[600], dark: theme.colors.primary[600] }; - const _valueColor = { light: "white", dark: "white" }; - return ( - - - {value} - - - {label} - - - ); - } +const Label = forwardRef( + ({ value, label, labelColor, valueBg, valueColor, ...props }, ref) => { + const { colorMode } = useColorMode(); + const _labelColor = { dark: "whiteAlpha.700", light: "blackAlpha.700" }; + return ( + + + {value} + + + {label} + + + ); + } ); + +export default Label; diff --git a/hyperglass/ui/components/Loading.js b/hyperglass/ui/components/Loading.js index 40acb93..cd5509b 100644 --- a/hyperglass/ui/components/Loading.js +++ b/hyperglass/ui/components/Loading.js @@ -1,37 +1,36 @@ -import React from "react"; +import * as React from "react"; import { Flex, Spinner, useColorMode } from "@chakra-ui/core"; const Loading = () => { - const { colorMode } = useColorMode(); - const bg = { light: "white", dark: "black" }; - const color = { light: "black", dark: "white" }; - return ( - - - - - - ); + const { colorMode } = useColorMode(); + const bg = { light: "white", dark: "black" }; + const color = { light: "black", dark: "white" }; + return ( + + + + + + ); }; -Loading.displayName = "Loading"; export default Loading; diff --git a/hyperglass/ui/components/MarkDown.js b/hyperglass/ui/components/MarkDown.js deleted file mode 100644 index 63ef400..0000000 --- a/hyperglass/ui/components/MarkDown.js +++ /dev/null @@ -1,75 +0,0 @@ -import React from "react"; -import dynamic from "next/dynamic"; -import { - Checkbox as ChakraCheckbox, - Divider, - Code, - Heading as ChakraHeading, - Link as ChakraLink, - List as ChakraList, - ListItem as ChakraListItem, - Spinner, - Text as ChakraText -} from "@chakra-ui/core"; -import CustomCodeBlock from "~/components/CodeBlock"; -import { TableCell, TableHeader, Table } from "~/components/Table"; - -// Dynaimc Imports -const ReactMarkdown = dynamic(() => import("react-markdown"), { loading: Spinner }); - -const Checkbox = ({ checked, children }) => ( - {children} -); - -const List = ({ ordered, children }) => ( - {children} -); - -const ListItem = ({ checked, children }) => - checked ? ( - {children} - ) : ( - {children} - ); - -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 {children}; -}; - -const Link = ({ children, ...props }) => ( - - {children} - -); - -const CodeBlock = ({ value }) => {value}; - -const TableData = ({ isHeader, children, ...props }) => { - const Component = isHeader ? TableHeader : TableCell; - return {children}; -}; - -const mdComponents = { - paragraph: ChakraText, - link: Link, - heading: Heading, - inlineCode: Code, - list: List, - listItem: ListItem, - thematicBreak: Divider, - code: CodeBlock, - table: Table, - tableCell: TableData -}; - -export default React.forwardRef(({ content }, ref) => ( - -)); diff --git a/hyperglass/ui/components/Markdown/MDComponents.js b/hyperglass/ui/components/Markdown/MDComponents.js new file mode 100644 index 0000000..ecb056d --- /dev/null +++ b/hyperglass/ui/components/Markdown/MDComponents.js @@ -0,0 +1,66 @@ +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 "~/components/Table"; + +import CustomCodeBlock from "~/components/CodeBlock"; + +export const Checkbox = ({ checked, children }) => ( + {children} +); + +export const List = ({ ordered, children }) => ( + {children} +); + +export const ListItem = ({ checked, children }) => + checked ? ( + {children} + ) : ( + {children} + ); + +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 {children}; +}; + +export const Link = ({ children, ...props }) => ( + + {children} + +); + +export const CodeBlock = ({ value }) => ( + {value} +); + +export const TableData = ({ isHeader, children, ...props }) => { + const Component = isHeader ? TableHeader : TableCell; + return {children}; +}; + +export const Paragraph = props => ; +export const InlineCode = props => ; +export const Divider = props => ; +export const Table = props => ; diff --git a/hyperglass/ui/components/Markdown/index.js b/hyperglass/ui/components/Markdown/index.js new file mode 100644 index 0000000..9579c06 --- /dev/null +++ b/hyperglass/ui/components/Markdown/index.js @@ -0,0 +1,34 @@ +import * as React from "react"; +import { forwardRef } from "react"; +import ReactMarkdown from "react-markdown"; +import { + List, + ListItem, + Heading, + Link, + CodeBlock, + TableData, + Paragraph, + InlineCode, + Divider, + Table +} from "./MDComponents"; + +const mdComponents = { + paragraph: Paragraph, + link: Link, + heading: Heading, + inlineCode: InlineCode, + list: List, + listItem: ListItem, + thematicBreak: Divider, + code: CodeBlock, + table: Table, + tableCell: TableData +}; + +const Markdown = forwardRef(({ content }, ref) => ( + +)); + +export default Markdown; diff --git a/hyperglass/ui/components/MediaProvider.js b/hyperglass/ui/components/MediaProvider.js index 8af5cb3..5efe028 100644 --- a/hyperglass/ui/components/MediaProvider.js +++ b/hyperglass/ui/components/MediaProvider.js @@ -1,4 +1,5 @@ -import React, { createContext, useContext, useMemo } from "react"; +import * as React from "react"; +import { createContext, useContext, useMemo } from "react"; import { useMediaLayout } from "use-media"; const MediaContext = createContext(null); diff --git a/hyperglass/ui/components/Meta.js b/hyperglass/ui/components/Meta.js index c83d36c..20bd498 100644 --- a/hyperglass/ui/components/Meta.js +++ b/hyperglass/ui/components/Meta.js @@ -1,4 +1,5 @@ -import React, { useEffect, useState } from "react"; +import * as React from "react"; +import { useEffect, useState } from "react"; import Head from "next/head"; import { useTheme } from "@chakra-ui/core"; import useConfig from "~/components/HyperglassProvider"; @@ -9,7 +10,7 @@ const Meta = () => { const theme = useTheme(); const [location, setLocation] = useState({}); const title = config?.site_title || "hyperglass"; - const description = config?.site_description || "The modern looking glass."; + const description = config?.site_description || "Network Looking Glass"; const siteName = `${title} - ${description}`; const keywords = config?.site_keywords || [ "hyperglass", diff --git a/hyperglass/ui/components/QueryLocation.js b/hyperglass/ui/components/QueryLocation.js index a2cc6d6..4b18041 100644 --- a/hyperglass/ui/components/QueryLocation.js +++ b/hyperglass/ui/components/QueryLocation.js @@ -1,4 +1,4 @@ -import React from "react"; +import * as React from "react"; import ChakraSelect from "~/components/ChakraSelect"; const buildLocations = networks => { @@ -29,16 +29,15 @@ const QueryLocation = ({ locations, onChange, label }) => { }; return ( ); }; -QueryLocation.displayName = "QueryLocation"; export default QueryLocation; diff --git a/hyperglass/ui/components/QueryTarget.js b/hyperglass/ui/components/QueryTarget.js index 23ff607..26f36ae 100644 --- a/hyperglass/ui/components/QueryTarget.js +++ b/hyperglass/ui/components/QueryTarget.js @@ -68,5 +68,4 @@ const QueryTarget = ({ ); }; -QueryTarget.displayName = "QueryTarget"; export default QueryTarget; diff --git a/hyperglass/ui/components/QueryType.js b/hyperglass/ui/components/QueryType.js index e5d6fbc..448d65c 100644 --- a/hyperglass/ui/components/QueryType.js +++ b/hyperglass/ui/components/QueryType.js @@ -1,4 +1,4 @@ -import React from "react"; +import * as React from "react"; import ChakraSelect from "~/components/ChakraSelect"; const QueryType = ({ queryTypes, onChange, label }) => { @@ -18,5 +18,4 @@ const QueryType = ({ queryTypes, onChange, label }) => { ); }; -QueryType.displayName = "QueryType"; export default QueryType; diff --git a/hyperglass/ui/components/QueryVrf.js b/hyperglass/ui/components/QueryVrf.js index 10bebe8..9cd61ed 100644 --- a/hyperglass/ui/components/QueryVrf.js +++ b/hyperglass/ui/components/QueryVrf.js @@ -1,17 +1,14 @@ -import React from "react"; +import * as React from "react"; import ChakraSelect from "~/components/ChakraSelect"; -const QueryVrf = ({ vrfs, onChange, label }) => { - return ( - onChange({ field: "query_vrf", value: e.value })} - name="query_vrf" - options={vrfs} - aria-label={label} - /> - ); -}; +const QueryVrf = ({ vrfs, onChange, label }) => ( + onChange({ field: "query_vrf", value: e.value })} + /> +); -QueryVrf.displayName = "QueryVrf"; export default QueryVrf; diff --git a/hyperglass/ui/components/RequeryButton.js b/hyperglass/ui/components/RequeryButton.js index 8ea0722..8b92476 100644 --- a/hyperglass/ui/components/RequeryButton.js +++ b/hyperglass/ui/components/RequeryButton.js @@ -1,20 +1,20 @@ -import React from "react"; +import * as React from "react"; import { Button, Icon, Tooltip } from "@chakra-ui/core"; -export default ({ requery, bg = "secondary", ...props }) => { - return ( - - - - ); -}; +const RequeryButton = ({ requery, bg = "secondary", ...props }) => ( + + + +); + +export default RequeryButton; diff --git a/hyperglass/ui/components/ResetButton.js b/hyperglass/ui/components/ResetButton.js index 1b31319..5954926 100644 --- a/hyperglass/ui/components/ResetButton.js +++ b/hyperglass/ui/components/ResetButton.js @@ -1,19 +1,18 @@ -import React from "react"; +import * as React from "react"; import { Button } from "@chakra-ui/core"; import { FiChevronLeft } from "react-icons/fi"; const ResetButton = React.forwardRef(({ isSubmitting, onClick }, ref) => ( )); -ResetButton.displayName = "ResetButton"; export default ResetButton; diff --git a/hyperglass/ui/components/ResolvedTarget.js b/hyperglass/ui/components/ResolvedTarget.js index 595ce17..c9f43b1 100644 --- a/hyperglass/ui/components/ResolvedTarget.js +++ b/hyperglass/ui/components/ResolvedTarget.js @@ -1,6 +1,15 @@ -import React, { useEffect } from "react"; -import { Button, Icon, Spinner, Stack, Tag, Text, Tooltip, useColorMode } from "@chakra-ui/core"; -import axios from "axios"; +import * as React from "react"; +import { forwardRef, useEffect } from "react"; +import { + Button, + Icon, + Spinner, + Stack, + Tag, + Text, + Tooltip, + useColorMode +} from "@chakra-ui/core"; import useAxios from "axios-hooks"; import format from "string-format"; import useConfig from "~/components/HyperglassProvider"; @@ -10,150 +19,164 @@ format.extend(String.prototype, {}); const labelBg = { dark: "secondary", light: "secondary" }; const labelBgSuccess = { dark: "success", light: "success" }; -async function containingPrefix(ipAddress) { - try { - const prefixData = await axios.get("https://stat.ripe.net/data/network-info/data.json", { - params: { resource: ipAddress }, - }); - return prefixData.data?.data?.prefix; - } catch (err) { - console.dir(err); - return null; - } -} +const ResolvedTarget = forwardRef( + ({ fqdnTarget, setTarget, queryTarget, families, availVrfs }, ref) => { + const { colorMode } = useColorMode(); + const config = useConfig(); + const labelBgStatus = { + true: labelBgSuccess[colorMode], + false: labelBg[colorMode] + }; + const dnsUrl = config.web.dns_provider.url; + const query4 = families.includes(4); + const query6 = families.includes(6); + const params = { + 4: { + url: dnsUrl, + params: { name: fqdnTarget, type: "A" }, + headers: { accept: "application/dns-json" }, + crossdomain: true, + timeout: 1000 + }, + 6: { + url: dnsUrl, + params: { name: fqdnTarget, type: "AAAA" }, + headers: { accept: "application/dns-json" }, + crossdomain: true, + timeout: 1000 + } + }; -const ResolvedTarget = React.forwardRef( - ({ fqdnTarget, setTarget, queryTarget, families, availVrfs }, ref) => { - const { colorMode } = useColorMode(); - const config = useConfig(); - const labelBgStatus = { true: labelBgSuccess[colorMode], false: labelBg[colorMode] }; - const dnsUrl = config.web.dns_provider.url; - const query4 = families.includes(4); - const query6 = families.includes(6); - const params = { - 4: { - url: dnsUrl, - params: { name: fqdnTarget, type: "A" }, - headers: { accept: "application/dns-json" }, - crossdomain: true, - timeout: 1000, - }, - 6: { - url: dnsUrl, - params: { name: fqdnTarget, type: "AAAA" }, - headers: { accept: "application/dns-json" }, - crossdomain: true, - timeout: 1000, - }, - }; + const [{ data: data4, loading: loading4, error: error4 }] = useAxios( + params[4] + ); - const [{ data: data4, loading: loading4, error: error4 }] = useAxios(params[4]); + const [{ data: data6, loading: loading6, error: error6 }] = useAxios( + params[6] + ); - const [{ data: data6, loading: loading6, error: error6 }] = useAxios(params[6]); + const handleOverride = overridden => { + setTarget({ field: "query_target", value: overridden }); + }; - const handleOverride = (overridden) => { - setTarget({ field: "query_target", value: overridden }); - }; + const isSelected = value => { + return labelBgStatus[value === queryTarget]; + }; - const isSelected = (value) => { - return labelBgStatus[value === queryTarget]; - }; + const findAnswer = data => { + return data?.Answer?.filter( + answerData => answerData.type === data?.Question[0]?.type + )[0]?.data; + }; - const findAnswer = (data) => { - return data?.Answer?.filter( - (answerData) => answerData.type === data?.Question[0]?.type - )[0]?.data; - }; - - useEffect(() => { - if (query6 && data6?.Answer) { - handleOverride(findAnswer(data6)); - } else if (query4 && data4?.Answer && !query6 && !data6?.Answer) { - handleOverride(findAnswer(data4)); - } else if (query4 && data4?.Answer) { - handleOverride(findAnswer(data4)); - } - }, [data4, data6]); - return ( - 1 - ? "space-between" - : "flex-end" - } - flexWrap="wrap" - > - {loading4 || - error4 || - (query4 && findAnswer(data4) && ( - - - - - {loading4 && } - {error4 && } - {findAnswer(data4) && ( - - {findAnswer(data4)} - - )} - - ))} - {loading6 || - error6 || - (query6 && findAnswer(data6) && ( - - - - - {loading6 && } - {error6 && } - {findAnswer(data6) && ( - - {findAnswer(data6)} - - )} - - ))} - - ); - } + useEffect(() => { + if (query6 && data6?.Answer) { + handleOverride(findAnswer(data6)); + } else if (query4 && data4?.Answer && !query6 && !data6?.Answer) { + handleOverride(findAnswer(data4)); + } else if (query4 && data4?.Answer) { + handleOverride(findAnswer(data4)); + } + }, [data4, data6]); + return ( + 1 + ? "space-between" + : "flex-end" + } + flexWrap="wrap" + > + {loading4 || + error4 || + (query4 && findAnswer(data4) && ( + + + + + {loading4 && } + {error4 && } + {findAnswer(data4) && ( + + {findAnswer(data4)} + + )} + + ))} + {loading6 || + error6 || + (query6 && findAnswer(data6) && ( + + + + + {loading6 && } + {error6 && } + {findAnswer(data6) && ( + + {findAnswer(data6)} + + )} + + ))} + + ); + } ); -ResolvedTarget.displayName = "ResolvedTarget"; export default ResolvedTarget; diff --git a/hyperglass/ui/components/Result.js b/hyperglass/ui/components/Result.js index a53cc88..8feae76 100644 --- a/hyperglass/ui/components/Result.js +++ b/hyperglass/ui/components/Result.js @@ -1,6 +1,6 @@ /** @jsx jsx */ import { jsx } from "@emotion/core"; -import { useEffect, useState } from "react"; +import { forwardRef, useEffect, useState } from "react"; import { AccordionItem, AccordionHeader, @@ -78,7 +78,7 @@ const scrollbar = { dark: "whiteAlpha.300", light: "blackAlpha.300" }; const scrollbarHover = { dark: "whiteAlpha.400", light: "blackAlpha.400" }; const scrollbarBg = { dark: "whiteAlpha.50", light: "blackAlpha.50" }; -const Result = React.forwardRef( +const Result = forwardRef( ( { device, @@ -276,5 +276,4 @@ const Result = React.forwardRef( } ); -Result.displayName = "HyperglassQueryResult"; export default Result; diff --git a/hyperglass/ui/components/ResultHeader.js b/hyperglass/ui/components/ResultHeader.js index 9e0845c..f5f7838 100644 --- a/hyperglass/ui/components/ResultHeader.js +++ b/hyperglass/ui/components/ResultHeader.js @@ -1,4 +1,5 @@ -import React from "react"; +import * as React from "react"; +import { forwardRef } from "react"; import { AccordionIcon, Icon, @@ -31,7 +32,7 @@ const defaultStatusColor = { light: "success.500" }; -export default React.forwardRef( +const ResultHeader = forwardRef( ({ title, loading, error, errorMsg, errorLevel, runtime }, ref) => { const { colorMode } = useColorMode(); const config = useConfig(); @@ -68,3 +69,5 @@ export default React.forwardRef( ); } ); + +export default ResultHeader; diff --git a/hyperglass/ui/components/Results.js b/hyperglass/ui/components/Results.js index 152c99d..63e33f7 100644 --- a/hyperglass/ui/components/Results.js +++ b/hyperglass/ui/components/Results.js @@ -1,4 +1,5 @@ -import React, { useState } from "react"; +import * as React from "react"; +import { useState } from "react"; import { Accordion, Box, Stack, useTheme } from "@chakra-ui/core"; import { motion, AnimatePresence } from "framer-motion"; import Label from "~/components/Label"; @@ -10,148 +11,155 @@ const AnimatedResult = motion.custom(Result); const AnimatedLabel = motion.custom(Label); const labelInitial = { - left: { - sm: { opacity: 0, x: -100 }, - md: { opacity: 0, x: -100 }, - lg: { opacity: 0, x: -100 }, - xl: { opacity: 0, x: -100 } - }, - center: { - sm: { opacity: 0 }, - md: { opacity: 0 }, - lg: { opacity: 0 }, - xl: { opacity: 0 } - }, - right: { - sm: { opacity: 0, x: 100 }, - md: { opacity: 0, x: 100 }, - lg: { opacity: 0, x: 100 }, - xl: { opacity: 0, x: 100 } - } + left: { + sm: { opacity: 0, x: -100 }, + md: { opacity: 0, x: -100 }, + lg: { opacity: 0, x: -100 }, + xl: { opacity: 0, x: -100 } + }, + center: { + sm: { opacity: 0 }, + md: { opacity: 0 }, + lg: { opacity: 0 }, + xl: { opacity: 0 } + }, + right: { + sm: { opacity: 0, x: 100 }, + md: { opacity: 0, x: 100 }, + lg: { opacity: 0, x: 100 }, + xl: { opacity: 0, x: 100 } + } }; const labelAnimate = { - left: { - sm: { opacity: 1, x: 0 }, - md: { opacity: 1, x: 0 }, - lg: { opacity: 1, x: 0 }, - xl: { opacity: 1, x: 0 } - }, - center: { - sm: { opacity: 1 }, - md: { opacity: 1 }, - lg: { opacity: 1 }, - xl: { opacity: 1 } - }, - right: { - sm: { opacity: 1, x: 0 }, - md: { opacity: 1, x: 0 }, - lg: { opacity: 1, x: 0 }, - xl: { opacity: 1, x: 0 } - } + left: { + sm: { opacity: 1, x: 0 }, + md: { opacity: 1, x: 0 }, + lg: { opacity: 1, x: 0 }, + xl: { opacity: 1, x: 0 } + }, + center: { + sm: { opacity: 1 }, + md: { opacity: 1 }, + lg: { opacity: 1 }, + xl: { opacity: 1 } + }, + right: { + sm: { opacity: 1, x: 0 }, + md: { opacity: 1, x: 0 }, + lg: { opacity: 1, x: 0 }, + xl: { opacity: 1, x: 0 } + } }; -const Results = ({ queryLocation, queryType, queryVrf, queryTarget, setSubmitting, ...props }) => { - const config = useConfig(); - const theme = useTheme(); - const { mediaSize } = useMedia(); - const matchedVrf = - config.vrfs.filter(v => v.id === queryVrf)[0] ?? - config.vrfs.filter(v => v.id === "default")[0]; - const [resultsComplete, setComplete] = useState(null); - return ( - <> - - - - {queryLocation && ( - <> - - - - - )} - - - - - - - {queryLocation && - queryLocation.map((loc, i) => ( - - ))} - - - - - ); +const Results = ({ + queryLocation, + queryType, + queryVrf, + queryTarget, + setSubmitting, + ...props +}) => { + const config = useConfig(); + const theme = useTheme(); + const { mediaSize } = useMedia(); + const matchedVrf = + config.vrfs.filter(v => v.id === queryVrf)[0] ?? + config.vrfs.filter(v => v.id === "default")[0]; + const [resultsComplete, setComplete] = useState(null); + return ( + <> + + + + {queryLocation && ( + <> + + + + + )} + + + + + + + {queryLocation && + queryLocation.map((loc, i) => ( + + ))} + + + + + ); }; Results.displayName = "HyperglassResults"; diff --git a/hyperglass/ui/components/SubmitButton.js b/hyperglass/ui/components/SubmitButton.js index c08265d..4435409 100644 --- a/hyperglass/ui/components/SubmitButton.js +++ b/hyperglass/ui/components/SubmitButton.js @@ -1,4 +1,5 @@ -import React from "react"; +import * as React from "react"; +import { forwardRef } from "react"; import { Box, PseudoBox, @@ -54,7 +55,11 @@ const btnSizeMap = { } }; -const SubmitButton = React.forwardRef( +const btnBg = { dark: "primary.300", light: "primary.500" }; +const btnBgActive = { dark: "primary.400", light: "primary.600" }; +const btnBgHover = { dark: "primary.200", light: "primary.400" }; + +const SubmitButton = forwardRef( ( { isLoading = false, @@ -71,18 +76,6 @@ const SubmitButton = React.forwardRef( const _isDisabled = isDisabled || isLoading; const { colorMode } = useColorMode(); const theme = useTheme(); - const btnBg = { - dark: theme.colors.primary[300], - light: theme.colors.primary[500] - }; - const btnBgActive = { - dark: theme.colors.primary[400], - light: theme.colors.primary[600] - }; - const btnBgHover = { - dark: theme.colors.primary[200], - light: theme.colors.primary[400] - }; const btnColor = opposingColor(theme, btnBg[colorMode]); const btnColorActive = opposingColor(theme, btnBgActive[colorMode]); const btnColorHover = opposingColor(theme, btnBgHover[colorMode]); @@ -126,5 +119,4 @@ const SubmitButton = React.forwardRef( } ); -SubmitButton.displayName = "SubmitButton"; export default SubmitButton; diff --git a/hyperglass/ui/components/Table.js b/hyperglass/ui/components/Table.js index 2ed42f3..651a469 100644 --- a/hyperglass/ui/components/Table.js +++ b/hyperglass/ui/components/Table.js @@ -1,24 +1,37 @@ -import React from "react"; +import * as React from "react"; import { Box, useColorMode } from "@chakra-ui/core"; -const Table = props => ; +const Table = props => ( + +); + +const bg = { light: "blackAlpha.50", dark: "whiteAlpha.50" }; const TableHeader = props => { - const { colorMode } = useColorMode(); - const bg = { light: "blackAlpha.50", dark: "whiteAlpha.50" }; - return ; + const { colorMode } = useColorMode(); + + return ( + + ); }; const TableCell = ({ isHeader = false, ...props }) => ( - + ); export { TableCell, TableHeader, Table }; diff --git a/hyperglass/ui/components/Table/TableBody.js b/hyperglass/ui/components/Table/TableBody.js index 78e0038..3f7d4c6 100644 --- a/hyperglass/ui/components/Table/TableBody.js +++ b/hyperglass/ui/components/Table/TableBody.js @@ -2,23 +2,19 @@ import { jsx } from "@emotion/core"; import { Box, css } from "@chakra-ui/core"; -const TableBody = ({ children, ...props }) => { - return ( - - {children} - - ); -}; - -TableBody.displayName = "TableBody"; +const TableBody = ({ children, ...props }) => ( + + {children} + +); export default TableBody; diff --git a/hyperglass/ui/components/Table/TableCell.js b/hyperglass/ui/components/Table/TableCell.js index 8c24022..4b8c5b0 100644 --- a/hyperglass/ui/components/Table/TableCell.js +++ b/hyperglass/ui/components/Table/TableCell.js @@ -1,19 +1,6 @@ import * as React from "react"; import { Box, useColorMode } from "@chakra-ui/core"; -// export const TableCell = styled("div")` -// ${space}; -// ${color}; -// ${justifyContent}; -// flex: 1; -// display: flex; -// min-width: 150px; -// align-items: center; -// border-bottom-width: 1px; -// overflow: hidden; -// text-overflow: ellipsis; -// `; - const cellBorder = { dark: { borderLeft: "1px", borderLeftColor: "whiteAlpha.100" }, light: { borderLeft: "1px", borderLeftColor: "blackAlpha.100" } @@ -48,6 +35,4 @@ const TableCell = ({ ); }; -TableCell.displayName = "TableCell"; - export default TableCell; diff --git a/hyperglass/ui/components/Table/TableHead.js b/hyperglass/ui/components/Table/TableHead.js index 1b49a7b..f25dac9 100644 --- a/hyperglass/ui/components/Table/TableHead.js +++ b/hyperglass/ui/components/Table/TableHead.js @@ -1,12 +1,6 @@ import * as React from "react"; import { Box, useColorMode } from "@chakra-ui/core"; -// export const TableHead = styled.div` -// ${space}; -// display: flex; -// flex-direction: row; -// `; - const bg = { dark: "whiteAlpha.100", light: "blackAlpha.100" }; const TableHead = ({ children, ...props }) => { @@ -24,6 +18,4 @@ const TableHead = ({ children, ...props }) => { ); }; -TableHead.displayName = "TableHead"; - export default TableHead; diff --git a/hyperglass/ui/components/Table/TableIconButton.js b/hyperglass/ui/components/Table/TableIconButton.js index 91eadfa..4252562 100644 --- a/hyperglass/ui/components/Table/TableIconButton.js +++ b/hyperglass/ui/components/Table/TableIconButton.js @@ -1,27 +1,6 @@ import * as React from "react"; import { IconButton } from "@chakra-ui/core"; -// export const TableIconButton = ({ icon, onClick, isDisabled, children, variantColor, ...rest }) => { -// return ( -// -// {children} -// -// ); -// }; - -// TableIconButton.defaultProps = { -// variantColor: "gray", -// }; - const TableIconButton = ({ icon, onClick, @@ -29,23 +8,19 @@ const TableIconButton = ({ color, children, ...props -}) => { - return ( - - {children} - - ); -}; - -TableIconButton.displayName = "TableIconButton"; +}) => ( + + {children} + +); export default TableIconButton; diff --git a/hyperglass/ui/components/Table/TableMain.js b/hyperglass/ui/components/Table/TableMain.js index 856630a..2567124 100644 --- a/hyperglass/ui/components/Table/TableMain.js +++ b/hyperglass/ui/components/Table/TableMain.js @@ -37,5 +37,4 @@ const MainTable = ({ children, ...props }) => { ); }; -MainTable.displayName = "MainTable"; export default MainTable; diff --git a/hyperglass/ui/components/Table/TableRow.js b/hyperglass/ui/components/Table/TableRow.js index 9447bfc..4ff1e1f 100644 --- a/hyperglass/ui/components/Table/TableRow.js +++ b/hyperglass/ui/components/Table/TableRow.js @@ -2,13 +2,6 @@ import * as React from "react"; import { PseudoBox, useColorMode, useTheme } from "@chakra-ui/core"; import { opposingColor } from "~/util"; -// export const TableRow = styled(Flex)` -// &:hover { -// cursor: pointer; -// background-color: rgba(0, 0, 0, 0.01); -// } -// `; - const hoverBg = { dark: "whiteAlpha.50", light: "blackAlpha.50" }; const bgStripe = { dark: "whiteAlpha.50", light: "blackAlpha.50" }; const rowBorder = { @@ -60,6 +53,4 @@ const TableRow = ({ ); }; -TableRow.displayName = "TableRow"; - export default TableRow; diff --git a/hyperglass/ui/components/Table/TableSelectShow.js b/hyperglass/ui/components/Table/TableSelectShow.js index b172325..eed633e 100644 --- a/hyperglass/ui/components/Table/TableSelectShow.js +++ b/hyperglass/ui/components/Table/TableSelectShow.js @@ -1,32 +1,15 @@ import * as React from "react"; import { Select } from "@chakra-ui/core"; -{ - /* + {[5, 10, 20, 30, 40, 50].map(value => ( + ))} - */ -} - -const TableSelectShow = ({ value, onChange, children, ...props }) => { - return ( - - ); -}; - -TableSelectShow.displayName = "TableSelectShow"; + {children} + +); export default TableSelectShow; diff --git a/hyperglass/ui/components/Table/index.js b/hyperglass/ui/components/Table/index.js index b50c894..605005d 100644 --- a/hyperglass/ui/components/Table/index.js +++ b/hyperglass/ui/components/Table/index.js @@ -194,6 +194,4 @@ const Table = ({ ); }; -Table.displayName = "Table"; - export default Table; diff --git a/hyperglass/ui/components/TextOutput.js b/hyperglass/ui/components/TextOutput.js index 093032d..6e37d40 100644 --- a/hyperglass/ui/components/TextOutput.js +++ b/hyperglass/ui/components/TextOutput.js @@ -40,5 +40,4 @@ const TextOutput = ({ children, ...props }) => { ); }; -TextOutput.displayName = "TextOutput"; export default TextOutput; diff --git a/hyperglass/ui/components/Title.js b/hyperglass/ui/components/Title.js index 86e9c8d..9b603da 100644 --- a/hyperglass/ui/components/Title.js +++ b/hyperglass/ui/components/Title.js @@ -1,49 +1,48 @@ -import React from "react"; +/** @jsx jsx */ +import { jsx } from "@emotion/core"; +import { forwardRef } from "react"; import { Button, Heading, Image, Stack, useColorMode } from "@chakra-ui/core"; -import { Textfit } from "react-textfit"; -import { motion, AnimatePresence } from "framer-motion"; import useConfig from "~/components/HyperglassProvider"; import useMedia from "~/components/MediaProvider"; -const subtitleAnimation = { - transition: { duration: 0.2, type: "tween" }, - initial: { opacity: 1, scale: 1 }, - animate: { opacity: 1, scale: 1 }, - exit: { opacity: 0, scale: 0.3 } -}; -const titleSize = { true: "2xl", false: "lg" }; +const titleSize = { true: ["2xl", "2xl", "5xl", "5xl"], false: "2xl" }; const titleMargin = { true: 2, false: 0 }; const textAlignment = { false: ["right", "center"], true: ["left", "center"] }; +const logoName = { light: "dark", dark: "light" }; +const justifyMap = { + true: ["flex-end", "center", "center", "center"], + false: ["flex-start", "center", "center", "center"] +}; + +const logoFallback = { + light: + "https://res.cloudinary.com/hyperglass/image/upload/v1593916013/logo-dark.svg", + dark: + "https://res.cloudinary.com/hyperglass/image/upload/v1593916013/logo-light.svg" +}; const TitleOnly = ({ text, showSubtitle }) => ( - {text} + {text} ); -const SubtitleOnly = React.forwardRef( - ({ text, mediaSize, size = "md", ...props }, ref) => ( - - - {text} - - - ) +const SubtitleOnly = ({ text, mediaSize, ...props }) => ( + + {text} + ); -const AnimatedSubtitle = motion.custom(SubtitleOnly); - const TextOnly = ({ text, mediaSize, showSubtitle, ...props }) => ( ( textAlign={textAlignment[showSubtitle]} {...props} > - - - - - {showSubtitle && ( - - )} - + + {showSubtitle && ( + + )} ); const Logo = ({ text, logo }) => { const { colorMode } = useColorMode(); - const logoExt = { light: logo.dark_format, dark: logo.light_format }; - const logoName = { light: "dark", dark: "light" }; + const { width, dark_format, light_format } = logo; + const logoExt = { light: dark_format, dark: light_format }; return ( {text.title} ); }; -const LogoSubtitle = ({ text, logo, showSubtitle, mediaSize }) => ( +const LogoSubtitle = ({ text, logo, mediaSize }) => ( <> - - {showSubtitle && ( - - )} - + ); @@ -108,12 +104,8 @@ const modeMap = { logo_subtitle: LogoSubtitle, all: All }; -const justifyMap = { - true: ["flex-end", "center", "center", "center"], - false: ["flex-start", "center", "center", "center"] -}; -const Title = React.forwardRef(({ onClick, isSubmitting, ...props }, ref) => { +const Title = forwardRef(({ onClick, isSubmitting, ...props }, ref) => { const { web } = useConfig(); const { mediaSize } = useMedia(); const titleMode = web.text.title_mode; @@ -143,5 +135,4 @@ const Title = React.forwardRef(({ onClick, isSubmitting, ...props }, ref) => { ); }); -Title.displayName = "Title"; export default Title; diff --git a/hyperglass/ui/components/icons/LightningBolt.js b/hyperglass/ui/components/icons/LightningBolt.js index 29d40d6..8d04976 100644 --- a/hyperglass/ui/components/icons/LightningBolt.js +++ b/hyperglass/ui/components/icons/LightningBolt.js @@ -2,24 +2,22 @@ import * as React from "react"; import { useTheme } from "@chakra-ui/core"; const LightningBolt = ({ size = 4, color = "currentColor" }) => { - const theme = useTheme(); - return ( - - - - ); + const theme = useTheme(); + return ( + + + + ); }; -LightningBolt.displayName = "LightningBolt"; - export default LightningBolt; diff --git a/hyperglass/ui/components/useConfig.js b/hyperglass/ui/components/useConfig.js deleted file mode 100644 index 3b5c7d2..0000000 --- a/hyperglass/ui/components/useConfig.js +++ /dev/null @@ -1,6 +0,0 @@ -import { useMemo } from "react"; -import config from "~/frontend.json"; - -export default () => useMemo(() => config); - -export const useConfig = cfg => useMemo(() => cfg); diff --git a/hyperglass/ui/hooks/useColored.js b/hyperglass/ui/hooks/useColored.js deleted file mode 100644 index d6ff52e..0000000 --- a/hyperglass/ui/hooks/useColored.js +++ /dev/null @@ -1,4 +0,0 @@ -import { useMemo } from "react"; - -export default (mode = "light", light = "black", dark = "white") => - useMemo(() => (mode ? light : dark)); diff --git a/hyperglass/ui/package.json b/hyperglass/ui/package.json index ece12c3..575a7b5 100644 --- a/hyperglass/ui/package.json +++ b/hyperglass/ui/package.json @@ -15,7 +15,7 @@ }, "browserslist": "> 0.25%, not dead", "dependencies": { - "@chakra-ui/core": "^0.7.0", + "@chakra-ui/core": "^0.8", "@emotion/core": "^10.0.28", "@emotion/styled": "^10.0.27", "@styled-system/should-forward-prop": "^5.1.5", @@ -28,17 +28,16 @@ "framer-motion": "^1.10.0", "html-to-react": "^1.4.3", "lodash": "^4.17.15", - "next": "^9.3.1", + "next": "^9.4", "react": "^16.13.1", "react-countdown": "^2.2.1", "react-dom": "^16.13.1", - "react-hook-form": "^5.1.1", + "react-hook-form": "^5.7", "react-icons": "^3.9.0", "react-markdown": "^4.3.1", "react-select": "^3.0.8", "react-string-replace": "^0.4.4", "react-table": "^7.0.4", - "react-textfit": "^1.1.0", "string-format": "^2.0.0", "styled-system": "^5.1.5", "tempy": "^0.5.0", diff --git a/hyperglass/ui/yarn.lock b/hyperglass/ui/yarn.lock index 16a3a3d..fae7f55 100644 --- a/hyperglass/ui/yarn.lock +++ b/hyperglass/ui/yarn.lock @@ -1015,22 +1015,22 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@chakra-ui/core@^0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/core/-/core-0.7.0.tgz#5066201cecacc6c48993c8d655f5d85f5da10c2e" - integrity sha512-Ph6y9ds7ejuAom7imEwEEhYqTz3EM23mYuRu5qtZxF6b2tvAVbTZ2CjecaUbwZbCVxxiAVCkC2O+cWokeqBEDA== +"@chakra-ui/core@^0.8": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/core/-/core-0.8.0.tgz#a377286becd86008448ec8cf29ceb8fc301ac2dc" + integrity sha512-il1I1nEWOmWJSspnC+WyArLHbHvs82hvKTNDd24wr6spa/7v2jaXFZeWDNenY35ay1NHV7Ya2StcBwQRGHMWYA== dependencies: - "@reach/auto-id" "0.9.0" + "@reach/auto-id" "0.10.2" "@styled-system/css" "5.1.5" "@styled-system/should-forward-prop" "5.1.5" "@types/styled-system" "5.1.9" aria-hidden "^1.1.1" - body-scroll-lock "^2.6.4" + body-scroll-lock "^3.0.1" color "3.1.2" copy-to-clipboard "3.3.1" exenv "^1.2.2" popper.js "^1.15.0" - react-animate-height "2.0.20" + react-animate-height "2.0.21" react-focus-lock "^2.2.1" react-spring "^8.0.27" styled-system "5.1.5" @@ -1504,25 +1504,26 @@ "@reach/component-component" "^0.1.3" "@reach/visually-hidden" "^0.1.4" -"@reach/auto-id@0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.9.0.tgz#73b5d34bcf432f3e73b235b9dcaa89ea05a0d4db" - integrity sha512-9/aXl+dT0pOenvpkB2kkmQnpMDlmSk8ZkBYmYFzFz3eA4PZFNuXcHVzQevFRhc0HVlskPjxwPNf92EkI9rdFOw== +"@reach/auto-id@0.10.2": + version "0.10.2" + resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.10.2.tgz#a447af67241123dcb701ecd61931a2c786ed111e" + integrity sha512-PWFZevkHshiJV/z0L/5WQkWhe9QRzdZqC7N/JHRCoYo+odvCz9izXVRsxJf7p4sCuOCvnc8zNzAokFk2E1ZzDg== dependencies: - "@reach/utils" "^0.9.0" - tslib "^1.10.0" + "@reach/utils" "^0.10.2" + tslib "^1.11.2" "@reach/component-component@^0.1.3": version "0.1.3" resolved "https://registry.yarnpkg.com/@reach/component-component/-/component-component-0.1.3.tgz#5d156319572dc38995b246f81878bc2577c517e5" integrity sha512-a1USH7L3bEfDdPN4iNZGvMEFuBfkdG+QNybeyDv8RloVFgZYRoM+KGXyy2KOfEnTUM8QWDRSROwaL3+ts5Angg== -"@reach/utils@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.9.0.tgz#ee47c25c79eb2f98e6c0e728a2672075cc9991d5" - integrity sha512-cmiykRaxuCysVTsSY3PgrLjySnEIt1PLiSYKh5rAH8nYyEmaOCtw0vaNItFAiqQIjfrxkixmcUE8dyD8kqVuJA== +"@reach/utils@^0.10.2": + version "0.10.5" + resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.10.5.tgz#fbac944d29565f6dd7abd0e1b13950e99b1e470b" + integrity sha512-5E/xxQnUbmpI/LrufBAOXjunl96DnqX6B4zC2MO2KH/dRzLug5gM5VuOwV26egsp0jvsSPxojwciOhS43px3qw== dependencies: - tslib "^1.10.0" + "@types/warning" "^3.0.0" + tslib "^2.0.0" warning "^4.0.3" "@reach/visually-hidden@^0.1.4": @@ -1691,6 +1692,11 @@ dependencies: csstype "^2.6.9" +"@types/warning@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52" + integrity sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI= + "@typescript-eslint/eslint-plugin@^2.24.0": version "2.34.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz#6f8ce8a46c7dea4a6f1d171d2bb8fbae6dac2be9" @@ -2438,10 +2444,10 @@ body-parser@1.19.0: raw-body "2.4.0" type-is "~1.6.17" -body-scroll-lock@^2.6.4: - version "2.7.1" - resolved "https://registry.yarnpkg.com/body-scroll-lock/-/body-scroll-lock-2.7.1.tgz#caf3f9c91773af1ffb684cd66ed9137b5b737014" - integrity sha512-hS53SQ8RhM0e4DsQ3PKz6Gr2O7Kpdh59TWU98GHjaQznL7y4dFycEPk7pFQAikqBaUSCArkc5E3pe7CWIt2fZA== +body-scroll-lock@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/body-scroll-lock/-/body-scroll-lock-3.0.3.tgz#221d87435bcfb50e27ab5d4508735f622aed11a2" + integrity sha512-EUryImgD6Gv87HOjJB/yB2WIGECiZMhmcUK+DrqVRFDDa64xR+FsK0LgvLPnBxZDTxIl+W80/KJ8i6gp2IwOHQ== boolbase@^1.0.0, boolbase@~1.0.0: version "1.0.0" @@ -6232,7 +6238,7 @@ next-tick@~1.0.0: resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= -next@^9.3.1: +next@^9.4: version "9.4.4" resolved "https://registry.yarnpkg.com/next/-/next-9.4.4.tgz#02ad9fea7f7016b6b42fc83b67835e4a0dd0c99a" integrity sha512-ZT8bU2SAv5jkFQ+y8py+Rl5RJRJ6DnZDS+VUnB1cIscmtmUhDi7LYED7pYm4MCKkYhPbEEM1Lbpo7fnoZJGWNQ== @@ -7320,7 +7326,7 @@ process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -process@^0.11.10, process@^0.11.9: +process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= @@ -7349,7 +7355,7 @@ prop-types-exact@1.2.0: object.assign "^4.1.0" reflect.ownkeys "^0.2.0" -prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@15.7.2, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -7518,10 +7524,10 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-animate-height@2.0.20: - version "2.0.20" - resolved "https://registry.yarnpkg.com/react-animate-height/-/react-animate-height-2.0.20.tgz#e519c33a41cb39c071e8115bb3c4f9daad6c703f" - integrity sha512-gs6j9oSiWNAnquEVpPMdTe/kwsdVORkRYsgPju4VfM1wKwai7pdmwob//1ECmCQTD8S0NfRDDBk0l7MJGFNmbw== +react-animate-height@2.0.21: + version "2.0.21" + resolved "https://registry.yarnpkg.com/react-animate-height/-/react-animate-height-2.0.21.tgz#da9223eb0e74457d52f72da477c8626550df2ce6" + integrity sha512-CZHdjMD8qqp10tYtWmauWYASXxxv9vYeljxFGFtbcrbNXhsUv0w3IjxVK+0yCnyfk7769WfMZKHra4vRcbMnQg== dependencies: classnames "^2.2.5" prop-types "^15.6.1" @@ -7562,7 +7568,7 @@ react-focus-lock@^2.2.1: use-callback-ref "^1.2.1" use-sidecar "^1.0.1" -react-hook-form@^5.1.1: +react-hook-form@^5.7: version "5.7.2" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-5.7.2.tgz#a84e259e5d37dd30949af4f79c4dac31101b79ac" integrity sha512-bJvY348vayIvEUmSK7Fvea/NgqbT2racA2IbnJz/aPlQ3GBtaTeDITH6rtCa6y++obZzG6E3Q8VuoXPir7QYUg== @@ -7641,14 +7647,6 @@ react-table@^7.0.4: dependencies: "@scarf/scarf" "^1.0.4" -react-textfit@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/react-textfit/-/react-textfit-1.1.0.tgz#088855580f2e7aad269efc81b734bf636877d0e1" - integrity sha512-iznFbj7fCizuo3Xof9iv57I8GZFiYp8vUFj+4qihHJZpzNwxWad7JZu7ALTAnwaiq/H0p60g8G4ifeEJYmfJuw== - dependencies: - process "^0.11.9" - prop-types "^15.5.10" - react-transition-group@^4.3.0: version "4.4.1" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" @@ -9109,11 +9107,16 @@ tsconfig-paths@^3.9.0: minimist "^1.2.0" strip-bom "^3.0.0" -tslib@^1.0.0, tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.0.0, tslib@^1.10.0, tslib@^1.11.2, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.13.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== +tslib@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3" + integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g== + tsutils@^3.17.1: version "3.17.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"