ConfigProvider全局化配置

为组件提供统一的全局化配置。

使用#

ConfigProvider 使用 React 的 context 特性,只需在应用外围包裹一次即可全局生效。

import { ConfigProvider } from 'sld';

// ...

export default () => (
  <ConfigProvider direction="rtl">
    <App />
  </ConfigProvider>
);

Content Security Policy#

部分组件为了支持波纹效果,使用了动态样式。如果开启了 Content Security Policy (CSP),你可以通过 csp 属性来进行配置:

<ConfigProvider csp={{ nonce: 'YourNonceCode' }}>
  <Button>My Button</Button>
</ConfigProvider>

代码演示

Change locale of components:
Click to confirm
0 item
0 item
2022
Jun
SuMoTuWeThFrSa
29
30
31
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
01
02
03
04
05
06
07
08
09
Name
Age
No Data

此处列出 SLD Design 中需要国际化支持的组件,你可以在演示里切换语言。

expand codeexpand code
import {
  ConfigProvider,
  Pagination,
  DatePicker,
  TimePicker,
  Calendar,
  Popconfirm,
  Table,
  Modal,
  Button,
  Select,
  Transfer,
  Radio,
} from 'sld';
import enUS from 'antd/lib/locale/en_US';
import zhCN from 'antd/lib/locale/zh_CN';
import moment from 'moment';
import 'moment/locale/zh-cn';

moment.locale('en');

const { Option } = Select;
const { RangePicker } = DatePicker;

const columns = [
  {
    title: 'Name',
    dataIndex: 'name',
    filters: [
      {
        text: 'filter1',
        value: 'filter1',
      },
    ],
  },
  {
    title: 'Age',
    dataIndex: 'age',
  },
];

class Page extends React.Component {
  state = {
    visible: false,
  };

  showModal = () => {
    this.setState({ visible: true });
  };

  hideModal = () => {
    this.setState({ visible: false });
  };

  render() {
    const info = () => {
      Modal.info({
        title: 'some info',
        content: 'some info',
      });
    };
    const confirm = () => {
      Modal.confirm({
        title: 'some info',
        content: 'some info',
      });
    };
    return (
      <div className="locale-components">
        <div className="example">
          <Pagination defaultCurrent={1} total={50} showSizeChanger />
        </div>
        <div className="example">
          <Select showSearch style={{ width: 200 }}>
            <Option value="jack">jack</Option>
            <Option value="lucy">lucy</Option>
          </Select>
          <DatePicker />
          <TimePicker />
          <RangePicker style={{ width: 200 }} />
        </div>
        <div className="example">
          <Button type="primary" onClick={this.showModal}>
            Show Modal
          </Button>
          <Button onClick={info}>Show info</Button>
          <Button onClick={confirm}>Show confirm</Button>
          <Popconfirm title="Question?">
            <a href="#">Click to confirm</a>
          </Popconfirm>
        </div>
        <div className="example">
          <Transfer dataSource={[]} showSearch targetKeys={[]} render={item => item.title} />
        </div>
        <div className="site-config-provider-calendar-wrapper">
          <Calendar fullscreen={false} value={moment()} />
        </div>
        <div className="example">
          <Table dataSource={[]} columns={columns} />
        </div>
        <Modal title="Locale Modal" visible={this.state.visible} onCancel={this.hideModal}>
          <p>Locale Modal</p>
        </Modal>
      </div>
    );
  }
}

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      locale: enUS,
    };
  }

  changeLocale = e => {
    const localeValue = e.target.value;
    this.setState({ locale: localeValue });
    if (!localeValue) {
      moment.locale('en');
    } else {
      moment.locale('zh-cn');
    }
  };

  render() {
    const { locale } = this.state;
    return (
      <div>
        <div className="change-locale">
          <span style={{ marginRight: 16 }}>Change locale of components: </span>
          <Radio.Group value={locale} onChange={this.changeLocale}>
            <Radio.Button key="en" value={enUS}>
              English
            </Radio.Button>
            <Radio.Button key="cn" value={zhCN}>
              中文
            </Radio.Button>
          </Radio.Group>
        </div>
        <ConfigProvider locale={locale}>
          <Page
            key={locale ? locale.locale : 'en' /* Have to refresh for production environment */}
          />
        </ConfigProvider>
      </div>
    );
  }
}

ReactDOM.render(<App />, mountNode);
.site-config-provider-calendar-wrapper {
  width: 319px;
  border: 1px solid #d9d9d9;
  border-radius: 2px;
}

.locale-components {
  padding-top: 16px;
  border-top: 1px solid #d9d9d9;
}

.code-box-demo .example {
  margin: 16px 0;
}

.code-box-demo .example > * {
  margin-right: 8px;
}

.change-locale {
  margin-bottom: 16px;
}
Change direction of components:
یک مورد انتخاب کنید
     With search:

      


parent 1
parent 1-0
leaf
leaf
parent 1-1
sss



Option1



Http://
.com

مورچه
مورچه


Finished
This is a description.
In Progress
This is a description.
Waiting
This is a description.

1
Step 1
This is a description.
2
Step 2
This is a description.
3
Step 3
This is a description.


* Note: Half star not implemented in RTL direction, it will be supported after rc-rate implement rtl support.
5



* Note: Every calculation in RTL grid system is from right side (offset, push, etc.)

col-8
col-8
col-6 col-offset-6
col-6 col-offset-6
col-12 col-offset-6
col-18 col-push-6
col-6 col-pull-18

