site: cc => fc (#39635)

This commit is contained in:
lijianan 2022-12-19 11:25:21 +08:00 committed by GitHub
parent d675c09bd0
commit a0b713c98b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 209 additions and 266 deletions

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React, { useMemo } from 'react';
import CopyToClipboard from 'react-copy-to-clipboard';
import { message } from 'antd';
@ -8,37 +8,25 @@ interface ColorBlockProps {
dark?: boolean;
}
class ColorBlock extends Component<ColorBlockProps> {
getTextStyle() {
const { color, index, dark } = this.props;
const colorMap = {
default: ['#fff', 'unset'],
dark: ['#314659', '#fff'],
};
const ColorBlock: React.FC<ColorBlockProps> = (props) => {
const { color, index, dark } = props;
const textStyle = useMemo<React.CSSProperties>(() => {
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}>
<div className="main-color-item" style={this.getTextStyle()}>
color-{index}
<span className="main-color-value">{color.toLowerCase()}</span>
</div>
</CopyToClipboard>
);
}
}
}, [color, dark, index]);
return (
<CopyToClipboard text={color} onCopy={() => message.success(`Copied: ${color}`)}>
<div className="main-color-item" style={textStyle}>
color-{index}
<span className="main-color-value">{color.toLowerCase()}</span>
</div>
</CopyToClipboard>
);
};
export default ColorBlock;

View File

