mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
restructure components & clean up unused code [skip ci]
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Button, Flex, Link, HStack, useToken } from '@chakra-ui/react';
|
||||
import { If, ColorModeToggle } from '~/components';
|
||||
import { Button, Flex, Link, Icon, HStack, useToken } from '@chakra-ui/react';
|
||||
import { If } from '~/components';
|
||||
import { useConfig, useMobile, useColorValue, useBreakpointValue } from '~/context';
|
||||
import { useStrf } from '~/hooks';
|
||||
import { FooterButton } from './button';
|
||||
import { ColorModeToggle } from './colorMode';
|
||||
|
||||
const CodeIcon = dynamic<MeronexIcon>(() => import('@meronex/icons/fi').then(i => i.FiCode));
|
||||
const ExtIcon = dynamic<MeronexIcon>(() => import('@meronex/icons/go').then(i => i.GoLinkExternal));
|
||||
@@ -52,7 +53,11 @@ export const Footer = () => {
|
||||
</If>
|
||||
{!isMobile && <Flex p={0} flex="0 0 auto" maxWidth="100%" mr="auto" />}
|
||||
<If c={web.credit.enable}>
|
||||
<FooterButton side="right" content={content.credit} title={<CodeIcon />} />
|
||||
<FooterButton
|
||||
side="right"
|
||||
content={content.credit}
|
||||
title={<Icon as={CodeIcon} boxSize={size} />}
|
||||
/>
|
||||
</If>
|
||||
<ColorModeToggle size={size} />
|
||||
</HStack>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { MenuListProps } from '@chakra-ui/react';
|
||||
import type { ButtonProps, MenuListProps } from '@chakra-ui/react';
|
||||
|
||||
type TFooterSide = 'left' | 'right';
|
||||
|
||||
@@ -9,3 +9,7 @@ export interface TFooterButton extends Omit<MenuListProps, 'title'> {
|
||||
}
|
||||
|
||||
export type TFooterItems = 'help' | 'credit' | 'terms';
|
||||
|
||||
export interface TColorModeToggle extends ButtonProps {
|
||||
size?: string;
|
||||
}
|
||||
|
@@ -1,251 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import { forwardRef, useState, useEffect } from 'react';
|
||||
import { Box, Flex } from '@chakra-ui/core';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { intersectionWith, isEqual } from 'lodash';
|
||||
import * as yup from 'yup';
|
||||
import format from 'string-format';
|
||||
import {
|
||||
FormField,
|
||||
HelpModal,
|
||||
QueryLocation,
|
||||
QueryType,
|
||||
QueryTarget,
|
||||
CommunitySelect,
|
||||
QueryVrf,
|
||||
ResolvedTarget,
|
||||
SubmitButton,
|
||||
} from 'app/components';
|
||||
import { useConfig } from 'app/context';
|
||||
|
||||
format.extend(String.prototype, {});
|
||||
|
||||
const formSchema = config =>
|
||||
yup.object().shape({
|
||||
query_location: yup
|
||||
.array()
|
||||
.of(yup.string())
|
||||
.required(
|
||||
config.messages.no_input.format({
|
||||
field: config.web.text.query_location,
|
||||
}),
|
||||
),
|
||||
query_type: yup
|
||||
.string()
|
||||
.required(config.messages.no_input.format({ field: config.web.text.query_type })),
|
||||
query_vrf: yup.string(),
|
||||
query_target: yup
|
||||
.string()
|
||||
.required(config.messages.no_input.format({ field: config.web.text.query_target })),
|
||||
});
|
||||
|
||||
const FormRow = ({ children, ...props }) => (
|
||||
<Flex
|
||||
flexDirection="row"
|
||||
flexWrap="wrap"
|
||||
w="100%"
|
||||
justifyContent={['center', 'center', 'space-between', 'space-between']}
|
||||
{...props}>
|
||||
{children}
|
||||
</Flex>
|
||||
);
|
||||
|
||||
export const HyperglassForm = forwardRef(
|
||||
({ isSubmitting, setSubmitting, setFormData, greetingAck, setGreetingAck, ...props }, ref) => {
|
||||
const config = useConfig();
|
||||
const { handleSubmit, register, unregister, setValue, errors } = useForm({
|
||||
validationSchema: formSchema(config),
|
||||
defaultValues: { query_vrf: 'default', query_target: '' },
|
||||
});
|
||||
|
||||
const [queryLocation, setQueryLocation] = useState([]);
|
||||
const [queryType, setQueryType] = useState('');
|
||||
const [queryVrf, setQueryVrf] = useState('');
|
||||
const [queryTarget, setQueryTarget] = useState('');
|
||||
const [availVrfs, setAvailVrfs] = useState([]);
|
||||
const [fqdnTarget, setFqdnTarget] = useState('');
|
||||
const [displayTarget, setDisplayTarget] = useState('');
|
||||
const [families, setFamilies] = useState([]);
|
||||
const onSubmit = values => {
|
||||
if (!greetingAck && config.web.greeting.required) {
|
||||
window.location.reload(false);
|
||||
setGreetingAck(false);
|
||||
} else {
|
||||
setFormData(values);
|
||||
setSubmitting(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleLocChange = locObj => {
|
||||
setQueryLocation(locObj.value);
|
||||
const allVrfs = [];
|
||||
const deviceVrfs = [];
|
||||
locObj.value.map(loc => {
|
||||
const locVrfs = [];
|
||||
config.devices[loc].vrfs.map(vrf => {
|
||||
locVrfs.push({
|
||||
label: vrf.display_name,
|
||||
value: vrf.id,
|
||||
});
|
||||
deviceVrfs.push([{ id: vrf.id, ipv4: vrf.ipv4, ipv6: vrf.ipv6 }]);
|
||||
});
|
||||
allVrfs.push(locVrfs);
|
||||
});
|
||||
|
||||
const intersecting = intersectionWith(...allVrfs, isEqual);
|
||||
setAvailVrfs(intersecting);
|
||||
!intersecting.includes(queryVrf) && queryVrf !== 'default' && setQueryVrf('default');
|
||||
|
||||
let ipv4 = 0;
|
||||
let ipv6 = 0;
|
||||
deviceVrfs.length !== 0 &&
|
||||
intersecting.length !== 0 &&
|
||||
deviceVrfs
|
||||
.filter(v => intersecting.every(i => i.id === v.id))
|
||||
.reduce((a, b) => a.concat(b))
|
||||
.filter(v => v.id === 'default')
|
||||
.map(v => {
|
||||
v.ipv4 === true && ipv4++;
|
||||
v.ipv6 === true && ipv6++;
|
||||
});
|
||||
if (ipv4 !== 0 && ipv4 === ipv6) {
|
||||
setFamilies([4, 6]);
|
||||
} else if (ipv4 > ipv6) {
|
||||
setFamilies([4]);
|
||||
} else if (ipv4 < ipv6) {
|
||||
setFamilies([6]);
|
||||
} else {
|
||||
setFamilies([]);
|
||||
}
|
||||
};
|
||||
|
||||
const handleChange = e => {
|
||||
setValue(e.field, e.value);
|
||||
e.field === 'query_location'
|
||||
? handleLocChange(e)
|
||||
: e.field === 'query_type'
|
||||
? setQueryType(e.value)
|
||||
: e.field === 'query_vrf'
|
||||
? setQueryVrf(e.value)
|
||||
: e.field === 'query_target'
|
||||
? setQueryTarget(e.value)
|
||||
: null;
|
||||
};
|
||||
|
||||
const vrfContent = config.content.vrf[queryVrf]?.[queryType];
|
||||
|
||||
const validFqdnQueryType =
|
||||
['ping', 'traceroute', 'bgp_route'].includes(queryType) &&
|
||||
fqdnTarget &&
|
||||
queryVrf === 'default'
|
||||
? fqdnTarget
|
||||
: null;
|
||||
|
||||
useEffect(() => {
|
||||
register({ name: 'query_location' });
|
||||
register({ name: 'query_type' });
|
||||
register({ name: 'query_vrf' });
|
||||
}, [register]);
|
||||
Object.keys(errors).length >= 1 && console.error(errors);
|
||||
return (
|
||||
<Box
|
||||
as="form"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
maxW={['100%', '100%', '75%', '75%']}
|
||||
w="100%"
|
||||
p={0}
|
||||
mx="auto"
|
||||
my={4}
|
||||
textAlign="left"
|
||||
ref={ref}
|
||||
{...props}>
|
||||
<FormRow>
|
||||
<FormField
|
||||
label={config.web.text.query_location}
|
||||
name="query_location"
|
||||
error={errors.query_location}>
|
||||
<QueryLocation
|
||||
onChange={handleChange}
|
||||
locations={config.networks}
|
||||
label={config.web.text.query_location}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField
|
||||
label={config.web.text.query_type}
|
||||
name="query_type"
|
||||
error={errors.query_type}
|
||||
labelAddOn={vrfContent && <HelpModal item={vrfContent} name="query_type" />}>
|
||||
<QueryType
|
||||
onChange={handleChange}
|
||||
queryTypes={config.queries.list}
|
||||
label={config.web.text.query_type}
|
||||
/>
|
||||
</FormField>
|
||||
</FormRow>
|
||||
<FormRow>
|
||||
{availVrfs.length > 1 && (
|
||||
<FormField label={config.web.text.query_vrf} name="query_vrf" error={errors.query_vrf}>
|
||||
<QueryVrf
|
||||
label={config.web.text.query_vrf}
|
||||
vrfs={availVrfs}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</FormField>
|
||||
)}
|
||||
<FormField
|
||||
label={config.web.text.query_target}
|
||||
name="query_target"
|
||||
error={errors.query_target}
|
||||
fieldAddOn={
|
||||
queryLocation.length !== 0 &&
|
||||
validFqdnQueryType && (
|
||||
<ResolvedTarget
|
||||
queryTarget={queryTarget}
|
||||
fqdnTarget={validFqdnQueryType}
|
||||
setTarget={handleChange}
|
||||
families={families}
|
||||
availVrfs={availVrfs}
|
||||
/>
|
||||
)
|
||||
}>
|
||||
{queryType === 'bgp_community' && config.queries.bgp_community.mode === 'select' ? (
|
||||
<CommunitySelect
|
||||
label={config.queries.bgp_community.display_name}
|
||||
name="query_target"
|
||||
register={register}
|
||||
unregister={unregister}
|
||||
onChange={handleChange}
|
||||
communities={config.queries.bgp_community.communities}
|
||||
/>
|
||||
) : (
|
||||
<QueryTarget
|
||||
name="query_target"
|
||||
placeholder={config.web.text.query_target}
|
||||
register={register}
|
||||
unregister={unregister}
|
||||
resolveTarget={['ping', 'traceroute', 'bgp_route'].includes(queryType)}
|
||||
value={queryTarget}
|
||||
setFqdn={setFqdnTarget}
|
||||
setTarget={handleChange}
|
||||
displayValue={displayTarget}
|
||||
setDisplayValue={setDisplayTarget}
|
||||
/>
|
||||
)}
|
||||
</FormField>
|
||||
</FormRow>
|
||||
<FormRow mt={0} justifyContent="flex-end">
|
||||
<Flex
|
||||
w="100%"
|
||||
maxW="100%"
|
||||
ml="auto"
|
||||
my={2}
|
||||
mr={[0, 0, 2, 2]}
|
||||
flexDirection="column"
|
||||
flex="0 0 0">
|
||||
<SubmitButton isLoading={isSubmitting} />
|
||||
</Flex>
|
||||
</FormRow>
|
||||
</Box>
|
||||
);
|
||||
},
|
||||
);
|
@@ -1,6 +0,0 @@
|
||||
export * from './colorMode';
|
||||
export * from './copy';
|
||||
export * from './path';
|
||||
export * from './requery';
|
||||
export * from './reset';
|
||||
export * from './submit';
|
@@ -1,25 +0,0 @@
|
||||
import { forwardRef } from 'react';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Button, Icon } from '@chakra-ui/react';
|
||||
import { useLGState } from '~/hooks';
|
||||
|
||||
import type { ButtonProps } from '@chakra-ui/react';
|
||||
|
||||
const ChevronLeft = dynamic<MeronexIcon>(() =>
|
||||
import('@meronex/icons/fi').then(i => i.FiChevronLeft),
|
||||
);
|
||||
|
||||
export const ResetButton = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
|
||||
const { isSubmitting } = useLGState();
|
||||
return (
|
||||
<Button
|
||||
ref={ref}
|
||||
color="current"
|
||||
variant="ghost"
|
||||
aria-label="Reset Form"
|
||||
opacity={isSubmitting.value ? 1 : 0}
|
||||
{...props}>
|
||||
<Icon as={ChevronLeft} boxSize={8} />
|
||||
</Button>
|
||||
);
|
||||
});
|
@@ -1,29 +0,0 @@
|
||||
import type { IconButtonProps, ButtonProps } from '@chakra-ui/react';
|
||||
import type { OnChangeArgs } from '~/types';
|
||||
|
||||
export interface TCopyButton extends ButtonProps {
|
||||
copyValue: string;
|
||||
}
|
||||
|
||||
export interface TColorModeToggle extends ButtonProps {
|
||||
size?: string;
|
||||
}
|
||||
|
||||
export interface TSubmitButton extends Omit<IconButtonProps, 'aria-label'> {
|
||||
handleChange(e: OnChangeArgs): void;
|
||||
}
|
||||
|
||||
export interface TRequeryButton extends ButtonProps {
|
||||
requery(): void;
|
||||
}
|
||||
|
||||
export interface TRSubmitButton {
|
||||
isOpen: boolean;
|
||||
onClose(): void;
|
||||
onChange(e: OnChangeArgs): void;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export interface TPathButton {
|
||||
onOpen(): void;
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
import { createContext, useContext } from 'react';
|
||||
import { createState, useState } from '@hookstate/core';
|
||||
import type { THeaderCtx, THeaderState } from './types';
|
||||
|
||||
const HeaderCtx = createContext<THeaderCtx>({
|
||||
showSubtitle: true,
|
||||
titleRef: {} as React.MutableRefObject<HTMLHeadingElement>,
|
||||
});
|
||||
|
||||
export const HeaderProvider = HeaderCtx.Provider;
|
||||
export const useHeaderCtx = (): THeaderCtx => useContext(HeaderCtx);
|
||||
|
||||
const HeaderState = createState<THeaderState>({ fontSize: '' });
|
||||
export const useHeader = () => useState<THeaderState>(HeaderState);
|
@@ -1,9 +1,7 @@
|
||||
import { useRef } from 'react';
|
||||
import { Flex, ScaleFade } from '@chakra-ui/react';
|
||||
import { ColorModeToggle } from '~/components';
|
||||
import { useColorValue, useBreakpointValue } from '~/context';
|
||||
import { useBooleanValue, useLGState } from '~/hooks';
|
||||
import { HeaderProvider } from './context';
|
||||
import { Title } from './title';
|
||||
|
||||
import type { THeader } from './types';
|
||||
@@ -26,35 +24,28 @@ export const Header = (props: THeader) => {
|
||||
const justify = useBreakpointValue({ base: 'flex-start', lg: 'center' });
|
||||
|
||||
return (
|
||||
<HeaderProvider value={{ showSubtitle: !isSubmitting.value, titleRef }}>
|
||||
<Flex
|
||||
px={4}
|
||||
pt={6}
|
||||
bg={bg}
|
||||
minH={16}
|
||||
zIndex={4}
|
||||
as="header"
|
||||
width="full"
|
||||
flex="0 1 auto"
|
||||
color="gray.500"
|
||||
{...rest}>
|
||||
<ScaleFade in initialScale={0.5} style={{ width: '100%' }}>
|
||||
<Flex
|
||||
d="flex"
|
||||
key="title"
|
||||
height="100%"
|
||||
ref={titleRef}
|
||||
mx={{ base: 0, lg: 'auto' }}
|
||||
maxW={titleWidth}
|
||||
// This is here for the logo
|
||||
justifyContent={justify}>
|
||||
<Title />
|
||||
</Flex>
|
||||
</ScaleFade>
|
||||
{/* <Flex pos="absolute" right={0} top={0} m={4}>
|
||||
<ColorModeToggle />
|
||||
</Flex> */}
|
||||
</Flex>
|
||||
</HeaderProvider>
|
||||
<Flex
|
||||
px={4}
|
||||
pt={6}
|
||||
bg={bg}
|
||||
minH={16}
|
||||
zIndex={4}
|
||||
as="header"
|
||||
width="full"
|
||||
flex="0 1 auto"
|
||||
color="gray.500"
|
||||
{...rest}>
|
||||
<ScaleFade in initialScale={0.5} style={{ width: '100%' }}>
|
||||
<Flex
|
||||
height="100%"
|
||||
ref={titleRef}
|
||||
maxW={titleWidth}
|
||||
// This is here for the logo
|
||||
justifyContent={justify}
|
||||
mx={{ base: 0, lg: 'auto' }}>
|
||||
<Title />
|
||||
</Flex>
|
||||
</ScaleFade>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
@@ -5,7 +5,6 @@ import { useConfig, useMobile } from '~/context';
|
||||
import { useBooleanValue, useLGState } from '~/hooks';
|
||||
import { Logo } from './logo';
|
||||
import { TitleOnly } from './titleOnly';
|
||||
import { useHeaderCtx } from './context';
|
||||
import { SubtitleOnly } from './subtitleOnly';
|
||||
|
||||
import type { StackProps } from '@chakra-ui/react';
|
||||
@@ -22,13 +21,13 @@ const MWrapper = (props: StackProps) => <VStack spacing={1} alignItems="flex-sta
|
||||
* Title wrapper for desktop devices, breakpoints lg & xl.
|
||||
*/
|
||||
const DWrapper = (props: TDWrapper) => {
|
||||
const { showSubtitle } = useHeaderCtx();
|
||||
const { isSubmitting } = useLGState();
|
||||
return (
|
||||
<AnimatedVStack
|
||||
spacing={1}
|
||||
initial="main"
|
||||
alignItems="center"
|
||||
animate={showSubtitle ? 'main' : 'submitting'}
|
||||
animate={isSubmitting.value ? 'submitting' : 'main'}
|
||||
transition={{ damping: 15, type: 'spring', stiffness: 100 }}
|
||||
variants={{ submitting: { scale: 0.5 }, main: { scale: 1 } }}
|
||||
{...props}
|
||||
|
@@ -1,14 +1,13 @@
|
||||
import { Heading } from '@chakra-ui/react';
|
||||
import { useConfig } from '~/context';
|
||||
import { useBooleanValue } from '~/hooks';
|
||||
import { useHeaderCtx } from './context';
|
||||
import { useBooleanValue, useLGState } from '~/hooks';
|
||||
import { useTitleSize } from './useTitleSize';
|
||||
|
||||
export const TitleOnly = () => {
|
||||
const { showSubtitle } = useHeaderCtx();
|
||||
const { web } = useConfig();
|
||||
const { isSubmitting } = useLGState();
|
||||
|
||||
const margin = useBooleanValue(showSubtitle, 2, 0);
|
||||
const margin = useBooleanValue(isSubmitting.value, 0, 2);
|
||||
const sizeSm = useTitleSize(web.text.title, '2xl', []);
|
||||
|
||||
return (
|
||||
|
@@ -25,7 +25,3 @@ export interface THeaderCtx {
|
||||
showSubtitle: boolean;
|
||||
titleRef: React.MutableRefObject<HTMLHeadingElement>;
|
||||
}
|
||||
|
||||
export interface THeaderState {
|
||||
fontSize: string;
|
||||
}
|
||||
|
@@ -1,4 +1,3 @@
|
||||
export * from './buttons';
|
||||
export * from './card';
|
||||
export * from './codeBlock';
|
||||
export * from './countdown';
|
||||
@@ -18,5 +17,6 @@ export * from './output';
|
||||
export * from './path';
|
||||
export * from './results';
|
||||
export * from './select';
|
||||
export * from './submit';
|
||||
export * from './table';
|
||||
export * from './util';
|
||||
|
@@ -15,7 +15,7 @@ export const Chart = (props: TChart) => {
|
||||
const { data } = props;
|
||||
const { primary_asn, org_name } = useConfig();
|
||||
|
||||
const dots = useColorToken('blackAlpha.500', 'whiteAlpha.400');
|
||||
const dots = useColorToken('colors', 'blackAlpha.500', 'whiteAlpha.400');
|
||||
|
||||
const flowProps = useBreakpointValue<Omit<ReactFlowProps, 'elements'>>({
|
||||
base: { defaultPosition: [0, 300], defaultZoom: 0 },
|
||||
|
@@ -8,9 +8,9 @@ import {
|
||||
Skeleton,
|
||||
ModalCloseButton,
|
||||
} from '@chakra-ui/react';
|
||||
import { PathButton } from '~/components';
|
||||
import { useColorValue } from '~/context';
|
||||
import { useLGState } from '~/hooks';
|
||||
import { PathButton } from './button';
|
||||
import { Chart } from './chart';
|
||||
|
||||
import type { TPath } from './types';
|
||||
|
@@ -23,3 +23,7 @@ export interface BasePath {
|
||||
asn: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface TPathButton {
|
||||
onOpen(): void;
|
||||
}
|
||||
|
@@ -12,11 +12,13 @@ import {
|
||||
import { motion } from 'framer-motion';
|
||||
import { BsLightningFill } from '@meronex/icons/bs';
|
||||
import { startCase } from 'lodash';
|
||||
import { BGPTable, Countdown, CopyButton, RequeryButton, TextOutput, If, Path } from '~/components';
|
||||
import { BGPTable, Countdown, TextOutput, If, Path } from '~/components';
|
||||
import { useColorValue, useConfig, useMobile } from '~/context';
|
||||
import { useStrf, useLGQuery, useLGState, useTableToString } from '~/hooks';
|
||||
import { isStructuredOutput, isStringOutput } from '~/types';
|
||||
import { isStackError, isFetchError, isLGError } from './guards';
|
||||
import { RequeryButton } from './requeryButton';
|
||||
import { CopyButton } from './copyButton';
|
||||
import { FormattedError } from './error';
|
||||
import { ResultHeader } from './header';
|
||||
|
||||
|
@@ -18,7 +18,7 @@ export const RequeryButton = forwardRef<HTMLButtonElement, TRequeryButton>((prop
|
||||
size="sm"
|
||||
zIndex="1"
|
||||
variant="ghost"
|
||||
onClick={requery}
|
||||
onClick={requery as TRequeryButton['onClick']}
|
||||
colorScheme="secondary"
|
||||
{...rest}>
|
||||
<Icon as={Repeat} boxSize="16px" />
|
@@ -1,4 +1,5 @@
|
||||
import type { FlexProps } from '@chakra-ui/react';
|
||||
import type { ButtonProps, FlexProps } from '@chakra-ui/react';
|
||||
import type { QueryResultBase } from 'react-query';
|
||||
import type { TDevice, TQueryTypes } from '~/types';
|
||||
|
||||
export interface TResultHeader {
|
||||
@@ -31,3 +32,11 @@ export interface TResult {
|
||||
}
|
||||
|
||||
export type TErrorLevels = 'success' | 'warning' | 'error';
|
||||
|
||||
export interface TCopyButton extends ButtonProps {
|
||||
copyValue: string;
|
||||
}
|
||||
|
||||
export interface TRequeryButton extends ButtonProps {
|
||||
requery: QueryResultBase<TQueryResponse>['refetch'];
|
||||
}
|
||||
|
1
hyperglass/ui/components/submit/index.ts
Normal file
1
hyperglass/ui/components/submit/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './submit';
|
13
hyperglass/ui/components/submit/types.ts
Normal file
13
hyperglass/ui/components/submit/types.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { IconButtonProps } from '@chakra-ui/react';
|
||||
import type { OnChangeArgs } from '~/types';
|
||||
|
||||
export interface TSubmitButton extends Omit<IconButtonProps, 'aria-label'> {
|
||||
handleChange(e: OnChangeArgs): void;
|
||||
}
|
||||
|
||||
export interface TRSubmitButton {
|
||||
isOpen: boolean;
|
||||
onClose(): void;
|
||||
onChange(e: OnChangeArgs): void;
|
||||
children: React.ReactNode;
|
||||
}
|
@@ -1,31 +1,6 @@
|
||||
import { createState, useState } from '@hookstate/core';
|
||||
import type { TGlobalState, TUseGlobalState } from './types';
|
||||
|
||||
// const StateContext = createContext(null);
|
||||
|
||||
// export const StateProvider = ({ children }) => {
|
||||
// const [isSubmitting, setSubmitting] = useState(false);
|
||||
// const [formData, setFormData] = useState({});
|
||||
// const [greetingAck, setGreetingAck] = useSessionStorage('hyperglass-greeting-ack', false);
|
||||
// const resetForm = layoutRef => {
|
||||
// layoutRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
// setSubmitting(false);
|
||||
// setFormData({});
|
||||
// };
|
||||
// const value = useMemo(() => ({
|
||||
// isSubmitting,
|
||||
// setSubmitting,
|
||||
// formData,
|
||||
// setFormData,
|
||||
// greetingAck,
|
||||
// setGreetingAck,
|
||||
// resetForm,
|
||||
// }));
|
||||
// return <StateContext.Provider value={value}>{children}</StateContext.Provider>;
|
||||
// };
|
||||
|
||||
// export const useHyperglassState = () => useContext(StateContext);
|
||||
|
||||
const defaultFormData = {
|
||||
query_location: [],
|
||||
query_target: '',
|
||||
|
@@ -31,8 +31,11 @@ export const useTheme = (): ITheme => useChakraTheme();
|
||||
export const useMobile = (): boolean =>
|
||||
useBreakpointValue({ base: true, md: true, lg: false, xl: false }) ?? true;
|
||||
|
||||
export const useColorToken = (light: string, dark: string): string =>
|
||||
useColorModeValue(useToken('colors', light), useToken('colors', dark));
|
||||
export const useColorToken = <L extends string, D extends string>(
|
||||
token: keyof ITheme,
|
||||
light: L,
|
||||
dark: D,
|
||||
): L | D => useColorModeValue(useToken(token, light), useToken(token, dark));
|
||||
|
||||
export {
|
||||
useColorMode,
|
||||
|
@@ -5,7 +5,6 @@ export * from './useGreeting';
|
||||
export * from './useLGQuery';
|
||||
export * from './useLGState';
|
||||
export * from './useOpposingColor';
|
||||
export * from './useSessionStorage';
|
||||
export * from './useStrf';
|
||||
export * from './useTableToString';
|
||||
export * from './useScaledText';
|
||||
|
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
react-use: useSessionStorage
|
||||
https://github.com/streamich/react-use/blob/master/src/useSessionStorage.ts
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export const useSessionStorage = (key, initialValue, raw) => {
|
||||
const isClient = typeof window === 'object';
|
||||
if (!isClient) {
|
||||
return [initialValue, () => {}];
|
||||
}
|
||||
|
||||
const [state, setState] = useState(() => {
|
||||
try {
|
||||
const sessionStorageValue = sessionStorage.getItem(key);
|
||||
if (typeof sessionStorageValue !== 'string') {
|
||||
sessionStorage.setItem(key, raw ? String(initialValue) : JSON.stringify(initialValue));
|
||||
return initialValue;
|
||||
} else {
|
||||
return raw ? sessionStorageValue : JSON.parse(sessionStorageValue || 'null');
|
||||
}
|
||||
} catch {
|
||||
// If user is in private mode or has storage restriction
|
||||
// sessionStorage can throw. JSON.parse and JSON.stringify
|
||||
// cat throw, too.
|
||||
return initialValue;
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
const serializedState = raw ? String(state) : JSON.stringify(state);
|
||||
sessionStorage.setItem(key, serializedState);
|
||||
} catch {
|
||||
// If user is in private mode or has storage restriction
|
||||
// sessionStorage can throw. Also JSON.stringify can throw.
|
||||
}
|
||||
});
|
||||
|
||||
return [state, setState];
|
||||
};
|
29
hyperglass/ui/types/react-textfit.d.ts
vendored
29
hyperglass/ui/types/react-textfit.d.ts
vendored
@@ -1,29 +0,0 @@
|
||||
declare module 'react-textfit' {
|
||||
type RenderFunction = (text: string) => React.ReactNode;
|
||||
interface TextfitProps {
|
||||
children: React.ReactNode | RenderFunction;
|
||||
text?: string;
|
||||
/**
|
||||
* @default number 1
|
||||
*/
|
||||
min?: number;
|
||||
/**
|
||||
* @default number 100
|
||||
*/
|
||||
max?: number;
|
||||
/**
|
||||
* @default single|multi multi
|
||||
*/
|
||||
mode?: 'single' | 'multi';
|
||||
/**
|
||||
* @default boolean true
|
||||
*/
|
||||
forceSingleModeWidth?: boolean;
|
||||
/**
|
||||
* @default number 50
|
||||
*/
|
||||
throttle?: number;
|
||||
onReady?: (mid: number) => void;
|
||||
}
|
||||
class Textfit extends React.Component<TextfitProps> {}
|
||||
}
|
Reference in New Issue
Block a user