这里列出了支持 rtl 方向的组件,您可以在演示中切换方向。

expand codeexpand code
import {
  Input,
  Col,
  Row,
  Select,
  InputNumber,
  ConfigProvider,
  Cascader,
  Radio,
  Switch,
  Tree,
  TreeSelect,
  Modal,
  Button,
  Pagination,
  Steps,
  Rate,
  Badge,
  Divider,
} from 'sld';

import {
  SearchOutlined as SearchIcon,
  SmileOutlined,
  DownloadOutlined,
  LeftOutlined,
  RightOutlined,
  MinusOutlined,
  PlusOutlined,
} from '@sld-icon/icons';

const InputGroup = Input.Group;
const ButtonGroup = Button.Group;
const { Option } = Select;
const { TreeNode } = Tree;
const { Search } = Input;
const { Step } = Steps;

const cascaderOptions = [
  {
    value: 'tehran',
    label: 'تهران',
    children: [
      {
        value: 'tehran-c',
        label: 'تهران',
        children: [
          {
            value: 'saadat-abad',
            label: 'سعادت آیاد',
          },
        ],
      },
    ],
  },
  {
    value: 'ardabil',
    label: 'اردبیل',
    children: [
      {
        value: 'ardabil-c',
        label: 'اردبیل',
        children: [
          {
            value: 'primadar',
            label: 'پیرمادر',
          },
        ],
      },
    ],
  },
  {
    value: 'gilan',
    label: 'گیلان',
    children: [
      {
        value: 'rasht',
        label: 'رشت',
        children: [
          {
            value: 'district-3',
            label: 'منطقه ۳',
          },
        ],
      },
    ],
  },
];

class Page extends React.Component {
  state = {
    currentStep: 0,
    modalVisible: false,

    badgeCount: 5,
    showBadge: true,
  };

  selectBefore = (
    <Select defaultValue="Http://" style={{ width: 90 }}>
      <Option value="Http://">Http://</Option>
      <Option value="Https://">Https://</Option>
    </Select>
  );

  selectAfter = (
    <Select defaultValue=".com" style={{ width: 80 }}>
      <Option value=".com">.com</Option>
      <Option value=".jp">.jp</Option>
      <Option value=".cn">.cn</Option>
      <Option value=".org">.org</Option>
    </Select>
  );

