added theme

This commit is contained in:
Arnaud Fauconnet
2022-10-28 11:41:58 +02:00
parent 99b63d95fd
commit 328a760eb8
67 changed files with 4358 additions and 6 deletions

View File

@ -0,0 +1,8 @@
import * as React from 'react';
import MuiAppBar from '@mui/material/AppBar';
function AppBar(props) {
return <MuiAppBar elevation={0} position="fixed" {...props} />;
}
export default AppBar;

View File

@ -0,0 +1,8 @@
import * as React from 'react';
import MuiAppBar, { AppBarProps } from '@mui/material/AppBar';
function AppBar(props: AppBarProps) {
return <MuiAppBar elevation={0} position="fixed" {...props} />;
}
export default AppBar;

View File

@ -0,0 +1,30 @@
import * as React from 'react';
import { experimentalStyled as styled } from '@mui/material/styles';
import MuiButton from '@mui/material/Button';
const ButtonRoot = styled(MuiButton)(({ theme, size }) => ({
borderRadius: 0,
fontWeight: theme.typography.fontWeightMedium,
fontFamily: theme.typography.h1.fontFamily,
padding: theme.spacing(2, 4),
fontSize: theme.typography.pxToRem(14),
boxShadow: 'none',
'&:active, &:focus': {
boxShadow: 'none',
},
...(size === 'small' && {
padding: theme.spacing(1, 3),
fontSize: theme.typography.pxToRem(13),
}),
...(size === 'large' && {
padding: theme.spacing(2, 5),
fontSize: theme.typography.pxToRem(16),
}),
}));
// See https://mui.com/guides/typescript/#usage-of-component-prop for why the types uses `C`.
function Button(props) {
return <ButtonRoot {...props} />;
}
export default Button;

View File

@ -0,0 +1,32 @@
import * as React from 'react';
import { experimentalStyled as styled } from '@mui/material/styles';
import MuiButton, { ButtonProps } from '@mui/material/Button';
const ButtonRoot = styled(MuiButton)(({ theme, size }) => ({
borderRadius: 0,
fontWeight: theme.typography.fontWeightMedium,
fontFamily: theme.typography.h1.fontFamily,
padding: theme.spacing(2, 4),
fontSize: theme.typography.pxToRem(14),
boxShadow: 'none',
'&:active, &:focus': {
boxShadow: 'none',
},
...(size === 'small' && {
padding: theme.spacing(1, 3),
fontSize: theme.typography.pxToRem(13),
}),
...(size === 'large' && {
padding: theme.spacing(2, 5),
fontSize: theme.typography.pxToRem(16),
}),
}));
// See https://mui.com/guides/typescript/#usage-of-component-prop for why the types uses `C`.
function Button<C extends React.ElementType>(
props: ButtonProps<C, { component?: C }>,
) {
return <ButtonRoot {...props} />;
}
export default Button;

View File

@ -0,0 +1,49 @@
import * as React from 'react';
import ReactMarkdown from 'markdown-to-jsx';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import Link from '@mui/material/Link';
const options = {
overrides: {
h1: {
component: Typography,
props: {
gutterBottom: true,
variant: 'h4',
},
},
h2: {
component: Typography,
props: { gutterBottom: true, variant: 'h6' },
},
h3: {
component: Typography,
props: { gutterBottom: true, variant: 'subtitle1' },
},
h4: {
component: Typography,
props: {
gutterBottom: true,
variant: 'caption',
paragraph: true,
},
},
p: {
component: Typography,
props: { paragraph: true },
},
a: { component: Link },
li: {
component: (props) => (
<Box component="li" sx={{ mt: 1 }}>
<Typography component="span" {...props} />
</Box>
),
},
},
};
export default function Markdown(props) {
return <ReactMarkdown options={options} {...props} />;
}

View File

