Browse Source
* docs: put an example loading component
* fix: site issue
* fix: site issue
* feat: add loading
* feat: alert
* docs: rm ReactDOM.render in md
* docs: use style tag
* chore: update snapshot
* Revert "docs: use style tag"
This reverts commit 1f75a99f8c
.
* docs: update demo
* chore: update demo
Co-authored-by: PeachScript <scdzwyxst@gmail.com>
pull/38588/head
MadCcc
2 years ago
committed by
GitHub
42 changed files with 1492 additions and 492 deletions
@ -0,0 +1,8 @@ |
|||
import { Alert, AlertProps } from 'antd'; |
|||
import React, { FC } from 'react'; |
|||
|
|||
const MdAlert: FC<AlertProps> = ({ style, ...props }) => { |
|||
return <Alert {...props} style={{ margin: '24px 0', ...style }} />; |
|||
}; |
|||
|
|||
export default MdAlert; |
@ -0,0 +1,4 @@ |
|||
// @ts-ignore
|
|||
import ColorPaletteTool from '../../common/Color/ColorPaletteTool'; |
|||
|
|||
export default ColorPaletteTool; |
@ -0,0 +1,4 @@ |
|||
// @ts-ignore
|
|||
import ColorPaletteToolDark from '../../common/Color/ColorPaletteToolDark'; |
|||
|
|||
export default ColorPaletteToolDark; |
@ -0,0 +1,4 @@ |
|||
// @ts-ignore
|
|||
import ColorPalettes from '../../common/Color/ColorPalettes'; |
|||
|
|||
export default ColorPalettes; |
@ -0,0 +1,4 @@ |
|||
// @ts-ignore
|
|||
import Palette from '../../common/Color/Palette'; |
|||
|
|||
export default Palette; |
@ -0,0 +1,36 @@ |
|||
import React, { Component } from 'react'; |
|||
import CopyToClipboard from 'react-copy-to-clipboard'; |
|||
import { message } from 'antd'; |
|||
|
|||
export default class ColorBlock extends Component { |
|||
getTextStyle() { |
|||
const { color, index, dark } = this.props; |
|||
const colorMap = { |
|||
default: ['#fff', 'unset'], |
|||
dark: ['#314659', '#fff'], |
|||
}; |
|||
const [lastColor, firstColor] = dark ? colorMap.dark : colorMap.default; |
|||
return { |
|||
background: color, |
|||
color: index > 5 ? lastColor : firstColor, |
|||
fontWeight: index === 6 ? 'bold' : 'normal', |
|||
}; |
|||
} |
|||
|
|||
onCopied = () => { |
|||
const { color } = this.props; |
|||
message.success(`Copied: ${color}`); |
|||
}; |
|||
|
|||
render() { |
|||
const { color, index } = this.props; |
|||
return ( |
|||
<CopyToClipboard text={color} onCopy={this.onCopied} title="click to copy color"> |
|||
<div className="main-color-item" style={this.getTextStyle()}> |
|||
color-{index} |
|||
<span className="main-color-value">{color.toLowerCase()}</span> |
|||
</div> |
|||
</CopyToClipboard> |
|||
); |
|||
} |
|||
} |
@ -0,0 +1,61 @@ |
|||
import React, { Component } from 'react'; |
|||
import { FormattedMessage } from 'dumi'; |
|||
import ColorPicker from './ColorPicker'; |
|||
import ColorPatterns from './ColorPatterns'; |
|||
|
|||
const primaryMinSaturation = 70; // 主色推荐最小饱和度 |
|||
const primaryMinBrightness = 70; // 主色推荐最小亮度 |
|||
|
|||
export default class ColorPaletteTool extends Component { |
|||
state = { |
|||
primaryColor: '#1890ff', |
|||
primaryColorInstance: null, |
|||
}; |
|||
|
|||
handleChangeColor = (e, color) => { |
|||
const value = e.target ? e.target.value : e; |
|||
this.setState({ |
|||
primaryColor: value, |
|||
primaryColorInstance: color, |
|||
}); |
|||
}; |
|||
|
|||
renderColorValidation() { |
|||
const { primaryColorInstance } = this.state; |
|||
let text = ''; |
|||
if (primaryColorInstance) { |
|||
if (primaryColorInstance.hsv.s * 100 < primaryMinSaturation) { |
|||
text += ` 饱和度建议不低于${primaryMinSaturation}(现在 ${( |
|||
primaryColorInstance.hsv.s * 100 |
|||
).toFixed(2)})`; |
|||
} |
|||
if (primaryColorInstance.hsv.v * 100 < primaryMinBrightness) { |
|||
text += ` 亮度建议不低于${primaryMinBrightness}(现在 ${( |
|||
primaryColorInstance.hsv.v * 100 |
|||
).toFixed(2)})`; |
|||
} |
|||
} |
|||
return <span className="color-palette-picker-validation">{text.trim()}</span>; |
|||
} |
|||
|
|||
render() { |
|||
const { primaryColor } = this.state; |
|||
return ( |
|||
<div className="color-palette-horizontal"> |
|||
<div className="color-palette-pick"> |
|||
<FormattedMessage id="app.docs.color.pick-primary" /> |
|||
</div> |
|||
<div className="main-color"> |
|||
<ColorPatterns color={primaryColor} /> |
|||
</div> |
|||
<div className="color-palette-picker"> |
|||
<span style={{ display: 'inline-block', verticalAlign: 'middle' }}> |
|||
<ColorPicker type="chrome" color={primaryColor} onChange={this.handleChangeColor} /> |
|||
</span> |
|||
<span className="color-palette-picker-value">{primaryColor}</span> |
|||
{this.renderColorValidation()} |
|||
</div> |
|||
</div> |
|||
); |
|||
} |
|||
} |
@ -0,0 +1,107 @@ |
|||
import React, { Component } from 'react'; |
|||
import { FormattedMessage } from 'dumi'; |
|||
import { Row, Col } from 'antd'; |
|||
import ColorPicker from './ColorPicker'; |
|||
import ColorPatterns from './ColorPatterns'; |
|||
|
|||
const primaryMinSaturation = 70; // 主色推荐最小饱和度 |
|||
const primaryMinBrightness = 70; // 主色推荐最小亮度 |
|||
|
|||
export default class ColorPaletteTool extends Component { |
|||
state = { |
|||
primaryColor: '#1890ff', |
|||
backgroundColor: '#141414', |
|||
primaryColorInstance: null, |
|||
}; |
|||
|
|||
handleChangeColor = (e, color) => { |
|||
const value = e.target ? e.target.value : e; |
|||
this.setState({ |
|||
primaryColor: value, |
|||
primaryColorInstance: color, |
|||
}); |
|||
}; |
|||
|
|||
handleChangeBackgroundColor = e => { |
|||
const value = e.target ? e.target.value : e; |
|||
this.setState({ |
|||
backgroundColor: value, |
|||
}); |
|||
}; |
|||
|
|||
renderColorValidation() { |
|||
const { primaryColorInstance } = this.state; |
|||
let text = ''; |
|||
if (primaryColorInstance) { |
|||
if (primaryColorInstance.hsv.s * 100 < primaryMinSaturation) { |
|||
text += ` 饱和度建议不低于${primaryMinSaturation}(现在 ${( |
|||
primaryColorInstance.hsv.s * 100 |
|||
).toFixed(2)})`; |
|||
} |
|||
if (primaryColorInstance.hsv.v * 100 < primaryMinBrightness) { |
|||
text += ` 亮度建议不低于${primaryMinBrightness}(现在 ${( |
|||
primaryColorInstance.hsv.v * 100 |
|||
).toFixed(2)})`; |
|||
} |
|||
} |
|||
return ( |
|||
<span className="color-palette-picker-validation color-palette-picker-validation-dark"> |
|||
{text.trim()} |
|||
</span> |
|||
); |
|||
} |
|||
|
|||
render() { |
|||
const { primaryColor, backgroundColor } = this.state; |
|||
return ( |
|||
<div className="color-palette-horizontal color-palette-horizontal-dark"> |
|||
<div className="main-color"> |
|||
<ColorPatterns color={primaryColor} dark backgroundColor={backgroundColor} /> |
|||
</div> |
|||
<div className="color-palette-picker"> |
|||
<Row> |
|||
<Col span={12}> |
|||
<div className="color-palette-pick"> |
|||
<FormattedMessage id="app.docs.color.pick-primary" /> |
|||
</div> |
|||
<span style={{ display: 'inline-block', verticalAlign: 'middle' }}> |
|||
<Row> |
|||
<Col span={18}> |
|||
<ColorPicker |
|||
type="chrome" |
|||
color={primaryColor} |
|||
onChange={this.handleChangeColor} |
|||
/> |
|||
</Col> |
|||
<Col span={6}> |
|||
<span className="color-palette-pick-hex">{primaryColor}</span> |
|||
</Col> |
|||
</Row> |
|||
</span> |
|||
</Col> |
|||
<Col span={12}> |
|||
<div className="color-palette-pick"> |
|||
<FormattedMessage id="app.docs.color.pick-background" /> |
|||
</div> |
|||
<span style={{ display: 'inline-block', verticalAlign: 'middle' }}> |
|||
<Row> |
|||
<Col span={18}> |
|||
<ColorPicker |
|||
type="chrome" |
|||
color={backgroundColor} |
|||
onChange={this.handleChangeBackgroundColor} |
|||
/> |
|||
</Col> |
|||
<Col span={6}> |
|||
<span className="color-palette-pick-hex">{backgroundColor}</span> |
|||
</Col> |
|||
</Row> |
|||
</span> |
|||
</Col> |
|||
</Row> |
|||
{this.renderColorValidation()} |
|||
</div> |
|||
</div> |
|||
); |
|||
} |
|||
} |
@ -0,0 +1,94 @@ |
|||
import React from 'react'; |
|||
import cls from 'classnames'; |
|||
import Palette from './Palette'; |
|||
|
|||
const ColorPalettes = props => { |
|||
const { dark } = props; |
|||
|
|||
const colors = [ |
|||
{ |
|||
name: 'red', |
|||
english: 'Dust Red', |
|||
chinese: '薄暮', |
|||
description: '斗志、奔放', |
|||
}, |
|||
{ |
|||
name: 'volcano', |
|||
english: 'Volcano', |
|||
chinese: '火山', |
|||
description: '醒目、澎湃', |
|||
}, |
|||
{ |
|||
name: 'orange', |
|||
english: 'Sunset Orange', |
|||
chinese: '日暮', |
|||
description: '温暖、欢快', |
|||
}, |
|||
{ |
|||
name: 'gold', |
|||
english: 'Calendula Gold', |
|||
chinese: '金盏花', |
|||
description: '活力、积极', |
|||
}, |
|||
{ |
|||
name: 'yellow', |
|||
english: 'Sunrise Yellow', |
|||
chinese: '日出', |
|||
description: '出生、阳光', |
|||
}, |
|||
{ |
|||
name: 'lime', |
|||
english: 'Lime', |
|||
chinese: '青柠', |
|||
description: '自然、生机', |
|||
}, |
|||
{ |
|||
name: 'green', |
|||
english: 'Polar Green', |
|||
chinese: '极光绿', |
|||
description: '健康、创新', |
|||
}, |
|||
{ |
|||
name: 'cyan', |
|||
english: 'Cyan', |
|||
chinese: '明青', |
|||
description: '希望、坚强', |
|||
}, |
|||
{ |
|||
name: 'blue', |
|||
english: 'Daybreak Blue', |
|||
chinese: '拂晓蓝', |
|||
description: '包容、科技、普惠', |
|||
}, |
|||
{ |
|||
name: 'geekblue', |
|||
english: 'Geek Blue', |
|||
chinese: '极客蓝', |
|||
description: '探索、钻研', |
|||
}, |
|||
{ |
|||
name: 'purple', |
|||
english: 'Golden Purple', |
|||
chinese: '酱紫', |
|||
description: '优雅、浪漫', |
|||
}, |
|||
{ |
|||
name: 'magenta', |
|||
english: 'Magenta', |
|||
chinese: '法式洋红', |
|||
description: '明快、感性', |
|||
}, |
|||
]; |
|||
const colorCls = cls('color-palettes', { |
|||
'color-palettes-dark': !!dark, |
|||
}); |
|||
return ( |
|||
<div className={colorCls}> |
|||
{colors.map(color => ( |
|||
<Palette key={color.name} color={color} dark={dark} showTitle /> |
|||
))} |
|||
</div> |
|||
); |
|||
}; |
|||
|
|||
export default ColorPalettes; |
@ -0,0 +1,11 @@ |
|||
import React from 'react'; |
|||
import { generate } from '@ant-design/colors'; |
|||
import uniq from 'lodash/uniq'; |
|||
import ColorBlock from './ColorBlock'; |
|||
|
|||
export default function ColorPatterns({ color, dark, backgroundColor }) { |
|||
const colors = generate(color, dark ? { theme: 'dark', backgroundColor } : {}); |
|||
return uniq(colors).map((colorString, i) => ( |
|||
<ColorBlock color={colorString} index={i + 1} dark={dark} key={colorString} /> |
|||
)); |
|||
} |
@ -0,0 +1,126 @@ |
|||
import React, { Component } from 'react'; |
|||
import { SketchPicker } from 'react-color'; |
|||
|
|||
const noop = () => {}; |
|||
|
|||
interface ColorPickerProps { |
|||
color?: string; |
|||
small: boolean; |
|||
position: string; |
|||
presetColors?: string[]; |
|||
onChange: (hex: string, color: { hex: string }) => void; |
|||
onChangeComplete: (hex: string) => void; |
|||
} |
|||
|
|||
export default class ColorPicker extends Component<ColorPickerProps> { |
|||
static getDerivedStateFromProps(props: ColorPickerProps) { |
|||
if ('color' in props) { |
|||
return { |
|||
color: props.color, |
|||
}; |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
state = { |
|||
displayColorPicker: false, |
|||
color: undefined, |
|||
}; |
|||
|
|||
handleClick = () => { |
|||
const { displayColorPicker } = this.state; |
|||
this.setState({ displayColorPicker: !displayColorPicker }); |
|||
}; |
|||
|
|||
handleClose = () => { |
|||
this.setState({ displayColorPicker: false }); |
|||
}; |
|||
|
|||
handleChange = (color: { hex: string }) => { |
|||
const { onChange = noop } = this.props; |
|||
this.setState({ color: color.hex }); |
|||
onChange(color.hex, color); |
|||
}; |
|||
|
|||
handleChangeComplete = (color: { hex: string }) => { |
|||
const { onChangeComplete = noop } = this.props; |
|||
this.setState({ color: color.hex }); |
|||
onChangeComplete(color.hex); |
|||
}; |
|||
|
|||
render() { |
|||
const { small, position = 'bottom', presetColors } = this.props; |
|||
const { color, displayColorPicker } = this.state; |
|||
const width = small ? 80 : 120; |
|||
const styles: Record<PropertyKey, React.CSSProperties> = { |
|||
color: { |
|||
width: `${width}px`, |
|||
height: small ? '16px' : '24px', |
|||
borderRadius: '2px', |
|||
background: color, |
|||
}, |
|||
swatch: { |
|||
padding: '4px', |
|||
background: '#fff', |
|||
borderRadius: '2px', |
|||
boxShadow: '0 0 0 1px rgba(0,0,0,.1)', |
|||
display: 'inline-block', |
|||
cursor: 'pointer', |
|||
}, |
|||
popover: { |
|||
position: 'absolute', |
|||
zIndex: 10, |
|||
}, |
|||
cover: { |
|||
position: 'fixed', |
|||
top: '0px', |
|||
right: '0px', |
|||
bottom: '0px', |
|||
left: '0px', |
|||
}, |
|||
wrapper: { |
|||
position: 'inherit', |
|||
zIndex: 100, |
|||
}, |
|||
}; |
|||
|
|||
if (position === 'top') { |
|||
styles.wrapper.transform = `translate(calc(-100% + ${width + 8}px), -100%)`; |
|||
styles.wrapper.paddingBottom = 8; |
|||
} |
|||
|
|||
const swatch = ( |
|||
<div style={styles.swatch} onClick={this.handleClick}> |
|||
<div style={styles.color} /> |
|||
</div> |
|||
); |
|||
const picker = displayColorPicker ? ( |
|||
<div style={styles.popover}> |
|||
<div style={styles.cover} onClick={this.handleClose} /> |
|||
<div style={styles.wrapper}> |
|||
<SketchPicker |
|||
presetColors={presetColors} |
|||
color={color} |
|||
onChange={this.handleChange} |
|||
onChangeComplete={this.handleChangeComplete} |
|||
/> |
|||
</div> |
|||
</div> |
|||
) : null; |
|||
|
|||
if (position === 'top') { |
|||
return ( |
|||
<div> |
|||
{picker} |
|||
{swatch} |
|||
</div> |
|||
); |
|||
} |
|||
return ( |
|||
<div> |
|||
{swatch} |
|||
{picker} |
|||
</div> |
|||
); |
|||
} |
|||
} |
@ -0,0 +1,290 @@ |
|||
import { Global, css } from '@emotion/react'; |
|||
import useSiteToken from '../../../hooks/useSiteToken'; |
|||
|
|||
const gray = { |
|||
1: '#fff', |
|||
2: '#fafafa', |
|||
3: '#f5f5f5', |
|||
4: '#f0f0f0', |
|||
5: '#d9d9d9', |
|||
6: '#bfbfbf', |
|||
7: '#8c8c8c', |
|||
8: '#595959', |
|||
9: '#434343', |
|||
10: '#262626', |
|||
11: '#1f1f1f', |
|||
12: '#141414', |
|||
13: '#000', |
|||
}; |
|||
|
|||
const ColorStyle = () => { |
|||
const { token } = useSiteToken(); |
|||
|
|||
const makePalette = (color: string, index: number = 1): string => { |
|||
if (index <= 10) { |
|||
return ` |
|||
.palette-${color}-${index} { |
|||
background: ${(token as any)[`${color}-${index}`]}; |
|||
} |
|||
${makePalette(color, index + 1)} |
|||
`;
|
|||
} |
|||
return ''; |
|||
}; |
|||
|
|||
const makeGrayPalette = (index: number = 1): string => { |
|||
if (index <= 13) { |
|||
return ` |
|||
.palette-gray-${index} { |
|||
background: ${(gray as any)[index]}; |
|||
} |
|||
${makeGrayPalette(index + 1)} |
|||
`;
|
|||
} |
|||
return ''; |
|||
}; |
|||
|
|||
return ( |
|||
<Global |
|||
styles={css` |
|||
.color-palettes { |
|||
margin: 0 1%; |
|||
|
|||
&-dark { |
|||
margin: 0; |
|||
padding: 0 28px; |
|||
background-color: #141414; |
|||
|
|||
.color-title { |
|||
color: rgba(255, 255, 255, 0.85); |
|||
} |
|||
|
|||
.color-description { |
|||
color: rgba(255, 255, 255, 0.45); |
|||
} |
|||
|
|||
.color-palette { |
|||
margin: 45px 3.5% 45px 0; |
|||
|
|||
&:nth-of-type(3n) { |
|||
margin-right: 0; |
|||
} |
|||
|
|||
.main-color-item { |
|||
margin-right: 0; |
|||
|
|||
&:hover { |
|||
margin-right: -8px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.color-palette { |
|||
display: inline-block; |
|||
width: 31%; |
|||
margin: 45px 1%; |
|||
|
|||
&-pick { |
|||
margin: 0 0 20px; |
|||
font-size: 20px; |
|||
text-align: center; |
|||
} |
|||
|
|||
&-picker { |
|||
margin: 24px 0; |
|||
|
|||
&-value { |
|||
position: relative; |
|||
top: -3px; |
|||
margin-left: 16px; |
|||
font-size: 14px; |
|||
font-family: Consolas, sans-serif; |
|||
|
|||
.ant-row-rtl & { |
|||
margin-right: 16px; |
|||
margin-left: 0; |
|||
} |
|||
} |
|||
|
|||
&-validation { |
|||
position: relative; |
|||
top: -3px; |
|||
margin-left: 16px; |
|||
color: ${token.colorError}; |
|||
font-size: 13px; |
|||
|
|||
.ant-row-rtl & { |
|||
margin-right: 16px; |
|||
margin-left: 0; |
|||
} |
|||
|
|||
&-dark { |
|||
margin-left: 0; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.main-color { |
|||
${makePalette('blue')} |
|||
${makePalette('purple')} |
|||
${makePalette('cyan')} |
|||
${makePalette('green')} |
|||
${makePalette('magenta')} |
|||
${makePalette('red')} |
|||
${makePalette('volcano')} |
|||
${makePalette('orange')} |
|||
${makePalette('gold')} |
|||
${makePalette('yellow')} |
|||
${makePalette('lime')} |
|||
${makePalette('geekblue')} |
|||
${makeGrayPalette()} |
|||
|
|||
text-align: left; |
|||
|
|||
&-item { |
|||
position: relative; |
|||
height: 44px; |
|||
margin-right: 4px; |
|||
padding: 0 12px; |
|||
font-size: 14px; |
|||
font-family: Consolas, sans-serif; |
|||
line-height: 44px; |
|||
cursor: pointer; |
|||
transition: all 0.2s; |
|||
|
|||
&:first-child { |
|||
border-radius: 4px 4px 0 0; |
|||
} |
|||
|
|||
&:last-child { |
|||
border-radius: 0 0 4px 4px; |
|||
} |
|||
|
|||
&:hover { |
|||
margin-right: -8px; |
|||
border-radius: 0 4px 4px 0; |
|||
} |
|||
} |
|||
|
|||
&-item &-text { |
|||
float: left; |
|||
transition: all 0.3s; |
|||
} |
|||
|
|||
&-item &-value { |
|||
position: relative; |
|||
left: 3px; |
|||
float: right; |
|||
transform: scale(0.85); |
|||
transform-origin: 100% 50%; |
|||
opacity: 0; |
|||
transition: all 0.3s; |
|||
} |
|||
} |
|||
|
|||
.color-title { |
|||
margin: 0 0 24px; |
|||
color: #5c6b77; |
|||
font-weight: 500; |
|||
font-size: 22px; |
|||
text-align: center; |
|||
text-transform: capitalize; |
|||
} |
|||
|
|||
.color-description { |
|||
display: block; |
|||
color: #777; |
|||
font-weight: lighter; |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.main-color:hover { |
|||
.main-color-value { |
|||
left: 0; |
|||
opacity: 0.7; |
|||
} |
|||
} |
|||
|
|||
.color-palette-horizontal { |
|||
width: 100%; |
|||
box-sizing: border-box; |
|||
|
|||
&-dark { |
|||
height: 303px; |
|||
padding: 32px 28px; |
|||
background-color: #141414; |
|||
|
|||
.color-palette-picker { |
|||
margin-bottom: 0; |
|||
} |
|||
|
|||
.color-palette-pick { |
|||
color: rgba(255, 255, 255, 0.65); |
|||
text-align: left; |
|||
|
|||
&-hex { |
|||
color: rgba(255, 255, 255, 0.65); |
|||
} |
|||
|
|||
.ant-row-rtl & { |
|||
direction: rtl; |
|||
text-align: right; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.main-color { |
|||
display: flex; |
|||
|
|||
&-item { |
|||
box-sizing: border-box; |
|||
position: relative; |
|||
flex: 1; |
|||
height: 86px; |
|||
margin-right: 0; |
|||
padding: 37px 0 0; |
|||
line-height: normal; |
|||
text-align: center; |
|||
border-radius: 0; |
|||
|
|||
.main-color-text { |
|||
float: none; |
|||
} |
|||
|
|||
&:hover { |
|||
height: 96px; |
|||
margin-top: -10px; |
|||
border-radius: 4px 4px 0 0; |
|||
} |
|||
} |
|||
|
|||
&-value { |
|||
position: absolute; |
|||
bottom: 0; |
|||
left: 0; |
|||
width: 100%; |
|||
text-align: center; |
|||
transform-origin: unset; |
|||
} |
|||
|
|||
&:hover { |
|||
.main-color-item { |
|||
padding-top: 8px; |
|||
} |
|||
|
|||
.main-color-value { |
|||
bottom: 8px; |
|||
opacity: 0.7; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
`}
|
|||
/> |
|||
); |
|||
}; |
|||
|
|||
export default ColorStyle; |
@ -0,0 +1,93 @@ |
|||
import React from 'react'; |
|||
import { message } from 'antd'; |
|||
import CopyToClipboard from 'react-copy-to-clipboard'; |
|||
import { presetDarkPalettes } from '@ant-design/colors'; |
|||
|
|||
const rgbToHex = rgbString => { |
|||
const rgb = rgbString.match(/\d+/g); |
|||
let r = parseInt(rgb[0], 10).toString(16); |
|||
let g = parseInt(rgb[1], 10).toString(16); |
|||
let b = parseInt(rgb[2], 10).toString(16); |
|||
r = r.length === 1 ? `0${r}` : r; |
|||
g = g.length === 1 ? `0${g}` : g; |
|||
b = b.length === 1 ? `0${b}` : b; |
|||
return `#${r}${g}${b}`; |
|||
}; |
|||
|
|||
export default class Palette extends React.Component { |
|||
componentDidMount() { |
|||
this.hexColors = {}; |
|||
Object.keys(this.colorNodes).forEach(key => { |
|||
const computedColor = getComputedStyle(this.colorNodes[key])['background-color']; |
|||
if (computedColor.includes('rgba')) { |
|||
this.hexColors[key] = computedColor; |
|||
} else { |
|||
this.hexColors[key] = rgbToHex(computedColor); |
|||
} |
|||
}); |
|||
this.forceUpdate(); |
|||
} |
|||
|
|||
render() { |
|||
this.colorNodes = this.colorNodes || {}; |
|||
const { |
|||
showTitle, |
|||
direction, |
|||
dark, |
|||
color: { name, description, english, chinese, count = 10 }, |
|||
} = this.props; |
|||
const className = direction === 'horizontal' ? 'color-palette-horizontal' : 'color-palette'; |
|||
const colors = []; |
|||
const colorName = `${english} / ${chinese}`; |
|||
const colorPaletteMap = { |
|||
dark: ['#fff', 'unset'], |
|||
default: ['rgba(0,0,0,0.85)', '#fff'], |
|||
}; |
|||
const [lastColor, firstColor] = dark ? colorPaletteMap.dark : colorPaletteMap.default; |
|||
for (let i = 1; i <= count; i += 1) { |
|||
const colorText = `${name}-${i}`; |
|||
const defaultBgStyle = dark ? presetDarkPalettes[name][i - 1] : ''; |
|||
colors.push( |
|||
<CopyToClipboard |
|||
text={this.hexColors ? this.hexColors[colorText] : ''} |
|||
onCopy={() => message.success(`@${colorText} copied: ${this.hexColors[colorText]}`)} |
|||
key={colorText} |
|||
> |
|||
<div |
|||
key={i} |
|||
ref={node => { |
|||
this.colorNodes[`${name}-${i}`] = node; |
|||
}} |
|||
className={`main-color-item palette-${name}-${i}`} |
|||
style={{ |
|||
color: (name === 'yellow' ? i > 6 : i > 5) ? firstColor : lastColor, |
|||
fontWeight: i === 6 ? 'bold' : 'normal', |
|||
backgroundColor: defaultBgStyle, |
|||
}} |
|||
title="click to copy color" |
|||
> |
|||
<span className="main-color-text">{colorText}</span> |
|||
{this.hexColors ? ( |
|||
<span className="main-color-value">{this.hexColors[colorText]}</span> |
|||
) : null} |
|||
</div> |
|||
</CopyToClipboard>, |
|||
); |
|||
} |
|||
return ( |
|||
<div className={className}> |
|||
{showTitle && ( |
|||
<div className="color-title"> |
|||
{colorName} |
|||
<span className="color-description">{description}</span> |
|||
</div> |
|||
)} |
|||
<div className="main-color">{colors}</div> |
|||
</div> |
|||
); |
|||
} |
|||
} |
|||
|
|||
Palette.defaultProps = { |
|||
color: { name: 'gray', count: 13 }, |
|||
} |
@ -0,0 +1,28 @@ |
|||
import React, { type FC } from 'react'; |
|||
import { Skeleton, Space, Spin } from 'antd'; |
|||
import { useLocation } from 'dumi'; |
|||
|
|||
const Loading: FC = () => { |
|||
const { pathname } = useLocation(); |
|||
|
|||
if ( |
|||
pathname.startsWith('/components') || |
|||
pathname.startsWith('/docs') || |
|||
pathname.startsWith('/changelog') |
|||
) { |
|||
return ( |
|||
<Space direction="vertical" style={{ width: '100%' }} size={40}> |
|||
<Skeleton title={false} active paragraph={{ rows: 3 }} /> |
|||
<Skeleton active paragraph={{ rows: 3 }} /> |
|||
</Space> |
|||
); |
|||
} |
|||
|
|||
return ( |
|||
<Space style={{ width: '100%', margin: '120px 0', justifyContent: 'center' }} align="center"> |
|||
<Spin size="large" /> |
|||
</Space> |
|||
); |
|||
}; |
|||
|
|||
export default Loading; |
@ -1,19 +1,17 @@ |
|||
import React from 'react'; |
|||
import { CheckOutlined, CloseOutlined } from '@ant-design/icons'; |
|||
import { Switch } from 'antd'; |
|||
import { Switch, Space } from 'antd'; |
|||
|
|||
const App: React.FC = () => ( |
|||
<> |
|||
<Space direction="vertical"> |
|||
<Switch checkedChildren="开启" unCheckedChildren="关闭" defaultChecked /> |
|||
<br /> |
|||
<Switch checkedChildren="1" unCheckedChildren="0" /> |
|||
<br /> |
|||
<Switch |
|||
checkedChildren={<CheckOutlined />} |
|||
unCheckedChildren={<CloseOutlined />} |
|||
defaultChecked |
|||
/> |
|||
</> |
|||
</Space> |
|||
); |
|||
|
|||
export default App; |
|||
|
@ -0,0 +1,3 @@ |
|||
// put it into `.dumi` folder when dumi ready
|
|||
// eslint-disable-next-line no-restricted-exports
|
|||
export { default } from './.dumi/theme/common/Loading'; |
Loading…
Reference in new issue