  // ==== Cascader ====
  cascaderFilter = (inputValue, path) =>
    path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);

  onCascaderChange = value => {
    console.log(value);
  };
  // ==== End Cascader ====

  // ==== Modal ====
  showModal = () => {
    this.setState({
      modalVisible: true,
    });
  };

  handleOk = e => {
    console.log(e);
    this.setState({
      modalVisible: false,
    });
  };

  handleCancel = e => {
    console.log(e);
    this.setState({
      modalVisible: false,
    });
  };
  // ==== End Modal ====

  onStepsChange = currentStep => {
    console.log('onChange:', currentStep);
    this.setState({ currentStep });
  };

  // ==== Badge ====

  increaseBadge = () => {
    const badgeCount = this.state.badgeCount + 1;
    this.setState({ badgeCount });
  };

  declineBadge = () => {
    let badgeCount = this.state.badgeCount - 1;
    if (badgeCount < 0) {
      badgeCount = 0;
    }
    this.setState({ badgeCount });
  };

  onChangeBadge = showBadge => {
    this.setState({ showBadge });
  };
  // ==== End Badge ====

  render() {
    const { currentStep } = this.state;
    return (
      <div className="direction-components">
        <Row>
          <Col span={24}>
            <Divider orientation="left">Cascader example</Divider>
            <Cascader
              suffixIcon={<SearchIcon />}
              options={cascaderOptions}
              onChange={this.onCascaderChange}
              placeholder="یک مورد انتخاب کنید"
              popupPlacement={this.props.popupPlacement}
            />
            &nbsp;&nbsp;&nbsp;&nbsp; With search:
            <Cascader
              suffixIcon={<SmileOutlined />}
              options={cascaderOptions}
              onChange={this.onCascaderChange}
              placeholder="Select an item"
              popupPlacement={this.props.popupPlacement}
              showSearch={this.cascaderFilter}
            />
          </Col>
        </Row>
        <br />
        <Row>
          <Col span={12}>
            <Divider orientation="left">Switch example</Divider>
            &nbsp;&nbsp;
            <Switch defaultChecked />
            &nbsp;&nbsp;
            <Switch loading defaultChecked />
            &nbsp;&nbsp;
            <Switch size="small" loading />
          </Col>
          <Col span={12}>
            <Divider orientation="left">Radio Group example</Divider>

            <Radio.Group defaultValue="c" buttonStyle="solid">
              <Radio.Button value="a">تهران</Radio.Button>
              <Radio.Button value="b" disabled>
                اصفهان
              </Radio.Button>
              <Radio.Button value="c">فارس</Radio.Button>
              <Radio.Button value="d">خوزستان</Radio.Button>
            </Radio.Group>
          </Col>
        </Row>
        <br />
        <Row>
          <Col span={12}>
            <Divider orientation="left">Button example</Divider>
            <div className="button-demo">
              <Button type="primary" icon={<DownloadOutlined />} />
              <Button type="primary" shape="circle" icon={<DownloadOutlined />} />
              <Button type="primary" shape="round" icon={<DownloadOutlined />} />
              <Button type="primary" shape="round" icon={<DownloadOutlined />}>
                Download
              </Button>
              <Button type="primary" icon={<DownloadOutlined />}>
                Download
              </Button>
              <br />
              <Button.Group>
                <Button type="primary">
                  <LeftOutlined />
                  Backward
                </Button>
                <Button type="primary">
                  Forward
                  <RightOutlined />
                </Button>
              </Button.Group>
              <Button type="primary" loading>
                Loading
              </Button>
              <Button type="primary" size="small" loading>
                Loading
              </Button>
            </div>
          </Col>
          <Col span={12}>
            <Divider orientation="left">Tree example</Divider>
            <Tree
              showLine
              checkable
              defaultExpandedKeys={['0-0-0', '0-0-1']}
              defaultSelectedKeys={['0-0-0', '0-0-1']}
              defaultCheckedKeys={['0-0-0', '0-0-1']}
            >
              <TreeNode title="parent 1" key="0-0">
                <TreeNode title="parent 1-0" key="0-0-0" disabled>
                  <TreeNode title="leaf" key="0-0-0-0" disableCheckbox />
                  <TreeNode title="leaf" key="0-0-0-1" />
                </TreeNode>
                <TreeNode title="parent 1-1" key="0-0-1">
                  <TreeNode title={<span style={{ color: '#1890ff' }}>sss</span>} key="0-0-1-0" />
                </TreeNode>
              </TreeNode>
            </Tree>
          </Col>
        </Row>
        <br />
        <Row>
          <Col span={24}>
            <Divider orientation="left">Input (Input Group) example</Divider>
            <InputGroup size="large">
              <Row gutter={8}>
                <Col span={5}>
                  <Input defaultValue="0571" />
                </Col>
                <Col span={8}>
                  <Input defaultValue="26888888" />
                </Col>
              </Row>
            </InputGroup>
            <br />
            <InputGroup compact>
              <Input style={{ width: '20%' }} defaultValue="0571" />
              <Input style={{ width: '30%' }} defaultValue="26888888" />
            </InputGroup>
            <br />
            <InputGroup compact>
              <Select defaultValue="Option1">
                <Option value="Option1">Option1</Option>
                <Option value="Option2">Option2</Option>
              </Select>
              <Input style={{ width: '50%' }} defaultValue="input content" />
              <InputNumber />
            </InputGroup>
            <br />
            <Search placeholder="input search text" enterButton="Search" size="large" />
            <br />
            <br />
            <div style={{ marginBottom: 16 }}>
              <Input
                addonBefore={this.selectBefore}
                addonAfter={this.selectAfter}
                defaultValue="mysite"
              />
            </div>
            <br />
            <Row>
              <Col span={12}>
                <Divider orientation="left">Select example</Divider>
                <Select mode="multiple" defaultValue="مورچه" style={{ width: 120 }}>
                  <Option value="jack">Jack</Option>
                  <Option value="مورچه">مورچه</Option>
                  <Option value="disabled" disabled>
                    Disabled
                  </Option>
                  <Option value="Yiminghe">yiminghe</Option>
                </Select>
                <Select defaultValue="مورچه" style={{ width: 120 }} disabled>
                  <Option value="مورچه">مورچه</Option>
                </Select>
                <Select defaultValue="مورچه" style={{ width: 120 }} loading>
                  <Option value="مورچه">مورچه</Option>
                </Select>
                <Select
                  showSearch
                  style={{ width: 200 }}
                  placeholder="Select a person"
                  optionFilterProp="children"
                  filterOption={(input, option) =>
                    option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
                  }
                >
                  <Option value="jack">Jack</Option>
                  <Option value="سعید">سعید</Option>
                  <Option value="tom">Tom</Option>
                </Select>
              </Col>
              <Col span={12}>
                <Divider orientation="left">TreeSelect example</Divider>
                <div>
                  <TreeSelect
                    showSearch
                    style={{ width: '100%' }}
                    dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
                    placeholder="Please select"
                    allowClear
                    treeDefaultExpandAll
                  >
                    <TreeNode value="parent 1" title="parent 1" key="0-1">
                      <TreeNode value="parent 1-0" title="parent 1-0" key="0-1-1">
                        <TreeNode value="leaf1" title="my leaf" key="random" />
                        <TreeNode value="leaf2" title="your leaf" key="random1" />
                      </TreeNode>
                      <TreeNode value="parent 1-1" title="parent 1-1" key="random2">
                        <TreeNode
                          value="sss"
                          title={<b style={{ color: '#08c' }}>sss</b>}
                          key="random3"
                        />
                      </TreeNode>
                    </TreeNode>
                  </TreeSelect>
                </div>
              </Col>
            </Row>
            <br />
            <Row>
              <Col span={24}>
                <Divider orientation="left">Modal example</Divider>
                <div>
                  <Button type="primary" onClick={this.showModal}>
                    Open Modal
                  </Button>
                  <Modal
                    title="پنچره ساده"
                    visible={this.state.modalVisible}
                    onOk={this.handleOk}
                    onCancel={this.handleCancel}
                  >
                    <p>نگاشته‌های خود را اینجا قراردهید</p>
                    <p>نگاشته‌های خود را اینجا قراردهید</p>
                    <p>نگاشته‌های خود را اینجا قراردهید</p>
                  </Modal>
                </div>
              </Col>
            </Row>
            <br />
            <Row>
              <Col span={24}>
                <Divider orientation="left">Steps example</Divider>
                <div>
                  <Steps progressDot current={currentStep}>
                    <Step title="Finished" description="This is a description." />
                    <Step title="In Progress" description="This is a description." />
                    <Step title="Waiting" description="This is a description." />
                  </Steps>
                  <br />
                  <Steps current={currentStep} onChange={this.onStepsChange}>
                    <Step title="Step 1" description="This is a description." />
                    <Step title="Step 2" description="This is a description." />
                    <Step title="Step 3" description="This is a description." />
                  </Steps>
                </div>
              </Col>
            </Row>
            <br />
            <Row>
              <Col span={12}>
                <Divider orientation="left">Rate example</Divider>
                <div>
                  <Rate defaultValue={2.5} />
                  <br />
                  <strong>* Note:</strong> Half star not implemented in RTL direction, it will be
                  supported after <a href="https://github.com/react-component/rate">rc-rate</a>{' '}
                  implement rtl support.
                </div>
              </Col>
              <Col span={12}>
                <Divider orientation="left">Badge example</Divider>
                <div>
                  <div>
                    <Badge count={this.state.badgeCount}>
                      <a href="#" className="head-example" />
                    </Badge>
                    <ButtonGroup>
                      <Button onClick={this.declineBadge}>
                        <MinusOutlined />
                      </Button>
                      <Button onClick={this.increaseBadge}>
                        <PlusOutlined />
                      </Button>
                    </ButtonGroup>
                  </div>
                  <div style={{ marginTop: 10 }}>
                    <Badge dot={this.state.showBadge}>
                      <a href="#" className="head-example" />
                    </Badge>
                    <Switch onChange={this.onChangeBadge} checked={this.state.showBadge} />
                  </div>
                </div>
              </Col>
            </Row>
          </Col>
        </Row>

        <br />
        <br />
        <Row>
          <Col span={24}>
            <Divider orientation="left">Pagination example</Divider>
            <Pagination showSizeChanger defaultCurrent={3} total={500} />
          </Col>
        </Row>
        <br />
        <Row>
          <Col span={24}>
            <Divider orientation="left">Grid System example</Divider>
            <div className="grid-demo">
              <div className="code-box-demo">
                <p>
                  <strong>* Note:</strong> Every calculation in RTL grid system is from right side
                  (offset, push, etc.)
                </p>
                <Row>
                  <Col span={8}>col-8</Col>
                  <Col span={8} offset={8}>
                    col-8
                  </Col>
                </Row>
                <Row>
                  <Col span={6} offset={6}>
                    col-6 col-offset-6
                  </Col>
                  <Col span={6} offset={6}>
                    col-6 col-offset-6
                  </Col>
                </Row>
                <Row>
                  <Col span={12} offset={6}>
                    col-12 col-offset-6
                  </Col>
                </Row>
                <Row>
                  <Col span={18} push={6}>
                    col-18 col-push-6
                  </Col>
                  <Col span={6} pull={18}>
                    col-6 col-pull-18
                  </Col>
                </Row>
              </div>
            </div>
          </Col>
        </Row>
      </div>
    );
  }
}