@ -0,0 +1,49 @@
import * as React from 'react';
import ReactMarkdown from 'markdown-to-jsx';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import Link from '@mui/material/Link';
const options = {
overrides: {
h1: {
component: Typography,
props: {
gutterBottom: true,
variant: 'h4',
},
},
h2: {
component: Typography,
props: { gutterBottom: true, variant: 'h6' },
},
h3: {
component: Typography,
props: { gutterBottom: true, variant: 'subtitle1' },
},
h4: {
component: Typography,
props: {
gutterBottom: true,
variant: 'caption',
paragraph: true,
},
},
p: {
component: Typography,
props: { paragraph: true },
},
a: { component: Link },
li: {
component: (props: any) => (
<Box component="li" sx={{ mt: 1 }}>
<Typography component="span" {...props} />
</Box>
),
},
},
};
export default function Markdown(props: any) {
return <ReactMarkdown options={options} {...props} />;
}

View File

@ -0,0 +1,40 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import MuiPaper from '@mui/material/Paper';
import { styled } from '@mui/material/styles';
const PaperRoot = styled(MuiPaper, {
shouldForwardProp: (prop) => prop !== 'background' && prop !== 'padding',
})(({ theme, background, padding }) => ({
backgroundColor: theme.palette.secondary[background],
...(padding && {
padding: theme.spacing(1),
}),
}));
function Paper(props) {
const { background, classes, className, padding = false, ...other } = props;
return (
<PaperRoot
square
elevation={0}
background={background}
padding={padding}
className={className}
{...other}
/>
);
}
Paper.propTypes = {
background: PropTypes.oneOf(['dark', 'light', 'main']).isRequired,
/**
* Override or extend the styles applied to the component.
*/
classes: PropTypes.object,
className: PropTypes.string,
padding: PropTypes.bool,
};
export default Paper;

View File

@ -0,0 +1,32 @@
import * as React from 'react';
import MuiPaper, { PaperProps } from '@mui/material/Paper';
import { styled } from '@mui/material/styles';
interface ExtraPaperProps {
background: 'light' | 'main' | 'dark';
padding?: boolean;
}
const PaperRoot = styled(MuiPaper, {
shouldForwardProp: (prop) => prop !== 'background' && prop !== 'padding',
})<ExtraPaperProps>(({ theme, background, padding }) => ({
backgroundColor: theme.palette.secondary[background],
...(padding && {
padding: theme.spacing(1),
}),
}));
export default function Paper(props: PaperProps & ExtraPaperProps) {
const { background, classes, className, padding = false, ...other } = props;
return (
<PaperRoot
square
elevation={0}
background={background}
padding={padding}
className={className}
{...other}
/>
);
}

View File

@ -0,0 +1,86 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { styled } from '@mui/material/styles';
import MuiSnackbar from '@mui/material/Snackbar';
import { snackbarContentClasses } from '@mui/material/SnackbarContent';
import Slide from '@mui/material/Slide';
import CloseIcon from '@mui/icons-material/Close';
import InfoIcon from '@mui/icons-material/Info';
import IconButton from '@mui/material/IconButton';
const styles = ({ theme }) => ({
[`& .${snackbarContentClasses.root}`]: {
backgroundColor: theme.palette.secondary.light,
color: theme.palette.text.primary,
flexWrap: 'inherit',
[theme.breakpoints.up('md')]: {
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
borderBottomRightRadius: 4,
borderBottomLeftRadius: 4,
},
},
[`& .${snackbarContentClasses.message}`]: {
fontSize: 16,
display: 'flex',
alignItems: 'center',
},
[`& .${snackbarContentClasses.action}`]: {
paddingLeft: theme.spacing(2),
},
'& .MuiSnackbarContent-info': {
flexShrink: 0,
marginRight: theme.spacing(2),
},
'& .MuiSnackbarContent-close': {
padding: theme.spacing(1),
},
});
function Transition(props) {
return <Slide {...props} direction="down" />;
}
function Snackbar(props) {
const { message, closeFunc, ...other } = props;
const classes = {
info: 'MuiSnackbarContent-info',
close: 'MuiSnackbarContent-close',
};
return (
<MuiSnackbar
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
autoHideDuration={6000}
TransitionComponent={Transition}
message={
<React.Fragment>
<InfoIcon className={classes.info} />
<span>{message}</span>
</React.Fragment>
}
action={[
<IconButton
key="close"
aria-label="close"
color="inherit"
className={classes.close}
onClick={() => closeFunc && closeFunc()}
>
<CloseIcon />
</IconButton>,
]}
{...other}
/>
);
}
Snackbar.propTypes = {
closeFunc: PropTypes.func,
/**
* The message to display.
*/
message: PropTypes.node,
};
export default styled(Snackbar)(styles);

