mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-28 13:09:40 +08:00
site: cc => fc (#39635)
This commit is contained in:
parent
d675c09bd0
commit
a0b713c98b
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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');
|
||||
|
Loading…
Reference in New Issue
Block a user