class App extends React.Component {
  state = {
    direction: 'ltr',
    popupPlacement: 'bottomLeft',
  };

  changeDirection = e => {
    const directionValue = e.target.value;
    this.setState({ direction: directionValue });
    if (directionValue === 'rtl') {
      this.setState({ popupPlacement: 'bottomRight' });
    } else {
      this.setState({ popupPlacement: 'bottomLeft' });
    }
  };

  render() {
    const { direction, popupPlacement } = this.state;
    return (
      <>
        <div style={{ marginBottom: 16 }}>
          <span style={{ marginRight: 16 }}>Change direction of components: </span>
          <Radio.Group defaultValue="ltr" onChange={this.changeDirection}>
            <Radio.Button key="ltr" value="ltr">
              LTR
            </Radio.Button>
            <Radio.Button key="rtl" value="rtl">
              RTL
            </Radio.Button>
          </Radio.Group>
        </div>
        <ConfigProvider direction={direction}>
          <Page className={direction} popupPlacement={popupPlacement} />
        </ConfigProvider>
      </>
    );
  }
}

ReactDOM.render(<App />, mountNode);
.button-demo .ant-btn,
.button-demo .ant-btn-group {
  margin-right: 8px;
  margin-bottom: 12px;
}
.button-demo .ant-btn-group > .ant-btn,
.button-demo .ant-btn-group > span > .ant-btn {
  margin-right: 0;
  margin-left: 0;
}

.head-example {
  display: inline-block;
  width: 42px;
  height: 42px;
  vertical-align: middle;
  background: #eee;
  border-radius: 4px;
}

.ant-badge:not(.ant-badge-not-a-wrapper) {
  margin-right: 20px;
}
.ant-badge-rtl:not(.ant-badge-not-a-wrapper) {
  margin-right: 0;
  margin-left: 20px;
}
Content of Tab Pane 1
demo
Card
NameAge
John Brown32
Jim Green42
Joe Black32

修改默认组件尺寸。

expand codeexpand code
import React, { useState } from 'react';
import {
  ConfigProvider,
  Radio,
  Input,
  Button,
  Select,
  DatePicker,
  Divider,
  Table,
  Card,
  Tabs,
} from 'sld';

const { TabPane } = Tabs;

