mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 12:39:49 +08:00
merge master
This commit is contained in:
commit
911867622e
76
.github/workflows/publish-to-github-package.yml
vendored
76
.github/workflows/publish-to-github-package.yml
vendored
@ -1,76 +0,0 @@
|
||||
name: Publish to github-package
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
compile:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@master
|
||||
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: install
|
||||
run: npm install
|
||||
|
||||
- name: compile
|
||||
run: npm run compile
|
||||
|
||||
- name: dist
|
||||
run: npm run dist
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: esm
|
||||
path: es
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: cjs
|
||||
path: lib
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: dist
|
||||
path: dist
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: package
|
||||
path: package.json
|
||||
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/download-artifact@master
|
||||
with:
|
||||
name: esm
|
||||
|
||||
- uses: actions/download-artifact@master
|
||||
with:
|
||||
name: cjs
|
||||
|
||||
- uses: actions/download-artifact@master
|
||||
with:
|
||||
name: dist
|
||||
|
||||
- uses: actions/download-artifact@master
|
||||
with:
|
||||
name: package
|
||||
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12.x'
|
||||
registry-url: 'https://npm.pkg.github.com'
|
||||
|
||||
- name: publish
|
||||
run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
14
.github/workflows/rebase.yml
vendored
Normal file
14
.github/workflows/rebase.yml
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
name: Automatic Rebase
|
||||
jobs:
|
||||
rebase:
|
||||
name: Rebase
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Automatic Rebase
|
||||
uses: cirrus-actions/rebase@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
@ -2,6 +2,7 @@ import * as React from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import toArray from 'rc-util/lib/Children/toArray';
|
||||
import omit from 'omit.js';
|
||||
import BreadcrumbItem from './BreadcrumbItem';
|
||||
import BreadcrumbSeparator from './BreadcrumbSeparator';
|
||||
import Menu from '../menu';
|
||||
@ -134,6 +135,7 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||
className,
|
||||
routes,
|
||||
children,
|
||||
...restProps
|
||||
} = this.props;
|
||||
const prefixCls = getPrefixCls('breadcrumb', customizePrefixCls);
|
||||
if (routes && routes.length > 0) {
|
||||
@ -159,7 +161,11 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||
});
|
||||
}
|
||||
return (
|
||||
<div className={classNames(className, prefixCls)} style={style}>
|
||||
<div
|
||||
className={classNames(className, prefixCls)}
|
||||
style={style}
|
||||
{...omit(restProps, ['itemRender', 'linkRender', 'nameRender', 'params'])}
|
||||
>
|
||||
{crumbs}
|
||||
</div>
|
||||
);
|
||||
|
@ -117,4 +117,14 @@ describe('Breadcrumb', () => {
|
||||
expect(linkRender).not.toHaveBeenCalled();
|
||||
expect(nameRender).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should support custom attribute', () => {
|
||||
const wrapper = render(
|
||||
<Breadcrumb data-custom="custom">
|
||||
<Breadcrumb.Item data-custom="custom-item">xxx</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>yyy</Breadcrumb.Item>
|
||||
</Breadcrumb>,
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -158,3 +158,36 @@ exports[`Breadcrumb should render a menu 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Breadcrumb should support custom attribute 1`] = `
|
||||
<div
|
||||
class="ant-breadcrumb"
|
||||
data-custom="custom"
|
||||
>
|
||||
<span>
|
||||
<span
|
||||
class="ant-breadcrumb-link"
|
||||
data-custom="custom-item"
|
||||
>
|
||||
xxx
|
||||
</span>
|
||||
<span
|
||||
class="ant-breadcrumb-separator"
|
||||
>
|
||||
/
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span
|
||||
class="ant-breadcrumb-link"
|
||||
>
|
||||
yyy
|
||||
</span>
|
||||
<span
|
||||
class="ant-breadcrumb-separator"
|
||||
>
|
||||
/
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
@ -22,37 +22,6 @@ const breadcrumbNameMap = {
|
||||
'/apps/2/detail': 'Detail',
|
||||
};
|
||||
|
||||
const Home = withRouter(props => {
|
||||
const { location, history } = props;
|
||||
const pathSnippets = location.pathname.split('/').filter(i => i);
|
||||
const extraBreadcrumbItems = pathSnippets.map((_, index) => {
|
||||
const url = `/${pathSnippets.slice(0, index + 1).join('/')}`;
|
||||
return (
|
||||
<Breadcrumb.Item key={url}>
|
||||
<Link to={url}>{breadcrumbNameMap[url]}</Link>
|
||||
</Breadcrumb.Item>
|
||||
);
|
||||
});
|
||||
const breadcrumbItems = [
|
||||
<Breadcrumb.Item key="home">
|
||||
<Link to="/">Home</Link>
|
||||
</Breadcrumb.Item>,
|
||||
].concat(extraBreadcrumbItems);
|
||||
return (
|
||||
<div className="demo">
|
||||
<div className="demo-nav">
|
||||
<a onClick={() => history.push('/')}>Home</a>
|
||||
<a onClick={() => history.push('/apps')}>Application List</a>
|
||||
</div>
|
||||
<Switch>
|
||||
<Route path="/apps" component={Apps} />
|
||||
<Route render={() => <span>Home Page</span>} />
|
||||
</Switch>
|
||||
<Breadcrumb>{breadcrumbItems}</Breadcrumb>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
describe('react router', () => {
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
@ -62,7 +31,37 @@ describe('react router', () => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
// https://github.com/airbnb/enzyme/issues/875
|
||||
it('react router 4', () => {
|
||||
(process.env.REACT === '15' ? it.skip : it)('react router 4', () => {
|
||||
const Home = withRouter(props => {
|
||||
const { location, history } = props;
|
||||
const pathSnippets = location.pathname.split('/').filter(i => i);
|
||||
const extraBreadcrumbItems = pathSnippets.map((_, index) => {
|
||||
const url = `/${pathSnippets.slice(0, index + 1).join('/')}`;
|
||||
return (
|
||||
<Breadcrumb.Item key={url}>
|
||||
<Link to={url}>{breadcrumbNameMap[url]}</Link>
|
||||
</Breadcrumb.Item>
|
||||
);
|
||||
});
|
||||
const breadcrumbItems = [
|
||||
<Breadcrumb.Item key="home">
|
||||
<Link to="/">Home</Link>
|
||||
</Breadcrumb.Item>,
|
||||
].concat(extraBreadcrumbItems);
|
||||
return (
|
||||
<div className="demo">
|
||||
<div className="demo-nav">
|
||||
<a onClick={() => history.push('/')}>Home</a>
|
||||
<a onClick={() => history.push('/apps')}>Application List</a>
|
||||
</div>
|
||||
<Switch>
|
||||
<Route path="/apps" component={Apps} />
|
||||
<Route render={() => <span>Home Page</span>} />
|
||||
</Switch>
|
||||
<Breadcrumb>{breadcrumbItems}</Breadcrumb>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
const wrapper = mount(
|
||||
<MemoryRouter initialEntries={['/']} initialIndex={0}>
|
||||
<Home />
|
||||
|
@ -130,6 +130,11 @@
|
||||
.button-size(@btn-height-lg; @btn-padding-lg; @btn-font-size-lg; 0);
|
||||
line-height: @btn-height-lg - 2px;
|
||||
}
|
||||
&-lg > .@{btnClassName}.@{btnClassName}-icon-only {
|
||||
.square(@btn-height-lg);
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
&-sm > .@{btnClassName},
|
||||
&-sm > span > .@{btnClassName} {
|
||||
.button-size(@btn-height-sm; @btn-padding-sm; @font-size-base; 0);
|
||||
@ -138,6 +143,11 @@
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
}
|
||||
&-sm > .@{btnClassName}.@{btnClassName}-icon-only {
|
||||
.square(@btn-height-sm);
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
// Base styles of buttons
|
||||
// --------------------------------------------------
|
||||
|
@ -10,7 +10,7 @@ import ResponsiveObserve, {
|
||||
responsiveArray,
|
||||
} from '../_util/responsiveObserve';
|
||||
|
||||
const RowAligns = tuple('top', 'middle', 'bottom');
|
||||
const RowAligns = tuple('top', 'middle', 'bottom', 'stretch');
|
||||
const RowJustify = tuple('start', 'end', 'center', 'space-around', 'space-between');
|
||||
export interface RowProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
gutter?: number | Partial<Record<Breakpoint, number>>;
|
||||
|
@ -212,7 +212,7 @@ exports[`renders ./components/input/demo/addon.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/input/demo/algin.md correctly 1`] = `
|
||||
exports[`renders ./components/input/demo/align.md correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-mentions"
|
||||
|
@ -18,7 +18,7 @@ subtitle: 页头
|
||||
| --- | --- | --- | --- | --- |
|
||||
| title | 自定义标题文字 | ReactNode | - | 3.14.0 |
|
||||
| subTitle | 自定义的二级标题文字 | ReactNode | - | 3.14.0 |
|
||||
| avatar | 标题栏旁的头像 | [avatar props](/components/avatar-cn/) | - | 3.22.0 |
|
||||
| avatar | 标题栏旁的头像 | [avatar props](/components/avatar/) | - | 3.22.0 |
|
||||
| backIcon | 自定义 back icon ,如果为 false 不渲染 back icon | ReactNode | `<ArrowLeft />` | 3.14.0 |
|
||||
| tags | title 旁的 tag 列表 | [Tag](https://ant.design/components/tag-cn/)[] \| [Tag](https://ant.design/components/tag-cn/) | - | 3.14.0 |
|
||||
| extra | 操作区,位于 title 行的行尾 | ReactNode | - | 3.14.0 |
|
||||
|
@ -526,7 +526,7 @@ exports[`renders ./components/select/demo/coordinate.md correctly 1`] = `
|
||||
exports[`renders ./components/select/demo/custom-dropdown-menu.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-single ant-select-show-arrow"
|
||||
style="width:120px"
|
||||
style="width:240px"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -548,9 +548,9 @@ exports[`renders ./components/select/demo/custom-dropdown-menu.md correctly 1`]
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-item"
|
||||
class="ant-select-selection-placeholder"
|
||||
>
|
||||
Lucy
|
||||
custom dropdown render
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
|
@ -5,7 +5,6 @@ import Select from '..';
|
||||
import Icon from '../../icon';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import { resetWarned } from '../../_util/warning';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@ -127,14 +126,4 @@ describe('Select', () => {
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
it('not warning if user use `inputValue`', () => {
|
||||
resetWarned();
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
mount(<Select inputValue="" />);
|
||||
expect(errorSpy).not.toHaveBeenCalled();
|
||||
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
@ -14,33 +14,52 @@ title:
|
||||
Customize the dropdown menu via `dropdownRender`.
|
||||
|
||||
```jsx
|
||||
import { Select, Divider, message } from 'antd';
|
||||
import { Select, Divider } from 'antd';
|
||||
import { Plus } from '@ant-design/icons';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
ReactDOM.render(
|
||||
<Select
|
||||
defaultValue="lucy"
|
||||
style={{ width: 120 }}
|
||||
dropdownRender={menu => (
|
||||
<div>
|
||||
{menu}
|
||||
<Divider style={{ margin: '4px 0' }} />
|
||||
<a
|
||||
style={{ padding: '8px', display: 'block', cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
message.info('Add an item!');
|
||||
}}
|
||||
>
|
||||
<Plus /> Add item
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<Option value="jack">Jack</Option>
|
||||
<Option value="lucy">Lucy</Option>
|
||||
</Select>,
|
||||
mountNode,
|
||||
);
|
||||
let index = 0;
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
items: ['jack', 'lucy'],
|
||||
};
|
||||
|
||||
addItem = () => {
|
||||
console.log('addItem');
|
||||
const { items } = this.state;
|
||||
this.setState({
|
||||
items: [...items, `New item ${index++}`],
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { items } = this.state;
|
||||
return (
|
||||
<Select
|
||||
style={{ width: 240 }}
|
||||
placeholder="custom dropdown render"
|
||||
dropdownRender={menu => (
|
||||
<div>
|
||||
{menu}
|
||||
<Divider style={{ margin: '4px 0' }} />
|
||||
<a
|
||||
style={{ padding: '8px', display: 'block', cursor: 'pointer' }}
|
||||
onClick={this.addItem}
|
||||
>
|
||||
<Plus /> Add item
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
{items.map(item => (
|
||||
<Option key={item}>{item}</Option>
|
||||
))}
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<App />, mountNode);
|
||||
```
|
||||
|
@ -46,7 +46,6 @@ Select component to select value from options.
|
||||
| optionFilterProp | Which prop value of option will be used for filter if filterOption is true | string | value | |
|
||||
| optionLabelProp | Which prop value of option will render as content of select. [Example](https://codesandbox.io/s/antd-reproduction-template-tk678) | string | `value` for `combobox`, `children` for other modes | |
|
||||
| placeholder | Placeholder of select | string\|ReactNode | - | |
|
||||
| searchValue | Search input value | string | - | 3.23.2 |
|
||||
| showArrow | Whether to show the drop-down arrow | boolean | true | 3.2.1 |
|
||||
| showSearch | Whether show search input in single mode. | boolean | false | |
|
||||
| size | Size of Select input. `default` `large` `small` | string | default | |
|
||||
@ -94,3 +93,9 @@ Select component to select value from options.
|
||||
| -------- | ----------- | --------------------- | ------- | ------- |
|
||||
| key | | string | - | |
|
||||
| label | Group label | string\|React.Element | - | |
|
||||
|
||||
## FAQ
|
||||
|
||||
### The dropdown is closed when click `dropdownRender` area?
|
||||
|
||||
See the [dropdownRender example](/components/select/#components-select-demo-custom-dropdown-menu).
|
||||
|
@ -47,7 +47,6 @@ title: Select
|
||||
| optionFilterProp | 搜索时过滤对应的 option 属性,如设置为 children 表示对内嵌内容进行搜索。[示例](https://codesandbox.io/s/antd-reproduction-template-tk678) | string | value | |
|
||||
| optionLabelProp | 回填到选择框的 Option 的属性值,默认是 Option 的子元素。比如在子元素需要高亮效果时,此值可以设为 `value`。 | string | `children` (combobox 模式下为 `value`) | |
|
||||
| placeholder | 选择框默认文字 | string | - | |
|
||||
| searchValue | 搜索框文本 | string | - | 3.23.2 |
|
||||
| showArrow | 是否显示下拉小箭头 | boolean | true | 3.2.1 |
|
||||
| showSearch | 使单选模式可搜索 | boolean | false | |
|
||||
| size | 选择框大小,可选 `large` `small` | string | default | |
|
||||
@ -97,3 +96,9 @@ title: Select
|
||||
| ----- | ---- | --------------------- | ------ | ---- |
|
||||
| key | | string | - | |
|
||||
| label | 组名 | string\|React.Element | 无 | |
|
||||
|
||||
## FAQ
|
||||
|
||||
### 点击 `dropdownRender` 里的内容浮层关闭怎么办?
|
||||
|
||||
看下 [dropdownRender 例子](/components/select-cn/#components-select-demo-custom-dropdown-menu) 里的说明。
|
||||
|
@ -356,3 +356,473 @@ exports[`Transfer should show sorted targetkey 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Transfer should support render value and label in item 1`] = `
|
||||
<Transfer
|
||||
dataSource={
|
||||
Array [
|
||||
Object {
|
||||
"key": "a",
|
||||
"title": "title",
|
||||
},
|
||||
]
|
||||
}
|
||||
locale={Object {}}
|
||||
render={[Function]}
|
||||
showSearch={false}
|
||||
>
|
||||
<LocaleReceiver
|
||||
componentName="Transfer"
|
||||
defaultLocale={
|
||||
Object {
|
||||
"itemUnit": "item",
|
||||
"itemsUnit": "items",
|
||||
"searchPlaceholder": "Search here",
|
||||
"titles": Array [
|
||||
"",
|
||||
"",
|
||||
],
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="ant-transfer"
|
||||
>
|
||||
<TransferList
|
||||
checkedKeys={Array []}
|
||||
dataSource={
|
||||
Array [
|
||||
Object {
|
||||
"key": "a",
|
||||
"title": "title",
|
||||
},
|
||||
]
|
||||
}
|
||||
direction="left"
|
||||
handleClear={[Function]}
|
||||
handleFilter={[Function]}
|
||||
itemUnit="item"
|
||||
itemsUnit="items"
|
||||
lazy={Object {}}
|
||||
notFoundContent={
|
||||
<Context.Consumer>
|
||||
[Function]
|
||||
</Context.Consumer>
|
||||
}
|
||||
onItemSelect={[Function]}
|
||||
onItemSelectAll={[Function]}
|
||||
onScroll={[Function]}
|
||||
prefixCls="ant-transfer-list"
|
||||
render={[Function]}
|
||||
searchPlaceholder="Search here"
|
||||
showSearch={false}
|
||||
titleText=""
|
||||
titles={
|
||||
Array [
|
||||
"",
|
||||
"",
|
||||
]
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="ant-transfer-list"
|
||||
>
|
||||
<div
|
||||
className="ant-transfer-list-header"
|
||||
>
|
||||
<Checkbox
|
||||
checked={false}
|
||||
indeterminate={false}
|
||||
onChange={[Function]}
|
||||
>
|
||||
<label
|
||||
className="ant-checkbox-wrapper"
|
||||
>
|
||||
<Checkbox
|
||||
checked={false}
|
||||
className=""
|
||||
defaultChecked={false}
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
prefixCls="ant-checkbox"
|
||||
style={Object {}}
|
||||
type="checkbox"
|
||||
>
|
||||
<span
|
||||
className="ant-checkbox"
|
||||
style={Object {}}
|
||||
>
|
||||
<input
|
||||
checked={false}
|
||||
className="ant-checkbox-input"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
className="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</Checkbox>
|
||||
</label>
|
||||
</Checkbox>
|
||||
<span
|
||||
className="ant-transfer-list-header-selected"
|
||||
>
|
||||
<span>
|
||||
1
|
||||
|
||||
item
|
||||
</span>
|
||||
<span
|
||||
className="ant-transfer-list-header-title"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="ant-transfer-list-body"
|
||||
>
|
||||
<ListBody
|
||||
dataSource={
|
||||
Array [
|
||||
Object {
|
||||
"key": "a",
|
||||
"title": "title",
|
||||
},
|
||||
]
|
||||
}
|
||||
direction="left"
|
||||
filteredItems={
|
||||
Array [
|
||||
Object {
|
||||
"key": "a",
|
||||
"title": "title",
|
||||
},
|
||||
]
|
||||
}
|
||||
filteredRenderItems={
|
||||
Array [
|
||||
Object {
|
||||
"item": Object {
|
||||
"key": "a",
|
||||
"title": "title",
|
||||
},
|
||||
"renderedEl": "label",
|
||||
"renderedText": "title value",
|
||||
},
|
||||
]
|
||||
}
|
||||
itemUnit="item"
|
||||
itemsUnit="items"
|
||||
lazy={Object {}}
|
||||
notFoundContent={
|
||||
<Context.Consumer>
|
||||
[Function]
|
||||
</Context.Consumer>
|
||||
}
|
||||
onItemSelect={[Function]}
|
||||
onItemSelectAll={[Function]}
|
||||
onScroll={[Function]}
|
||||
prefixCls="ant-transfer-list"
|
||||
render={[Function]}
|
||||
searchPlaceholder="Search here"
|
||||
selectedKeys={Array []}
|
||||
showSearch={false}
|
||||
titleText=""
|
||||
titles={
|
||||
Array [
|
||||
"",
|
||||
"",
|
||||
]
|
||||
}
|
||||
>
|
||||
<Animate
|
||||
animation={Object {}}
|
||||
className="ant-transfer-list-content"
|
||||
component="ul"
|
||||
componentProps={
|
||||
Object {
|
||||
"onScroll": [Function],
|
||||
}
|
||||
}
|
||||
onAppear={[Function]}
|
||||
onEnd={[Function]}
|
||||
onEnter={[Function]}
|
||||
onLeave={[Function]}
|
||||
transitionAppear={false}
|
||||
transitionEnter={true}
|
||||
transitionLeave={false}
|
||||
transitionName=""
|
||||
>
|
||||
<ul
|
||||
className="ant-transfer-list-content"
|
||||
onScroll={[Function]}
|
||||
>
|
||||
<AnimateChild
|
||||
animation={Object {}}
|
||||
key="a"
|
||||
transitionAppear={false}
|
||||
transitionEnter={true}
|
||||
transitionLeave={false}
|
||||
transitionName=""
|
||||
>
|
||||
<ListItem
|
||||
checked={false}
|
||||
item={
|
||||
Object {
|
||||
"key": "a",
|
||||
"title": "title",
|
||||
}
|
||||
}
|
||||
key="a"
|
||||
lazy={Object {}}
|
||||
onClick={[Function]}
|
||||
prefixCls="ant-transfer-list"
|
||||
renderedEl="label"
|
||||
renderedText="title value"
|
||||
>
|
||||
<LazyLoad
|
||||
debounce={false}
|
||||
elementType="div"
|
||||
height={32}
|
||||
offset={500}
|
||||
offsetBottom={0}
|
||||
offsetHorizontal={0}
|
||||
offsetLeft={0}
|
||||
offsetRight={0}
|
||||
offsetTop={0}
|
||||
offsetVertical={0}
|
||||
throttle={0}
|
||||
>
|
||||
<div
|
||||
className="LazyLoad"
|
||||
style={
|
||||
Object {
|
||||
"height": 32,
|
||||
"width": undefined,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</LazyLoad>
|
||||
</ListItem>
|
||||
</AnimateChild>
|
||||
</ul>
|
||||
</Animate>
|
||||
</ListBody>
|
||||
</div>
|
||||
</div>
|
||||
</TransferList>
|
||||
<Operation
|
||||
className="ant-transfer-operation"
|
||||
leftActive={false}
|
||||
moveToLeft={[Function]}
|
||||
moveToRight={[Function]}
|
||||
rightActive={false}
|
||||
>
|
||||
<div
|
||||
className="ant-transfer-operation"
|
||||
>
|
||||
<Button
|
||||
block={false}
|
||||
disabled={true}
|
||||
ghost={false}
|
||||
htmlType="button"
|
||||
icon="right"
|
||||
loading={false}
|
||||
onClick={[Function]}
|
||||
size="small"
|
||||
type="primary"
|
||||
>
|
||||
<Wave>
|
||||
<button
|
||||
className="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
right
|
||||
</button>
|
||||
</Wave>
|
||||
</Button>
|
||||
<Button
|
||||
block={false}
|
||||
disabled={true}
|
||||
ghost={false}
|
||||
htmlType="button"
|
||||
icon="left"
|
||||
loading={false}
|
||||
onClick={[Function]}
|
||||
size="small"
|
||||
type="primary"
|
||||
>
|
||||
<Wave>
|
||||
<button
|
||||
className="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
left
|
||||
</button>
|
||||
</Wave>
|
||||
</Button>
|
||||
</div>
|
||||
</Operation>
|
||||
<TransferList
|
||||
checkedKeys={Array []}
|
||||
dataSource={Array []}
|
||||
direction="right"
|
||||
handleClear={[Function]}
|
||||
handleFilter={[Function]}
|
||||
itemUnit="item"
|
||||
itemsUnit="items"
|
||||
lazy={Object {}}
|
||||
notFoundContent={
|
||||
<Context.Consumer>
|
||||
[Function]
|
||||
</Context.Consumer>
|
||||
}
|
||||
onItemSelect={[Function]}
|
||||
onItemSelectAll={[Function]}
|
||||
onScroll={[Function]}
|
||||
prefixCls="ant-transfer-list"
|
||||
render={[Function]}
|
||||
searchPlaceholder="Search here"
|
||||
showSearch={false}
|
||||
titleText=""
|
||||
titles={
|
||||
Array [
|
||||
"",
|
||||
"",
|
||||
]
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="ant-transfer-list"
|
||||
>
|
||||
<div
|
||||
className="ant-transfer-list-header"
|
||||
>
|
||||
<Checkbox
|
||||
checked={false}
|
||||
indeterminate={false}
|
||||
onChange={[Function]}
|
||||
>
|
||||
<label
|
||||
className="ant-checkbox-wrapper"
|
||||
>
|
||||
<Checkbox
|
||||
checked={false}
|
||||
className=""
|
||||
defaultChecked={false}
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
prefixCls="ant-checkbox"
|
||||
style={Object {}}
|
||||
type="checkbox"
|
||||
>
|
||||
<span
|
||||
className="ant-checkbox"
|
||||
style={Object {}}
|
||||
>
|
||||
<input
|
||||
checked={false}
|
||||
className="ant-checkbox-input"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
className="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</Checkbox>
|
||||
</label>
|
||||
</Checkbox>
|
||||
<span
|
||||
className="ant-transfer-list-header-selected"
|
||||
>
|
||||
<span>
|
||||
0
|
||||
|
||||
item
|
||||
</span>
|
||||
<span
|
||||
className="ant-transfer-list-header-title"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="ant-transfer-list-body"
|
||||
>
|
||||
<div
|
||||
className="ant-transfer-list-body-not-found"
|
||||
>
|
||||
<Empty
|
||||
className="ant-empty-small"
|
||||
image={<Simple />}
|
||||
>
|
||||
<LocaleReceiver
|
||||
componentName="Empty"
|
||||
>
|
||||
<div
|
||||
className="ant-empty ant-empty-normal ant-empty-small"
|
||||
>
|
||||
<div
|
||||
className="ant-empty-image"
|
||||
>
|
||||
<Simple>
|
||||
<svg
|
||||
height="41"
|
||||
viewBox="0 0 64 41"
|
||||
width="64"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g
|
||||
fill="none"
|
||||
fillRule="evenodd"
|
||||
transform="translate(0 1)"
|
||||
>
|
||||
<ellipse
|
||||
cx="32"
|
||||
cy="33"
|
||||
fill="#F5F5F5"
|
||||
rx="32"
|
||||
ry="7"
|
||||
/>
|
||||
<g
|
||||
fillRule="nonzero"
|
||||
stroke="#D9D9D9"
|
||||
>
|
||||
<path
|
||||
d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z"
|
||||
/>
|
||||
<path
|
||||
d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z"
|
||||
fill="#FAFAFA"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</Simple>
|
||||
</div>
|
||||
<p
|
||||
className="ant-empty-description"
|
||||
>
|
||||
No Data
|
||||
</p>
|
||||
</div>
|
||||
</LocaleReceiver>
|
||||
</Empty>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</TransferList>
|
||||
</div>
|
||||
</LocaleReceiver>
|
||||
</Transfer>
|
||||
`;
|
||||
|
@ -113,6 +113,24 @@ describe('Transfer', () => {
|
||||
expect(handleChange).toHaveBeenCalledWith(['a', 'b'], 'right', ['a']);
|
||||
});
|
||||
|
||||
it('should move selected keys to left list', () => {
|
||||
const handleChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Transfer
|
||||
{...listCommonProps}
|
||||
selectedKeys={['a']}
|
||||
targetKeys={['a']}
|
||||
onChange={handleChange}
|
||||
/>,
|
||||
);
|
||||
wrapper
|
||||
.find(TransferOperation)
|
||||
.find(Button)
|
||||
.at(1)
|
||||
.simulate('click'); // move selected keys to left list
|
||||
expect(handleChange).toHaveBeenCalledWith([], 'left', ['a']);
|
||||
});
|
||||
|
||||
it('should move selected keys expect disabled to corresponding list', () => {
|
||||
const handleChange = jest.fn();
|
||||
const wrapper = mount(<Transfer {...listDisabledProps} onChange={handleChange} />);
|
||||
@ -459,4 +477,44 @@ describe('Transfer', () => {
|
||||
expect(listTarget.prop('style')).toHaveProperty('backgroundColor', 'blue');
|
||||
expect(operation.prop('style')).toHaveProperty('backgroundColor', 'yellow');
|
||||
});
|
||||
|
||||
it('should support onScroll', () => {
|
||||
const onScroll = jest.fn();
|
||||
const component = mount(<Transfer {...listCommonProps} onScroll={onScroll} />);
|
||||
component
|
||||
.find('.ant-transfer-list')
|
||||
.at(0)
|
||||
.find('.ant-transfer-list-content')
|
||||
.at(0)
|
||||
.simulate('scroll');
|
||||
expect(onScroll).toHaveBeenLastCalledWith('left', expect.anything());
|
||||
component
|
||||
.find('.ant-transfer-list')
|
||||
.at(1)
|
||||
.find('.ant-transfer-list-content')
|
||||
.at(0)
|
||||
.simulate('scroll');
|
||||
expect(onScroll).toHaveBeenLastCalledWith('right', expect.anything());
|
||||
});
|
||||
|
||||
it('should support rowKey is function', () => {
|
||||
expect(() => {
|
||||
mount(<Transfer {...listCommonProps} rowKey={record => record.key} />);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should support render value and label in item', () => {
|
||||
const component = mount(
|
||||
<Transfer
|
||||
dataSource={[
|
||||
{
|
||||
key: 'a',
|
||||
title: 'title',
|
||||
},
|
||||
]}
|
||||
render={record => ({ value: `${record.title} value`, label: 'label' })}
|
||||
/>,
|
||||
);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -25,6 +25,7 @@ describe('Transfer.Search', () => {
|
||||
});
|
||||
|
||||
it('onSearch', () => {
|
||||
jest.useFakeTimers();
|
||||
const dataSource = [
|
||||
{
|
||||
key: 'a',
|
||||
@ -59,6 +60,7 @@ describe('Transfer.Search', () => {
|
||||
.find('.ant-input')
|
||||
.at(0)
|
||||
.simulate('change', { target: { value: 'a' } });
|
||||
jest.runAllTimers();
|
||||
expect(onSearch).toHaveBeenCalledWith('left', 'a');
|
||||
|
||||
onSearch.mockReset();
|
||||
@ -68,6 +70,7 @@ describe('Transfer.Search', () => {
|
||||
.at(0)
|
||||
.simulate('click');
|
||||
expect(onSearch).toHaveBeenCalledWith('left', '');
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('legacy props#onSearchChange doesnot work anymore', () => {
|
||||
@ -81,6 +84,7 @@ describe('Transfer.Search', () => {
|
||||
.find('.ant-input')
|
||||
.at(0)
|
||||
.simulate('change', { target: { value: 'a' } });
|
||||
jest.runAllTimers();
|
||||
|
||||
expect(errorSpy.mock.calls.length).toBe(0);
|
||||
expect(onSearchChange).not.toHaveBeenCalled();
|
||||
|
@ -0,0 +1,93 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TreeSelect TreeSelect Custom Icons should support customized icons 1`] = `
|
||||
<span
|
||||
aria-haspopup="listbox"
|
||||
class="ant-select ant-select-enabled ant-select-allow-clear"
|
||||
role="combobox"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection ant-select-selection--multiple"
|
||||
>
|
||||
<ul
|
||||
class="ant-select-selection__rendered"
|
||||
role="menubar"
|
||||
>
|
||||
<li
|
||||
class="ant-select-selection__choice"
|
||||
role="menuitem"
|
||||
style="user-select: none;"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection__choice__remove"
|
||||
>
|
||||
<span>
|
||||
remove
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection__choice__content"
|
||||
>
|
||||
leaf1
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
class="ant-select-selection__choice"
|
||||
role="menuitem"
|
||||
style="user-select: none;"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection__choice__remove"
|
||||
>
|
||||
<span>
|
||||
remove
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection__choice__content"
|
||||
>
|
||||
leaf2
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
class="ant-select-search ant-select-search--inline"
|
||||
>
|
||||
<span
|
||||
class="ant-select-search__field__wrap"
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
aria-label="filter select"
|
||||
aria-multiline="false"
|
||||
class="ant-select-search__field"
|
||||
style="width: 0px;"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-select-search__field__mirror"
|
||||
>
|
||||
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<span
|
||||
class="ant-select-selection__clear"
|
||||
>
|
||||
<span>
|
||||
clear
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-search__field__placeholder"
|
||||
style="display: none;"
|
||||
>
|
||||
Please select
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import TreeSelect from '..';
|
||||
import TreeSelect, { TreeNode } from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
|
||||
@ -17,4 +17,30 @@ describe('TreeSelect', () => {
|
||||
expect(multiple.find('.ant-select-search__field').length).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('TreeSelect Custom Icons', () => {
|
||||
it('should support customized icons', () => {
|
||||
const wrapper = mount(
|
||||
<TreeSelect
|
||||
showSearch
|
||||
clearIcon={<span>clear</span>}
|
||||
removeIcon={<span>remove</span>}
|
||||
value={['leaf1', 'leaf2']}
|
||||
placeholder="Please select"
|
||||
multiple
|
||||
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>
|
||||
</TreeSelect>,
|
||||
);
|
||||
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -7,6 +7,7 @@ import { Loading, CaretDown, Down, Close, CloseCircleFilled } from '@ant-design/
|
||||
import { TreeSelectProps, TreeNodeValue } from './interface';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import warning from '../_util/warning';
|
||||
import { cloneElement } from '../_util/reactNode';
|
||||
import { AntTreeNodeProps } from '../tree';
|
||||
|
||||
export { TreeNode, TreeSelectProps } from './interface';
|
||||
@ -75,6 +76,8 @@ export default class TreeSelect<T extends TreeNodeValue> extends React.Component
|
||||
dropdownStyle,
|
||||
dropdownClassName,
|
||||
suffixIcon,
|
||||
removeIcon,
|
||||
clearIcon,
|
||||
getPopupContainer,
|
||||
...restProps
|
||||
} = this.props;
|
||||
@ -100,14 +103,23 @@ export default class TreeSelect<T extends TreeNodeValue> extends React.Component
|
||||
checkable = <span className={`${prefixCls}-tree-checkbox-inner`} />;
|
||||
}
|
||||
|
||||
const inputIcon = (suffixIcon &&
|
||||
(React.isValidElement<{ className?: string }>(suffixIcon)
|
||||
? React.cloneElement(suffixIcon)
|
||||
: suffixIcon)) || <Down className={`${prefixCls}-arrow-icon`} />;
|
||||
const inputIcon = suffixIcon ? (
|
||||
cloneElement(suffixIcon)
|
||||
) : (
|
||||
<Down className={`${prefixCls}-arrow-icon`} />
|
||||
);
|
||||
|
||||
const removeIcon = <Close className={`${prefixCls}-remove-icon`} />;
|
||||
const finalRemoveIcon = removeIcon ? (
|
||||
cloneElement(removeIcon)
|
||||
) : (
|
||||
<Close className={`${prefixCls}-remove-icon`} />
|
||||
);
|
||||
|
||||
const clearIcon = <CloseCircleFilled className={`${prefixCls}-clear-icon`} />;
|
||||
const finalClearIcon = clearIcon ? (
|
||||
cloneElement(clearIcon)
|
||||
) : (
|
||||
<CloseCircleFilled className={`${prefixCls}-clear-icon`} />
|
||||
);
|
||||
|
||||
return (
|
||||
<RcTreeSelect
|
||||
@ -115,8 +127,8 @@ export default class TreeSelect<T extends TreeNodeValue> extends React.Component
|
||||
this.renderSwitcherIcon(prefixCls, nodeProps)
|
||||
}
|
||||
inputIcon={inputIcon}
|
||||
removeIcon={removeIcon}
|
||||
clearIcon={clearIcon}
|
||||
removeIcon={finalRemoveIcon}
|
||||
clearIcon={finalClearIcon}
|
||||
{...rest}
|
||||
showSearch={showSearch}
|
||||
getPopupContainer={getPopupContainer || getContextPopupContainer}
|
||||
|
@ -50,6 +50,8 @@ export interface TreeSelectProps<T extends TreeNodeValue> extends Omit<SelectPro
|
||||
searchValue?: string;
|
||||
showCheckedStrategy?: 'SHOW_ALL' | 'SHOW_PARENT' | 'SHOW_CHILD';
|
||||
suffixIcon?: React.ReactNode;
|
||||
removeIcon?: React.ReactNode;
|
||||
clearIcon?: React.ReactNode;
|
||||
treeCheckable?: boolean | React.ReactNode;
|
||||
treeCheckStrictly?: boolean;
|
||||
treeData?: Array<TreeNode>;
|
||||
|
@ -196,24 +196,26 @@ export default class Tree extends React.Component<TreeProps, any> {
|
||||
if (loading) {
|
||||
return <Loading className={`${prefixCls}-switcher-loading-icon`} />;
|
||||
}
|
||||
if (showLine) {
|
||||
if (isLeaf) {
|
||||
if (isLeaf) {
|
||||
if (showLine) {
|
||||
return <File className={`${prefixCls}-switcher-line-icon`} />;
|
||||
}
|
||||
return React.createElement(expanded ? MinusSquare : PlusSquare, {
|
||||
className: `${prefixCls}-switcher-line-icon`,
|
||||
});
|
||||
}
|
||||
const switcherCls = `${prefixCls}-switcher-icon`;
|
||||
if (isLeaf) {
|
||||
return null;
|
||||
}
|
||||
const switcherCls = `${prefixCls}-switcher-icon`;
|
||||
if (switcherIcon) {
|
||||
const switcherOriginCls = switcherIcon.props.className || '';
|
||||
return React.cloneElement(switcherIcon, {
|
||||
className: classNames(switcherOriginCls, switcherCls),
|
||||
});
|
||||
}
|
||||
if (showLine) {
|
||||
return expanded ? (
|
||||
<MinusSquare className={`${prefixCls}-switcher-line-icon`} />
|
||||
) : (
|
||||
<PlusSquare className={`${prefixCls}-switcher-line-icon`} />
|
||||
);
|
||||
}
|
||||
return <CaretDownFilled className={switcherCls} />;
|
||||
};
|
||||
|
||||
|
@ -2285,3 +2285,267 @@ exports[`renders ./components/tree/demo/search.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/tree/demo/switcher-icon.md correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
role="tree"
|
||||
>
|
||||
<input
|
||||
style="width:0;height:0;display:flex;overflow:hidden;opacity:0;border:0;padding:0;margin:0"
|
||||
tabindex="0"
|
||||
value=""
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-tree-list ant-tree ant-tree-icon-hide ant-tree-show-line"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-tree-list-holder-inner"
|
||||
style="display:flex;flex-direction:column"
|
||||
>
|
||||
<div
|
||||
class="ant-tree-treenode ant-tree-treenode-switcher-open"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-switcher ant-tree-switcher_open"
|
||||
/>
|
||||
<span
|
||||
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"
|
||||
title="parent 1"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-title"
|
||||
>
|
||||
parent 1
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tree-treenode ant-tree-treenode-switcher-open"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="ant-tree-indent"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-indent-unit ant-tree-indent-unit-start"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-tree-switcher ant-tree-switcher_open"
|
||||
/>
|
||||
<span
|
||||
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"
|
||||
title="parent 1-0"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-title"
|
||||
>
|
||||
parent 1-0
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tree-treenode ant-tree-treenode-switcher-close"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="ant-tree-indent"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-indent-unit ant-tree-indent-unit-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-tree-indent-unit ant-tree-indent-unit-start"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-tree-switcher ant-tree-switcher-noop"
|
||||
>
|
||||
<span
|
||||
aria-label="file"
|
||||
class="anticon anticon-file ant-tree-switcher-line-icon"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="file"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"
|
||||
title="leaf"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-title"
|
||||
>
|
||||
leaf
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tree-treenode ant-tree-treenode-switcher-close"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="ant-tree-indent"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-indent-unit ant-tree-indent-unit-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-tree-indent-unit"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-tree-switcher ant-tree-switcher-noop"
|
||||
>
|
||||
<span
|
||||
aria-label="file"
|
||||
class="anticon anticon-file ant-tree-switcher-line-icon"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="file"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"
|
||||
title="leaf"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-title"
|
||||
>
|
||||
leaf
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tree-treenode ant-tree-treenode-switcher-close"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="ant-tree-indent"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-indent-unit ant-tree-indent-unit-start"
|
||||
/>
|
||||
<span
|
||||
class="ant-tree-indent-unit ant-tree-indent-unit-end"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-tree-switcher ant-tree-switcher-noop"
|
||||
>
|
||||
<span
|
||||
aria-label="file"
|
||||
class="anticon anticon-file ant-tree-switcher-line-icon"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="file"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"
|
||||
title="leaf"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-title"
|
||||
>
|
||||
leaf
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tree-treenode ant-tree-treenode-switcher-close"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="ant-tree-indent"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-indent-unit"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-tree-switcher ant-tree-switcher_close"
|
||||
/>
|
||||
<span
|
||||
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"
|
||||
title="parent 1-1"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-title"
|
||||
>
|
||||
parent 1-1
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tree-treenode ant-tree-treenode-switcher-close"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="ant-tree-indent"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-indent-unit ant-tree-indent-unit-end"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-tree-switcher ant-tree-switcher_close"
|
||||
/>
|
||||
<span
|
||||
class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"
|
||||
title="parent 1-2"
|
||||
>
|
||||
<span
|
||||
class="ant-tree-title"
|
||||
>
|
||||
parent 1-2
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
54
components/tree/demo/switcher-icon.md
Normal file
54
components/tree/demo/switcher-icon.md
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: 自定义展开/折叠图标
|
||||
en-US: Customize collapse/expand icon
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
自定义展开/折叠图标。
|
||||
|
||||
## en-US
|
||||
|
||||
customize collapse/expand icon of tree node
|
||||
|
||||
```jsx
|
||||
import { Tree, Icon } from 'antd';
|
||||
|
||||
const { TreeNode } = Tree;
|
||||
|
||||
class Demo extends React.Component {
|
||||
onSelect = (selectedKeys, info) => {
|
||||
console.log('selected', selectedKeys, info);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Tree
|
||||
showLine
|
||||
switcherIcon={<Icon type="down" />}
|
||||
defaultExpandedKeys={['0-0-0']}
|
||||
onSelect={this.onSelect}
|
||||
>
|
||||
<TreeNode title="parent 1" key="0-0">
|
||||
<TreeNode title="parent 1-0" key="0-0-0">
|
||||
<TreeNode title="leaf" key="0-0-0-0" />
|
||||
<TreeNode title="leaf" key="0-0-0-1" />
|
||||
<TreeNode title="leaf" key="0-0-0-2" />
|
||||
</TreeNode>
|
||||
<TreeNode title="parent 1-1" key="0-0-1">
|
||||
<TreeNode title="leaf" key="0-0-1-0" />
|
||||
</TreeNode>
|
||||
<TreeNode title="parent 1-2" key="0-0-2">
|
||||
<TreeNode title="leaf" key="0-0-2-0" />
|
||||
<TreeNode title="leaf" key="0-0-2-1" />
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</Tree>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
```
|
@ -161,6 +161,8 @@
|
||||
|
||||
> span {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix}-loading,
|
||||
@ -378,6 +380,7 @@
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.@{upload-item}-name {
|
||||
|
@ -7,6 +7,7 @@ title: Third-Party Libraries
|
||||
|
||||
| Category | Recommended Components |
|
||||
| --- | --- |
|
||||
| Visualization and charts | [🔥 AntV 数据可视化解决方案](https://antv.alipay.com) [BizCharts](https://github.com/alibaba/BizCharts) [recharts](https://github.com/recharts/recharts/) [viser](https://viserjs.github.io/) |
|
||||
| Router | [react-router](https://github.com/ReactTraining/react-router) |
|
||||
| Layout | [@rebass/grid](https://github.com/rebassjs/grid) [react-blocks](http://whoisandy.github.io/react-blocks/) [react-flexbox-grid](https://github.com/roylee0704/react-flexbox-grid) |
|
||||
| Drag and drop | [react-beautiful-dnd](https://github.com/atlassian/react-beautiful-dnd/) [react-dnd](https://github.com/gaearon/react-dnd) [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc) |
|
||||
@ -19,7 +20,6 @@ title: Third-Party Libraries
|
||||
| Document head manager | [react-helmet](https://github.com/nfl/react-helmet) [react-document-title](https://github.com/gaearon/react-document-title) |
|
||||
| Icons | [react-fa](https://github.com/andreypopp/react-fa) [react-icons](https://github.com/gorangajic/react-icons) |
|
||||
| QR Code | [qrcode.react](https://github.com/zpao/qrcode.react) |
|
||||
| Charts | [BizCharts](https://github.com/alibaba/BizCharts) [recharts](https://github.com/recharts/recharts/) [victory](https://github.com/FormidableLabs/victory) |
|
||||
| Visual Graph Editor | [GGEditor](https://github.com/gaoli/GGEditor) |
|
||||
| Top Progress Bar | [nprogress](https://github.com/rstacruz/nprogress) |
|
||||
| i18n | [react-intl](https://github.com/yahoo/react-intl) |
|
||||
@ -27,6 +27,7 @@ title: Third-Party Libraries
|
||||
| Markdown renderer | [react-markdown](http://rexxars.github.io/react-markdown/) |
|
||||
| Infinite Scroll | [react-virtualized](https://github.com/bvaughn/react-virtualized) [antd-table-infinity](https://github.com/Leonard-Li777/antd-table-infinity) |
|
||||
| Map | [react-google-maps](https://github.com/tomchentw/react-google-maps) [google-map-react](https://github.com/istarkov/google-map-react) [react-amap](https://github.com/ElemeFE/react-amap) |
|
||||
| Video | [react-player](https://github.com/CookPete/react-player) [video-react](https://github.com/video-react/video-react) [video.js](http://docs.videojs.com/tutorial-react.html) |
|
||||
| Context Menu | [react-contextmenu](https://github.com/vkbansal/react-contextmenu/) [react-contexify](https://github.com/fkhadra/react-contexify) |
|
||||
| Emoji | [emoji-mart](https://github.com/missive/emoji-mart) |
|
||||
| Split View | [react-split-pane](https://github.com/tomkp/react-split-pane) |
|
||||
|
@ -7,6 +7,7 @@ title: 社区精选组件
|
||||
|
||||
| 类型 | 推荐组件 |
|
||||
| --- | --- |
|
||||
| 可视化图表 | [🔥 AntV 数据可视化解决方案](https://antv.alipay.com) [BizCharts](https://github.com/alibaba/BizCharts) [recharts](https://github.com/recharts/recharts/) [viser](https://viserjs.github.io/) |
|
||||
| 路由 | [react-router](https://github.com/ReactTraining/react-router) |
|
||||
| 布局 | [@rebass/grid](https://github.com/rebassjs/grid) [react-blocks](https://github.com/whoisandy/react-blocks) [react-flexbox-grid](https://github.com/roylee0704/react-flexbox-grid) |
|
||||
| 拖拽 | [react-beautiful-dnd](https://github.com/atlassian/react-beautiful-dnd/) [react-dnd](https://github.com/gaearon/react-dnd) [react-sortable-hoc](https://github.com/clauderic/react-sortable-hoc) |
|
||||
@ -19,7 +20,6 @@ title: 社区精选组件
|
||||
| 页面 meta 属性 | [react-helmet](https://github.com/nfl/react-helmet) [react-document-title](https://github.com/gaearon/react-document-title) |
|
||||
| 图标 | [react-fa](https://github.com/andreypopp/react-fa) [react-icons](https://github.com/gorangajic/react-icons) |
|
||||
| 二维码 | [qrcode.react](https://github.com/zpao/qrcode.react) |
|
||||
| 可视化图表 | [BizCharts](https://github.com/alibaba/BizCharts) [recharts](https://github.com/recharts/recharts/) [victory](https://github.com/FormidableLabs/victory) |
|
||||
| 可视化图编辑器 | [GGEditor](https://github.com/gaoli/GGEditor) |
|
||||
| 顶部进度条 | [nprogress](https://github.com/rstacruz/nprogress) |
|
||||
| 应用国际化 | [react-intl](https://github.com/yahoo/react-intl) |
|
||||
@ -27,6 +27,7 @@ title: 社区精选组件
|
||||
| Markdown 渲染 | [react-markdown](http://rexxars.github.io/react-markdown/) |
|
||||
| 无限滚动 | [react-virtualized](https://github.com/bvaughn/react-virtualized) [antd-table-infinity](https://github.com/Leonard-Li777/antd-table-infinity) |
|
||||
| 地图 | [react-google-maps](https://github.com/tomchentw/react-google-maps) [google-map-react](https://github.com/istarkov/google-map-react) [react-amap 高德](https://github.com/ElemeFE/react-amap) |
|
||||
| 视频播放 | [react-player](https://github.com/CookPete/react-player) [video-react](https://github.com/video-react/video-react) [video.js](http://docs.videojs.com/tutorial-react.html) |
|
||||
| 右键菜单 | [react-contextmenu](https://github.com/vkbansal/react-contextmenu/) [react-contexify](https://github.com/fkhadra/react-contexify) |
|
||||
| Emoji | [emoji-mart](https://github.com/missive/emoji-mart) |
|
||||
| 分割面板 | [react-split-pane](https://github.com/tomkp/react-split-pane) |
|
||||
|
@ -23,10 +23,10 @@ As a part of nature, it will have deep influence on user behavior, and designers
|
||||
- The visual system plays the most important role in human perception and cognition. By refining the objective laws in nature and applying it to the interface design, a more layered product experience is created. In addition, hearing systems or tactile systems could be added in future to bring more dimensions and more real product experience. See visual language.
|
||||
- In the real product design, a series of methods such as behavior analysis, artificial intelligence and sensors could be applied to assist users to make effective decisions and reduce extra operations of users, so as to save users' mental and physical resources and make human-computer interaction more natural.
|
||||
|
||||
## Determinacy
|
||||
## Certainty
|
||||
|
||||
<div>
|
||||
<img src="https://gw.alipayobjects.com/zos/rmsportal/ZxgRAMzXNrxHTcvMLchq.png" alt="Determine" />
|
||||
<img src="https://gw.alipayobjects.com/zos/rmsportal/ZxgRAMzXNrxHTcvMLchq.png" alt="Certainty" />
|
||||
</div>
|
||||
|
||||
The designers needs to make better design decisions and create a high-definition and low-entropy atmosphere for developer team. Meanwhile, different designers could produce the same design output which fit business needs based on the same understanding of business requirements and design system.
|
||||
|
@ -150,9 +150,12 @@
|
||||
"@sentry/browser": "^5.4.0",
|
||||
"@types/classnames": "^2.2.8",
|
||||
"@types/gtag.js": "^0.0.3",
|
||||
"@types/lodash": "^4.14.139",
|
||||
"@types/prop-types": "^15.7.1",
|
||||
"@types/react": "~16.9.1",
|
||||
"@types/raf": "^3.4.0",
|
||||
"@types/react": "^16.9.0",
|
||||
"@types/react-dom": "^16.8.4",
|
||||
"@types/shallowequal": "^1.1.1",
|
||||
"@types/warning": "^3.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^2.0.0",
|
||||
"@typescript-eslint/parser": "^2.0.0",
|
||||
@ -204,7 +207,7 @@
|
||||
"prettier": "^1.17.1",
|
||||
"pretty-quick": "^1.11.0",
|
||||
"querystring": "^0.2.0",
|
||||
"rc-footer": "^0.4.0",
|
||||
"rc-footer": "^0.5.0",
|
||||
"rc-queue-anim": "^1.6.12",
|
||||
"rc-scroll-anim": "^2.5.8",
|
||||
"rc-tween-one": "^2.4.1",
|
||||
@ -230,7 +233,7 @@
|
||||
"scrollama": "^2.0.0",
|
||||
"simple-git": "^1.113.0",
|
||||
"stylelint": "^11.0.0",
|
||||
"stylelint-config-prettier": "^5.2.0",
|
||||
"stylelint-config-prettier": "^6.0.0",
|
||||
"stylelint-config-rational-order": "^0.1.2",
|
||||
"stylelint-config-standard": "^19.0.0",
|
||||
"stylelint-declaration-block-no-ignored-properties": "^2.1.0",
|
||||
|
@ -111,7 +111,7 @@
|
||||
padding: 0 24px;
|
||||
font-size: 16px;
|
||||
font-family: Avenir, @font-family, sans-serif;
|
||||
line-height: 38px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
border: 1px solid #2f54eb;
|
||||
|
26
typings/custom-typings.d.ts
vendored
26
typings/custom-typings.d.ts
vendored
@ -4,7 +4,7 @@ declare module 'rc-calendar*';
|
||||
|
||||
declare module 'rc-time-picker*';
|
||||
|
||||
declare module 'rc-pagination*';
|
||||
declare module 'rc-pagination/*';
|
||||
|
||||
declare module 'omit.js';
|
||||
|
||||
@ -12,14 +12,10 @@ declare module 'rc-animate*';
|
||||
|
||||
declare module 'rc-util*';
|
||||
|
||||
declare module 'shallowequal';
|
||||
|
||||
declare module 'css-animation*';
|
||||
|
||||
declare module 'rc-cascader';
|
||||
|
||||
declare module 'array-tree-filter';
|
||||
|
||||
declare module 'rc-checkbox';
|
||||
|
||||
declare module 'rc-radio';
|
||||
@ -45,7 +41,7 @@ declare module 'rc-calendar';
|
||||
|
||||
declare module 'rc-input-number';
|
||||
|
||||
declare module 'rc-pagination';
|
||||
declare module 'rc-collapse';
|
||||
|
||||
declare module 'rc-notification';
|
||||
|
||||
@ -73,8 +69,6 @@ declare module 'rc-tree-select';
|
||||
|
||||
declare module 'rc-upload';
|
||||
|
||||
declare module 'rc-collapse';
|
||||
|
||||
declare module 'rc-form*';
|
||||
|
||||
declare module 'react-lazy-load';
|
||||
@ -89,22 +83,6 @@ declare module '*.json' {
|
||||
export default value;
|
||||
}
|
||||
|
||||
declare module 'lodash/isEqual';
|
||||
|
||||
declare module 'lodash/debounce';
|
||||
|
||||
declare module 'lodash/padStart';
|
||||
|
||||
declare module 'lodash/padEnd';
|
||||
|
||||
declare module 'lodash/repeat';
|
||||
|
||||
declare module 'lodash/uniqBy';
|
||||
|
||||
declare module 'lodash/findIndex';
|
||||
|
||||
declare module 'raf';
|
||||
|
||||
declare module 'react-lifecycles-compat';
|
||||
|
||||
declare module 'react-copy-to-clipboard';
|
||||
|
Loading…
Reference in New Issue
Block a user