View File

@ -0,0 +1,85 @@
import * as React from 'react';
import { Theme, styled } from '@mui/material/styles';
import MuiSnackbar, { SnackbarProps } from '@mui/material/Snackbar';
import { snackbarContentClasses } from '@mui/material/SnackbarContent';
import Slide from '@mui/material/Slide';
import CloseIcon from '@mui/icons-material/Close';
import InfoIcon from '@mui/icons-material/Info';
import IconButton from '@mui/material/IconButton';
import { TransitionProps } from '@mui/material/transitions/transition';
const styles = ({ theme }: { theme: Theme }) =>
({
[`& .${snackbarContentClasses.root}`]: {
backgroundColor: theme.palette.secondary.light,
color: theme.palette.text.primary,
flexWrap: 'inherit',
[theme.breakpoints.up('md')]: {
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
borderBottomRightRadius: 4,
borderBottomLeftRadius: 4,
},
},
[`& .${snackbarContentClasses.message}`]: {
fontSize: 16,
display: 'flex',
alignItems: 'center',
},
[`& .${snackbarContentClasses.action}`]: {
paddingLeft: theme.spacing(2),
},
'& .MuiSnackbarContent-info': {
flexShrink: 0,
marginRight: theme.spacing(2),
},
'& .MuiSnackbarContent-close': {
padding: theme.spacing(1),
},
} as const);
function Transition(
props: TransitionProps & { children: React.ReactElement<any, any> },
) {
return <Slide {...props} direction="down" />;
}
interface ExtraSnackbarProps {
closeFunc?: () => void;
}
function Snackbar(props: SnackbarProps & ExtraSnackbarProps) {
const { message, closeFunc, ...other } = props;
const classes = {
info: 'MuiSnackbarContent-info',
close: 'MuiSnackbarContent-close',
};
return (
<MuiSnackbar
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
autoHideDuration={6000}
TransitionComponent={Transition}
message={
<React.Fragment>
<InfoIcon className={classes.info} />
<span>{message}</span>
</React.Fragment>
}
action={[
<IconButton
key="close"
aria-label="close"
color="inherit"
className={classes.close}
onClick={() => closeFunc && closeFunc()}
>
<CloseIcon />
</IconButton>,
]}
{...other}
/>
);
}
export default styled(Snackbar)(styles);

View File