const FormSizeDemo = () => {
  const [componentSize, setComponentSize] = useState('small');
  return (
    <div>
      <Radio.Group
        value={componentSize}
        onChange={e => {
          setComponentSize(e.target.value);
        }}
      >
        <Radio.Button value="small">Small</Radio.Button>
        <Radio.Button value="middle">Middle</Radio.Button>
        <Radio.Button value="large">Large</Radio.Button>
      </Radio.Group>
      <Divider />
      <ConfigProvider componentSize={componentSize}>
        <div className="example">
          <Input />
        </div>
        <div className="example">
          <Tabs defaultActiveKey="1">
            <TabPane tab="Tab 1" key="1">
              Content of Tab Pane 1
            </TabPane>
            <TabPane tab="Tab 2" key="2">
              Content of Tab Pane 2
            </TabPane>
            <TabPane tab="Tab 3" key="3">
              Content of Tab Pane 3
            </TabPane>
          </Tabs>
        </div>
        <div className="example">
          <Input.Search allowClear />
        </div>
        <div className="example">
          <Input.TextArea allowClear />
        </div>
        <div className="example">
          <Select defaultValue="demo" options={[{ value: 'demo' }]} />
        </div>
        <div className="example">
          <DatePicker />
        </div>
        <div className="example">
          <DatePicker.RangePicker />
        </div>
        <div className="example">
          <Button>Button</Button>
        </div>
        <div className="example">
          <Card title="Card">
            <Table
              columns={[
                { title: 'Name', dataIndex: 'name' },
                { title: 'Age', dataIndex: 'age' },
              ]}
              dataSource={[
                {
                  key: '1',
                  name: 'John Brown',
                  age: 32,
                },
                {
                  key: '2',
                  name: 'Jim Green',
                  age: 42,
                },
                {
                  key: '3',
                  name: 'Joe Black',
                  age: 32,
                },
              ]}
            />
          </Card>
        </div>
      </ConfigProvider>
    </div>
  );
};
ReactDOM.render(<FormSizeDemo />, mountNode);
var(`--ant-primary-color`)
var(`--ant-error-color`)
var(`--ant-warning-color`)
var(`--ant-success-color`)
var(`--ant-info-color`)
Text (success)
Text(warning)
Text(danger)
Text
Finished
This is a description.
2
In Progress
Left 00:00:08
This is a description.
3
Waiting
This is a description.
Finished
You can hover on the dot.
In Progress
You can hover on the dot.
Error
You can hover on the dot.
Waiting
You can hover on the dot.
Key
Bamboo
Light
Little
Content of Tab Pane 1
success
processing
error
warning
default
CheckableTag
  • Create a services site 2015-09-01
  • Solve initial network problems 2015-09-01
  • Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
Little
Light
Bamboo
30%
75%
1/19 items
  • content1
  • content2
  • content3
  • content4
  • content5
  • content6
  • content7
  • content8
  • content9
  • content10
  • content11
  • content12
  • content13
  • content14
  • content15
  • content16
  • content17
  • content18
  • content20
1 item
  • content19

通过 css variable 修改全局主题色(你可以切换到组件页面查看更详细的样式展示),不支持 IE。自动生成的变量可能会根据设计调整,请勿直接依赖。详细配置请点击查看

expand codeexpand code
import { SketchPicker } from 'react-color';
import React, { useState } from 'react';
import { DownOutlined, MailOutlined, SettingOutlined, ClockCircleOutlined } from '@sld-icon/icons';
import {
  ConfigProvider,
  Tag,
  Mentions,
  Steps,
  Button,
  Radio,
  Space,
  Form,
  Input,
  Row,
  Col,
  Typography,
  Menu,
  Dropdown,
  Divider,
  Pagination,
  Select,
  Checkbox,
  DatePicker,
  TimePicker,
  InputNumber,
  Slider,
  Switch,
  TreeSelect,
  Card,
  Table,
  Tabs,
  Timeline,
  Tree,
  Alert,
  Progress,
  Spin,
  Transfer,
} from 'sld';

const SplitSpace = props => <Space split={<Divider type="vertical" />} size={4} {...props} />;

const inputProps = {
  style: { width: 128 },
};

const selectProps = {
  ...inputProps,
  options: [
    { value: 'light', label: 'Light' },
    { value: 'bamboo', label: 'Bamboo' },
    { value: 'little', label: 'Little' },
  ],
};

const treeData = [
  {
    value: 'little',
    key: 'little',
    label: 'Little',
    title: 'Little',
    children: [
      { value: 'light', key: 'light', label: 'Light', title: 'Light' },
      { value: 'bamboo', key: 'bamboo', label: 'Bamboo', title: 'Bamboo' },
    ],
  },
];

const treeSelectProps = {
  ...inputProps,
  treeCheckable: true,
  maxTagCount: 'responsive',
  treeData,
};

const carTabListNoTitle = [
  {
    key: 'article',
    tab: 'article',
  },
  {
    key: 'app',
    tab: 'app',
  },
  {
    key: 'project',
    tab: 'project',
  },
];

const MyTransfer = () => {
  const mockData = [];
  for (let i = 0; i < 20; i++) {
    mockData.push({
      key: i.toString(),
      title: `content${i + 1}`,
      description: `description of content${i + 1}`,
    });
  }

  return (
    <Transfer
      dataSource={mockData}
      targetKeys={['18']}
      selectedKeys={['3']}
      render={item => item.title}
    />
  );
};