@ -1,5 +1,5 @@
import type { ChangeEvent } from 'react';
import React, { Component } from 'react';
import React, { useMemo, useState } from 'react';
import { FormattedMessage } from 'dumi';
import ColorPicker from './ColorPicker';
import ColorPatterns from './ColorPatterns';
@ -7,21 +7,17 @@ import ColorPatterns from './ColorPatterns';
const primaryMinSaturation = 70; // 主色推荐最小饱和度
const primaryMinBrightness = 70; // 主色推荐最小亮度
class ColorPaletteTool extends Component {
state = {
primaryColor: '#1890ff',
primaryColorInstance: null,
};
handleChangeColor = (e: string | ChangeEvent, color: { hex: string }) => {
const ColorPaletteTool: React.FC = () => {
const [primaryColor, setPrimaryColor] = useState<string>('#1890ff');
const [primaryColorInstance, setPrimaryColorInstance] = useState(null);
const handleChangeColor = (e: string | ChangeEvent, color: { hex: string }) => {
const value = (e as ChangeEvent<HTMLInputElement>).target
? (e as ChangeEvent<HTMLInputElement>).target.value
: e;
this.setState({ primaryColor: value, primaryColorInstance: color });
setPrimaryColor(value as string);
setPrimaryColorInstance(color);
};
renderColorValidation() {
const { primaryColorInstance } = this.state;
const colorValidation = useMemo<React.ReactNode>(() => {
let text = '';
if (primaryColorInstance) {
if (primaryColorInstance.hsv.s * 100 < primaryMinSaturation) {
@ -36,26 +32,22 @@ class ColorPaletteTool extends Component {
}
}
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 color={primaryColor} onChange={this.handleChangeColor} />
</span>
<span className="color-palette-picker-value">{primaryColor}</span>
{this.renderColorValidation()}
</div>
}, [primaryColorInstance, primaryMinSaturation, primaryMinBrightness]);
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 color={primaryColor} onChange={handleChangeColor} />
</span>
<span className="color-palette-picker-value">{primaryColor}</span>
{colorValidation}
</div>
</div>
);
};
export default ColorPaletteTool;

View File

@ -1,5 +1,5 @@
import React, { useMemo, useState } from 'react';
import type { ChangeEvent } from 'react';
import React, { Component } from 'react';
import { FormattedMessage } from 'dumi';
import { Row, Col } from 'antd';
import ColorPicker from './ColorPicker';
@ -8,29 +8,27 @@ import ColorPatterns from './ColorPatterns';
const primaryMinSaturation = 70; // 主色推荐最小饱和度
const primaryMinBrightness = 70; // 主色推荐最小亮度
class ColorPaletteTool extends Component {
state = {
primaryColor: '#1890ff',
backgroundColor: '#141414',
primaryColorInstance: null,
};
const ColorPaletteTool: React.FC = () => {
const [primaryColor, setPrimaryColor] = useState<string>('#1890ff');
const [backgroundColor, setBackgroundColor] = useState<string>('#141414');
const [primaryColorInstance, setPrimaryColorInstance] = useState(null);
handleChangeColor = (e: string | ChangeEvent, color: { hex: string }) => {
const handleChangeColor = (e: string | ChangeEvent, color: { hex: string }) => {
const value = (e as ChangeEvent<HTMLInputElement>).target
? (e as ChangeEvent<HTMLInputElement>).target.value
: e;
this.setState({ primaryColor: value, primaryColorInstance: color });
setPrimaryColor(value as string);
setPrimaryColorInstance(color);
};
handleChangeBackgroundColor = (e: string | ChangeEvent) => {
const handleChangeBackgroundColor = (e: string | ChangeEvent) => {
const value = (e as ChangeEvent<HTMLInputElement>).target
? (e as ChangeEvent<HTMLInputElement>).target.value
: e;
this.setState({ backgroundColor: value });
setBackgroundColor(value as string);
};
renderColorValidation() {
const { primaryColorInstance } = this.state;
const colorValidation = useMemo<React.ReactNode>(() => {
let text = '';
if (primaryColorInstance) {
if (primaryColorInstance.hsv.s * 100 < primaryMinSaturation) {
@ -49,56 +47,50 @@ class ColorPaletteTool extends Component {
{text.trim()}
</span>
);
}
}, [primaryColorInstance]);
render() {
const { primaryColor, backgroundColor } = this.state;
return (
<div className="color-palette-horizontal color-palette-horizontal-dark">
<div className="main-color">
{ColorPatterns({ color: primaryColor, dark: true, 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 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
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>
return (
<div className="color-palette-horizontal color-palette-horizontal-dark">
<div className="main-color">
{ColorPatterns({ color: primaryColor, dark: true, 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 color={primaryColor} onChange={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 color={backgroundColor} onChange={handleChangeBackgroundColor} />
</Col>
<Col span={6}>
<span className="color-palette-pick-hex">{backgroundColor}</span>
</Col>
</Row>
</span>
</Col>
</Row>
{colorValidation}
</div>
</div>
);
};
export default ColorPaletteTool;

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React, { useState } from 'react';
import { SketchPicker } from 'react-color';
const noop = () => {};
@ -12,115 +12,105 @@ interface ColorPickerProps {
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;
const ColorPicker: React.FC<ColorPickerProps> = (props) => {
const {
small,
position = 'bottom',
presetColors,
onChange = noop,
onChangeComplete = noop,
} = props;
const [color, setColor] = useState<string>(props.color);
const [displayColorPicker, setDisplayColorPicker] = useState<boolean>(false);
const handleClick = () => {
setDisplayColorPicker(displayColorPicker);
};
const handleClose = () => {
setDisplayColorPicker(false);
};
const handleChange = (changeColor: { hex: string }) => {
setColor(changeColor.hex);
onChange(changeColor.hex, changeColor);
};
const handleChangeComplete = (completeColor: { hex: string }) => {
setColor(completeColor.hex);
onChangeComplete(completeColor.hex);
};
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;
}
state = {
displayColorPicker: false,
color: undefined,
};
const swatch: React.ReactNode = (
<div style={styles.swatch} onClick={handleClick}>
<div style={styles.color} />
</div>
);
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} />
const picker: React.ReactNode = displayColorPicker ? (
<div style={styles.popover}>
<div style={styles.cover} onClick={handleClose} />
<div style={styles.wrapper}>
<SketchPicker
presetColors={presetColors}
color={color}
onChange={handleChange}
onChangeComplete={handleChangeComplete}
/>
</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;
</div>
) : null;
if (position === 'top') {
return (
<div>
{picker}
{swatch}
</div>
);
}
return (
<div>
{swatch}
{picker}
</div>
);
}
}
return position === 'top' ? (
<div>
{picker}
{swatch}
</div>
) : (
<div>
{swatch}
{picker}
</div>
);
};
export default ColorPicker;

View File

@ -1,12 +1,13 @@
import { SearchOutlined } from '@ant-design/icons';
import { resetWarned } from 'rc-util/lib/warning';
import React, { Component } from 'react';
import React, { useState } from 'react';
import { act } from 'react-dom/test-utils';
import Button from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { fireEvent, render, waitFakeTimer } from '../../../tests/utils';
import ConfigProvider from '../../config-provider';
import type { BaseButtonProps } from '../button';
describe('Button', () => {
mountTest(Button);
@ -133,48 +134,28 @@ describe('Button', () => {
});
it('should change loading state instantly by default', () => {
class DefaultButton extends Component {
state = {
loading: false,
};
enterLoading = () => {
this.setState({ loading: true });
};
render() {
const { loading } = this.state;
return (
<Button loading={loading} onClick={this.enterLoading}>
Button
</Button>
);
}
}
const DefaultButton: React.FC = () => {
const [loading, setLoading] = useState<BaseButtonProps['loading']>(false);
return (
<Button loading={loading} onClick={() => setLoading(true)}>
Button
</Button>
);
};
const wrapper = render(<DefaultButton />);
fireEvent.click(wrapper.container.firstChild!);
expect(wrapper.container.querySelectorAll('.ant-btn-loading').length).toBe(1);
});
it('should change loading state with delay', () => {
class DefaultButton extends Component {
state = {
loading: false,
};
enterLoading = () => {
this.setState({ loading: { delay: 1000 } });
};
render() {
const { loading } = this.state;
return (
<Button loading={loading} onClick={this.enterLoading}>
Button
</Button>
);
}
}
const DefaultButton: React.FC = () => {
const [loading, setLoading] = useState<BaseButtonProps['loading']>(false);
return (
<Button loading={loading} onClick={() => setLoading({ delay: 1000 })}>
Button
</Button>
);
};
const wrapper = render(<DefaultButton />);
fireEvent.click(wrapper.container.firstChild!);
expect(wrapper.container.firstChild).not.toHaveClass('ant-btn-loading');