mirror of
https://github.com/zhigang1992/react.git
synced 2026-03-26 22:42:51 +08:00
Merge pull request #81 from unix/customization
docs: add customization page
This commit is contained in:
@@ -3,19 +3,21 @@ import withDefaults from '../utils/with-defaults'
|
||||
import AutoCompleteSearch from './auto-complete-searching'
|
||||
|
||||
interface Props {
|
||||
hidden?: boolean
|
||||
className?: string
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
hidden: false,
|
||||
className: '',
|
||||
}
|
||||
|
||||
export type AutoCompleteEmptyProps = Props & typeof defaultProps & React.HTMLAttributes<any>
|
||||
|
||||
const AutoCompleteEmpty: React.FC<React.PropsWithChildren<AutoCompleteEmptyProps>> = ({
|
||||
children, className,
|
||||
children, hidden, className,
|
||||
}) => {
|
||||
|
||||
if (hidden) return null
|
||||
return <AutoCompleteSearch className={className}>{children}</AutoCompleteSearch>
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ export type AutoCompleteOption = {
|
||||
value: string
|
||||
}
|
||||
|
||||
export type AutoCompleteOptions = Array<AutoCompleteOption | typeof AutoCompleteItem>
|
||||
export type AutoCompleteOptions = Array<typeof AutoCompleteItem | AutoCompleteOption>
|
||||
|
||||
interface Props {
|
||||
options: AutoCompleteOptions
|
||||
@@ -32,7 +32,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
options: [] as AutoCompleteOptions[],
|
||||
options: [] as AutoCompleteOptions,
|
||||
initialValue: '',
|
||||
disabled: false,
|
||||
clearable: false,
|
||||
@@ -43,7 +43,7 @@ const defaultProps = {
|
||||
type NativeAttrs = Omit<React.InputHTMLAttributes<any>, keyof Props>
|
||||
export type AutoCompleteProps = Props & typeof defaultProps & NativeAttrs
|
||||
|
||||
const childrenToOptionsNode = (options: AutoCompleteOptions) => {
|
||||
const childrenToOptionsNode = (options: Array<AutoCompleteOption>) => {
|
||||
if (options.length === 0) return null
|
||||
|
||||
return options.map((item, index) => {
|
||||
@@ -85,7 +85,7 @@ const AutoComplete: React.FC<React.PropsWithChildren<AutoCompleteProps>> = ({
|
||||
if (state === '') return null
|
||||
return hasEmptyChild ? emptyChild : <AutoCompleteEmpty>No Options</AutoCompleteEmpty>
|
||||
}
|
||||
return childrenToOptionsNode(options)
|
||||
return childrenToOptionsNode(options as Array<AutoCompleteOption>)
|
||||
}, [searching, options])
|
||||
const showClearIcon = useMemo(
|
||||
() => clearable && searching === undefined,
|
||||
|
||||
@@ -28,7 +28,7 @@ const Link = React.memo(React.forwardRef<HTMLAnchorElement, React.PropsWithChild
|
||||
href, color, underline, pure, children, className, block, ...props
|
||||
}, ref: React.Ref<HTMLAnchorElement>) => {
|
||||
const theme = useTheme()
|
||||
const linkColor = color || block ? theme.palette.success : 'inherit'
|
||||
const linkColor = color || block ? theme.palette.link : 'inherit'
|
||||
const padding = block ? theme.layout.gapQuarter : '0'
|
||||
const decoration = underline ? 'underline' : 'none'
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ type PopoverComponent<P = {}> = React.FC<P> & {
|
||||
|
||||
type ComponentProps = Partial<typeof defaultProps>
|
||||
& Omit<Props, keyof typeof defaultProps>
|
||||
& Omit<TooltipProps, keyof ExcludeTooltipProps>
|
||||
& Partial<Omit<TooltipProps, keyof ExcludeTooltipProps>>
|
||||
|
||||
(Popover as PopoverComponent<ComponentProps>).defaultProps = defaultProps
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ const Dropdown: React.FC<React.PropsWithChildren<Props>> = React.memo(({
|
||||
width: ${rect.width}px;
|
||||
top: ${rect.top + 2}px;
|
||||
left: ${rect.left}px;
|
||||
z-index: 100;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
|
||||
@@ -80,7 +80,7 @@ const CSSBaseline: React.FC<React.PropsWithChildren<{}>> = React.memo(({
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
color: ${theme.expressiveness.linkColor};
|
||||
color: ${theme.palette.link};
|
||||
text-decoration: ${theme.expressiveness.linkStyle};
|
||||
}
|
||||
|
||||
|
||||
@@ -14,13 +14,13 @@ export interface Props {
|
||||
theme?: ThemeParam
|
||||
}
|
||||
|
||||
interface MergeObject {
|
||||
export interface MergeObject {
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
const isObject = (target: any) => target && typeof target === 'object'
|
||||
export const isObject = (target: any) => target && typeof target === 'object'
|
||||
|
||||
const deepMergeObject = <T extends MergeObject,>(source: T, target: T): T => {
|
||||
export const deepMergeObject = <T extends MergeObject,>(source: T, target: T): T => {
|
||||
if (!isObject(target) || !isObject(source)) return source
|
||||
|
||||
const sourceKeys = Object.keys(source) as Array<keyof T>
|
||||
@@ -67,7 +67,7 @@ const ThemeProvider: React.FC<PropsWithChildren<Props>> = ({ children, theme })
|
||||
const currentTheme = useTheme()
|
||||
const merged = mergeTheme(currentTheme, customTheme)
|
||||
const userTheme = currentTheme.type !== merged.type ? switchTheme(merged) : merged
|
||||
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={userTheme}>{children}</ThemeContext.Provider>
|
||||
)
|
||||
|
||||
@@ -36,14 +36,13 @@ export const palette: ZeitUIThemesPalette = {
|
||||
purple: '#f81ce5',
|
||||
alert: '#ff0080',
|
||||
violet: '#7928ca',
|
||||
link: '#fff',
|
||||
}
|
||||
|
||||
export const expressiveness: ZeitUIThemesExpressiveness = {
|
||||
linkColor: '#fff',
|
||||
linkStyle: 'none',
|
||||
linkHoverStyle: 'none',
|
||||
dropdownBoxShadow: '0 0 0 1px #333',
|
||||
dropdownTriangleStroke: '#fff',
|
||||
scrollerStart: 'rgba(255, 255, 255, 1)',
|
||||
scrollerEnd: 'rgba(255, 255, 255, 0)',
|
||||
shadowSmall: '0 0 0 1px #333',
|
||||
@@ -62,7 +61,7 @@ export const layout: ZeitUIThemesLayout = {
|
||||
pageMargin: '16pt',
|
||||
pageWidth: '750pt',
|
||||
pageWidthWithMargin: '782pt',
|
||||
breakpointMobile: '600px',
|
||||
breakpointMobile: '720px',
|
||||
breakpointTablet: '960px',
|
||||
radius: '5px',
|
||||
}
|
||||
|
||||
@@ -36,14 +36,13 @@ export const palette: ZeitUIThemesPalette = {
|
||||
purple: '#f81ce5',
|
||||
alert: '#ff0080',
|
||||
violet: '#7928ca',
|
||||
link: '#0070f3',
|
||||
}
|
||||
|
||||
export const expressiveness: ZeitUIThemesExpressiveness = {
|
||||
linkColor: '#0070f3',
|
||||
linkStyle: 'none',
|
||||
linkHoverStyle: 'none',
|
||||
dropdownBoxShadow: '0 4px 4px 0 rgba(0, 0, 0, 0.02)',
|
||||
dropdownTriangleStroke: '#fff',
|
||||
scrollerStart: 'rgba(255, 255, 255, 1)',
|
||||
scrollerEnd: 'rgba(255, 255, 255, 0)',
|
||||
shadowSmall: '0 5px 10px rgba(0, 0, 0, 0.12)',
|
||||
@@ -62,7 +61,7 @@ export const layout: ZeitUIThemesLayout = {
|
||||
pageMargin: '16pt',
|
||||
pageWidth: '750pt',
|
||||
pageWidthWithMargin: '782pt',
|
||||
breakpointMobile: '600px',
|
||||
breakpointMobile: '720px',
|
||||
breakpointTablet: '960px',
|
||||
radius: '5px',
|
||||
}
|
||||
|
||||
@@ -30,14 +30,13 @@ export interface ZeitUIThemesPalette {
|
||||
purple: string
|
||||
alert: string
|
||||
violet: string
|
||||
link: string
|
||||
}
|
||||
|
||||
export interface ZeitUIThemesExpressiveness {
|
||||
linkColor: string
|
||||
linkStyle: string
|
||||
linkHoverStyle: string
|
||||
dropdownBoxShadow: string
|
||||
dropdownTriangleStroke: string
|
||||
scrollerStart: string
|
||||
scrollerEnd: string
|
||||
shadowSmall: string
|
||||
|
||||
@@ -105,7 +105,7 @@ const Attributes: React.FC<React.PropsWithChildren<AttributesProps>> = React.mem
|
||||
border-left: 1px solid transparent;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
@media only screen and (max-width: ${theme.layout.breakpointMobile}) {
|
||||
.attr {
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import SunIcon from './icons/sun'
|
||||
const Controls: React.FC<{}> = React.memo(({
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const { onChange, updateChineseState } = useConfigs()
|
||||
const { updateCustomTheme, updateChineseState } = useConfigs()
|
||||
const { pathname } = useRouter()
|
||||
const { locale } = useLocale()
|
||||
const isChinese = useMemo(() => locale === 'zh-cn', [locale])
|
||||
@@ -19,9 +19,8 @@ const Controls: React.FC<{}> = React.memo(({
|
||||
return pathname.replace(locale, nextLocale)
|
||||
}, [locale, pathname])
|
||||
|
||||
const switchThemes = (val: string) => {
|
||||
const isDark = val === 'dark'
|
||||
onChange && onChange(isDark)
|
||||
const switchThemes = (type: 'dark' | 'light') => {
|
||||
updateCustomTheme({ type })
|
||||
}
|
||||
const switchLanguages = () => {
|
||||
updateChineseState(!isChinese)
|
||||
@@ -87,7 +86,7 @@ const Controls: React.FC<{}> = React.memo(({
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
@media only screen and (max-width: ${theme.layout.breakpointMobile}) {
|
||||
.controls {
|
||||
display: none;
|
||||
pointer-events: none;
|
||||
|
||||
138
lib/components/customization/codes.tsx
Normal file
138
lib/components/customization/codes.tsx
Normal file
@@ -0,0 +1,138 @@
|
||||
import React, { useMemo } from 'react'
|
||||
import { Text, Spacer, useTheme, Code, useToasts } from 'components'
|
||||
import DefaultTheme from 'components/styles/themes/default'
|
||||
import { isObject, MergeObject } from 'components/styles/theme-provider/theme-provider'
|
||||
import { LiveEditor, LiveProvider } from 'react-live'
|
||||
import makeCodeTheme from 'lib/components/playground/code-theme'
|
||||
import useClipboard from 'components/utils/use-clipboard'
|
||||
import CopyIcon from 'components/snippet/snippet-icon'
|
||||
import { useConfigs } from 'lib/config-context'
|
||||
|
||||
export const getDeepDifferents = <T extends MergeObject,>(source: T, target: T): T => {
|
||||
if (!isObject(target) || !isObject(source)) return target
|
||||
|
||||
const sourceKeys = Object.keys(source) as Array<keyof T>
|
||||
let result = {} as T
|
||||
for (const key of sourceKeys) {
|
||||
const sourceValue = source[key]
|
||||
const targetValue = target[key]
|
||||
|
||||
if (isObject(sourceValue) && isObject(targetValue)) {
|
||||
const childrenDiff = getDeepDifferents(sourceValue, { ...targetValue })
|
||||
if (Object.keys(childrenDiff).length !== 0) {
|
||||
result[key] = childrenDiff
|
||||
}
|
||||
} else if (sourceValue !== targetValue) {
|
||||
result[key] = targetValue
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const CustomizationCodes = () => {
|
||||
const theme = useTheme()
|
||||
const { isChinese } = useConfigs()
|
||||
const codeTheme = makeCodeTheme(theme)
|
||||
const { copy } = useClipboard()
|
||||
const [, setToast] = useToasts()
|
||||
|
||||
const deepDifferents = useMemo(
|
||||
() => getDeepDifferents(DefaultTheme, theme),
|
||||
[DefaultTheme, theme],
|
||||
)
|
||||
const userCodes = useMemo(() => {
|
||||
return `const myTheme = ${JSON.stringify(deepDifferents, null, 2)}
|
||||
|
||||
/***
|
||||
* Usage::
|
||||
* export const App = () => {
|
||||
* return (
|
||||
* <ZEITUIProvider theme={myTheme}>
|
||||
* <CSSBaseline />
|
||||
* <YourComponent />
|
||||
* </ZEITUIProvider>
|
||||
* )
|
||||
* }
|
||||
**/`
|
||||
}, [deepDifferents])
|
||||
|
||||
const copyCode = () => {
|
||||
copy(userCodes)
|
||||
setToast({ text: 'Theme code copied.' })
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="custom-codes">
|
||||
<h3 className="title">{isChinese ? '主题代码' : 'Theme Codes'}</h3>
|
||||
{isChinese ? (
|
||||
<Text>这里是你所有的变更,点击 <Code>copy</Code> 按钮即可使用在你自己的项目中。</Text>
|
||||
) : (
|
||||
<Text>This is all your changes, click <Code>copy</Code> to use it in your own project.</Text>
|
||||
)}
|
||||
<Spacer y={2} />
|
||||
<div className="codes">
|
||||
<div className="copy" onClick={copyCode}><CopyIcon /></div>
|
||||
<LiveProvider code={userCodes} disabled theme={codeTheme}>
|
||||
<LiveEditor />
|
||||
</LiveProvider>
|
||||
</div>
|
||||
<Spacer y={5} />
|
||||
<style jsx>{`
|
||||
.custom-codes {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
margin: 4.5rem auto 2.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
display: inline-block;
|
||||
background: ${theme.palette.foreground};
|
||||
color: ${theme.palette.background};
|
||||
font-size: 1rem;
|
||||
line-height: 1rem;
|
||||
padding: ${theme.layout.gap} 0;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1.5px;
|
||||
}
|
||||
|
||||
.codes {
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
border: 1px solid ${theme.palette.border};
|
||||
border-radius: ${theme.layout.radius};
|
||||
overflow: hidden;
|
||||
padding: calc(.6 * ${theme.layout.gap}) ${theme.layout.gap};
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.copy {
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
top: 1rem;
|
||||
z-index: 2000;
|
||||
color: ${theme.palette.accents_3};
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: color 200ms ease;
|
||||
}
|
||||
|
||||
.copy:hover {
|
||||
color: ${theme.palette.accents_6};
|
||||
}
|
||||
|
||||
@media only screen and (max-width: ${theme.layout.breakpointMobile}) {
|
||||
.title, .codes {
|
||||
width: 90vw;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CustomizationCodes
|
||||
37
lib/components/customization/colors.tsx
Normal file
37
lib/components/customization/colors.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React from 'react'
|
||||
import { Card, useTheme } from 'components'
|
||||
import { CardTypes } from 'components/utils/prop-types'
|
||||
|
||||
const types = ['secondary', 'success', 'warning', 'error',
|
||||
'dark', 'alert', 'purple', 'violet', 'cyan', 'lite']
|
||||
|
||||
const Colors: React.FC<React.PropsWithChildren<{}>> = () => {
|
||||
const theme = useTheme()
|
||||
|
||||
return (
|
||||
<div className="colors">
|
||||
{types.map((type, index) => {
|
||||
return (
|
||||
<div key={`${type}-${index}`} className="color-card">
|
||||
<Card type={type as CardTypes}>{type}</Card>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<style jsx>{`
|
||||
.colors {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.color-card {
|
||||
display: flex;
|
||||
width: 9rem;
|
||||
margin-right: ${theme.layout.gapHalf};
|
||||
margin-bottom: ${theme.layout.gapHalf};
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Colors
|
||||
86
lib/components/customization/demo.tsx
Normal file
86
lib/components/customization/demo.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import React from 'react'
|
||||
import Colors from './colors'
|
||||
import { useTheme, Button, Text, Code, Spacer, Link, Select } from 'components'
|
||||
import { useConfigs } from 'lib/config-context'
|
||||
|
||||
const Demo: React.FC<React.PropsWithChildren<{}>> = () => {
|
||||
const theme = useTheme()
|
||||
const { isChinese } = useConfigs()
|
||||
|
||||
return (
|
||||
<div className="demo">
|
||||
<div className="content">
|
||||
{isChinese ? (
|
||||
<>
|
||||
<Text h3>预览</Text>
|
||||
<Text>这里是你变更主题后的即时预览。此外,当你每次更新主题变量时,整个文档站点也会随之变化。</Text>
|
||||
<Text>你可以拷贝自动生成的代码,或是与任何人分享你自定义的主题样式。</Text>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Text h3>Preview</Text>
|
||||
<Text>Here's a preview of your changes to the Theme. When you set the changes,
|
||||
the entire document site will change with the theme.</Text>
|
||||
<Text>You can copy automatically generated codes or share your custom theme with anyone.</Text>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Spacer y={1.7} />
|
||||
<Text h4>{isChinese ? '色彩' : 'Colors'}</Text>
|
||||
<Colors />
|
||||
|
||||
<Spacer y={1.7} />
|
||||
<Text h4>{isChinese ? '排版' : 'Typography'}</Text>
|
||||
<Text><Code>inline codes</Code></Text>
|
||||
<Text><a>Hyperlink Text</a> </Text>
|
||||
<Text><Link href="#" color>Link Component</Link></Text>
|
||||
<Text>Our mission is to make cloud computing accessible to everyone. We build products for developers and designers. And those who aspire to become one.</Text>
|
||||
<Text h6>Heading</Text>
|
||||
<Text h5>Heading</Text>
|
||||
<Text h4>Heading</Text>
|
||||
<Text h3>Heading</Text>
|
||||
<Text h2>Heading</Text>
|
||||
<Text h1>Heading</Text>
|
||||
|
||||
<Spacer y={1.7} />
|
||||
<Text h4>{isChinese ? '基础组件' : 'Basic Components'}</Text>
|
||||
<Select placeholder="Choose one" initialValue="1">
|
||||
<Select.Option value="1">Option 1</Select.Option>
|
||||
<Select.Option value="2">Option 2</Select.Option>
|
||||
</Select>
|
||||
<Spacer y={1} />
|
||||
<Button disabled auto size="small">Action</Button>
|
||||
<Spacer inline x={.5} />
|
||||
<Button auto size="small">Action</Button>
|
||||
<Spacer inline x={.5} />
|
||||
<Button auto type="secondary" size="small">Action</Button>
|
||||
<Spacer y={.5} />
|
||||
<Button>Action</Button>
|
||||
</div>
|
||||
<style jsx>{`
|
||||
.demo {
|
||||
width: 34%;
|
||||
margin-top: calc(${theme.layout.gap} * 2);
|
||||
margin-right: ${theme.layout.gap};
|
||||
padding-right: ${theme.layout.gapQuarter};
|
||||
position: relative;
|
||||
border-right: 1px solid ${theme.palette.border};
|
||||
height: 100%;
|
||||
transition: width 200ms ease;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: ${theme.layout.breakpointMobile}) {
|
||||
.demo {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Demo
|
||||
118
lib/components/customization/editor-color-item.tsx
Normal file
118
lib/components/customization/editor-color-item.tsx
Normal file
@@ -0,0 +1,118 @@
|
||||
import React, { useMemo } from 'react'
|
||||
import { useTheme, ZeitUIThemesPalette, Popover } from 'components'
|
||||
import { ColorResult, TwitterPicker } from 'react-color'
|
||||
import { useConfigs } from 'lib/config-context'
|
||||
import DefaultTheme from 'components/styles/themes/default'
|
||||
|
||||
interface Props {
|
||||
value?: string
|
||||
keyName: keyof ZeitUIThemesPalette
|
||||
}
|
||||
|
||||
const getRandomColor = () => {
|
||||
const hex = `00000${(Math.random() * 0x1000000 << 0).toString(16)}`
|
||||
return `#${hex.substr(-6)}`
|
||||
}
|
||||
|
||||
const getRandomColors = () => {
|
||||
const kyes = Object.keys(DefaultTheme.palette) as Array<keyof ZeitUIThemesPalette>
|
||||
const basicColors = new Array(5).fill('')
|
||||
.map(() => {
|
||||
const index = Math.round(Math.random() * (kyes.length)) + kyes.length
|
||||
return DefaultTheme.palette[kyes[index]]
|
||||
})
|
||||
const deduplicatedColors = [...new Set(...basicColors)]
|
||||
const randomColors = new Array(10 - deduplicatedColors.length)
|
||||
.fill('')
|
||||
.map(() => getRandomColor())
|
||||
return deduplicatedColors.concat(randomColors)
|
||||
}
|
||||
|
||||
const EditorColorItem: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
keyName,
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const { updateCustomTheme } = useConfigs()
|
||||
const label = `${keyName}`
|
||||
const mainColor = useMemo(() => theme.palette[keyName], [theme.palette, keyName])
|
||||
const randomColors = useMemo(() => getRandomColors(), [])
|
||||
const colorChangeHandler = ({ hex }: ColorResult) => {
|
||||
updateCustomTheme({
|
||||
palette: { [keyName]: hex }
|
||||
})
|
||||
}
|
||||
|
||||
const popoverContent = (color: string) => (
|
||||
<TwitterPicker triangle="hide" color={color}
|
||||
onChangeComplete={colorChangeHandler}
|
||||
colors={randomColors} />
|
||||
)
|
||||
return (
|
||||
<Popover content={() => popoverContent(mainColor)} portalClassName="editor-popover" offset={3}>
|
||||
<div className="editor-item">
|
||||
<div className="dot-box">
|
||||
<span className="dot" />
|
||||
</div>
|
||||
{label}
|
||||
<style jsx>{`
|
||||
.editor-item {
|
||||
background-color: transparent;
|
||||
width: auto;
|
||||
padding: 0 ${theme.layout.gapHalf};
|
||||
line-height: 2rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
border: 1px solid ${theme.palette.border};
|
||||
border-radius: ${theme.layout.radius};
|
||||
color: ${theme.palette.accents_5};
|
||||
margin-right: .75rem;
|
||||
margin-bottom: .5rem;
|
||||
cursor: pointer;
|
||||
transition: color 200ms ease;
|
||||
}
|
||||
|
||||
:global(.editor-popover .inner) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
:global(.editor-popover .twitter-picker) {
|
||||
box-shadow: none !important;
|
||||
border: 0 !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.editor-item:hover {
|
||||
color: ${theme.palette.accents_8};
|
||||
}
|
||||
|
||||
.editor-item:hover .dot {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.dot-box, .dot {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dot-box {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin-right: .75rem;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background-color: ${mainColor};
|
||||
transform: scale(.8);
|
||||
transition: transform 200ms ease;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
||||
export default EditorColorItem
|
||||
57
lib/components/customization/editor-input-item.tsx
Normal file
57
lib/components/customization/editor-input-item.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import React, { useMemo } from 'react'
|
||||
import { useTheme, Input, ZeitUIThemes } from 'components'
|
||||
import { useConfigs } from 'lib/config-context'
|
||||
|
||||
type Props = {
|
||||
value?: string
|
||||
groupName: keyof ZeitUIThemes
|
||||
keyName: string
|
||||
}
|
||||
|
||||
const EditorInputItem: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
groupName, keyName
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const { updateCustomTheme } = useConfigs()
|
||||
const currentVal = useMemo(() => {
|
||||
const group = theme[groupName]
|
||||
const key = keyName as keyof typeof group
|
||||
return theme[groupName][key]
|
||||
}, [theme.expressiveness, keyName])
|
||||
const width = useMemo(() => `${currentVal}`.length > 15 ? '350px' : 'auto', [])
|
||||
|
||||
const changeHandler = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateCustomTheme({
|
||||
[groupName]: { [keyName]: event.target.value },
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="editor-item">
|
||||
<Input value={currentVal as string} label={keyName}
|
||||
onChange={changeHandler}
|
||||
className="editor-input" />
|
||||
<style jsx>{`
|
||||
.editor-item {
|
||||
background-color: transparent;
|
||||
width: auto;
|
||||
padding: 0;
|
||||
line-height: 2rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: ${theme.palette.accents_5};
|
||||
margin-right: .75rem;
|
||||
margin-bottom: .5rem;
|
||||
cursor: pointer;
|
||||
transition: color 200ms ease;
|
||||
}
|
||||
|
||||
.editor-item :global(.editor-input) {
|
||||
width: ${width};
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default EditorInputItem
|
||||
120
lib/components/customization/editor.tsx
Normal file
120
lib/components/customization/editor.tsx
Normal file
@@ -0,0 +1,120 @@
|
||||
import React from 'react'
|
||||
import { Text, Button, useTheme, ZeitUIThemesPalette, ZeitUIThemesExpressiveness, ZeitUIThemesLayout } from 'components'
|
||||
import EditorColorItem from './editor-color-item'
|
||||
import EditorInputItem from './editor-input-item'
|
||||
import DefaultTheme from 'components/styles/themes/default'
|
||||
import { useConfigs } from 'lib/config-context'
|
||||
|
||||
const basicColors: Array<keyof ZeitUIThemesPalette> = [
|
||||
'accents_1', 'accents_2', 'accents_3', 'accents_4', 'accents_5', 'accents_6',
|
||||
'accents_7', 'accents_8', 'foreground', 'background',
|
||||
]
|
||||
const statusColors: Array<keyof ZeitUIThemesPalette> = [
|
||||
'success', 'successLight', 'successDark', 'error', 'errorLight', 'errorDark',
|
||||
'warning', 'warningLight', 'warningDark',
|
||||
]
|
||||
const otherColors: Array<keyof ZeitUIThemesPalette> = [
|
||||
'selection', 'secondary', 'link', 'border', 'code', 'cyan', 'purple', 'alert', 'violet'
|
||||
]
|
||||
const expressiveness: Array<keyof ZeitUIThemesExpressiveness> = [
|
||||
'linkStyle', 'linkHoverStyle', 'dropdownBoxShadow', 'shadowSmall',
|
||||
'shadowMedium', 'shadowLarge',
|
||||
]
|
||||
const pageLayout: Array<keyof ZeitUIThemesLayout> = [
|
||||
'pageWidth', 'pageWidthWithMargin', 'pageMargin', 'radius',
|
||||
]
|
||||
const gapLayout: Array<keyof ZeitUIThemesLayout> = [
|
||||
'gap', 'gapNegative', 'gapHalf', 'gapHalfNegative', 'gapQuarter', 'gapQuarterNegative',
|
||||
]
|
||||
|
||||
const Editor = () => {
|
||||
const theme = useTheme()
|
||||
const { updateCustomTheme, isChinese } = useConfigs()
|
||||
|
||||
const resetLayout = () => updateCustomTheme({ layout: DefaultTheme.layout })
|
||||
const restColors = () => updateCustomTheme({ palette: DefaultTheme.palette })
|
||||
const resetExpressiveness = () => {
|
||||
updateCustomTheme({ expressiveness: DefaultTheme.expressiveness })
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="editor">
|
||||
<Text h3>{isChinese ? '色彩' : 'Colors'}
|
||||
<Button type="abort" auto size="mini" onClick={restColors}>{isChinese ? '重置' : 'Reset'}</Button>
|
||||
</Text>
|
||||
<p className="subtitle">{isChinese ? '基础' : 'basic'}</p>
|
||||
<div className="content">
|
||||
{basicColors.map((item, index) => (
|
||||
<EditorColorItem key={`${item}-${index}`} keyName={item} />
|
||||
))}
|
||||
</div>
|
||||
<p className="subtitle">{isChinese ? '状态' : 'status'}</p>
|
||||
<div className="content">
|
||||
{statusColors.map((item, index) => (
|
||||
<EditorColorItem key={`${item}-${index}`} keyName={item} />
|
||||
))}
|
||||
</div>
|
||||
<p className="subtitle">{isChinese ? '其他' : 'others'}</p>
|
||||
<div className="content">
|
||||
{otherColors.map((item, index) => (
|
||||
<EditorColorItem key={`${item}-${index}`} keyName={item} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Text h3>{isChinese ? '表现力' : 'Expressiveness'}
|
||||
<Button type="abort" auto size="mini" onClick={resetExpressiveness}>{isChinese ? '重置' : 'Reset'}</Button>
|
||||
</Text>
|
||||
<p className="subtitle">{isChinese ? '基础' : 'basic'}</p>
|
||||
<div className="content">
|
||||
{expressiveness.map((item, index) => (
|
||||
<EditorInputItem key={`${item}-${index}`} groupName="expressiveness" keyName={item} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Text h3>{isChinese ? '布局' : 'Layout'}
|
||||
<Button type="abort" auto size="mini" onClick={resetLayout}>{isChinese ? '重置' : 'Reset'}</Button>
|
||||
</Text>
|
||||
{isChinese ? (
|
||||
<p>大多数的布局间距都依赖这些变量,不合理的更改可能会导致布局失衡。</p>
|
||||
) : (
|
||||
<p>Most layout spacing depends on these variables, unreasonable changes may cause layout imbalance.</p>
|
||||
)}
|
||||
<p className="subtitle">{isChinese ? '基础' : 'basic'}</p>
|
||||
<div className="content">
|
||||
{pageLayout.map((item, index) => (
|
||||
<EditorInputItem key={`${item}-${index}`} groupName="layout" keyName={item} />
|
||||
))}
|
||||
</div>
|
||||
<p className="subtitle">{isChinese ? '间距' : 'gaps'}</p>
|
||||
<div className="content">
|
||||
{gapLayout.map((item, index) => (
|
||||
<EditorInputItem key={`${item}-${index}`} groupName="layout" keyName={item} />
|
||||
))}
|
||||
</div>
|
||||
<style jsx>{`
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
width: auto;
|
||||
margin: 0 auto;
|
||||
padding-left: ${theme.layout.gapQuarter};
|
||||
}
|
||||
|
||||
.editor :global(h3) {
|
||||
margin: 2rem 0 1rem 0;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: ${theme.palette.accents_4};
|
||||
text-transform: uppercase;
|
||||
font-size: .75rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Editor
|
||||
41
lib/components/customization/layout.tsx
Normal file
41
lib/components/customization/layout.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import React from 'react'
|
||||
import { useTheme, Row } from 'components'
|
||||
import CustomizationCodes from './codes'
|
||||
import Demo from './demo'
|
||||
|
||||
const CustomizationLayout: React.FC<React.PropsWithChildren<{}>> = ({
|
||||
children,
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
|
||||
return (
|
||||
<div className="layout">
|
||||
<Row>
|
||||
<Demo />
|
||||
<div className="content">{children}</div>
|
||||
</Row>
|
||||
<Row>
|
||||
<CustomizationCodes />
|
||||
</Row>
|
||||
|
||||
<style jsx>{`
|
||||
.layout {
|
||||
min-height: calc(100vh - 108px);
|
||||
max-width: ${theme.layout.pageWidthWithMargin};
|
||||
margin: 0 auto;
|
||||
padding: 0 ${theme.layout.gap};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CustomizationLayout
|
||||
28
lib/components/icons/full-screen-close.tsx
Normal file
28
lib/components/icons/full-screen-close.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React from 'react'
|
||||
import withDefaults from 'components/utils/with-defaults'
|
||||
|
||||
interface Props {
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
width: 20,
|
||||
height: 20,
|
||||
}
|
||||
|
||||
export type FullScreenCloseIconProps = Props & typeof defaultProps & React.SVGAttributes<any>
|
||||
|
||||
const FullScreenCloseIcon: React.FC<React.PropsWithChildren<FullScreenCloseIconProps>> = ({
|
||||
width, height, ...props
|
||||
}) => {
|
||||
return (
|
||||
<svg viewBox="0 0 24 24" width={width} height={height} {...props} stroke="currentColor" strokeWidth="1.5"
|
||||
strokeLinecap="round" strokeLinejoin="round" fill="none" shapeRendering="geometricPrecision"
|
||||
style={{ color: 'currentColor' }}>
|
||||
<path d="M4 14h6m0 0v6m0-6l-7 7m17-11h-6m0 0V4m0 6l7-7m-7 17v-6m0 0h6m-6 0l7 7M10 4v6m0 0H4m6 0L3 3"/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default withDefaults(FullScreenCloseIcon, defaultProps)
|
||||
27
lib/components/icons/full-screen.tsx
Normal file
27
lib/components/icons/full-screen.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import React from 'react'
|
||||
import withDefaults from 'components/utils/with-defaults'
|
||||
|
||||
interface Props {
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
width: 20,
|
||||
height: 20,
|
||||
}
|
||||
|
||||
export type FullScreenIconProps = Props & typeof defaultProps & React.SVGAttributes<any>
|
||||
|
||||
const FullScreenIcon: React.FC<React.PropsWithChildren<FullScreenIconProps>> = ({
|
||||
width, height, ...props
|
||||
}) => {
|
||||
return (
|
||||
<svg viewBox="0 0 24 24" width={width} height={height} {...props} stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"
|
||||
strokeLinejoin="round" fill="none" shapeRendering="geometricPrecision" style={{ color: 'currentColor' }}>
|
||||
<path d="M15 3h6m0 0v6m0-6l-7 7M9 21H3m0 0v-6m0 6l7-7M3 9V3m0 0h6M3 3l7 7m11 5v6m0 0h-6m6 0l-7-7"/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default withDefaults(FullScreenIcon, defaultProps)
|
||||
@@ -37,7 +37,7 @@ export const Layout: React.FC<React.PropsWithChildren<Props>> = React.memo(({ ch
|
||||
<style jsx>{`
|
||||
.layout {
|
||||
min-height: calc(100vh - 108px);
|
||||
max-width: 1000px;
|
||||
max-width: ${theme.layout.pageWidthWithMargin};
|
||||
margin: 0 auto;
|
||||
padding: 0 ${theme.layout.gap};
|
||||
display: flex;
|
||||
@@ -74,7 +74,7 @@ export const Layout: React.FC<React.PropsWithChildren<Props>> = React.memo(({ ch
|
||||
padding-bottom: 150px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
@media only screen and (max-width: ${theme.layout.breakpointMobile}) {
|
||||
.layout {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
|
||||
@@ -98,7 +98,7 @@ const MenuSticker = () => {
|
||||
}
|
||||
|
||||
.inner {
|
||||
max-width: 1000px;
|
||||
max-width: ${theme.layout.pageWidth};
|
||||
padding: 0 ${theme.layout.gap};
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
@@ -71,7 +71,7 @@ export const Sidebar: React.FC<Props> = React.memo(() => {
|
||||
margin-bottom: ${theme.layout.gap};
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
@media only screen and (max-width: ${theme.layout.breakpointMobile}) {
|
||||
.box {
|
||||
padding: calc(3.5 * ${theme.layout.gap}) 15vw;
|
||||
width: 100vw;
|
||||
|
||||
@@ -55,7 +55,7 @@ const SideItem: React.FC<React.PropsWithChildren<SideItemProps>> = React.memo(({
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
@media only screen and (max-width: ${theme.layout.breakpointMobile}) {
|
||||
.link {
|
||||
border-bottom: 1px solid ${theme.palette.border};
|
||||
height: 3.5rem;
|
||||
|
||||
@@ -51,7 +51,7 @@ const TabbarMobile:React.FC<Props> = ({ onClick }) => {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 767px) {
|
||||
@media only screen and (min-width: ${theme.layout.breakpointMobile}) {
|
||||
.tabbar {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import React from 'react'
|
||||
import { ZeitUIThemes } from 'components/styles/themes'
|
||||
import { DeepPartial } from 'components/utils/types'
|
||||
|
||||
export interface Configs {
|
||||
onChange?: Function
|
||||
onThemeChange?: Function
|
||||
isChinese?: boolean
|
||||
updateChineseState: Function
|
||||
sidebarScrollHeight: number
|
||||
@@ -9,6 +11,9 @@ export interface Configs {
|
||||
|
||||
tabbarFixed: boolean
|
||||
updateTabbarFixed: Function
|
||||
|
||||
customTheme: DeepPartial<ZeitUIThemes>
|
||||
updateCustomTheme: (theme: DeepPartial<ZeitUIThemes>) => void
|
||||
}
|
||||
|
||||
export const defaultConfigs: Configs = {
|
||||
@@ -18,6 +23,10 @@ export const defaultConfigs: Configs = {
|
||||
|
||||
tabbarFixed: false,
|
||||
updateTabbarFixed: () => {},
|
||||
|
||||
customTheme: {},
|
||||
updateCustomTheme: () => {},
|
||||
onThemeChange: () => {},
|
||||
}
|
||||
|
||||
export const ConfigContext = React.createContext<Configs>(defaultConfigs)
|
||||
|
||||
@@ -2,9 +2,14 @@ import React, { useMemo, useState } from 'react'
|
||||
import withDefaults from 'components/utils/with-defaults'
|
||||
import { ConfigContext, Configs } from 'lib/config-context'
|
||||
import { useRouter } from 'next/router'
|
||||
import { DeepPartial } from 'components/utils/types'
|
||||
import { ZeitUIThemes } from 'components/styles/themes'
|
||||
import { deepMergeObject } from 'components/styles/theme-provider/theme-provider'
|
||||
import useCurrentState from 'components/utils/use-current-state'
|
||||
import { useTheme } from 'components'
|
||||
|
||||
interface Props {
|
||||
onChange?: Function
|
||||
onThemeChange?: Function
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
@@ -13,23 +18,33 @@ const defaultProps = {
|
||||
export type ConfigProviderProps = Props & typeof defaultProps
|
||||
|
||||
const ConfigProvider: React.FC<React.PropsWithChildren<ConfigProviderProps>> = React.memo(({
|
||||
onChange, children,
|
||||
onThemeChange, children,
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const { pathname } = useRouter()
|
||||
const [isChinese, setIsChinese] = useState<boolean>(() => pathname.includes('zh-cn'))
|
||||
const [scrollHeight, setScrollHeight] = useState<number>(0)
|
||||
const [tabbarFixed, setTabbarFixed] = useState<boolean>(false)
|
||||
const [customTheme, setCustomTheme, customThemeRef] = useCurrentState<DeepPartial<ZeitUIThemes>>(theme)
|
||||
|
||||
const updateSidebarScrollHeight = (height: number) => setScrollHeight(height)
|
||||
const updateChineseState = (state: boolean) => setIsChinese(state)
|
||||
const updateTabbarFixed = (state: boolean) => setTabbarFixed(state)
|
||||
const updateCustomTheme = (nextTheme: DeepPartial<ZeitUIThemes>) => {
|
||||
const mergedTheme = deepMergeObject(customThemeRef.current, nextTheme)
|
||||
setCustomTheme(mergedTheme)
|
||||
onThemeChange && onThemeChange(mergedTheme)
|
||||
}
|
||||
|
||||
const initialValue = useMemo<Configs>(() => ({
|
||||
onChange, isChinese, tabbarFixed,
|
||||
onThemeChange, isChinese, tabbarFixed,
|
||||
customTheme,
|
||||
updateCustomTheme,
|
||||
updateTabbarFixed,
|
||||
updateChineseState,
|
||||
sidebarScrollHeight: scrollHeight,
|
||||
updateSidebarScrollHeight,
|
||||
}), [onChange, scrollHeight, tabbarFixed, isChinese])
|
||||
}), [onThemeChange, scrollHeight, tabbarFixed, isChinese])
|
||||
|
||||
return (
|
||||
<ConfigContext.Provider value={initialValue}>
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"name":"guide","children":[{"name":"getting-started","children":[{"name":"introduction","url":"/en-us/guide/introduction","index":5,"group":"getting-started"},{"name":"installation","url":"/en-us/guide/installation","index":10,"group":"getting-started"},{"name":"Server Render","url":"/en-us/guide/server-render","index":15,"group":"getting-started"}]},{"name":"customization","children":[{"name":"Colors","url":"/en-us/guide/colors","index":100,"group":"customization"},{"name":"Themes","url":"/en-us/guide/themes","index":100,"group":"customization"}]}]},{"name":"components","children":[{"name":"General","children":[{"name":"button","url":"/en-us/components/button","index":100,"group":"General"},{"name":"Code","url":"/en-us/components/code","index":100,"group":"General"},{"name":"Spacer","url":"/en-us/components/spacer","index":100,"group":"General"},{"name":"text","url":"/en-us/components/text","index":100,"group":"General"}]},{"name":"layout","children":[{"name":"layout","url":"/en-us/components/layout","index":100,"group":"layout"}]},{"name":"Surfaces","children":[{"name":"card","url":"/en-us/components/card","index":100,"group":"Surfaces"},{"name":"collapse","url":"/en-us/components/collapse","index":100,"group":"Surfaces"},{"name":"fieldset","url":"/en-us/components/fieldset","index":100,"group":"Surfaces"}]},{"name":"Data Entry","children":[{"name":"Auto-Complete","url":"/en-us/components/auto-complete","index":100,"group":"Data Entry"},{"name":"checkbox","url":"/en-us/components/checkbox","index":100,"group":"Data Entry"},{"name":"Input","url":"/en-us/components/input","index":100,"group":"Data Entry"},{"name":"radio","url":"/en-us/components/radio","index":100,"group":"Data Entry"},{"name":"select","url":"/en-us/components/select","index":100,"group":"Data Entry"},{"name":"textarea","url":"/en-us/components/textarea","index":100,"group":"Data Entry"},{"name":"Toggle","url":"/en-us/components/toggle","index":100,"group":"Data Entry"}]},{"name":"Data Display","children":[{"name":"avatar","url":"/en-us/components/avatar","index":100,"group":"Data Display"},{"name":"Badge","url":"/en-us/components/badge","index":100,"group":"Data Display"},{"name":"Capacity","url":"/en-us/components/capacity","index":100,"group":"Data Display"},{"name":"Description","url":"/en-us/components/description","index":100,"group":"Data Display"},{"name":"Display","url":"/en-us/components/display","index":100,"group":"Data Display"},{"name":"Dot","url":"/en-us/components/dot","index":100,"group":"Data Display"},{"name":"File-Tree","url":"/en-us/components/file-tree","index":100,"group":"Data Display"},{"name":"Image","url":"/en-us/components/image","index":100,"group":"Data Display"},{"name":"keyboard","url":"/en-us/components/keyboard","index":100,"group":"Data Display"},{"name":"Popover","url":"/en-us/components/popover","index":100,"group":"Data Display"},{"name":"Table","url":"/en-us/components/table","index":100,"group":"Data Display"},{"name":"Tag","url":"/en-us/components/tag","index":100,"group":"Data Display"},{"name":"Tooltip","url":"/en-us/components/tooltip","index":100,"group":"Data Display"}]},{"name":"Feedback","children":[{"name":"Loading","url":"/en-us/components/loading","index":100,"group":"Feedback"},{"name":"modal","url":"/en-us/components/modal","index":100,"group":"Feedback"},{"name":"note","url":"/en-us/components/note","index":100,"group":"Feedback"},{"name":"Progress","url":"/en-us/components/progress","index":100,"group":"Feedback"},{"name":"Spinner","url":"/en-us/components/spinner","index":100,"group":"Feedback"},{"name":"toast","url":"/en-us/components/toast","index":100,"group":"Feedback"}]},{"name":"Navigation","children":[{"name":"link","url":"/en-us/components/link","index":100,"group":"Navigation"},{"name":"tabs","url":"/en-us/components/tabs","index":100,"group":"Navigation"},{"name":"button-dropdown","url":"/en-us/components/button-dropdown","index":101,"group":"Navigation"}]},{"name":"Others","children":[{"name":"Snippet","url":"/en-us/components/snippet","index":100,"group":"Others"}]}]}]
|
||||
[{"name":"guide","children":[{"name":"getting-started","children":[{"name":"introduction","url":"/en-us/guide/introduction","index":5,"group":"getting-started"},{"name":"installation","url":"/en-us/guide/installation","index":10,"group":"getting-started"},{"name":"Server Render","url":"/en-us/guide/server-render","index":15,"group":"getting-started"}]},{"name":"customization","children":[{"name":"Colors","url":"/en-us/guide/colors","index":100,"group":"customization"},{"name":"Themes","url":"/en-us/guide/themes","index":100,"group":"customization"}]}]},{"name":"components","children":[{"name":"General","children":[{"name":"button","url":"/en-us/components/button","index":100,"group":"General"},{"name":"Code","url":"/en-us/components/code","index":100,"group":"General"},{"name":"Spacer","url":"/en-us/components/spacer","index":100,"group":"General"},{"name":"text","url":"/en-us/components/text","index":100,"group":"General"}]},{"name":"layout","children":[{"name":"layout","url":"/en-us/components/layout","index":100,"group":"layout"}]},{"name":"Surfaces","children":[{"name":"card","url":"/en-us/components/card","index":100,"group":"Surfaces"},{"name":"collapse","url":"/en-us/components/collapse","index":100,"group":"Surfaces"},{"name":"fieldset","url":"/en-us/components/fieldset","index":100,"group":"Surfaces"}]},{"name":"Data Entry","children":[{"name":"Auto-Complete","url":"/en-us/components/auto-complete","index":100,"group":"Data Entry"},{"name":"checkbox","url":"/en-us/components/checkbox","index":100,"group":"Data Entry"},{"name":"Input","url":"/en-us/components/input","index":100,"group":"Data Entry"},{"name":"radio","url":"/en-us/components/radio","index":100,"group":"Data Entry"},{"name":"select","url":"/en-us/components/select","index":100,"group":"Data Entry"},{"name":"textarea","url":"/en-us/components/textarea","index":100,"group":"Data Entry"},{"name":"Toggle","url":"/en-us/components/toggle","index":100,"group":"Data Entry"}]},{"name":"Data Display","children":[{"name":"avatar","url":"/en-us/components/avatar","index":100,"group":"Data Display"},{"name":"Badge","url":"/en-us/components/badge","index":100,"group":"Data Display"},{"name":"Capacity","url":"/en-us/components/capacity","index":100,"group":"Data Display"},{"name":"Description","url":"/en-us/components/description","index":100,"group":"Data Display"},{"name":"Display","url":"/en-us/components/display","index":100,"group":"Data Display"},{"name":"Dot","url":"/en-us/components/dot","index":100,"group":"Data Display"},{"name":"File-Tree","url":"/en-us/components/file-tree","index":100,"group":"Data Display"},{"name":"Image","url":"/en-us/components/image","index":100,"group":"Data Display"},{"name":"keyboard","url":"/en-us/components/keyboard","index":100,"group":"Data Display"},{"name":"Popover","url":"/en-us/components/popover","index":100,"group":"Data Display"},{"name":"Table","url":"/en-us/components/table","index":100,"group":"Data Display"},{"name":"Tag","url":"/en-us/components/tag","index":100,"group":"Data Display"},{"name":"Tooltip","url":"/en-us/components/tooltip","index":100,"group":"Data Display"}]},{"name":"Feedback","children":[{"name":"Loading","url":"/en-us/components/loading","index":100,"group":"Feedback"},{"name":"modal","url":"/en-us/components/modal","index":100,"group":"Feedback"},{"name":"note","url":"/en-us/components/note","index":100,"group":"Feedback"},{"name":"Progress","url":"/en-us/components/progress","index":100,"group":"Feedback"},{"name":"Spinner","url":"/en-us/components/spinner","index":100,"group":"Feedback"},{"name":"toast","url":"/en-us/components/toast","index":100,"group":"Feedback"}]},{"name":"Navigation","children":[{"name":"link","url":"/en-us/components/link","index":100,"group":"Navigation"},{"name":"tabs","url":"/en-us/components/tabs","index":100,"group":"Navigation"},{"name":"button-dropdown","url":"/en-us/components/button-dropdown","index":101,"group":"Navigation"}]},{"name":"Others","children":[{"name":"Snippet","url":"/en-us/components/snippet","index":100,"group":"Others"}]}]},{"name":"customization","children":[]}]
|
||||
|
||||
@@ -1 +1 @@
|
||||
[{"name":"guide","children":[{"name":"快速上手","children":[{"name":"什么是 ZEIT UI","url":"/zh-cn/guide/introduction","index":5,"group":"快速上手"},{"name":"安装","url":"/zh-cn/guide/installation","index":10,"group":"快速上手"},{"name":"服务端渲染","url":"/zh-cn/guide/server-render","index":15,"group":"快速上手"}]},{"name":"定制化","children":[{"name":"色彩","url":"/zh-cn/guide/colors","index":100,"group":"定制化"},{"name":"主题","url":"/zh-cn/guide/themes","index":100,"group":"定制化"}]}],"localeName":"上手指南"},{"name":"components","children":[{"name":"通用","children":[{"name":"按钮 Button","url":"/zh-cn/components/button","index":100,"group":"通用"},{"name":"代码 Code","url":"/zh-cn/components/code","index":100,"group":"通用"},{"name":"间距 Spacer","url":"/zh-cn/components/spacer","index":100,"group":"通用"},{"name":"文本 Text","url":"/zh-cn/components/text","index":100,"group":"通用"}]},{"name":"布局","children":[{"name":"布局 Layout","url":"/zh-cn/components/layout","index":100,"group":"布局"}]},{"name":"表面","children":[{"name":"卡片 Card","url":"/zh-cn/components/card","index":100,"group":"表面"},{"name":"折叠框 Collapse","url":"/zh-cn/components/collapse","index":100,"group":"表面"},{"name":"控件组 Fieldset","url":"/zh-cn/components/fieldset","index":100,"group":"表面"}]},{"name":"数据录入","children":[{"name":"复选框 Checkbox","url":"/zh-cn/components/checkbox","index":100,"group":"数据录入"},{"name":"输入框 Input","url":"/zh-cn/components/input","index":100,"group":"数据录入"},{"name":"单选框 Radio","url":"/zh-cn/components/radio","index":100,"group":"数据录入"},{"name":"选择器 Select","url":"/zh-cn/components/select","index":100,"group":"数据录入"},{"name":"文本输入框 Textarea","url":"/zh-cn/components/textarea","index":100,"group":"数据录入"},{"name":"开关 Toggle","url":"/zh-cn/components/toggle","index":100,"group":"数据录入"},{"name":"自动完成 Auto-Complete","url":"/zh-cn/components/auto-complete","index":104,"group":"数据录入"}]},{"name":"数据展示","children":[{"name":"头像 Avatar","url":"/zh-cn/components/avatar","index":100,"group":"数据展示"},{"name":"徽章 Badge","url":"/zh-cn/components/badge","index":100,"group":"数据展示"},{"name":"容量 Capacity","url":"/zh-cn/components/capacity","index":100,"group":"数据展示"},{"name":"描述 Description","url":"/zh-cn/components/description","index":100,"group":"数据展示"},{"name":"陈列框 Display","url":"/zh-cn/components/display","index":100,"group":"数据展示"},{"name":"点 Dot","url":"/zh-cn/components/dot","index":100,"group":"数据展示"},{"name":"文件树 File Tree","url":"/zh-cn/components/file-tree","index":100,"group":"数据展示"},{"name":"图片 Image","url":"/zh-cn/components/image","index":100,"group":"数据展示"},{"name":"键盘 keyboard","url":"/zh-cn/components/keyboard","index":100,"group":"数据展示"},{"name":"气泡卡片 Popover","url":"/zh-cn/components/popover","index":100,"group":"数据展示"},{"name":"表格 Table","url":"/zh-cn/components/table","index":100,"group":"数据展示"},{"name":"标签 Tag","url":"/zh-cn/components/tag","index":100,"group":"数据展示"},{"name":"文字提示 Tooltip","url":"/zh-cn/components/tooltip","index":100,"group":"数据展示"}]},{"name":"反馈","children":[{"name":"加载中 Loading","url":"/zh-cn/components/loading","index":100,"group":"反馈"},{"name":"对话框 Modal","url":"/zh-cn/components/modal","index":100,"group":"反馈"},{"name":"提示 Note","url":"/zh-cn/components/note","index":100,"group":"反馈"},{"name":"进度条 Progress","url":"/zh-cn/components/progress","index":100,"group":"反馈"},{"name":"指示器 Spinner","url":"/zh-cn/components/spinner","index":100,"group":"反馈"},{"name":"通知 Toast","url":"/zh-cn/components/toast","index":100,"group":"反馈"}]},{"name":"导航","children":[{"name":"链接 Link","url":"/zh-cn/components/link","index":100,"group":"导航"},{"name":"选项卡 Tabs","url":"/zh-cn/components/tabs","index":100,"group":"导航"},{"name":"下拉按钮 Btn Dropdown","url":"/zh-cn/components/button-dropdown","index":105,"group":"导航"}]},{"name":"其他","children":[{"name":"片段 Snippet","url":"/zh-cn/components/snippet","index":100,"group":"其他"}]}],"localeName":"所有组件"}]
|
||||
[{"name":"guide","children":[{"name":"快速上手","children":[{"name":"什么是 ZEIT UI","url":"/zh-cn/guide/introduction","index":5,"group":"快速上手"},{"name":"安装","url":"/zh-cn/guide/installation","index":10,"group":"快速上手"},{"name":"服务端渲染","url":"/zh-cn/guide/server-render","index":15,"group":"快速上手"}]},{"name":"定制化","children":[{"name":"色彩","url":"/zh-cn/guide/colors","index":100,"group":"定制化"},{"name":"主题","url":"/zh-cn/guide/themes","index":100,"group":"定制化"}]}],"localeName":"上手指南"},{"name":"components","children":[{"name":"通用","children":[{"name":"按钮 Button","url":"/zh-cn/components/button","index":100,"group":"通用"},{"name":"代码 Code","url":"/zh-cn/components/code","index":100,"group":"通用"},{"name":"间距 Spacer","url":"/zh-cn/components/spacer","index":100,"group":"通用"},{"name":"文本 Text","url":"/zh-cn/components/text","index":100,"group":"通用"}]},{"name":"布局","children":[{"name":"布局 Layout","url":"/zh-cn/components/layout","index":100,"group":"布局"}]},{"name":"表面","children":[{"name":"卡片 Card","url":"/zh-cn/components/card","index":100,"group":"表面"},{"name":"折叠框 Collapse","url":"/zh-cn/components/collapse","index":100,"group":"表面"},{"name":"控件组 Fieldset","url":"/zh-cn/components/fieldset","index":100,"group":"表面"}]},{"name":"数据录入","children":[{"name":"复选框 Checkbox","url":"/zh-cn/components/checkbox","index":100,"group":"数据录入"},{"name":"输入框 Input","url":"/zh-cn/components/input","index":100,"group":"数据录入"},{"name":"单选框 Radio","url":"/zh-cn/components/radio","index":100,"group":"数据录入"},{"name":"选择器 Select","url":"/zh-cn/components/select","index":100,"group":"数据录入"},{"name":"文本输入框 Textarea","url":"/zh-cn/components/textarea","index":100,"group":"数据录入"},{"name":"开关 Toggle","url":"/zh-cn/components/toggle","index":100,"group":"数据录入"},{"name":"自动完成 Auto-Complete","url":"/zh-cn/components/auto-complete","index":104,"group":"数据录入"}]},{"name":"数据展示","children":[{"name":"头像 Avatar","url":"/zh-cn/components/avatar","index":100,"group":"数据展示"},{"name":"徽章 Badge","url":"/zh-cn/components/badge","index":100,"group":"数据展示"},{"name":"容量 Capacity","url":"/zh-cn/components/capacity","index":100,"group":"数据展示"},{"name":"描述 Description","url":"/zh-cn/components/description","index":100,"group":"数据展示"},{"name":"陈列框 Display","url":"/zh-cn/components/display","index":100,"group":"数据展示"},{"name":"点 Dot","url":"/zh-cn/components/dot","index":100,"group":"数据展示"},{"name":"文件树 File Tree","url":"/zh-cn/components/file-tree","index":100,"group":"数据展示"},{"name":"图片 Image","url":"/zh-cn/components/image","index":100,"group":"数据展示"},{"name":"键盘 keyboard","url":"/zh-cn/components/keyboard","index":100,"group":"数据展示"},{"name":"气泡卡片 Popover","url":"/zh-cn/components/popover","index":100,"group":"数据展示"},{"name":"表格 Table","url":"/zh-cn/components/table","index":100,"group":"数据展示"},{"name":"标签 Tag","url":"/zh-cn/components/tag","index":100,"group":"数据展示"},{"name":"文字提示 Tooltip","url":"/zh-cn/components/tooltip","index":100,"group":"数据展示"}]},{"name":"反馈","children":[{"name":"加载中 Loading","url":"/zh-cn/components/loading","index":100,"group":"反馈"},{"name":"对话框 Modal","url":"/zh-cn/components/modal","index":100,"group":"反馈"},{"name":"提示 Note","url":"/zh-cn/components/note","index":100,"group":"反馈"},{"name":"进度条 Progress","url":"/zh-cn/components/progress","index":100,"group":"反馈"},{"name":"指示器 Spinner","url":"/zh-cn/components/spinner","index":100,"group":"反馈"},{"name":"通知 Toast","url":"/zh-cn/components/toast","index":100,"group":"反馈"}]},{"name":"导航","children":[{"name":"链接 Link","url":"/zh-cn/components/link","index":100,"group":"导航"},{"name":"选项卡 Tabs","url":"/zh-cn/components/tabs","index":100,"group":"导航"},{"name":"下拉按钮 Btn Dropdown","url":"/zh-cn/components/button-dropdown","index":105,"group":"导航"}]},{"name":"其他","children":[{"name":"片段 Snippet","url":"/zh-cn/components/snippet","index":100,"group":"其他"}]}],"localeName":"所有组件"},{"name":"customization","children":[],"localeName":"定制化"}]
|
||||
|
||||
@@ -39,21 +39,11 @@ const nextConfig = {
|
||||
permanent: true,
|
||||
destination: '/en-us/guide/:path*'
|
||||
},
|
||||
{
|
||||
source: '/en-us/customization/:path*',
|
||||
permanent: true,
|
||||
destination: '/en-us/guide/:path*'
|
||||
},
|
||||
{
|
||||
source: '/zh-cn/getting-started/:path*',
|
||||
permanent: true,
|
||||
destination: '/zh-cn/guide/:path*'
|
||||
},
|
||||
{
|
||||
source: '/zh-cn/customization/:path*',
|
||||
permanent: true,
|
||||
destination: '/zh-cn/guide/:path*'
|
||||
},
|
||||
{
|
||||
source: '/zh-cn/',
|
||||
permanent: true,
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
"@mdx-js/loader": "^1.5.7",
|
||||
"@next/mdx": "^9.2.2",
|
||||
"@types/react": "^16.9.22",
|
||||
"@types/react-color": "^3.0.1",
|
||||
"@types/react-dom": "^16.9.5",
|
||||
"@types/styled-jsx": "^2.2.8",
|
||||
"@typescript-eslint/eslint-plugin": "^2.24.0",
|
||||
@@ -61,6 +62,7 @@
|
||||
"fs-extra": "^8.1.0",
|
||||
"next": "^9.3.2",
|
||||
"react": "^16.13.0",
|
||||
"react-color": "^2.18.0",
|
||||
"react-dom": "^16.13.0",
|
||||
"react-live": "^2.2.2",
|
||||
"styled-jsx": "^3.2.4",
|
||||
@@ -69,4 +71,4 @@
|
||||
"webpack-cli": "^3.3.11"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import Head from 'next/head'
|
||||
import { NextPage } from 'next'
|
||||
import { AppProps } from 'next/app'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { CSSBaseline, ZEITUIProvider, useTheme } from 'components'
|
||||
import { useState } from 'react'
|
||||
import { CSSBaseline, ZEITUIProvider, useTheme, ZeitUIThemes } from 'components'
|
||||
import Menu from 'lib/components/menu'
|
||||
import ConfigContext from 'lib/config-provider'
|
||||
import { DeepPartial } from 'components/utils/types'
|
||||
|
||||
const Application: NextPage<AppProps> = ({ Component, pageProps }) => {
|
||||
const theme = useTheme()
|
||||
const [themeType, setThemeType] = useState<typeof theme.type>(theme.type)
|
||||
const changeHandle = useCallback((isDark: boolean) => {
|
||||
setThemeType(isDark ? 'dark' : 'light')
|
||||
}, [])
|
||||
const [customTheme, setCustomTheme] = useState<DeepPartial<ZeitUIThemes>>({})
|
||||
const themeChangeHandle = (theme: DeepPartial<ZeitUIThemes>) => {
|
||||
setCustomTheme(theme)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -32,9 +33,9 @@ const Application: NextPage<AppProps> = ({ Component, pageProps }) => {
|
||||
<meta property="twitter:image" content="https://user-images.githubusercontent.com/11304944/76085431-fd036480-5fec-11ea-8412-9e581425344a.png" />
|
||||
<meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, viewport-fit=cover" />
|
||||
</Head>
|
||||
<ZEITUIProvider theme={{ type: themeType }}>
|
||||
<ZEITUIProvider theme={customTheme}>
|
||||
<CSSBaseline />
|
||||
<ConfigContext onChange={changeHandle}>
|
||||
<ConfigContext onThemeChange={themeChangeHandle}>
|
||||
<Menu />
|
||||
<Component {...pageProps} />
|
||||
</ConfigContext>
|
||||
|
||||
@@ -251,6 +251,7 @@ AutoComplete control of input field.
|
||||
|
||||
| Attribute | Description | Type | Accepted values | Default
|
||||
| ---------- | ---------- | ---- | -------------- | ------ |
|
||||
| hidden | hide empty box | `boolean` | - | `false` |
|
||||
| ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - |
|
||||
|
||||
<Attributes.Title>type AutoCompleteOptions</Attributes.Title>
|
||||
|
||||
18
pages/en-us/customization/index.tsx
Normal file
18
pages/en-us/customization/index.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import React from 'react'
|
||||
import { Text, Spacer } from 'components'
|
||||
import CustomizationLayout from 'lib/components/customization/layout'
|
||||
import CustomizationEditor from 'lib/components/customization/editor'
|
||||
|
||||
const Customization = () => {
|
||||
return (
|
||||
<CustomizationLayout>
|
||||
<Spacer y={1.2} />
|
||||
<Text h2>Customization</Text>
|
||||
<Text>Custom themes is a very simple thing in ZEIT UI, click change, copy or share.</Text>
|
||||
<CustomizationEditor />
|
||||
<Spacer y={2} />
|
||||
</CustomizationLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default Customization
|
||||
@@ -252,6 +252,7 @@ export const meta = {
|
||||
|
||||
| 属性 | 描述 | 类型 | 推荐值 | 默认
|
||||
| ---------- | ---------- | ---- | -------------- | ------ |
|
||||
| hidden | 隐藏无结果提示框 | `boolean` | - | `false` |
|
||||
| ... | 原生属性 | `HTMLAttributes` | `'id', 'className', ...` | - |
|
||||
|
||||
<Attributes.Title>type AutoCompleteOptions</Attributes.Title>
|
||||
|
||||
18
pages/zh-cn/customization/index.tsx
Normal file
18
pages/zh-cn/customization/index.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import React from 'react'
|
||||
import { Text, Spacer } from 'components'
|
||||
import CustomizationLayout from 'lib/components/customization/layout'
|
||||
import CustomizationEditor from 'lib/components/customization/editor'
|
||||
|
||||
const Customization = () => {
|
||||
return (
|
||||
<CustomizationLayout>
|
||||
<Spacer y={1.2} />
|
||||
<Text h2>定制化</Text>
|
||||
<Text>在 ZEIT UI 中自定义主题非常简单,点击更改,然后拷贝或是分享。</Text>
|
||||
<CustomizationEditor />
|
||||
<Spacer y={2} />
|
||||
</CustomizationLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default Customization
|
||||
@@ -11,8 +11,8 @@ const weights = {
|
||||
'guide': 1,
|
||||
'docs': 2,
|
||||
'getting-started': 3,
|
||||
'customization': 4,
|
||||
'components': 5,
|
||||
'customization': 10,
|
||||
}
|
||||
const groupWeights = {
|
||||
'快速上手': 1,
|
||||
|
||||
45
yarn.lock
45
yarn.lock
@@ -1020,6 +1020,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7"
|
||||
integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==
|
||||
|
||||
"@icons/material@^0.2.4":
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8"
|
||||
integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==
|
||||
|
||||
"@mapbox/rehype-prism@^0.4.0":
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/rehype-prism/-/rehype-prism-0.4.0.tgz#58714b345ec01256aa74c24762a341f6a771494e"
|
||||
@@ -1125,6 +1130,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
|
||||
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
|
||||
|
||||
"@types/react-color@^3.0.1":
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-color/-/react-color-3.0.1.tgz#5433e2f503ea0e0831cbc6fd0c20f8157d93add0"
|
||||
integrity sha512-J6mYm43Sid9y+OjZ7NDfJ2VVkeeuTPNVImNFITgQNXodHteKfl/t/5pAR5Z9buodZ2tCctsZjgiMlQOpfntakw==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-dom@^16.9.5":
|
||||
version "16.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.5.tgz#5de610b04a35d07ffd8f44edad93a71032d9aaa7"
|
||||
@@ -4728,7 +4740,7 @@ lodash.uniq@4.5.0:
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
|
||||
|
||||
lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4:
|
||||
lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
@@ -4824,6 +4836,11 @@ markdown-escapes@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535"
|
||||
integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==
|
||||
|
||||
material-colors@^1.2.1:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46"
|
||||
integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==
|
||||
|
||||
md5.js@^1.3.4:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
|
||||
@@ -6239,7 +6256,7 @@ prop-types-exact@1.2.0:
|
||||
object.assign "^4.1.0"
|
||||
reflect.ownkeys "^0.2.0"
|
||||
|
||||
prop-types@15.7.2, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
@@ -6360,6 +6377,18 @@ raw-body@2.4.0:
|
||||
iconv-lite "0.4.24"
|
||||
unpipe "1.0.0"
|
||||
|
||||
react-color@^2.18.0:
|
||||
version "2.18.0"
|
||||
resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.18.0.tgz#34956f0bac394f6c3bc01692fd695644cc775ffd"
|
||||
integrity sha512-FyVeU1kQiSokWc8NPz22azl1ezLpJdUyTbWL0LPUpcuuYDrZ/Y1veOk9rRK5B3pMlyDGvTk4f4KJhlkIQNRjEA==
|
||||
dependencies:
|
||||
"@icons/material" "^0.2.4"
|
||||
lodash "^4.17.11"
|
||||
material-colors "^1.2.1"
|
||||
prop-types "^15.5.10"
|
||||
reactcss "^1.2.0"
|
||||
tinycolor2 "^1.4.1"
|
||||
|
||||
react-dom@^16.13.0:
|
||||
version "16.13.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.0.tgz#cdde54b48eb9e8a0ca1b3dc9943d9bb409b81866"
|
||||
@@ -6413,6 +6442,13 @@ react@^16.13.0:
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
reactcss@^1.2.0:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/reactcss/-/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd"
|
||||
integrity sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==
|
||||
dependencies:
|
||||
lodash "^4.0.1"
|
||||
|
||||
read-pkg@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8"
|
||||
@@ -7443,6 +7479,11 @@ tiny-emitter@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
|
||||
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
|
||||
|
||||
tinycolor2@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8"
|
||||
integrity sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=
|
||||
|
||||
title-case@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa"
|
||||
|
||||
Reference in New Issue
Block a user