const FormSizeDemo = () => {
  const [color, setColor] = useState({
    primaryColor: '#1890ff',
    errorColor: '#ff4d4f',
    warningColor: '#faad14',
    successColor: '#52c41a',
    infoColor: '#1890ff',
  });

  function onColorChange(nextColor) {
    const mergedNextColor = {
      ...color,
      ...nextColor,
    };
    setColor(mergedNextColor);
    ConfigProvider.config({
      theme: mergedNextColor,
    });
  }

  return (
    <Row gutter={16} wrap={false}>
      <Col flex="none">
        <Space direction="vertical" align="center">
          {/* Primary Color */}
          <SketchPicker
            presetColors={['#1890ff', '#25b864', '#ff6f00']}
            color={color.primaryColor}
            onChange={({ hex }) => {
              onColorChange({
                primaryColor: hex,
              });
            }}
          />

          <span style={{ color: 'var(--ant-primary-color)' }}>var(`--ant-primary-color`)</span>

          {/* Error Color */}
          <SketchPicker
            presetColors={['#ff4d4f']}
            color={color.errorColor}
            onChange={({ hex }) => {
              onColorChange({
                errorColor: hex,
              });
            }}
          />

          <span style={{ color: 'var(--ant-error-color)' }}>var(`--ant-error-color`)</span>

          {/* Warning Color */}
          <SketchPicker
            presetColors={['#faad14']}
            color={color.warningColor}
            onChange={({ hex }) => {
              onColorChange({
                warningColor: hex,
              });
            }}
          />

          <span style={{ color: 'var(--ant-warning-color)' }}>var(`--ant-warning-color`)</span>

          {/* Success Color */}
          <SketchPicker
            presetColors={['#52c41a']}
            color={color.successColor}
            onChange={({ hex }) => {
              onColorChange({
                successColor: hex,
              });
            }}
          />

          <span style={{ color: 'var(--ant-success-color)' }}>var(`--ant-success-color`)</span>

          {/* Info Color */}
          <SketchPicker
            presetColors={['#1890ff']}
            color={color.infoColor}
            onChange={({ hex }) => {
              onColorChange({
                infoColor: hex,
              });
            }}
          />

          <span style={{ color: 'var(--ant-info-color)' }}>var(`--ant-info-color`)</span>
        </Space>
      </Col>

      <Col flex="auto">
        <Space direction="vertical" split={<Divider />} style={{ width: '100%' }} size={0}>
          {/* Primary Button */}
          <SplitSpace>
            <Button type="primary">Primary</Button>
            <Button>Default</Button>
            <Button type="dashed">Dashed</Button>
            <Button type="text">Text</Button>
            <Button type="link">Link</Button>
          </SplitSpace>

          {/* Danger Button */}
          <SplitSpace>
            <Button danger type="primary">
              Primary
            </Button>
            <Button danger>Default</Button>
            <Button danger type="dashed">
              Dashed
            </Button>
            <Button danger type="text">
              Text
            </Button>
            <Button danger type="link">
              Link
            </Button>
          </SplitSpace>

          {/* Ghost Button */}
          <SplitSpace style={{ background: 'rgb(190, 200, 200)' }}>
            <Button type="primary" ghost>
              Primary
            </Button>
            <Button ghost>Default</Button>
            <Button type="dashed" ghost>
              Dashed
            </Button>
            <Button type="primary" ghost danger>
              Primary
            </Button>
            <Button ghost danger>
              Default
            </Button>
            <Button type="dashed" ghost danger>
              Dashed
            </Button>
          </SplitSpace>

          {/* Typography */}
          <SplitSpace>
            <Typography.Text type="success">Text (success)</Typography.Text>
            <Typography.Text type="warning">Text(warning)</Typography.Text>
            <Typography.Text type="danger">Text(danger)</Typography.Text>
            <Typography.Link href="https://slingdesign.dtyunxi.com" target="_blank">
              Link
            </Typography.Link>
            <Typography.Text copyable>Text</Typography.Text>

            {/* Dropdown */}
            <Dropdown
              overlay={
                <Menu>
                  <Menu.Item>1st menu item</Menu.Item>
                  <Menu.Item danger>a danger item</Menu.Item>
                </Menu>
              }
            >
              <a className="ant-dropdown-link" onClick={e => e.preventDefault()}>
                Hover me <DownOutlined />
              </a>
            </Dropdown>

            {/* Spin */}
            <Spin />
          </SplitSpace>

          {/* Menu - horizontal */}
          <Row gutter={16}>
            <Col span={12}>
              <Menu mode="horizontal" defaultSelectedKeys={['mail']}>
                <Menu.Item key="mail" icon={<MailOutlined />}>
                  Mail
                </Menu.Item>
                <Menu.SubMenu key="SubMenu" icon={<SettingOutlined />} title="Submenu">
                  <Menu.ItemGroup title="Item 1">
                    <Menu.Item key="setting:1">Option 1</Menu.Item>
                    <Menu.Item key="setting:2">Option 2</Menu.Item>
                  </Menu.ItemGroup>
                </Menu.SubMenu>
              </Menu>
            </Col>
            <Col span={12}>
              <Menu mode="horizontal" theme="dark" defaultSelectedKeys={['mail']}>
                <Menu.Item key="mail" icon={<MailOutlined />}>
                  Mail
                </Menu.Item>
                <Menu.SubMenu key="SubMenu" icon={<SettingOutlined />} title="Submenu">
                  <Menu.ItemGroup title="Item 1">
                    <Menu.Item key="setting:1">Option 1</Menu.Item>
                    <Menu.Item key="setting:2">Option 2</Menu.Item>
                  </Menu.ItemGroup>
                </Menu.SubMenu>
              </Menu>
            </Col>
          </Row>

          {/* Menu - vertical */}
          <Row gutter={16}>
            <Col span={12}>
              <Menu mode="inline" defaultSelectedKeys={['mail']}>
                <Menu.Item key="mail" icon={<MailOutlined />}>
                  Mail
                </Menu.Item>
                <Menu.SubMenu key="SubMenu" icon={<SettingOutlined />} title="Submenu">
                  <Menu.ItemGroup title="Item 1">
                    <Menu.Item key="setting:1">Option 1</Menu.Item>
                    <Menu.Item key="setting:2">Option 2</Menu.Item>
                  </Menu.ItemGroup>
                </Menu.SubMenu>
              </Menu>
            </Col>
            <Col span={12}>
              <Menu mode="vertical" theme="dark" defaultSelectedKeys={['mail']}>
                <Menu.Item key="mail" icon={<MailOutlined />}>
                  Mail
                </Menu.Item>
                <Menu.SubMenu key="SubMenu" icon={<SettingOutlined />} title="Submenu">
                  <Menu.ItemGroup title="Item 1">
                    <Menu.Item key="setting:1">Option 1</Menu.Item>
                    <Menu.Item key="setting:2">Option 2</Menu.Item>
                  </Menu.ItemGroup>
                </Menu.SubMenu>
              </Menu>
            </Col>
          </Row>

          {/* Pagination */}
          <Pagination showQuickJumper defaultCurrent={2} total={500} />

          {/* Steps */}
          <Steps current={1} percent={60}>
            <Steps.Step title="Finished" description="This is a description." />
            <Steps.Step
              title="In Progress"
              subTitle="Left 00:00:08"
              description="This is a description."
            />
            <Steps.Step title="Waiting" description="This is a description." />
          </Steps>

          {/* Steps - dot */}
          <Steps current={2} status="error" progressDot>
            <Steps.Step title="Finished" description="You can hover on the dot." />
            <Steps.Step title="In Progress" description="You can hover on the dot." />
            <Steps.Step title="Error" description="You can hover on the dot." />
            <Steps.Step title="Waiting" description="You can hover on the dot." />
          </Steps>

          {/* Form - Input */}
          <Form>
            <SplitSpace>
              <Form.Item>
                <Input {...inputProps} />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="success">
                <Input {...inputProps} />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="warning">
                <Input {...inputProps} />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="error">
                <Input {...inputProps} />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="validating">
                <Input {...inputProps} />
              </Form.Item>
            </SplitSpace>
          </Form>

          {/* Form - Select */}
          <Form>
            <SplitSpace>
              <Form.Item>
                <Select {...selectProps} />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="success">
                <Select {...selectProps} />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="warning">
                <Select {...selectProps} />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="error">
                <Select {...selectProps} />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="validating">
                <Select {...selectProps} />
              </Form.Item>
            </SplitSpace>
          </Form>

          {/* Form - TreeSelect */}
          <Form>
            <SplitSpace>
              <Form.Item>
                <TreeSelect {...treeSelectProps} />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="success">
                <TreeSelect {...treeSelectProps} />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="warning">
                <TreeSelect {...treeSelectProps} />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="error">
                <TreeSelect {...treeSelectProps} />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="validating">
                <TreeSelect {...treeSelectProps} />
              </Form.Item>
            </SplitSpace>
          </Form>

          {/* Form - InputNumber */}
          <Form>
            <SplitSpace>
              <Form.Item>
                <InputNumber />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="success">
                <InputNumber />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="warning">
                <InputNumber />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="error">
                <InputNumber />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="validating">
                <InputNumber />
              </Form.Item>
            </SplitSpace>
          </Form>

          {/* Form - DatePicker */}
          <Form>
            <SplitSpace>
              <Form.Item>
                <DatePicker />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="success">
                <DatePicker />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="warning">
                <DatePicker />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="error">
                <DatePicker />
              </Form.Item>
              <Form.Item hasFeedback validateStatus="validating">
                <DatePicker />
              </Form.Item>
            </SplitSpace>
          </Form>

          <SplitSpace>
            <Checkbox>Checkbox</Checkbox>

            <Radio.Group defaultValue="bamboo">
              <Radio value="bamboo">Bamboo</Radio>
              <Radio value="light">Light</Radio>
              <Radio value="little">Little</Radio>
            </Radio.Group>

            <Mentions placeholder="Mention by @">
              <Mentions.Option value="afc163">afc163</Mentions.Option>
              <Mentions.Option value="zombieJ">zombieJ</Mentions.Option>
              <Mentions.Option value="yesmeck">yesmeck</Mentions.Option>
            </Mentions>

            <Slider defaultValue={30} style={{ width: 100 }} />

            <Switch defaultChecked />
          </SplitSpace>

          <SplitSpace>
            <DatePicker.RangePicker />
            <TimePicker.RangePicker />
          </SplitSpace>

          <Row gutter={16}>
            <Col span={8}>
              {/* Card */}
              <Card
                style={{ width: '100%' }}
                tabList={carTabListNoTitle}
                tabBarExtraContent={<a href="#">More</a>}
              />
            </Col>
            <Col span={8}>
              {/* Table */}
              <Table
                size="small"
                bordered
                rowSelection={{}}
                columns={[
                  {
                    title: 'Key',
                    dataIndex: 'key',
                    filters: [
                      {
                        text: 'Little',
                        value: 'little',
                      },
                    ],
                    sorter: (a, b) => a.key.length - b.key.length,
                  },
                ]}
                dataSource={[
                  {
                    key: 'Bamboo',
                  },
                  {
                    key: 'Light',
                  },
                  {
                    key: 'Little',
                  },
                ]}
              />
            </Col>
            <Col span={8}>
              {/* Table */}
              <Tabs defaultActiveKey="1">
                <Tabs.TabPane tab="Tab 1" key="1">
                  Content of Tab Pane 1
                </Tabs.TabPane>
                <Tabs.TabPane tab="Tab 2" key="2">
                  Content of Tab Pane 2
                </Tabs.TabPane>
                <Tabs.TabPane tab="Tab 3" key="3">
                  Content of Tab Pane 3
                </Tabs.TabPane>
              </Tabs>
            </Col>
          </Row>

          <SplitSpace>
            <Tag color="success">success</Tag>
            <Tag color="processing">processing</Tag>
            <Tag color="error">error</Tag>
            <Tag color="warning">warning</Tag>
            <Tag color="default">default</Tag>
            <Tag.CheckableTag checked>CheckableTag</Tag.CheckableTag>
          </SplitSpace>

          <Row gutter={16}>
            <Col span={16}>
              <Timeline mode="alternate">
                <Timeline.Item>Create a services site 2015-09-01</Timeline.Item>
                <Timeline.Item color="gray">
                  Solve initial network problems 2015-09-01
                </Timeline.Item>
                <Timeline.Item dot={<ClockCircleOutlined style={{ fontSize: '16px' }} />}>
                  Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
                  doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore
                  veritatis et quasi architecto beatae vitae dicta sunt explicabo.
                </Timeline.Item>
              </Timeline>
            </Col>

            <Col span={8}>
              <Tree treeData={treeData} height={200} defaultExpandAll checkable />
            </Col>
          </Row>

          {/* Alert */}
          <Row gutter={16}>
            <Col span={6}>
              <Alert showIcon message="Success Text" type="success" />
            </Col>
            <Col span={6}>
              <Alert showIcon message="Info Text" type="info" />
            </Col>
            <Col span={6}>
              <Alert showIcon message="Warning Text" type="warning" />
            </Col>
            <Col span={6}>
              <Alert showIcon message="Error Text" type="error" />
            </Col>
          </Row>

          {/* Progress */}
          <Row gutter={16}>
            <Col flex="auto">
              <Progress percent={30} />
              <Progress percent={70} status="exception" />
              <Progress percent={100} />
            </Col>
            <Col flex="none">
              <Progress type="circle" percent={75} />
              <Progress type="circle" percent={70} status="exception" />
              <Progress type="circle" percent={100} />
            </Col>
          </Row>

          <MyTransfer />
        </Space>
      </Col>
    </Row>
  );
};
ReactDOM.render(<FormSizeDemo />, mountNode);
4.17.0