@ -0,0 +1,139 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { styled } from '@mui/material/styles';
import MuiTextField from '@mui/material/TextField';
import { selectClasses } from '@mui/material/Select';
import { inputLabelClasses } from '@mui/material/InputLabel';
const inputStyleMappingClasses = {
small: 'OnePirateTextField-inputSizeSmall',
medium: 'OnePirateTextField-inputSizeMedium',
large: 'OnePirateTextField-inputSizeLarge',
xlarge: 'OnePirateTextField-inputSizeXLarge',
};
const classes = {
root: 'OnePirateTextField-root',
input: 'OnePirateTextField-input',
inputBorder: 'OnePirateTextField-inputBorder',
};
const styles = ({ theme }) => ({
[`& .${classes.root}`]: {
padding: 0,
'label + &': {
marginTop: theme.spacing(3),
},
},
[`& .${classes.input}`]: {
minWidth: theme.spacing(6),
backgroundColor: theme.palette.common.white,
'&.Mui-disabled': {
backgroundColor: theme.palette.divider,
},
},
[`& .${classes.inputBorder}`]: {
border: '1px solid #e9ddd0',
'&:focus': {
borderColor: theme.palette.secondary.main,
},
},
[`& .${inputStyleMappingClasses.small}`]: {
fontSize: 14,
padding: theme.spacing(1),
width: `calc(100% - ${theme.spacing(2)})`,
},
[`& .${inputStyleMappingClasses.medium}`]: {
fontSize: 16,
padding: theme.spacing(2),
width: `calc(100% - ${theme.spacing(4)})`,
},
[`& .${inputStyleMappingClasses.large}`]: {
fontSize: 18,
padding: 20,
width: `calc(100% - ${20 * 2}px)`,
},
[`& .${inputStyleMappingClasses.xlarge}`]: {
fontSize: 20,
padding: 25,
width: `calc(100% - ${25 * 2}px)`,
},
[`& .${inputLabelClasses.root}`]: {
fontSize: 18,
},
[`& .${selectClasses.select}`]: {
height: 'auto',
borderRadius: 0,
},
[`& .${selectClasses.icon}`]: {
top: '50%',
marginTop: -12,
},
});
function TextField(props) {
const {
InputProps = {},
InputLabelProps,
noBorder,
size = 'medium',
SelectProps,
...other
} = props;
const {
classes: { input: InputPropsClassesInput, ...InputPropsClassesOther } = {},
...InputPropsOther
} = InputProps;
return (
<MuiTextField
InputProps={{
classes: {
root: classes.root,
input: clsx(
classes.input,
inputStyleMappingClasses[size],
{
[classes.inputBorder]: !noBorder,
},
InputPropsClassesInput,
),
...InputPropsClassesOther,
},
disableUnderline: true,
...InputPropsOther,
}}
InputLabelProps={{
...InputLabelProps,
shrink: true,
}}
SelectProps={SelectProps}
{...other}
/>
);
}
TextField.propTypes = {
/**
* Props applied to the [`InputLabel`](/material-ui/api/input-label/) element.
* Pointer events like `onClick` are enabled if and only if `shrink` is `true`.
*/
InputLabelProps: PropTypes.object,
/**
* Props applied to the Input element.
* It will be a [`FilledInput`](/material-ui/api/filled-input/),
* [`OutlinedInput`](/material-ui/api/outlined-input/) or [`Input`](/material-ui/api/input/)
* component depending on the `variant` prop value.
*/
InputProps: PropTypes.object,
noBorder: PropTypes.bool,
/**
* Props applied to the [`Select`](/material-ui/api/select/) element.
*/
SelectProps: PropTypes.object,
size: PropTypes.oneOf(['large', 'medium', 'small', 'xlarge']),
};
export default styled(TextField)(styles);

View File

