2020-12-29 02:05:28 -07:00
|
|
|
import { Flex, Button, VStack } from '@chakra-ui/react';
|
|
|
|
|
import { motion } from 'framer-motion';
|
2021-01-03 00:08:29 -07:00
|
|
|
import { isSafari } from 'react-device-detect';
|
2021-12-17 21:44:35 -07:00
|
|
|
import { Switch, Case } from 'react-if';
|
2020-12-29 02:05:28 -07:00
|
|
|
import { useConfig, useMobile } from '~/context';
|
2021-12-18 00:29:51 -07:00
|
|
|
import { useFormState, useFormInteractive } from '~/hooks';
|
2020-12-29 02:05:28 -07:00
|
|
|
import { SubtitleOnly } from './subtitleOnly';
|
2021-01-03 00:08:29 -07:00
|
|
|
import { TitleOnly } from './titleOnly';
|
|
|
|
|
import { Logo } from './logo';
|
2020-12-29 02:05:28 -07:00
|
|
|
|
2021-01-02 16:53:13 -07:00
|
|
|
import type { TTitle, TTitleWrapper, TDWrapper, TMWrapper } from './types';
|
2020-12-29 02:05:28 -07:00
|
|
|
|
2021-04-22 21:45:01 -07:00
|
|
|
const AnimatedVStack = motion(VStack);
|
2021-12-18 00:29:51 -07:00
|
|
|
const AnimatedFlex = motion(Flex);
|
2020-12-29 02:05:28 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Title wrapper for mobile devices, breakpoints sm & md.
|
|
|
|
|
*/
|
2021-12-17 21:08:45 -07:00
|
|
|
const MWrapper = (props: TMWrapper): JSX.Element => {
|
2021-12-18 00:29:51 -07:00
|
|
|
const formInteractive = useFormInteractive();
|
2021-01-02 16:53:13 -07:00
|
|
|
return (
|
|
|
|
|
<AnimatedVStack
|
|
|
|
|
layout
|
|
|
|
|
spacing={1}
|
2021-12-18 00:29:51 -07:00
|
|
|
alignItems={formInteractive ? 'center' : 'flex-start'}
|
2021-01-02 16:53:13 -07:00
|
|
|
{...props}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
};
|
2020-12-29 02:05:28 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Title wrapper for desktop devices, breakpoints lg & xl.
|
|
|
|
|
*/
|
2021-12-17 21:08:45 -07:00
|
|
|
const DWrapper = (props: TDWrapper): JSX.Element => {
|
2021-12-18 00:29:51 -07:00
|
|
|
const formInteractive = useFormInteractive();
|
2020-12-29 02:05:28 -07:00
|
|
|
return (
|
|
|
|
|
<AnimatedVStack
|
|
|
|
|
spacing={1}
|
|
|
|
|
initial="main"
|
|
|
|
|
alignItems="center"
|
2021-12-18 00:29:51 -07:00
|
|
|
animate={formInteractive}
|
2020-12-29 02:05:28 -07:00
|
|
|
transition={{ damping: 15, type: 'spring', stiffness: 100 }}
|
2021-09-21 08:20:44 -07:00
|
|
|
variants={{ results: { scale: 0.5 }, form: { scale: 1 } }}
|
2020-12-29 02:05:28 -07:00
|
|
|
{...props}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Universal wrapper for title sub-components, which will be different depending on the
|
|
|
|
|
* `title_mode` configuration variable.
|
|
|
|
|
*/
|
2021-12-17 21:08:45 -07:00
|
|
|
const TitleWrapper = (props: TDWrapper | TMWrapper): JSX.Element => {
|
2020-12-29 02:05:28 -07:00
|
|
|
const isMobile = useMobile();
|
|
|
|
|
return (
|
|
|
|
|
<>
|
2021-01-02 17:06:59 -07:00
|
|
|
{isMobile ? <MWrapper {...(props as TMWrapper)} /> : <DWrapper {...(props as TDWrapper)} />}
|
2020-12-29 02:05:28 -07:00
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Title sub-component if `title_mode` is set to `text_only`.
|
|
|
|
|
*/
|
2021-12-17 21:08:45 -07:00
|
|
|
const TextOnly = (props: TTitleWrapper): JSX.Element => {
|
2020-12-29 02:05:28 -07:00
|
|
|
return (
|
|
|
|
|
<TitleWrapper {...props}>
|
|
|
|
|
<TitleOnly />
|
|
|
|
|
<SubtitleOnly />
|
|
|
|
|
</TitleWrapper>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Title sub-component if `title_mode` is set to `logo_only`. Renders only the logo.
|
|
|
|
|
*/
|
2021-12-17 21:08:45 -07:00
|
|
|
const LogoOnly = (): JSX.Element => (
|
2020-12-29 02:05:28 -07:00
|
|
|
<TitleWrapper>
|
|
|
|
|
<Logo />
|
|
|
|
|
</TitleWrapper>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Title sub-component if `title_mode` is set to `logo_subtitle`. Renders the logo with the
|
|
|
|
|
* subtitle underneath.
|
|
|
|
|
*/
|
2021-12-17 21:08:45 -07:00
|
|
|
const LogoSubtitle = (): JSX.Element => (
|
2020-12-29 02:05:28 -07:00
|
|
|
<TitleWrapper>
|
|
|
|
|
<Logo />
|
|
|
|
|
<SubtitleOnly />
|
|
|
|
|
</TitleWrapper>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Title sub-component if `title_mode` is set to `all`. Renders the logo, title, and subtitle.
|
|
|
|
|
*/
|
2021-12-17 21:08:45 -07:00
|
|
|
const All = (): JSX.Element => (
|
2020-12-29 02:05:28 -07:00
|
|
|
<TitleWrapper>
|
|
|
|
|
<Logo />
|
|
|
|
|
<TextOnly mt={2} />
|
|
|
|
|
</TitleWrapper>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Title component which renders sub-components based on the `title_mode` configuration variable.
|
|
|
|
|
*/
|
2021-12-17 21:08:45 -07:00
|
|
|
export const Title = (props: TTitle): JSX.Element => {
|
2020-12-29 02:05:28 -07:00
|
|
|
const { fontSize, ...rest } = props;
|
|
|
|
|
const { web } = useConfig();
|
2021-09-10 23:13:27 -07:00
|
|
|
const { titleMode } = web.text;
|
2020-12-29 02:05:28 -07:00
|
|
|
|
2021-12-18 00:29:51 -07:00
|
|
|
const reset = useFormState(s => s.reset);
|
|
|
|
|
const formInteractive = useFormInteractive();
|
2020-12-29 02:05:28 -07:00
|
|
|
|
|
|
|
|
return (
|
2021-12-18 00:29:51 -07:00
|
|
|
<AnimatedFlex
|
2020-12-29 02:05:28 -07:00
|
|
|
px={0}
|
|
|
|
|
flexWrap="wrap"
|
|
|
|
|
flexDir="column"
|
2021-12-18 00:29:51 -07:00
|
|
|
animate={{ height: formInteractive ? undefined : '20vh' }}
|
2020-12-29 02:05:28 -07:00
|
|
|
justifyContent="center"
|
2021-01-02 12:54:00 -07:00
|
|
|
/* flexBasis
|
|
|
|
|
This is a fix for Safari specifically. LMGTFY: Safari flex-basis width. Nutshell: Safari
|
|
|
|
|
is stupid, in that it infers the default flex-basis from the width, 100%. Other browsers
|
|
|
|
|
don't do this. Without the below fix, the logo will appear gigantic, filling the entire
|
|
|
|
|
div up to the parent's max-width. The fix is to hard-code a flex-basis width.
|
|
|
|
|
*/
|
2021-01-03 00:08:29 -07:00
|
|
|
flexBasis={{ base: '100%', lg: isSafari ? '33%' : '100%' }}
|
2021-12-18 00:29:51 -07:00
|
|
|
mt={{ md: formInteractive ? undefined : 'auto' }}
|
2021-01-03 23:51:09 -07:00
|
|
|
{...rest}
|
|
|
|
|
>
|
2020-12-29 02:05:28 -07:00
|
|
|
<Button
|
|
|
|
|
px={0}
|
|
|
|
|
variant="link"
|
|
|
|
|
flexWrap="wrap"
|
|
|
|
|
flexDir="column"
|
2021-09-21 08:20:44 -07:00
|
|
|
onClick={() => reset()}
|
2020-12-29 02:05:28 -07:00
|
|
|
_focus={{ boxShadow: 'none' }}
|
2021-01-03 23:51:09 -07:00
|
|
|
_hover={{ textDecoration: 'none' }}
|
|
|
|
|
>
|
2021-12-17 21:44:35 -07:00
|
|
|
<Switch>
|
|
|
|
|
<Case condition={titleMode === 'text_only'}>
|
|
|
|
|
<TextOnly />
|
|
|
|
|
</Case>
|
|
|
|
|
<Case condition={titleMode === 'logo_only'}>
|
|
|
|
|
<LogoOnly />
|
|
|
|
|
</Case>
|
|
|
|
|
<Case condition={titleMode === 'logo_subtitle'}>
|
|
|
|
|
<LogoSubtitle />
|
|
|
|
|
</Case>
|
|
|
|
|
<Case condition={titleMode === 'all'}>
|
|
|
|
|
<All />
|
|
|
|
|
</Case>
|
|
|
|
|
</Switch>
|
2020-12-29 02:05:28 -07:00
|
|
|
</Button>
|
2021-12-18 00:29:51 -07:00
|
|
|
</AnimatedFlex>
|
2020-12-29 02:05:28 -07:00
|
|
|
);
|
|
|
|
|
};
|