API#

参数说明类型默认值版本
autoInsertSpaceInButton设置为 false 时,移除按钮中 2 个汉字之间的空格booleantrue
componentSize设置 sld-ui 组件大小small | middle | large-
csp设置 Content Security Policy 配置{ nonce: string }-
direction设置文本展示方向。ltr | rtlltr
dropdownMatchSelectWidth下拉菜单和选择器同宽。默认将设置 min-width,当值小于选择框宽度时会被忽略。false 时会关闭虚拟滚动boolean | number-
form设置 Form 组件的通用属性{ validateMessages?: ValidateMessages, requiredMark?: boolean | optional, colon?: boolean}-requiredMark: 4.8.0; colon: 4.18.0
getPopupContainer弹出框(Select, Tooltip, Menu 等等)渲染父节点,默认渲染到 body 上。function(triggerNode)() => document.body
getTargetContainer配置 Affix、Anchor 滚动监听容器。() => HTMLElement() => window
iconPrefixCls设置图标统一样式前缀。注意:需要配合 less 变量 @iconfont-css-prefix 使用stringanticon
input设置 Input 组件的通用属性{ autoComplete?: string }-
locale语言包配置,语言包可到 sld-ui/lib/locale 目录下寻找object-
pageHeader统一设置 PageHeader 的 ghost,参考 PageHeader{ ghost: boolean }true
prefixCls设置统一样式前缀。注意:需要配合 less 变量 使用stringsld
renderEmpty自定义组件空状态。参考 空状态function(componentName: string): ReactNode-
space设置 Space 的 size,参考 Space{ size: small | middle | large | number }-
virtual设置 false 时关闭虚拟滚动boolean-

ConfigProvider.config()#

设置 ModalMessageNotification rootPrefixCls。

ConfigProvider.config({
  prefixCls: 'sld', // 4.13.0+
  iconPrefixCls: 'anticon', // 4.17.0+
});

FAQ#

如何增加一个新的语言包?#

参考《增加语言包》

为什么我使用了 ConfigProvider locale,时间类组件的国际化还有问题?#

请检查是否正确设置了 moment 语言包,或者是否有两个版本的 moment 共存。

import 'moment/locale/zh-cn';
moment.locale('zh-cn');

配置 getPopupContainer 导致 Modal 报错?#

当如下全局设置 getPopupContainer 为触发节点的 parentNode 时,由于 Modal 的用法不存在 triggerNode,这样会导致 triggerNode is undefined 的报错,需要增加一个判断条件

 <ConfigProvider
-  getPopupContainer={triggerNode => triggerNode.parentNode}
+  getPopupContainer={node => {
+    if (node) {
+      return node.parentNode;
+    }
+    return document.body;
+  }}
 >
   <App />
 </ConfigProvider>