@ -0,0 +1,126 @@
import * as React from 'react';
import clsx from 'clsx';
import { styled, Theme } from '@mui/material/styles';
import MuiTextField, {
FilledTextFieldProps,
StandardTextFieldProps,
} from '@mui/material/TextField';
import { selectClasses } from '@mui/material/Select';
import { inputLabelClasses } from '@mui/material/InputLabel';
const inputStyleMappingClasses = {
small: 'OnePirateTextField-inputSizeSmall',
medium: 'OnePirateTextField-inputSizeMedium',
large: 'OnePirateTextField-inputSizeLarge',
xlarge: 'OnePirateTextField-inputSizeXLarge',
};
const classes = {
root: 'OnePirateTextField-root',
input: 'OnePirateTextField-input',
inputBorder: 'OnePirateTextField-inputBorder',
};
const styles = ({ theme }: { theme: Theme }) => ({
[`& .${classes.root}`]: {
padding: 0,
'label + &': {
marginTop: theme.spacing(3),
},
},
[`& .${classes.input}`]: {
minWidth: theme.spacing(6),
backgroundColor: theme.palette.common.white,
'&.Mui-disabled': {
backgroundColor: theme.palette.divider,
},
},
[`& .${classes.inputBorder}`]: {
border: '1px solid #e9ddd0',
'&:focus': {
borderColor: theme.palette.secondary.main,
},
},
[`& .${inputStyleMappingClasses.small}`]: {
fontSize: 14,
padding: theme.spacing(1),
width: `calc(100% - ${theme.spacing(2)})`,
},
[`& .${inputStyleMappingClasses.medium}`]: {
fontSize: 16,
padding: theme.spacing(2),
width: `calc(100% - ${theme.spacing(4)})`,
},
[`& .${inputStyleMappingClasses.large}`]: {
fontSize: 18,
padding: 20,
width: `calc(100% - ${20 * 2}px)`,
},
[`& .${inputStyleMappingClasses.xlarge}`]: {
fontSize: 20,
padding: 25,
width: `calc(100% - ${25 * 2}px)`,
},
[`& .${inputLabelClasses.root}`]: {
fontSize: 18,
},
[`& .${selectClasses.select}`]: {
height: 'auto',
borderRadius: 0,
},
[`& .${selectClasses.icon}`]: {
top: '50%',
marginTop: -12,
},
});
export interface OnePirateTextFieldProps
extends Omit<FilledTextFieldProps | StandardTextFieldProps, 'size'> {
noBorder?: boolean;
size?: 'small' | 'medium' | 'large' | 'xlarge';
}
function TextField(props: OnePirateTextFieldProps) {
const {
InputProps = {},
InputLabelProps,
noBorder,
size = 'medium',
SelectProps,
...other
} = props;
const {
classes: { input: InputPropsClassesInput, ...InputPropsClassesOther } = {},
...InputPropsOther
} = InputProps;
return (
<MuiTextField
InputProps={{
classes: {
root: classes.root,
input: clsx(
classes.input,
inputStyleMappingClasses[size],
{
[classes.inputBorder]: !noBorder,
},
InputPropsClassesInput,
),
...InputPropsClassesOther,
},
disableUnderline: true,
...InputPropsOther,
}}
InputLabelProps={{
...InputLabelProps,
shrink: true,
}}
SelectProps={SelectProps}
{...other}
/>
);
}
export default styled(TextField)(styles);

View File

@ -0,0 +1,11 @@
import { styled } from '@mui/material/styles';
import MuiToolbar from '@mui/material/Toolbar';
const Toolbar = styled(MuiToolbar)(({ theme }) => ({
height: 64,
[theme.breakpoints.up('sm')]: {
height: 70,
},
}));
export default Toolbar;

View File

@ -0,0 +1,11 @@
import { styled } from '@mui/material/styles';
import MuiToolbar from '@mui/material/Toolbar';
const Toolbar = styled(MuiToolbar)(({ theme }) => ({
height: 64,
[theme.breakpoints.up('sm')]: {
height: 70,
},
}));
export default Toolbar;

View File

