feat(docs): comparative code section done

This commit is contained in:
Junior García 2022-01-09 12:18:58 -03:00
parent 45c9f47865
commit a379fa3d21
29 changed files with 1269 additions and 376 deletions

View File

@ -6,8 +6,8 @@
{
"root": ["./"],
"alias": {
"@components": "./src/components",
"@content": "./content",
"@components": "./src/components",
"@layouts": "./src/layouts",
"@hooks": "./src/hooks",
"@utils": "./src/utils",

View File

@ -0,0 +1,101 @@
import React from 'react';
import { Moon, Magic, Flash, Devices } from '@components';
export default {
topFeatures: [
{
title: 'Themeable',
description:
'Provides a simple way to customize default themes, you can change the colors, fonts, breakpoints and everything you need.',
icon: <Magic fill="#FF4ECD" />
},
{
title: 'Fast',
description:
'Avoids unnecessary styles props at runtime, making it more performant than other UI libraries.',
icon: <Flash fill="#FF4ECD" />
},
{
title: 'Light & Dark UI',
description:
'Automatic dark mode recognition, NextUI automatically changes the theme when detects HTML theme prop changes.',
icon: <Moon fill="#FF4ECD" />
},
{
title: 'Unique DX',
description:
'NextUI is fully-typed to minimize the learning curve, and provide the best possible developer experience.',
icon: <Devices fill="#FF4ECD" />
}
],
comparativeCode: {
nextui: `import * as React from 'react';
import { Input } from '@nextui-org/react';
const MyComponent = () => {
return (
<Input.Password bordered labelPlaceholder="Password" />
);
};
export default MyComponent
`,
others: `import * as React from 'react';
import ButtonIcon from '@other-library/ButtonIcon';
import InputOutlined from '@other-library/InputOutlined';
import LabelInput from '@other-library/LabelInput';
import AdornmentInput from '@other-library/AdornmentInput';
import ControlForm from '@other-library/ControlForm';
import EyeIcon from '@other-library/icons/EyeIcon';
import EyeIconOff from '@other-library/icons/EyeIconOff';
const MyComponent = () => {
const [values, setValues] = React.useState({
password: '',
showPassword: false
});
const handleChange = (event) => {
setValues({ ...values, password: event.target.value });
};
const handleClickShowPassword = () => {
setValues({
...values,
showPassword: !values.showPassword
});
};
const handleMouseDownPassword = (event) => {
event.preventDefault();
};
return (
<ControlForm sx={{ m: 1, width: '25ch' }} variant="outlined">
<LabelInput htmlFor="outlined-adornment-password">Password</LabelInput>
<InputOutlined
id="outlined-adornment-password"
type={values.showPassword ? 'text' : 'password'}
value={values.password}
onChange={handleChange}
endAdornment={
<AdornmentInput position="end">
<ButtonIcon
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
>
{values.showPassword ? <EyeIcon /> : <EyeIconOff />}
</ButtonIcon>
</AdornmentInput>
}
label="Password"
/>
</ControlForm>
);
};
export default MyComponent;`
}
};

View File

@ -19,12 +19,14 @@
"algoliasearch": "^4.10.3",
"classnames": "^2.3.1",
"gray-matter": "^4.0.3",
"hast-util-to-html": "7.1.2",
"kbar": "0.1.0-beta.6",
"lodash": "^4.17.21",
"match-sorter": "^6.3.0",
"next": "^11.0.0",
"next-mdx-remote": "^3.0.2",
"next-themes": "^0.0.15",
"parse-numeric-range": "1.2.0",
"prism-react-renderer": "^1.2.1",
"querystring": "^0.2.1",
"react": "^17.0.2",
@ -35,17 +37,24 @@
"react-instantsearch-dom": "^6.12.0",
"react-live": "^2.2.3",
"react-markdown": "^6.0.2",
"refractor": "3.3.1",
"rehype": "11.0.0",
"rehype-parse": "7.0.1",
"remark-autolink-headings": "^6.0.1",
"remark-slug": "^6.0.0",
"shelljs": "^0.8.4",
"styled-jsx": "^4.0.1",
"unified": "9.2.1",
"unist-util-visit": "2.0.3",
"util.promisify": "^1.1.1"
},
"devDependencies": {
"@types/parse-numeric-range": "^0.0.1",
"@types/react": "^17.0.11",
"@types/react-autosuggest": "^10.1.5",
"@types/react-dom": "^17.0.8",
"@types/react-instantsearch-dom": "^6.12.0",
"@types/refractor": "^3.0.2",
"@types/shelljs": "^0.8.9",
"babel-plugin-module-resolver": "^4.1.0",
"eslint-config-next": "^11.0.0",

View File

@ -0,0 +1,167 @@
// Inspired by https://github.dev/modulz/stitches-site code demo
import React from 'react';
import refractor from 'refractor/core';
import js from 'refractor/lang/javascript';
import jsx from 'refractor/lang/jsx';
import bash from 'refractor/lang/bash';
import css from 'refractor/lang/css';
import diff from 'refractor/lang/diff';
import hastToHtml from 'hast-util-to-html';
import rangeParser from 'parse-numeric-range';
import highlightLine from '@lib/rehype-highlight-line';
import highlightWord from '@lib/rehype-highlight-word';
import { Pre } from './pre';
refractor.register(js);
refractor.register(jsx);
refractor.register(bash);
refractor.register(css);
refractor.register(diff);
type PreProps = Omit<React.ComponentProps<typeof Pre>, 'css'>;
type CodeBlockProps = PreProps & {
language: 'js' | 'jsx' | 'bash' | 'css' | 'diff';
value: string;
line?: string;
css?: any;
mode?: 'static' | 'typewriter';
showLineNumbers?: boolean;
};
/**
* recursively get all text nodes as an array for a given element
*/
function getTextNodes(node: any) {
let childTextNodes = [];
if (!node.hasChildNodes()) return;
const childNodes = node.childNodes;
for (let i = 0; i < childNodes.length; i++) {
if (childNodes[i].nodeType == Node.TEXT_NODE) {
childTextNodes.push(childNodes[i]);
} else if (childNodes[i].nodeType == Node.ELEMENT_NODE) {
Array.prototype.push.apply(childTextNodes, getTextNodes(childNodes[i]));
}
}
return childTextNodes;
}
/**
* given a text node, wrap each character in the
* given tag.
*/
function wrapEachCharacter(textNode: any, tag: string, count: number) {
const text = textNode.nodeValue;
const parent = textNode.parentNode;
const characters = text.split('');
characters.forEach(function (character: any, letterIndex: any) {
const delay = (count + letterIndex) * 50;
var element = document.createElement(tag);
var characterNode = document.createTextNode(character);
element.appendChild(characterNode);
element.style.opacity = '0';
element.style.transition = `all ease 0ms ${delay}ms`;
parent.insertBefore(element, textNode);
// skip a couple of frames to trigger transition
requestAnimationFrame(() =>
requestAnimationFrame(() => (element.style.opacity = '1'))
);
});
parent.removeChild(textNode);
}
function CodeTypewriter({ value, className, css, ...props }: any) {
const wrapperRef = React.useRef(null);
React.useEffect(() => {
const wrapper = wrapperRef.current as any;
if (wrapper) {
var allTextNodes = getTextNodes(wrapper);
let count = 0;
allTextNodes?.forEach((textNode) => {
wrapEachCharacter(textNode, 'span', count);
count = count + textNode.nodeValue.length;
});
wrapper.style.opacity = '1';
}
return () => (wrapper.innerHTML = value);
}, []);
return (
<Pre className={className} css={css} {...props}>
<code
ref={wrapperRef}
style={{ opacity: 0 }}
className={className}
dangerouslySetInnerHTML={{ __html: value }}
/>
</Pre>
);
}
const CodeBlock = React.forwardRef<HTMLPreElement, CodeBlockProps>(
(_props, forwardedRef) => {
const {
language,
value,
line = '0',
className = '',
mode,
css,
showLineNumbers,
...props
} = _props;
let result: any = refractor.highlight(value, language);
result = highlightLine(result, rangeParser(line));
result = highlightWord(result);
// convert to html
result = hastToHtml(result);
// TODO reset theme
const classes = `language-${language} ${className}`;
if (mode === 'typewriter') {
return (
<CodeTypewriter
className={classes}
css={css}
value={result}
{...props}
/>
);
}
return (
<Pre
ref={forwardedRef}
className={classes}
css={css}
data-line-numbers={showLineNumbers}
{...props}
>
<code
className={classes}
dangerouslySetInnerHTML={{ __html: result }}
/>
</Pre>
);
}
);
CodeBlock.displayName = 'NextUI - CodeBlock';
export default CodeBlock;

View File

@ -0,0 +1,200 @@
import { styled } from '@nextui-org/react';
import makeCodeTheme, { getCodeThemeColors } from '../playground/code-theme';
const codeTheme = makeCodeTheme();
const {
stringColor,
functionColor,
punctuationColor,
primitiveColor,
classnameColor
} = getCodeThemeColors();
export const Pre = styled('pre', {
$$background: codeTheme.plain.backgroundColor,
$$text: codeTheme.plain.color,
$$outline: '$shadows$md',
$$syntax1: functionColor?.style.color,
$$syntax2: stringColor?.style.color,
$$syntax3: primitiveColor?.style.color,
$$syntax4: '$colors$yellow600',
$$syntax5: classnameColor?.style.color,
$$syntax6: '$colors$yellow400',
$$comment: punctuationColor?.style.color,
$$removed: '$colors$red300',
$$added: '$colors$green300',
$$lineNumbers: punctuationColor?.style.color,
$$fadedLines: punctuationColor?.style.color,
$$highlightedWord1Bg: '$colors$purple500',
$$highlightedWord1BgActive: '$colors$purple600',
$$highlightedWord1Text: '$colors$purple800',
$$highlightedWord2Bg: '$colors$red100',
$$highlightedWord2BgActive: '$colors$red500',
$$highlightedWord2Text: '$colors$red200',
$$highlightedWord3Bg: '$colors$green300',
$$highlightedWord3BgActive: '$colors$green500',
$$highlightedWord3Text: '$colors$green100',
boxSizing: 'border-box',
borderRadius: '$lg',
padding: '$8',
overflow: 'auto',
fontFamily: '$mono',
fontSize: '$xs',
lineHeight: '21px',
whiteSpace: 'pre',
position: 'relative',
backgroundColor: '$$background',
color: '$$text',
boxShadow: '$$outline',
width: '100%',
'& > code': {
color: 'inherit',
fontSize: 'inherit',
background: 'inherit',
display: 'block',
transition: 'none',
'&:hover': {
opacity: 1
}
},
'.token.parameter': {
color: '$$text'
},
'.token.tag, .token.selector, .token.selector .class, .token.function': {
color: '$$syntax1'
},
'.token.script.language-javascript': {
color: '$$text'
},
'.token.class-name': {
color: '$$syntax5'
},
'.token.attr-value, .token.class, .token.string, .token.number, .token.unit, .token.color':
{
color: '$$syntax2'
},
'.token.keyword, .token.rule, .token.operator, .token.pseudo-class, .token.important':
{
color: '$$syntax3'
},
'.token.attr-name': {
color: '$$syntax6'
},
'.token.punctuation, .token.module, .token.property': {
color: '$$syntax4'
},
'.token.comment': {
color: '$$comment'
},
'.token.atapply .token:not(.rule):not(.important)': {
color: 'inherit'
},
'.language-shell .token:not(.comment)': {
color: 'inherit'
},
'.language-css .token.function': {
color: 'inherit'
},
'.token.deleted:not(.prefix), .token.inserted:not(.prefix)': {
display: 'block',
px: '$4',
mx: '-20px'
},
'.token.deleted:not(.prefix)': {
color: '$$removed'
},
'.token.inserted:not(.prefix)': {
color: '$$added'
},
'.token.deleted.prefix, .token.inserted.prefix': {
userSelect: 'none'
},
// Styles for highlighted word
'.highlight-word': {
$$bgAndShadow: '$$highlightedWord1Bg',
$$xOffset: '1px',
color: '$$highlightedWord1Text',
backgroundColor: '$$bgAndShadow',
display: 'inline-block',
boxShadow: '$$xOffset 0 0 0 $$bgAndShadow, -$$xOffset 0 0 0 $$bgAndShadow',
// reset the color for tokens inside highlighted words
'.token': {
color: 'inherit'
},
'&.on': {
$$bgAndShadow: '$$highlightedWord1BgActive',
transition: 'all 100ms ease',
cursor: 'pointer'
}
},
'.token.deleted .highlight-word': {
$$bgAndShadow: '$$highlightedWord2Bg',
color: '$$highlightedWord2Text',
'&.on': {
$$bgAndShadow: '$$highlightedWord2BgActive'
}
},
'.token.inserted .highlight-word': {
$$bgAndShadow: '$$highlightedWord3Bg',
color: '$$highlightedWord3Text',
'&.on': {
$$bgAndShadow: '$$highlightedWord3BgActive'
}
},
// Line numbers
'&[data-line-numbers=true]': {
'.highlight-line': {
position: 'relative',
paddingLeft: '$9',
'&::before': {
content: 'attr(data-line)',
position: 'absolute',
left: -5,
top: 0,
color: '$$lineNumbers'
}
}
},
// Styles for highlighted lines
'.highlight-line': {
'&, *': {
transition: 'color 150ms ease'
},
'&[data-highlighted=false]': {
'&, *': {
color: '$$fadedLines'
}
}
},
// Typewriter styles
'.typewriter': {
opacity: 0
}
});

View File

@ -3,8 +3,7 @@ import {
Snippet,
StyledSnippetPre,
globalCss,
StyledSnippetCopyButton,
useTheme
StyledSnippetCopyButton
} from '@nextui-org/react';
import makeCodeTheme from '../playground/code-theme';
@ -18,9 +17,7 @@ const globalStyles = globalCss({
const Codeblock: React.FC<React.PropsWithChildren<unknown>> = ({
children
}) => {
const themeObj = useTheme();
const { theme, isDark } = themeObj;
const codeTheme = makeCodeTheme(themeObj);
const codeTheme = makeCodeTheme();
const stringColor = codeTheme.styles.find((style) =>
style.types.includes('string')
);
@ -101,9 +98,7 @@ const Codeblock: React.FC<React.PropsWithChildren<unknown>> = ({
[`& ${StyledSnippetCopyButton}`]: {
bg: codeTheme.plain.backgroundColor,
path: {
fill: !isDark
? theme?.colors?.accents2?.value
: theme?.colors?.accents5?.value
fill: '$colors$codeCopyIconColor'
}
}
}}

View File

@ -16,7 +16,7 @@ export type FeaturesGridProps = Props & GridProps;
const FeaturesGrid: React.FC<FeaturesGridProps> = ({ features, ...props }) => {
return (
<Grid.Container gap={2} {...props}>
<Grid.Container gap={2} css={{ px: 0 }} {...props}>
{features.map((feat, index) => (
<Grid key={`${feat.title}_${index}`} xs={12} sm={4} lg={3}>
<FeatureItem>

View File

@ -6,7 +6,7 @@ export const FeatureItem = styled(Grid, {
borderRadius: '$lg',
display: 'flex',
flexDirection: 'column',
px: '$8',
p: '$8',
bf: 'saturate(180%) blur(14px)',
bg: 'rgba(255, 255, 255, 0.05)',
'& .icon-wrapper': {

View File

@ -23,7 +23,10 @@ import { useTheme as useNextTheme } from 'next-themes';
const StyledContainer = styled('div', {
dflex: 'center',
position: 'absolute',
zIndex: '$2'
zIndex: '$2',
'@xsMax': {
display: 'none'
}
});
const HeroComponents = () => {

View File

@ -34,16 +34,14 @@ const Hero: React.FC = () => {
alignItems="center"
justify="space-between"
wrap="nowrap"
gap={0}
as="section"
css={{
position: 'relative',
height: '60vh',
height: 'calc(84vh - 76px)',
'@xsMax': {
height: 'calc(100vh - 64px)',
overflow: 'hidden'
},
'@lgMax': {
padding: '0 20px'
}
}}
>
@ -83,7 +81,7 @@ const Hero: React.FC = () => {
</StyledSubtitle>
<Spacer y={1.5} />
<Grid.Container
gap={1}
gap={0}
alignItems="center"
css={{
'@md': {

View File

@ -1,3 +1,8 @@
export * from './search';
export * from './icons';
export * from './templates';
export * from './primitives';
export { default as Logo } from './logo';
export { default as Hero } from './hero';
export { default as ImageBrowser } from './image-browser';
@ -24,6 +29,5 @@ export { default as Blockholder } from './blockholder';
export { default as LooperBG } from './looper-bg';
export { default as FeaturesGrid } from './features-grid';
export type { Feature as FeatureType } from './features-grid';
export * from './search';
export * from './icons';
export * from './templates';
export { default as Codeblock } from './codeblock';
export { default as CodeDemo } from './code-demo';

View File

@ -1,7 +1,7 @@
/* eslint-disable react/display-name */
import * as React from 'react';
import Playground from '../playground';
import Codeblock from './codeblock';
import Codeblock from '../codeblock';
import CarbonAd from '../carbon-ad';
import * as Icons from '../icons';
import { useTheme } from '@nextui-org/react';

View File

@ -1,23 +1,20 @@
import { PrismTheme } from 'prism-react-renderer';
import { NextUIThemeContext } from '@nextui-org/react';
const makeCodeTheme = ({ theme, isDark }: NextUIThemeContext): PrismTheme => ({
const makeCodeTheme = (): PrismTheme => ({
plain: {
backgroundColor: isDark ? '#111' : '#363449',
color: '#fff',
backgroundColor: '$colors$codeBackground',
color: '$colors$white',
fontWeight: '500',
fontStyle: 'normal',
fontFamily: theme?.fonts?.mono?.value,
fontSize: theme?.fontSizes?.xs?.value,
fontFamily: '$mono',
fontSize: '$xs',
textRendering: 'geometricPrecision'
},
styles: [
{
types: ['comment', 'prolog', 'doctype', 'cdata', 'punctuation'],
style: {
color: isDark
? theme?.colors?.accents6?.value
: theme?.colors?.accents3?.value,
color: '$colors$codeComment',
opacity: 0.5
}
},
@ -48,7 +45,7 @@ const makeCodeTheme = ({ theme, isDark }: NextUIThemeContext): PrismTheme => ({
{
types: ['property', 'function'],
style: {
color: theme?.colors?.success?.value
color: '$success'
}
},
{
@ -60,7 +57,7 @@ const makeCodeTheme = ({ theme, isDark }: NextUIThemeContext): PrismTheme => ({
{
types: ['attr-name'],
style: {
color: theme?.colors?.yellow500?.value
color: '$yellow500'
}
},
{
@ -93,7 +90,7 @@ const makeCodeTheme = ({ theme, isDark }: NextUIThemeContext): PrismTheme => ({
{
types: ['language-javascript', 'script'],
style: {
color: theme?.colors?.success?.value
color: '$success'
}
},
{
@ -115,7 +112,7 @@ const makeCodeTheme = ({ theme, isDark }: NextUIThemeContext): PrismTheme => ({
}
},
{
types: ['important'],
types: ['important', 'primitive'],
style: {
color: '#c678dd'
}
@ -123,4 +120,52 @@ const makeCodeTheme = ({ theme, isDark }: NextUIThemeContext): PrismTheme => ({
]
});
export const getCodeThemeColors = () => {
const codeTheme = makeCodeTheme();
const stringColor = codeTheme.styles.find((style) =>
style.types.includes('string')
);
const punctuationColor = codeTheme.styles.find((style) =>
style.types.includes('punctuation')
);
const numberColor = codeTheme.styles.find((style) =>
style.types.includes('number')
);
const textColor = codeTheme.styles.find((style) =>
style.types.includes('text')
);
const selectorColor = codeTheme.styles.find((style) =>
style.types.includes('selector')
);
const commentColor = codeTheme.styles.find((style) =>
style.types.includes('comment')
);
const classnameColor = codeTheme.styles.find((style) =>
style.types.includes('tag')
);
const attrColor = codeTheme.styles.find((style) =>
style.types.includes('attr-name')
);
const functionColor = codeTheme.styles.find((style) =>
style.types.includes('function')
);
const primitiveColor = codeTheme.styles.find((style) =>
style.types.includes('primitive')
);
return {
stringColor,
punctuationColor,
numberColor,
textColor,
selectorColor,
commentColor,
classnameColor,
attrColor,
functionColor,
primitiveColor
};
};
export default makeCodeTheme;

View File

@ -1,6 +1,5 @@
import React from 'react';
import { LivePreview, LiveProvider, LiveError } from 'react-live';
import { useTheme } from '@nextui-org/react';
import makeCodeTheme from './code-theme';
import Editor from './editor';
import NextLink from 'next/link';
@ -9,6 +8,7 @@ import * as TemplateComponents from '../templates';
import { useMediaQuery } from '@hooks/use-media-query';
import { validateEmail } from '@utils/index';
import withDefaults from '@utils/with-defaults';
import { Box } from '@components';
import * as Components from '@nextui-org/react';
import * as Icons from '../icons';
@ -23,15 +23,41 @@ const defaultProps = {
showEditor: true
};
const StyledWrapper = Components.styled(Box, {
width: '100%',
padding: '$lg $sm',
marginLeft: '-$sm',
display: 'flex',
flexWrap: 'wrap',
flexDirection: 'column',
'& > div': {
width: '100%'
},
variants: {
overflow: {
visible: {
overflowX: 'visible'
},
hidden: {
overflowX: 'hidden'
},
auto: {
overflowX: 'auto'
}
}
},
defaultVariants: {
overflow: 'hidden'
}
});
const DynamicLive: React.FC<Props> = ({
code,
showEditor,
initialEditorOpen,
overflow
}) => {
const themeObject = useTheme();
const { theme } = themeObject;
const codeTheme = makeCodeTheme(themeObject);
const codeTheme = makeCodeTheme();
const scope = {
...Components,
...Icons,
@ -43,26 +69,11 @@ const DynamicLive: React.FC<Props> = ({
};
return (
<LiveProvider code={code} scope={scope} theme={codeTheme}>
<div className="wrapper">
<StyledWrapper className="wrapper" overflow={overflow}>
<LivePreview />
<LiveError />
</div>
</StyledWrapper>
{showEditor && <Editor initialOpen={initialEditorOpen} />}
<style jsx>{`
.wrapper {
width: 100%;
padding: ${theme?.space?.lg?.value} ${theme?.space?.sm?.value};
margin-left: -${theme?.space?.sm?.value};
display: flex;
flex-wrap: wrap;
overflow-x: ${overflow};
flex-direction: column;
box-sizing: border-box;
}
.wrapper > :global(div) {
width: 100%;
}
`}</style>
</LiveProvider>
);
};

View File

@ -0,0 +1,55 @@
import { styled } from '@nextui-org/react';
export const Title = styled('h1', {
display: 'inline',
fontWeight: '$bold',
color: '$text',
lh: '1.2',
fs: '2.5rem',
mb: 0,
'@sm': {
fs: '3rem'
},
'@lg': {
fs: '3.5rem'
},
variants: {
color: {
violet: {
textGradient: '180deg, #FF1CF7 25%, #b249f8 100%'
},
warning: {
textGradient: '180deg, #f36534 25%, #F69F27 100%'
}
},
fullWidth: {
true: {
display: 'block',
width: '100%'
}
}
}
});
export const Subtitle = styled('p', {
pl: '$1',
fs: '$sm',
fontWeight: '$medium',
color: '$accents6',
display: 'block',
mw: '100%',
width: '100%',
'@sm': {
mw: '50%'
}
});
export const Section = styled('section', {
zIndex: '$2',
width: '100%'
});
export const Box = styled('div', {
// Reset
boxSizing: 'border-box'
});

View File

@ -1,7 +1,7 @@
import React from 'react';
import cn from 'classnames';
import { Moon, Sun } from '../icons';
import { useTheme, styled } from '@nextui-org/react';
import { styled } from '@nextui-org/react';
import { useTheme as useNextTheme } from 'next-themes';
import Blockholder from '../blockholder';
import useIsMounted from '@hooks/use-is-mounted';
@ -17,6 +17,9 @@ const StyledButton = styled('button', {
background: 'transparent',
border: 'none',
padding: 0,
'& .theme-selector-icon': {
color: '$colors$headerIconColor'
},
'@xsMax': {
px: '$2'
}
@ -24,8 +27,8 @@ const StyledButton = styled('button', {
export const ThemeToggle: React.FC<Props> = ({ className }) => {
const isMounted = useIsMounted();
const { setTheme } = useNextTheme();
const { theme, isDark } = useTheme();
const { setTheme, theme } = useNextTheme();
const isDark = theme === 'dark';
if (!isMounted) {
return (
@ -45,25 +48,9 @@ export const ThemeToggle: React.FC<Props> = ({ className }) => {
onClick={handleToggleTheme}
>
{isDark ? (
<Sun
filled
fill={
isDark
? theme?.colors?.accents6?.value
: theme?.colors?.accents4?.value
}
size={20}
/>
<Sun filled className="theme-selector-icon" size={20} />
) : (
<Moon
filled
fill={
isDark
? theme?.colors?.accents6?.value
: theme?.colors?.accents4?.value
}
size={20}
/>
<Moon filled className="theme-selector-icon" size={20} />
)}
</StyledButton>
);

View File

@ -3,7 +3,6 @@ import Header from './header';
import Footer from './footer';
import Navbar from './navbar';
import { Container } from '@nextui-org/react';
// import { DotsContainer } from '@components';
import { Route } from '@lib/docs/page';
export interface Props {
@ -20,6 +19,7 @@ const DefaultLayout: React.FC<React.PropsWithChildren<Props>> = ({
return (
<>
<Header />
<Navbar isHome routes={routes} />
<Container
lg
display="flex"
@ -30,9 +30,7 @@ const DefaultLayout: React.FC<React.PropsWithChildren<Props>> = ({
position: 'relative',
minHeight: '100vh'
}}
gap={0}
>
<Navbar isHome routes={routes} />
{children}
<Footer />
</Container>

View File

@ -34,25 +34,9 @@ const DocsLayout: React.FC<React.PropsWithChildren<Props>> = ({
meta
}) => {
const [headings, setHeadings] = useState<Heading[]>([]);
const [scrollPosition, setScrollPosition] = useState(
(typeof window !== 'undefined' && window.pageYOffset) || 0
);
const { theme, type } = useTheme();
const isDark = type === 'dark';
useEffect(() => {
window.addEventListener('scroll', onScroll.bind(this));
return () => {
window.removeEventListener('scroll', onScroll.bind(this));
};
}, []);
const onScroll = () => {
requestAnimationFrame(() => {
setScrollPosition(window.pageYOffset);
});
};
useEffect(() => {
setHeadings(getHeadings());
}, [routes]);
@ -60,140 +44,147 @@ const DocsLayout: React.FC<React.PropsWithChildren<Props>> = ({
const editUrl = `${GITHUB_URL}/${REPO_NAME}/edit/${TAG}/${CONTENT_PATH}${currentRoute?.path}`;
return (
<Container lg as="main" className="docs__container" display="flex" gap={0}>
<Header {...meta} />
<Navbar routes={routes} detached={scrollPosition > 0} />
<Row className="docs__content" gap={0}>
<Sticky offset={10} className="docs__left-sidebar">
<Sidebar routes={routes} tag={tag} slug={slug} />
</Sticky>
<Col className="docs__center">
{children}
<PageNav tag={tag} prevRoute={prevRoute} nextRoute={nextRoute} />
<footer>
{tag ? (
<NextLink href={slug || ''}>
<Link>
<small>Go to the live version of this page</small>
</Link>
</NextLink>
) : (
<a href={editUrl} target="_blank" rel="noopener noreferrer">
<small>Edit this page on GitHub</small>
</a>
)}
</footer>
</Col>
<Sticky offset={10} className="docs__right-sidebar">
<TableOfContent headings={headings} />
</Sticky>
{isDark && (
<img
className="docs__gradient-blue"
src="/gradient-left-dark.svg"
alt="gradient blue background"
/>
)}
{isDark && (
<img
className="docs__gradient-violet"
src="/gradient-right-dark.svg"
alt="gradient violet background"
/>
)}
</Row>
<Footer />
<style jsx>
{`
:global(.docs__container) {
position: relative;
}
:global(.docs__left-sidebar) {
width: 20%;
max-height: calc(100vh - 4rem);
overflow: auto;
display: none;
}
:global(.docs__center) {
z-index: 99;
padding: 0 1.4rem !important;
}
:global(.docs__left-sidebar::-webkit-scrollbar) {
width: 0px;
}
:global(.docs__content) {
padding-top: 1rem;
}
:global(.docs__right-sidebar, .docs__left-sidebar) {
display: none;
width: 24%;
}
:global(.docs__gradient-blue, .docs__gradient-violet) {
top: 0;
opacity: 0;
position: fixed;
animation: appear 200ms 100ms ease forwards;
}
:global(.docs__gradient-blue) {
top: 10%;
left: -10%;
z-index: 1;
}
:global(.docs__gradient-violet) {
display: block;
z-index: 1;
top: -50%;
right: -50%;
}
@media only screen and (max-width: ${theme?.breakpoints?.xs.value}) {
:global(.docs__content) {
margin-top: 64px;
padding-left: 0 !important;
padding-right: 0 !important;
margin-left: 0 !important;
margin-right: 0 !important;
padding: 0;
<>
<Navbar routes={routes} />
<Container lg as="main" className="docs__container" display="flex">
<Header {...meta} />
<Row className="docs__content" gap={0}>
<Sticky offset={84} className="docs__left-sidebar">
<Sidebar routes={routes} tag={tag} slug={slug} />
</Sticky>
<Col className="docs__center">
{children}
<PageNav tag={tag} prevRoute={prevRoute} nextRoute={nextRoute} />
<footer>
{tag ? (
<NextLink href={slug || ''}>
<Link>
<small>Go to the live version of this page</small>
</Link>
</NextLink>
) : (
<a href={editUrl} target="_blank" rel="noopener noreferrer">
<small>Edit this page on GitHub</small>
</a>
)}
</footer>
</Col>
<Sticky offset={84} className="docs__right-sidebar">
<TableOfContent headings={headings} />
</Sticky>
{isDark && (
<img
className="docs__gradient-blue"
src="/gradient-left-dark.svg"
alt="gradient blue background"
/>
)}
{isDark && (
<img
className="docs__gradient-violet"
src="/gradient-right-dark.svg"
alt="gradient violet background"
/>
)}
</Row>
<Footer />
<style jsx>
{`
:global(.docs__container) {
position: relative;
}
}
@media only screen and (min-width: ${theme?.breakpoints?.md.value}) {
:global(.docs__left-sidebar) {
display: block;
width: 20%;
max-height: calc(100vh - 4rem);
overflow: auto;
display: none;
}
}
@media only screen and (max-width: ${theme?.breakpoints?.md.value}) {
:global(.docs__center) {
padding: 0 1rem !important;
z-index: 99;
padding: 0 1.4rem !important;
}
:global(.docs__left-sidebar::-webkit-scrollbar) {
width: 0px;
}
:global(.docs__content) {
padding-top: 1rem;
}
:global(.docs__right-sidebar, .docs__left-sidebar) {
display: none;
width: 24%;
}
:global(.docs__gradient-blue, .docs__gradient-violet) {
top: 0;
opacity: 0;
position: fixed;
animation: appear 200ms 100ms ease forwards;
}
:global(.docs__gradient-blue) {
top: 10%;
left: -10%;
z-index: 1;
}
:global(.docs__gradient-violet) {
top: -35%;
right: -45%;
}
}
@media only screen and (max-width: ${theme?.breakpoints?.lg.value}) {
:global(.docs__content) {
padding: 0 20px;
}
}
@media only screen and (min-width: ${theme?.breakpoints?.lg.value}) {
:global(.docs__right-sidebar) {
display: block;
}
:global(.docs__right-sidebar, .docs__gradient-violet) {
z-index: 1;
top: -50%;
right: -50%;
}
}
@keyframes appear {
from {
opacity: 0;
@media only screen and (max-width: ${theme?.breakpoints?.xs
.value}) {
:global(.docs__content) {
margin-top: 64px;
padding-left: 0 !important;
padding-right: 0 !important;
margin-left: 0 !important;
margin-right: 0 !important;
padding: 0;
}
}
to {
opacity: 1;
@media only screen and (min-width: ${theme?.breakpoints?.md
.value}) {
:global(.docs__left-sidebar) {
display: block;
}
}
}
`}
</style>
</Container>
@media only screen and (max-width: ${theme?.breakpoints?.md
.value}) {
:global(.docs__center) {
padding: 0 1rem !important;
}
:global(.docs__gradient-violet) {
top: -35%;
right: -45%;
}
}
@media only screen and (max-width: ${theme?.breakpoints?.lg
.value}) {
:global(.docs__content) {
padding: 0 20px;
}
}
@media only screen and (min-width: ${theme?.breakpoints?.lg
.value}) {
:global(.docs__right-sidebar) {
display: block;
}
:global(.docs__right-sidebar, .docs__gradient-violet) {
top: -50%;
right: -50%;
}
}
@keyframes appear {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
`}
</style>
</Container>
</>
);
};

View File

@ -20,15 +20,16 @@ import {
useBodyScroll
} from '@nextui-org/react';
import { Route } from '@lib/docs/page';
import { Container } from '@nextui-org/react';
import { useRouter } from 'next/router';
import { useMediaQuery } from '@hooks/use-media-query';
import { addColorAlpha } from '@utils/index';
import { isActive } from '@utils/links';
import { StyledNavContainer } from './styles';
export interface Props {
isHome?: boolean;
detached?: boolean;
routes?: Route[];
isHome?: boolean;
}
const MobileNavigation = dynamic(
@ -45,12 +46,30 @@ const SearchInput = dynamic(
}
);
const Navbar: React.FC<Props> = ({ detached, routes }) => {
const Navbar: React.FC<Props> = ({ isHome, routes }) => {
const [expanded, setExpanded] = useState(false);
const router = useRouter();
const { theme, isDark } = useTheme();
const isMobile = useMediaQuery(960);
const [, setBodyHidden] = useBodyScroll(null, { scrollLayer: true });
const [scrollPosition, setScrollPosition] = useState(
(typeof window !== 'undefined' && window.pageYOffset) || 0
);
const detached = scrollPosition > 0;
useEffect(() => {
window.addEventListener('scroll', onScroll.bind(this));
return () => {
window.removeEventListener('scroll', onScroll.bind(this));
};
}, []);
const onScroll = () => {
requestAnimationFrame(() => {
setScrollPosition(window.pageYOffset);
});
};
useEffect(() => {
if (!isMobile) {
@ -64,12 +83,13 @@ const Navbar: React.FC<Props> = ({ detached, routes }) => {
isMobile && setBodyHidden(!expanded);
};
const showBlur = !!expanded || !!detached;
const showBlur = !!expanded || !!detached || isHome;
return (
<nav className="navbar__container">
<div className="navbar__wrapper">
<StyledNavContainer detached={detached} showBlur={showBlur}>
<Container lg as="nav" display="flex" wrap="nowrap" alignItems="center">
<Col
className="navbar__logo-container"
className="navbar__logo-conta8iner"
css={{
'@mdMax': {
width: '100%'
@ -155,14 +175,7 @@ const Navbar: React.FC<Props> = ({ detached, routes }) => {
target="_blank"
rel="noreferrer"
>
<Twitter
size={24}
fill={
isDark
? theme?.colors?.accents6?.value
: theme?.colors?.accents4?.value
}
/>
<Twitter size={24} />
</Link>
<Link
className="navbar__social-icon"
@ -170,14 +183,7 @@ const Navbar: React.FC<Props> = ({ detached, routes }) => {
target="_blank"
rel="noreferrer"
>
<Discord
size={24}
fill={
isDark
? theme?.colors?.accents6?.value
: theme?.colors?.accents4?.value
}
/>
<Discord size={24} />
</Link>
<Link
className="navbar__social-icon"
@ -185,14 +191,7 @@ const Navbar: React.FC<Props> = ({ detached, routes }) => {
target="_blank"
rel="noreferrer"
>
<Github
size={24}
fill={
isDark
? theme?.colors?.accents6?.value
: theme?.colors?.accents4?.value
}
/>
<Github size={24} />
</Link>
<ThemeToggle className="navbar__social-icon" />
</Row>
@ -216,19 +215,8 @@ const Navbar: React.FC<Props> = ({ detached, routes }) => {
setBodyHidden(false);
}}
/>
</div>
</Container>
<style jsx>{`
.navbar__container,
.navbar__wrapper {
width: 100%;
height: 100%;
display: flex;
align-items: center;
}
.navbar__container {
height: 76px;
z-index: 9999;
}
:global(.navbar__search-row) {
position: initial !important;
}
@ -274,38 +262,12 @@ const Navbar: React.FC<Props> = ({ detached, routes }) => {
}
@media only screen and (max-width: ${theme?.breakpoints.xs.value}) {
:global(.navbar__container) {
top: 0;
position: fixed;
background: ${showBlur
? addColorAlpha(theme?.colors.background.value, 0.6)
: 'transparent'};
box-shadow: ${detached
? '0px 5px 20px -5px rgba(2, 1, 1, 0.1)'
: 'none'};
min-height: 64px;
max-height: 64px;
}
:global(.navbar__search-row) {
justify-content: center;
}
@supports (
(-webkit-backdrop-filter: blur(10px)) or
(backdrop-filter: blur(10px))
) {
:global(.navbar__container) {
backdrop-filter: ${showBlur
? 'saturate(180%) blur(10px)'
: 'none'};
}
}
@supports (
not (-webkit-backdrop-filter: blur(10px)) and not
(backdrop-filter: blur(10px))
) {
:global(.navbar__container) {
background: ${theme?.colors.background.value};
}
}
:global(.navbar__logo-container a:active) {
opacity: 0.7;
}
@ -328,7 +290,7 @@ const Navbar: React.FC<Props> = ({ detached, routes }) => {
}
}
`}</style>
</nav>
</StyledNavContainer>
);
};

View File

@ -0,0 +1,27 @@
import { styled } from '@nextui-org/react';
export const StyledNavContainer = styled('nav', {
top: 0,
display: 'flex',
alignItems: 'center',
height: '76px',
position: 'sticky',
background: 'transparent',
zIndex: '$max',
'& .navbar__social-icon': {
fill: '$colors$headerIconColor'
},
variants: {
showBlur: {
true: {
background: '$headerBackground',
backdropFilter: 'saturate(180%) blur(10px)'
}
},
detached: {
true: {
boxShadow: '0px 5px 20px -5px rgba(2, 1, 1, 0.1)'
}
}
}
});

View File

@ -0,0 +1,119 @@
// Inspired by https://github.dev/modulz/stitches-site
const hastToHtml = require('hast-util-to-html');
const unified = require('unified');
const parse = require('rehype-parse');
const lineNumberify = function lineNumberify(ast, lineNum = 1) {
let lineNumber = lineNum;
return ast.reduce(
(result, node) => {
if (node.type === 'text') {
if (node.value.indexOf('\n') === -1) {
node.lineNumber = lineNumber;
result.nodes.push(node);
return result;
}
const lines = node.value.split('\n');
for (let i = 0; i < lines.length; i++) {
// eslint-disable-next-line no-plusplus
if (i !== 0) ++lineNumber;
if (i === lines.length - 1 && lines[i].length === 0) continue;
result.nodes.push({
type: 'text',
value: i === lines.length - 1 ? lines[i] : `${lines[i]}\n`,
lineNumber: lineNumber
});
}
result.lineNumber = lineNumber;
return result;
}
if (node.children) {
node.lineNumber = lineNumber;
const processed = lineNumberify(node.children, lineNumber);
node.children = processed.nodes;
result.lineNumber = processed.lineNumber;
result.nodes.push(node);
return result;
}
result.nodes.push(node);
return result;
},
{ nodes: [], lineNumber: lineNumber }
);
};
const wrapLines = function wrapLines(ast, linesToHighlight) {
const highlightAll =
linesToHighlight.length === 1 && linesToHighlight[0] === 0;
const allLines = Array.from(new Set(ast.map((x) => x.lineNumber)));
let i = 0;
const wrapped = allLines.reduce((nodes, marker) => {
const line = marker;
const children = [];
for (; i < ast.length; i++) {
if (ast[i].lineNumber < line) {
nodes.push(ast[i]);
continue;
}
if (ast[i].lineNumber === line) {
children.push(ast[i]);
continue;
}
if (ast[i].lineNumber > line) {
break;
}
}
nodes.push({
type: 'element',
tagName: 'div',
properties: {
dataLine: line,
className: 'highlight-line',
dataHighlighted:
linesToHighlight.includes(line) || highlightAll ? 'true' : 'false'
},
children: children,
lineNumber: line
});
return nodes;
}, []);
return wrapped;
};
// https://github.com/gatsbyjs/gatsby/pull/26161/files
const MULTILINE_TOKEN_SPAN =
/<span class="token ([^"]+)">[^<]*\n[^<]*<\/span>/g;
const applyMultilineFix = function (ast) {
// AST to HTML
let html = hastToHtml(ast);
// Fix JSX issue
html = html.replace(MULTILINE_TOKEN_SPAN, (match, token) =>
match.replace(/\n/g, `</span>\n<span class="token ${token}">`)
);
// HTML to AST
const hast = unified()
.use(parse, { emitParseErrors: true, fragment: true })
.parse(html);
return hast.children;
};
module.exports = function (ast, lines) {
const formattedAst = applyMultilineFix(ast);
const numbered = lineNumberify(formattedAst).nodes;
return wrapLines(numbered, lines);
};

View File

@ -0,0 +1,17 @@
const hastToHtml = require('hast-util-to-html');
const unified = require('unified');
const parse = require('rehype-parse');
const CALLOUT = /__(.*?)__/g;
module.exports = (code) => {
const html = hastToHtml(code);
const result = html.replace(
CALLOUT,
(_, text) => `<span class="highlight-word">${text}</span>`
);
const hast = unified()
.use(parse, { emitParseErrors: true, fragment: true })
.parse(result);
return hast.children;
};

View File

@ -58,7 +58,6 @@ const DocsPage: React.FC<Props> = ({ routes, currentRoute, source, meta }) => {
}, [routes]);
useRegisterActions([homeAction].filter(Boolean));
return (
<DocsLayout
routes={routes}

View File

@ -3,58 +3,26 @@ import { GetStaticProps } from 'next';
import router, { useRouter } from 'next/router';
import {
FeaturesGrid,
FeatureType,
Hero,
Moon,
Magic,
Flash,
Devices
Section,
Title,
Subtitle,
CodeDemo,
Logo
} from '@components';
import landingContent from '@content/landing';
import DefaultLayout from '@layouts/default';
import { getSlug } from '@lib/docs/utils';
import { Route, getCurrentTag, fetchDocsManifest } from '@lib/docs/page';
import { Action, useRegisterActions } from 'kbar';
import { getId } from '@utils/collections';
import { styled } from '@nextui-org/react';
import { Spacer, Row, Grid, Text, Col } from '@nextui-org/react';
interface Props {
routes: Route[];
currentRoute: Route;
}
const Section = styled('section', {
zIndex: '$2',
px: '$10',
width: '100%'
});
const topFeatures: FeatureType[] = [
{
title: 'Themeable',
description:
'Provides a simple way to customize default themes, you can change the colors, fonts, breakpoints and everything you need.',
icon: <Magic fill="#FF4ECD" />
},
{
title: 'Fast',
description:
'Avoids unnecessary styles props at runtime, making it more performant than other UI libraries.',
icon: <Flash fill="#FF4ECD" />
},
{
title: 'Light & Dark UI',
description:
'Automatic dark mode recognition, NextUI automatically changes the theme when detects HTML theme prop changes.',
icon: <Moon fill="#FF4ECD" />
},
{
title: 'Unique DX',
description:
'NextUI is fully-typed to minimize the learning curve, and provide the best possible developer experience.',
icon: <Devices fill="#FF4ECD" />
}
];
const IndexPage: React.FC<Props> = ({ routes, currentRoute }) => {
const { query } = useRouter();
const { tag, slug } = getSlug(query);
@ -82,7 +50,51 @@ const IndexPage: React.FC<Props> = ({ routes, currentRoute }) => {
>
<Hero />
<Section>
<FeaturesGrid features={topFeatures} />
<FeaturesGrid features={landingContent.topFeatures} />
</Section>
<Spacer y={4} />
<Section>
<Row justify="flex-start">
<Title>Do</Title>
<Spacer x={0.5} />
<Title color="violet">more.</Title>
</Row>
<Row justify="flex-start">
<Title>Write</Title>
<Spacer x={0.5} />
<Title color="warning">less code.</Title>
</Row>
<Subtitle>
NextUI Components has been built taking into account Developers
Experience in mind avoding having to import multiples components for
showing only one.
</Subtitle>
<Grid.Container gap={1.5}>
<Grid xs={12} sm={6} css={{ pl: 0 }}>
<Col css={{ dflex: 'center', fd: 'column' }}>
<CodeDemo
language="jsx"
value={landingContent.comparativeCode.nextui}
css={{
minHeight: 300
}}
/>
<Text css={{ color: '$text', fontSize: '$md' }}>NextUI</Text>
</Col>
</Grid>
<Grid xs={12} sm={6} css={{ pr: 0 }}>
<Col css={{ dflex: 'center', fd: 'column' }}>
<CodeDemo
language="jsx"
css={{
height: 300
}}
value={landingContent.comparativeCode.others}
/>
<Text css={{ color: '$accents5', fontSize: '$md' }}>Others</Text>
</Col>
</Grid>
</Grid.Container>
</Section>
</DefaultLayout>
);

View File

@ -0,0 +1,56 @@
import * as React from 'react';
import IconButton from '@mui/material/IconButton';
import OutlinedInput from '@mui/material/OutlinedInput';
import InputLabel from '@mui/material/InputLabel';
import InputAdornment from '@mui/material/InputAdornment';
import FormControl from '@mui/material/FormControl';
import Visibility from '@mui/icons-material/Visibility';
import VisibilityOff from '@mui/icons-material/VisibilityOff';
const App = () => {
const [values, setValues] = React.useState({
password: '',
showPassword: false
});
const handleChange = (event) => {
setValues({ ...values, password: event.target.value });
};
const handleClickShowPassword = () => {
setValues({
...values,
showPassword: !values.showPassword
});
};
const handleMouseDownPassword = (event) => {
event.preventDefault();
};
return (
<FormControl sx={{ m: 1, width: '25ch' }} variant="outlined">
<InputLabel htmlFor="outlined-adornment-password">Password</InputLabel>
<OutlinedInput
id="outlined-adornment-password"
type={values.showPassword ? 'text' : 'password'}
value={values.password}
onChange={handleChange}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
>
{values.showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
}
label="Password"
/>
</FormControl>
);
};
export default App;

View File

@ -13,10 +13,28 @@ const sharedTheme: Theme = {
export const lightTheme = createTheme({
...sharedTheme,
type: 'light'
type: 'light',
theme: {
colors: {
headerBackground: 'hsla(0,0%,100%,0.8)',
headerIconColor: '$accents4',
codeBackground: '#363449',
codeComment: '$accents3',
codeCopyIconColor: '$accents2'
}
}
});
export const darkTheme = createTheme({
...sharedTheme,
type: 'dark'
type: 'dark',
theme: {
colors: {
headerBackground: 'rgba(0,0,0,0.5)',
headerIconColor: '$accents6',
codeBackground: '#111111',
codeComment: '$accents6',
codeCopyIconColor: '$accents5'
}
}
});

View File

@ -1,39 +0,0 @@
// Code based on the code from mantine SsrProvider https://github.dev/mantinedev/mantine
import React, { createContext, useContext, useState } from 'react';
function randomId() {
return `mantine-${Math.random().toString(36).substr(2, 9)}`;
}
const UuidContext = createContext<() => string>(() => randomId());
export const useUuid = (staticId?: string) => {
const generateId = useContext(UuidContext);
const [uid, setUid] = useState('');
const _useEffect =
typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
_useEffect(() => {
setUid(generateId());
}, []);
return staticId || uid;
};
interface SsrProviderProps {
children: React.ReactNode;
}
export function SsrProvider({ children }: SsrProviderProps) {
let id = 0;
const generateId = () => {
id += 1;
return `nextui-${id}`;
};
return (
<UuidContext.Provider value={generateId}>{children}</UuidContext.Provider>
);
}

View File

@ -5,7 +5,6 @@ import withDefaults from '../utils/with-defaults';
import { CreateTheme, NextUIThemeContext, ThemeType } from './types';
import deepMerge from '../utils/deep-merge';
import { copyObject } from '../utils/object';
import { SsrProvider } from './ssr-provider';
import {
changeTheme,
getThemeName,
@ -97,12 +96,10 @@ const ThemeProvider: React.FC<PropsWithChildren<ThemeProviderProps>> = ({
}, [isBrowser, userTheme]);
return (
<SsrProvider>
<ThemeContext.Provider value={providerValue}>
{!disableBaseline && <CssBaseline />}
{children}
</ThemeContext.Provider>
</SsrProvider>
<ThemeContext.Provider value={providerValue}>
{!disableBaseline && <CssBaseline />}
{children}
</ThemeContext.Provider>
);
};

161
yarn.lock
View File

@ -4025,6 +4025,11 @@
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
"@types/parse-numeric-range@^0.0.1":
version "0.0.1"
resolved "https://registry.yarnpkg.com/@types/parse-numeric-range/-/parse-numeric-range-0.0.1.tgz#1a807487565a753f486cb3ee4b2145937d49759d"
integrity sha512-nI3rPGKk8BxedokP2VilnW5JyZHYNjGCUDsAZ2JQgISgDflHNUO0wXMfGYP8CkihrKYDm5tilD52XfGhO/ZFCA==
"@types/parse5@^5.0.0":
version "5.0.3"
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109"
@ -4040,6 +4045,11 @@
resolved "https://registry.yarnpkg.com/@types/pretty-hrtime/-/pretty-hrtime-1.0.1.tgz#72a26101dc567b0d68fd956cf42314556e42d601"
integrity sha512-VjID5MJb1eGKthz2qUerWT8+R4b9N+CHvGCzg9fn4kWZgaF9AhdYikQio3R7wV8YY1NsQKPaCwKz1Yff+aHNUQ==
"@types/prismjs@*":
version "1.16.6"
resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.16.6.tgz#377054f72f671b36dbe78c517ce2b279d83ecc40"
integrity sha512-dTvnamRITNqNkqhlBd235kZl3KfVJQQoT5jkXeiWSBK7i4/TLKBNLV0S1wOt8gy4E2TY722KLtdmv2xc6+Wevg==
"@types/prop-types@*":
version "15.7.4"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
@ -4104,6 +4114,13 @@
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/refractor@^3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/refractor/-/refractor-3.0.2.tgz#2d42128d59f78f84d2c799ffc5ab5cadbcba2d82"
integrity sha512-2HMXuwGuOqzUG+KUTm9GDJCHl0LCBKsB5cg28ujEmVi/0qgTb6jOmkVSO5K48qXksyl2Fr3C0Q2VrgD4zbwyXg==
dependencies:
"@types/prismjs" "*"
"@types/scheduler@*":
version "0.16.2"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
@ -6084,6 +6101,11 @@ char-regex@^1.0.2:
resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==
character-entities-html4@^1.0.0:
version "1.1.4"
resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.4.tgz#0e64b0a3753ddbf1fdc044c5fd01d0199a02e125"
integrity sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g==
character-entities-legacy@^1.0.0:
version "1.1.4"
resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1"
@ -6292,6 +6314,15 @@ cli-width@^3.0.0:
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
clipboard@^2.0.0:
version "2.0.8"
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.8.tgz#ffc6c103dd2967a83005f3f61976aa4655a4cdba"
integrity sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==
dependencies:
good-listener "^1.2.2"
select "^1.1.2"
tiny-emitter "^2.0.0"
cliui@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
@ -7131,6 +7162,11 @@ delayed-stream@~1.0.0:
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
delegate@^3.1.2:
version "3.2.0"
resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==
delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
@ -9227,6 +9263,13 @@ globrex@^0.1.2:
resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098"
integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==
good-listener@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=
dependencies:
delegate "^3.1.2"
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.6:
version "4.2.8"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
@ -9438,6 +9481,11 @@ hast-util-from-parse5@^6.0.0:
vfile-location "^3.2.0"
web-namespaces "^1.0.0"
hast-util-is-element@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz#3b3ed5159a2707c6137b48637fbfe068e175a425"
integrity sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ==
hast-util-parse-selector@^2.0.0:
version "2.2.5"
resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a"
@ -9459,6 +9507,38 @@ hast-util-raw@6.0.1:
xtend "^4.0.0"
zwitch "^1.0.0"
hast-util-to-html@7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-7.1.2.tgz#db677f0ee483658cea0eecc9dec30aba42b67111"
integrity sha512-pu73bvORzdF6XZgwl9eID/0RjBb/jtRfoGRRSykpR1+o9rCdiAHpgkSukZsQBRlIqMg6ylAcd7F0F7myJUb09Q==
dependencies:
ccount "^1.0.0"
comma-separated-tokens "^1.0.0"
hast-util-is-element "^1.0.0"
hast-util-whitespace "^1.0.0"
html-void-elements "^1.0.0"
property-information "^5.0.0"
space-separated-tokens "^1.0.0"
stringify-entities "^3.0.1"
unist-util-is "^4.0.0"
xtend "^4.0.0"
hast-util-to-html@^7.1.1:
version "7.1.3"
resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-7.1.3.tgz#9f339ca9bea71246e565fc79ff7dbfe98bb50f5e"
integrity sha512-yk2+1p3EJTEE9ZEUkgHsUSVhIpCsL/bvT8E5GzmWc+N1Po5gBw+0F8bo7dpxXR0nu0bQVxVZGX2lBGF21CmeDw==
dependencies:
ccount "^1.0.0"
comma-separated-tokens "^1.0.0"
hast-util-is-element "^1.0.0"
hast-util-whitespace "^1.0.0"
html-void-elements "^1.0.0"
property-information "^5.0.0"
space-separated-tokens "^1.0.0"
stringify-entities "^3.0.1"
unist-util-is "^4.0.0"
xtend "^4.0.0"
hast-util-to-parse5@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz#1ec44650b631d72952066cea9b1445df699f8479"
@ -9475,6 +9555,11 @@ hast-util-to-string@^1.0.4:
resolved "https://registry.yarnpkg.com/hast-util-to-string/-/hast-util-to-string-1.0.4.tgz#9b24c114866bdb9478927d7e9c36a485ac728378"
integrity sha512-eK0MxRX47AV2eZ+Lyr18DCpQgodvaS3fAQO2+b9Two9F5HEoRPhiUMNzoXArMJfZi2yieFzUBMRl3HNJ3Jus3w==
hast-util-whitespace@^1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz#e4fe77c4a9ae1cb2e6c25e02df0043d0164f6e41"
integrity sha512-I5GTdSfhYfAPNztx2xJRQpG8cuDSNt599/7YUn7Gx/WxNMsG+a835k97TDkFgk123cwjfwINaZknkKkphx/f2A==
hastscript@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640"
@ -13062,6 +13147,11 @@ parse-json@^5.0.0:
json-parse-even-better-errors "^2.3.0"
lines-and-columns "^1.1.6"
parse-numeric-range@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/parse-numeric-range/-/parse-numeric-range-1.2.0.tgz#aa70b00f29624ed13e9f943e9461b306e386b0fa"
integrity sha512-1q2tXpAOplPxcl8vrIGPWz1dJxxfmdRkCFcpxxMBerDnGuuHalOWF/xj9L8Nn5XoTUoB/6F0CeQBp2fMgkOYFg==
parse-passwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
@ -13532,6 +13622,13 @@ prismjs@^1.21.0, prismjs@~1.25.0:
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.25.0.tgz#6f822df1bdad965734b310b315a23315cf999756"
integrity sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==
prismjs@~1.23.0:
version "1.23.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.23.0.tgz#d3b3967f7d72440690497652a9d40ff046067f33"
integrity sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==
optionalDependencies:
clipboard "^2.0.0"
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@ -14344,6 +14441,15 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"
refractor@3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.3.1.tgz#ebbc04b427ea81dc25ad333f7f67a0b5f4f0be3a"
integrity sha512-vaN6R56kLMuBszHSWlwTpcZ8KTMG6aUCok4GrxYDT20UIOXxOc5o6oDc8tNTzSlH3m2sI+Eu9Jo2kVdDcUTWYw==
dependencies:
hastscript "^6.0.0"
parse-entities "^2.0.0"
prismjs "~1.23.0"
refractor@^3.1.0, refractor@^3.3.1:
version "3.5.0"
resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.5.0.tgz#334586f352dda4beaf354099b48c2d18e0819aec"
@ -14427,6 +14533,30 @@ regjsparser@^0.7.0:
dependencies:
jsesc "~0.5.0"
rehype-parse@7.0.1, rehype-parse@^7.0.0:
version "7.0.1"
resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-7.0.1.tgz#58900f6702b56767814afc2a9efa2d42b1c90c57"
integrity sha512-fOiR9a9xH+Le19i4fGzIEowAbwG7idy2Jzs4mOrFWBSJ0sNUgy0ev871dwWnbOo371SjgjG4pwzrbgSVrKxecw==
dependencies:
hast-util-from-parse5 "^6.0.0"
parse5 "^6.0.0"
rehype-stringify@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/rehype-stringify/-/rehype-stringify-8.0.0.tgz#9b6afb599bcf3165f10f93fc8548f9a03d2ec2ba"
integrity sha512-VkIs18G0pj2xklyllrPSvdShAV36Ff3yE5PUO9u36f6+2qJFnn22Z5gKwBOwgXviux4UC7K+/j13AnZfPICi/g==
dependencies:
hast-util-to-html "^7.1.1"
rehype@11.0.0:
version "11.0.0"
resolved "https://registry.yarnpkg.com/rehype/-/rehype-11.0.0.tgz#d81729e65f4ac2b26f5de0b6bafc257eb0780e1f"
integrity sha512-qXqRqiCFJD5CJ61CSJuNImTFrm3zVkOU9XywHDwrUuvWN74MWt72KJ67c5CM5x8g0vGcOkRVCrYj85vqkmHulQ==
dependencies:
rehype-parse "^7.0.0"
rehype-stringify "^8.0.0"
unified "^9.0.0"
relateurl@^0.2.7:
version "0.2.7"
resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
@ -14892,6 +15022,11 @@ secure-compare@3.0.1:
resolved "https://registry.yarnpkg.com/secure-compare/-/secure-compare-3.0.1.tgz#f1a0329b308b221fae37b9974f3d578d0ca999e3"
integrity sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=
select@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=
"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.1:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
@ -15614,6 +15749,15 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
stringify-entities@^3.0.1:
version "3.1.0"
resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-3.1.0.tgz#b8d3feac256d9ffcc9fa1fefdcf3ca70576ee903"
integrity sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg==
dependencies:
character-entities-html4 "^1.0.0"
character-entities-legacy "^1.0.0"
xtend "^4.0.0"
strip-ansi@6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
@ -16014,6 +16158,11 @@ timers-browserify@2.0.12, timers-browserify@^2.0.4:
dependencies:
setimmediate "^1.0.4"
tiny-emitter@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
tiny-glob@^0.2.6:
version "0.2.9"
resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2"
@ -16507,6 +16656,18 @@ unified@9.2.0:
trough "^1.0.0"
vfile "^4.0.0"
unified@9.2.1:
version "9.2.1"
resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.1.tgz#ae18d5674c114021bfdbdf73865ca60f410215a3"
integrity sha512-juWjuI8Z4xFg8pJbnEZ41b5xjGUWGHqXALmBZ3FC3WX0PIx1CZBIIJ6mXbYMcf6Yw4Fi0rFUTA1cdz/BglbOhA==
dependencies:
bail "^1.0.0"
extend "^3.0.0"
is-buffer "^2.0.0"
is-plain-obj "^2.0.0"
trough "^1.0.0"
vfile "^4.0.0"
unified@^9.0.0:
version "9.2.2"
resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975"