mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-02 12:09:14 +08:00
commit
fb9c2fc51e
@ -19,37 +19,32 @@ import { PlusOutlined } from '@ant-design/icons';
|
|||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
class DrawerForm extends React.Component {
|
export default () => {
|
||||||
state = { visible: false };
|
const [visible, setVisible] = React.useState(false);
|
||||||
|
|
||||||
showDrawer = () => {
|
const showDrawer = () => {
|
||||||
this.setState({
|
setVisible(true);
|
||||||
visible: true,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onClose = () => {
|
const onClose = () => {
|
||||||
this.setState({
|
setVisible(false);
|
||||||
visible: false,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button type="primary" onClick={this.showDrawer} icon={<PlusOutlined />}>
|
<Button type="primary" onClick={showDrawer} icon={<PlusOutlined />}>
|
||||||
New account
|
New account
|
||||||
</Button>
|
</Button>
|
||||||
<Drawer
|
<Drawer
|
||||||
title="Create a new account"
|
title="Create a new account"
|
||||||
width={720}
|
width={720}
|
||||||
onClose={this.onClose}
|
onClose={onClose}
|
||||||
visible={this.state.visible}
|
visible={visible}
|
||||||
bodyStyle={{ paddingBottom: 80 }}
|
bodyStyle={{ paddingBottom: 80 }}
|
||||||
extra={
|
extra={
|
||||||
<Space>
|
<Space>
|
||||||
<Button onClick={this.onClose}>Cancel</Button>
|
<Button onClick={onClose}>Cancel</Button>
|
||||||
<Button onClick={this.onClose} type="primary">
|
<Button onClick={onClose} type="primary">
|
||||||
Submit
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
@ -153,10 +148,7 @@ class DrawerForm extends React.Component {
|
|||||||
</Drawer>
|
</Drawer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default () => <DrawerForm />;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```css
|
```css
|
||||||
|
@ -16,65 +16,54 @@ Open a new drawer on top of an existing drawer to handle multi branch tasks.
|
|||||||
```jsx
|
```jsx
|
||||||
import { Drawer, Button } from 'antd';
|
import { Drawer, Button } from 'antd';
|
||||||
|
|
||||||
class App extends React.Component {
|
export default () => {
|
||||||
state = { visible: false, childrenDrawer: false };
|
const [visible, setVisible] = React.useState(false);
|
||||||
|
const [childrenDrawer, setChildrenDrawer] = React.useState(false);
|
||||||
|
|
||||||
showDrawer = () => {
|
const showDrawer = () => {
|
||||||
this.setState({
|
setVisible(true);
|
||||||
visible: true,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onClose = () => {
|
const onClose = () => {
|
||||||
this.setState({
|
setVisible(false);
|
||||||
visible: false,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
showChildrenDrawer = () => {
|
const showChildrenDrawer = () => {
|
||||||
this.setState({
|
setChildrenDrawer(true);
|
||||||
childrenDrawer: true,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onChildrenDrawerClose = () => {
|
const onChildrenDrawerClose = () => {
|
||||||
this.setState({
|
setChildrenDrawer(false);
|
||||||
childrenDrawer: false,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button type="primary" onClick={this.showDrawer}>
|
<Button type="primary" onClick={showDrawer}>
|
||||||
Open drawer
|
Open drawer
|
||||||
</Button>
|
</Button>
|
||||||
<Drawer
|
<Drawer
|
||||||
title="Multi-level drawer"
|
title="Multi-level drawer"
|
||||||
width={520}
|
width={520}
|
||||||
closable={false}
|
closable={false}
|
||||||
onClose={this.onClose}
|
onClose={onClose}
|
||||||
visible={this.state.visible}
|
visible={visible}
|
||||||
>
|
>
|
||||||
<Button type="primary" onClick={this.showChildrenDrawer}>
|
<Button type="primary" onClick={showChildrenDrawer}>
|
||||||
Two-level drawer
|
Two-level drawer
|
||||||
</Button>
|
</Button>
|
||||||
<Drawer
|
<Drawer
|
||||||
title="Two-level Drawer"
|
title="Two-level Drawer"
|
||||||
width={320}
|
width={320}
|
||||||
closable={false}
|
closable={false}
|
||||||
onClose={this.onChildrenDrawerClose}
|
onClose={onChildrenDrawerClose}
|
||||||
visible={this.state.childrenDrawer}
|
visible={childrenDrawer}
|
||||||
>
|
>
|
||||||
This is two-level drawer
|
This is two-level drawer
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -16,39 +16,32 @@ The Drawer can appear from any edge of the screen.
|
|||||||
```jsx
|
```jsx
|
||||||
import { Drawer, Button, Radio, Space } from 'antd';
|
import { Drawer, Button, Radio, Space } from 'antd';
|
||||||
|
|
||||||
class App extends React.Component {
|
export default () => {
|
||||||
state = { visible: false, placement: 'left' };
|
const [visible, setVisible] = React.useState(false);
|
||||||
|
const [placement, setPlacement] = React.useState('left');
|
||||||
|
|
||||||
showDrawer = () => {
|
const showDrawer = () => {
|
||||||
this.setState({
|
setVisible(true);
|
||||||
visible: true,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onClose = () => {
|
const onClose = () => {
|
||||||
this.setState({
|
setVisible(false);
|
||||||
visible: false,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onChange = e => {
|
const onChange = e => {
|
||||||
this.setState({
|
setPlacement(e.target.value);
|
||||||
placement: e.target.value,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
|
||||||
const { placement, visible } = this.state;
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Space>
|
<Space>
|
||||||
<Radio.Group value={placement} onChange={this.onChange}>
|
<Radio.Group value={placement} onChange={onChange}>
|
||||||
<Radio value="top">top</Radio>
|
<Radio value="top">top</Radio>
|
||||||
<Radio value="right">right</Radio>
|
<Radio value="right">right</Radio>
|
||||||
<Radio value="bottom">bottom</Radio>
|
<Radio value="bottom">bottom</Radio>
|
||||||
<Radio value="left">left</Radio>
|
<Radio value="left">left</Radio>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
<Button type="primary" onClick={this.showDrawer}>
|
<Button type="primary" onClick={showDrawer}>
|
||||||
Open
|
Open
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
@ -56,7 +49,7 @@ class App extends React.Component {
|
|||||||
title="Basic Drawer"
|
title="Basic Drawer"
|
||||||
placement={placement}
|
placement={placement}
|
||||||
closable={false}
|
closable={false}
|
||||||
onClose={this.onClose}
|
onClose={onClose}
|
||||||
visible={visible}
|
visible={visible}
|
||||||
key={placement}
|
key={placement}
|
||||||
>
|
>
|
||||||
@ -66,8 +59,5 @@ class App extends React.Component {
|
|||||||
</Drawer>
|
</Drawer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
```
|
```
|
||||||
|
@ -16,27 +16,22 @@ Render in current dom. custom container, check `getContainer`.
|
|||||||
```jsx
|
```jsx
|
||||||
import { Drawer, Button } from 'antd';
|
import { Drawer, Button } from 'antd';
|
||||||
|
|
||||||
class App extends React.Component {
|
export default () => {
|
||||||
state = { visible: false };
|
const [visible, setVisible] = React.useState(false);
|
||||||
|
|
||||||
showDrawer = () => {
|
const showDrawer = () => {
|
||||||
this.setState({
|
setVisible(true);
|
||||||
visible: true,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onClose = () => {
|
const onClose = () => {
|
||||||
this.setState({
|
setVisible(false);
|
||||||
visible: false,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
return (
|
||||||
<div className="site-drawer-render-in-current-wrapper">
|
<div className="site-drawer-render-in-current-wrapper">
|
||||||
Render in this
|
Render in this
|
||||||
<div style={{ marginTop: 16 }}>
|
<div style={{ marginTop: 16 }}>
|
||||||
<Button type="primary" onClick={this.showDrawer}>
|
<Button type="primary" onClick={showDrawer}>
|
||||||
Open
|
Open
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@ -44,8 +39,8 @@ class App extends React.Component {
|
|||||||
title="Basic Drawer"
|
title="Basic Drawer"
|
||||||
placement="right"
|
placement="right"
|
||||||
closable={false}
|
closable={false}
|
||||||
onClose={this.onClose}
|
onClose={onClose}
|
||||||
visible={this.state.visible}
|
visible={visible}
|
||||||
getContainer={false}
|
getContainer={false}
|
||||||
style={{ position: 'absolute' }}
|
style={{ position: 'absolute' }}
|
||||||
>
|
>
|
||||||
@ -53,10 +48,7 @@ class App extends React.Component {
|
|||||||
</Drawer>
|
</Drawer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```css
|
```css
|
||||||
|
@ -23,22 +23,17 @@ const DescriptionItem = ({ title, content }) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
class App extends React.Component {
|
export default () => {
|
||||||
state = { visible: false };
|
const [visible, setVisible] = React.useState(false);
|
||||||
|
|
||||||
showDrawer = () => {
|
const showDrawer = () => {
|
||||||
this.setState({
|
setVisible(true);
|
||||||
visible: true,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onClose = () => {
|
const onClose = () => {
|
||||||
this.setState({
|
setVisible(false);
|
||||||
visible: false,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<List
|
<List
|
||||||
@ -55,7 +50,7 @@ class App extends React.Component {
|
|||||||
<List.Item
|
<List.Item
|
||||||
key={item.id}
|
key={item.id}
|
||||||
actions={[
|
actions={[
|
||||||
<a onClick={this.showDrawer} key={`a-${item.id}`}>
|
<a onClick={showDrawer} key={`a-${item.id}`}>
|
||||||
View Profile
|
View Profile
|
||||||
</a>,
|
</a>,
|
||||||
]}
|
]}
|
||||||
@ -70,13 +65,7 @@ class App extends React.Component {
|
|||||||
</List.Item>
|
</List.Item>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Drawer
|
<Drawer width={640} placement="right" closable={false} onClose={onClose} visible={visible}>
|
||||||
width={640}
|
|
||||||
placement="right"
|
|
||||||
closable={false}
|
|
||||||
onClose={this.onClose}
|
|
||||||
visible={this.state.visible}
|
|
||||||
>
|
|
||||||
<p className="site-description-item-profile-p" style={{ marginBottom: 24 }}>
|
<p className="site-description-item-profile-p" style={{ marginBottom: 24 }}>
|
||||||
User Profile
|
User Profile
|
||||||
</p>
|
</p>
|
||||||
@ -164,10 +153,7 @@ class App extends React.Component {
|
|||||||
</Drawer>
|
</Drawer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```css
|
```css
|
||||||
|
@ -27,25 +27,23 @@ const menu = (
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
class App extends React.Component {
|
export default () => {
|
||||||
state = {
|
const [loadings, setLodings] = React.useState([]);
|
||||||
loadings: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
enterLoading = index => {
|
const enterLoading = index => {
|
||||||
const newLoadings = [...this.state.loadings];
|
const newLoadings = [...loadings];
|
||||||
newLoadings[index] = true;
|
newLoadings[index] = true;
|
||||||
this.setState({
|
setLodings(newLoadings);
|
||||||
loadings: newLoadings,
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
newLoadings[index] = false;
|
setLodings(prevLoadings => {
|
||||||
this.setState({ loadings: newLoadings });
|
const temLoadings = [...prevLoadings];
|
||||||
|
temLoadings[index] = false;
|
||||||
|
return temLoadings;
|
||||||
|
});
|
||||||
}, 6000);
|
}, 6000);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
|
||||||
const { loadings } = this.state;
|
|
||||||
return (
|
return (
|
||||||
<Space direction="vertical">
|
<Space direction="vertical">
|
||||||
<Dropdown.Button type="primary" loading overlay={menu}>
|
<Dropdown.Button type="primary" loading overlay={menu}>
|
||||||
@ -58,7 +56,7 @@ class App extends React.Component {
|
|||||||
type="primary"
|
type="primary"
|
||||||
loading={loadings[0]}
|
loading={loadings[0]}
|
||||||
overlay={menu}
|
overlay={menu}
|
||||||
onClick={() => this.enterLoading(0)}
|
onClick={() => enterLoading(0)}
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
</Dropdown.Button>
|
</Dropdown.Button>
|
||||||
@ -66,13 +64,11 @@ class App extends React.Component {
|
|||||||
icon={<DownOutlined />}
|
icon={<DownOutlined />}
|
||||||
loading={loadings[1]}
|
loading={loadings[1]}
|
||||||
overlay={menu}
|
overlay={menu}
|
||||||
onClick={() => this.enterLoading(1)}
|
onClick={() => enterLoading(1)}
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
</Dropdown.Button>
|
</Dropdown.Button>
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
export default App;
|
|
||||||
```
|
```
|
||||||
|
@ -17,25 +17,22 @@ The default is to close the menu when you click on menu items, this feature can
|
|||||||
import { Menu, Dropdown, Space } from 'antd';
|
import { Menu, Dropdown, Space } from 'antd';
|
||||||
import { DownOutlined } from '@ant-design/icons';
|
import { DownOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
class OverlayVisible extends React.Component {
|
export default () => {
|
||||||
state = {
|
const [visible, setVisible] = React.useState(false);
|
||||||
visible: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
handleMenuClick = e => {
|
const handleMenuClick = e => {
|
||||||
if (e.key === '3') {
|
if (e.key === '3') {
|
||||||
this.setState({ visible: false });
|
setVisible(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleVisibleChange = flag => {
|
const handleVisibleChange = flag => {
|
||||||
this.setState({ visible: flag });
|
setVisible(flag);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
|
||||||
const menu = (
|
const menu = (
|
||||||
<Menu
|
<Menu
|
||||||
onClick={this.handleMenuClick}
|
onClick={handleMenuClick}
|
||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
label: 'Clicking me will not close the menu.',
|
label: 'Clicking me will not close the menu.',
|
||||||
@ -52,12 +49,9 @@ class OverlayVisible extends React.Component {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown
|
<Dropdown overlay={menu} onVisibleChange={handleVisibleChange} visible={visible}>
|
||||||
overlay={menu}
|
|
||||||
onVisibleChange={this.handleVisibleChange}
|
|
||||||
visible={this.state.visible}
|
|
||||||
>
|
|
||||||
<a onClick={e => e.preventDefault()}>
|
<a onClick={e => e.preventDefault()}>
|
||||||
<Space>
|
<Space>
|
||||||
Hover me
|
Hover me
|
||||||
@ -66,8 +60,5 @@ class OverlayVisible extends React.Component {
|
|||||||
</a>
|
</a>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default () => <OverlayVisible />;
|
|
||||||
```
|
```
|
||||||
|
@ -36,21 +36,17 @@ const customizeRenderEmpty = () => (
|
|||||||
|
|
||||||
const style = { width: 200 };
|
const style = { width: 200 };
|
||||||
|
|
||||||
class Demo extends React.Component {
|
export default () => {
|
||||||
state = {
|
const [customize, setCustomize] = React.useState(false);
|
||||||
customize: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { customize } = this.state;
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Switch
|
<Switch
|
||||||
unCheckedChildren="default"
|
unCheckedChildren="default"
|
||||||
checkedChildren="customize"
|
checkedChildren="customize"
|
||||||
checked={customize}
|
checked={customize}
|
||||||
onChange={val => {
|
onChange={value => {
|
||||||
this.setState({ customize: val });
|
setCustomize(value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -93,10 +89,7 @@ class Demo extends React.Component {
|
|||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default Demo;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -30,27 +30,26 @@ const colCounts = {};
|
|||||||
colCounts[i] = value;
|
colCounts[i] = value;
|
||||||
});
|
});
|
||||||
|
|
||||||
class App extends React.Component {
|
export default () => {
|
||||||
state = {
|
const [state, setState] = React.useState({
|
||||||
gutterKey: 1,
|
gutterKey: 1,
|
||||||
vgutterKey: 1,
|
vgutterKey: 1,
|
||||||
colCountKey: 2,
|
colCountKey: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
const onGutterChange = gutterKey => {
|
||||||
|
setState({ ...state, gutterKey });
|
||||||
};
|
};
|
||||||
|
|
||||||
onGutterChange = gutterKey => {
|
const onVGutterChange = vgutterKey => {
|
||||||
this.setState({ gutterKey });
|
setState({ ...state, vgutterKey });
|
||||||
};
|
};
|
||||||
|
|
||||||
onVGutterChange = vgutterKey => {
|
const onColCountChange = colCountKey => {
|
||||||
this.setState({ vgutterKey });
|
setState({ ...state, colCountKey });
|
||||||
};
|
};
|
||||||
|
|
||||||
onColCountChange = colCountKey => {
|
const { gutterKey, vgutterKey, colCountKey } = state;
|
||||||
this.setState({ colCountKey });
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { gutterKey, vgutterKey, colCountKey } = this.state;
|
|
||||||
const cols = [];
|
const cols = [];
|
||||||
const colCount = colCounts[colCountKey];
|
const colCount = colCounts[colCountKey];
|
||||||
let colCode = '';
|
let colCode = '';
|
||||||
@ -62,6 +61,7 @@ class App extends React.Component {
|
|||||||
);
|
);
|
||||||
colCode += ` <Col span={${24 / colCount}} />\n`;
|
colCode += ` <Col span={${24 / colCount}} />\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<span>Horizontal Gutter (px): </span>
|
<span>Horizontal Gutter (px): </span>
|
||||||
@ -70,7 +70,7 @@ class App extends React.Component {
|
|||||||
min={0}
|
min={0}
|
||||||
max={Object.keys(gutters).length - 1}
|
max={Object.keys(gutters).length - 1}
|
||||||
value={gutterKey}
|
value={gutterKey}
|
||||||
onChange={this.onGutterChange}
|
onChange={onGutterChange}
|
||||||
marks={gutters}
|
marks={gutters}
|
||||||
step={null}
|
step={null}
|
||||||
tipFormatter={value => gutters[value]}
|
tipFormatter={value => gutters[value]}
|
||||||
@ -82,7 +82,7 @@ class App extends React.Component {
|
|||||||
min={0}
|
min={0}
|
||||||
max={Object.keys(vgutters).length - 1}
|
max={Object.keys(vgutters).length - 1}
|
||||||
value={vgutterKey}
|
value={vgutterKey}
|
||||||
onChange={this.onVGutterChange}
|
onChange={onVGutterChange}
|
||||||
marks={vgutters}
|
marks={vgutters}
|
||||||
step={null}
|
step={null}
|
||||||
tipFormatter={value => vgutters[value]}
|
tipFormatter={value => vgutters[value]}
|
||||||
@ -94,7 +94,7 @@ class App extends React.Component {
|
|||||||
min={0}
|
min={0}
|
||||||
max={Object.keys(colCounts).length - 1}
|
max={Object.keys(colCounts).length - 1}
|
||||||
value={colCountKey}
|
value={colCountKey}
|
||||||
onChange={this.onColCountChange}
|
onChange={onColCountChange}
|
||||||
marks={colCounts}
|
marks={colCounts}
|
||||||
step={null}
|
step={null}
|
||||||
tipFormatter={value => colCounts[value]}
|
tipFormatter={value => colCounts[value]}
|
||||||
@ -110,10 +110,7 @@ class App extends React.Component {
|
|||||||
<pre className="demo-code">{`<Row gutter={[${gutters[gutterKey]}, ${vgutters[vgutterKey]}]}>\n${colCode}</Row>`}</pre>
|
<pre className="demo-code">{`<Row gutter={[${gutters[gutterKey]}, ${vgutters[vgutterKey]}]}>\n${colCode}</Row>`}</pre>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```css
|
```css
|
||||||
|
@ -16,30 +16,22 @@ Click the button to toggle between available and disabled states.
|
|||||||
```jsx
|
```jsx
|
||||||
import { InputNumber, Button } from 'antd';
|
import { InputNumber, Button } from 'antd';
|
||||||
|
|
||||||
class App extends React.Component {
|
export default () => {
|
||||||
state = {
|
const [disabled, setDisabled] = React.useState(true);
|
||||||
disabled: true,
|
|
||||||
|
const toggle = () => {
|
||||||
|
setDisabled(!disabled);
|
||||||
};
|
};
|
||||||
|
|
||||||
toggle = () => {
|
|
||||||
this.setState({
|
|
||||||
disabled: !this.state.disabled,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<InputNumber min={1} max={10} disabled={this.state.disabled} defaultValue={3} />
|
<InputNumber min={1} max={10} disabled={disabled} defaultValue={3} />
|
||||||
<div style={{ marginTop: 20 }}>
|
<div style={{ marginTop: 20 }}>
|
||||||
<Button onClick={this.toggle} type="primary">
|
<Button onClick={toggle} type="primary">
|
||||||
Toggle disabled
|
Toggle disabled
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
```
|
```
|
||||||
|
@ -18,18 +18,14 @@ import { Input } from 'antd';
|
|||||||
|
|
||||||
const { TextArea } = Input;
|
const { TextArea } = Input;
|
||||||
|
|
||||||
class Demo extends React.Component {
|
export default () => {
|
||||||
state = {
|
const [value, setValue] = React.useState();
|
||||||
value: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
onChange = ({ target: { value } }) => {
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||||
this.setState({ value });
|
const onChange = ({ target: { value } }) => {
|
||||||
|
setValue(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
|
||||||
const { value } = this.state;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TextArea placeholder="Autosize height based on content lines" autoSize />
|
<TextArea placeholder="Autosize height based on content lines" autoSize />
|
||||||
@ -41,14 +37,11 @@ class Demo extends React.Component {
|
|||||||
<div style={{ margin: '24px 0' }} />
|
<div style={{ margin: '24px 0' }} />
|
||||||
<TextArea
|
<TextArea
|
||||||
value={value}
|
value={value}
|
||||||
onChange={this.onChange}
|
onChange={onChange}
|
||||||
placeholder="Controlled autosize"
|
placeholder="Controlled autosize"
|
||||||
autoSize={{ minRows: 3, maxRows: 5 }}
|
autoSize={{ minRows: 3, maxRows: 5 }}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default Demo;
|
|
||||||
```
|
```
|
||||||
|
@ -22,28 +22,17 @@ const { TextArea } = Input;
|
|||||||
const defaultValue =
|
const defaultValue =
|
||||||
'The autoSize property applies to textarea nodes, and only the height changes automatically. In addition, autoSize can be set to an object, specifying the minimum number of rows and the maximum number of rows. The autoSize property applies to textarea nodes, and only the height changes automatically. In addition, autoSize can be set to an object, specifying the minimum number of rows and the maximum number of rows.';
|
'The autoSize property applies to textarea nodes, and only the height changes automatically. In addition, autoSize can be set to an object, specifying the minimum number of rows and the maximum number of rows. The autoSize property applies to textarea nodes, and only the height changes automatically. In addition, autoSize can be set to an object, specifying the minimum number of rows and the maximum number of rows.';
|
||||||
|
|
||||||
class Demo extends React.Component {
|
export default () => {
|
||||||
state = {
|
const [autoResize, setAutoResize] = React.useState(false);
|
||||||
autoResize: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { autoResize } = this.state;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button onClick={() => setAutoResize(!autoResize)} style={{ marginBottom: 16 }}>
|
||||||
onClick={() => this.setState({ autoResize: !autoResize })}
|
|
||||||
style={{ marginBottom: 16 }}
|
|
||||||
>
|
|
||||||
Auto Resize: {String(autoResize)}
|
Auto Resize: {String(autoResize)}
|
||||||
</Button>
|
</Button>
|
||||||
<TextArea rows={4} autoSize={autoResize} defaultValue={defaultValue} />
|
<TextArea rows={4} autoSize={autoResize} defaultValue={defaultValue} />
|
||||||
<TextArea allowClear style={{ width: 93 }} />
|
<TextArea allowClear style={{ width: 93 }} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default Demo;
|
|
||||||
```
|
```
|
||||||
|
@ -20,18 +20,19 @@ function formatNumber(value) {
|
|||||||
return new Intl.NumberFormat().format(value);
|
return new Intl.NumberFormat().format(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
class NumericInput extends React.Component {
|
const NumericInput = props => {
|
||||||
onChange = e => {
|
const { value, onBlur, onChange } = props;
|
||||||
const { value } = e.target;
|
|
||||||
|
const handleChange = e => {
|
||||||
|
const inputValue = e.target.value;
|
||||||
const reg = /^-?\d*(\.\d*)?$/;
|
const reg = /^-?\d*(\.\d*)?$/;
|
||||||
if ((!isNaN(value) && reg.test(value)) || value === '' || value === '-') {
|
if ((!isNaN(inputValue) && reg.test(inputValue)) || inputValue === '' || inputValue === '-') {
|
||||||
this.props.onChange(value);
|
onChange(inputValue);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// '.' at the end or only '-' in the input box.
|
// '.' at the end or only '-' in the input box.
|
||||||
onBlur = () => {
|
const handleBlur = () => {
|
||||||
const { value, onBlur, onChange } = this.props;
|
|
||||||
let valueTemp = value;
|
let valueTemp = value;
|
||||||
if (value.charAt(value.length - 1) === '.' || value === '-') {
|
if (value.charAt(value.length - 1) === '.' || value === '-') {
|
||||||
valueTemp = value.slice(0, -1);
|
valueTemp = value.slice(0, -1);
|
||||||
@ -42,50 +43,33 @@ class NumericInput extends React.Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
|
||||||
const { value } = this.props;
|
|
||||||
const title = value ? (
|
const title = value ? (
|
||||||
<span className="numeric-input-title">{value !== '-' ? formatNumber(value) : '-'}</span>
|
<span className="numeric-input-title">{value !== '-' ? formatNumber(value) : '-'}</span>
|
||||||
) : (
|
) : (
|
||||||
'Input a number'
|
'Input a number'
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip trigger={['focus']} title={title} placement="topLeft" overlayClassName="numeric-input">
|
||||||
trigger={['focus']}
|
|
||||||
title={title}
|
|
||||||
placement="topLeft"
|
|
||||||
overlayClassName="numeric-input"
|
|
||||||
>
|
|
||||||
<Input
|
<Input
|
||||||
{...this.props}
|
{...props}
|
||||||
onChange={this.onChange}
|
onChange={handleChange}
|
||||||
onBlur={this.onBlur}
|
onBlur={handleBlur}
|
||||||
placeholder="Input a number"
|
placeholder="Input a number"
|
||||||
maxLength={25}
|
maxLength={25}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NumericInputDemo extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = { value: '' };
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange = value => {
|
|
||||||
this.setState({ value });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
export default () => {
|
||||||
return (
|
const [value, setValue] = React.useState();
|
||||||
<NumericInput style={{ width: 120 }} value={this.state.value} onChange={this.onChange} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default () => <NumericInputDemo />;
|
const onChange = val => {
|
||||||
|
setValue(val);
|
||||||
|
};
|
||||||
|
|
||||||
|
return <NumericInput style={{ width: 120 }} value={value} onChange={onChange} />;
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
```css
|
```css
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mount } from 'enzyme';
|
|
||||||
import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons';
|
import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
import mountTest from '../../../tests/shared/mountTest';
|
import mountTest from '../../../tests/shared/mountTest';
|
||||||
import rtlTest from '../../../tests/shared/rtlTest';
|
import rtlTest from '../../../tests/shared/rtlTest';
|
||||||
|
import { render, fireEvent } from '../../../tests/utils';
|
||||||
|
|
||||||
import Segmented from '../index';
|
import Segmented from '../index';
|
||||||
import type { SegmentedValue } from '../index';
|
import type { SegmentedValue } from '../index';
|
||||||
import { render } from '../../../tests/utils';
|
|
||||||
|
|
||||||
// Make CSSMotion working without transition
|
// Make CSSMotion working without transition
|
||||||
jest.mock('rc-motion/lib/util/motion', () => ({
|
jest.mock('rc-motion/lib/util/motion', () => ({
|
||||||
@ -16,6 +16,19 @@ jest.mock('rc-motion/lib/util/motion', () => ({
|
|||||||
|
|
||||||
const prefixCls = 'ant-segmented';
|
const prefixCls = 'ant-segmented';
|
||||||
|
|
||||||
|
function expectMatchChecked(container: HTMLElement, checkedList: boolean[]) {
|
||||||
|
const inputList = Array.from(
|
||||||
|
container.querySelectorAll<HTMLInputElement>(`.${prefixCls}-item-input`),
|
||||||
|
);
|
||||||
|
expect(inputList).toHaveLength(checkedList.length);
|
||||||
|
|
||||||
|
inputList.forEach((input, i) => {
|
||||||
|
const checked = checkedList[i];
|
||||||
|
|
||||||
|
expect(input.checked).toBe(checked);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
describe('Segmented', () => {
|
describe('Segmented', () => {
|
||||||
mountTest(Segmented);
|
mountTest(Segmented);
|
||||||
rtlTest(Segmented);
|
rtlTest(Segmented);
|
||||||
@ -29,26 +42,22 @@ describe('Segmented', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('render empty segmented', () => {
|
it('render empty segmented', () => {
|
||||||
const wrapper = mount(<Segmented options={[]} />);
|
const { asFragment } = render(<Segmented options={[]} />);
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented ok', () => {
|
it('render segmented ok', () => {
|
||||||
const wrapper = mount(
|
const { asFragment, container } = render(
|
||||||
<Segmented options={[{ label: 'Daily', value: 'Daily' }, 'Weekly', 'Monthly']} />,
|
<Segmented options={[{ label: 'Daily', value: 'Daily' }, 'Weekly', 'Monthly']} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
|
|
||||||
expect(
|
expectMatchChecked(container, [true, false, false]);
|
||||||
wrapper
|
|
||||||
.find(`.${prefixCls}-item-input`)
|
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
|
||||||
).toEqual([true, false, false]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render label with ReactNode', () => {
|
it('render label with ReactNode', () => {
|
||||||
const wrapper = mount(
|
const { asFragment, container } = render(
|
||||||
<Segmented
|
<Segmented
|
||||||
options={[
|
options={[
|
||||||
{ label: 'Daily', value: 'Daily' },
|
{ label: 'Daily', value: 'Daily' },
|
||||||
@ -58,164 +67,127 @@ describe('Segmented', () => {
|
|||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
|
|
||||||
expect(
|
expectMatchChecked(container, [true, false, false]);
|
||||||
wrapper
|
|
||||||
.find(`.${prefixCls}-item-input`)
|
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
|
||||||
).toEqual([true, false, false]);
|
|
||||||
|
|
||||||
expect(wrapper.find('#weekly').at(0).text()).toContain('Weekly');
|
expect(container.querySelector('#weekly')?.textContent).toContain('Weekly');
|
||||||
expect(wrapper.find('h2').at(0).text()).toContain('Monthly');
|
expect(container.querySelectorAll('h2')[0].textContent).toContain('Monthly');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented with defaultValue', () => {
|
it('render segmented with defaultValue', () => {
|
||||||
const wrapper = mount(
|
const { container } = render(
|
||||||
<Segmented
|
<Segmented
|
||||||
options={['Daily', 'Weekly', 'Monthly', 'Quarterly', 'Yearly']}
|
options={['Daily', 'Weekly', 'Monthly', 'Quarterly', 'Yearly']}
|
||||||
defaultValue="Quarterly"
|
defaultValue="Quarterly"
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expectMatchChecked(container, [false, false, false, true, false]);
|
||||||
wrapper
|
|
||||||
.find(`.${prefixCls}-item-input`)
|
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
|
||||||
).toEqual([false, false, false, true, false]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented with string options', () => {
|
it('render segmented with string options', () => {
|
||||||
const handleValueChange = jest.fn();
|
const handleValueChange = jest.fn();
|
||||||
const wrapper = mount(
|
const { asFragment, container } = render(
|
||||||
<Segmented options={['Daily', 'Weekly', 'Monthly']} onChange={handleValueChange} />,
|
<Segmented options={['Daily', 'Weekly', 'Monthly']} onChange={handleValueChange} />,
|
||||||
);
|
);
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
|
|
||||||
|
expectMatchChecked(container, [true, false, false]);
|
||||||
expect(
|
expect(
|
||||||
wrapper
|
container
|
||||||
.find(`.${prefixCls}-item-input`)
|
.querySelectorAll(`label.${prefixCls}-item`)[0]
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
.classList.contains(`${prefixCls}-item-selected`),
|
||||||
).toEqual([true, false, false]);
|
|
||||||
expect(
|
|
||||||
wrapper.find(`label.${prefixCls}-item`).at(0).hasClass(`${prefixCls}-item-selected`),
|
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
wrapper.find(`.${prefixCls}-item-input`).at(2).simulate('change');
|
fireEvent.click(container.querySelectorAll(`.${prefixCls}-item-input`)[2]);
|
||||||
expect(handleValueChange).toBeCalledWith('Monthly');
|
expect(handleValueChange).toBeCalledWith('Monthly');
|
||||||
|
|
||||||
expect(
|
expectMatchChecked(container, [false, false, true]);
|
||||||
wrapper
|
|
||||||
.find(`.${prefixCls}-item-input`)
|
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
|
||||||
).toEqual([false, false, true]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented with numeric options', () => {
|
it('render segmented with numeric options', () => {
|
||||||
const handleValueChange = jest.fn();
|
const handleValueChange = jest.fn();
|
||||||
const wrapper = mount(
|
const { asFragment, container } = render(
|
||||||
<Segmented options={[1, 2, 3, 4, 5]} onChange={value => handleValueChange(value)} />,
|
<Segmented options={[1, 2, 3, 4, 5]} onChange={value => handleValueChange(value)} />,
|
||||||
);
|
);
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
expect(
|
expectMatchChecked(container, [true, false, false, false, false]);
|
||||||
wrapper
|
|
||||||
.find(`.${prefixCls}-item-input`)
|
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
|
||||||
).toEqual([true, false, false, false, false]);
|
|
||||||
|
|
||||||
wrapper.find(`.${prefixCls}-item-input`).last().simulate('change');
|
fireEvent.click(container.querySelectorAll(`.${prefixCls}-item-input`)[4]);
|
||||||
expect(handleValueChange).toBeCalledWith(5);
|
expect(handleValueChange).toBeCalledWith(5);
|
||||||
|
|
||||||
expect(
|
expectMatchChecked(container, [false, false, false, false, true]);
|
||||||
wrapper
|
|
||||||
.find(`.${prefixCls}-item-input`)
|
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
|
||||||
).toEqual([false, false, false, false, true]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented with mixed options', () => {
|
it('render segmented with mixed options', () => {
|
||||||
const handleValueChange = jest.fn();
|
const handleValueChange = jest.fn();
|
||||||
const wrapper = mount(
|
const { asFragment, container } = render(
|
||||||
<Segmented
|
<Segmented
|
||||||
options={['Daily', { label: 'Weekly', value: 'Weekly' }, 'Monthly']}
|
options={['Daily', { label: 'Weekly', value: 'Weekly' }, 'Monthly']}
|
||||||
onChange={value => handleValueChange(value)}
|
onChange={value => handleValueChange(value)}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
|
expectMatchChecked(container, [true, false, false]);
|
||||||
|
|
||||||
wrapper.find(`.${prefixCls}-item-input`).at(1).simulate('change');
|
fireEvent.click(container.querySelectorAll(`.${prefixCls}-item-input`)[1]);
|
||||||
expect(handleValueChange).toBeCalledWith('Weekly');
|
expect(handleValueChange).toBeCalledWith('Weekly');
|
||||||
|
|
||||||
expect(
|
expectMatchChecked(container, [false, true, false]);
|
||||||
wrapper
|
|
||||||
.find(`.${prefixCls}-item-input`)
|
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
|
||||||
).toEqual([false, true, false]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented with options: disabled', () => {
|
it('render segmented with options: disabled', () => {
|
||||||
const handleValueChange = jest.fn();
|
const handleValueChange = jest.fn();
|
||||||
const wrapper = mount(
|
const { asFragment, container } = render(
|
||||||
<Segmented
|
<Segmented
|
||||||
options={['Daily', { label: 'Weekly', value: 'Weekly', disabled: true }, 'Monthly']}
|
options={['Daily', { label: 'Weekly', value: 'Weekly', disabled: true }, 'Monthly']}
|
||||||
onChange={value => handleValueChange(value)}
|
onChange={value => handleValueChange(value)}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
expect(
|
expect(
|
||||||
wrapper.find(`label.${prefixCls}-item`).at(1).hasClass(`${prefixCls}-item-disabled`),
|
container
|
||||||
|
.querySelectorAll(`label.${prefixCls}-item`)[1]
|
||||||
|
.classList.contains(`${prefixCls}-item-disabled`),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
expect(wrapper.find(`.${prefixCls}-item-input`).at(1).prop('disabled')).toBeTruthy();
|
expect(container.querySelectorAll(`.${prefixCls}-item-input`)[1]).toHaveAttribute('disabled');
|
||||||
|
|
||||||
wrapper.find(`.${prefixCls}-item-input`).at(1).simulate('change');
|
fireEvent.click(container.querySelectorAll(`.${prefixCls}-item-input`)[1]);
|
||||||
expect(handleValueChange).not.toBeCalled();
|
expect(handleValueChange).not.toBeCalled();
|
||||||
|
|
||||||
expect(
|
expectMatchChecked(container, [true, false, false]);
|
||||||
wrapper
|
|
||||||
.find(`.${prefixCls}-item-input`)
|
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
|
||||||
).toEqual([true, false, false]);
|
|
||||||
|
|
||||||
wrapper.find(`.${prefixCls}-item-input`).at(2).simulate('change');
|
fireEvent.click(container.querySelectorAll(`.${prefixCls}-item-input`)[2]);
|
||||||
expect(handleValueChange).toBeCalledWith('Monthly');
|
expect(handleValueChange).toBeCalledWith('Monthly');
|
||||||
expect(handleValueChange).toBeCalledTimes(1);
|
expect(handleValueChange).toBeCalledTimes(1);
|
||||||
|
|
||||||
expect(
|
expectMatchChecked(container, [false, false, true]);
|
||||||
wrapper
|
|
||||||
.find(`.${prefixCls}-item-input`)
|
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
|
||||||
).toEqual([false, false, true]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented: disabled', () => {
|
it('render segmented: disabled', () => {
|
||||||
const handleValueChange = jest.fn();
|
const handleValueChange = jest.fn();
|
||||||
const wrapper = mount(
|
const { asFragment, container } = render(
|
||||||
<Segmented
|
<Segmented
|
||||||
disabled
|
disabled
|
||||||
options={['Daily', 'Weekly', 'Monthly']}
|
options={['Daily', 'Weekly', 'Monthly']}
|
||||||
onChange={value => handleValueChange(value)}
|
onChange={value => handleValueChange(value)}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
expect(wrapper.find(`.${prefixCls}`).hasClass(`${prefixCls}-disabled`)).toBeTruthy();
|
expect(
|
||||||
|
container.querySelectorAll(`.${prefixCls}`)[0].classList.contains(`${prefixCls}-disabled`),
|
||||||
|
).toBeTruthy();
|
||||||
|
|
||||||
wrapper.find(`.${prefixCls}-item-input`).at(1).simulate('change');
|
fireEvent.click(container.querySelectorAll(`.${prefixCls}-item-input`)[1]);
|
||||||
expect(handleValueChange).not.toBeCalled();
|
expect(handleValueChange).not.toBeCalled();
|
||||||
|
|
||||||
expect(
|
expectMatchChecked(container, [true, false, false]);
|
||||||
wrapper
|
|
||||||
.find(`.${prefixCls}-item-input`)
|
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
|
||||||
).toEqual([true, false, false]);
|
|
||||||
|
|
||||||
wrapper.find(`.${prefixCls}-item-input`).at(2).simulate('change');
|
fireEvent.click(container.querySelectorAll(`.${prefixCls}-item-input`)[2]);
|
||||||
expect(handleValueChange).not.toBeCalled();
|
expect(handleValueChange).not.toBeCalled();
|
||||||
|
|
||||||
expect(
|
expectMatchChecked(container, [true, false, false]);
|
||||||
wrapper
|
|
||||||
.find(`.${prefixCls}-item-input`)
|
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
|
||||||
).toEqual([true, false, false]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented with className and other html attributes', () => {
|
it('render segmented with className and other html attributes', () => {
|
||||||
@ -234,11 +206,11 @@ describe('Segmented', () => {
|
|||||||
|
|
||||||
it('render segmented with ref', () => {
|
it('render segmented with ref', () => {
|
||||||
const ref = React.createRef<HTMLDivElement>();
|
const ref = React.createRef<HTMLDivElement>();
|
||||||
const wrapper = mount(
|
const { container } = render(
|
||||||
<Segmented options={['Daily', 'Monthly', 'Weekly']} defaultValue="Weekly" ref={ref} />,
|
<Segmented options={['Daily', 'Monthly', 'Weekly']} defaultValue="Weekly" ref={ref} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect((wrapper.find(Segmented).getElement() as any).ref).toBe(ref);
|
expect(ref.current).toBe(container.querySelector(`.${prefixCls}`));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented with controlled mode', async () => {
|
it('render segmented with controlled mode', async () => {
|
||||||
@ -249,6 +221,7 @@ describe('Segmented', () => {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Segmented
|
<Segmented
|
||||||
options={['Map', 'Transit', 'Satellite']}
|
options={['Map', 'Transit', 'Satellite']}
|
||||||
value={this.state.value}
|
value={this.state.value}
|
||||||
@ -258,106 +231,114 @@ describe('Segmented', () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<div className="value">{this.state.value}</div>
|
||||||
|
<input
|
||||||
|
className="control"
|
||||||
|
onChange={e => {
|
||||||
|
this.setState({ value: e.target.value });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const wrapper = mount<typeof Demo>(<Demo />);
|
const { container } = render(<Demo />);
|
||||||
wrapper.find('Segmented').find(`.${prefixCls}-item-input`).at(0).simulate('change');
|
fireEvent.click(container.querySelectorAll(`.${prefixCls}-item-input`)[0]);
|
||||||
expect(wrapper.find(Demo).state().value).toBe('Map');
|
expect(container.querySelector('.value')?.textContent).toBe('Map');
|
||||||
|
|
||||||
wrapper.find('Segmented').find(`.${prefixCls}-item-input`).at(1).simulate('change');
|
fireEvent.click(container.querySelectorAll(`.${prefixCls}-item-input`)[1]);
|
||||||
expect(wrapper.find(Demo).state().value).toBe('Transit');
|
expect(container.querySelector('.value')?.textContent).toBe('Transit');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented with options null/undefined', () => {
|
it('render segmented with options null/undefined', () => {
|
||||||
const handleValueChange = jest.fn();
|
const handleValueChange = jest.fn();
|
||||||
const wrapper = mount(
|
const { asFragment, container } = render(
|
||||||
<Segmented
|
<Segmented
|
||||||
options={[null, undefined, ''] as any}
|
options={[null, undefined, ''] as any}
|
||||||
disabled
|
disabled
|
||||||
onChange={value => handleValueChange(value)}
|
onChange={value => handleValueChange(value)}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
expect(wrapper.find(`.${prefixCls}-item-label`).map(n => n.getDOMNode().textContent)).toEqual([
|
expect(
|
||||||
'',
|
Array.from(container.querySelectorAll(`.${prefixCls}-item-label`)).map(n => n.textContent),
|
||||||
'',
|
).toEqual(['', '', '']);
|
||||||
'',
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented with thumb', () => {
|
it('render segmented with thumb', () => {
|
||||||
const handleValueChange = jest.fn();
|
const handleValueChange = jest.fn();
|
||||||
const wrapper = mount(
|
const { asFragment, container } = render(
|
||||||
<Segmented
|
<Segmented
|
||||||
options={['Map', 'Transit', 'Satellite']}
|
options={['Map', 'Transit', 'Satellite']}
|
||||||
onChange={value => handleValueChange(value)}
|
onChange={value => handleValueChange(value)}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
|
|
||||||
|
expectMatchChecked(container, [true, false, false]);
|
||||||
expect(
|
expect(
|
||||||
wrapper
|
container
|
||||||
.find(`.${prefixCls}-item-input`)
|
.querySelectorAll(`label.${prefixCls}-item`)[0]
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
.classList.contains(`${prefixCls}-item-selected`),
|
||||||
).toEqual([true, false, false]);
|
|
||||||
expect(
|
|
||||||
wrapper.find(`label.${prefixCls}-item`).at(0).hasClass(`${prefixCls}-item-selected`),
|
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
wrapper.find(`.${prefixCls}-item-input`).at(2).simulate('change');
|
fireEvent.click(container.querySelectorAll(`.${prefixCls}-item-input`)[2]);
|
||||||
expect(handleValueChange).toBeCalledWith('Satellite');
|
expect(handleValueChange).toBeCalledWith('Satellite');
|
||||||
|
|
||||||
expect(
|
expectMatchChecked(container, [false, false, true]);
|
||||||
wrapper
|
|
||||||
.find(`.${prefixCls}-item-input`)
|
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
|
||||||
).toEqual([false, false, true]);
|
|
||||||
|
|
||||||
// thumb appeared
|
// thumb appeared
|
||||||
expect(wrapper.find(`.${prefixCls}-thumb`).length).toBe(1);
|
expect(container.querySelectorAll(`.${prefixCls}-thumb`).length).toBe(1);
|
||||||
|
|
||||||
// change selection again
|
// change selection again
|
||||||
wrapper.find(`.${prefixCls}-item-input`).at(1).simulate('change');
|
fireEvent.click(container.querySelectorAll(`.${prefixCls}-item-input`)[1]);
|
||||||
expect(handleValueChange).toBeCalledWith('Transit');
|
expect(handleValueChange).toBeCalledWith('Transit');
|
||||||
|
|
||||||
expect(
|
expectMatchChecked(container, [false, true, false]);
|
||||||
wrapper
|
|
||||||
.find(`.${prefixCls}-item-input`)
|
|
||||||
.map(el => (el.getDOMNode() as HTMLInputElement).checked),
|
|
||||||
).toEqual([false, true, false]);
|
|
||||||
|
|
||||||
// thumb appeared
|
// thumb appeared
|
||||||
expect(wrapper.find(`.${prefixCls}-thumb`).length).toBe(1);
|
expect(container.querySelectorAll(`.${prefixCls}-thumb`).length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented with `block`', () => {
|
it('render segmented with `block`', () => {
|
||||||
const wrapper = mount(<Segmented block options={['Daily', 'Weekly', 'Monthly']} />);
|
const { asFragment, container } = render(
|
||||||
|
<Segmented block options={['Daily', 'Weekly', 'Monthly']} />,
|
||||||
|
);
|
||||||
|
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
|
|
||||||
expect(wrapper.find(`.${prefixCls}`).at(0).hasClass(`${prefixCls}-block`)).toBeTruthy();
|
expect(
|
||||||
|
container.querySelectorAll(`.${prefixCls}`)[0].classList.contains(`${prefixCls}-block`),
|
||||||
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented with `size#small`', () => {
|
it('render segmented with `size#small`', () => {
|
||||||
const wrapper = mount(<Segmented size="small" options={['Daily', 'Weekly', 'Monthly']} />);
|
const { asFragment, container } = render(
|
||||||
|
<Segmented size="small" options={['Daily', 'Weekly', 'Monthly']} />,
|
||||||
|
);
|
||||||
|
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
|
|
||||||
expect(wrapper.find(`.${prefixCls}`).at(0).hasClass(`${prefixCls}-sm`)).toBeTruthy();
|
expect(
|
||||||
|
container.querySelectorAll(`.${prefixCls}`)[0].classList.contains(`${prefixCls}-sm`),
|
||||||
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render segmented with `size#large`', () => {
|
it('render segmented with `size#large`', () => {
|
||||||
const wrapper = mount(<Segmented size="large" options={['Daily', 'Weekly', 'Monthly']} />);
|
const { asFragment, container } = render(
|
||||||
|
<Segmented size="large" options={['Daily', 'Weekly', 'Monthly']} />,
|
||||||
|
);
|
||||||
|
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
|
|
||||||
expect(wrapper.find(`.${prefixCls}`).at(0).hasClass(`${prefixCls}-lg`)).toBeTruthy();
|
expect(
|
||||||
|
container.querySelectorAll(`.${prefixCls}`)[0].classList.contains(`${prefixCls}-lg`),
|
||||||
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render with icons', () => {
|
it('render with icons', () => {
|
||||||
const wrapper = mount(
|
const { asFragment, container } = render(
|
||||||
<Segmented
|
<Segmented
|
||||||
options={[
|
options={[
|
||||||
{
|
{
|
||||||
@ -372,8 +353,12 @@ describe('Segmented', () => {
|
|||||||
]}
|
]}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(asFragment().firstChild).toMatchSnapshot();
|
||||||
expect(wrapper.find(`span.${prefixCls}-item-icon`).length).toBe(2);
|
expect(container.querySelectorAll(`span.${prefixCls}-item-icon`).length).toBe(2);
|
||||||
expect(wrapper.find(`div.${prefixCls}-item-label`).at(1).contains('KanbanYes')).toBeTruthy();
|
expect(
|
||||||
|
container
|
||||||
|
.querySelectorAll(`div.${prefixCls}-item-label`)[1]
|
||||||
|
.textContent?.includes('KanbanYes'),
|
||||||
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -214,6 +214,7 @@ Properties for row selection.
|
|||||||
| onSelectAll | Callback executed when select/deselect all rows | function(selected, selectedRows, changeRows) | - | |
|
| onSelectAll | Callback executed when select/deselect all rows | function(selected, selectedRows, changeRows) | - | |
|
||||||
| onSelectInvert | Callback executed when row selection is inverted | function(selectedRowKeys) | - | |
|
| onSelectInvert | Callback executed when row selection is inverted | function(selectedRowKeys) | - | |
|
||||||
| onSelectNone | Callback executed when row selection is cleared | function() | - | |
|
| onSelectNone | Callback executed when row selection is cleared | function() | - | |
|
||||||
|
| onSelectMultiple | Callback executed when row selection is changed by pressing shift | function(selected, selectedRows, changeRows) | - | |
|
||||||
|
|
||||||
### scroll
|
### scroll
|
||||||
|
|
||||||
|
@ -216,6 +216,7 @@ const columns = [
|
|||||||
| onSelectAll | 用户手动选择/取消选择所有行的回调 | function(selected, selectedRows, changeRows) | - | |
|
| onSelectAll | 用户手动选择/取消选择所有行的回调 | function(selected, selectedRows, changeRows) | - | |
|
||||||
| onSelectInvert | 用户手动选择反选的回调 | function(selectedRowKeys) | - | |
|
| onSelectInvert | 用户手动选择反选的回调 | function(selectedRowKeys) | - | |
|
||||||
| onSelectNone | 用户清空选择的回调 | function() | - | |
|
| onSelectNone | 用户清空选择的回调 | function() | - | |
|
||||||
|
| onSelectMultiple | 用户使用键盘 shift 选择多行的回调 | function(selected, selectedRows, changeRows) | - | |
|
||||||
|
|
||||||
### scroll
|
### scroll
|
||||||
|
|
||||||
|
@ -153,11 +153,13 @@ export interface TableRowSelection<T> {
|
|||||||
onChange?: (selectedRowKeys: Key[], selectedRows: T[]) => void;
|
onChange?: (selectedRowKeys: Key[], selectedRows: T[]) => void;
|
||||||
getCheckboxProps?: (record: T) => Partial<Omit<CheckboxProps, 'checked' | 'defaultChecked'>>;
|
getCheckboxProps?: (record: T) => Partial<Omit<CheckboxProps, 'checked' | 'defaultChecked'>>;
|
||||||
onSelect?: SelectionSelectFn<T>;
|
onSelect?: SelectionSelectFn<T>;
|
||||||
|
/** @deprecated This function is deprecated and should use `onChange` instead */
|
||||||
onSelectMultiple?: (selected: boolean, selectedRows: T[], changeRows: T[]) => void;
|
onSelectMultiple?: (selected: boolean, selectedRows: T[], changeRows: T[]) => void;
|
||||||
/** @deprecated This function is meaningless and should use `onChange` instead */
|
/** @deprecated This function is deprecated and should use `onChange` instead */
|
||||||
onSelectAll?: (selected: boolean, selectedRows: T[], changeRows: T[]) => void;
|
onSelectAll?: (selected: boolean, selectedRows: T[], changeRows: T[]) => void;
|
||||||
/** @deprecated This function is meaningless and should use `onChange` instead */
|
/** @deprecated This function is deprecated and should use `onChange` instead */
|
||||||
onSelectInvert?: (selectedRowKeys: Key[]) => void;
|
onSelectInvert?: (selectedRowKeys: Key[]) => void;
|
||||||
|
/** @deprecated This function is deprecated and should use `onChange` instead */
|
||||||
onSelectNone?: () => void;
|
onSelectNone?: () => void;
|
||||||
selections?: INTERNAL_SELECTION_ITEM[] | boolean;
|
selections?: INTERNAL_SELECTION_ITEM[] | boolean;
|
||||||
hideSelectAll?: boolean;
|
hideSelectAll?: boolean;
|
||||||
|
@ -122,11 +122,11 @@ ReactDOM.render(<Articles />, mountNode);
|
|||||||
|
|
||||||
### UI/UE 设计师
|
### UI/UE 设计师
|
||||||
|
|
||||||
简历和作品集请投递:lindong.lld#antgroup.com
|
简历和作品集请投递:jiayin.liu#antgroup.com
|
||||||
|
|
||||||
> 注明简历来自 ant.design 官网
|
> 注明简历来自 ant.design 官网
|
||||||
|
|
||||||
- 岗位级别:P6/P7/P8
|
- 岗位级别:P5/P6/P7/P8
|
||||||
- 岗位地点:杭州
|
- 岗位地点:杭州
|
||||||
- 岗位要求:
|
- 岗位要求:
|
||||||
- 至少 3-5 年的工作经验,扎实设计功底;
|
- 至少 3-5 年的工作经验,扎实设计功底;
|
||||||
@ -141,7 +141,6 @@ ReactDOM.render(<Articles />, mountNode);
|
|||||||
- 参与 Ant Design 的打磨,将其建设成全球卓越的设计体系。
|
- 参与 Ant Design 的打磨,将其建设成全球卓越的设计体系。
|
||||||
- 参与 AntV 的打磨,将其建设成全球一流的数据可视化体系。
|
- 参与 AntV 的打磨,将其建设成全球一流的数据可视化体系。
|
||||||
- One More Thing ❤️ :
|
- One More Thing ❤️ :
|
||||||
|
|
||||||
- 你们总是为世界带去美好,但总是忘却你们也需要美好。我们正在努力打造 [🍳 Kitchen:一款为设计师提效的 Sketch 工具集](https://kitchen.alipay.com/)等专属设计师的产品,让设计真正变成财富。期待志同道合的你,一道给设计行业带来「微小而美好的改变」。
|
- 你们总是为世界带去美好,但总是忘却你们也需要美好。我们正在努力打造 [🍳 Kitchen:一款为设计师提效的 Sketch 工具集](https://kitchen.alipay.com/)等专属设计师的产品,让设计真正变成财富。期待志同道合的你,一道给设计行业带来「微小而美好的改变」。
|
||||||
|
|
||||||
### 前端工程师
|
### 前端工程师
|
||||||
@ -150,21 +149,20 @@ ReactDOM.render(<Articles />, mountNode);
|
|||||||
|
|
||||||
> 注明简历来自 ant.design 官网
|
> 注明简历来自 ant.design 官网
|
||||||
|
|
||||||
- 岗位级别:P6/P7/P8
|
- 岗位级别:P5/P6/P7/P8
|
||||||
- 岗位地点:杭州
|
- 岗位地点:杭州/上海
|
||||||
- 岗位要求:
|
- 岗位要求:
|
||||||
- 在 React 技术栈持续耕耘,情有独钟。
|
- 在 React 技术栈持续耕耘,情有独钟。
|
||||||
- 热爱开源。
|
- 热爱开源。
|
||||||
- 坚持和善于用技术和工具解决其他问题。
|
- 坚持和善于用技术和工具解决其他问题。
|
||||||
- 丰富的中后台前端研发经验。
|
- 丰富的中后台前端研发经验。
|
||||||
- 爱 🐱。
|
|
||||||
- 岗位职责:
|
- 岗位职责:
|
||||||
- 负责 Ant Design 前端基础设施研发。
|
- 负责 Ant Design 前端基础设施研发。
|
||||||
- 负责中后台设计/前端工具体系建设。
|
- 负责中后台设计/前端工具体系建设。
|
||||||
|
|
||||||
### ADI(Artificial Design Intelligence) 工程师
|
### ADI(Artificial Design Intelligence) 工程师
|
||||||
|
|
||||||
简历和作品集请投递:lindong.lld#alipay.com
|
简历和作品集请投递:jiayin.liu#antgroup.com
|
||||||
|
|
||||||
> 注明简历来自 ant.design 官网
|
> 注明简历来自 ant.design 官网
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@
|
|||||||
"cheerio": "^1.0.0-rc.3",
|
"cheerio": "^1.0.0-rc.3",
|
||||||
"concurrently": "^7.0.0",
|
"concurrently": "^7.0.0",
|
||||||
"cross-env": "^7.0.0",
|
"cross-env": "^7.0.0",
|
||||||
"css-minimizer-webpack-plugin": "^3.2.0",
|
"css-minimizer-webpack-plugin": "^1.3.0",
|
||||||
"dekko": "^0.2.1",
|
"dekko": "^0.2.1",
|
||||||
"docsearch-react-fork": "^0.0.0-alpha.0",
|
"docsearch-react-fork": "^0.0.0-alpha.0",
|
||||||
"docsearch.js": "^2.6.3",
|
"docsearch.js": "^2.6.3",
|
||||||
@ -246,7 +246,7 @@
|
|||||||
"jsonml.js": "^0.1.0",
|
"jsonml.js": "^0.1.0",
|
||||||
"less-vars-to-js": "^1.3.0",
|
"less-vars-to-js": "^1.3.0",
|
||||||
"lz-string": "^1.4.4",
|
"lz-string": "^1.4.4",
|
||||||
"mini-css-extract-plugin": "^2.4.5",
|
"mini-css-extract-plugin": "^1.6.2",
|
||||||
"mockdate": "^3.0.0",
|
"mockdate": "^3.0.0",
|
||||||
"open": "^8.0.1",
|
"open": "^8.0.1",
|
||||||
"prettier": "^2.3.2",
|
"prettier": "^2.3.2",
|
||||||
@ -279,12 +279,11 @@
|
|||||||
"remark-cli": "^10.0.0",
|
"remark-cli": "^10.0.0",
|
||||||
"remark-lint": "^9.0.0",
|
"remark-lint": "^9.0.0",
|
||||||
"remark-preset-lint-recommended": "^6.0.0",
|
"remark-preset-lint-recommended": "^6.0.0",
|
||||||
"remove-files-webpack-plugin": "^1.4.5",
|
"remove-files-webpack-plugin": "1.4.4",
|
||||||
"rimraf": "^3.0.0",
|
"rimraf": "^3.0.0",
|
||||||
"scrollama": "^3.0.0",
|
"scrollama": "^3.0.0",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
"simple-git": "^3.0.0",
|
"simple-git": "^3.0.0",
|
||||||
"string-replace-loader": "^3.0.3",
|
|
||||||
"stylelint": "^14.0.0",
|
"stylelint": "^14.0.0",
|
||||||
"stylelint-config-prettier": "^9.0.2",
|
"stylelint-config-prettier": "^9.0.2",
|
||||||
"stylelint-config-rational-order": "^0.1.2",
|
"stylelint-config-rational-order": "^0.1.2",
|
||||||
|
Loading…
Reference in New Issue
Block a user