@ -0,0 +1,118 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { styled } from '@mui/material/styles';
import MuiTypography from '@mui/material/Typography';
const markClassesMapping = {
center: {
h1: '',
h2: 'OnePirateTypography-markedH2Center',
h3: 'OnePirateTypography-markedH3Center',
h4: 'OnePirateTypography-markedH4Center',
h5: '',
h6: '',
},
left: {
h1: '',
h2: '',
h3: '',
h4: '',
h5: '',
h6: 'OnePirateTypography-markedH6Left',
},
none: {
h1: '',
h2: '',
h3: '',
h4: '',
h5: '',
h6: '',
},
};
const styles = ({ theme }) => ({
[`& .${markClassesMapping.center.h2}`]: {
height: 4,
width: 73,
display: 'block',
margin: `${theme.spacing(1)} auto 0`,
backgroundColor: theme.palette.secondary.main,
},
[`& .${markClassesMapping.center.h3}`]: {
height: 4,
width: 55,
display: 'block',
margin: `${theme.spacing(1)} auto 0`,
backgroundColor: theme.palette.secondary.main,
},
[`& .${markClassesMapping.center.h4}`]: {
height: 4,
width: 55,
display: 'block',
margin: `${theme.spacing(1)} auto 0`,
backgroundColor: theme.palette.secondary.main,
},
[`& .${markClassesMapping.left.h6}`]: {
height: 2,
width: 28,
display: 'block',
marginTop: theme.spacing(0.5),
background: 'currentColor',
},
});
const variantMapping = {
h1: 'h1',
h2: 'h1',
h3: 'h1',
h4: 'h1',
h5: 'h3',
h6: 'h2',
subtitle1: 'h3',
};
function Typography(props) {
const { children, variant, marked = 'none', ...other } = props;
let markedClassName = '';
if (variant && variant in markClassesMapping[marked]) {
markedClassName = markClassesMapping[marked][variant];
}
return (
<MuiTypography variantMapping={variantMapping} variant={variant} {...other}>
{children}
{markedClassName ? <span className={markedClassName} /> : null}
</MuiTypography>
);
}
Typography.propTypes = {
/**
* The content of the component.
*/
children: PropTypes.node,
marked: PropTypes.oneOf(['center', 'left', 'none']),
/**
* Applies the theme typography styles.
* @default 'body1'
*/
variant: PropTypes.oneOf([
'body1',
'body2',
'button',
'caption',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'inherit',
'overline',
'subtitle1',
'subtitle2',
]),
};
export default styled(Typography)(styles);

View File

@ -0,0 +1,97 @@
import * as React from 'react';
import { styled, Theme } from '@mui/material/styles';
import MuiTypography, { TypographyProps } from '@mui/material/Typography';
const markClassesMapping: {
[index: string]: { [subindex: string]: string };
} = {
center: {
h1: '',
h2: 'OnePirateTypography-markedH2Center',
h3: 'OnePirateTypography-markedH3Center',
h4: 'OnePirateTypography-markedH4Center',
h5: '',
h6: '',
},
left: {
h1: '',
h2: '',
h3: '',
h4: '',
h5: '',
h6: 'OnePirateTypography-markedH6Left',
},
none: {
h1: '',
h2: '',
h3: '',
h4: '',
h5: '',
h6: '',
},
};
const styles = ({ theme }: { theme: Theme }) => ({
[`& .${markClassesMapping.center.h2}`]: {
height: 4,
width: 73,
display: 'block',
margin: `${theme.spacing(1)} auto 0`,
backgroundColor: theme.palette.secondary.main,
},
[`& .${markClassesMapping.center.h3}`]: {
height: 4,
width: 55,
display: 'block',
margin: `${theme.spacing(1)} auto 0`,
backgroundColor: theme.palette.secondary.main,
},
[`& .${markClassesMapping.center.h4}`]: {
height: 4,
width: 55,
display: 'block',
margin: `${theme.spacing(1)} auto 0`,
backgroundColor: theme.palette.secondary.main,
},
[`& .${markClassesMapping.left.h6}`]: {
height: 2,
width: 28,
display: 'block',
marginTop: theme.spacing(0.5),
background: 'currentColor',
},
});
interface ExtraTypographyProps {
marked?: 'center' | 'left' | 'none';
}
const variantMapping = {
h1: 'h1',
h2: 'h1',
h3: 'h1',
h4: 'h1',
h5: 'h3',
h6: 'h2',
subtitle1: 'h3',
};
function Typography<C extends React.ElementType>(
props: TypographyProps<C, { component?: C }> & ExtraTypographyProps,
) {
const { children, variant, marked = 'none', ...other } = props;
let markedClassName = '';
if (variant && variant in markClassesMapping[marked]) {
markedClassName = markClassesMapping[marked][variant];
}
return (
<MuiTypography variantMapping={variantMapping} variant={variant} {...other}>
{children}
{markedClassName ? <span className={markedClassName} /> : null}
</MuiTypography>
);
}
export default styled(Typography)(styles);