mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-08 01:53:34 +08:00
support prettier
This commit is contained in:
parent
16c3a9453e
commit
dca9715186
27
.eslintrc.js
27
.eslintrc.js
@ -1,5 +1,5 @@
|
|||||||
const eslintrc = {
|
const eslintrc = {
|
||||||
extends: ['eslint-config-airbnb'],
|
extends: ['airbnb', 'prettier'],
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
node: true,
|
node: true,
|
||||||
@ -8,18 +8,27 @@ const eslintrc = {
|
|||||||
es6: true,
|
es6: true,
|
||||||
},
|
},
|
||||||
parser: 'babel-eslint',
|
parser: 'babel-eslint',
|
||||||
plugins: [
|
plugins: ['markdown', 'react', 'babel'],
|
||||||
'markdown',
|
|
||||||
'react',
|
|
||||||
'babel',
|
|
||||||
],
|
|
||||||
rules: {
|
rules: {
|
||||||
'react/jsx-one-expression-per-line': 0,
|
'react/jsx-one-expression-per-line': 0,
|
||||||
'react/prop-types': 0,
|
'react/prop-types': 0,
|
||||||
'react/forbid-prop-types': 0,
|
'react/forbid-prop-types': 0,
|
||||||
'import/no-extraneous-dependencies': ['error', {
|
'react/jsx-indent': 0,
|
||||||
devDependencies: ['site/**', 'tests/**', 'scripts/**', '**/*.test.js', '**/__tests__/*', '*.config.js', '**/*.md'],
|
'react/jsx-wrap-multilines': ['error', { declaration: false, assignment: false }],
|
||||||
}],
|
'import/no-extraneous-dependencies': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
devDependencies: [
|
||||||
|
'site/**',
|
||||||
|
'tests/**',
|
||||||
|
'scripts/**',
|
||||||
|
'**/*.test.js',
|
||||||
|
'**/__tests__/*',
|
||||||
|
'*.config.js',
|
||||||
|
'**/*.md',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx', '.md'] }],
|
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx', '.md'] }],
|
||||||
'jsx-a11y/no-static-element-interactions': 0,
|
'jsx-a11y/no-static-element-interactions': 0,
|
||||||
'jsx-a11y/anchor-has-content': 0,
|
'jsx-a11y/anchor-has-content': 0,
|
||||||
|
7
.prettierignore
Normal file
7
.prettierignore
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
**/*.md
|
||||||
|
**/*.svg
|
||||||
|
**/*.ejs
|
||||||
|
**/*.html
|
||||||
|
package.json
|
||||||
|
.umi
|
||||||
|
.umi-production
|
19
.prettierrc
Normal file
19
.prettierrc
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"printWidth": 100,
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ".prettierrc",
|
||||||
|
"options": {
|
||||||
|
"parser": "json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ".stylelintrc",
|
||||||
|
"options": {
|
||||||
|
"parser": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"extends": "stylelint-config-standard",
|
"extends": ["stylelint-config-standard", "stylelint-config-prettier"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"comment-empty-line-before": null,
|
"comment-empty-line-before": null,
|
||||||
"declaration-empty-line-before": null,
|
"declaration-empty-line-before": null,
|
||||||
|
@ -14,7 +14,7 @@ describe('antd', () => {
|
|||||||
|
|
||||||
it('should hint when import all components in dev mode', () => {
|
it('should hint when import all components in dev mode', () => {
|
||||||
expect(warnSpy).toBeCalledWith(
|
expect(warnSpy).toBeCalledWith(
|
||||||
'You are using a whole package of antd, please use https://www.npmjs.com/package/babel-plugin-import to reduce app bundle size.'
|
'You are using a whole package of antd, please use https://www.npmjs.com/package/babel-plugin-import to reduce app bundle size.',
|
||||||
);
|
);
|
||||||
warnSpy.mockRestore();
|
warnSpy.mockRestore();
|
||||||
});
|
});
|
||||||
|
@ -88,7 +88,7 @@ describe('Test utils function', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('delayRaf', (done) => {
|
it('delayRaf', done => {
|
||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
|
|
||||||
let bamboo = false;
|
let bamboo = false;
|
||||||
@ -118,9 +118,13 @@ describe('Test utils function', () => {
|
|||||||
|
|
||||||
it('triggerEvent', () => {
|
it('triggerEvent', () => {
|
||||||
const button = document.createElement('button');
|
const button = document.createElement('button');
|
||||||
button.addEventListener('click', () => {
|
button.addEventListener(
|
||||||
|
'click',
|
||||||
|
() => {
|
||||||
button.style.width = '100px';
|
button.style.width = '100px';
|
||||||
}, true);
|
},
|
||||||
|
true,
|
||||||
|
);
|
||||||
triggerEvent(button, 'click');
|
triggerEvent(button, 'click');
|
||||||
expect(button.style.width).toBe('100px');
|
expect(button.style.width).toBe('100px');
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
export default function isFlexSupported() {
|
export default function isFlexSupported() {
|
||||||
if (typeof window !== 'undefined' && window.document && window.document.documentElement) {
|
if (typeof window !== 'undefined' && window.document && window.document.documentElement) {
|
||||||
const { documentElement } = window.document;
|
const { documentElement } = window.document;
|
||||||
return 'flex' in documentElement.style ||
|
return (
|
||||||
|
'flex' in documentElement.style ||
|
||||||
'webkitFlex' in documentElement.style ||
|
'webkitFlex' in documentElement.style ||
|
||||||
'Flex' in documentElement.style ||
|
'Flex' in documentElement.style ||
|
||||||
'msFlex' in documentElement.style;
|
'msFlex' in documentElement.style
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import raf from 'raf';
|
import raf from 'raf';
|
||||||
|
|
||||||
interface RafMap {
|
interface RafMap {
|
||||||
[id: number]: number,
|
[id: number]: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
let id: number = 0;
|
let id: number = 0;
|
||||||
@ -31,4 +31,4 @@ export default function wrapperRaf(callback: () => void, delayFrames: number = 1
|
|||||||
wrapperRaf.cancel = function(id: number) {
|
wrapperRaf.cancel = function(id: number) {
|
||||||
raf.cancel(ids[id]);
|
raf.cancel(ids[id]);
|
||||||
delete ids[id];
|
delete ids[id];
|
||||||
}
|
};
|
||||||
|
@ -22,7 +22,7 @@ export default class Wave extends React.Component<{insertExtraNode?: boolean}> {
|
|||||||
private clickWaveTimeoutId: number;
|
private clickWaveTimeoutId: number;
|
||||||
private animationStartId: number;
|
private animationStartId: number;
|
||||||
private animationStart: boolean = false;
|
private animationStart: boolean = false;
|
||||||
private destroy: boolean = false
|
private destroy: boolean = false;
|
||||||
|
|
||||||
isNotGrey(color: string) {
|
isNotGrey(color: string) {
|
||||||
const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\.\d]*)?\)/);
|
const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\.\d]*)?\)/);
|
||||||
@ -45,15 +45,16 @@ export default class Wave extends React.Component<{insertExtraNode?: boolean}> {
|
|||||||
node.setAttribute(attributeName, 'true');
|
node.setAttribute(attributeName, 'true');
|
||||||
// Not white or transparnt or grey
|
// Not white or transparnt or grey
|
||||||
styleForPesudo = styleForPesudo || document.createElement('style');
|
styleForPesudo = styleForPesudo || document.createElement('style');
|
||||||
if (waveColor &&
|
if (
|
||||||
|
waveColor &&
|
||||||
waveColor !== '#ffffff' &&
|
waveColor !== '#ffffff' &&
|
||||||
waveColor !== 'rgb(255, 255, 255)' &&
|
waveColor !== 'rgb(255, 255, 255)' &&
|
||||||
this.isNotGrey(waveColor) &&
|
this.isNotGrey(waveColor) &&
|
||||||
!/rgba\(\d*, \d*, \d*, 0\)/.test(waveColor) && // any transparent rgba color
|
!/rgba\(\d*, \d*, \d*, 0\)/.test(waveColor) && // any transparent rgba color
|
||||||
waveColor !== 'transparent') {
|
waveColor !== 'transparent'
|
||||||
|
) {
|
||||||
extraNode.style.borderColor = waveColor;
|
extraNode.style.borderColor = waveColor;
|
||||||
styleForPesudo.innerHTML =
|
styleForPesudo.innerHTML = `[ant-click-animating-without-extra-node]:after { border-color: ${waveColor}; }`;
|
||||||
`[ant-click-animating-without-extra-node]:after { border-color: ${waveColor}; }`;
|
|
||||||
if (!document.body.contains(styleForPesudo)) {
|
if (!document.body.contains(styleForPesudo)) {
|
||||||
document.body.appendChild(styleForPesudo);
|
document.body.appendChild(styleForPesudo);
|
||||||
}
|
}
|
||||||
@ -63,13 +64,15 @@ export default class Wave extends React.Component<{insertExtraNode?: boolean}> {
|
|||||||
}
|
}
|
||||||
TransitionEvents.addStartEventListener(node, this.onTransitionStart);
|
TransitionEvents.addStartEventListener(node, this.onTransitionStart);
|
||||||
TransitionEvents.addEndEventListener(node, this.onTransitionEnd);
|
TransitionEvents.addEndEventListener(node, this.onTransitionEnd);
|
||||||
}
|
};
|
||||||
|
|
||||||
bindAnimationEvent = (node: HTMLElement) => {
|
bindAnimationEvent = (node: HTMLElement) => {
|
||||||
if (!node ||
|
if (
|
||||||
|
!node ||
|
||||||
!node.getAttribute ||
|
!node.getAttribute ||
|
||||||
node.getAttribute('disabled') ||
|
node.getAttribute('disabled') ||
|
||||||
node.className.indexOf('disabled') >= 0) {
|
node.className.indexOf('disabled') >= 0
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const onClick = (e: MouseEvent) => {
|
const onClick = (e: MouseEvent) => {
|
||||||
@ -99,7 +102,7 @@ export default class Wave extends React.Component<{insertExtraNode?: boolean}> {
|
|||||||
node.removeEventListener('click', onClick, true);
|
node.removeEventListener('click', onClick, true);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
getAttributeName() {
|
getAttributeName() {
|
||||||
const { insertExtraNode } = this.props;
|
const { insertExtraNode } = this.props;
|
||||||
@ -132,14 +135,14 @@ export default class Wave extends React.Component<{insertExtraNode?: boolean}> {
|
|||||||
if (!this.animationStart) {
|
if (!this.animationStart) {
|
||||||
this.resetEffect(node);
|
this.resetEffect(node);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
onTransitionEnd = (e: AnimationEvent) => {
|
onTransitionEnd = (e: AnimationEvent) => {
|
||||||
if (!e || e.animationName !== 'fadeEffect') {
|
if (!e || e.animationName !== 'fadeEffect') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.resetEffect(e.target as HTMLElement);
|
this.resetEffect(e.target as HTMLElement);
|
||||||
}
|
};
|
||||||
|
|
||||||
removeExtraStyleNode() {
|
removeExtraStyleNode() {
|
||||||
if (styleForPesudo) {
|
if (styleForPesudo) {
|
||||||
|
@ -12,7 +12,7 @@ class AffixMounter extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getTarget = () => this.container
|
getTarget = () => this.container;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
@ -21,7 +21,9 @@ class AffixMounter extends React.Component {
|
|||||||
height: 100,
|
height: 100,
|
||||||
overflowY: 'scroll',
|
overflowY: 'scroll',
|
||||||
}}
|
}}
|
||||||
ref={(node) => { this.container = node; }}
|
ref={node => {
|
||||||
|
this.container = node;
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="background"
|
className="background"
|
||||||
@ -32,12 +34,12 @@ class AffixMounter extends React.Component {
|
|||||||
>
|
>
|
||||||
<Affix
|
<Affix
|
||||||
target={() => this.container}
|
target={() => this.container}
|
||||||
ref={(ele) => { this.affix = ele; }}
|
ref={ele => {
|
||||||
|
this.affix = ele;
|
||||||
|
}}
|
||||||
{...this.props}
|
{...this.props}
|
||||||
>
|
>
|
||||||
<Button type="primary">
|
<Button type="primary">Fixed at the top of container</Button>
|
||||||
Fixed at the top of container
|
|
||||||
</Button>
|
|
||||||
</Affix>
|
</Affix>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -56,9 +58,14 @@ describe('Affix Render', () => {
|
|||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
const scrollTo = (top) => {
|
const scrollTo = top => {
|
||||||
wrapper.instance().affix.fixedNode.parentNode.getBoundingClientRect = jest.fn(() => ({
|
wrapper.instance().affix.fixedNode.parentNode.getBoundingClientRect = jest.fn(() => ({
|
||||||
bottom: 100, height: 28, left: 0, right: 0, top: 50 - top, width: 195,
|
bottom: 100,
|
||||||
|
height: 28,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
top: 50 - top,
|
||||||
|
width: 195,
|
||||||
}));
|
}));
|
||||||
wrapper.instance().container.scrollTop = top;
|
wrapper.instance().container.scrollTop = top;
|
||||||
events.scroll({
|
events.scroll({
|
||||||
@ -86,7 +93,9 @@ describe('Affix Render', () => {
|
|||||||
it('support offsetBottom', () => {
|
it('support offsetBottom', () => {
|
||||||
document.body.innerHTML = '<div id="mounter" />';
|
document.body.innerHTML = '<div id="mounter" />';
|
||||||
|
|
||||||
wrapper = mount(<AffixMounter offsetBottom={0} />, { attachTo: document.getElementById('mounter') });
|
wrapper = mount(<AffixMounter offsetBottom={0} />, {
|
||||||
|
attachTo: document.getElementById('mounter'),
|
||||||
|
});
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
|
|
||||||
scrollTo(0);
|
scrollTo(0);
|
||||||
@ -102,7 +111,9 @@ describe('Affix Render', () => {
|
|||||||
it('updatePosition when offsetTop changed', () => {
|
it('updatePosition when offsetTop changed', () => {
|
||||||
document.body.innerHTML = '<div id="mounter" />';
|
document.body.innerHTML = '<div id="mounter" />';
|
||||||
|
|
||||||
wrapper = mount(<AffixMounter offsetTop={0} />, { attachTo: document.getElementById('mounter') });
|
wrapper = mount(<AffixMounter offsetTop={0} />, {
|
||||||
|
attachTo: document.getElementById('mounter'),
|
||||||
|
});
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
|
|
||||||
scrollTo(100);
|
scrollTo(100);
|
||||||
|
@ -9,9 +9,9 @@ import getScroll from '../_util/getScroll';
|
|||||||
import { throttleByAnimationFrameDecorator } from '../_util/throttleByAnimationFrame';
|
import { throttleByAnimationFrameDecorator } from '../_util/throttleByAnimationFrame';
|
||||||
|
|
||||||
function getTargetRect(target: HTMLElement | Window | null): ClientRect {
|
function getTargetRect(target: HTMLElement | Window | null): ClientRect {
|
||||||
return target !== window ?
|
return target !== window
|
||||||
(target as HTMLElement).getBoundingClientRect() :
|
? (target as HTMLElement).getBoundingClientRect()
|
||||||
{ top: 0, left: 0, bottom: 0 } as ClientRect;
|
: ({ top: 0, left: 0, bottom: 0 } as ClientRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOffset(element: HTMLElement, target: HTMLElement | Window | null) {
|
function getOffset(element: HTMLElement, target: HTMLElement | Window | null) {
|
||||||
@ -26,10 +26,8 @@ function getOffset(element: HTMLElement, target: HTMLElement | Window | null) {
|
|||||||
const clientLeft = docElem.clientLeft || 0;
|
const clientLeft = docElem.clientLeft || 0;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
top: elemRect.top - targetRect.top +
|
top: elemRect.top - targetRect.top + scrollTop - clientTop,
|
||||||
scrollTop - clientTop,
|
left: elemRect.left - targetRect.left + scrollLeft - clientLeft,
|
||||||
left: elemRect.left - targetRect.left +
|
|
||||||
scrollLeft - clientLeft,
|
|
||||||
width: elemRect.width,
|
width: elemRect.width,
|
||||||
height: elemRect.height,
|
height: elemRect.height,
|
||||||
};
|
};
|
||||||
@ -101,8 +99,7 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
|||||||
}
|
}
|
||||||
this.setState({ affixStyle: affixStyle as React.CSSProperties }, () => {
|
this.setState({ affixStyle: affixStyle as React.CSSProperties }, () => {
|
||||||
const affixed = !!this.state.affixStyle;
|
const affixed = !!this.state.affixStyle;
|
||||||
if ((affixStyle && !originalAffixStyle) ||
|
if ((affixStyle && !originalAffixStyle) || (!affixStyle && originalAffixStyle)) {
|
||||||
(!affixStyle && originalAffixStyle)) {
|
|
||||||
onChange(affixed);
|
onChange(affixed);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -184,7 +181,7 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
|||||||
offsetMode.bottom
|
offsetMode.bottom
|
||||||
) {
|
) {
|
||||||
// Fixed Bottom
|
// Fixed Bottom
|
||||||
const targetBottomOffet = targetNode === window ? 0 : (window.innerHeight - targetRect.bottom);
|
const targetBottomOffet = targetNode === window ? 0 : window.innerHeight - targetRect.bottom;
|
||||||
const width = elemOffset.width;
|
const width = elemOffset.width;
|
||||||
this.setAffixStyle(e, {
|
this.setAffixStyle(e, {
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
@ -198,7 +195,12 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const { affixStyle } = this.state;
|
const { affixStyle } = this.state;
|
||||||
if (e.type === 'resize' && affixStyle && affixStyle.position === 'fixed' && affixNode.offsetWidth) {
|
if (
|
||||||
|
e.type === 'resize' &&
|
||||||
|
affixStyle &&
|
||||||
|
affixStyle.position === 'fixed' &&
|
||||||
|
affixNode.offsetWidth
|
||||||
|
) {
|
||||||
this.setAffixStyle(e, { ...affixStyle, width: affixNode.offsetWidth });
|
this.setAffixStyle(e, { ...affixStyle, width: affixNode.offsetWidth });
|
||||||
} else {
|
} else {
|
||||||
this.setAffixStyle(e, null);
|
this.setAffixStyle(e, null);
|
||||||
@ -264,18 +266,24 @@ export default class Affix extends React.Component<AffixProps, AffixState> {
|
|||||||
|
|
||||||
saveFixedNode = (node: HTMLDivElement) => {
|
saveFixedNode = (node: HTMLDivElement) => {
|
||||||
this.fixedNode = node;
|
this.fixedNode = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
savePlaceholderNode = (node: HTMLDivElement) => {
|
savePlaceholderNode = (node: HTMLDivElement) => {
|
||||||
this.placeholderNode = node;
|
this.placeholderNode = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const className = classNames({
|
const className = classNames({
|
||||||
[this.props.prefixCls || 'ant-affix']: this.state.affixStyle,
|
[this.props.prefixCls || 'ant-affix']: this.state.affixStyle,
|
||||||
});
|
});
|
||||||
|
|
||||||
const props = omit(this.props, ['prefixCls', 'offsetTop', 'offsetBottom', 'target', 'onChange']);
|
const props = omit(this.props, [
|
||||||
|
'prefixCls',
|
||||||
|
'offsetTop',
|
||||||
|
'offsetBottom',
|
||||||
|
'target',
|
||||||
|
'onChange',
|
||||||
|
]);
|
||||||
const placeholderStyle = { ...this.state.placeholderStyle, ...this.props.style };
|
const placeholderStyle = { ...this.state.placeholderStyle, ...this.props.style };
|
||||||
return (
|
return (
|
||||||
<div {...props} style={placeholderStyle} ref={this.savePlaceholderNode}>
|
<div {...props} style={placeholderStyle} ref={this.savePlaceholderNode}>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
|
|
||||||
.@{ant-prefix}-affix {
|
.@{ant-prefix}-affix {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -21,7 +21,7 @@ describe('Alert', () => {
|
|||||||
closable
|
closable
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
afterClose={afterClose}
|
afterClose={afterClose}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
wrapper.find('.ant-alert-close-icon').simulate('click');
|
wrapper.find('.ant-alert-close-icon').simulate('click');
|
||||||
expect(onClose).toBeCalled();
|
expect(onClose).toBeCalled();
|
||||||
@ -31,26 +31,20 @@ describe('Alert', () => {
|
|||||||
|
|
||||||
describe('data and aria props', () => {
|
describe('data and aria props', () => {
|
||||||
it('sets data attributes on input', () => {
|
it('sets data attributes on input', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Alert data-test="test-id" data-id="12345" />);
|
||||||
<Alert data-test="test-id" data-id="12345" />
|
|
||||||
);
|
|
||||||
const input = wrapper.find('.ant-alert').getDOMNode();
|
const input = wrapper.find('.ant-alert').getDOMNode();
|
||||||
expect(input.getAttribute('data-test')).toBe('test-id');
|
expect(input.getAttribute('data-test')).toBe('test-id');
|
||||||
expect(input.getAttribute('data-id')).toBe('12345');
|
expect(input.getAttribute('data-id')).toBe('12345');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets aria attributes on input', () => {
|
it('sets aria attributes on input', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Alert aria-describedby="some-label" />);
|
||||||
<Alert aria-describedby="some-label" />
|
|
||||||
);
|
|
||||||
const input = wrapper.find('.ant-alert').getDOMNode();
|
const input = wrapper.find('.ant-alert').getDOMNode();
|
||||||
expect(input.getAttribute('aria-describedby')).toBe('some-label');
|
expect(input.getAttribute('aria-describedby')).toBe('some-label');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets role attribute on input', () => {
|
it('sets role attribute on input', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Alert role="status" />);
|
||||||
<Alert role="status" />
|
|
||||||
);
|
|
||||||
const input = wrapper.find('.ant-alert').getDOMNode();
|
const input = wrapper.find('.ant-alert').getDOMNode();
|
||||||
expect(input.getAttribute('role')).toBe('status');
|
expect(input.getAttribute('role')).toBe('status');
|
||||||
});
|
});
|
||||||
|
@ -35,8 +35,8 @@ export interface AlertProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AlertState {
|
export interface AlertState {
|
||||||
closing: boolean,
|
closing: boolean;
|
||||||
closed: boolean
|
closed: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Alert extends React.Component<AlertProps, AlertState> {
|
export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||||
@ -57,7 +57,7 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
|||||||
closing: false,
|
closing: false,
|
||||||
});
|
});
|
||||||
(this.props.onClose || noop)(e);
|
(this.props.onClose || noop)(e);
|
||||||
}
|
};
|
||||||
|
|
||||||
animationEnd = () => {
|
animationEnd = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -65,12 +65,18 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
|||||||
closing: true,
|
closing: true,
|
||||||
});
|
});
|
||||||
(this.props.afterClose || noop)();
|
(this.props.afterClose || noop)();
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
description, prefixCls = 'ant-alert', message, closeText, banner,
|
description,
|
||||||
className = '', style, icon,
|
prefixCls = 'ant-alert',
|
||||||
|
message,
|
||||||
|
closeText,
|
||||||
|
banner,
|
||||||
|
className = '',
|
||||||
|
style,
|
||||||
|
icon,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
let { closable, type, showIcon, iconType } = this.props;
|
let { closable, type, showIcon, iconType } = this.props;
|
||||||
|
|
||||||
@ -111,13 +117,18 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
|||||||
closable = true;
|
closable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const alertCls = classNames(prefixCls, `${prefixCls}-${type}`, {
|
const alertCls = classNames(
|
||||||
|
prefixCls,
|
||||||
|
`${prefixCls}-${type}`,
|
||||||
|
{
|
||||||
[`${prefixCls}-close`]: !this.state.closing,
|
[`${prefixCls}-close`]: !this.state.closing,
|
||||||
[`${prefixCls}-with-description`]: !!description,
|
[`${prefixCls}-with-description`]: !!description,
|
||||||
[`${prefixCls}-no-icon`]: !showIcon,
|
[`${prefixCls}-no-icon`]: !showIcon,
|
||||||
[`${prefixCls}-banner`]: !!banner,
|
[`${prefixCls}-banner`]: !!banner,
|
||||||
[`${prefixCls}-closable`]: closable,
|
[`${prefixCls}-closable`]: closable,
|
||||||
}, className);
|
},
|
||||||
|
className,
|
||||||
|
);
|
||||||
|
|
||||||
const closeIcon = closable ? (
|
const closeIcon = closable ? (
|
||||||
<a onClick={this.handleClose} className={`${prefixCls}-close-icon`}>
|
<a onClick={this.handleClose} className={`${prefixCls}-close-icon`}>
|
||||||
@ -127,19 +138,17 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
|||||||
|
|
||||||
const dataOrAriaProps = getDataOrAriaProps(this.props);
|
const dataOrAriaProps = getDataOrAriaProps(this.props);
|
||||||
|
|
||||||
const iconNode = icon && (
|
const iconNode = (icon &&
|
||||||
React.isValidElement<{ className?: string }>(icon)
|
(React.isValidElement<{ className?: string }>(icon) ? (
|
||||||
? React.cloneElement(
|
React.cloneElement(icon, {
|
||||||
icon,
|
|
||||||
{
|
|
||||||
className: classNames({
|
className: classNames({
|
||||||
[icon.props.className as string]: icon.props.className,
|
[icon.props.className as string]: icon.props.className,
|
||||||
[`${prefixCls}-icon`]: true,
|
[`${prefixCls}-icon`]: true,
|
||||||
}),
|
}),
|
||||||
},
|
})
|
||||||
) : <span className={`${prefixCls}-icon`}>{icon}</span>) || (
|
) : (
|
||||||
<Icon className={`${prefixCls}-icon`} type={iconType} theme={iconTheme} />
|
<span className={`${prefixCls}-icon`}>{icon}</span>
|
||||||
);
|
))) || <Icon className={`${prefixCls}-icon`} type={iconType} theme={iconTheme} />;
|
||||||
|
|
||||||
return this.state.closed ? null : (
|
return this.state.closed ? null : (
|
||||||
<Animate
|
<Animate
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
@alert-prefix-cls: ~"@{ant-prefix}-alert";
|
@alert-prefix-cls: ~'@{ant-prefix}-alert';
|
||||||
|
|
||||||
@alert-message-color: @heading-color;
|
@alert-message-color: @heading-color;
|
||||||
@alert-text-color: @text-color;
|
@alert-text-color: @text-color;
|
||||||
@ -76,7 +76,7 @@
|
|||||||
|
|
||||||
.@{iconfont-css-prefix}-close {
|
.@{iconfont-css-prefix}-close {
|
||||||
color: @alert-close-color;
|
color: @alert-close-color;
|
||||||
transition: color .3s;
|
transition: color 0.3s;
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #404040;
|
color: #404040;
|
||||||
}
|
}
|
||||||
@ -131,12 +131,12 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
transition: all .3s @ease-in-out-circ;
|
transition: all 0.3s @ease-in-out-circ;
|
||||||
transform-origin: 50% 0;
|
transform-origin: 50% 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-slide-up-leave {
|
&-slide-up-leave {
|
||||||
animation: antAlertSlideUpOut .3s @ease-in-out-circ;
|
animation: antAlertSlideUpOut 0.3s @ease-in-out-circ;
|
||||||
animation-fill-mode: both;
|
animation-fill-mode: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,17 +38,24 @@ function easeInOutCubic(t: number, b: number, c: number, d: number) {
|
|||||||
const cc = c - b;
|
const cc = c - b;
|
||||||
t /= d / 2;
|
t /= d / 2;
|
||||||
if (t < 1) {
|
if (t < 1) {
|
||||||
return cc / 2 * t * t * t + b;
|
return (cc / 2) * t * t * t + b;
|
||||||
}
|
}
|
||||||
return cc / 2 * ((t -= 2) * t * t + 2) + b;
|
return (cc / 2) * ((t -= 2) * t * t + 2) + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sharpMatcherRegx = /#([^#]+)$/;
|
const sharpMatcherRegx = /#([^#]+)$/;
|
||||||
function scrollTo(href: string, offsetTop = 0, getContainer: () => AnchorContainer, callback = () => { }) {
|
function scrollTo(
|
||||||
|
href: string,
|
||||||
|
offsetTop = 0,
|
||||||
|
getContainer: () => AnchorContainer,
|
||||||
|
callback = () => {},
|
||||||
|
) {
|
||||||
const container = getContainer();
|
const container = getContainer();
|
||||||
const scrollTop = getScroll(container, true);
|
const scrollTop = getScroll(container, true);
|
||||||
const sharpLinkMatch = sharpMatcherRegx.exec(href);
|
const sharpLinkMatch = sharpMatcherRegx.exec(href);
|
||||||
if (!sharpLinkMatch) { return; }
|
if (!sharpLinkMatch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const targetElement = document.getElementById(sharpLinkMatch[1]);
|
const targetElement = document.getElementById(sharpLinkMatch[1]);
|
||||||
if (!targetElement) {
|
if (!targetElement) {
|
||||||
return;
|
return;
|
||||||
@ -91,7 +98,10 @@ export interface AnchorProps {
|
|||||||
affix?: boolean;
|
affix?: boolean;
|
||||||
showInkInFixed?: boolean;
|
showInkInFixed?: boolean;
|
||||||
getContainer?: () => AnchorContainer;
|
getContainer?: () => AnchorContainer;
|
||||||
onClick?: (e: React.MouseEvent<HTMLElement>, link: { title: React.ReactNode, href: string }) => void;
|
onClick?: (
|
||||||
|
e: React.MouseEvent<HTMLElement>,
|
||||||
|
link: { title: React.ReactNode; href: string },
|
||||||
|
) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AnchorState {
|
export interface AnchorState {
|
||||||
@ -110,7 +120,10 @@ export interface AntAnchor {
|
|||||||
unregisterLink: (link: string) => void;
|
unregisterLink: (link: string) => void;
|
||||||
activeLink: string | null;
|
activeLink: string | null;
|
||||||
scrollTo: (link: string) => void;
|
scrollTo: (link: string) => void;
|
||||||
onClick?: (e: React.MouseEvent<HTMLElement>, link: { title: React.ReactNode, href: string }) => void;
|
onClick?: (
|
||||||
|
e: React.MouseEvent<HTMLElement>,
|
||||||
|
link: { title: React.ReactNode; href: string },
|
||||||
|
) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||||
@ -181,7 +194,7 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
|||||||
this.setState({
|
this.setState({
|
||||||
activeLink: this.getCurrentAnchor(offsetTop, bounds),
|
activeLink: this.getCurrentAnchor(offsetTop, bounds),
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
handleScrollTo = (link: string) => {
|
handleScrollTo = (link: string) => {
|
||||||
const { offsetTop, getContainer } = this.props as AnchorDefaultProps;
|
const { offsetTop, getContainer } = this.props as AnchorDefaultProps;
|
||||||
@ -190,7 +203,7 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
|||||||
scrollTo(link, offsetTop, getContainer, () => {
|
scrollTo(link, offsetTop, getContainer, () => {
|
||||||
this.animating = false;
|
this.animating = false;
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
getCurrentAnchor(offsetTop = 0, bounds = 5): string {
|
getCurrentAnchor(offsetTop = 0, bounds = 5): string {
|
||||||
const activeLink = '';
|
const activeLink = '';
|
||||||
@ -203,7 +216,9 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
|||||||
const container = getContainer();
|
const container = getContainer();
|
||||||
this.links.forEach(link => {
|
this.links.forEach(link => {
|
||||||
const sharpLinkMatch = sharpMatcherRegx.exec(link.toString());
|
const sharpLinkMatch = sharpMatcherRegx.exec(link.toString());
|
||||||
if (!sharpLinkMatch) { return; }
|
if (!sharpLinkMatch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const target = document.getElementById(sharpLinkMatch[1]);
|
const target = document.getElementById(sharpLinkMatch[1]);
|
||||||
if (target) {
|
if (target) {
|
||||||
const top = getOffsetTop(target, container);
|
const top = getOffsetTop(target, container);
|
||||||
@ -217,7 +232,7 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (linkSections.length) {
|
if (linkSections.length) {
|
||||||
const maxSection = linkSections.reduce((prev, curr) => curr.top > prev.top ? curr : prev);
|
const maxSection = linkSections.reduce((prev, curr) => (curr.top > prev.top ? curr : prev));
|
||||||
return maxSection.link;
|
return maxSection.link;
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
@ -233,11 +248,11 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
|||||||
if (linkNode) {
|
if (linkNode) {
|
||||||
this.inkNode.style.top = `${(linkNode as any).offsetTop + linkNode.clientHeight / 2 - 4.5}px`;
|
this.inkNode.style.top = `${(linkNode as any).offsetTop + linkNode.clientHeight / 2 - 4.5}px`;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
saveInkNode = (node: HTMLSpanElement) => {
|
saveInkNode = (node: HTMLSpanElement) => {
|
||||||
this.inkNode = node;
|
this.inkNode = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
@ -259,7 +274,7 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
|||||||
const wrapperClass = classNames(className, `${prefixCls}-wrapper`);
|
const wrapperClass = classNames(className, `${prefixCls}-wrapper`);
|
||||||
|
|
||||||
const anchorClass = classNames(prefixCls, {
|
const anchorClass = classNames(prefixCls, {
|
||||||
'fixed': !affix && !showInkInFixed,
|
fixed: !affix && !showInkInFixed,
|
||||||
});
|
});
|
||||||
|
|
||||||
const wrapperStyle = {
|
const wrapperStyle = {
|
||||||
@ -268,10 +283,7 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const anchorContent = (
|
const anchorContent = (
|
||||||
<div
|
<div className={wrapperClass} style={wrapperStyle}>
|
||||||
className={wrapperClass}
|
|
||||||
style={wrapperStyle}
|
|
||||||
>
|
|
||||||
<div className={anchorClass}>
|
<div className={anchorClass}>
|
||||||
<div className={`${prefixCls}-ink`}>
|
<div className={`${prefixCls}-ink`}>
|
||||||
<span className={inkClass} ref={this.saveInkNode} />
|
<span className={inkClass} ref={this.saveInkNode} />
|
||||||
@ -281,7 +293,9 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return !affix ? anchorContent : (
|
return !affix ? (
|
||||||
|
anchorContent
|
||||||
|
) : (
|
||||||
<Affix offsetTop={offsetTop} target={getContainer}>
|
<Affix offsetTop={offsetTop} target={getContainer}>
|
||||||
{anchorContent}
|
{anchorContent}
|
||||||
</Affix>
|
</Affix>
|
||||||
|
@ -47,15 +47,10 @@ export default class AnchorLink extends React.Component<AnchorLinkProps, any> {
|
|||||||
onClick(e, { title, href });
|
onClick(e, { title, href });
|
||||||
}
|
}
|
||||||
scrollTo(href);
|
scrollTo(href);
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const { prefixCls, href, title, children } = this.props;
|
||||||
prefixCls,
|
|
||||||
href,
|
|
||||||
title,
|
|
||||||
children,
|
|
||||||
} = this.props;
|
|
||||||
const active = this.context.antAnchor.activeLink === href;
|
const active = this.context.antAnchor.activeLink === href;
|
||||||
const wrapperClassName = classNames(`${prefixCls}-link`, {
|
const wrapperClassName = classNames(`${prefixCls}-link`, {
|
||||||
[`${prefixCls}-link-active`]: active,
|
[`${prefixCls}-link-active`]: active,
|
||||||
|
@ -9,7 +9,7 @@ describe('Anchor Render', () => {
|
|||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Anchor>
|
<Anchor>
|
||||||
<Link href="#API" title="API" />
|
<Link href="#API" title="API" />
|
||||||
</Anchor>
|
</Anchor>,
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.find('a[href="#API"]').simulate('click');
|
wrapper.find('a[href="#API"]').simulate('click');
|
||||||
@ -22,7 +22,7 @@ describe('Anchor Render', () => {
|
|||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Anchor>
|
<Anchor>
|
||||||
<Link href="http://www.example.com/#API" title="API" />
|
<Link href="http://www.example.com/#API" title="API" />
|
||||||
</Anchor>
|
</Anchor>,
|
||||||
);
|
);
|
||||||
wrapper.find('a[href="http://www.example.com/#API"]').simulate('click');
|
wrapper.find('a[href="http://www.example.com/#API"]').simulate('click');
|
||||||
expect(wrapper.instance().state.activeLink).toBe('http://www.example.com/#API');
|
expect(wrapper.instance().state.activeLink).toBe('http://www.example.com/#API');
|
||||||
@ -39,7 +39,7 @@ describe('Anchor Render', () => {
|
|||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Anchor>
|
<Anchor>
|
||||||
<Link href="http://www.example.com/#API" title="API" />
|
<Link href="http://www.example.com/#API" title="API" />
|
||||||
</Anchor>
|
</Anchor>,
|
||||||
);
|
);
|
||||||
wrapper.instance().handleScroll();
|
wrapper.instance().handleScroll();
|
||||||
expect(wrapper.instance().state.activeLink).toBe('http://www.example.com/#API');
|
expect(wrapper.instance().state.activeLink).toBe('http://www.example.com/#API');
|
||||||
@ -57,7 +57,7 @@ describe('Anchor Render', () => {
|
|||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Anchor>
|
<Anchor>
|
||||||
<Link href="##API" title="API" />
|
<Link href="##API" title="API" />
|
||||||
</Anchor>
|
</Anchor>,
|
||||||
);
|
);
|
||||||
wrapper.instance().handleScrollTo('##API');
|
wrapper.instance().handleScrollTo('##API');
|
||||||
expect(wrapper.instance().state.activeLink).toBe('##API');
|
expect(wrapper.instance().state.activeLink).toBe('##API');
|
||||||
@ -70,7 +70,7 @@ describe('Anchor Render', () => {
|
|||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Anchor>
|
<Anchor>
|
||||||
<Link href="#API" title="API" />
|
<Link href="#API" title="API" />
|
||||||
</Anchor>
|
</Anchor>,
|
||||||
);
|
);
|
||||||
const removeListenerSpy = jest.spyOn(wrapper.instance().scrollEvent, 'remove');
|
const removeListenerSpy = jest.spyOn(wrapper.instance().scrollEvent, 'remove');
|
||||||
wrapper.unmount();
|
wrapper.unmount();
|
||||||
@ -81,7 +81,7 @@ describe('Anchor Render', () => {
|
|||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Anchor>
|
<Anchor>
|
||||||
<Link href="#API" title="API" />
|
<Link href="#API" title="API" />
|
||||||
</Anchor>
|
</Anchor>,
|
||||||
);
|
);
|
||||||
expect(wrapper.instance().links).toEqual(['#API']);
|
expect(wrapper.instance().links).toEqual(['#API']);
|
||||||
wrapper.setProps({ children: null });
|
wrapper.setProps({ children: null });
|
||||||
@ -92,7 +92,11 @@ describe('Anchor Render', () => {
|
|||||||
let anchorInstance = null;
|
let anchorInstance = null;
|
||||||
function AnchorUpdate({ href }) {
|
function AnchorUpdate({ href }) {
|
||||||
return (
|
return (
|
||||||
<Anchor ref={(c) => { anchorInstance = c; }}>
|
<Anchor
|
||||||
|
ref={c => {
|
||||||
|
anchorInstance = c;
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Link href={href} title="API" />
|
<Link href={href} title="API" />
|
||||||
</Anchor>
|
</Anchor>
|
||||||
);
|
);
|
||||||
@ -107,7 +111,9 @@ describe('Anchor Render', () => {
|
|||||||
it('Anchor onClick event', () => {
|
it('Anchor onClick event', () => {
|
||||||
let event;
|
let event;
|
||||||
let link;
|
let link;
|
||||||
const handleClick = (...arg) => { [event, link] = arg; };
|
const handleClick = (...arg) => {
|
||||||
|
[event, link] = arg;
|
||||||
|
};
|
||||||
|
|
||||||
const href = '#API';
|
const href = '#API';
|
||||||
const title = 'API';
|
const title = 'API';
|
||||||
@ -115,7 +121,7 @@ describe('Anchor Render', () => {
|
|||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Anchor onClick={handleClick}>
|
<Anchor onClick={handleClick}>
|
||||||
<Link href={href} title={title} />
|
<Link href={href} title={title} />
|
||||||
</Anchor>
|
</Anchor>,
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.find(`a[href="${href}"]`).simulate('click');
|
wrapper.find(`a[href="${href}"]`).simulate('click');
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
@anchor-border-width: 2px;
|
@anchor-border-width: 2px;
|
||||||
|
|
||||||
@ -38,7 +38,7 @@
|
|||||||
border: 2px solid @primary-color;
|
border: 2px solid @primary-color;
|
||||||
background-color: @component-background;
|
background-color: @component-background;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transition: top .3s ease-in-out;
|
transition: top 0.3s ease-in-out;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
&.visible {
|
&.visible {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -57,7 +57,7 @@
|
|||||||
&-title {
|
&-title {
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: all .3s;
|
transition: all 0.3s;
|
||||||
color: @text-color;
|
color: @text-color;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -9,22 +9,28 @@ export default class InputElement extends React.Component<InputElementProps, any
|
|||||||
private ele: HTMLInputElement;
|
private ele: HTMLInputElement;
|
||||||
|
|
||||||
focus = () => {
|
focus = () => {
|
||||||
this.ele.focus ? this.ele.focus() : (ReactDOM.findDOMNode(this.ele) as HTMLInputElement).focus();
|
this.ele.focus
|
||||||
}
|
? this.ele.focus()
|
||||||
|
: (ReactDOM.findDOMNode(this.ele) as HTMLInputElement).focus();
|
||||||
|
};
|
||||||
blur = () => {
|
blur = () => {
|
||||||
this.ele.blur ? this.ele.blur() : (ReactDOM.findDOMNode(this.ele) as HTMLInputElement).blur();
|
this.ele.blur ? this.ele.blur() : (ReactDOM.findDOMNode(this.ele) as HTMLInputElement).blur();
|
||||||
}
|
};
|
||||||
saveRef = (ele: HTMLInputElement) => {
|
saveRef = (ele: HTMLInputElement) => {
|
||||||
this.ele = ele;
|
this.ele = ele;
|
||||||
const { ref: childRef } = this.props.children as any;
|
const { ref: childRef } = this.props.children as any;
|
||||||
if (typeof childRef === 'function') {
|
if (typeof childRef === 'function') {
|
||||||
childRef(ele);
|
childRef(ele);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
render() {
|
render() {
|
||||||
return React.cloneElement(this.props.children, {
|
return React.cloneElement(
|
||||||
|
this.props.children,
|
||||||
|
{
|
||||||
...this.props,
|
...this.props,
|
||||||
ref: this.saveRef,
|
ref: this.saveRef,
|
||||||
}, null);
|
},
|
||||||
|
null,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,17 @@ describe('AutoComplete with Custom Input Element Render', () => {
|
|||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<AutoComplete dataSource={['12345', '23456', '34567']}>
|
<AutoComplete dataSource={['12345', '23456', '34567']}>
|
||||||
<textarea />
|
<textarea />
|
||||||
</AutoComplete>
|
</AutoComplete>,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(wrapper.find('textarea').length).toBe(1);
|
expect(wrapper.find('textarea').length).toBe(1);
|
||||||
wrapper.find('textarea').simulate('change', { target: { value: '123' } });
|
wrapper.find('textarea').simulate('change', { target: { value: '123' } });
|
||||||
const dropdownWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
const dropdownWrapper = mount(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
|
|
||||||
// should not filter data source defaultly
|
// should not filter data source defaultly
|
||||||
expect(dropdownWrapper.find('MenuItem').length).toBe(3);
|
expect(dropdownWrapper.find('MenuItem').length).toBe(3);
|
||||||
@ -26,7 +31,7 @@ describe('AutoComplete with Custom Input Element Render', () => {
|
|||||||
mount(
|
mount(
|
||||||
<AutoComplete dataSource={[]}>
|
<AutoComplete dataSource={[]}>
|
||||||
<input ref={mockRef} />
|
<input ref={mockRef} />
|
||||||
</AutoComplete>
|
</AutoComplete>,
|
||||||
);
|
);
|
||||||
expect(mockRef).toHaveBeenCalled();
|
expect(mockRef).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
@ -5,12 +5,15 @@ import Select, { AbstractSelectProps, SelectValue, OptionProps, OptGroupProps }
|
|||||||
import Input from '../input';
|
import Input from '../input';
|
||||||
import InputElement from './InputElement';
|
import InputElement from './InputElement';
|
||||||
|
|
||||||
export interface DataSourceItemObject { value: string; text: string; }
|
export interface DataSourceItemObject {
|
||||||
|
value: string;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
export type DataSourceItemType =
|
export type DataSourceItemType =
|
||||||
string |
|
| string
|
||||||
DataSourceItemObject |
|
| DataSourceItemObject
|
||||||
React.ReactElement<OptionProps> |
|
| React.ReactElement<OptionProps>
|
||||||
React.ReactElement<OptGroupProps>;
|
| React.ReactElement<OptGroupProps>;
|
||||||
|
|
||||||
export interface AutoCompleteInputProps {
|
export interface AutoCompleteInputProps {
|
||||||
onChange?: React.FormEventHandler<any>;
|
onChange?: React.FormEventHandler<any>;
|
||||||
@ -18,9 +21,9 @@ export interface AutoCompleteInputProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type ValidInputElement =
|
export type ValidInputElement =
|
||||||
HTMLInputElement |
|
| HTMLInputElement
|
||||||
HTMLTextAreaElement |
|
| HTMLTextAreaElement
|
||||||
React.ReactElement<AutoCompleteInputProps>;
|
| React.ReactElement<AutoCompleteInputProps>;
|
||||||
|
|
||||||
export interface AutoCompleteProps extends AbstractSelectProps {
|
export interface AutoCompleteProps extends AbstractSelectProps {
|
||||||
value?: SelectValue;
|
value?: SelectValue;
|
||||||
@ -33,9 +36,10 @@ export interface AutoCompleteProps extends AbstractSelectProps {
|
|||||||
onSelect?: (value: SelectValue, option: Object) => any;
|
onSelect?: (value: SelectValue, option: Object) => any;
|
||||||
onBlur?: (value: SelectValue) => void;
|
onBlur?: (value: SelectValue) => void;
|
||||||
onFocus?: () => void;
|
onFocus?: () => void;
|
||||||
children?: ValidInputElement |
|
children?:
|
||||||
React.ReactElement<OptionProps> |
|
| ValidInputElement
|
||||||
Array<React.ReactElement<OptionProps>>;
|
| React.ReactElement<OptionProps>
|
||||||
|
| Array<React.ReactElement<OptionProps>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSelectOptionOrSelectOptGroup(child: any): Boolean {
|
function isSelectOptionOrSelectOptGroup(child: any): Boolean {
|
||||||
@ -59,15 +63,17 @@ export default class AutoComplete extends React.Component<AutoCompleteProps, {}>
|
|||||||
|
|
||||||
getInputElement = () => {
|
getInputElement = () => {
|
||||||
const { children } = this.props;
|
const { children } = this.props;
|
||||||
const element = children && React.isValidElement(children) && children.type !== Option ?
|
const element =
|
||||||
React.Children.only(this.props.children) : <Input />;
|
children && React.isValidElement(children) && children.type !== Option ? (
|
||||||
|
React.Children.only(this.props.children)
|
||||||
|
) : (
|
||||||
|
<Input />
|
||||||
|
);
|
||||||
const elementProps = { ...element.props };
|
const elementProps = { ...element.props };
|
||||||
// https://github.com/ant-design/ant-design/pull/7742
|
// https://github.com/ant-design/ant-design/pull/7742
|
||||||
delete elementProps.children;
|
delete elementProps.children;
|
||||||
return (
|
return <InputElement {...elementProps}>{element}</InputElement>;
|
||||||
<InputElement {...elementProps}>{element}</InputElement>
|
};
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
this.select.focus();
|
this.select.focus();
|
||||||
@ -79,11 +85,17 @@ export default class AutoComplete extends React.Component<AutoCompleteProps, {}>
|
|||||||
|
|
||||||
saveSelect = (node: any) => {
|
saveSelect = (node: any) => {
|
||||||
this.select = node;
|
this.select = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
size, className = '', notFoundContent, prefixCls, optionLabelProp, dataSource, children,
|
size,
|
||||||
|
className = '',
|
||||||
|
notFoundContent,
|
||||||
|
prefixCls,
|
||||||
|
optionLabelProp,
|
||||||
|
dataSource,
|
||||||
|
children,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const cls = classNames({
|
const cls = classNames({
|
||||||
@ -96,12 +108,11 @@ export default class AutoComplete extends React.Component<AutoCompleteProps, {}>
|
|||||||
|
|
||||||
let options;
|
let options;
|
||||||
const childArray = React.Children.toArray(children);
|
const childArray = React.Children.toArray(children);
|
||||||
if (childArray.length &&
|
if (childArray.length && isSelectOptionOrSelectOptGroup(childArray[0])) {
|
||||||
isSelectOptionOrSelectOptGroup(childArray[0])
|
|
||||||
) {
|
|
||||||
options = children;
|
options = children;
|
||||||
} else {
|
} else {
|
||||||
options = dataSource ? dataSource.map((item) => {
|
options = dataSource
|
||||||
|
? dataSource.map(item => {
|
||||||
if (React.isValidElement(item)) {
|
if (React.isValidElement(item)) {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
@ -115,9 +126,12 @@ export default class AutoComplete extends React.Component<AutoCompleteProps, {}>
|
|||||||
</Option>
|
</Option>
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
throw new Error('AutoComplete[dataSource] only supports type `string[] | Object[]`.');
|
throw new Error(
|
||||||
|
'AutoComplete[dataSource] only supports type `string[] | Object[]`.',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}) : [];
|
})
|
||||||
|
: [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
@import "../../input/style/mixin";
|
@import '../../input/style/mixin';
|
||||||
|
|
||||||
@input-prefix-cls: ~"@{ant-prefix}-input";
|
@input-prefix-cls: ~'@{ant-prefix}-input';
|
||||||
@select-prefix-cls: ~"@{ant-prefix}-select";
|
@select-prefix-cls: ~'@{ant-prefix}-select';
|
||||||
@autocomplete-prefix-cls: ~"@{select-prefix-cls}-auto-complete";
|
@autocomplete-prefix-cls: ~'@{select-prefix-cls}-auto-complete';
|
||||||
|
|
||||||
.@{autocomplete-prefix-cls} {
|
.@{autocomplete-prefix-cls} {
|
||||||
.reset-component;
|
.reset-component;
|
||||||
|
@ -38,14 +38,14 @@ describe('Avatar Render', () => {
|
|||||||
class Foo extends React.Component {
|
class Foo extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
src: LOAD_FAILURE_SRC,
|
src: LOAD_FAILURE_SRC,
|
||||||
}
|
};
|
||||||
|
|
||||||
handleImgError = () => {
|
handleImgError = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
src: LOAD_SUCCESS_SRC,
|
src: LOAD_SUCCESS_SRC,
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { src } = this.state;
|
const { src } = this.state;
|
||||||
|
@ -51,9 +51,11 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps: AvatarProps, prevState: AvatarState) {
|
componentDidUpdate(prevProps: AvatarProps, prevState: AvatarState) {
|
||||||
if (prevProps.children !== this.props.children
|
if (
|
||||||
|| (prevState.scale !== this.state.scale && this.state.scale === 1)
|
prevProps.children !== this.props.children ||
|
||||||
|| (prevState.isImgExist !== this.state.isImgExist)) {
|
(prevState.scale !== this.state.scale && this.state.scale === 1) ||
|
||||||
|
prevState.isImgExist !== this.state.isImgExist
|
||||||
|
) {
|
||||||
this.setScale();
|
this.setScale();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,7 +77,7 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleImgLoadError = () => {
|
handleImgLoadError = () => {
|
||||||
const { onError } = this.props;
|
const { onError } = this.props;
|
||||||
@ -83,12 +85,10 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
|||||||
if (errorFlag !== false) {
|
if (errorFlag !== false) {
|
||||||
this.setState({ isImgExist: false });
|
this.setState({ isImgExist: false });
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const { prefixCls, shape, size, src, srcSet, icon, className, alt, ...others } = this.props;
|
||||||
prefixCls, shape, size, src, srcSet, icon, className, alt, ...others
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const { isImgExist, scale } = this.state;
|
const { isImgExist, scale } = this.state;
|
||||||
|
|
||||||
@ -103,23 +103,19 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
|||||||
[`${prefixCls}-icon`]: icon,
|
[`${prefixCls}-icon`]: icon,
|
||||||
});
|
});
|
||||||
|
|
||||||
const sizeStyle: React.CSSProperties = typeof size === 'number' ? {
|
const sizeStyle: React.CSSProperties =
|
||||||
|
typeof size === 'number'
|
||||||
|
? {
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
lineHeight: `${size}px`,
|
lineHeight: `${size}px`,
|
||||||
fontSize: icon ? size / 2 : 18,
|
fontSize: icon ? size / 2 : 18,
|
||||||
} : {};
|
}
|
||||||
|
: {};
|
||||||
|
|
||||||
let children = this.props.children;
|
let children = this.props.children;
|
||||||
if (src && isImgExist) {
|
if (src && isImgExist) {
|
||||||
children = (
|
children = <img src={src} srcSet={srcSet} onError={this.handleImgLoadError} alt={alt} />;
|
||||||
<img
|
|
||||||
src={src}
|
|
||||||
srcSet={srcSet}
|
|
||||||
onError={this.handleImgLoadError}
|
|
||||||
alt={alt}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else if (icon) {
|
} else if (icon) {
|
||||||
children = <Icon type={icon} />;
|
children = <Icon type={icon} />;
|
||||||
} else {
|
} else {
|
||||||
@ -132,13 +128,15 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
|||||||
transform: transformString,
|
transform: transformString,
|
||||||
};
|
};
|
||||||
const sizeChildrenStyle: React.CSSProperties =
|
const sizeChildrenStyle: React.CSSProperties =
|
||||||
typeof size === 'number' ? {
|
typeof size === 'number'
|
||||||
|
? {
|
||||||
lineHeight: `${size}px`,
|
lineHeight: `${size}px`,
|
||||||
} : {};
|
}
|
||||||
|
: {};
|
||||||
children = (
|
children = (
|
||||||
<span
|
<span
|
||||||
className={`${prefixCls}-string`}
|
className={`${prefixCls}-string`}
|
||||||
ref={span => this.avatarChildren = span}
|
ref={span => (this.avatarChildren = span)}
|
||||||
style={{ ...sizeChildrenStyle, ...childrenStyle }}
|
style={{ ...sizeChildrenStyle, ...childrenStyle }}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
@ -146,21 +144,14 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
children = (
|
children = (
|
||||||
<span
|
<span className={`${prefixCls}-string`} ref={span => (this.avatarChildren = span)}>
|
||||||
className={`${prefixCls}-string`}
|
|
||||||
ref={span => this.avatarChildren = span}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<span
|
<span {...others} style={{ ...sizeStyle, ...others.style }} className={classString}>
|
||||||
{...others}
|
|
||||||
style={{ ...sizeStyle, ...others.style }}
|
|
||||||
className={classString}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
@avatar-prefix-cls: ~"@{ant-prefix}-avatar";
|
@avatar-prefix-cls: ~'@{ant-prefix}-avatar';
|
||||||
|
|
||||||
.@{avatar-prefix-cls} {
|
.@{avatar-prefix-cls} {
|
||||||
.reset-component;
|
.reset-component;
|
||||||
|
@ -10,9 +10,9 @@ const easeInOutCubic = (t: number, b: number, c: number, d: number) => {
|
|||||||
const cc = c - b;
|
const cc = c - b;
|
||||||
t /= d / 2;
|
t /= d / 2;
|
||||||
if (t < 1) {
|
if (t < 1) {
|
||||||
return cc / 2 * t * t * t + b;
|
return (cc / 2) * t * t * t + b;
|
||||||
} else {
|
} else {
|
||||||
return cc / 2 * ((t -= 2) * t * t + 2) + b;
|
return (cc / 2) * ((t -= 2) * t * t + 2) + b;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ export default class BackTop extends React.Component<BackTopProps, any> {
|
|||||||
return window.pageYOffset || document.body.scrollTop || document.documentElement!.scrollTop;
|
return window.pageYOffset || document.body.scrollTop || document.documentElement!.scrollTop;
|
||||||
}
|
}
|
||||||
return (targetNode as HTMLElement).scrollTop;
|
return (targetNode as HTMLElement).scrollTop;
|
||||||
}
|
};
|
||||||
|
|
||||||
scrollToTop = (e: React.MouseEvent<HTMLDivElement>) => {
|
scrollToTop = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||||
const scrollTop = this.getCurrentScrollTop();
|
const scrollTop = this.getCurrentScrollTop();
|
||||||
@ -69,7 +69,7 @@ export default class BackTop extends React.Component<BackTopProps, any> {
|
|||||||
};
|
};
|
||||||
raf(frameFunc);
|
raf(frameFunc);
|
||||||
(this.props.onClick || noop)(e);
|
(this.props.onClick || noop)(e);
|
||||||
}
|
};
|
||||||
|
|
||||||
setScrollTop(value: number) {
|
setScrollTop(value: number) {
|
||||||
const getTarget = this.props.target || getDefaultTarget;
|
const getTarget = this.props.target || getDefaultTarget;
|
||||||
@ -88,7 +88,7 @@ export default class BackTop extends React.Component<BackTopProps, any> {
|
|||||||
this.setState({
|
this.setState({
|
||||||
visible: scrollTop > (visibilityHeight as number),
|
visible: scrollTop > (visibilityHeight as number),
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const getTarget = this.props.target || getDefaultTarget;
|
const getTarget = this.props.target || getDefaultTarget;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
@backtop-prefix-cls: ~"@{ant-prefix}-back-top";
|
@backtop-prefix-cls: ~'@{ant-prefix}-back-top';
|
||||||
|
|
||||||
.@{backtop-prefix-cls} {
|
.@{backtop-prefix-cls} {
|
||||||
.reset-component;
|
.reset-component;
|
||||||
@ -20,12 +20,12 @@
|
|||||||
background-color: @back-top-bg;
|
background-color: @back-top-bg;
|
||||||
color: @back-top-color;
|
color: @back-top-color;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
transition: all .3s @ease-in-out;
|
transition: all 0.3s @ease-in-out;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: @back-top-hover-bg;
|
background-color: @back-top-hover-bg;
|
||||||
transition: all .3s @ease-in-out;
|
transition: all 0.3s @ease-in-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +33,8 @@
|
|||||||
margin: 12px auto;
|
margin: 12px auto;
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAoCAYAAACWwljjAAAABGdBTUEAALGPC/xhBQAAAbtJREFUWAntmMtKw0AUhhMvS5cuxILgQlRUpIggIoKIIoigG1eC+AA+jo+i6FIXBfeuXIgoeKVeitVWJX5HWhhDksnUpp3FDPyZk3Nm5nycmZKkXhAEOXSA3lG7muTeRzmfy6HneUvIhnYkQK+Q9NhAA0Opg0vBEhjBKHiyb8iGMyQMOYuK41BcBSypAL+MYXSKjtFAW7EAGEO3qN4uMQbbAkXiSfRQJ1H6a+yhlkKRcAoVFYiweYNjtCVQJJpBz2GCiPt7fBOZQpFgDpUikse5HgnkM4Fi4QX0Fpc5wf9EbLqpUCy4jMoJSXWhFwbMNgWKhVbRhy5jirhs9fy/oFhgHVVTJEs7RLZ8sSEoJm6iz7SZDMbJ+/OKERQTttCXQRLToRUmrKWCYuA2+jbN0MB4OQobYShfdTCgn/sL1K36M7TLrN3n+758aPy2rrpR6+/od5E8tf/A1uLS9aId5T7J3CNYihkQ4D9PiMdMC7mp4rjB9kjFjZp8BlnVHJBuO1yFXIV0FdDF3RlyFdJVQBdv5AxVdIsq8apiZ2PyYO1EVykesGfZEESsCkweyR8MUW+V8uJ1gkYipmpdP1pm2aJVPEGzAAAAAElFTkSuQmCC) ~"100%/100%" no-repeat;
|
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAoCAYAAACWwljjAAAABGdBTUEAALGPC/xhBQAAAbtJREFUWAntmMtKw0AUhhMvS5cuxILgQlRUpIggIoKIIoigG1eC+AA+jo+i6FIXBfeuXIgoeKVeitVWJX5HWhhDksnUpp3FDPyZk3Nm5nycmZKkXhAEOXSA3lG7muTeRzmfy6HneUvIhnYkQK+Q9NhAA0Opg0vBEhjBKHiyb8iGMyQMOYuK41BcBSypAL+MYXSKjtFAW7EAGEO3qN4uMQbbAkXiSfRQJ1H6a+yhlkKRcAoVFYiweYNjtCVQJJpBz2GCiPt7fBOZQpFgDpUikse5HgnkM4Fi4QX0Fpc5wf9EbLqpUCy4jMoJSXWhFwbMNgWKhVbRhy5jirhs9fy/oFhgHVVTJEs7RLZ8sSEoJm6iz7SZDMbJ+/OKERQTttCXQRLToRUmrKWCYuA2+jbN0MB4OQobYShfdTCgn/sL1K36M7TLrN3n+758aPy2rrpR6+/od5E8tf/A1uLS9aId5T7J3CNYihkQ4D9PiMdMC7mp4rjB9kjFjZp8BlnVHJBuO1yFXIV0FdDF3RlyFdJVQBdv5AxVdIsq8apiZ2PyYO1EVykesGfZEESsCkweyR8MUW+V8uJ1gkYipmpdP1pm2aJVPEGzAAAAAElFTkSuQmCC)
|
||||||
|
~'100%/100%' no-repeat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,11 +4,13 @@ import omit from 'omit.js';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
function getNumberArray(num: string | number | undefined | null) {
|
function getNumberArray(num: string | number | undefined | null) {
|
||||||
return num ?
|
return num
|
||||||
num.toString()
|
? num
|
||||||
|
.toString()
|
||||||
.split('')
|
.split('')
|
||||||
.reverse()
|
.reverse()
|
||||||
.map(i => Number(i)) : [];
|
.map(i => Number(i))
|
||||||
|
: [];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ScrollNumberProps {
|
export interface ScrollNumberProps {
|
||||||
@ -31,8 +33,7 @@ export default class ScrollNumber extends Component<ScrollNumberProps, ScrollNum
|
|||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
prefixCls: 'ant-scroll-number',
|
prefixCls: 'ant-scroll-number',
|
||||||
count: null,
|
count: null,
|
||||||
onAnimated() {
|
onAnimated() {},
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
lastCount: any;
|
lastCount: any;
|
||||||
@ -71,40 +72,52 @@ export default class ScrollNumber extends Component<ScrollNumberProps, ScrollNum
|
|||||||
}
|
}
|
||||||
this.lastCount = this.state.count;
|
this.lastCount = this.state.count;
|
||||||
// 复原数字初始位置
|
// 复原数字初始位置
|
||||||
this.setState({
|
this.setState(
|
||||||
|
{
|
||||||
animateStarted: true,
|
animateStarted: true,
|
||||||
}, () => {
|
},
|
||||||
|
() => {
|
||||||
// 等待数字位置复原完毕
|
// 等待数字位置复原完毕
|
||||||
// 开始设置完整的数字
|
// 开始设置完整的数字
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.setState({
|
this.setState(
|
||||||
|
{
|
||||||
animateStarted: false,
|
animateStarted: false,
|
||||||
count: nextProps.count,
|
count: nextProps.count,
|
||||||
}, () => {
|
},
|
||||||
|
() => {
|
||||||
const onAnimated = this.props.onAnimated;
|
const onAnimated = this.props.onAnimated;
|
||||||
if (onAnimated) {
|
if (onAnimated) {
|
||||||
onAnimated();
|
onAnimated();
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}, 5);
|
}, 5);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderNumberList(position: number) {
|
renderNumberList(position: number) {
|
||||||
const childrenToReturn: React.ReactElement<any>[] = [];
|
const childrenToReturn: React.ReactElement<any>[] = [];
|
||||||
for (let i = 0; i < 30; i++) {
|
for (let i = 0; i < 30; i++) {
|
||||||
const currentClassName = (position === i) ? 'current' : '';
|
const currentClassName = position === i ? 'current' : '';
|
||||||
childrenToReturn.push(<p key={i.toString()} className={currentClassName}>{i % 10}</p>);
|
childrenToReturn.push(
|
||||||
|
<p key={i.toString()} className={currentClassName}>
|
||||||
|
{i % 10}
|
||||||
|
</p>,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return childrenToReturn;
|
return childrenToReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCurrentNumber(num: number, i: number) {
|
renderCurrentNumber(num: number, i: number) {
|
||||||
const position = this.getPositionByNum(num, i);
|
const position = this.getPositionByNum(num, i);
|
||||||
const removeTransition = this.state.animateStarted ||
|
const removeTransition =
|
||||||
(getNumberArray(this.lastCount)[i] === undefined);
|
this.state.animateStarted || getNumberArray(this.lastCount)[i] === undefined;
|
||||||
return createElement('span', {
|
return createElement(
|
||||||
|
'span',
|
||||||
|
{
|
||||||
className: `${this.props.prefixCls}-only`,
|
className: `${this.props.prefixCls}-only`,
|
||||||
style: {
|
style: {
|
||||||
transition: removeTransition ? 'none' : undefined,
|
transition: removeTransition ? 'none' : undefined,
|
||||||
@ -113,7 +126,9 @@ export default class ScrollNumber extends Component<ScrollNumberProps, ScrollNum
|
|||||||
transform: `translateY(${-position * 100}%)`,
|
transform: `translateY(${-position * 100}%)`,
|
||||||
},
|
},
|
||||||
key: i,
|
key: i,
|
||||||
}, this.renderNumberList(position));
|
},
|
||||||
|
this.renderNumberList(position),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderNumberElement() {
|
renderNumberElement() {
|
||||||
@ -122,7 +137,8 @@ export default class ScrollNumber extends Component<ScrollNumberProps, ScrollNum
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
return getNumberArray(count)
|
return getNumberArray(count)
|
||||||
.map((num, i) => this.renderCurrentNumber(num, i)).reverse();
|
.map((num, i) => this.renderCurrentNumber(num, i))
|
||||||
|
.reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -151,10 +167,6 @@ export default class ScrollNumber extends Component<ScrollNumberProps, ScrollNum
|
|||||||
className: `${prefixCls}-custom-component`,
|
className: `${prefixCls}-custom-component`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return createElement(
|
return createElement(component as any, newProps, this.renderNumberElement());
|
||||||
component as any,
|
|
||||||
newProps,
|
|
||||||
this.renderNumberElement(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,12 @@ describe('Badge', () => {
|
|||||||
|
|
||||||
it('should have an overriden title attribute', () => {
|
it('should have an overriden title attribute', () => {
|
||||||
const badge = mount(<Badge count={10} title="Custom title" />);
|
const badge = mount(<Badge count={10} title="Custom title" />);
|
||||||
expect(badge.find('.ant-scroll-number').getDOMNode().attributes.getNamedItem('title').value).toEqual('Custom title');
|
expect(
|
||||||
|
badge
|
||||||
|
.find('.ant-scroll-number')
|
||||||
|
.getDOMNode()
|
||||||
|
.attributes.getNamedItem('title').value,
|
||||||
|
).toEqual('Custom title');
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/10626
|
// https://github.com/ant-design/ant-design/issues/10626
|
||||||
@ -32,7 +37,7 @@ describe('Badge', () => {
|
|||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Tooltip title="Fix the error">
|
<Tooltip title="Fix the error">
|
||||||
<Badge status="error" />
|
<Badge status="error" />
|
||||||
</Tooltip>
|
</Tooltip>,
|
||||||
);
|
);
|
||||||
wrapper.find('Badge').simulate('mouseenter');
|
wrapper.find('Badge').simulate('mouseenter');
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
@ -59,7 +64,12 @@ describe('Badge', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be compatible with borderColor style', () => {
|
it('should be compatible with borderColor style', () => {
|
||||||
const wrapper = render(<Badge count={4} style={{ backgroundColor: '#fff', color: '#999', borderColor: '#d9d9d9' }} />);
|
const wrapper = render(
|
||||||
|
<Badge
|
||||||
|
count={4}
|
||||||
|
style={{ backgroundColor: '#fff', color: '#999', borderColor: '#d9d9d9' }}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -42,12 +42,7 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getBadgeClassName() {
|
getBadgeClassName() {
|
||||||
const {
|
const { prefixCls, className, status, children } = this.props;
|
||||||
prefixCls,
|
|
||||||
className,
|
|
||||||
status,
|
|
||||||
children,
|
|
||||||
} = this.props;
|
|
||||||
return classNames(className, prefixCls, {
|
return classNames(className, prefixCls, {
|
||||||
[`${prefixCls}-status`]: !!status,
|
[`${prefixCls}-status`]: !!status,
|
||||||
[`${prefixCls}-not-a-wrapper`]: !children,
|
[`${prefixCls}-not-a-wrapper`]: !children,
|
||||||
@ -76,7 +71,8 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
|||||||
|
|
||||||
getNumberedDispayCount() {
|
getNumberedDispayCount() {
|
||||||
const { count, overflowCount } = this.props;
|
const { count, overflowCount } = this.props;
|
||||||
const displayCount = (count as number) > (overflowCount as number) ? `${overflowCount}+` : count;
|
const displayCount =
|
||||||
|
(count as number) > (overflowCount as number) ? `${overflowCount}+` : count;
|
||||||
return displayCount as string | number | null;
|
return displayCount as string | number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,38 +90,33 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
|||||||
if (title) {
|
if (title) {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
return (typeof count === 'string' || typeof count === 'number') ? count : undefined;
|
return typeof count === 'string' || typeof count === 'number' ? count : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
getStyleWithOffset() {
|
getStyleWithOffset() {
|
||||||
const { offset, style } = this.props;
|
const { offset, style } = this.props;
|
||||||
return offset ? {
|
return offset
|
||||||
|
? {
|
||||||
right: -parseInt(offset[0] as string, 10),
|
right: -parseInt(offset[0] as string, 10),
|
||||||
marginTop: offset[1],
|
marginTop: offset[1],
|
||||||
...style,
|
...style,
|
||||||
} : style;
|
}
|
||||||
|
: style;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderStatusText() {
|
renderStatusText() {
|
||||||
const { prefixCls, text } = this.props;
|
const { prefixCls, text } = this.props;
|
||||||
const hidden = this.isHidden();
|
const hidden = this.isHidden();
|
||||||
return (hidden || !text) ? null : (
|
return hidden || !text ? null : <span className={`${prefixCls}-status-text`}>{text}</span>;
|
||||||
<span className={`${prefixCls}-status-text`}>{text}</span>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDispayComponent() {
|
renderDispayComponent() {
|
||||||
const { count } = this.props;
|
const { count } = this.props;
|
||||||
return (count && typeof count === 'object') ? (count as React.ReactElement<any>) : undefined;
|
return count && typeof count === 'object' ? (count as React.ReactElement<any>) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBadgeNumber() {
|
renderBadgeNumber() {
|
||||||
const {
|
const { count, prefixCls, scrollNumberPrefixCls, status } = this.props;
|
||||||
count,
|
|
||||||
prefixCls,
|
|
||||||
scrollNumberPrefixCls,
|
|
||||||
status,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const displayCount = this.getDispayCount();
|
const displayCount = this.getDispayCount();
|
||||||
const isDot = this.isDot();
|
const isDot = this.isDot();
|
||||||
@ -134,7 +125,8 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
|||||||
const scrollNumberCls = classNames({
|
const scrollNumberCls = classNames({
|
||||||
[`${prefixCls}-dot`]: isDot,
|
[`${prefixCls}-dot`]: isDot,
|
||||||
[`${prefixCls}-count`]: !isDot,
|
[`${prefixCls}-count`]: !isDot,
|
||||||
[`${prefixCls}-multiple-words`]: !isDot && count && count.toString && count.toString().length > 1,
|
[`${prefixCls}-multiple-words`]:
|
||||||
|
!isDot && count && count.toString && count.toString().length > 1,
|
||||||
[`${prefixCls}-status-${status}`]: !!status,
|
[`${prefixCls}-status-${status}`]: !!status,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
@badge-prefix-cls: ~"@{ant-prefix}-badge";
|
@badge-prefix-cls: ~'@{ant-prefix}-badge';
|
||||||
@number-prefix-cls: ~"@{ant-prefix}-scroll-number";
|
@number-prefix-cls: ~'@{ant-prefix}-scroll-number';
|
||||||
|
|
||||||
.@{badge-prefix-cls} {
|
.@{badge-prefix-cls} {
|
||||||
.reset-component;
|
.reset-component;
|
||||||
@ -86,7 +86,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border: 1px solid @processing-color;
|
border: 1px solid @processing-color;
|
||||||
content: "";
|
content: '';
|
||||||
animation: antStatusProcessing 1.2s infinite ease-in-out;
|
animation: antStatusProcessing 1.2s infinite ease-in-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,12 +108,12 @@
|
|||||||
|
|
||||||
&-zoom-appear,
|
&-zoom-appear,
|
||||||
&-zoom-enter {
|
&-zoom-enter {
|
||||||
animation: antZoomBadgeIn .3s @ease-out-back;
|
animation: antZoomBadgeIn 0.3s @ease-out-back;
|
||||||
animation-fill-mode: both;
|
animation-fill-mode: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-zoom-leave {
|
&-zoom-leave {
|
||||||
animation: antZoomBadgeOut .3s @ease-in-back;
|
animation: antZoomBadgeOut 0.3s @ease-in-back;
|
||||||
animation-fill-mode: both;
|
animation-fill-mode: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +147,7 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
&-only {
|
&-only {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
transition: all .3s @ease-in-out;
|
transition: all 0.3s @ease-in-out;
|
||||||
height: @badge-height;
|
height: @badge-height;
|
||||||
> p {
|
> p {
|
||||||
height: @badge-height;
|
height: @badge-height;
|
||||||
|
@ -15,7 +15,12 @@ export interface BreadcrumbProps {
|
|||||||
routes?: Route[];
|
routes?: Route[];
|
||||||
params?: any;
|
params?: any;
|
||||||
separator?: React.ReactNode;
|
separator?: React.ReactNode;
|
||||||
itemRender?: (route: any, params: any, routes: Array<any>, paths: Array<string>) => React.ReactNode;
|
itemRender?: (
|
||||||
|
route: any,
|
||||||
|
params: any,
|
||||||
|
routes: Array<any>,
|
||||||
|
paths: Array<string>,
|
||||||
|
) => React.ReactNode;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
@ -35,9 +40,7 @@ function getBreadcrumbName(route: Route, params: any) {
|
|||||||
function defaultItemRender(route: Route, params: any, routes: Route[], paths: string[]) {
|
function defaultItemRender(route: Route, params: any, routes: Route[], paths: string[]) {
|
||||||
const isLastItem = routes.indexOf(route) === routes.length - 1;
|
const isLastItem = routes.indexOf(route) === routes.length - 1;
|
||||||
const name = getBreadcrumbName(route, params);
|
const name = getBreadcrumbName(route, params);
|
||||||
return isLastItem
|
return isLastItem ? <span>{name}</span> : <a href={`#/${paths.join('/')}`}>{name}</a>;
|
||||||
? <span>{name}</span>
|
|
||||||
: <a href={`#/${paths.join('/')}`}>{name}</a>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||||
@ -69,12 +72,18 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
|||||||
render() {
|
render() {
|
||||||
let crumbs;
|
let crumbs;
|
||||||
const {
|
const {
|
||||||
separator, prefixCls, style, className, routes, params = {},
|
separator,
|
||||||
children, itemRender = defaultItemRender,
|
prefixCls,
|
||||||
|
style,
|
||||||
|
className,
|
||||||
|
routes,
|
||||||
|
params = {},
|
||||||
|
children,
|
||||||
|
itemRender = defaultItemRender,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
if (routes && routes.length > 0) {
|
if (routes && routes.length > 0) {
|
||||||
const paths: string[] = [];
|
const paths: string[] = [];
|
||||||
crumbs = routes.map((route) => {
|
crumbs = routes.map(route => {
|
||||||
route.path = route.path || '';
|
route.path = route.path || '';
|
||||||
let path: string = route.path.replace(/^\//, '');
|
let path: string = route.path.replace(/^\//, '');
|
||||||
Object.keys(params).forEach(key => {
|
Object.keys(params).forEach(key => {
|
||||||
@ -96,7 +105,7 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
|||||||
}
|
}
|
||||||
warning(
|
warning(
|
||||||
element.type && element.type.__ANT_BREADCRUMB_ITEM,
|
element.type && element.type.__ANT_BREADCRUMB_ITEM,
|
||||||
'Breadcrumb only accepts Breadcrumb.Item as it\'s children',
|
"Breadcrumb only accepts Breadcrumb.Item as it's children",
|
||||||
);
|
);
|
||||||
return cloneElement(element, {
|
return cloneElement(element, {
|
||||||
separator,
|
separator,
|
||||||
|
@ -17,10 +17,7 @@ export default class BreadcrumbItem extends React.Component<BreadcrumbItemProps,
|
|||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
prefixCls: PropTypes.string,
|
prefixCls: PropTypes.string,
|
||||||
separator: PropTypes.oneOfType([
|
separator: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
|
||||||
PropTypes.string,
|
|
||||||
PropTypes.element,
|
|
||||||
]),
|
|
||||||
href: PropTypes.string,
|
href: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -28,9 +25,17 @@ export default class BreadcrumbItem extends React.Component<BreadcrumbItemProps,
|
|||||||
const { prefixCls, separator, children, ...restProps } = this.props;
|
const { prefixCls, separator, children, ...restProps } = this.props;
|
||||||
let link;
|
let link;
|
||||||
if ('href' in this.props) {
|
if ('href' in this.props) {
|
||||||
link = <a className={`${prefixCls}-link`} {...restProps}>{children}</a>;
|
link = (
|
||||||
|
<a className={`${prefixCls}-link`} {...restProps}>
|
||||||
|
{children}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
link = <span className={`${prefixCls}-link`} {...restProps}>{children}</span>;
|
link = (
|
||||||
|
<span className={`${prefixCls}-link`} {...restProps}>
|
||||||
|
{children}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (children) {
|
if (children) {
|
||||||
return (
|
return (
|
||||||
|
@ -19,11 +19,11 @@ describe('Breadcrumb', () => {
|
|||||||
mount(
|
mount(
|
||||||
<Breadcrumb>
|
<Breadcrumb>
|
||||||
<MyCom />
|
<MyCom />
|
||||||
</Breadcrumb>
|
</Breadcrumb>,
|
||||||
);
|
);
|
||||||
expect(errorSpy.mock.calls).toHaveLength(1);
|
expect(errorSpy.mock.calls).toHaveLength(1);
|
||||||
expect(errorSpy.mock.calls[0][0]).toMatch(
|
expect(errorSpy.mock.calls[0][0]).toMatch(
|
||||||
'Breadcrumb only accepts Breadcrumb.Item as it\'s children'
|
"Breadcrumb only accepts Breadcrumb.Item as it's children",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ describe('Breadcrumb', () => {
|
|||||||
{null}
|
{null}
|
||||||
<Breadcrumb.Item>Home</Breadcrumb.Item>
|
<Breadcrumb.Item>Home</Breadcrumb.Item>
|
||||||
{undefined}
|
{undefined}
|
||||||
</Breadcrumb>
|
</Breadcrumb>,
|
||||||
);
|
);
|
||||||
expect(errorSpy).not.toHaveBeenCalled();
|
expect(errorSpy).not.toHaveBeenCalled();
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
@ -47,7 +47,7 @@ describe('Breadcrumb', () => {
|
|||||||
<Breadcrumb.Item />
|
<Breadcrumb.Item />
|
||||||
<Breadcrumb.Item>xxx</Breadcrumb.Item>
|
<Breadcrumb.Item>xxx</Breadcrumb.Item>
|
||||||
<Breadcrumb.Item>yyy</Breadcrumb.Item>
|
<Breadcrumb.Item>yyy</Breadcrumb.Item>
|
||||||
</Breadcrumb>
|
</Breadcrumb>,
|
||||||
);
|
);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import { Route, Switch, Link, withRouter, MemoryRouter } from 'react-router-dom';
|
||||||
Route, Switch, Link, withRouter, MemoryRouter,
|
|
||||||
} from 'react-router-dom';
|
|
||||||
import { mount } from 'enzyme';
|
import { mount } from 'enzyme';
|
||||||
import Breadcrumb from '../index';
|
import Breadcrumb from '../index';
|
||||||
|
|
||||||
@ -24,24 +22,22 @@ const breadcrumbNameMap = {
|
|||||||
'/apps/2/detail': 'Detail',
|
'/apps/2/detail': 'Detail',
|
||||||
};
|
};
|
||||||
|
|
||||||
const Home = withRouter((props) => {
|
const Home = withRouter(props => {
|
||||||
const { location, history } = props;
|
const { location, history } = props;
|
||||||
const pathSnippets = location.pathname.split('/').filter(i => i);
|
const pathSnippets = location.pathname.split('/').filter(i => i);
|
||||||
const extraBreadcrumbItems = pathSnippets.map((_, index) => {
|
const extraBreadcrumbItems = pathSnippets.map((_, index) => {
|
||||||
const url = `/${pathSnippets.slice(0, index + 1).join('/')}`;
|
const url = `/${pathSnippets.slice(0, index + 1).join('/')}`;
|
||||||
return (
|
return (
|
||||||
<Breadcrumb.Item key={url}>
|
<Breadcrumb.Item key={url}>
|
||||||
<Link to={url}>
|
<Link to={url}>{breadcrumbNameMap[url]}</Link>
|
||||||
{breadcrumbNameMap[url]}
|
|
||||||
</Link>
|
|
||||||
</Breadcrumb.Item>
|
</Breadcrumb.Item>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
const breadcrumbItems = [(
|
const breadcrumbItems = [
|
||||||
<Breadcrumb.Item key="home">
|
<Breadcrumb.Item key="home">
|
||||||
<Link to="/">Home</Link>
|
<Link to="/">Home</Link>
|
||||||
</Breadcrumb.Item>
|
</Breadcrumb.Item>,
|
||||||
)].concat(extraBreadcrumbItems);
|
].concat(extraBreadcrumbItems);
|
||||||
return (
|
return (
|
||||||
<div className="demo">
|
<div className="demo">
|
||||||
<div className="demo-nav">
|
<div className="demo-nav">
|
||||||
@ -52,9 +48,7 @@ const Home = withRouter((props) => {
|
|||||||
<Route path="/apps" component={Apps} />
|
<Route path="/apps" component={Apps} />
|
||||||
<Route render={() => <span>Home Page</span>} />
|
<Route render={() => <span>Home Page</span>} />
|
||||||
</Switch>
|
</Switch>
|
||||||
<Breadcrumb>
|
<Breadcrumb>{breadcrumbItems}</Breadcrumb>
|
||||||
{breadcrumbItems}
|
|
||||||
</Breadcrumb>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -72,17 +66,31 @@ describe('react router', () => {
|
|||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<MemoryRouter initialEntries={['/']} initialIndex={0}>
|
<MemoryRouter initialEntries={['/']} initialIndex={0}>
|
||||||
<Home />
|
<Home />
|
||||||
</MemoryRouter>
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
expect(wrapper.find('BreadcrumbItem').length).toBe(1);
|
expect(wrapper.find('BreadcrumbItem').length).toBe(1);
|
||||||
expect(wrapper.find('BreadcrumbItem .ant-breadcrumb-link').at(0).text()).toBe('Home');
|
expect(
|
||||||
wrapper.find('.demo-nav a').at(1).simulate('click');
|
wrapper
|
||||||
|
.find('BreadcrumbItem .ant-breadcrumb-link')
|
||||||
|
.at(0)
|
||||||
|
.text(),
|
||||||
|
).toBe('Home');
|
||||||
|
wrapper
|
||||||
|
.find('.demo-nav a')
|
||||||
|
.at(1)
|
||||||
|
.simulate('click');
|
||||||
expect(wrapper.find('BreadcrumbItem').length).toBe(2);
|
expect(wrapper.find('BreadcrumbItem').length).toBe(2);
|
||||||
expect(wrapper.find('BreadcrumbItem .ant-breadcrumb-link').at(1).text()).toBe('Application List');
|
expect(
|
||||||
|
wrapper
|
||||||
|
.find('BreadcrumbItem .ant-breadcrumb-link')
|
||||||
|
.at(1)
|
||||||
|
.text(),
|
||||||
|
).toBe('Application List');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('react router 3', () => {
|
it('react router 3', () => {
|
||||||
const routes = [{
|
const routes = [
|
||||||
|
{
|
||||||
name: 'home',
|
name: 'home',
|
||||||
breadcrumbName: 'Home',
|
breadcrumbName: 'Home',
|
||||||
path: '/',
|
path: '/',
|
||||||
@ -143,10 +151,9 @@ describe('react router', () => {
|
|||||||
name: 'detail',
|
name: 'detail',
|
||||||
breadcrumbName: 'Detail',
|
breadcrumbName: 'Detail',
|
||||||
path: 'detail',
|
path: 'detail',
|
||||||
}];
|
},
|
||||||
const wrapper = mount(
|
];
|
||||||
<Breadcrumb routes={routes} params={{ id: 1 }} />
|
const wrapper = mount(<Breadcrumb routes={routes} params={{ id: 1 }} />);
|
||||||
);
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
@breadcrumb-prefix-cls: ~"@{ant-prefix}-breadcrumb";
|
@breadcrumb-prefix-cls: ~'@{ant-prefix}-breadcrumb';
|
||||||
|
|
||||||
.@{breadcrumb-prefix-cls} {
|
.@{breadcrumb-prefix-cls} {
|
||||||
.reset-component;
|
.reset-component;
|
||||||
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
a {
|
a {
|
||||||
color: @breadcrumb-link-color;
|
color: @breadcrumb-link-color;
|
||||||
transition: color .3s;
|
transition: color 0.3s;
|
||||||
&:hover {
|
&:hover {
|
||||||
color: @breadcrumb-link-color-hover;
|
color: @breadcrumb-link-color-hover;
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,7 @@ import Icon from '../../icon';
|
|||||||
|
|
||||||
describe('Button', () => {
|
describe('Button', () => {
|
||||||
it('renders correctly', () => {
|
it('renders correctly', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(<Button>Follow</Button>);
|
||||||
<Button>Follow</Button>
|
|
||||||
);
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -20,41 +18,40 @@ describe('Button', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('renders Chinese characters correctly', () => {
|
it('renders Chinese characters correctly', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(<Button>按钮</Button>);
|
||||||
<Button>按钮</Button>
|
|
||||||
);
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
// should not insert space when there is icon
|
// should not insert space when there is icon
|
||||||
const wrapper1 = render(
|
const wrapper1 = render(<Button icon="search">按钮</Button>);
|
||||||
<Button icon="search">按钮</Button>
|
|
||||||
);
|
|
||||||
expect(wrapper1).toMatchSnapshot();
|
expect(wrapper1).toMatchSnapshot();
|
||||||
// should not insert space when there is icon
|
// should not insert space when there is icon
|
||||||
const wrapper2 = render(
|
const wrapper2 = render(
|
||||||
<Button><Icon type="search" />按钮</Button>
|
<Button>
|
||||||
|
<Icon type="search" />
|
||||||
|
按钮
|
||||||
|
</Button>,
|
||||||
);
|
);
|
||||||
expect(wrapper2).toMatchSnapshot();
|
expect(wrapper2).toMatchSnapshot();
|
||||||
// should not insert space when there is icon
|
// should not insert space when there is icon
|
||||||
const wrapper3 = render(
|
const wrapper3 = render(<Button icon="search">按钮</Button>);
|
||||||
<Button icon="search">按钮</Button>
|
|
||||||
);
|
|
||||||
expect(wrapper3).toMatchSnapshot();
|
expect(wrapper3).toMatchSnapshot();
|
||||||
// should not insert space when there is icon while loading
|
// should not insert space when there is icon while loading
|
||||||
const wrapper4 = render(
|
const wrapper4 = render(
|
||||||
<Button icon="search" loading>按钮</Button>
|
<Button icon="search" loading>
|
||||||
|
按钮
|
||||||
|
</Button>,
|
||||||
);
|
);
|
||||||
expect(wrapper4).toMatchSnapshot();
|
expect(wrapper4).toMatchSnapshot();
|
||||||
// should insert space while loading
|
// should insert space while loading
|
||||||
const wrapper5 = render(
|
const wrapper5 = render(<Button loading>按钮</Button>);
|
||||||
<Button loading>按钮</Button>
|
|
||||||
);
|
|
||||||
expect(wrapper5).toMatchSnapshot();
|
expect(wrapper5).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders Chinese characters correctly in HOC', () => {
|
it('renders Chinese characters correctly in HOC', () => {
|
||||||
const Text = ({ children }) => <span>{children}</span>;
|
const Text = ({ children }) => <span>{children}</span>;
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Button><Text>按钮</Text></Button>
|
<Button>
|
||||||
|
<Text>按钮</Text>
|
||||||
|
</Button>,
|
||||||
);
|
);
|
||||||
expect(wrapper.find('.ant-btn').hasClass('ant-btn-two-chinese-chars')).toBe(true);
|
expect(wrapper.find('.ant-btn').hasClass('ant-btn-two-chinese-chars')).toBe(true);
|
||||||
wrapper.setProps({
|
wrapper.setProps({
|
||||||
@ -70,9 +67,7 @@ describe('Button', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('have static property for type detecting', () => {
|
it('have static property for type detecting', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Button>Button Text</Button>);
|
||||||
<Button>Button Text</Button>
|
|
||||||
);
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
expect(wrapper.type().__ANT_BUTTON).toBe(true);
|
expect(wrapper.type().__ANT_BUTTON).toBe(true);
|
||||||
});
|
});
|
||||||
@ -85,16 +80,18 @@ describe('Button', () => {
|
|||||||
|
|
||||||
enterLoading = () => {
|
enterLoading = () => {
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { loading } = this.state;
|
const { loading } = this.state;
|
||||||
return <Button loading={loading} onClick={this.enterLoading}>Button</Button>;
|
return (
|
||||||
}
|
<Button loading={loading} onClick={this.enterLoading}>
|
||||||
}
|
Button
|
||||||
const wrapper = mount(
|
</Button>
|
||||||
<DefaultButton />
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const wrapper = mount(<DefaultButton />);
|
||||||
wrapper.simulate('click');
|
wrapper.simulate('click');
|
||||||
expect(wrapper.find('.ant-btn-loading').length).toBe(1);
|
expect(wrapper.find('.ant-btn-loading').length).toBe(1);
|
||||||
});
|
});
|
||||||
@ -108,54 +105,55 @@ describe('Button', () => {
|
|||||||
|
|
||||||
enterLoading = () => {
|
enterLoading = () => {
|
||||||
this.setState({ loading: { delay: 1000 } });
|
this.setState({ loading: { delay: 1000 } });
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { loading } = this.state;
|
const { loading } = this.state;
|
||||||
return <Button loading={loading} onClick={this.enterLoading}>Button</Button>;
|
return (
|
||||||
}
|
<Button loading={loading} onClick={this.enterLoading}>
|
||||||
}
|
Button
|
||||||
const wrapper = mount(
|
</Button>
|
||||||
<DefaultButton />
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const wrapper = mount(<DefaultButton />);
|
||||||
wrapper.simulate('click');
|
wrapper.simulate('click');
|
||||||
expect(wrapper.hasClass('ant-btn-loading')).toBe(false);
|
expect(wrapper.hasClass('ant-btn-loading')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support link button', () => {
|
it('should support link button', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Button target="_blank" href="http://ant.design">link button</Button>
|
<Button target="_blank" href="http://ant.design">
|
||||||
|
link button
|
||||||
|
</Button>,
|
||||||
);
|
);
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(wrapper.render()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fixbug renders {0} , 0 and {false}', () => {
|
it('fixbug renders {0} , 0 and {false}', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(<Button>{0}</Button>);
|
||||||
<Button>{0}</Button>
|
|
||||||
);
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
const wrapper1 = render(
|
const wrapper1 = render(<Button>0</Button>);
|
||||||
<Button>0</Button>
|
|
||||||
);
|
|
||||||
expect(wrapper1).toMatchSnapshot();
|
expect(wrapper1).toMatchSnapshot();
|
||||||
const wrapper2 = render(
|
const wrapper2 = render(<Button>{false}</Button>);
|
||||||
<Button>{false}</Button>
|
|
||||||
);
|
|
||||||
expect(wrapper2).toMatchSnapshot();
|
expect(wrapper2).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should has click wave effect', async () => {
|
it('should has click wave effect', async () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Button type="primary">button</Button>);
|
||||||
<Button type="primary">button</Button>
|
wrapper
|
||||||
);
|
.find('.ant-btn')
|
||||||
wrapper.find('.ant-btn').getDOMNode().click();
|
.getDOMNode()
|
||||||
|
.click();
|
||||||
await new Promise(resolve => setTimeout(resolve, 0));
|
await new Promise(resolve => setTimeout(resolve, 0));
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(wrapper.render()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not render as link button when href is undefined', async () => {
|
it('should not render as link button when href is undefined', async () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Button type="primary" href={undefined}>button</Button>
|
<Button type="primary" href={undefined}>
|
||||||
|
button
|
||||||
|
</Button>,
|
||||||
);
|
);
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(wrapper.render()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,7 @@ export interface ButtonGroupProps {
|
|||||||
prefixCls?: string;
|
prefixCls?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ButtonGroup: React.SFC<ButtonGroupProps> = (props) => {
|
const ButtonGroup: React.SFC<ButtonGroupProps> = props => {
|
||||||
const { prefixCls = 'ant-btn-group', size, className, ...others } = props;
|
const { prefixCls = 'ant-btn-group', size, className, ...others } = props;
|
||||||
|
|
||||||
// large => lg
|
// large => lg
|
||||||
@ -25,9 +25,13 @@ const ButtonGroup: React.SFC<ButtonGroupProps> = (props) => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const classes = classNames(prefixCls, {
|
const classes = classNames(
|
||||||
|
prefixCls,
|
||||||
|
{
|
||||||
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
||||||
}, className);
|
},
|
||||||
|
className,
|
||||||
|
);
|
||||||
|
|
||||||
return <div {...others} className={classes} />;
|
return <div {...others} className={classes} />;
|
||||||
};
|
};
|
||||||
|
@ -19,10 +19,13 @@ function insertSpace(child: React.ReactChild, needInserted: boolean) {
|
|||||||
}
|
}
|
||||||
const SPACE = needInserted ? ' ' : '';
|
const SPACE = needInserted ? ' ' : '';
|
||||||
// strictNullChecks oops.
|
// strictNullChecks oops.
|
||||||
if (typeof child !== 'string' && typeof child !== 'number' &&
|
if (
|
||||||
isString(child.type) && isTwoCNChar(child.props.children)) {
|
typeof child !== 'string' &&
|
||||||
return React.cloneElement(child, {},
|
typeof child !== 'number' &&
|
||||||
child.props.children.split('').join(SPACE));
|
isString(child.type) &&
|
||||||
|
isTwoCNChar(child.props.children)
|
||||||
|
) {
|
||||||
|
return React.cloneElement(child, {}, child.props.children.split('').join(SPACE));
|
||||||
}
|
}
|
||||||
if (typeof child === 'string') {
|
if (typeof child === 'string') {
|
||||||
if (isTwoCNChar(child)) {
|
if (isTwoCNChar(child)) {
|
||||||
@ -55,12 +58,14 @@ export type AnchorButtonProps = {
|
|||||||
href: string;
|
href: string;
|
||||||
target?: string;
|
target?: string;
|
||||||
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
|
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
|
||||||
} & BaseButtonProps & React.AnchorHTMLAttributes<HTMLAnchorElement>;
|
} & BaseButtonProps &
|
||||||
|
React.AnchorHTMLAttributes<HTMLAnchorElement>;
|
||||||
|
|
||||||
export type NativeButtonProps = {
|
export type NativeButtonProps = {
|
||||||
htmlType?: ButtonHTMLType;
|
htmlType?: ButtonHTMLType;
|
||||||
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
} & BaseButtonProps & React.ButtonHTMLAttributes<HTMLButtonElement>;
|
} & BaseButtonProps &
|
||||||
|
React.ButtonHTMLAttributes<HTMLButtonElement>;
|
||||||
|
|
||||||
export type ButtonProps = AnchorButtonProps | NativeButtonProps;
|
export type ButtonProps = AnchorButtonProps | NativeButtonProps;
|
||||||
|
|
||||||
@ -129,7 +134,7 @@ export default class Button extends React.Component<ButtonProps, any> {
|
|||||||
|
|
||||||
saveButtonRef = (node: HTMLElement | null) => {
|
saveButtonRef = (node: HTMLElement | null) => {
|
||||||
this.buttonNode = node;
|
this.buttonNode = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
fixTwoCNChar() {
|
fixTwoCNChar() {
|
||||||
// Fix for HOC usage like <FormatMessage />
|
// Fix for HOC usage like <FormatMessage />
|
||||||
@ -159,7 +164,7 @@ export default class Button extends React.Component<ButtonProps, any> {
|
|||||||
if (onClick) {
|
if (onClick) {
|
||||||
(onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)(e);
|
(onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)(e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
isNeedInserted() {
|
isNeedInserted() {
|
||||||
const { icon, children } = this.props;
|
const { icon, children } = this.props;
|
||||||
@ -168,7 +173,17 @@ export default class Button extends React.Component<ButtonProps, any> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
type, shape, size, className, children, icon, prefixCls, ghost, loading: _loadingProp, block, ...rest
|
type,
|
||||||
|
shape,
|
||||||
|
size,
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
icon,
|
||||||
|
prefixCls,
|
||||||
|
ghost,
|
||||||
|
loading: _loadingProp,
|
||||||
|
block,
|
||||||
|
...rest
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const { loading, hasTwoCNChar } = this.state;
|
const { loading, hasTwoCNChar } = this.state;
|
||||||
@ -202,8 +217,10 @@ export default class Button extends React.Component<ButtonProps, any> {
|
|||||||
|
|
||||||
const iconType = loading ? 'loading' : icon;
|
const iconType = loading ? 'loading' : icon;
|
||||||
const iconNode = iconType ? <Icon type={iconType} /> : null;
|
const iconNode = iconType ? <Icon type={iconType} /> : null;
|
||||||
const kids = (children || children === 0)
|
const kids =
|
||||||
? React.Children.map(children, child => insertSpace(child, this.isNeedInserted())) : null;
|
children || children === 0
|
||||||
|
? React.Children.map(children, child => insertSpace(child, this.isNeedInserted()))
|
||||||
|
: null;
|
||||||
|
|
||||||
const title = isChristmas ? 'Ho Ho Ho!' : rest.title;
|
const title = isChristmas ? 'Ho Ho Ho!' : rest.title;
|
||||||
|
|
||||||
@ -217,7 +234,8 @@ export default class Button extends React.Component<ButtonProps, any> {
|
|||||||
title={title}
|
title={title}
|
||||||
ref={this.saveButtonRef}
|
ref={this.saveButtonRef}
|
||||||
>
|
>
|
||||||
{iconNode}{kids}
|
{iconNode}
|
||||||
|
{kids}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -228,14 +246,15 @@ export default class Button extends React.Component<ButtonProps, any> {
|
|||||||
return (
|
return (
|
||||||
<Wave>
|
<Wave>
|
||||||
<button
|
<button
|
||||||
{...(otherProps as NativeButtonProps)}
|
{...otherProps as NativeButtonProps}
|
||||||
type={htmlType || 'button'}
|
type={htmlType || 'button'}
|
||||||
className={classes}
|
className={classes}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
title={title}
|
title={title}
|
||||||
ref={this.saveButtonRef}
|
ref={this.saveButtonRef}
|
||||||
>
|
>
|
||||||
{iconNode}{kids}
|
{iconNode}
|
||||||
|
{kids}
|
||||||
</button>
|
</button>
|
||||||
</Wave>
|
</Wave>
|
||||||
);
|
);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
@import "./mixin";
|
@import './mixin';
|
||||||
|
|
||||||
@btn-prefix-cls: ~"@{ant-prefix}-btn";
|
@btn-prefix-cls: ~'@{ant-prefix}-btn';
|
||||||
|
|
||||||
// for compatible
|
// for compatible
|
||||||
@btn-ghost-color: @text-color;
|
@btn-ghost-color: @text-color;
|
||||||
@ -82,16 +82,16 @@
|
|||||||
right: -1px;
|
right: -1px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
opacity: 0.35;
|
opacity: 0.35;
|
||||||
content: "";
|
content: '';
|
||||||
border-radius: inherit;
|
border-radius: inherit;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
transition: opacity .2s;
|
transition: opacity 0.2s;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.@{iconfont-css-prefix} {
|
.@{iconfont-css-prefix} {
|
||||||
transition: margin-left .3s @ease-in-out;
|
transition: margin-left 0.3s @ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
&&-loading:before {
|
&&-loading:before {
|
||||||
@ -150,12 +150,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-two-chinese-chars:first-letter {
|
&-two-chinese-chars:first-letter {
|
||||||
letter-spacing: .34em;
|
letter-spacing: 0.34em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-two-chinese-chars > *:not(.@{iconfont-css-prefix}) {
|
&-two-chinese-chars > *:not(.@{iconfont-css-prefix}) {
|
||||||
letter-spacing: .34em;
|
letter-spacing: 0.34em;
|
||||||
margin-right: -.34em;
|
margin-right: -0.34em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-block {
|
&-block {
|
||||||
@ -163,13 +163,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.christmas&-primary:before {
|
.christmas&-primary:before {
|
||||||
content: "";
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -6px;
|
top: -6px;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE0AAAAXCAYAAABOHMIhAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABiZJREFUeNrsWMtPlFcUvzPMwIDysLyRR4uATDHWCiVgSmRlios2DeiiXUFs0nRBd6arxqQhJDapkYXhP4BqDKTQhZaFNQSCaBEVJjwdHsNr5DUMDDPDzPT3u7nTDEgRKrKgc5KT+z3uufec33de99P4fD4RpL2RNgjB3kn35MkTeRERESFiYmLkGBoaKnQ6nWSNRvPPZFxr+vv7k6KioiIdDsfa8vLyQkFBgcP3Bnel3MDAQArWI0eFhISE87nb7bZ7PJ4VvLYuLi5O5+fnu9+kMNfq6+tLjIyMzMY6KeBEbK/XarXReI3lPDZMWcc4v7GxYV1dXR3Jy8ub2E5HPvJ6vRSSDH0ku1wuAfsEZOV1IEFHoeNFdHS0yMrK2knR0Lm5uR+hxLdQMjbwHTZbB41h8RGwCdc9MzMzneHh4bGJiYlf4SN8ijkfwqiIncCAAR7Iz2GPSShudjqdfeCeqampvwBQfFxc3JdYqwTv8gB8/F48A8BgKecE14V+L7ju2tpae05OzkuCCZvkPOj8mizmC6vVKtmPu+bx48cC3qI1mUyFUOyywWD4SHlELBaLJmCHNcwAghuAOujtuF4FqHO4nsX4EsAS3I4TJ04ME1h8PDE9PS09TYZoY2Pj1729vd6lpSVfkDYTPG0UkfNDRUWFgQ5Gb2Mh0N29e9eG/GQfHh4W8/PzwUy/ObQ/gMfVVlZW1iAiZdQxp3nv3LljRoL/5erVq1UIxzSiiVD9X4EDYATynCwAzGO858hCQRoaGmJFZNJz8YIcBc4BF966dau6sLAwBxVSJCUlCSThQwuU3W6XkYUok1Vzm5znQx5bbm9v77p+/frPeNSNRzZ/ISBwrG4ZR48eLamtrf2+uLjYSEG9Xi/wTISFhQlWGXohyzO/CJlVl23KQRLbABoaHx+/Z1lUZ/Hq1SsJFj3JT3hmHx8fnydPTEzMj46OziHPW2w22wxeD4Kfgadh/4YEzU8Az4DhffAn5eXlX1y6dKkEoCTspAQ9Mjs7+0BBo8Fms1lkZGTsOo0QLLRNkvnR+fEJzIMHD0xtbW39CL8JTFtSbAOvBIyLHIGVm9VzE2gKuDAMSSpcT6KXyT137lx2cnLyMXhcGDb3wq3XuWF3d/fCzZs3P0c4v5eSknJQbYLo7Ox0gC2lpaVZ3Be67Th/dnZWoAJKsJC3XA8fPhxoamp6hMb+BaaMgWcUMGtszZjiFDNmvcDI91pzG0iY4ARwkwrxkcHBwUdgNrRMbnrqoRbkVzDcvn3bl5qaWsmcgFH4G8XdEGUWFhak51AuISFBnkoCTyFbyWKxCJwIxlC0fq2rq7tcVFRkRKskjh8/Lr0+kBjCCDV/knfdv3//WX19/R8IRRNemxlu4AXwKqM+EJwdj1HbPYSwh3sCPAJDABm2LLchCjS+5/kirKGhwWk0GrMuXrxYQuX9hm/XXTMXMY+srKwI5ApZrbYmZh7deEJhAUKjLe/pLTzSsCuHrK+1tbUJVe3P6upq87Vr174rKysrYHVj/uW+OH3IfEuw4F3ee/fuPQfAvwOs5yyE4CnlFOu7BWrTCWlreO6FACpBZGwUw4BvkANLobReHb3kGZYGsGzTq/zlO8AT1ru6uoZbWlqeA6gINJAfnz59OlVLoX8Jtebm5raampqfcMvQYgTknz9//sKVK1c+y83NTdIEuCnaKMuNGzd+6+np6cCtSTkAw9D9X8Dyh+dbgaaAC1XAnUlPTy+qqqq6cPbs2UzkmWjNljiDJzpwHFnCkW2yo6NjCKW8H54wjlezKvRT09LSTsJrz5w6dSoN+Yp51ADAPUj8VoDbDq9pxrwuJcNIYQllJTIi/xopBw/VA7DJp0+f9hA78CgL5F5C8J2CpoCj8sfA6WCe/FPRhsRlZmbGIs8Y4FFO5CJgtrSsvrRVGW1V93b1myoGnKAKEcHgnwsWpg1lNI0fphwrmdqbckeU18WrnlOjqp5/j7W3BWvfQVPKa5SBkcrYCNVB65TRTlWZ1lXiXVU5xbtlDb2SPaLWYwrgHIcqPg6Vc7fbX69Yoyqfa7/AeiegbWOEVhmsVcWDwPn224iDJgla8Hd38Hd3ELQgaIeI/hZgAIPEp0vmQJdoAAAAAElFTkSuQmCC) no-repeat 50% 0;
|
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE0AAAAXCAYAAABOHMIhAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABiZJREFUeNrsWMtPlFcUvzPMwIDysLyRR4uATDHWCiVgSmRlios2DeiiXUFs0nRBd6arxqQhJDapkYXhP4BqDKTQhZaFNQSCaBEVJjwdHsNr5DUMDDPDzPT3u7nTDEgRKrKgc5KT+z3uufec33de99P4fD4RpL2RNgjB3kn35MkTeRERESFiYmLkGBoaKnQ6nWSNRvPPZFxr+vv7k6KioiIdDsfa8vLyQkFBgcP3Bnel3MDAQArWI0eFhISE87nb7bZ7PJ4VvLYuLi5O5+fnu9+kMNfq6+tLjIyMzMY6KeBEbK/XarXReI3lPDZMWcc4v7GxYV1dXR3Jy8ub2E5HPvJ6vRSSDH0ku1wuAfsEZOV1IEFHoeNFdHS0yMrK2knR0Lm5uR+hxLdQMjbwHTZbB41h8RGwCdc9MzMzneHh4bGJiYlf4SN8ijkfwqiIncCAAR7Iz2GPSShudjqdfeCeqampvwBQfFxc3JdYqwTv8gB8/F48A8BgKecE14V+L7ju2tpae05OzkuCCZvkPOj8mizmC6vVKtmPu+bx48cC3qI1mUyFUOyywWD4SHlELBaLJmCHNcwAghuAOujtuF4FqHO4nsX4EsAS3I4TJ04ME1h8PDE9PS09TYZoY2Pj1729vd6lpSVfkDYTPG0UkfNDRUWFgQ5Gb2Mh0N29e9eG/GQfHh4W8/PzwUy/ObQ/gMfVVlZW1iAiZdQxp3nv3LljRoL/5erVq1UIxzSiiVD9X4EDYATynCwAzGO858hCQRoaGmJFZNJz8YIcBc4BF966dau6sLAwBxVSJCUlCSThQwuU3W6XkYUok1Vzm5znQx5bbm9v77p+/frPeNSNRzZ/ISBwrG4ZR48eLamtrf2+uLjYSEG9Xi/wTISFhQlWGXohyzO/CJlVl23KQRLbABoaHx+/Z1lUZ/Hq1SsJFj3JT3hmHx8fnydPTEzMj46OziHPW2w22wxeD4Kfgadh/4YEzU8Az4DhffAn5eXlX1y6dKkEoCTspAQ9Mjs7+0BBo8Fms1lkZGTsOo0QLLRNkvnR+fEJzIMHD0xtbW39CL8JTFtSbAOvBIyLHIGVm9VzE2gKuDAMSSpcT6KXyT137lx2cnLyMXhcGDb3wq3XuWF3d/fCzZs3P0c4v5eSknJQbYLo7Ox0gC2lpaVZ3Be67Th/dnZWoAJKsJC3XA8fPhxoamp6hMb+BaaMgWcUMGtszZjiFDNmvcDI91pzG0iY4ARwkwrxkcHBwUdgNrRMbnrqoRbkVzDcvn3bl5qaWsmcgFH4G8XdEGUWFhak51AuISFBnkoCTyFbyWKxCJwIxlC0fq2rq7tcVFRkRKskjh8/Lr0+kBjCCDV/knfdv3//WX19/R8IRRNemxlu4AXwKqM+EJwdj1HbPYSwh3sCPAJDABm2LLchCjS+5/kirKGhwWk0GrMuXrxYQuX9hm/XXTMXMY+srKwI5ApZrbYmZh7deEJhAUKjLe/pLTzSsCuHrK+1tbUJVe3P6upq87Vr174rKysrYHVj/uW+OH3IfEuw4F3ee/fuPQfAvwOs5yyE4CnlFOu7BWrTCWlreO6FACpBZGwUw4BvkANLobReHb3kGZYGsGzTq/zlO8AT1ru6uoZbWlqeA6gINJAfnz59OlVLoX8Jtebm5raampqfcMvQYgTknz9//sKVK1c+y83NTdIEuCnaKMuNGzd+6+np6cCtSTkAw9D9X8Dyh+dbgaaAC1XAnUlPTy+qqqq6cPbs2UzkmWjNljiDJzpwHFnCkW2yo6NjCKW8H54wjlezKvRT09LSTsJrz5w6dSoN+Yp51ADAPUj8VoDbDq9pxrwuJcNIYQllJTIi/xopBw/VA7DJp0+f9hA78CgL5F5C8J2CpoCj8sfA6WCe/FPRhsRlZmbGIs8Y4FFO5CJgtrSsvrRVGW1V93b1myoGnKAKEcHgnwsWpg1lNI0fphwrmdqbckeU18WrnlOjqp5/j7W3BWvfQVPKa5SBkcrYCNVB65TRTlWZ1lXiXVU5xbtlDb2SPaLWYwrgHIcqPg6Vc7fbX69Yoyqfa7/AeiegbWOEVhmsVcWDwPn224iDJgla8Hd38Hd3ELQgaIeI/hZgAIPEp0vmQJdoAAAAAElFTkSuQmCC)
|
||||||
|
no-repeat 50% 0;
|
||||||
background-size: 64px;
|
background-size: 64px;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
@ -24,17 +24,21 @@
|
|||||||
|
|
||||||
.button-variant-primary(@color; @background) {
|
.button-variant-primary(@color; @background) {
|
||||||
.button-color(@color; @background; @background);
|
.button-color(@color; @background; @background);
|
||||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, .12);
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12);
|
||||||
box-shadow: 0 2px 0 rgba(0, 0, 0, .045);
|
box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045);
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
.button-color(@color; ~`colorPalette("@{background}", 5)`; ~`colorPalette("@{background}", 5)`);
|
.button-color(
|
||||||
|
@color; ~`colorPalette('@{background}', 5) `; ~`colorPalette('@{background}', 5) `
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active,
|
&:active,
|
||||||
&.active {
|
&.active {
|
||||||
.button-color(@color; ~`colorPalette("@{background}", 7)`; ~`colorPalette("@{background}", 7)`);
|
.button-color(
|
||||||
|
@color; ~`colorPalette('@{background}', 7) `; ~`colorPalette('@{background}', 7) `
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-disabled();
|
.button-disabled();
|
||||||
@ -60,16 +64,20 @@
|
|||||||
.button-color(@color; @background; @border);
|
.button-color(@color; @background; @border);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.button-color(@btn-primary-color; ~`colorPalette("@{color}", 5)`; ~`colorPalette("@{color}", 5)`);
|
.button-color(
|
||||||
|
@btn-primary-color; ~`colorPalette('@{color}', 5) `; ~`colorPalette('@{color}', 5) `
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
.button-color(~`colorPalette("@{color}", 5)`; #fff; ~`colorPalette("@{color}", 5)`);
|
.button-color(~`colorPalette('@{color}', 5) `; #fff; ~`colorPalette('@{color}', 5) `);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active,
|
&:active,
|
||||||
&.active {
|
&.active {
|
||||||
.button-color(@btn-primary-color; ~`colorPalette("@{color}", 7)`; ~`colorPalette("@{color}", 7)`);
|
.button-color(
|
||||||
|
@btn-primary-color; ~`colorPalette('@{color}', 7) `; ~`colorPalette('@{color}', 7) `
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-disabled();
|
.button-disabled();
|
||||||
@ -81,12 +89,12 @@
|
|||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
.button-color(~`colorPalette("@{color}", 5)`; transparent; ~`colorPalette("@{color}", 5)`);
|
.button-color(~`colorPalette('@{color}', 5) `; transparent; ~`colorPalette('@{color}', 5) `);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active,
|
&:active,
|
||||||
&.active {
|
&.active {
|
||||||
.button-color(~`colorPalette("@{color}", 7)`; transparent; ~`colorPalette("@{color}", 7)`);
|
.button-color(~`colorPalette('@{color}', 7) `; transparent; ~`colorPalette('@{color}', 7) `);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-disabled();
|
.button-disabled();
|
||||||
@ -101,7 +109,7 @@
|
|||||||
> a:only-child {
|
> a:only-child {
|
||||||
color: currentColor;
|
color: currentColor;
|
||||||
&:after {
|
&:after {
|
||||||
content: "";
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@ -161,9 +169,9 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
.button-size(@btn-height-base; @btn-padding-base; @font-size-base; @btn-border-radius-base);
|
.button-size(@btn-height-base; @btn-padding-base; @font-size-base; @btn-border-radius-base);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
transition: all .3s @ease-in-out;
|
transition: all 0.3s @ease-in-out;
|
||||||
position: relative;
|
position: relative;
|
||||||
box-shadow: 0 2px 0 rgba(0, 0, 0, .015);
|
box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
|
||||||
|
|
||||||
> .@{iconfont-css-prefix} {
|
> .@{iconfont-css-prefix} {
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
|
@ -125,7 +125,7 @@ export default class Header extends React.Component<HeaderProps, any> {
|
|||||||
if (onValueChange) {
|
if (onValueChange) {
|
||||||
onValueChange(newValue);
|
onValueChange(newValue);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
onMonthChange = (month: string) => {
|
onMonthChange = (month: string) => {
|
||||||
const newValue = this.props.value.clone();
|
const newValue = this.props.value.clone();
|
||||||
@ -134,24 +134,26 @@ export default class Header extends React.Component<HeaderProps, any> {
|
|||||||
if (onValueChange) {
|
if (onValueChange) {
|
||||||
onValueChange(newValue);
|
onValueChange(newValue);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
onTypeChange = (e: RadioChangeEvent) => {
|
onTypeChange = (e: RadioChangeEvent) => {
|
||||||
const onTypeChange = this.props.onTypeChange;
|
const onTypeChange = this.props.onTypeChange;
|
||||||
if (onTypeChange) {
|
if (onTypeChange) {
|
||||||
onTypeChange(e.target.value);
|
onTypeChange(e.target.value);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
getCalenderHeaderNode = (node: HTMLDivElement) => {
|
getCalenderHeaderNode = (node: HTMLDivElement) => {
|
||||||
this.calenderHeaderNode = node;
|
this.calenderHeaderNode = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { type, value, prefixCls, locale, fullscreen } = this.props;
|
const { type, value, prefixCls, locale, fullscreen } = this.props;
|
||||||
const yearSelect = this.getYearSelectElement(value.year());
|
const yearSelect = this.getYearSelectElement(value.year());
|
||||||
const monthSelect = type === 'date' ?
|
const monthSelect =
|
||||||
this.getMonthSelectElement(value.month(), this.getMonthsLocale(value)) : null;
|
type === 'date'
|
||||||
|
? this.getMonthSelectElement(value.month(), this.getMonthsLocale(value))
|
||||||
|
: null;
|
||||||
const size = (fullscreen ? 'default' : 'small') as any;
|
const size = (fullscreen ? 'default' : 'small') as any;
|
||||||
const typeSwitch = (
|
const typeSwitch = (
|
||||||
<Group onChange={this.onTypeChange} value={type} size={size}>
|
<Group onChange={this.onTypeChange} value={type} size={size}>
|
||||||
|
@ -7,10 +7,11 @@ import Calendar from '..';
|
|||||||
describe('Calendar', () => {
|
describe('Calendar', () => {
|
||||||
it('Calendar should be selectable', () => {
|
it('Calendar should be selectable', () => {
|
||||||
const onSelect = jest.fn();
|
const onSelect = jest.fn();
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Calendar onSelect={onSelect} />);
|
||||||
<Calendar onSelect={onSelect} />
|
wrapper
|
||||||
);
|
.find('.ant-fullcalendar-cell')
|
||||||
wrapper.find('.ant-fullcalendar-cell').at(0).simulate('click');
|
.at(0)
|
||||||
|
.simulate('click');
|
||||||
expect(onSelect).toBeCalledWith(expect.anything());
|
expect(onSelect).toBeCalledWith(expect.anything());
|
||||||
const value = onSelect.mock.calls[0][0];
|
const value = onSelect.mock.calls[0][0];
|
||||||
expect(Moment.isMoment(value)).toBe(true);
|
expect(Moment.isMoment(value)).toBe(true);
|
||||||
@ -20,10 +21,16 @@ describe('Calendar', () => {
|
|||||||
const onSelect = jest.fn();
|
const onSelect = jest.fn();
|
||||||
const validRange = [Moment('2018-02-02'), Moment('2018-02-18')];
|
const validRange = [Moment('2018-02-02'), Moment('2018-02-18')];
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Calendar onSelect={onSelect} validRange={validRange} defaultValue={Moment('2018-02-02')} />
|
<Calendar onSelect={onSelect} validRange={validRange} defaultValue={Moment('2018-02-02')} />,
|
||||||
);
|
);
|
||||||
wrapper.find('[title="February 1, 2018"]').at(0).simulate('click');
|
wrapper
|
||||||
wrapper.find('[title="February 2, 2018"]').at(0).simulate('click');
|
.find('[title="February 1, 2018"]')
|
||||||
|
.at(0)
|
||||||
|
.simulate('click');
|
||||||
|
wrapper
|
||||||
|
.find('[title="February 2, 2018"]')
|
||||||
|
.at(0)
|
||||||
|
.simulate('click');
|
||||||
expect(onSelect.mock.calls.length).toBe(1);
|
expect(onSelect.mock.calls.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -31,10 +38,15 @@ describe('Calendar', () => {
|
|||||||
const onSelect = jest.fn();
|
const onSelect = jest.fn();
|
||||||
const validRange = [Moment('2018-02-02'), Moment('2018-02-18')];
|
const validRange = [Moment('2018-02-02'), Moment('2018-02-18')];
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Calendar onSelect={onSelect} validRange={validRange} defaultValue={Moment('2018-02-02')} />
|
<Calendar onSelect={onSelect} validRange={validRange} defaultValue={Moment('2018-02-02')} />,
|
||||||
);
|
);
|
||||||
wrapper.find('[title="February 20, 2018"]').at(0).simulate('click');
|
wrapper
|
||||||
const elem = wrapper.find('[title="February 20, 2018"]').hasClass('ant-fullcalendar-disabled-cell');
|
.find('[title="February 20, 2018"]')
|
||||||
|
.at(0)
|
||||||
|
.simulate('click');
|
||||||
|
const elem = wrapper
|
||||||
|
.find('[title="February 20, 2018"]')
|
||||||
|
.hasClass('ant-fullcalendar-disabled-cell');
|
||||||
expect(elem).toEqual(true);
|
expect(elem).toEqual(true);
|
||||||
expect(onSelect.mock.calls.length).toBe(0);
|
expect(onSelect.mock.calls.length).toBe(0);
|
||||||
});
|
});
|
||||||
@ -43,33 +55,64 @@ describe('Calendar', () => {
|
|||||||
const onSelect = jest.fn();
|
const onSelect = jest.fn();
|
||||||
const validRange = [Moment('2018-02-02'), Moment('2018-05-18')];
|
const validRange = [Moment('2018-02-02'), Moment('2018-05-18')];
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Calendar onSelect={onSelect} validRange={validRange} defaultValue={Moment('2018-02-02')} mode="year" />
|
<Calendar
|
||||||
|
onSelect={onSelect}
|
||||||
|
validRange={validRange}
|
||||||
|
defaultValue={Moment('2018-02-02')}
|
||||||
|
mode="year"
|
||||||
|
/>,
|
||||||
);
|
);
|
||||||
expect(wrapper.find('[title="Jan"]').at(0).hasClass('ant-fullcalendar-month-panel-cell-disabled')).toBe(true);
|
expect(
|
||||||
expect(wrapper.find('[title="Feb"]').at(0).hasClass('ant-fullcalendar-month-panel-cell-disabled')).toBe(false);
|
wrapper
|
||||||
expect(wrapper.find('[title="Jun"]').at(0).hasClass('ant-fullcalendar-month-panel-cell-disabled')).toBe(true);
|
.find('[title="Jan"]')
|
||||||
wrapper.find('[title="Jan"]').at(0).simulate('click');
|
.at(0)
|
||||||
wrapper.find('[title="Mar"]').at(0).simulate('click');
|
.hasClass('ant-fullcalendar-month-panel-cell-disabled'),
|
||||||
|
).toBe(true);
|
||||||
|
expect(
|
||||||
|
wrapper
|
||||||
|
.find('[title="Feb"]')
|
||||||
|
.at(0)
|
||||||
|
.hasClass('ant-fullcalendar-month-panel-cell-disabled'),
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
wrapper
|
||||||
|
.find('[title="Jun"]')
|
||||||
|
.at(0)
|
||||||
|
.hasClass('ant-fullcalendar-month-panel-cell-disabled'),
|
||||||
|
).toBe(true);
|
||||||
|
wrapper
|
||||||
|
.find('[title="Jan"]')
|
||||||
|
.at(0)
|
||||||
|
.simulate('click');
|
||||||
|
wrapper
|
||||||
|
.find('[title="Mar"]')
|
||||||
|
.at(0)
|
||||||
|
.simulate('click');
|
||||||
expect(onSelect.mock.calls.length).toBe(1);
|
expect(onSelect.mock.calls.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('months other than in valid range should not be shown in header', () => {
|
it('months other than in valid range should not be shown in header', () => {
|
||||||
const validRange = [Moment('2017-02-02'), Moment('2018-05-18')];
|
const validRange = [Moment('2017-02-02'), Moment('2018-05-18')];
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Calendar validRange={validRange} />);
|
||||||
<Calendar validRange={validRange} />
|
wrapper
|
||||||
);
|
.find('.ant-fullcalendar-year-select')
|
||||||
wrapper.find('.ant-fullcalendar-year-select').hostNodes().simulate('click');
|
.hostNodes()
|
||||||
wrapper.find('.ant-select-dropdown-menu-item').first().simulate('click');
|
.simulate('click');
|
||||||
wrapper.find('.ant-fullcalendar-month-select').hostNodes().simulate('click');
|
wrapper
|
||||||
|
.find('.ant-select-dropdown-menu-item')
|
||||||
|
.first()
|
||||||
|
.simulate('click');
|
||||||
|
wrapper
|
||||||
|
.find('.ant-fullcalendar-month-select')
|
||||||
|
.hostNodes()
|
||||||
|
.simulate('click');
|
||||||
// 2 years and 11 months
|
// 2 years and 11 months
|
||||||
expect(wrapper.find('.ant-select-dropdown-menu-item').length).toBe(13);
|
expect(wrapper.find('.ant-select-dropdown-menu-item').length).toBe(13);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('getDateRange should returns a disabledDate function', () => {
|
it('getDateRange should returns a disabledDate function', () => {
|
||||||
const validRange = [Moment('2018-02-02'), Moment('2018-05-18')];
|
const validRange = [Moment('2018-02-02'), Moment('2018-05-18')];
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Calendar validRange={validRange} defaultValue={Moment('2018-02-02')} />);
|
||||||
<Calendar validRange={validRange} defaultValue={Moment('2018-02-02')} />
|
|
||||||
);
|
|
||||||
const instance = wrapper.instance();
|
const instance = wrapper.instance();
|
||||||
const disabledDate = instance.getDateRange(validRange);
|
const disabledDate = instance.getDateRange(validRange);
|
||||||
expect(disabledDate(Moment('2018-06-02'))).toBe(true);
|
expect(disabledDate(Moment('2018-06-02'))).toBe(true);
|
||||||
@ -79,9 +122,7 @@ describe('Calendar', () => {
|
|||||||
it('Calendar should change mode by prop', () => {
|
it('Calendar should change mode by prop', () => {
|
||||||
const monthMode = 'month';
|
const monthMode = 'month';
|
||||||
const yearMode = 'year';
|
const yearMode = 'year';
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Calendar />);
|
||||||
<Calendar />
|
|
||||||
);
|
|
||||||
expect(wrapper.state().mode).toEqual(monthMode);
|
expect(wrapper.state().mode).toEqual(monthMode);
|
||||||
wrapper.setProps({ mode: 'year' });
|
wrapper.setProps({ mode: 'year' });
|
||||||
expect(wrapper.state().mode).toEqual(yearMode);
|
expect(wrapper.state().mode).toEqual(yearMode);
|
||||||
@ -91,9 +132,7 @@ describe('Calendar', () => {
|
|||||||
const monthMode = 'month';
|
const monthMode = 'month';
|
||||||
const yearMode = 'year';
|
const yearMode = 'year';
|
||||||
const onPanelChangeStub = jest.fn();
|
const onPanelChangeStub = jest.fn();
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Calendar mode={yearMode} onPanelChange={onPanelChangeStub} />);
|
||||||
<Calendar mode={yearMode} onPanelChange={onPanelChangeStub} />
|
|
||||||
);
|
|
||||||
expect(wrapper.state().mode).toEqual(yearMode);
|
expect(wrapper.state().mode).toEqual(yearMode);
|
||||||
wrapper.instance().setType('date');
|
wrapper.instance().setType('date');
|
||||||
expect(wrapper.state().mode).toEqual(monthMode);
|
expect(wrapper.state().mode).toEqual(monthMode);
|
||||||
@ -104,9 +143,7 @@ describe('Calendar', () => {
|
|||||||
MockDate.set(Moment('2018-10-19'));
|
MockDate.set(Moment('2018-10-19'));
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const zhCN = require('../locale/zh_CN').default;
|
const zhCN = require('../locale/zh_CN').default;
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Calendar locale={zhCN} />);
|
||||||
<Calendar locale={zhCN} />
|
|
||||||
);
|
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(wrapper.render()).toMatchSnapshot();
|
||||||
MockDate.reset();
|
MockDate.reset();
|
||||||
});
|
});
|
||||||
|
@ -10,7 +10,9 @@ import enUS from './locale/en_US';
|
|||||||
|
|
||||||
export { HeaderProps } from './Header';
|
export { HeaderProps } from './Header';
|
||||||
|
|
||||||
function noop() { return null; }
|
function noop() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function zerofixed(v: number) {
|
function zerofixed(v: number) {
|
||||||
if (v < 10) {
|
if (v < 10) {
|
||||||
@ -106,29 +108,21 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
|||||||
const { prefixCls, monthCellRender = noop as Function } = this.props;
|
const { prefixCls, monthCellRender = noop as Function } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={`${prefixCls}-month`}>
|
<div className={`${prefixCls}-month`}>
|
||||||
<div className={`${prefixCls}-value`}>
|
<div className={`${prefixCls}-value`}>{value.localeData().monthsShort(value)}</div>
|
||||||
{value.localeData().monthsShort(value)}
|
<div className={`${prefixCls}-content`}>{monthCellRender(value)}</div>
|
||||||
</div>
|
|
||||||
<div className={`${prefixCls}-content`}>
|
|
||||||
{monthCellRender(value)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
dateCellRender = (value: moment.Moment) => {
|
dateCellRender = (value: moment.Moment) => {
|
||||||
const { prefixCls, dateCellRender = noop as Function } = this.props;
|
const { prefixCls, dateCellRender = noop as Function } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className={`${prefixCls}-date`}>
|
<div className={`${prefixCls}-date`}>
|
||||||
<div className={`${prefixCls}-value`}>
|
<div className={`${prefixCls}-value`}>{zerofixed(value.date())}</div>
|
||||||
{zerofixed(value.date())}
|
<div className={`${prefixCls}-content`}>{dateCellRender(value)}</div>
|
||||||
</div>
|
|
||||||
<div className={`${prefixCls}-content`}>
|
|
||||||
{dateCellRender(value)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
setValue = (value: moment.Moment, way: 'select' | 'changePanel') => {
|
setValue = (value: moment.Moment, way: 'select' | 'changePanel') => {
|
||||||
if (!('value' in this.props)) {
|
if (!('value' in this.props)) {
|
||||||
@ -141,23 +135,23 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
|||||||
} else if (way === 'changePanel') {
|
} else if (way === 'changePanel') {
|
||||||
this.onPanelChange(value, this.state.mode);
|
this.onPanelChange(value, this.state.mode);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
setType = (type: string) => {
|
setType = (type: string) => {
|
||||||
const mode = (type === 'date') ? 'month' : 'year';
|
const mode = type === 'date' ? 'month' : 'year';
|
||||||
if (this.state.mode !== mode) {
|
if (this.state.mode !== mode) {
|
||||||
this.setState({ mode });
|
this.setState({ mode });
|
||||||
this.onPanelChange(this.state.value, mode);
|
this.onPanelChange(this.state.value, mode);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
onHeaderValueChange = (value: moment.Moment) => {
|
onHeaderValueChange = (value: moment.Moment) => {
|
||||||
this.setValue(value, 'changePanel');
|
this.setValue(value, 'changePanel');
|
||||||
}
|
};
|
||||||
|
|
||||||
onHeaderTypeChange = (type: string) => {
|
onHeaderTypeChange = (type: string) => {
|
||||||
this.setType(type);
|
this.setType(type);
|
||||||
}
|
};
|
||||||
|
|
||||||
onPanelChange(value: moment.Moment, mode: CalendarMode | undefined) {
|
onPanelChange(value: moment.Moment, mode: CalendarMode | undefined) {
|
||||||
const { onPanelChange, onChange } = this.props;
|
const { onPanelChange, onChange } = this.props;
|
||||||
@ -171,7 +165,7 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
|||||||
|
|
||||||
onSelect = (value: moment.Moment) => {
|
onSelect = (value: moment.Moment) => {
|
||||||
this.setValue(value, 'select');
|
this.setValue(value, 'select');
|
||||||
}
|
};
|
||||||
|
|
||||||
getDateRange = (
|
getDateRange = (
|
||||||
validRange: [moment.Moment, moment.Moment],
|
validRange: [moment.Moment, moment.Moment],
|
||||||
@ -183,10 +177,10 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
|||||||
const [startDate, endDate] = validRange;
|
const [startDate, endDate] = validRange;
|
||||||
const inRange = !current.isBetween(startDate, endDate, 'days', '[]');
|
const inRange = !current.isBetween(startDate, endDate, 'days', '[]');
|
||||||
if (disabledDate) {
|
if (disabledDate) {
|
||||||
return (disabledDate(current) || inRange);
|
return disabledDate(current) || inRange;
|
||||||
}
|
}
|
||||||
return inRange;
|
return inRange;
|
||||||
}
|
};
|
||||||
|
|
||||||
renderCalendar = (locale: any, localeCode: string) => {
|
renderCalendar = (locale: any, localeCode: string) => {
|
||||||
const { state, props } = this;
|
const { state, props } = this;
|
||||||
@ -194,12 +188,19 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
|||||||
if (value && localeCode) {
|
if (value && localeCode) {
|
||||||
value.locale(localeCode);
|
value.locale(localeCode);
|
||||||
}
|
}
|
||||||
const { prefixCls, style, className, fullscreen, dateFullCellRender, monthFullCellRender } = props;
|
const {
|
||||||
const type = (mode === 'year') ? 'month' : 'date';
|
prefixCls,
|
||||||
|
style,
|
||||||
|
className,
|
||||||
|
fullscreen,
|
||||||
|
dateFullCellRender,
|
||||||
|
monthFullCellRender,
|
||||||
|
} = props;
|
||||||
|
const type = mode === 'year' ? 'month' : 'date';
|
||||||
|
|
||||||
let cls = className || '';
|
let cls = className || '';
|
||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
cls += (` ${prefixCls}-fullscreen`);
|
cls += ` ${prefixCls}-fullscreen`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const monthCellRender = monthFullCellRender || this.monthCellRender;
|
const monthCellRender = monthFullCellRender || this.monthCellRender;
|
||||||
@ -238,7 +239,7 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
getDefaultLocale = () => {
|
getDefaultLocale = () => {
|
||||||
const result = {
|
const result = {
|
||||||
@ -250,14 +251,11 @@ export default class Calendar extends React.Component<CalendarProps, CalendarSta
|
|||||||
...(this.props.locale || {}).lang,
|
...(this.props.locale || {}).lang,
|
||||||
};
|
};
|
||||||
return result;
|
return result;
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<LocaleReceiver
|
<LocaleReceiver componentName="Calendar" defaultLocale={this.getDefaultLocale}>
|
||||||
componentName="Calendar"
|
|
||||||
defaultLocale={this.getDefaultLocale}
|
|
||||||
>
|
|
||||||
{this.renderCalendar}
|
{this.renderCalendar}
|
||||||
</LocaleReceiver>
|
</LocaleReceiver>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
@full-calendar-prefix-cls: ~"@{ant-prefix}-fullcalendar";
|
@full-calendar-prefix-cls: ~'@{ant-prefix}-fullcalendar';
|
||||||
|
|
||||||
.@{full-calendar-prefix-cls} {
|
.@{full-calendar-prefix-cls} {
|
||||||
.reset-component;
|
.reset-component;
|
||||||
@ -84,7 +84,7 @@
|
|||||||
&-month,
|
&-month,
|
||||||
&-date {
|
&-date {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
transition: all .3s;
|
transition: all 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-value {
|
&-value {
|
||||||
@ -97,7 +97,7 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
transition: all .3s;
|
transition: all 0.3s;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: @item-hover-bg;
|
background: @item-hover-bg;
|
||||||
@ -180,7 +180,7 @@
|
|||||||
height: 116px;
|
height: 116px;
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
border-top: 2px solid @border-color-split;
|
border-top: 2px solid @border-color-split;
|
||||||
transition: background .3s;
|
transition: background 0.3s;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: @item-hover-bg;
|
background: @item-hover-bg;
|
||||||
|
@ -15,13 +15,16 @@ export default (props: CardMetaProps) => {
|
|||||||
const classString = classNames(`${prefixCls}-meta`, className);
|
const classString = classNames(`${prefixCls}-meta`, className);
|
||||||
const avatarDom = avatar ? <div className={`${prefixCls}-meta-avatar`}>{avatar}</div> : null;
|
const avatarDom = avatar ? <div className={`${prefixCls}-meta-avatar`}>{avatar}</div> : null;
|
||||||
const titleDom = title ? <div className={`${prefixCls}-meta-title`}>{title}</div> : null;
|
const titleDom = title ? <div className={`${prefixCls}-meta-title`}>{title}</div> : null;
|
||||||
const descriptionDom = description ?
|
const descriptionDom = description ? (
|
||||||
<div className={`${prefixCls}-meta-description`}>{description}</div> : null;
|
<div className={`${prefixCls}-meta-description`}>{description}</div>
|
||||||
const MetaDetail = titleDom || descriptionDom ?
|
) : null;
|
||||||
|
const MetaDetail =
|
||||||
|
titleDom || descriptionDom ? (
|
||||||
<div className={`${prefixCls}-meta-detail`}>
|
<div className={`${prefixCls}-meta-detail`}>
|
||||||
{titleDom}
|
{titleDom}
|
||||||
{descriptionDom}
|
{descriptionDom}
|
||||||
</div> : null;
|
</div>
|
||||||
|
) : null;
|
||||||
return (
|
return (
|
||||||
<div {...others} className={classString}>
|
<div {...others} className={classString}>
|
||||||
{avatarDom}
|
{avatarDom}
|
||||||
|
@ -17,7 +17,9 @@ describe('Card', () => {
|
|||||||
function fakeResizeWindowTo(wrapper, width) {
|
function fakeResizeWindowTo(wrapper, width) {
|
||||||
Object.defineProperties(wrapper.instance().container, {
|
Object.defineProperties(wrapper.instance().container, {
|
||||||
offsetWidth: {
|
offsetWidth: {
|
||||||
get() { return width; },
|
get() {
|
||||||
|
return width;
|
||||||
|
},
|
||||||
configurable: true,
|
configurable: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -37,7 +39,11 @@ describe('Card', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should still have padding when card which set padding to 0 is loading', () => {
|
it('should still have padding when card which set padding to 0 is loading', () => {
|
||||||
const wrapper = mount(<Card loading bodyStyle={{ padding: 0 }}>xxx</Card>);
|
const wrapper = mount(
|
||||||
|
<Card loading bodyStyle={{ padding: 0 }}>
|
||||||
|
xxx
|
||||||
|
</Card>,
|
||||||
|
);
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(wrapper.render()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -45,7 +51,7 @@ describe('Card', () => {
|
|||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Card title="Card title" extra={<Button>Button</Button>} style={{ width: 300 }}>
|
<Card title="Card title" extra={<Button>Button</Button>} style={{ width: 300 }}>
|
||||||
<p>Card content</p>
|
<p>Card content</p>
|
||||||
</Card>
|
</Card>,
|
||||||
);
|
);
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(wrapper.render()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
@ -70,7 +70,10 @@ export default class Card extends React.Component<CardProps, CardState> {
|
|||||||
!this.props.noHovering,
|
!this.props.noHovering,
|
||||||
'`noHovering` of Card is deprecated, you can remove it safely or use `hoverable` instead.',
|
'`noHovering` of Card is deprecated, you can remove it safely or use `hoverable` instead.',
|
||||||
);
|
);
|
||||||
warning(!!this.props.noHovering, '`noHovering={false}` of Card is deprecated, use `hoverable` instead.');
|
warning(
|
||||||
|
!!this.props.noHovering,
|
||||||
|
'`noHovering={false}` of Card is deprecated, use `hoverable` instead.',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,11 +107,11 @@ export default class Card extends React.Component<CardProps, CardState> {
|
|||||||
if (this.props.onTabChange) {
|
if (this.props.onTabChange) {
|
||||||
this.props.onTabChange(key);
|
this.props.onTabChange(key);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
saveRef = (node: HTMLDivElement) => {
|
saveRef = (node: HTMLDivElement) => {
|
||||||
this.container = node;
|
this.container = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
isContainGrid() {
|
isContainGrid() {
|
||||||
let containGrid;
|
let containGrid;
|
||||||
@ -128,8 +131,7 @@ export default class Card extends React.Component<CardProps, CardState> {
|
|||||||
<li style={{ width: `${100 / actions.length}%` }} key={`action-${index}`}>
|
<li style={{ width: `${100 / actions.length}%` }} key={`action-${index}`}>
|
||||||
<span>{action}</span>
|
<span>{action}</span>
|
||||||
</li>
|
</li>
|
||||||
),
|
));
|
||||||
);
|
|
||||||
return actionList;
|
return actionList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,8 +146,24 @@ export default class Card extends React.Component<CardProps, CardState> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
prefixCls = 'ant-card', className, extra, headStyle = {}, bodyStyle = {}, noHovering, hoverable, title, loading,
|
prefixCls = 'ant-card',
|
||||||
bordered = true, type, cover, actions, tabList, children, activeTabKey, defaultActiveTabKey, ...others
|
className,
|
||||||
|
extra,
|
||||||
|
headStyle = {},
|
||||||
|
bodyStyle = {},
|
||||||
|
noHovering,
|
||||||
|
hoverable,
|
||||||
|
title,
|
||||||
|
loading,
|
||||||
|
bordered = true,
|
||||||
|
type,
|
||||||
|
cover,
|
||||||
|
actions,
|
||||||
|
tabList,
|
||||||
|
children,
|
||||||
|
activeTabKey,
|
||||||
|
defaultActiveTabKey,
|
||||||
|
...others
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const classString = classNames(prefixCls, className, {
|
const classString = classNames(prefixCls, className, {
|
||||||
@ -159,14 +177,11 @@ export default class Card extends React.Component<CardProps, CardState> {
|
|||||||
[`${prefixCls}-type-${type}`]: !!type,
|
[`${prefixCls}-type-${type}`]: !!type,
|
||||||
});
|
});
|
||||||
|
|
||||||
const loadingBlockStyle = (bodyStyle.padding === 0 || bodyStyle.padding === '0px')
|
const loadingBlockStyle =
|
||||||
? { padding: 24 } : undefined;
|
bodyStyle.padding === 0 || bodyStyle.padding === '0px' ? { padding: 24 } : undefined;
|
||||||
|
|
||||||
const loadingBlock = (
|
const loadingBlock = (
|
||||||
<div
|
<div className={`${prefixCls}-loading-content`} style={loadingBlockStyle}>
|
||||||
className={`${prefixCls}-loading-content`}
|
|
||||||
style={loadingBlockStyle}
|
|
||||||
>
|
|
||||||
<Row gutter={8}>
|
<Row gutter={8}>
|
||||||
<Col span={22}>
|
<Col span={22}>
|
||||||
<div className={`${prefixCls}-loading-block`} />
|
<div className={`${prefixCls}-loading-block`} />
|
||||||
@ -229,14 +244,17 @@ export default class Card extends React.Component<CardProps, CardState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let head;
|
let head;
|
||||||
const tabs = tabList && tabList.length ? (
|
const tabs =
|
||||||
|
tabList && tabList.length ? (
|
||||||
<Tabs
|
<Tabs
|
||||||
{...extraProps}
|
{...extraProps}
|
||||||
className={`${prefixCls}-head-tabs`}
|
className={`${prefixCls}-head-tabs`}
|
||||||
size="large"
|
size="large"
|
||||||
onChange={this.onTabChange}
|
onChange={this.onTabChange}
|
||||||
>
|
>
|
||||||
{tabList.map(item => <Tabs.TabPane tab={item.tab} disabled={item.disabled} key={item.key} />)}
|
{tabList.map(item => (
|
||||||
|
<Tabs.TabPane tab={item.tab} disabled={item.disabled} key={item.key} />
|
||||||
|
))}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
) : null;
|
) : null;
|
||||||
if (title || extra || tabs) {
|
if (title || extra || tabs) {
|
||||||
@ -256,11 +274,11 @@ export default class Card extends React.Component<CardProps, CardState> {
|
|||||||
{loading ? loadingBlock : children}
|
{loading ? loadingBlock : children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const actionDom = actions && actions.length ?
|
const actionDom =
|
||||||
<ul className={`${prefixCls}-actions`}>{this.getAction(actions)}</ul> : null;
|
actions && actions.length ? (
|
||||||
const divProps = omit(others, [
|
<ul className={`${prefixCls}-actions`}>{this.getAction(actions)}</ul>
|
||||||
'onTabChange',
|
) : null;
|
||||||
]);
|
const divProps = omit(others, ['onTabChange']);
|
||||||
return (
|
return (
|
||||||
<div {...divProps} className={classString} ref={this.saveRef}>
|
<div {...divProps} className={classString} ref={this.saveRef}>
|
||||||
{head}
|
{head}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
@card-prefix-cls: ~"@{ant-prefix}-card";
|
@card-prefix-cls: ~'@{ant-prefix}-card';
|
||||||
@card-head-height: 48px;
|
@card-head-height: 48px;
|
||||||
@card-hover-border: rgba(0, 0, 0, 0.09);
|
@card-hover-border: rgba(0, 0, 0, 0.09);
|
||||||
@card-radius: @border-radius-sm;
|
@card-radius: @border-radius-sm;
|
||||||
@ -11,7 +11,7 @@
|
|||||||
background: @component-background;
|
background: @component-background;
|
||||||
border-radius: @card-radius;
|
border-radius: @card-radius;
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: all .3s;
|
transition: all 0.3s;
|
||||||
|
|
||||||
&-hoverable {
|
&-hoverable {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -88,11 +88,13 @@
|
|||||||
&-grid {
|
&-grid {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
box-shadow: 1px 0 0 0 @border-color-split, 0 1px 0 0 @border-color-split, 1px 1px 0 0 @border-color-split, 1px 0 0 0 @border-color-split inset, 0 1px 0 0 @border-color-split inset;
|
box-shadow: 1px 0 0 0 @border-color-split, 0 1px 0 0 @border-color-split,
|
||||||
|
1px 1px 0 0 @border-color-split, 1px 0 0 0 @border-color-split inset,
|
||||||
|
0 1px 0 0 @border-color-split inset;
|
||||||
width: 33.33%;
|
width: 33.33%;
|
||||||
float: left;
|
float: left;
|
||||||
padding: @card-padding-base;
|
padding: @card-padding-base;
|
||||||
transition: all .3s;
|
transition: all 0.3s;
|
||||||
&:hover {
|
&:hover {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@ -143,7 +145,7 @@
|
|||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: @primary-color;
|
color: @primary-color;
|
||||||
transition: color .3s;
|
transition: color 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .anticon {
|
& > .anticon {
|
||||||
@ -179,7 +181,7 @@
|
|||||||
|
|
||||||
&-padding-transition &-head,
|
&-padding-transition &-head,
|
||||||
&-padding-transition &-body {
|
&-padding-transition &-body {
|
||||||
transition: padding .3s;
|
transition: padding 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-type-inner &-head {
|
&-type-inner &-head {
|
||||||
@ -244,7 +246,12 @@
|
|||||||
height: 14px;
|
height: 14px;
|
||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
border-radius: @card-radius;
|
border-radius: @card-radius;
|
||||||
background: linear-gradient(90deg, rgba(207, 216, 220, .2), rgba(207, 216, 220, .4), rgba(207, 216, 220, .2));
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
rgba(207, 216, 220, 0.2),
|
||||||
|
rgba(207, 216, 220, 0.4),
|
||||||
|
rgba(207, 216, 220, 0.2)
|
||||||
|
);
|
||||||
animation: card-loading 1.4s ease infinite;
|
animation: card-loading 1.4s ease infinite;
|
||||||
background-size: 600% 600%;
|
background-size: 600% 600%;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,11 @@ describe('Carousel', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should has innerSlider', () => {
|
it('should has innerSlider', () => {
|
||||||
const wrapper = mount(<Carousel><div /></Carousel>);
|
const wrapper = mount(
|
||||||
|
<Carousel>
|
||||||
|
<div />
|
||||||
|
</Carousel>,
|
||||||
|
);
|
||||||
const { innerSlider } = wrapper.instance();
|
const { innerSlider } = wrapper.instance();
|
||||||
const innerSliderFromRefs = wrapper.instance().slick.innerSlider;
|
const innerSliderFromRefs = wrapper.instance().slick.innerSlider;
|
||||||
expect(innerSlider).toBe(innerSliderFromRefs);
|
expect(innerSlider).toBe(innerSliderFromRefs);
|
||||||
@ -20,7 +24,13 @@ describe('Carousel', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should has prev, next and go function', () => {
|
it('should has prev, next and go function', () => {
|
||||||
const wrapper = mount(<Carousel><div>1</div><div>2</div><div>3</div></Carousel>);
|
const wrapper = mount(
|
||||||
|
<Carousel>
|
||||||
|
<div>1</div>
|
||||||
|
<div>2</div>
|
||||||
|
<div>3</div>
|
||||||
|
</Carousel>,
|
||||||
|
);
|
||||||
const { prev, next, goTo } = wrapper.instance();
|
const { prev, next, goTo } = wrapper.instance();
|
||||||
expect(typeof prev).toBe('function');
|
expect(typeof prev).toBe('function');
|
||||||
expect(typeof next).toBe('function');
|
expect(typeof next).toBe('function');
|
||||||
@ -39,7 +49,13 @@ describe('Carousel', () => {
|
|||||||
|
|
||||||
it('should trigger autoPlay after window resize', async () => {
|
it('should trigger autoPlay after window resize', async () => {
|
||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
const wrapper = mount(<Carousel autoplay><div>1</div><div>2</div><div>3</div></Carousel>);
|
const wrapper = mount(
|
||||||
|
<Carousel autoplay>
|
||||||
|
<div>1</div>
|
||||||
|
<div>2</div>
|
||||||
|
<div>3</div>
|
||||||
|
</Carousel>,
|
||||||
|
);
|
||||||
const spy = jest.spyOn(wrapper.instance().slick.innerSlider, 'autoPlay');
|
const spy = jest.spyOn(wrapper.instance().slick.innerSlider, 'autoPlay');
|
||||||
window.resizeTo(1000);
|
window.resizeTo(1000);
|
||||||
expect(spy).not.toBeCalled();
|
expect(spy).not.toBeCalled();
|
||||||
@ -48,7 +64,13 @@ describe('Carousel', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('cancel resize listener when unmount', async () => {
|
it('cancel resize listener when unmount', async () => {
|
||||||
const wrapper = mount(<Carousel autoplay><div>1</div><div>2</div><div>3</div></Carousel>);
|
const wrapper = mount(
|
||||||
|
<Carousel autoplay>
|
||||||
|
<div>1</div>
|
||||||
|
<div>2</div>
|
||||||
|
<div>3</div>
|
||||||
|
</Carousel>,
|
||||||
|
);
|
||||||
const { onWindowResized } = wrapper.instance();
|
const { onWindowResized } = wrapper.instance();
|
||||||
const spy = jest.spyOn(wrapper.instance().onWindowResized, 'cancel');
|
const spy = jest.spyOn(wrapper.instance().onWindowResized, 'cancel');
|
||||||
const spy2 = jest.spyOn(window, 'removeEventListener');
|
const spy2 = jest.spyOn(window, 'removeEventListener');
|
||||||
|
@ -8,10 +8,8 @@ if (typeof window !== 'undefined') {
|
|||||||
return {
|
return {
|
||||||
media: mediaQuery,
|
media: mediaQuery,
|
||||||
matches: false,
|
matches: false,
|
||||||
addListener() {
|
addListener() {},
|
||||||
},
|
removeListener() {},
|
||||||
removeListener() {
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
window.matchMedia = window.matchMedia || matchMediaPolyfill;
|
window.matchMedia = window.matchMedia || matchMediaPolyfill;
|
||||||
@ -108,11 +106,11 @@ export default class Carousel extends React.Component<CarouselProps, {}> {
|
|||||||
if (autoplay && this.slick && this.slick.innerSlider && this.slick.innerSlider.autoPlay) {
|
if (autoplay && this.slick && this.slick.innerSlider && this.slick.innerSlider.autoPlay) {
|
||||||
this.slick.innerSlider.autoPlay();
|
this.slick.innerSlider.autoPlay();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
saveSlick = (node: any) => {
|
saveSlick = (node: any) => {
|
||||||
this.slick = node;
|
this.slick = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
next() {
|
next() {
|
||||||
this.slick.slickNext();
|
this.slick.slickNext();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
.@{ant-prefix}-carousel {
|
.@{ant-prefix}-carousel {
|
||||||
.reset-component;
|
.reset-component;
|
||||||
@ -49,7 +49,7 @@
|
|||||||
|
|
||||||
&:before,
|
&:before,
|
||||||
&:after {
|
&:after {
|
||||||
content: "";
|
content: '';
|
||||||
display: table;
|
display: table;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@
|
|||||||
float: left;
|
float: left;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 1px;
|
min-height: 1px;
|
||||||
[dir="rtl"] & {
|
[dir='rtl'] & {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
img {
|
img {
|
||||||
@ -133,14 +133,14 @@
|
|||||||
.slick-prev {
|
.slick-prev {
|
||||||
left: -25px;
|
left: -25px;
|
||||||
&:before {
|
&:before {
|
||||||
content: "←";
|
content: '←';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.slick-next {
|
.slick-next {
|
||||||
right: -25px;
|
right: -25px;
|
||||||
&:before {
|
&:before {
|
||||||
content: "→";
|
content: '→';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +174,7 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
transition: all .5s;
|
transition: all 0.5s;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
|
@ -4,58 +4,79 @@ import KeyCode from 'rc-util/lib/KeyCode';
|
|||||||
import Cascader from '..';
|
import Cascader from '..';
|
||||||
import focusTest from '../../../tests/shared/focusTest';
|
import focusTest from '../../../tests/shared/focusTest';
|
||||||
|
|
||||||
const options = [{
|
const options = [
|
||||||
|
{
|
||||||
value: 'zhejiang',
|
value: 'zhejiang',
|
||||||
label: 'Zhejiang',
|
label: 'Zhejiang',
|
||||||
children: [{
|
children: [
|
||||||
|
{
|
||||||
value: 'hangzhou',
|
value: 'hangzhou',
|
||||||
label: 'Hangzhou',
|
label: 'Hangzhou',
|
||||||
children: [{
|
children: [
|
||||||
|
{
|
||||||
value: 'xihu',
|
value: 'xihu',
|
||||||
label: 'West Lake',
|
label: 'West Lake',
|
||||||
}],
|
},
|
||||||
}],
|
],
|
||||||
}, {
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
value: 'jiangsu',
|
value: 'jiangsu',
|
||||||
label: 'Jiangsu',
|
label: 'Jiangsu',
|
||||||
children: [{
|
children: [
|
||||||
|
{
|
||||||
value: 'nanjing',
|
value: 'nanjing',
|
||||||
label: 'Nanjing',
|
label: 'Nanjing',
|
||||||
children: [{
|
children: [
|
||||||
|
{
|
||||||
value: 'zhonghuamen',
|
value: 'zhonghuamen',
|
||||||
label: 'Zhong Hua Men',
|
label: 'Zhong Hua Men',
|
||||||
}],
|
},
|
||||||
}],
|
],
|
||||||
}];
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
function filter(inputValue, path) {
|
function filter(inputValue, path) {
|
||||||
return path.some(option => (option.label).toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
|
return path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Cascader', () => {
|
describe('Cascader', () => {
|
||||||
focusTest(Cascader);
|
focusTest(Cascader);
|
||||||
|
|
||||||
it('popup correctly when panel is hidden', () => {
|
it('popup correctly when panel is hidden', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Cascader options={options} />);
|
||||||
<Cascader options={options} />
|
expect(
|
||||||
);
|
render(
|
||||||
expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
),
|
||||||
|
).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('popup correctly when panel is open', () => {
|
it('popup correctly when panel is open', () => {
|
||||||
const onPopupVisibleChange = jest.fn();
|
const onPopupVisibleChange = jest.fn();
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Cascader options={options} onPopupVisibleChange={onPopupVisibleChange} />
|
<Cascader options={options} onPopupVisibleChange={onPopupVisibleChange} />,
|
||||||
);
|
);
|
||||||
wrapper.find('input').simulate('click');
|
wrapper.find('input').simulate('click');
|
||||||
expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
|
expect(
|
||||||
|
render(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
),
|
||||||
|
).toMatchSnapshot();
|
||||||
expect(onPopupVisibleChange).toHaveBeenCalledWith(true);
|
expect(onPopupVisibleChange).toHaveBeenCalledWith(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('support controlled mode', () => {
|
it('support controlled mode', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Cascader options={options} />);
|
||||||
<Cascader options={options} />
|
|
||||||
);
|
|
||||||
wrapper.setProps({
|
wrapper.setProps({
|
||||||
value: ['zhejiang', 'hangzhou', 'xihu'],
|
value: ['zhejiang', 'hangzhou', 'xihu'],
|
||||||
});
|
});
|
||||||
@ -63,38 +84,99 @@ describe('Cascader', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('popup correctly with defaultValue', () => {
|
it('popup correctly with defaultValue', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />);
|
||||||
<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />
|
|
||||||
);
|
|
||||||
wrapper.find('input').simulate('click');
|
wrapper.find('input').simulate('click');
|
||||||
expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
|
expect(
|
||||||
|
render(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
),
|
||||||
|
).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support popupVisible', () => {
|
it('should support popupVisible', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />);
|
||||||
<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />
|
expect(
|
||||||
);
|
wrapper
|
||||||
expect(wrapper.find('Trigger').instance().getComponent().props.visible).toBe(false);
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent().props.visible,
|
||||||
|
).toBe(false);
|
||||||
wrapper.setProps({ popupVisible: true });
|
wrapper.setProps({ popupVisible: true });
|
||||||
expect(wrapper.find('Trigger').instance().getComponent().props.visible).toBe(true);
|
expect(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent().props.visible,
|
||||||
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can be selected', () => {
|
it('can be selected', () => {
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
const wrapper = mount(<Cascader options={options} onChange={onChange} />);
|
const wrapper = mount(<Cascader options={options} onChange={onChange} />);
|
||||||
wrapper.find('input').simulate('click');
|
wrapper.find('input').simulate('click');
|
||||||
let popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
let popupWrapper = mount(
|
||||||
popupWrapper.find('.ant-cascader-menu').at(0).find('.ant-cascader-menu-item').at(0)
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
|
popupWrapper
|
||||||
|
.find('.ant-cascader-menu')
|
||||||
|
.at(0)
|
||||||
|
.find('.ant-cascader-menu-item')
|
||||||
|
.at(0)
|
||||||
.simulate('click');
|
.simulate('click');
|
||||||
expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
|
expect(
|
||||||
popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
render(
|
||||||
popupWrapper.find('.ant-cascader-menu').at(1).find('.ant-cascader-menu-item').at(0)
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
),
|
||||||
|
).toMatchSnapshot();
|
||||||
|
popupWrapper = mount(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
|
popupWrapper
|
||||||
|
.find('.ant-cascader-menu')
|
||||||
|
.at(1)
|
||||||
|
.find('.ant-cascader-menu-item')
|
||||||
|
.at(0)
|
||||||
.simulate('click');
|
.simulate('click');
|
||||||
expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
|
expect(
|
||||||
popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
render(
|
||||||
popupWrapper.find('.ant-cascader-menu').at(2).find('.ant-cascader-menu-item').at(0)
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
),
|
||||||
|
).toMatchSnapshot();
|
||||||
|
popupWrapper = mount(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
|
popupWrapper
|
||||||
|
.find('.ant-cascader-menu')
|
||||||
|
.at(2)
|
||||||
|
.find('.ant-cascader-menu-item')
|
||||||
|
.at(0)
|
||||||
.simulate('click');
|
.simulate('click');
|
||||||
expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
|
expect(
|
||||||
|
render(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
),
|
||||||
|
).toMatchSnapshot();
|
||||||
expect(onChange).toHaveBeenCalledWith(['zhejiang', 'hangzhou', 'xihu'], expect.anything());
|
expect(onChange).toHaveBeenCalledWith(['zhejiang', 'hangzhou', 'xihu'], expect.anything());
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -112,7 +194,12 @@ describe('Cascader', () => {
|
|||||||
wrapper.find('input').simulate('click');
|
wrapper.find('input').simulate('click');
|
||||||
wrapper.find('input').simulate('change', { target: { value: 'z' } });
|
wrapper.find('input').simulate('change', { target: { value: 'z' } });
|
||||||
expect(wrapper.state('inputValue')).toBe('z');
|
expect(wrapper.state('inputValue')).toBe('z');
|
||||||
const popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
const popupWrapper = mount(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
expect(popupWrapper).toMatchSnapshot();
|
expect(popupWrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -121,14 +208,22 @@ describe('Cascader', () => {
|
|||||||
wrapper.find('input').simulate('click');
|
wrapper.find('input').simulate('click');
|
||||||
wrapper.find('input').simulate('change', { target: { value: '__notfoundkeyword__' } });
|
wrapper.find('input').simulate('change', { target: { value: '__notfoundkeyword__' } });
|
||||||
expect(wrapper.state('inputValue')).toBe('__notfoundkeyword__');
|
expect(wrapper.state('inputValue')).toBe('__notfoundkeyword__');
|
||||||
const popupWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
const popupWrapper = mount(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
expect(popupWrapper).toMatchSnapshot();
|
expect(popupWrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support to clear selection', () => {
|
it('should support to clear selection', () => {
|
||||||
const wrapper = mount(<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />);
|
const wrapper = mount(<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />);
|
||||||
expect(wrapper.find('.ant-cascader-picker-label').text()).toBe('Zhejiang / Hangzhou');
|
expect(wrapper.find('.ant-cascader-picker-label').text()).toBe('Zhejiang / Hangzhou');
|
||||||
wrapper.find('.ant-cascader-picker-clear').at(0).simulate('click');
|
wrapper
|
||||||
|
.find('.ant-cascader-picker-clear')
|
||||||
|
.at(0)
|
||||||
|
.simulate('click');
|
||||||
expect(wrapper.find('.ant-cascader-picker-label').text()).toBe('');
|
expect(wrapper.find('.ant-cascader-picker-label').text()).toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -140,35 +235,33 @@ describe('Cascader', () => {
|
|||||||
popupVisible
|
popupVisible
|
||||||
defaultValue={['zhejiang', 'hangzhou']}
|
defaultValue={['zhejiang', 'hangzhou']}
|
||||||
onPopupVisibleChange={onPopupVisibleChange}
|
onPopupVisibleChange={onPopupVisibleChange}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
wrapper.find('.ant-cascader-picker-clear').at(0).simulate('click');
|
wrapper
|
||||||
|
.find('.ant-cascader-picker-clear')
|
||||||
|
.at(0)
|
||||||
|
.simulate('click');
|
||||||
expect(onPopupVisibleChange).toHaveBeenCalledWith(false);
|
expect(onPopupVisibleChange).toHaveBeenCalledWith(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should clear search input when clear selection', () => {
|
it('should clear search input when clear selection', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Cascader
|
<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} showSearch />,
|
||||||
options={options}
|
|
||||||
defaultValue={['zhejiang', 'hangzhou']}
|
|
||||||
showSearch
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
wrapper.find('input').simulate('click');
|
wrapper.find('input').simulate('click');
|
||||||
wrapper.find('input').simulate('change', { target: { value: 'xxx' } });
|
wrapper.find('input').simulate('change', { target: { value: 'xxx' } });
|
||||||
expect(wrapper.state('inputValue')).toBe('xxx');
|
expect(wrapper.state('inputValue')).toBe('xxx');
|
||||||
wrapper.find('.ant-cascader-picker-clear').at(0).simulate('click');
|
wrapper
|
||||||
|
.find('.ant-cascader-picker-clear')
|
||||||
|
.at(0)
|
||||||
|
.simulate('click');
|
||||||
expect(wrapper.state('inputValue')).toBe('');
|
expect(wrapper.state('inputValue')).toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not trigger visible change when click search input', () => {
|
it('should not trigger visible change when click search input', () => {
|
||||||
const onPopupVisibleChange = jest.fn();
|
const onPopupVisibleChange = jest.fn();
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Cascader
|
<Cascader options={options} showSearch onPopupVisibleChange={onPopupVisibleChange} />,
|
||||||
options={options}
|
|
||||||
showSearch
|
|
||||||
onPopupVisibleChange={onPopupVisibleChange}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
wrapper.find('input').simulate('focus');
|
wrapper.find('input').simulate('focus');
|
||||||
expect(onPopupVisibleChange).toHaveBeenCalledTimes(0);
|
expect(onPopupVisibleChange).toHaveBeenCalledTimes(0);
|
||||||
@ -192,29 +285,40 @@ describe('Cascader', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('can use fieldNames', () => {
|
it('can use fieldNames', () => {
|
||||||
const customerOptions = [{
|
const customerOptions = [
|
||||||
|
{
|
||||||
code: 'zhejiang',
|
code: 'zhejiang',
|
||||||
name: 'Zhejiang',
|
name: 'Zhejiang',
|
||||||
items: [{
|
items: [
|
||||||
|
{
|
||||||
code: 'hangzhou',
|
code: 'hangzhou',
|
||||||
name: 'Hangzhou',
|
name: 'Hangzhou',
|
||||||
items: [{
|
items: [
|
||||||
|
{
|
||||||
code: 'xihu',
|
code: 'xihu',
|
||||||
name: 'West Lake',
|
name: 'West Lake',
|
||||||
}],
|
},
|
||||||
}],
|
],
|
||||||
}, {
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
code: 'jiangsu',
|
code: 'jiangsu',
|
||||||
name: 'Jiangsu',
|
name: 'Jiangsu',
|
||||||
items: [{
|
items: [
|
||||||
|
{
|
||||||
code: 'nanjing',
|
code: 'nanjing',
|
||||||
name: 'Nanjing',
|
name: 'Nanjing',
|
||||||
items: [{
|
items: [
|
||||||
|
{
|
||||||
code: 'zhonghuamen',
|
code: 'zhonghuamen',
|
||||||
name: 'Zhong Hua Men',
|
name: 'Zhong Hua Men',
|
||||||
}],
|
},
|
||||||
}],
|
],
|
||||||
}];
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Cascader
|
<Cascader
|
||||||
options={customerOptions}
|
options={customerOptions}
|
||||||
@ -223,38 +327,54 @@ describe('Cascader', () => {
|
|||||||
label: 'name',
|
label: 'name',
|
||||||
value: 'code',
|
value: 'code',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
wrapper.instance().handleChange(['zhejiang', 'hangzhou', 'xihu'], customerOptions);
|
wrapper.instance().handleChange(['zhejiang', 'hangzhou', 'xihu'], customerOptions);
|
||||||
expect(wrapper.find('.ant-cascader-picker-label').text().split('/').length).toBe(3);
|
expect(
|
||||||
|
wrapper
|
||||||
|
.find('.ant-cascader-picker-label')
|
||||||
|
.text()
|
||||||
|
.split('/').length,
|
||||||
|
).toBe(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/12970
|
// https://github.com/ant-design/ant-design/issues/12970
|
||||||
it('can use filedNames too, for compatibility', () => {
|
it('can use filedNames too, for compatibility', () => {
|
||||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||||
const customerOptions = [{
|
const customerOptions = [
|
||||||
|
{
|
||||||
code: 'zhejiang',
|
code: 'zhejiang',
|
||||||
name: 'Zhejiang',
|
name: 'Zhejiang',
|
||||||
items: [{
|
items: [
|
||||||
|
{
|
||||||
code: 'hangzhou',
|
code: 'hangzhou',
|
||||||
name: 'Hangzhou',
|
name: 'Hangzhou',
|
||||||
items: [{
|
items: [
|
||||||
|
{
|
||||||
code: 'xihu',
|
code: 'xihu',
|
||||||
name: 'West Lake',
|
name: 'West Lake',
|
||||||
}],
|
},
|
||||||
}],
|
],
|
||||||
}, {
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
code: 'jiangsu',
|
code: 'jiangsu',
|
||||||
name: 'Jiangsu',
|
name: 'Jiangsu',
|
||||||
items: [{
|
items: [
|
||||||
|
{
|
||||||
code: 'nanjing',
|
code: 'nanjing',
|
||||||
name: 'Nanjing',
|
name: 'Nanjing',
|
||||||
items: [{
|
items: [
|
||||||
|
{
|
||||||
code: 'zhonghuamen',
|
code: 'zhonghuamen',
|
||||||
name: 'Zhong Hua Men',
|
name: 'Zhong Hua Men',
|
||||||
}],
|
},
|
||||||
}],
|
],
|
||||||
}];
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Cascader
|
<Cascader
|
||||||
options={customerOptions}
|
options={customerOptions}
|
||||||
@ -263,12 +383,17 @@ describe('Cascader', () => {
|
|||||||
label: 'name',
|
label: 'name',
|
||||||
value: 'code',
|
value: 'code',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
wrapper.instance().handleChange(['zhejiang', 'hangzhou', 'xihu'], customerOptions);
|
wrapper.instance().handleChange(['zhejiang', 'hangzhou', 'xihu'], customerOptions);
|
||||||
expect(wrapper.find('.ant-cascader-picker-label').text().split('/').length).toBe(3);
|
expect(
|
||||||
|
wrapper
|
||||||
|
.find('.ant-cascader-picker-label')
|
||||||
|
.text()
|
||||||
|
.split('/').length,
|
||||||
|
).toBe(3);
|
||||||
expect(errorSpy).toHaveBeenLastCalledWith(
|
expect(errorSpy).toHaveBeenLastCalledWith(
|
||||||
'Warning: `filedNames` of Cascader is a typo usage and deprecated, please use `fieldNames` instead.'
|
'Warning: `filedNames` of Cascader is a typo usage and deprecated, please use `fieldNames` instead.',
|
||||||
);
|
);
|
||||||
errorSpy.mockReset();
|
errorSpy.mockReset();
|
||||||
});
|
});
|
||||||
@ -300,7 +425,7 @@ describe('Cascader', () => {
|
|||||||
wrapper.find('input').simulate('change', { target: { value: 'a' } });
|
wrapper.find('input').simulate('change', { target: { value: 'a' } });
|
||||||
expect(wrapper.find('.ant-cascader-menu-item').length).toBe(2);
|
expect(wrapper.find('.ant-cascader-menu-item').length).toBe(2);
|
||||||
expect(errorSpy).toBeCalledWith(
|
expect(errorSpy).toBeCalledWith(
|
||||||
'Warning: \'limit\' of showSearch in Cascader should be positive number or false.'
|
"Warning: 'limit' of showSearch in Cascader should be positive number or false.",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -40,7 +40,12 @@ export interface ShowSearchType {
|
|||||||
prefixCls: string | undefined,
|
prefixCls: string | undefined,
|
||||||
names: FilledFieldNamesType,
|
names: FilledFieldNamesType,
|
||||||
) => React.ReactNode;
|
) => React.ReactNode;
|
||||||
sort?: (a: CascaderOptionType[], b: CascaderOptionType[], inputValue: string, names: FilledFieldNamesType) => number;
|
sort?: (
|
||||||
|
a: CascaderOptionType[],
|
||||||
|
b: CascaderOptionType[],
|
||||||
|
inputValue: string,
|
||||||
|
names: FilledFieldNamesType,
|
||||||
|
) => number;
|
||||||
matchInputWidth?: boolean;
|
matchInputWidth?: boolean;
|
||||||
limit?: number | false;
|
limit?: number | false;
|
||||||
}
|
}
|
||||||
@ -104,14 +109,23 @@ export interface CascaderState {
|
|||||||
const defaultLimit = 50;
|
const defaultLimit = 50;
|
||||||
|
|
||||||
function highlightKeyword(str: string, keyword: string, prefixCls: string | undefined) {
|
function highlightKeyword(str: string, keyword: string, prefixCls: string | undefined) {
|
||||||
return str.split(keyword)
|
return str.split(keyword).map((node: string, index: number) =>
|
||||||
.map((node: string, index: number) => index === 0 ? node : [
|
index === 0
|
||||||
<span className={`${prefixCls}-menu-item-keyword`} key="seperator">{keyword}</span>,
|
? node
|
||||||
|
: [
|
||||||
|
<span className={`${prefixCls}-menu-item-keyword`} key="seperator">
|
||||||
|
{keyword}
|
||||||
|
</span>,
|
||||||
node,
|
node,
|
||||||
]);
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function defaultFilterOption(inputValue: string, path: CascaderOptionType[], names: FilledFieldNamesType) {
|
function defaultFilterOption(
|
||||||
|
inputValue: string,
|
||||||
|
path: CascaderOptionType[],
|
||||||
|
names: FilledFieldNamesType,
|
||||||
|
) {
|
||||||
return path.some(option => (option[names.label] as string).indexOf(inputValue) > -1);
|
return path.some(option => (option[names.label] as string).indexOf(inputValue) > -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,14 +137,19 @@ function defaultRenderFilteredOption(
|
|||||||
) {
|
) {
|
||||||
return path.map((option, index) => {
|
return path.map((option, index) => {
|
||||||
const label = option[names.label];
|
const label = option[names.label];
|
||||||
const node = (label as string).indexOf(inputValue) > -1 ?
|
const node =
|
||||||
highlightKeyword(label as string, inputValue, prefixCls) : label;
|
(label as string).indexOf(inputValue) > -1
|
||||||
|
? highlightKeyword(label as string, inputValue, prefixCls)
|
||||||
|
: label;
|
||||||
return index === 0 ? node : [' / ', node];
|
return index === 0 ? node : [' / ', node];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function defaultSortFilteredOption(
|
function defaultSortFilteredOption(
|
||||||
a: CascaderOptionType[], b: CascaderOptionType[], inputValue: string, names: FilledFieldNamesType,
|
a: CascaderOptionType[],
|
||||||
|
b: CascaderOptionType[],
|
||||||
|
inputValue: string,
|
||||||
|
names: FilledFieldNamesType,
|
||||||
) {
|
) {
|
||||||
function callback(elem: CascaderOptionType) {
|
function callback(elem: CascaderOptionType) {
|
||||||
return (elem[names.label] as string).indexOf(inputValue) > -1;
|
return (elem[names.label] as string).indexOf(inputValue) > -1;
|
||||||
@ -183,8 +202,7 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
inputValue: '',
|
inputValue: '',
|
||||||
inputFocused: false,
|
inputFocused: false,
|
||||||
popupVisible: props.popupVisible,
|
popupVisible: props.popupVisible,
|
||||||
flattenOptions:
|
flattenOptions: props.showSearch ? this.flattenTree(props.options, props) : undefined,
|
||||||
props.showSearch ? this.flattenTree(props.options, props) : undefined,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +229,7 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setValue(value, selectedOptions);
|
this.setValue(value, selectedOptions);
|
||||||
}
|
};
|
||||||
|
|
||||||
handlePopupVisibleChange = (popupVisible: boolean) => {
|
handlePopupVisibleChange = (popupVisible: boolean) => {
|
||||||
if (!('popupVisible' in this.props)) {
|
if (!('popupVisible' in this.props)) {
|
||||||
@ -226,13 +244,13 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
if (onPopupVisibleChange) {
|
if (onPopupVisibleChange) {
|
||||||
onPopupVisibleChange(popupVisible);
|
onPopupVisibleChange(popupVisible);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleInputBlur = () => {
|
handleInputBlur = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
inputFocused: false,
|
inputFocused: false,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
handleInputClick = (e: React.MouseEvent<HTMLInputElement>) => {
|
handleInputClick = (e: React.MouseEvent<HTMLInputElement>) => {
|
||||||
const { inputFocused, popupVisible } = this.state;
|
const { inputFocused, popupVisible } = this.state;
|
||||||
@ -243,18 +261,18 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
e.nativeEvent.stopImmediatePropagation();
|
e.nativeEvent.stopImmediatePropagation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
if (e.keyCode === KeyCode.BACKSPACE) {
|
if (e.keyCode === KeyCode.BACKSPACE) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const inputValue = e.target.value;
|
const inputValue = e.target.value;
|
||||||
this.setState({ inputValue });
|
this.setState({ inputValue });
|
||||||
}
|
};
|
||||||
|
|
||||||
setValue = (value: string[], selectedOptions: CascaderOptionType[] = []) => {
|
setValue = (value: string[], selectedOptions: CascaderOptionType[] = []) => {
|
||||||
if (!('value' in this.props)) {
|
if (!('value' in this.props)) {
|
||||||
@ -264,14 +282,15 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
if (onChange) {
|
if (onChange) {
|
||||||
onChange(value, selectedOptions);
|
onChange(value, selectedOptions);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
getLabel() {
|
getLabel() {
|
||||||
const { options, displayRender = defaultDisplayRender as Function } = this.props;
|
const { options, displayRender = defaultDisplayRender as Function } = this.props;
|
||||||
const names = getFilledFieldNames(this.props);
|
const names = getFilledFieldNames(this.props);
|
||||||
const value = this.state.value;
|
const value = this.state.value;
|
||||||
const unwrappedValue = Array.isArray(value[0]) ? value[0] : value;
|
const unwrappedValue = Array.isArray(value[0]) ? value[0] : value;
|
||||||
const selectedOptions: CascaderOptionType[] = arrayTreeFilter(options,
|
const selectedOptions: CascaderOptionType[] = arrayTreeFilter(
|
||||||
|
options,
|
||||||
(o: CascaderOptionType, level: number) => o[names.value] === unwrappedValue[level],
|
(o: CascaderOptionType, level: number) => o[names.value] === unwrappedValue[level],
|
||||||
{ childrenKeyName: names.children },
|
{ childrenKeyName: names.children },
|
||||||
);
|
);
|
||||||
@ -288,7 +307,7 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
} else {
|
} else {
|
||||||
this.setState({ inputValue: '' });
|
this.setState({ inputValue: '' });
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
flattenTree(
|
flattenTree(
|
||||||
options: CascaderOptionType[],
|
options: CascaderOptionType[],
|
||||||
@ -298,19 +317,13 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
const names: FilledFieldNamesType = getFilledFieldNames(props);
|
const names: FilledFieldNamesType = getFilledFieldNames(props);
|
||||||
let flattenOptions = [] as CascaderOptionType[][];
|
let flattenOptions = [] as CascaderOptionType[][];
|
||||||
const childrenName = names.children;
|
const childrenName = names.children;
|
||||||
options.forEach((option) => {
|
options.forEach(option => {
|
||||||
const path = ancestor.concat(option);
|
const path = ancestor.concat(option);
|
||||||
if (props.changeOnSelect || !option[childrenName] || !option[childrenName].length) {
|
if (props.changeOnSelect || !option[childrenName] || !option[childrenName].length) {
|
||||||
flattenOptions.push(path);
|
flattenOptions.push(path);
|
||||||
}
|
}
|
||||||
if (option[childrenName]) {
|
if (option[childrenName]) {
|
||||||
flattenOptions = flattenOptions.concat(
|
flattenOptions = flattenOptions.concat(this.flattenTree(option[childrenName], props, path));
|
||||||
this.flattenTree(
|
|
||||||
option[childrenName],
|
|
||||||
props,
|
|
||||||
path,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return flattenOptions;
|
return flattenOptions;
|
||||||
@ -334,7 +347,7 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
let matchCount = 0;
|
let matchCount = 0;
|
||||||
|
|
||||||
// Perf optimization to filter items only below the limit
|
// Perf optimization to filter items only below the limit
|
||||||
flattenOptions.some((path) => {
|
flattenOptions.some(path => {
|
||||||
const match = filter(this.state.inputValue, path, names);
|
const match = filter(this.state.inputValue, path, names);
|
||||||
if (match) {
|
if (match) {
|
||||||
filtered.push(path);
|
filtered.push(path);
|
||||||
@ -345,9 +358,9 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
} else {
|
} else {
|
||||||
warning(
|
warning(
|
||||||
typeof limit !== 'number',
|
typeof limit !== 'number',
|
||||||
'\'limit\' of showSearch in Cascader should be positive number or false.',
|
"'limit' of showSearch in Cascader should be positive number or false.",
|
||||||
);
|
);
|
||||||
filtered = flattenOptions.filter((path) => filter(this.state.inputValue, path, names));
|
filtered = flattenOptions.filter(path => filter(this.state.inputValue, path, names));
|
||||||
}
|
}
|
||||||
|
|
||||||
filtered.sort((a, b) => sort(a, b, inputValue, names));
|
filtered.sort((a, b) => sort(a, b, inputValue, names));
|
||||||
@ -363,7 +376,9 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
} as CascaderOptionType;
|
} as CascaderOptionType;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return [{ [names.label]: notFoundContent, [names.value]: 'ANT_CASCADER_NOT_FOUND', disabled: true }];
|
return [
|
||||||
|
{ [names.label]: notFoundContent, [names.value]: 'ANT_CASCADER_NOT_FOUND', disabled: true },
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
@ -376,13 +391,23 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
|
|
||||||
saveInput = (node: Input) => {
|
saveInput = (node: Input) => {
|
||||||
this.input = node;
|
this.input = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
renderCascader = ({ getPopupContainer: getContextPopupContainer }: ConfigProviderProps) => {
|
renderCascader = ({ getPopupContainer: getContextPopupContainer }: ConfigProviderProps) => {
|
||||||
const { props, state } = this;
|
const { props, state } = this;
|
||||||
const {
|
const {
|
||||||
prefixCls, inputPrefixCls, children, placeholder, size, disabled,
|
prefixCls,
|
||||||
className, style, allowClear, showSearch = false, suffixIcon, ...otherProps
|
inputPrefixCls,
|
||||||
|
children,
|
||||||
|
placeholder,
|
||||||
|
size,
|
||||||
|
disabled,
|
||||||
|
className,
|
||||||
|
style,
|
||||||
|
allowClear,
|
||||||
|
showSearch = false,
|
||||||
|
suffixIcon,
|
||||||
|
...otherProps
|
||||||
} = props;
|
} = props;
|
||||||
const { value, inputFocused } = state;
|
const { value, inputFocused } = state;
|
||||||
|
|
||||||
@ -390,7 +415,8 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
[`${inputPrefixCls}-lg`]: size === 'large',
|
[`${inputPrefixCls}-lg`]: size === 'large',
|
||||||
[`${inputPrefixCls}-sm`]: size === 'small',
|
[`${inputPrefixCls}-sm`]: size === 'small',
|
||||||
});
|
});
|
||||||
const clearIcon = (allowClear && !disabled && value.length > 0) || state.inputValue ? (
|
const clearIcon =
|
||||||
|
(allowClear && !disabled && value.length > 0) || state.inputValue ? (
|
||||||
<Icon
|
<Icon
|
||||||
type="close-circle"
|
type="close-circle"
|
||||||
theme="filled"
|
theme="filled"
|
||||||
@ -402,8 +428,7 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
[`${prefixCls}-picker-arrow`]: true,
|
[`${prefixCls}-picker-arrow`]: true,
|
||||||
[`${prefixCls}-picker-arrow-expand`]: state.popupVisible,
|
[`${prefixCls}-picker-arrow-expand`]: state.popupVisible,
|
||||||
});
|
});
|
||||||
const pickerCls = classNames(
|
const pickerCls = classNames(className, `${prefixCls}-picker`, {
|
||||||
className, `${prefixCls}-picker`, {
|
|
||||||
[`${prefixCls}-picker-with-value`]: state.inputValue,
|
[`${prefixCls}-picker-with-value`]: state.inputValue,
|
||||||
[`${prefixCls}-picker-disabled`]: disabled,
|
[`${prefixCls}-picker-disabled`]: disabled,
|
||||||
[`${prefixCls}-picker-${size}`]: !!size,
|
[`${prefixCls}-picker-${size}`]: !!size,
|
||||||
@ -445,39 +470,34 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
this.cachedOptions = options;
|
this.cachedOptions = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dropdownMenuColumnStyle: { width?: number, height?: string } = {};
|
const dropdownMenuColumnStyle: { width?: number; height?: string } = {};
|
||||||
const isNotFound = (options || []).length === 1 && options[0].value === 'ANT_CASCADER_NOT_FOUND';
|
const isNotFound =
|
||||||
|
(options || []).length === 1 && options[0].value === 'ANT_CASCADER_NOT_FOUND';
|
||||||
if (isNotFound) {
|
if (isNotFound) {
|
||||||
dropdownMenuColumnStyle.height = 'auto'; // Height of one row.
|
dropdownMenuColumnStyle.height = 'auto'; // Height of one row.
|
||||||
}
|
}
|
||||||
// The default value of `matchInputWidth` is `true`
|
// The default value of `matchInputWidth` is `true`
|
||||||
const resultListMatchInputWidth = (showSearch as ShowSearchType).matchInputWidth === false ? false : true;
|
const resultListMatchInputWidth =
|
||||||
|
(showSearch as ShowSearchType).matchInputWidth === false ? false : true;
|
||||||
if (resultListMatchInputWidth && state.inputValue && this.input) {
|
if (resultListMatchInputWidth && state.inputValue && this.input) {
|
||||||
dropdownMenuColumnStyle.width = this.input.input.offsetWidth;
|
dropdownMenuColumnStyle.width = this.input.input.offsetWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputIcon = suffixIcon && (
|
const inputIcon = (suffixIcon &&
|
||||||
React.isValidElement<{ className?: string }>(suffixIcon)
|
(React.isValidElement<{ className?: string }>(suffixIcon) ? (
|
||||||
? React.cloneElement(
|
React.cloneElement(suffixIcon, {
|
||||||
suffixIcon,
|
|
||||||
{
|
|
||||||
className: classNames({
|
className: classNames({
|
||||||
[suffixIcon.props.className!]: suffixIcon.props.className,
|
[suffixIcon.props.className!]: suffixIcon.props.className,
|
||||||
[`${prefixCls}-picker-arrow`]: true,
|
[`${prefixCls}-picker-arrow`]: true,
|
||||||
}),
|
}),
|
||||||
},
|
})
|
||||||
) : <span className={`${prefixCls}-picker-arrow`}>{suffixIcon}</span>) || (
|
) : (
|
||||||
<Icon type="down" className={arrowCls} />
|
<span className={`${prefixCls}-picker-arrow`}>{suffixIcon}</span>
|
||||||
);
|
))) || <Icon type="down" className={arrowCls} />;
|
||||||
|
|
||||||
const input = children || (
|
const input = children || (
|
||||||
<span
|
<span style={style} className={pickerCls}>
|
||||||
style={style}
|
<span className={`${prefixCls}-picker-label`}>{this.getLabel()}</span>
|
||||||
className={pickerCls}
|
|
||||||
>
|
|
||||||
<span className={`${prefixCls}-picker-label`}>
|
|
||||||
{this.getLabel()}
|
|
||||||
</span>
|
|
||||||
<Input
|
<Input
|
||||||
{...inputProps}
|
{...inputProps}
|
||||||
ref={this.saveInput}
|
ref={this.saveInput}
|
||||||
@ -498,9 +518,7 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
const expandIcon = (
|
const expandIcon = <Icon type="right" />;
|
||||||
<Icon type="right" />
|
|
||||||
);
|
|
||||||
|
|
||||||
const loadingIcon = (
|
const loadingIcon = (
|
||||||
<span className={`${prefixCls}-menu-item-loading-icon`}>
|
<span className={`${prefixCls}-menu-item-loading-icon`}>
|
||||||
@ -527,13 +545,9 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
|||||||
{input}
|
{input}
|
||||||
</RcCascader>
|
</RcCascader>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return <ConfigConsumer>{this.renderCascader}</ConfigConsumer>;
|
||||||
<ConfigConsumer>
|
|
||||||
{this.renderCascader}
|
|
||||||
</ConfigConsumer>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
@import "../../input/style/mixin";
|
@import '../../input/style/mixin';
|
||||||
|
|
||||||
@cascader-prefix-cls: ~"@{ant-prefix}-cascader";
|
@cascader-prefix-cls: ~'@{ant-prefix}-cascader';
|
||||||
|
|
||||||
.@{cascader-prefix-cls} {
|
.@{cascader-prefix-cls} {
|
||||||
.reset-component;
|
.reset-component;
|
||||||
@ -28,7 +28,7 @@
|
|||||||
background-color: @component-background;
|
background-color: @component-background;
|
||||||
border-radius: @border-radius-base;
|
border-radius: @border-radius-base;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
transition: color .3s;
|
transition: color 0.3s;
|
||||||
|
|
||||||
&-with-value &-label {
|
&-with-value &-label {
|
||||||
color: transparent;
|
color: transparent;
|
||||||
@ -101,7 +101,7 @@
|
|||||||
margin-top: -6px;
|
margin-top: -6px;
|
||||||
line-height: 12px;
|
line-height: 12px;
|
||||||
color: @disabled-color;
|
color: @disabled-color;
|
||||||
transition: transform .2s;
|
transition: transform 0.2s;
|
||||||
&&-expand {
|
&&-expand {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
}
|
}
|
||||||
|
@ -53,10 +53,16 @@ export default class Checkbox extends React.Component<CheckboxProps, {}, {}> {
|
|||||||
|
|
||||||
private rcCheckbox: any;
|
private rcCheckbox: any;
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: CheckboxProps, nextState: {}, nextContext: CheckboxGroupContext) {
|
shouldComponentUpdate(
|
||||||
return !shallowEqual(this.props, nextProps) ||
|
nextProps: CheckboxProps,
|
||||||
|
nextState: {},
|
||||||
|
nextContext: CheckboxGroupContext,
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
!shallowEqual(this.props, nextProps) ||
|
||||||
!shallowEqual(this.state, nextState) ||
|
!shallowEqual(this.state, nextState) ||
|
||||||
!shallowEqual(this.context.checkboxGroup, nextContext.checkboxGroup);
|
!shallowEqual(this.context.checkboxGroup, nextContext.checkboxGroup)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
@ -69,7 +75,7 @@ export default class Checkbox extends React.Component<CheckboxProps, {}, {}> {
|
|||||||
|
|
||||||
saveCheckbox = (node: any) => {
|
saveCheckbox = (node: any) => {
|
||||||
this.rcCheckbox = node;
|
this.rcCheckbox = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { props, context } = this;
|
const { props, context } = this;
|
||||||
|
@ -85,8 +85,7 @@ class CheckboxGroup extends React.Component<CheckboxGroupProps, CheckboxGroupSta
|
|||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: CheckboxGroupProps, nextState: CheckboxGroupState) {
|
shouldComponentUpdate(nextProps: CheckboxGroupProps, nextState: CheckboxGroupState) {
|
||||||
return !shallowEqual(this.props, nextProps) ||
|
return !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState);
|
||||||
!shallowEqual(this.state, nextState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getOptions() {
|
getOptions() {
|
||||||
@ -118,7 +117,7 @@ class CheckboxGroup extends React.Component<CheckboxGroupProps, CheckboxGroupSta
|
|||||||
if (onChange) {
|
if (onChange) {
|
||||||
onChange(value);
|
onChange(value);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { props, state } = this;
|
const { props, state } = this;
|
||||||
|
@ -10,12 +10,7 @@ describe('Checkbox', () => {
|
|||||||
const onMouseEnter = jest.fn();
|
const onMouseEnter = jest.fn();
|
||||||
const onMouseLeave = jest.fn();
|
const onMouseLeave = jest.fn();
|
||||||
|
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(<Checkbox onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />);
|
||||||
<Checkbox
|
|
||||||
onMouseEnter={onMouseEnter}
|
|
||||||
onMouseLeave={onMouseLeave}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
wrapper.simulate('mouseenter');
|
wrapper.simulate('mouseenter');
|
||||||
expect(onMouseEnter).toHaveBeenCalled();
|
expect(onMouseEnter).toHaveBeenCalled();
|
||||||
|
@ -6,32 +6,47 @@ describe('CheckboxGroup', () => {
|
|||||||
it('should work basically', () => {
|
it('should work basically', () => {
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Checkbox.Group options={['Apple', 'Pear', 'Orange']} onChange={onChange} />
|
<Checkbox.Group options={['Apple', 'Pear', 'Orange']} onChange={onChange} />,
|
||||||
);
|
);
|
||||||
wrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
wrapper
|
||||||
|
.find('.ant-checkbox-input')
|
||||||
|
.at(0)
|
||||||
|
.simulate('change');
|
||||||
expect(onChange).toBeCalledWith(['Apple']);
|
expect(onChange).toBeCalledWith(['Apple']);
|
||||||
wrapper.find('.ant-checkbox-input').at(1).simulate('change');
|
wrapper
|
||||||
|
.find('.ant-checkbox-input')
|
||||||
|
.at(1)
|
||||||
|
.simulate('change');
|
||||||
expect(onChange).toBeCalledWith(['Apple', 'Pear']);
|
expect(onChange).toBeCalledWith(['Apple', 'Pear']);
|
||||||
wrapper.find('.ant-checkbox-input').at(2).simulate('change');
|
wrapper
|
||||||
|
.find('.ant-checkbox-input')
|
||||||
|
.at(2)
|
||||||
|
.simulate('change');
|
||||||
expect(onChange).toBeCalledWith(['Apple', 'Pear', 'Orange']);
|
expect(onChange).toBeCalledWith(['Apple', 'Pear', 'Orange']);
|
||||||
wrapper.find('.ant-checkbox-input').at(1).simulate('change');
|
wrapper
|
||||||
|
.find('.ant-checkbox-input')
|
||||||
|
.at(1)
|
||||||
|
.simulate('change');
|
||||||
expect(onChange).toBeCalledWith(['Apple', 'Orange']);
|
expect(onChange).toBeCalledWith(['Apple', 'Orange']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not trigger onChange callback of both Checkbox and CheckboxGroup when CheckboxGroup is disabled', () => {
|
it('does not trigger onChange callback of both Checkbox and CheckboxGroup when CheckboxGroup is disabled', () => {
|
||||||
const onChangeGroup = jest.fn();
|
const onChangeGroup = jest.fn();
|
||||||
|
|
||||||
const options = [
|
const options = [{ label: 'Apple', value: 'Apple' }, { label: 'Pear', value: 'Pear' }];
|
||||||
{ label: 'Apple', value: 'Apple' },
|
|
||||||
{ label: 'Pear', value: 'Pear' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const groupWrapper = mount(
|
const groupWrapper = mount(
|
||||||
<Checkbox.Group options={options} onChange={onChangeGroup} disabled />
|
<Checkbox.Group options={options} onChange={onChangeGroup} disabled />,
|
||||||
);
|
);
|
||||||
groupWrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
groupWrapper
|
||||||
|
.find('.ant-checkbox-input')
|
||||||
|
.at(0)
|
||||||
|
.simulate('change');
|
||||||
expect(onChangeGroup).not.toBeCalled();
|
expect(onChangeGroup).not.toBeCalled();
|
||||||
groupWrapper.find('.ant-checkbox-input').at(1).simulate('change');
|
groupWrapper
|
||||||
|
.find('.ant-checkbox-input')
|
||||||
|
.at(1)
|
||||||
|
.simulate('change');
|
||||||
expect(onChangeGroup).not.toBeCalled();
|
expect(onChangeGroup).not.toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -43,37 +58,31 @@ describe('CheckboxGroup', () => {
|
|||||||
{ label: 'Orange', value: 'Orange', disabled: true },
|
{ label: 'Orange', value: 'Orange', disabled: true },
|
||||||
];
|
];
|
||||||
|
|
||||||
const groupWrapper = mount(
|
const groupWrapper = mount(<Checkbox.Group options={options} onChange={onChangeGroup} />);
|
||||||
<Checkbox.Group options={options} onChange={onChangeGroup} />
|
groupWrapper
|
||||||
);
|
.find('.ant-checkbox-input')
|
||||||
groupWrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
.at(0)
|
||||||
|
.simulate('change');
|
||||||
expect(onChangeGroup).toBeCalledWith(['Apple']);
|
expect(onChangeGroup).toBeCalledWith(['Apple']);
|
||||||
groupWrapper.find('.ant-checkbox-input').at(1).simulate('change');
|
groupWrapper
|
||||||
|
.find('.ant-checkbox-input')
|
||||||
|
.at(1)
|
||||||
|
.simulate('change');
|
||||||
expect(onChangeGroup).toBeCalledWith(['Apple']);
|
expect(onChangeGroup).toBeCalledWith(['Apple']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes prefixCls down to checkbox', () => {
|
it('passes prefixCls down to checkbox', () => {
|
||||||
const options = [
|
const options = [{ label: 'Apple', value: 'Apple' }, { label: 'Orange', value: 'Orange' }];
|
||||||
{ label: 'Apple', value: 'Apple' },
|
|
||||||
{ label: 'Orange', value: 'Orange' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const wrapper = render(
|
const wrapper = render(<Checkbox.Group prefixCls="my-checkbox" options={options} />);
|
||||||
<Checkbox.Group prefixCls="my-checkbox" options={options} />
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be controlled by value', () => {
|
it('should be controlled by value', () => {
|
||||||
const options = [
|
const options = [{ label: 'Apple', value: 'Apple' }, { label: 'Orange', value: 'Orange' }];
|
||||||
{ label: 'Apple', value: 'Apple' },
|
|
||||||
{ label: 'Orange', value: 'Orange' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Checkbox.Group options={options} />);
|
||||||
<Checkbox.Group options={options} />
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(wrapper.instance().state.value).toEqual([]);
|
expect(wrapper.instance().state.value).toEqual([]);
|
||||||
wrapper.setProps({ value: ['Apple'] });
|
wrapper.setProps({ value: ['Apple'] });
|
||||||
@ -86,9 +95,12 @@ describe('CheckboxGroup', () => {
|
|||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<Checkbox.Group>
|
<Checkbox.Group>
|
||||||
<Checkbox value="my" onChange={onChange} />
|
<Checkbox value="my" onChange={onChange} />
|
||||||
</Checkbox.Group>
|
</Checkbox.Group>,
|
||||||
);
|
);
|
||||||
wrapper.find('.ant-checkbox-input').at(0).simulate('change');
|
wrapper
|
||||||
|
.find('.ant-checkbox-input')
|
||||||
|
.at(0)
|
||||||
|
.simulate('change');
|
||||||
expect(onChange).toBeCalled();
|
expect(onChange).toBeCalled();
|
||||||
expect(onChange.mock.calls[0][0].target.value).toEqual('my');
|
expect(onChange.mock.calls[0][0].target.value).toEqual('my');
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "./mixin";
|
@import './mixin';
|
||||||
|
|
||||||
.antCheckboxFn();
|
.antCheckboxFn();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
.antCheckboxFn(@checkbox-prefix-cls: ~"@{ant-prefix}-checkbox") {
|
.antCheckboxFn(@checkbox-prefix-cls: ~'@{ant-prefix}-checkbox') {
|
||||||
@checkbox-inner-prefix-cls: ~"@{checkbox-prefix-cls}-inner";
|
@checkbox-inner-prefix-cls: ~'@{checkbox-prefix-cls}-inner';
|
||||||
// 一般状态
|
// 一般状态
|
||||||
.@{checkbox-prefix-cls} {
|
.@{checkbox-prefix-cls} {
|
||||||
.reset-component;
|
.reset-component;
|
||||||
@ -28,7 +28,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
border-radius: @border-radius-sm;
|
border-radius: @border-radius-sm;
|
||||||
border: 1px solid @checkbox-color;
|
border: 1px solid @checkbox-color;
|
||||||
content: "";
|
content: '';
|
||||||
animation: antCheckboxEffect 0.36s ease-in-out;
|
animation: antCheckboxEffect 0.36s ease-in-out;
|
||||||
animation-fill-mode: both;
|
animation-fill-mode: both;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
@ -49,7 +49,7 @@
|
|||||||
border: @checkbox-border-width @border-style-base @border-color-base;
|
border: @checkbox-border-width @border-style-base @border-color-base;
|
||||||
border-radius: @border-radius-sm;
|
border-radius: @border-radius-sm;
|
||||||
background-color: @checkbox-check-color;
|
background-color: @checkbox-check-color;
|
||||||
transition: all .3s;
|
transition: all 0.3s;
|
||||||
// Fix IE checked style
|
// Fix IE checked style
|
||||||
// https://github.com/ant-design/ant-design/issues/12597
|
// https://github.com/ant-design/ant-design/issues/12597
|
||||||
border-collapse: separate;
|
border-collapse: separate;
|
||||||
@ -68,7 +68,7 @@
|
|||||||
border-top: 0;
|
border-top: 0;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
content: ' ';
|
content: ' ';
|
||||||
transition: all .1s @ease-in-back, opacity .1s;
|
transition: all 0.1s @ease-in-back, opacity 0.1s;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@
|
|||||||
border-top: 0;
|
border-top: 0;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
content: ' ';
|
content: ' ';
|
||||||
transition: all .2s @ease-out-back .1s;
|
transition: all 0.2s @ease-out-back 0.1s;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,16 +28,17 @@ export default class Collapse extends React.Component<CollapseProps, any> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
renderExpandIcon = () => {
|
renderExpandIcon = () => {
|
||||||
return (
|
return <Icon type="right" className={`arrow`} />;
|
||||||
<Icon type="right" className={`arrow`} />
|
};
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { prefixCls, className = '', bordered } = this.props;
|
const { prefixCls, className = '', bordered } = this.props;
|
||||||
const collapseClassName = classNames({
|
const collapseClassName = classNames(
|
||||||
|
{
|
||||||
[`${prefixCls}-borderless`]: !bordered,
|
[`${prefixCls}-borderless`]: !bordered,
|
||||||
}, className);
|
},
|
||||||
|
className,
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<RcCollapse
|
<RcCollapse
|
||||||
{...this.props}
|
{...this.props}
|
||||||
|
@ -17,9 +17,12 @@ export interface CollapsePanelProps {
|
|||||||
export default class CollapsePanel extends React.Component<CollapsePanelProps, {}> {
|
export default class CollapsePanel extends React.Component<CollapsePanelProps, {}> {
|
||||||
render() {
|
render() {
|
||||||
const { prefixCls, className = '', showArrow = true } = this.props;
|
const { prefixCls, className = '', showArrow = true } = this.props;
|
||||||
const collapsePanelClassName = classNames({
|
const collapsePanelClassName = classNames(
|
||||||
|
{
|
||||||
[`${prefixCls}-no-arrow`]: !showArrow,
|
[`${prefixCls}-no-arrow`]: !showArrow,
|
||||||
}, className);
|
},
|
||||||
|
className,
|
||||||
|
);
|
||||||
return <RcCollapse.Panel {...this.props} className={collapsePanelClassName} />;
|
return <RcCollapse.Panel {...this.props} className={collapsePanelClassName} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
@collapse-prefix-cls: ~"@{ant-prefix}-collapse";
|
@collapse-prefix-cls: ~'@{ant-prefix}-collapse';
|
||||||
|
|
||||||
.collapse-close() {
|
.collapse-close() {
|
||||||
transform: rotate(0);
|
transform: rotate(0);
|
||||||
@ -33,7 +33,7 @@
|
|||||||
color: @heading-color;
|
color: @heading-color;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: all .3s;
|
transition: all 0.3s;
|
||||||
|
|
||||||
.arrow {
|
.arrow {
|
||||||
.iconfont-mixin();
|
.iconfont-mixin();
|
||||||
@ -64,7 +64,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-anim-active {
|
&-anim-active {
|
||||||
transition: height .2s @ease-out;
|
transition: height 0.2s @ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-content {
|
&-content {
|
||||||
@ -88,7 +88,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& > &-item > &-header[aria-expanded="true"] {
|
& > &-item > &-header[aria-expanded='true'] {
|
||||||
.anticon-right svg {
|
.anticon-right svg {
|
||||||
.collapse-open();
|
.collapse-open();
|
||||||
}
|
}
|
||||||
|
@ -25,30 +25,21 @@ export interface CommentProps {
|
|||||||
export default class Comment extends React.Component<CommentProps, {}> {
|
export default class Comment extends React.Component<CommentProps, {}> {
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
prefixCls: 'ant-comment',
|
prefixCls: 'ant-comment',
|
||||||
}
|
};
|
||||||
|
|
||||||
getAction(actions: React.ReactNode[]) {
|
getAction(actions: React.ReactNode[]) {
|
||||||
if (!actions || !actions.length) {
|
if (!actions || !actions.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const actionList = actions.map((action, index) => (
|
const actionList = actions.map((action, index) => <li key={`action-${index}`}>{action}</li>);
|
||||||
<li key={`action-${index}`}>
|
|
||||||
{action}
|
|
||||||
</li>
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return actionList;
|
return actionList;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderNested = (children: any) => {
|
renderNested = (children: any) => {
|
||||||
const { prefixCls } = this.props;
|
const { prefixCls } = this.props;
|
||||||
|
|
||||||
return (
|
return <div className={classNames(`${prefixCls}-nested`)}>{children}</div>;
|
||||||
<div className={classNames(`${prefixCls}-nested`)}>
|
};
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
@ -70,31 +61,22 @@ export default class Comment extends React.Component<CommentProps, {}> {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const actionDom = actions && actions.length
|
const actionDom =
|
||||||
? <ul className={`${prefixCls}-actions`}>{this.getAction(actions)}</ul>
|
actions && actions.length ? (
|
||||||
: null;
|
<ul className={`${prefixCls}-actions`}>{this.getAction(actions)}</ul>
|
||||||
|
) : null;
|
||||||
|
|
||||||
const authorContent = (
|
const authorContent = (
|
||||||
<div className={`${prefixCls}-content-author`}>
|
<div className={`${prefixCls}-content-author`}>
|
||||||
{author && (
|
{author && <span className={`${prefixCls}-content-author-name`}>{author}</span>}
|
||||||
<span className={`${prefixCls}-content-author-name`}>
|
{datetime && <span className={`${prefixCls}-content-author-time`}>{datetime}</span>}
|
||||||
{author}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{datetime && (
|
|
||||||
<span className={`${prefixCls}-content-author-time`}>
|
|
||||||
{datetime}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const contentDom = (
|
const contentDom = (
|
||||||
<div className={`${prefixCls}-content`}>
|
<div className={`${prefixCls}-content`}>
|
||||||
{authorContent}
|
{authorContent}
|
||||||
<div className={`${prefixCls}-content-detail`}>
|
<div className={`${prefixCls}-content-detail`}>{content}</div>
|
||||||
{content}
|
|
||||||
</div>
|
|
||||||
{actionDom}
|
{actionDom}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
@comment-prefix-cls: ~"@{ant-prefix}-comment";
|
@comment-prefix-cls: ~'@{ant-prefix}-comment';
|
||||||
|
|
||||||
.@{comment-prefix-cls} {
|
.@{comment-prefix-cls} {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -44,7 +44,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-name {
|
&-name {
|
||||||
transition: color .3s;
|
transition: color 0.3s;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: @comment-author-name-color;
|
color: @comment-author-name-color;
|
||||||
> * {
|
> * {
|
||||||
@ -75,7 +75,7 @@
|
|||||||
color: @comment-action-color;
|
color: @comment-action-color;
|
||||||
> span {
|
> span {
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
transition: color .3s;
|
transition: color 0.3s;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: @comment-action-color;
|
color: @comment-action-color;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -7,18 +7,14 @@ export interface ConfigProviderProps {
|
|||||||
|
|
||||||
const ConfigContext: Context<ConfigProviderProps | null> = createReactContext({});
|
const ConfigContext: Context<ConfigProviderProps | null> = createReactContext({});
|
||||||
|
|
||||||
const ConfigProvider: React.SFC<ConfigProviderProps> = (props) => {
|
const ConfigProvider: React.SFC<ConfigProviderProps> = props => {
|
||||||
const { getPopupContainer, children } = props;
|
const { getPopupContainer, children } = props;
|
||||||
const config = {
|
const config = {
|
||||||
getPopupContainer,
|
getPopupContainer,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>;
|
||||||
<ConfigContext.Provider value={config}>
|
};
|
||||||
{children}
|
|
||||||
</ConfigContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ConfigConsumer = ConfigContext.Consumer;
|
export const ConfigConsumer = ConfigContext.Consumer;
|
||||||
|
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
// placeholder
|
// placeholder
|
||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
|
@ -33,7 +33,9 @@ function formatValue(value: moment.Moment | undefined, format: string): string {
|
|||||||
return (value && value.format(format)) || '';
|
return (value && value.format(format)) || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function pickerValueAdapter(value?: moment.Moment | RangePickerValue): RangePickerValue | undefined {
|
function pickerValueAdapter(
|
||||||
|
value?: moment.Moment | RangePickerValue,
|
||||||
|
): RangePickerValue | undefined {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -88,7 +90,7 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (('open' in nextProps) && prevState.open !== nextProps.open) {
|
if ('open' in nextProps && prevState.open !== nextProps.open) {
|
||||||
state = {
|
state = {
|
||||||
...state,
|
...state,
|
||||||
open: nextProps.open,
|
open: nextProps.open,
|
||||||
@ -104,8 +106,8 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
const value = props.value || props.defaultValue || [];
|
const value = props.value || props.defaultValue || [];
|
||||||
const [start, end] = value;
|
const [start, end] = value;
|
||||||
if (
|
if (
|
||||||
start && !interopDefault(moment).isMoment(start) ||
|
(start && !interopDefault(moment).isMoment(start)) ||
|
||||||
end && !interopDefault(moment).isMoment(end)
|
(end && !interopDefault(moment).isMoment(end))
|
||||||
) {
|
) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'The value/defaultValue of RangePicker must be a moment object array after `antd@2.0`, ' +
|
'The value/defaultValue of RangePicker must be a moment object array after `antd@2.0`, ' +
|
||||||
@ -126,7 +128,7 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this.setState({ value: [] });
|
this.setState({ value: [] });
|
||||||
this.handleChange([]);
|
this.handleChange([]);
|
||||||
}
|
};
|
||||||
|
|
||||||
clearHoverValue = () => this.setState({ hoverValue: [] });
|
clearHoverValue = () => this.setState({ hoverValue: [] });
|
||||||
|
|
||||||
@ -139,11 +141,8 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
const [start, end] = value;
|
const [start, end] = value;
|
||||||
props.onChange(value, [
|
props.onChange(value, [formatValue(start, props.format), formatValue(end, props.format)]);
|
||||||
formatValue(start, props.format),
|
};
|
||||||
formatValue(end, props.format),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOpenChange = (open: boolean) => {
|
handleOpenChange = (open: boolean) => {
|
||||||
if (!('open' in this.props)) {
|
if (!('open' in this.props)) {
|
||||||
@ -162,7 +161,7 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
if (!open) {
|
if (!open) {
|
||||||
this.focus();
|
this.focus();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleShowDateChange = (showDate: RangePickerValue) => this.setState({ showDate });
|
handleShowDateChange = (showDate: RangePickerValue) => this.setState({ showDate });
|
||||||
|
|
||||||
@ -172,7 +171,7 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
if (this.state.open) {
|
if (this.state.open) {
|
||||||
this.clearHoverValue();
|
this.clearHoverValue();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleCalendarInputSelect = (value: RangePickerValue) => {
|
handleCalendarInputSelect = (value: RangePickerValue) => {
|
||||||
const [start] = value;
|
const [start] = value;
|
||||||
@ -183,7 +182,7 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
value,
|
value,
|
||||||
showDate: getShowDateFromValue(value) || showDate,
|
showDate: getShowDateFromValue(value) || showDate,
|
||||||
}));
|
}));
|
||||||
}
|
};
|
||||||
|
|
||||||
handleRangeClick = (value: RangePickerPresetRange) => {
|
handleRangeClick = (value: RangePickerPresetRange) => {
|
||||||
if (typeof value === 'function') {
|
if (typeof value === 'function') {
|
||||||
@ -200,7 +199,7 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
if (onOpenChange) {
|
if (onOpenChange) {
|
||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
setValue(value: RangePickerValue, hidePanel?: boolean) {
|
setValue(value: RangePickerValue, hidePanel?: boolean) {
|
||||||
this.handleChange(value);
|
this.handleChange(value);
|
||||||
@ -219,7 +218,7 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
|
|
||||||
savePicker = (node: HTMLSpanElement) => {
|
savePicker = (node: HTMLSpanElement) => {
|
||||||
this.picker = node;
|
this.picker = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
renderFooter = (...args: any[]) => {
|
renderFooter = (...args: any[]) => {
|
||||||
const { prefixCls, ranges, renderExtraFooter, tagPrefixCls } = this.props;
|
const { prefixCls, ranges, renderExtraFooter, tagPrefixCls } = this.props;
|
||||||
@ -231,7 +230,7 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
{renderExtraFooter(...args)}
|
{renderExtraFooter(...args)}
|
||||||
</div>
|
</div>
|
||||||
) : null;
|
) : null;
|
||||||
const operations = Object.keys(ranges || {}).map((range) => {
|
const operations = Object.keys(ranges || {}).map(range => {
|
||||||
const value = ranges[range];
|
const value = ranges[range];
|
||||||
return (
|
return (
|
||||||
<Tag
|
<Tag
|
||||||
@ -246,23 +245,34 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
</Tag>
|
</Tag>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
const rangeNode = (operations && operations.length > 0) ? (
|
const rangeNode =
|
||||||
|
operations && operations.length > 0 ? (
|
||||||
<div className={`${prefixCls}-footer-extra ${prefixCls}-range-quick-selector`} key="range">
|
<div className={`${prefixCls}-footer-extra ${prefixCls}-range-quick-selector`} key="range">
|
||||||
{operations}
|
{operations}
|
||||||
</div>
|
</div>
|
||||||
) : null;
|
) : null;
|
||||||
return [rangeNode, customFooter];
|
return [rangeNode, customFooter];
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { state, props } = this;
|
const { state, props } = this;
|
||||||
const { value, showDate, hoverValue, open } = state;
|
const { value, showDate, hoverValue, open } = state;
|
||||||
const {
|
const {
|
||||||
prefixCls, popupStyle, style,
|
prefixCls,
|
||||||
disabledDate, disabledTime,
|
popupStyle,
|
||||||
showTime, showToday,
|
style,
|
||||||
ranges, onOk, locale, localeCode, format,
|
disabledDate,
|
||||||
dateRender, onCalendarChange, suffixIcon,
|
disabledTime,
|
||||||
|
showTime,
|
||||||
|
showToday,
|
||||||
|
ranges,
|
||||||
|
onOk,
|
||||||
|
locale,
|
||||||
|
localeCode,
|
||||||
|
format,
|
||||||
|
dateRender,
|
||||||
|
onCalendarChange,
|
||||||
|
suffixIcon,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
fixLocale(value, localeCode);
|
fixLocale(value, localeCode);
|
||||||
@ -291,10 +301,10 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
calendarProps.mode = props.mode;
|
calendarProps.mode = props.mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const startPlaceholder = ('placeholder' in props)
|
const startPlaceholder =
|
||||||
? props.placeholder[0] : locale.lang.rangePlaceholder[0];
|
'placeholder' in props ? props.placeholder[0] : locale.lang.rangePlaceholder[0];
|
||||||
const endPlaceholder = ('placeholder' in props)
|
const endPlaceholder =
|
||||||
? props.placeholder[1] : locale.lang.rangePlaceholder[1];
|
'placeholder' in props ? props.placeholder[1] : locale.lang.rangePlaceholder[1];
|
||||||
|
|
||||||
const calendar = (
|
const calendar = (
|
||||||
<RangeCalendar
|
<RangeCalendar
|
||||||
@ -327,7 +337,8 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
pickerStyle.width = (style && style.width) || 350;
|
pickerStyle.width = (style && style.width) || 350;
|
||||||
}
|
}
|
||||||
const [startValue, endValue] = value as RangePickerValue;
|
const [startValue, endValue] = value as RangePickerValue;
|
||||||
const clearIcon = (!props.disabled && props.allowClear && value && (startValue || endValue)) ? (
|
const clearIcon =
|
||||||
|
!props.disabled && props.allowClear && value && (startValue || endValue) ? (
|
||||||
<Icon
|
<Icon
|
||||||
type="close-circle"
|
type="close-circle"
|
||||||
className={`${prefixCls}-picker-clear`}
|
className={`${prefixCls}-picker-clear`}
|
||||||
@ -336,19 +347,17 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
|||||||
/>
|
/>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
const inputIcon = suffixIcon && (
|
const inputIcon = (suffixIcon &&
|
||||||
React.isValidElement<{ className?: string }>(suffixIcon)
|
(React.isValidElement<{ className?: string }>(suffixIcon) ? (
|
||||||
? React.cloneElement(
|
React.cloneElement(suffixIcon, {
|
||||||
suffixIcon,
|
|
||||||
{
|
|
||||||
className: classNames({
|
className: classNames({
|
||||||
[suffixIcon.props.className!]: suffixIcon.props.className,
|
[suffixIcon.props.className!]: suffixIcon.props.className,
|
||||||
[`${prefixCls}-picker-icon`]: true,
|
[`${prefixCls}-picker-icon`]: true,
|
||||||
}),
|
}),
|
||||||
},
|
})
|
||||||
) : <span className={`${prefixCls}-picker-icon`}>{suffixIcon}</span>) || (
|
) : (
|
||||||
<Icon type="calendar" className={`${prefixCls}-picker-icon`} />
|
<span className={`${prefixCls}-picker-icon`}>{suffixIcon}</span>
|
||||||
);
|
))) || <Icon type="calendar" className={`${prefixCls}-picker-icon`} />;
|
||||||
|
|
||||||
const input = ({ value: inputValue }: { value: any }) => {
|
const input = ({ value: inputValue }: { value: any }) => {
|
||||||
const [start, end] = inputValue;
|
const [start, end] = inputValue;
|
||||||
|
@ -56,30 +56,26 @@ class WeekPicker extends React.Component<any, WeekPickerState> {
|
|||||||
weekDateRender = (current: any) => {
|
weekDateRender = (current: any) => {
|
||||||
const selectedValue = this.state.value;
|
const selectedValue = this.state.value;
|
||||||
const { prefixCls } = this.props;
|
const { prefixCls } = this.props;
|
||||||
if (selectedValue &&
|
if (
|
||||||
|
selectedValue &&
|
||||||
current.year() === selectedValue.year() &&
|
current.year() === selectedValue.year() &&
|
||||||
current.week() === selectedValue.week()) {
|
current.week() === selectedValue.week()
|
||||||
|
) {
|
||||||
return (
|
return (
|
||||||
<div className={`${prefixCls}-selected-day`}>
|
<div className={`${prefixCls}-selected-day`}>
|
||||||
<div className={`${prefixCls}-date`}>
|
<div className={`${prefixCls}-date`}>{current.date()}</div>
|
||||||
{current.date()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className={`${prefixCls}-date`}>
|
|
||||||
{current.date()}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return <div className={`${prefixCls}-date`}>{current.date()}</div>;
|
||||||
|
};
|
||||||
|
|
||||||
handleChange = (value: moment.Moment | null) => {
|
handleChange = (value: moment.Moment | null) => {
|
||||||
if (!('value' in this.props)) {
|
if (!('value' in this.props)) {
|
||||||
this.setState({ value });
|
this.setState({ value });
|
||||||
}
|
}
|
||||||
this.props.onChange(value, formatValue(value, this.props.format));
|
this.props.onChange(value, formatValue(value, this.props.format));
|
||||||
}
|
};
|
||||||
|
|
||||||
handleOpenChange = (open: boolean) => {
|
handleOpenChange = (open: boolean) => {
|
||||||
const { onOpenChange } = this.props;
|
const { onOpenChange } = this.props;
|
||||||
@ -100,7 +96,7 @@ class WeekPicker extends React.Component<any, WeekPickerState> {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this.handleChange(null);
|
this.handleChange(null);
|
||||||
}
|
};
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
this.input.focus();
|
this.input.focus();
|
||||||
@ -112,13 +108,26 @@ class WeekPicker extends React.Component<any, WeekPickerState> {
|
|||||||
|
|
||||||
saveInput = (node: any) => {
|
saveInput = (node: any) => {
|
||||||
this.input = node;
|
this.input = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
prefixCls, className, disabled, pickerClass, popupStyle,
|
prefixCls,
|
||||||
pickerInputClass, format, allowClear, locale, localeCode, disabledDate,
|
className,
|
||||||
style, onFocus, onBlur, id, suffixIcon,
|
disabled,
|
||||||
|
pickerClass,
|
||||||
|
popupStyle,
|
||||||
|
pickerInputClass,
|
||||||
|
format,
|
||||||
|
allowClear,
|
||||||
|
locale,
|
||||||
|
localeCode,
|
||||||
|
disabledDate,
|
||||||
|
style,
|
||||||
|
onFocus,
|
||||||
|
onBlur,
|
||||||
|
id,
|
||||||
|
suffixIcon,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const { open } = this.state;
|
const { open } = this.state;
|
||||||
@ -127,8 +136,8 @@ class WeekPicker extends React.Component<any, WeekPickerState> {
|
|||||||
pickerValue.locale(localeCode);
|
pickerValue.locale(localeCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
const placeholder = ('placeholder' in this.props)
|
const placeholder =
|
||||||
? this.props.placeholder : locale.lang.placeholder;
|
'placeholder' in this.props ? this.props.placeholder : locale.lang.placeholder;
|
||||||
|
|
||||||
const calendar = (
|
const calendar = (
|
||||||
<Calendar
|
<Calendar
|
||||||
@ -142,7 +151,8 @@ class WeekPicker extends React.Component<any, WeekPickerState> {
|
|||||||
disabledDate={disabledDate}
|
disabledDate={disabledDate}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
const clearIcon = (!disabled && allowClear && this.state.value) ? (
|
const clearIcon =
|
||||||
|
!disabled && allowClear && this.state.value ? (
|
||||||
<Icon
|
<Icon
|
||||||
type="close-circle"
|
type="close-circle"
|
||||||
className={`${prefixCls}-picker-clear`}
|
className={`${prefixCls}-picker-clear`}
|
||||||
@ -151,19 +161,17 @@ class WeekPicker extends React.Component<any, WeekPickerState> {
|
|||||||
/>
|
/>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
const inputIcon = suffixIcon && (
|
const inputIcon = (suffixIcon &&
|
||||||
React.isValidElement<{ className?: string }>(suffixIcon)
|
(React.isValidElement<{ className?: string }>(suffixIcon) ? (
|
||||||
? React.cloneElement(
|
React.cloneElement(suffixIcon, {
|
||||||
suffixIcon,
|
|
||||||
{
|
|
||||||
className: classNames({
|
className: classNames({
|
||||||
[suffixIcon.props.className!]: suffixIcon.props.className,
|
[suffixIcon.props.className!]: suffixIcon.props.className,
|
||||||
[`${prefixCls}-picker-icon`]: true,
|
[`${prefixCls}-picker-icon`]: true,
|
||||||
}),
|
}),
|
||||||
},
|
})
|
||||||
) : <span className={`${prefixCls}-picker-icon`}>{suffixIcon}</span>) || (
|
) : (
|
||||||
<Icon type="calendar" className={`${prefixCls}-picker-icon`} />
|
<span className={`${prefixCls}-picker-icon`}>{suffixIcon}</span>
|
||||||
);
|
))) || <Icon type="calendar" className={`${prefixCls}-picker-icon`} />;
|
||||||
|
|
||||||
const input = ({ value }: { value: moment.Moment | undefined }) => {
|
const input = ({ value }: { value: moment.Moment | undefined }) => {
|
||||||
return (
|
return (
|
||||||
@ -184,11 +192,7 @@ class WeekPicker extends React.Component<any, WeekPickerState> {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<span
|
<span className={classNames(className, pickerClass)} style={style} id={id}>
|
||||||
className={classNames(className, pickerClass)}
|
|
||||||
style={style}
|
|
||||||
id={id}
|
|
||||||
>
|
|
||||||
<RcDatePicker
|
<RcDatePicker
|
||||||
{...this.props}
|
{...this.props}
|
||||||
calendar={calendar}
|
calendar={calendar}
|
||||||
|
@ -3,14 +3,7 @@ import { mount } from 'enzyme';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import MockDate from 'mockdate';
|
import MockDate from 'mockdate';
|
||||||
import DatePicker from '..';
|
import DatePicker from '..';
|
||||||
import {
|
import { selectDate, openPanel, clearInput, nextYear, nextMonth, hasSelected } from './utils';
|
||||||
selectDate,
|
|
||||||
openPanel,
|
|
||||||
clearInput,
|
|
||||||
nextYear,
|
|
||||||
nextMonth,
|
|
||||||
hasSelected,
|
|
||||||
} from './utils';
|
|
||||||
import focusTest from '../../../tests/shared/focusTest';
|
import focusTest from '../../../tests/shared/focusTest';
|
||||||
|
|
||||||
describe('DatePicker', () => {
|
describe('DatePicker', () => {
|
||||||
@ -28,10 +21,7 @@ describe('DatePicker', () => {
|
|||||||
const locale = {
|
const locale = {
|
||||||
lang: {
|
lang: {
|
||||||
placeholder: 'Избери дата',
|
placeholder: 'Избери дата',
|
||||||
rangePlaceholder: [
|
rangePlaceholder: ['Начална дата', 'Крайна дата'],
|
||||||
'Начална дата',
|
|
||||||
'Крайна дата',
|
|
||||||
],
|
|
||||||
today: 'Днес',
|
today: 'Днес',
|
||||||
now: 'Сега',
|
now: 'Сега',
|
||||||
backToToday: 'Към днес',
|
backToToday: 'Към днес',
|
||||||
@ -63,9 +53,7 @@ describe('DatePicker', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const birthday = moment('2000-01-01', 'YYYY-MM-DD');
|
const birthday = moment('2000-01-01', 'YYYY-MM-DD');
|
||||||
const wrapper = mount(
|
const wrapper = mount(<DatePicker open locale={locale} value={birthday} />);
|
||||||
<DatePicker open locale={locale} value={birthday} />
|
|
||||||
);
|
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(wrapper.render()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -75,9 +63,9 @@ describe('DatePicker', () => {
|
|||||||
state = {
|
state = {
|
||||||
cleared: false,
|
cleared: false,
|
||||||
value: moment(),
|
value: moment(),
|
||||||
}
|
};
|
||||||
|
|
||||||
onChange = (value) => {
|
onChange = value => {
|
||||||
let { cleared } = this.state;
|
let { cleared } = this.state;
|
||||||
|
|
||||||
let newValue = value;
|
let newValue = value;
|
||||||
@ -91,7 +79,7 @@ describe('DatePicker', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ value: newValue, cleared });
|
this.setState({ value: newValue, cleared });
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { value } = this.state;
|
const { value } = this.state;
|
||||||
@ -118,9 +106,7 @@ describe('DatePicker', () => {
|
|||||||
|
|
||||||
it('triggers onChange only when date was selected', () => {
|
it('triggers onChange only when date was selected', () => {
|
||||||
const handleChange = jest.fn();
|
const handleChange = jest.fn();
|
||||||
const wrapper = mount(
|
const wrapper = mount(<DatePicker onChange={handleChange} />);
|
||||||
<DatePicker onChange={handleChange} />
|
|
||||||
);
|
|
||||||
openPanel(wrapper);
|
openPanel(wrapper);
|
||||||
nextYear(wrapper);
|
nextYear(wrapper);
|
||||||
expect(handleChange).not.toBeCalled();
|
expect(handleChange).not.toBeCalled();
|
||||||
@ -131,9 +117,7 @@ describe('DatePicker', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('clear input', () => {
|
it('clear input', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<DatePicker />);
|
||||||
<DatePicker />
|
|
||||||
);
|
|
||||||
openPanel(wrapper);
|
openPanel(wrapper);
|
||||||
selectDate(wrapper, moment('2016-11-23'));
|
selectDate(wrapper, moment('2016-11-23'));
|
||||||
clearInput(wrapper);
|
clearInput(wrapper);
|
||||||
@ -142,35 +126,27 @@ describe('DatePicker', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('sets data attributes on input', () => {
|
it('sets data attributes on input', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<DatePicker data-test="test-id" data-id="12345" />);
|
||||||
<DatePicker data-test="test-id" data-id="12345" />
|
|
||||||
);
|
|
||||||
const input = wrapper.find('.ant-calendar-picker-input').getDOMNode();
|
const input = wrapper.find('.ant-calendar-picker-input').getDOMNode();
|
||||||
expect(input.getAttribute('data-test')).toBe('test-id');
|
expect(input.getAttribute('data-test')).toBe('test-id');
|
||||||
expect(input.getAttribute('data-id')).toBe('12345');
|
expect(input.getAttribute('data-id')).toBe('12345');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets aria attributes on input', () => {
|
it('sets aria attributes on input', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<DatePicker aria-label="some-label" aria-labelledby="label-id" />);
|
||||||
<DatePicker aria-label="some-label" aria-labelledby="label-id" />
|
|
||||||
);
|
|
||||||
const input = wrapper.find('.ant-calendar-picker-input').getDOMNode();
|
const input = wrapper.find('.ant-calendar-picker-input').getDOMNode();
|
||||||
expect(input.getAttribute('aria-label')).toBe('some-label');
|
expect(input.getAttribute('aria-label')).toBe('some-label');
|
||||||
expect(input.getAttribute('aria-labelledby')).toBe('label-id');
|
expect(input.getAttribute('aria-labelledby')).toBe('label-id');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets role attribute on input', () => {
|
it('sets role attribute on input', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<DatePicker role="search" />);
|
||||||
<DatePicker role="search" />
|
|
||||||
);
|
|
||||||
const input = wrapper.find('.ant-calendar-picker-input').getDOMNode();
|
const input = wrapper.find('.ant-calendar-picker-input').getDOMNode();
|
||||||
expect(input.getAttribute('role')).toBe('search');
|
expect(input.getAttribute('role')).toBe('search');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('changes year/month when under control', () => {
|
it('changes year/month when under control', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<DatePicker value={moment('2018-07-01')} />);
|
||||||
<DatePicker value={moment('2018-07-01')} />
|
|
||||||
);
|
|
||||||
openPanel(wrapper);
|
openPanel(wrapper);
|
||||||
expect(wrapper.find('.ant-calendar-my-select').text()).toBe('Jul2018');
|
expect(wrapper.find('.ant-calendar-my-select').text()).toBe('Jul2018');
|
||||||
wrapper.find('.ant-calendar-prev-year-btn').simulate('click');
|
wrapper.find('.ant-calendar-prev-year-btn').simulate('click');
|
||||||
@ -183,9 +159,7 @@ describe('DatePicker', () => {
|
|||||||
return current && current < moment().endOf('day');
|
return current && current < moment().endOf('day');
|
||||||
}
|
}
|
||||||
|
|
||||||
const wrapper = mount(
|
const wrapper = mount(<DatePicker disabledDate={disabledDate} />);
|
||||||
<DatePicker disabledDate={disabledDate} />
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(wrapper.render()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
@ -11,11 +11,15 @@ describe('MonthPicker', () => {
|
|||||||
focusTest(MonthPicker);
|
focusTest(MonthPicker);
|
||||||
|
|
||||||
it('reset select item when popup close', () => {
|
it('reset select item when popup close', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<MonthPicker value={moment('2018-07-01')} />);
|
||||||
<MonthPicker value={moment('2018-07-01')} />
|
|
||||||
);
|
|
||||||
openPanel(wrapper);
|
openPanel(wrapper);
|
||||||
wrapper.find('.ant-calendar-month-panel-month').first().simulate('click');
|
wrapper
|
||||||
wrapper.find('.ant-calendar-month-panel-cell').at(6).hasClass('ant-calendar-month-panel-selected-cell');
|
.find('.ant-calendar-month-panel-month')
|
||||||
|
.first()
|
||||||
|
.simulate('click');
|
||||||
|
wrapper
|
||||||
|
.find('.ant-calendar-month-panel-cell')
|
||||||
|
.at(6)
|
||||||
|
.hasClass('ant-calendar-month-panel-selected-cell');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -22,17 +22,18 @@ describe('RangePicker', () => {
|
|||||||
it('show month panel according to value', () => {
|
it('show month panel according to value', () => {
|
||||||
const birthday = moment('2000-01-01', 'YYYY-MM-DD').locale('zh-cn');
|
const birthday = moment('2000-01-01', 'YYYY-MM-DD').locale('zh-cn');
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<RangePicker
|
<RangePicker getCalendarContainer={trigger => trigger} format="YYYY/MM/DD" showTime open />,
|
||||||
getCalendarContainer={trigger => trigger}
|
|
||||||
format="YYYY/MM/DD"
|
|
||||||
showTime
|
|
||||||
open
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.setProps({ value: [birthday, birthday] });
|
wrapper.setProps({ value: [birthday, birthday] });
|
||||||
expect(render(wrapper.find('Trigger').instance().getComponent()))
|
expect(
|
||||||
.toMatchSnapshot();
|
render(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
),
|
||||||
|
).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('switch to corresponding month panel when click presetted ranges', () => {
|
it('switch to corresponding month panel when click presetted ranges', () => {
|
||||||
@ -46,14 +47,24 @@ describe('RangePicker', () => {
|
|||||||
format="YYYY/MM/DD"
|
format="YYYY/MM/DD"
|
||||||
showTime
|
showTime
|
||||||
open
|
open
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
const rangeCalendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
const rangeCalendarWrapper = mount(
|
||||||
rangeCalendarWrapper.find('.ant-calendar-range-quick-selector Tag')
|
wrapper
|
||||||
.simulate('click');
|
.find('Trigger')
|
||||||
expect(render(wrapper.find('Trigger').instance().getComponent()))
|
.instance()
|
||||||
.toMatchSnapshot();
|
.getComponent(),
|
||||||
|
);
|
||||||
|
rangeCalendarWrapper.find('.ant-calendar-range-quick-selector Tag').simulate('click');
|
||||||
|
expect(
|
||||||
|
render(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
),
|
||||||
|
).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('highlight range when hover presetted range', () => {
|
it('highlight range when hover presetted range', () => {
|
||||||
@ -65,13 +76,22 @@ describe('RangePicker', () => {
|
|||||||
getCalendarContainer={trigger => trigger}
|
getCalendarContainer={trigger => trigger}
|
||||||
format="YYYY/MM/DD"
|
format="YYYY/MM/DD"
|
||||||
open
|
open
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
let rangeCalendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
let rangeCalendarWrapper = mount(
|
||||||
rangeCalendarWrapper.find('.ant-calendar-range-quick-selector Tag')
|
wrapper
|
||||||
.simulate('mouseEnter');
|
.find('Trigger')
|
||||||
rangeCalendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
|
rangeCalendarWrapper.find('.ant-calendar-range-quick-selector Tag').simulate('mouseEnter');
|
||||||
|
rangeCalendarWrapper = mount(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
expect(rangeCalendarWrapper.find('.ant-calendar-selected-day').length).toBe(2);
|
expect(rangeCalendarWrapper.find('.ant-calendar-selected-day').length).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -82,10 +102,18 @@ describe('RangePicker', () => {
|
|||||||
getCalendarContainer={trigger => trigger}
|
getCalendarContainer={trigger => trigger}
|
||||||
onCalendarChange={onCalendarChangeFn}
|
onCalendarChange={onCalendarChangeFn}
|
||||||
open
|
open
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
const rangeCalendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
const rangeCalendarWrapper = mount(
|
||||||
rangeCalendarWrapper.find('.ant-calendar-cell').at(15).simulate('click');
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
|
rangeCalendarWrapper
|
||||||
|
.find('.ant-calendar-cell')
|
||||||
|
.at(15)
|
||||||
|
.simulate('click');
|
||||||
expect(onCalendarChangeFn).toHaveBeenCalled();
|
expect(onCalendarChangeFn).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -93,34 +121,57 @@ describe('RangePicker', () => {
|
|||||||
it('should not throw error when value is reset to `[]`', () => {
|
it('should not throw error when value is reset to `[]`', () => {
|
||||||
const birthday = moment('2000-01-01', 'YYYY-MM-DD');
|
const birthday = moment('2000-01-01', 'YYYY-MM-DD');
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<RangePicker
|
<RangePicker getCalendarContainer={trigger => trigger} value={[birthday, birthday]} open />,
|
||||||
getCalendarContainer={trigger => trigger}
|
|
||||||
value={[birthday, birthday]}
|
|
||||||
open
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
wrapper.setProps({ value: [] });
|
wrapper.setProps({ value: [] });
|
||||||
const rangeCalendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
const rangeCalendarWrapper = mount(
|
||||||
expect(() => rangeCalendarWrapper.find('.ant-calendar-cell').at(15).simulate('click').simulate('click'))
|
wrapper
|
||||||
.not.toThrow();
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
|
expect(() =>
|
||||||
|
rangeCalendarWrapper
|
||||||
|
.find('.ant-calendar-cell')
|
||||||
|
.at(15)
|
||||||
|
.simulate('click')
|
||||||
|
.simulate('click'),
|
||||||
|
).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
// issue: https://github.com/ant-design/ant-design/issues/7077
|
// issue: https://github.com/ant-design/ant-design/issues/7077
|
||||||
it('should not throw error when select after clear', () => {
|
it('should not throw error when select after clear', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<RangePicker getCalendarContainer={trigger => trigger} open />);
|
||||||
<RangePicker
|
let rangeCalendarWrapper = mount(
|
||||||
getCalendarContainer={trigger => trigger}
|
wrapper
|
||||||
open
|
.find('Trigger')
|
||||||
/>
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
);
|
);
|
||||||
let rangeCalendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
rangeCalendarWrapper
|
||||||
rangeCalendarWrapper.find('.ant-calendar-cell').at(15).simulate('click').simulate('click');
|
.find('.ant-calendar-cell')
|
||||||
|
.at(15)
|
||||||
|
.simulate('click')
|
||||||
|
.simulate('click');
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
wrapper.find('.ant-calendar-picker-clear').hostNodes().simulate('click');
|
wrapper
|
||||||
|
.find('.ant-calendar-picker-clear')
|
||||||
|
.hostNodes()
|
||||||
|
.simulate('click');
|
||||||
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
||||||
rangeCalendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
rangeCalendarWrapper = mount(
|
||||||
expect(() => rangeCalendarWrapper.find('.ant-calendar-cell').at(15).simulate('click').simulate('click'))
|
wrapper
|
||||||
.not.toThrow();
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
|
expect(() =>
|
||||||
|
rangeCalendarWrapper
|
||||||
|
.find('.ant-calendar-cell')
|
||||||
|
.at(15)
|
||||||
|
.simulate('click')
|
||||||
|
.simulate('click'),
|
||||||
|
).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('clear hover value after panel close', () => {
|
it('clear hover value after panel close', () => {
|
||||||
@ -128,16 +179,25 @@ describe('RangePicker', () => {
|
|||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<div>
|
<div>
|
||||||
<RangePicker value={[moment(), moment().add(2, 'day')]} />
|
<RangePicker value={[moment(), moment().add(2, 'day')]} />
|
||||||
</div>
|
</div>,
|
||||||
);
|
);
|
||||||
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
||||||
wrapper.find('.ant-calendar-cell').at(25).simulate('click');
|
wrapper
|
||||||
wrapper.find('.ant-calendar-cell').at(27).simulate('mouseEnter');
|
.find('.ant-calendar-cell')
|
||||||
|
.at(25)
|
||||||
|
.simulate('click');
|
||||||
|
wrapper
|
||||||
|
.find('.ant-calendar-cell')
|
||||||
|
.at(27)
|
||||||
|
.simulate('mouseEnter');
|
||||||
document.dispatchEvent(new MouseEvent('mousedown'));
|
document.dispatchEvent(new MouseEvent('mousedown'));
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('.ant-calendar-cell').at(23).hasClass('ant-calendar-in-range-cell')
|
wrapper
|
||||||
|
.find('.ant-calendar-cell')
|
||||||
|
.at(23)
|
||||||
|
.hasClass('ant-calendar-in-range-cell'),
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -145,19 +205,20 @@ describe('RangePicker', () => {
|
|||||||
it('static range', () => {
|
it('static range', () => {
|
||||||
const range = [moment().subtract(2, 'd'), moment()];
|
const range = [moment().subtract(2, 'd'), moment()];
|
||||||
const format = 'YYYY-MM-DD HH:mm:ss';
|
const format = 'YYYY-MM-DD HH:mm:ss';
|
||||||
const wrapper = mount(
|
const wrapper = mount(<RangePicker ranges={{ 'recent two days': range }} format={format} />);
|
||||||
<RangePicker
|
|
||||||
ranges={{ 'recent two days': range }}
|
|
||||||
format={format}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
||||||
wrapper.find('.ant-calendar-range-quick-selector Tag').simulate('click');
|
wrapper.find('.ant-calendar-range-quick-selector Tag').simulate('click');
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('.ant-calendar-range-picker-input').first().getDOMNode().value
|
wrapper
|
||||||
|
.find('.ant-calendar-range-picker-input')
|
||||||
|
.first()
|
||||||
|
.getDOMNode().value,
|
||||||
).toBe(range[0].format(format));
|
).toBe(range[0].format(format));
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('.ant-calendar-range-picker-input').last().getDOMNode().value
|
wrapper
|
||||||
|
.find('.ant-calendar-range-picker-input')
|
||||||
|
.last()
|
||||||
|
.getDOMNode().value,
|
||||||
).toBe(range[1].format(format));
|
).toBe(range[1].format(format));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -165,18 +226,21 @@ describe('RangePicker', () => {
|
|||||||
const range = [moment().subtract(2, 'd'), moment()];
|
const range = [moment().subtract(2, 'd'), moment()];
|
||||||
const format = 'YYYY-MM-DD HH:mm:ss';
|
const format = 'YYYY-MM-DD HH:mm:ss';
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<RangePicker
|
<RangePicker ranges={{ 'recent two days': () => range }} format={format} />,
|
||||||
ranges={{ 'recent two days': () => range }}
|
|
||||||
format={format}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
||||||
wrapper.find('.ant-calendar-range-quick-selector Tag').simulate('click');
|
wrapper.find('.ant-calendar-range-quick-selector Tag').simulate('click');
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('.ant-calendar-range-picker-input').first().getDOMNode().value
|
wrapper
|
||||||
|
.find('.ant-calendar-range-picker-input')
|
||||||
|
.first()
|
||||||
|
.getDOMNode().value,
|
||||||
).toBe(range[0].format(format));
|
).toBe(range[0].format(format));
|
||||||
expect(
|
expect(
|
||||||
wrapper.find('.ant-calendar-range-picker-input').last().getDOMNode().value
|
wrapper
|
||||||
|
.find('.ant-calendar-range-picker-input')
|
||||||
|
.last()
|
||||||
|
.getDOMNode().value,
|
||||||
).toBe(range[1].format(format));
|
).toBe(range[1].format(format));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -193,12 +257,7 @@ describe('RangePicker', () => {
|
|||||||
it('triggers onOk when click on preset range', () => {
|
it('triggers onOk when click on preset range', () => {
|
||||||
const handleOk = jest.fn();
|
const handleOk = jest.fn();
|
||||||
const range = [moment().subtract(2, 'd'), moment()];
|
const range = [moment().subtract(2, 'd'), moment()];
|
||||||
const wrapper = mount(
|
const wrapper = mount(<RangePicker ranges={{ 'recent two days': range }} onOk={handleOk} />);
|
||||||
<RangePicker
|
|
||||||
ranges={{ 'recent two days': range }}
|
|
||||||
onOk={handleOk}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
||||||
wrapper.find('.ant-calendar-range-quick-selector Tag').simulate('click');
|
wrapper.find('.ant-calendar-range-quick-selector Tag').simulate('click');
|
||||||
expect(handleOk).toBeCalledWith(range);
|
expect(handleOk).toBeCalledWith(range);
|
||||||
@ -211,25 +270,46 @@ describe('RangePicker', () => {
|
|||||||
selectDate(wrapper, moment('2017-09-18'), 0);
|
selectDate(wrapper, moment('2017-09-18'), 0);
|
||||||
selectDate(wrapper, moment('2017-10-18'), 1);
|
selectDate(wrapper, moment('2017-10-18'), 1);
|
||||||
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
||||||
expect(() => (
|
expect(() =>
|
||||||
wrapper.find('.ant-calendar-input').at(1).simulate('change', { target: { value: '2016-01-01' } })
|
wrapper
|
||||||
)).not.toThrow();
|
.find('.ant-calendar-input')
|
||||||
|
.at(1)
|
||||||
|
.simulate('change', { target: { value: '2016-01-01' } }),
|
||||||
|
).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('changes year/month when under control', () => {
|
it('changes year/month when under control', () => {
|
||||||
const wrapper = mount(<RangePicker value={[moment('2018-07-01'), moment('2018-07-02')]} />);
|
const wrapper = mount(<RangePicker value={[moment('2018-07-01'), moment('2018-07-02')]} />);
|
||||||
openPanel(wrapper);
|
openPanel(wrapper);
|
||||||
expect(wrapper.find('.ant-calendar-my-select').first().text()).toBe('Jul2018');
|
expect(
|
||||||
wrapper.find('.ant-calendar-prev-year-btn').first().simulate('click');
|
wrapper
|
||||||
wrapper.find('.ant-calendar-prev-month-btn').first().simulate('click');
|
.find('.ant-calendar-my-select')
|
||||||
expect(wrapper.find('.ant-calendar-my-select').first().text()).toBe('Jun2017');
|
.first()
|
||||||
|
.text(),
|
||||||
|
).toBe('Jul2018');
|
||||||
|
wrapper
|
||||||
|
.find('.ant-calendar-prev-year-btn')
|
||||||
|
.first()
|
||||||
|
.simulate('click');
|
||||||
|
wrapper
|
||||||
|
.find('.ant-calendar-prev-month-btn')
|
||||||
|
.first()
|
||||||
|
.simulate('click');
|
||||||
|
expect(
|
||||||
|
wrapper
|
||||||
|
.find('.ant-calendar-my-select')
|
||||||
|
.first()
|
||||||
|
.text(),
|
||||||
|
).toBe('Jun2017');
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/11631
|
// https://github.com/ant-design/ant-design/issues/11631
|
||||||
it('triggers onOpenChange when click on preset range', () => {
|
it('triggers onOpenChange when click on preset range', () => {
|
||||||
const handleOpenChange = jest.fn();
|
const handleOpenChange = jest.fn();
|
||||||
const range = [moment().subtract(2, 'd'), moment()];
|
const range = [moment().subtract(2, 'd'), moment()];
|
||||||
const wrapper = mount(<RangePicker onOpenChange={handleOpenChange} ranges={{ 'recent two days': range }} />);
|
const wrapper = mount(
|
||||||
|
<RangePicker onOpenChange={handleOpenChange} ranges={{ 'recent two days': range }} />,
|
||||||
|
);
|
||||||
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
wrapper.find('.ant-calendar-picker-input').simulate('click');
|
||||||
wrapper.find('.ant-calendar-range-quick-selector Tag').simulate('click');
|
wrapper.find('.ant-calendar-range-quick-selector Tag').simulate('click');
|
||||||
expect(handleOpenChange).toBeCalledWith(false);
|
expect(handleOpenChange).toBeCalledWith(false);
|
||||||
|
@ -9,9 +9,7 @@ describe('WeekPicker', () => {
|
|||||||
focusTest(WeekPicker);
|
focusTest(WeekPicker);
|
||||||
|
|
||||||
it('should support style prop', () => {
|
it('should support style prop', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<WeekPicker style={{ width: 400 }} />);
|
||||||
<WeekPicker style={{ width: 400 }} />
|
|
||||||
);
|
|
||||||
expect(wrapper.render()).toMatchSnapshot();
|
expect(wrapper.render()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,10 +3,7 @@ import { mount } from 'enzyme';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import MockDate from 'mockdate';
|
import MockDate from 'mockdate';
|
||||||
import DatePicker from '..';
|
import DatePicker from '..';
|
||||||
import {
|
import { selectDate, openPanel } from './utils';
|
||||||
selectDate,
|
|
||||||
openPanel,
|
|
||||||
} from './utils';
|
|
||||||
|
|
||||||
const { MonthPicker, WeekPicker, RangePicker } = DatePicker;
|
const { MonthPicker, WeekPicker, RangePicker } = DatePicker;
|
||||||
|
|
||||||
@ -20,18 +17,14 @@ describe('DatePicker', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should focus trigger input after select date in DatePicker', () => {
|
it('should focus trigger input after select date in DatePicker', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<DatePicker />);
|
||||||
<DatePicker />
|
|
||||||
);
|
|
||||||
openPanel(wrapper);
|
openPanel(wrapper);
|
||||||
selectDate(wrapper, moment('2016-11-23'));
|
selectDate(wrapper, moment('2016-11-23'));
|
||||||
expect(wrapper.find('.ant-calendar-picker-input').getDOMNode()).toBe(document.activeElement);
|
expect(wrapper.find('.ant-calendar-picker-input').getDOMNode()).toBe(document.activeElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should focus trigger input after select date in RangePicker', () => {
|
it('should focus trigger input after select date in RangePicker', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<RangePicker />);
|
||||||
<RangePicker />
|
|
||||||
);
|
|
||||||
openPanel(wrapper);
|
openPanel(wrapper);
|
||||||
selectDate(wrapper, moment('2016-11-23'), 0);
|
selectDate(wrapper, moment('2016-11-23'), 0);
|
||||||
selectDate(wrapper, moment('2016-11-28'), 1);
|
selectDate(wrapper, moment('2016-11-28'), 1);
|
||||||
@ -39,19 +32,21 @@ describe('DatePicker', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should focus trigger input after select date in MonthPicker', () => {
|
it('should focus trigger input after select date in MonthPicker', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<MonthPicker />);
|
||||||
<MonthPicker />
|
|
||||||
);
|
|
||||||
openPanel(wrapper);
|
openPanel(wrapper);
|
||||||
wrapper.find('.ant-calendar-month-panel-month').first().simulate('click');
|
wrapper
|
||||||
wrapper.find('.ant-calendar-month-panel-cell').at(6).hasClass('ant-calendar-month-panel-selected-cell');
|
.find('.ant-calendar-month-panel-month')
|
||||||
|
.first()
|
||||||
|
.simulate('click');
|
||||||
|
wrapper
|
||||||
|
.find('.ant-calendar-month-panel-cell')
|
||||||
|
.at(6)
|
||||||
|
.hasClass('ant-calendar-month-panel-selected-cell');
|
||||||
expect(wrapper.find('.ant-calendar-picker-input').getDOMNode()).toBe(document.activeElement);
|
expect(wrapper.find('.ant-calendar-picker-input').getDOMNode()).toBe(document.activeElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should focus trigger input after select date in WeekPicker', () => {
|
it('should focus trigger input after select date in WeekPicker', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<WeekPicker />);
|
||||||
<WeekPicker />
|
|
||||||
);
|
|
||||||
openPanel(wrapper);
|
openPanel(wrapper);
|
||||||
selectDate(wrapper, moment('2016-11-23'));
|
selectDate(wrapper, moment('2016-11-23'));
|
||||||
expect(wrapper.find('.ant-calendar-picker-input').getDOMNode()).toBe(document.activeElement);
|
expect(wrapper.find('.ant-calendar-picker-input').getDOMNode()).toBe(document.activeElement);
|
||||||
|
@ -8,19 +8,29 @@ const { MonthPicker, WeekPicker } = DatePicker;
|
|||||||
describe('MonthPicker and WeekPicker', () => {
|
describe('MonthPicker and WeekPicker', () => {
|
||||||
it('render MonthPicker', () => {
|
it('render MonthPicker', () => {
|
||||||
const birthday = moment('2000-01-01', 'YYYY-MM-DD').locale('zh-cn');
|
const birthday = moment('2000-01-01', 'YYYY-MM-DD').locale('zh-cn');
|
||||||
const wrapper = mount(
|
const wrapper = mount(<MonthPicker open />);
|
||||||
<MonthPicker open />
|
|
||||||
);
|
|
||||||
wrapper.setProps({ value: birthday });
|
wrapper.setProps({ value: birthday });
|
||||||
expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
|
expect(
|
||||||
|
render(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
),
|
||||||
|
).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render WeekPicker', () => {
|
it('render WeekPicker', () => {
|
||||||
const birthday = moment('2000-01-01', 'YYYY-MM-DD').locale('zh-cn');
|
const birthday = moment('2000-01-01', 'YYYY-MM-DD').locale('zh-cn');
|
||||||
const wrapper = mount(
|
const wrapper = mount(<WeekPicker open />);
|
||||||
<WeekPicker open />
|
|
||||||
);
|
|
||||||
wrapper.setProps({ value: birthday });
|
wrapper.setProps({ value: birthday });
|
||||||
expect(render(wrapper.find('Trigger').instance().getComponent())).toMatchSnapshot();
|
expect(
|
||||||
|
render(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
),
|
||||||
|
).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -9,11 +9,19 @@ describe('DatePicker with showTime', () => {
|
|||||||
const onChangeFn = jest.fn();
|
const onChangeFn = jest.fn();
|
||||||
const onOpenChangeFn = jest.fn();
|
const onOpenChangeFn = jest.fn();
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<DatePicker showTime open onChange={onChangeFn} onOpenChange={onOpenChangeFn} />
|
<DatePicker showTime open onChange={onChangeFn} onOpenChange={onOpenChangeFn} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
const calendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
const calendarWrapper = mount(
|
||||||
calendarWrapper.find('.ant-calendar-date').at(0).simulate('click');
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
|
calendarWrapper
|
||||||
|
.find('.ant-calendar-date')
|
||||||
|
.at(0)
|
||||||
|
.simulate('click');
|
||||||
expect(onChangeFn).toHaveBeenCalled();
|
expect(onChangeFn).toHaveBeenCalled();
|
||||||
expect(onOpenChangeFn).not.toHaveBeenCalled();
|
expect(onOpenChangeFn).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@ -24,10 +32,21 @@ describe('DatePicker with showTime', () => {
|
|||||||
const onChangeFn = jest.fn();
|
const onChangeFn = jest.fn();
|
||||||
|
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<DatePicker showTime open onChange={onChangeFn} onOk={onOkFn} onOpenChange={onOpenChangeFn} />
|
<DatePicker
|
||||||
|
showTime
|
||||||
|
open
|
||||||
|
onChange={onChangeFn}
|
||||||
|
onOk={onOkFn}
|
||||||
|
onOpenChange={onOpenChangeFn}
|
||||||
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
const calendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
const calendarWrapper = mount(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
calendarWrapper.find('.ant-calendar-ok-btn').simulate('click');
|
calendarWrapper.find('.ant-calendar-ok-btn').simulate('click');
|
||||||
expect(onOkFn).toHaveBeenCalled();
|
expect(onOkFn).toHaveBeenCalled();
|
||||||
expect(onOpenChangeFn).toHaveBeenCalledWith(false);
|
expect(onOpenChangeFn).toHaveBeenCalledWith(false);
|
||||||
@ -39,22 +58,33 @@ describe('DatePicker with showTime', () => {
|
|||||||
const onChangeFn = jest.fn();
|
const onChangeFn = jest.fn();
|
||||||
|
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<DatePicker showTime open onChange={onChangeFn} onOpenChange={onOpenChangeFn} />
|
<DatePicker showTime open onChange={onChangeFn} onOpenChange={onOpenChangeFn} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
const calendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
const calendarWrapper = mount(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
calendarWrapper.find('.ant-calendar-today-btn').simulate('click');
|
calendarWrapper.find('.ant-calendar-today-btn').simulate('click');
|
||||||
expect(onOpenChangeFn).toHaveBeenCalledWith(false);
|
expect(onOpenChangeFn).toHaveBeenCalledWith(false);
|
||||||
expect(onChangeFn).toHaveBeenCalled();
|
expect(onChangeFn).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have correct className when use12Hours is true', () => {
|
it('should have correct className when use12Hours is true', () => {
|
||||||
const wrapper = mount(
|
const wrapper = mount(<DatePicker showTime={{ use12Hours: true }} open />);
|
||||||
<DatePicker showTime={{ use12Hours: true }} open />
|
const calendarWrapper = mount(
|
||||||
|
wrapper
|
||||||
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
);
|
);
|
||||||
const calendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
|
||||||
expect(calendarWrapper.find('.ant-calendar-time-picker-column-4').length).toBe(0);
|
expect(calendarWrapper.find('.ant-calendar-time-picker-column-4').length).toBe(0);
|
||||||
calendarWrapper.find('.ant-calendar-time-picker-btn').at(0).simulate('click');
|
calendarWrapper
|
||||||
|
.find('.ant-calendar-time-picker-btn')
|
||||||
|
.at(0)
|
||||||
|
.simulate('click');
|
||||||
expect(calendarWrapper.find('.ant-calendar-time-picker-column-4').hostNodes().length).toBe(1);
|
expect(calendarWrapper.find('.ant-calendar-time-picker-column-4').hostNodes().length).toBe(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -64,16 +94,39 @@ describe('RangePicker with showTime', () => {
|
|||||||
const onChangeFn = jest.fn();
|
const onChangeFn = jest.fn();
|
||||||
const onOpenChangeFn = jest.fn();
|
const onOpenChangeFn = jest.fn();
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<RangePicker showTime open onChange={onChangeFn} onOpenChange={onOpenChangeFn} />
|
<RangePicker showTime open onChange={onChangeFn} onOpenChange={onOpenChangeFn} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
const calendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
const calendarWrapper = mount(
|
||||||
expect(calendarWrapper.find('.ant-calendar-time-picker-btn').hasClass('ant-calendar-time-picker-btn-disabled')).toBe(true);
|
wrapper
|
||||||
expect(calendarWrapper.find('.ant-calendar-ok-btn').hasClass('ant-calendar-ok-btn-disabled')).toBe(true);
|
.find('Trigger')
|
||||||
calendarWrapper.find('.ant-calendar-date').at(10).simulate('click');
|
.instance()
|
||||||
calendarWrapper.find('.ant-calendar-date').at(11).simulate('click');
|
.getComponent(),
|
||||||
expect(calendarWrapper.find('.ant-calendar-time-picker-btn').hasClass('ant-calendar-time-picker-btn-disabled')).toBe(false);
|
);
|
||||||
expect(calendarWrapper.find('.ant-calendar-ok-btn').hasClass('ant-calendar-ok-btn-disabled')).toBe(false);
|
expect(
|
||||||
|
calendarWrapper
|
||||||
|
.find('.ant-calendar-time-picker-btn')
|
||||||
|
.hasClass('ant-calendar-time-picker-btn-disabled'),
|
||||||
|
).toBe(true);
|
||||||
|
expect(
|
||||||
|
calendarWrapper.find('.ant-calendar-ok-btn').hasClass('ant-calendar-ok-btn-disabled'),
|
||||||
|
).toBe(true);
|
||||||
|
calendarWrapper
|
||||||
|
.find('.ant-calendar-date')
|
||||||
|
.at(10)
|
||||||
|
.simulate('click');
|
||||||
|
calendarWrapper
|
||||||
|
.find('.ant-calendar-date')
|
||||||
|
.at(11)
|
||||||
|
.simulate('click');
|
||||||
|
expect(
|
||||||
|
calendarWrapper
|
||||||
|
.find('.ant-calendar-time-picker-btn')
|
||||||
|
.hasClass('ant-calendar-time-picker-btn-disabled'),
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
calendarWrapper.find('.ant-calendar-ok-btn').hasClass('ant-calendar-ok-btn-disabled'),
|
||||||
|
).toBe(false);
|
||||||
expect(onChangeFn).toHaveBeenCalled();
|
expect(onChangeFn).toHaveBeenCalled();
|
||||||
expect(onOpenChangeFn).not.toHaveBeenCalled();
|
expect(onOpenChangeFn).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@ -89,12 +142,23 @@ describe('RangePicker with showTime', () => {
|
|||||||
onOk={onOkFn}
|
onOk={onOkFn}
|
||||||
onChange={onChangeFn}
|
onChange={onChangeFn}
|
||||||
onOpenChange={onOpenChangeFn}
|
onOpenChange={onOpenChangeFn}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
const calendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
|
const calendarWrapper = mount(
|
||||||
calendarWrapper.find('.ant-calendar-date').at(10).simulate('click');
|
wrapper
|
||||||
calendarWrapper.find('.ant-calendar-date').at(11).simulate('click');
|
.find('Trigger')
|
||||||
|
.instance()
|
||||||
|
.getComponent(),
|
||||||
|
);
|
||||||
|
calendarWrapper
|
||||||
|
.find('.ant-calendar-date')
|
||||||
|
.at(10)
|
||||||
|
.simulate('click');
|
||||||
|
calendarWrapper
|
||||||
|
.find('.ant-calendar-date')
|
||||||
|
.at(11)
|
||||||
|
.simulate('click');
|
||||||
onChangeFn.mockClear();
|
onChangeFn.mockClear();
|
||||||
calendarWrapper.find('.ant-calendar-ok-btn').simulate('click');
|
calendarWrapper.find('.ant-calendar-ok-btn').simulate('click');
|
||||||
expect(onOkFn).toHaveBeenCalled();
|
expect(onOkFn).toHaveBeenCalled();
|
||||||
|
@ -8,7 +8,9 @@ export function selectDate(wrapper, date, index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function hasSelected(wrapper, date) {
|
export function hasSelected(wrapper, date) {
|
||||||
return wrapper.find({ title: date.format('LL'), role: 'gridcell' }).hasClass('ant-calendar-selected-day');
|
return wrapper
|
||||||
|
.find({ title: date.format('LL'), role: 'gridcell' })
|
||||||
|
.hasClass('ant-calendar-selected-day');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function openPanel(wrapper) {
|
export function openPanel(wrapper) {
|
||||||
@ -16,7 +18,10 @@ export function openPanel(wrapper) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function clearInput(wrapper) {
|
export function clearInput(wrapper) {
|
||||||
wrapper.find('.ant-calendar-picker-clear').hostNodes().simulate('click');
|
wrapper
|
||||||
|
.find('.ant-calendar-picker-clear')
|
||||||
|
.hostNodes()
|
||||||
|
.simulate('click');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function nextYear(wrapper) {
|
export function nextYear(wrapper) {
|
||||||
|
@ -71,17 +71,15 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
|||||||
renderFooter = (...args: any[]) => {
|
renderFooter = (...args: any[]) => {
|
||||||
const { prefixCls, renderExtraFooter } = this.props;
|
const { prefixCls, renderExtraFooter } = this.props;
|
||||||
return renderExtraFooter ? (
|
return renderExtraFooter ? (
|
||||||
<div className={`${prefixCls}-footer-extra`}>
|
<div className={`${prefixCls}-footer-extra`}>{renderExtraFooter(...args)}</div>
|
||||||
{renderExtraFooter(...args)}
|
|
||||||
</div>
|
|
||||||
) : null;
|
) : null;
|
||||||
}
|
};
|
||||||
|
|
||||||
clearSelection = (e: React.MouseEvent<HTMLElement>) => {
|
clearSelection = (e: React.MouseEvent<HTMLElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this.handleChange(null);
|
this.handleChange(null);
|
||||||
}
|
};
|
||||||
|
|
||||||
handleChange = (value: moment.Moment | null) => {
|
handleChange = (value: moment.Moment | null) => {
|
||||||
const props = this.props;
|
const props = this.props;
|
||||||
@ -92,11 +90,11 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
props.onChange(value, (value && value.format(props.format)) || '');
|
props.onChange(value, (value && value.format(props.format)) || '');
|
||||||
}
|
};
|
||||||
|
|
||||||
handleCalendarChange = (value: moment.Moment) => {
|
handleCalendarChange = (value: moment.Moment) => {
|
||||||
this.setState({ showDate: value });
|
this.setState({ showDate: value });
|
||||||
}
|
};
|
||||||
|
|
||||||
handleOpenChange = (open: boolean) => {
|
handleOpenChange = (open: boolean) => {
|
||||||
const { onOpenChange } = this.props;
|
const { onOpenChange } = this.props;
|
||||||
@ -123,15 +121,14 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
|||||||
|
|
||||||
saveInput = (node: any) => {
|
saveInput = (node: any) => {
|
||||||
this.input = node;
|
this.input = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { value, showDate, open } = this.state;
|
const { value, showDate, open } = this.state;
|
||||||
const props = omit(this.props, ['onChange']);
|
const props = omit(this.props, ['onChange']);
|
||||||
const { prefixCls, locale, localeCode, suffixIcon } = props;
|
const { prefixCls, locale, localeCode, suffixIcon } = props;
|
||||||
|
|
||||||
const placeholder = ('placeholder' in props)
|
const placeholder = 'placeholder' in props ? props.placeholder : locale.lang.placeholder;
|
||||||
? props.placeholder : locale.lang.placeholder;
|
|
||||||
|
|
||||||
const disabledTime = props.showTime ? props.disabledTime : null;
|
const disabledTime = props.showTime ? props.disabledTime : null;
|
||||||
|
|
||||||
@ -162,7 +159,10 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
|||||||
calendarProps.mode = props.mode;
|
calendarProps.mode = props.mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
warning(!('onOK' in props), 'It should be `DatePicker[onOk]` or `MonthPicker[onOk]`, instead of `onOK`!');
|
warning(
|
||||||
|
!('onOK' in props),
|
||||||
|
'It should be `DatePicker[onOk]` or `MonthPicker[onOk]`, instead of `onOK`!',
|
||||||
|
);
|
||||||
const calendar = (
|
const calendar = (
|
||||||
<TheCalendar
|
<TheCalendar
|
||||||
{...calendarProps}
|
{...calendarProps}
|
||||||
@ -186,7 +186,8 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const clearIcon = (!props.disabled && props.allowClear && value) ? (
|
const clearIcon =
|
||||||
|
!props.disabled && props.allowClear && value ? (
|
||||||
<Icon
|
<Icon
|
||||||
type="close-circle"
|
type="close-circle"
|
||||||
className={`${prefixCls}-picker-clear`}
|
className={`${prefixCls}-picker-clear`}
|
||||||
@ -195,19 +196,17 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
|||||||
/>
|
/>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
const inputIcon = suffixIcon && (
|
const inputIcon = (suffixIcon &&
|
||||||
React.isValidElement<{ className?: string }>(suffixIcon)
|
(React.isValidElement<{ className?: string }>(suffixIcon) ? (
|
||||||
? React.cloneElement(
|
React.cloneElement(suffixIcon, {
|
||||||
suffixIcon,
|
|
||||||
{
|
|
||||||
className: classNames({
|
className: classNames({
|
||||||
[suffixIcon.props.className!]: suffixIcon.props.className,
|
[suffixIcon.props.className!]: suffixIcon.props.className,
|
||||||
[`${prefixCls}-picker-icon`]: true,
|
[`${prefixCls}-picker-icon`]: true,
|
||||||
}),
|
}),
|
||||||
},
|
})
|
||||||
) : <span className={`${prefixCls}-picker-icon`}>{suffixIcon}</span>) || (
|
) : (
|
||||||
<Icon type="calendar" className={`${prefixCls}-picker-icon`} />
|
<span className={`${prefixCls}-picker-icon`}>{suffixIcon}</span>
|
||||||
);
|
))) || <Icon type="calendar" className={`${prefixCls}-picker-icon`} />;
|
||||||
|
|
||||||
const dataOrAriaProps = getDataOrAriaProps(props);
|
const dataOrAriaProps = getDataOrAriaProps(props);
|
||||||
const input = ({ value: inputValue }: { value: moment.Moment | null }) => (
|
const input = ({ value: inputValue }: { value: moment.Moment | null }) => (
|
||||||
|
@ -7,7 +7,9 @@ import RangePicker from './RangePicker';
|
|||||||
import WeekPicker from './WeekPicker';
|
import WeekPicker from './WeekPicker';
|
||||||
import { DatePickerProps, DatePickerDecorator } from './interface';
|
import { DatePickerProps, DatePickerDecorator } from './interface';
|
||||||
|
|
||||||
const DatePicker = wrapPicker(createPicker(RcCalendar)) as React.ClassicComponentClass<DatePickerProps>;
|
const DatePicker = wrapPicker(createPicker(RcCalendar)) as React.ClassicComponentClass<
|
||||||
|
DatePickerProps
|
||||||
|
>;
|
||||||
|
|
||||||
const MonthPicker = wrapPicker(createPicker(MonthCalendar), 'YYYY-MM');
|
const MonthPicker = wrapPicker(createPicker(MonthCalendar), 'YYYY-MM');
|
||||||
|
|
||||||
|
@ -36,10 +36,12 @@ export interface DatePickerProps extends PickerProps, SinglePickerProps {
|
|||||||
showTime?: TimePickerProps | boolean;
|
showTime?: TimePickerProps | boolean;
|
||||||
showToday?: boolean;
|
showToday?: boolean;
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
disabledTime?: (current: moment.Moment) => {
|
disabledTime?: (
|
||||||
disabledHours?: () => number[],
|
current: moment.Moment,
|
||||||
disabledMinutes?: () => number[],
|
) => {
|
||||||
disabledSeconds?: () => number[],
|
disabledHours?: () => number[];
|
||||||
|
disabledMinutes?: () => number[];
|
||||||
|
disabledSeconds?: () => number[];
|
||||||
};
|
};
|
||||||
onOpenChange?: (status: boolean) => void;
|
onOpenChange?: (status: boolean) => void;
|
||||||
onOk?: (selectedTime: RangePickerValue) => void;
|
onOk?: (selectedTime: RangePickerValue) => void;
|
||||||
@ -52,10 +54,10 @@ export interface MonthPickerProps extends PickerProps, SinglePickerProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type RangePickerValue =
|
export type RangePickerValue =
|
||||||
undefined[] |
|
| undefined[]
|
||||||
[moment.Moment] |
|
| [moment.Moment]
|
||||||
[undefined, moment.Moment] |
|
| [undefined, moment.Moment]
|
||||||
[moment.Moment, moment.Moment];
|
| [moment.Moment, moment.Moment];
|
||||||
export type RangePickerPresetRange = RangePickerValue | (() => RangePickerValue);
|
export type RangePickerPresetRange = RangePickerValue | (() => RangePickerValue);
|
||||||
|
|
||||||
export interface RangePickerProps extends PickerProps {
|
export interface RangePickerProps extends PickerProps {
|
||||||
@ -68,14 +70,17 @@ export interface RangePickerProps extends PickerProps {
|
|||||||
onOk?: (selectedTime: moment.Moment) => void;
|
onOk?: (selectedTime: moment.Moment) => void;
|
||||||
showTime?: TimePickerProps | boolean;
|
showTime?: TimePickerProps | boolean;
|
||||||
ranges?: {
|
ranges?: {
|
||||||
[range: string]: RangePickerPresetRange,
|
[range: string]: RangePickerPresetRange;
|
||||||
};
|
};
|
||||||
placeholder?: [string, string];
|
placeholder?: [string, string];
|
||||||
mode?: string | string[];
|
mode?: string | string[];
|
||||||
disabledTime?: (current: moment.Moment, type: string) => {
|
disabledTime?: (
|
||||||
disabledHours?: () => number[],
|
current: moment.Moment,
|
||||||
disabledMinutes?: () => number[],
|
type: string,
|
||||||
disabledSeconds?: () => number[],
|
) => {
|
||||||
|
disabledHours?: () => number[];
|
||||||
|
disabledMinutes?: () => number[];
|
||||||
|
disabledSeconds?: () => number[];
|
||||||
};
|
};
|
||||||
onPanelChange?: (value?: RangePickerValue, mode?: string | string[]) => void;
|
onPanelChange?: (value?: RangePickerValue, mode?: string | string[]) => void;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
{
|
{
|
||||||
"lang": {
|
"lang": {
|
||||||
"placeholder": "Select date",
|
"placeholder": "Select date",
|
||||||
"rangePlaceholder": [
|
"rangePlaceholder": ["Start date", "End date"],
|
||||||
"Start date",
|
|
||||||
"End date"
|
|
||||||
],
|
|
||||||
"today": "Today",
|
"today": "Today",
|
||||||
"now": "Now",
|
"now": "Now",
|
||||||
"backToToday": "Back to today",
|
"backToToday": "Back to today",
|
||||||
|
@ -5,7 +5,7 @@ import TimePickerLocale from '../../time-picker/locale/it_IT';
|
|||||||
const locale = {
|
const locale = {
|
||||||
lang: {
|
lang: {
|
||||||
placeholder: 'Selezionare la data',
|
placeholder: 'Selezionare la data',
|
||||||
rangePlaceholder: ['Data d\'inizio', 'Data di fine'],
|
rangePlaceholder: ["Data d'inizio", 'Data di fine'],
|
||||||
...CalendarLocale,
|
...CalendarLocale,
|
||||||
},
|
},
|
||||||
timePickerLocale: {
|
timePickerLocale: {
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
color: @text-color-secondary;
|
color: @text-color-secondary;
|
||||||
font-family: Arial, "Hiragino Sans GB", "Microsoft Yahei", "Microsoft Sans Serif", sans-serif;
|
font-family: Arial, 'Hiragino Sans GB', 'Microsoft Yahei', 'Microsoft Sans Serif', sans-serif;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -214,7 +214,9 @@
|
|||||||
background: tint(@primary-color, 80%);
|
background: tint(@primary-color, 80%);
|
||||||
}
|
}
|
||||||
|
|
||||||
&-selected-date, &-selected-start-date, &-selected-end-date {
|
&-selected-date,
|
||||||
|
&-selected-start-date,
|
||||||
|
&-selected-end-date {
|
||||||
.@{calendar-prefix-cls}-date {
|
.@{calendar-prefix-cls}-date {
|
||||||
background: @primary-color;
|
background: @primary-color;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@ -243,7 +245,7 @@
|
|||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
&:before {
|
&:before {
|
||||||
content: " ";
|
content: ' ';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -1px;
|
top: -1px;
|
||||||
left: 5px;
|
left: 5px;
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.@{calendar-prefix-cls}-decade-panel-header {
|
.@{calendar-prefix-cls}-decade-panel-header {
|
||||||
.calendarPanelHeader(~"@{calendar-prefix-cls}-decade-panel");
|
.calendarPanelHeader(~'@{calendar-prefix-cls}-decade-panel');
|
||||||
}
|
}
|
||||||
|
|
||||||
.@{calendar-prefix-cls}-decade-panel-body {
|
.@{calendar-prefix-cls}-decade-panel-body {
|
||||||
height: ~"calc(100% - 40px)";
|
height: ~'calc(100% - 40px)';
|
||||||
}
|
}
|
||||||
|
|
||||||
.@{calendar-prefix-cls}-decade-panel-table {
|
.@{calendar-prefix-cls}-decade-panel-table {
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
background: @component-background;
|
background: @component-background;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
> div { // TODO: this is a useless wrapper, and we need to remove it in rc-calendar
|
> div {
|
||||||
|
// TODO: this is a useless wrapper, and we need to remove it in rc-calendar
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -19,11 +20,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.@{calendar-prefix-cls}-month-panel-header {
|
.@{calendar-prefix-cls}-month-panel-header {
|
||||||
.calendarPanelHeader(~"@{calendar-prefix-cls}-month-panel");
|
.calendarPanelHeader(~'@{calendar-prefix-cls}-month-panel');
|
||||||
}
|
}
|
||||||
|
|
||||||
.@{calendar-prefix-cls}-month-panel-body {
|
.@{calendar-prefix-cls}-month-panel-body {
|
||||||
height: ~"calc(100% - 40px)";
|
height: ~'calc(100% - 40px)';
|
||||||
}
|
}
|
||||||
|
|
||||||
.@{calendar-prefix-cls}-month-panel-table {
|
.@{calendar-prefix-cls}-month-panel-table {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@import "../../button/style/mixin";
|
@import '../../button/style/mixin';
|
||||||
|
|
||||||
.@{calendar-prefix-cls}-picker-container {
|
.@{calendar-prefix-cls}-picker-container {
|
||||||
.reset-component;
|
.reset-component;
|
||||||
@ -65,7 +65,7 @@
|
|||||||
margin-top: -7px;
|
margin-top: -7px;
|
||||||
line-height: 14px;
|
line-height: 14px;
|
||||||
font-size: @font-size-sm;
|
font-size: @font-size-sm;
|
||||||
transition: all .3s;
|
transition: all 0.3s;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
@ -89,7 +89,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-icon {
|
&-icon {
|
||||||
font-family: "anticon";
|
font-family: 'anticon';
|
||||||
font-size: @font-size-base;
|
font-size: @font-size-base;
|
||||||
color: @disabled-color;
|
color: @disabled-color;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
.@{calendar-prefix-cls}-date-panel {
|
.@{calendar-prefix-cls}-date-panel {
|
||||||
&::after {
|
&::after {
|
||||||
content: ".";
|
content: '.';
|
||||||
display: block;
|
display: block;
|
||||||
height: 0;
|
height: 0;
|
||||||
clear: both;
|
clear: both;
|
||||||
@ -134,7 +134,7 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
&:before {
|
&:before {
|
||||||
content: "";
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
background: @item-active-bg;
|
background: @item-active-bg;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
@ -90,7 +90,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
li:last-child:after {
|
li:last-child:after {
|
||||||
content: "";
|
content: '';
|
||||||
height: 202px;
|
height: 202px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
.@{calendar-prefix-cls}-body tr {
|
.@{calendar-prefix-cls}-body tr {
|
||||||
transition: all .3s;
|
transition: all 0.3s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
background: @primary-1;
|
background: @primary-1;
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
background: @component-background;
|
background: @component-background;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
> div { // TODO: this is a useless wrapper, and we need to remove it in rc-calendar
|
> div {
|
||||||
|
// TODO: this is a useless wrapper, and we need to remove it in rc-calendar
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -19,11 +20,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.@{calendar-prefix-cls}-year-panel-header {
|
.@{calendar-prefix-cls}-year-panel-header {
|
||||||
.calendarPanelHeader(~"@{calendar-prefix-cls}-year-panel");
|
.calendarPanelHeader(~'@{calendar-prefix-cls}-year-panel');
|
||||||
}
|
}
|
||||||
|
|
||||||
.@{calendar-prefix-cls}-year-panel-body {
|
.@{calendar-prefix-cls}-year-panel-body {
|
||||||
height: ~"calc(100% - 40px)";
|
height: ~'calc(100% - 40px)';
|
||||||
}
|
}
|
||||||
|
|
||||||
.@{calendar-prefix-cls}-year-panel-table {
|
.@{calendar-prefix-cls}-year-panel-table {
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
@import "../../input/style/mixin";
|
@import '../../input/style/mixin';
|
||||||
@import "../../button/style/mixin";
|
@import '../../button/style/mixin';
|
||||||
|
|
||||||
@calendar-prefix-cls: ~"@{ant-prefix}-calendar";
|
@calendar-prefix-cls: ~'@{ant-prefix}-calendar';
|
||||||
@calendar-timepicker-prefix-cls: ~"@{ant-prefix}-calendar-time-picker";
|
@calendar-timepicker-prefix-cls: ~'@{ant-prefix}-calendar-time-picker';
|
||||||
|
|
||||||
@import "Picker";
|
@import 'Picker';
|
||||||
@import "Calendar";
|
@import 'Calendar';
|
||||||
@import "RangePicker";
|
@import 'RangePicker';
|
||||||
@import "TimePicker";
|
@import 'TimePicker';
|
||||||
@import "MonthPanel";
|
@import 'MonthPanel';
|
||||||
@import "YearPanel";
|
@import 'YearPanel';
|
||||||
@import "DecadePanel";
|
@import 'DecadePanel';
|
||||||
@import "MonthPicker";
|
@import 'MonthPicker';
|
||||||
@import "WeekPicker";
|
@import 'WeekPicker';
|
||||||
|
@ -28,12 +28,9 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, defaultFor
|
|||||||
format: defaultFormat || 'YYYY-MM-DD',
|
format: defaultFormat || 'YYYY-MM-DD',
|
||||||
transitionName: 'slide-up',
|
transitionName: 'slide-up',
|
||||||
popupStyle: {},
|
popupStyle: {},
|
||||||
onChange() {
|
onChange() {},
|
||||||
},
|
onOk() {},
|
||||||
onOk() {
|
onOpenChange() {},
|
||||||
},
|
|
||||||
onOpenChange() {
|
|
||||||
},
|
|
||||||
locale: {},
|
locale: {},
|
||||||
prefixCls: 'ant-calendar',
|
prefixCls: 'ant-calendar',
|
||||||
inputPrefixCls: 'ant-input',
|
inputPrefixCls: 'ant-input',
|
||||||
@ -51,35 +48,35 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, defaultFor
|
|||||||
handleOpenChange = (open: boolean) => {
|
handleOpenChange = (open: boolean) => {
|
||||||
const { onOpenChange } = this.props;
|
const { onOpenChange } = this.props;
|
||||||
onOpenChange(open);
|
onOpenChange(open);
|
||||||
}
|
};
|
||||||
|
|
||||||
handleFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {
|
handleFocus: React.FocusEventHandler<HTMLInputElement> = e => {
|
||||||
const { onFocus } = this.props;
|
const { onFocus } = this.props;
|
||||||
if (onFocus) {
|
if (onFocus) {
|
||||||
onFocus(e);
|
onFocus(e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleBlur: React.FocusEventHandler<HTMLInputElement> = (e) => {
|
handleBlur: React.FocusEventHandler<HTMLInputElement> = e => {
|
||||||
const { onBlur } = this.props;
|
const { onBlur } = this.props;
|
||||||
if (onBlur) {
|
if (onBlur) {
|
||||||
onBlur(e);
|
onBlur(e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleMouseEnter: React.MouseEventHandler<HTMLInputElement> = (e) => {
|
handleMouseEnter: React.MouseEventHandler<HTMLInputElement> = e => {
|
||||||
const { onMouseEnter } = this.props;
|
const { onMouseEnter } = this.props;
|
||||||
if (onMouseEnter) {
|
if (onMouseEnter) {
|
||||||
onMouseEnter(e);
|
onMouseEnter(e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleMouseLeave: React.MouseEventHandler<HTMLInputElement> = (e) => {
|
handleMouseLeave: React.MouseEventHandler<HTMLInputElement> = e => {
|
||||||
const { onMouseLeave } = this.props;
|
const { onMouseLeave } = this.props;
|
||||||
if (onMouseLeave) {
|
if (onMouseLeave) {
|
||||||
onMouseLeave(e);
|
onMouseLeave(e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
this.picker.focus();
|
this.picker.focus();
|
||||||
@ -91,7 +88,7 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, defaultFor
|
|||||||
|
|
||||||
savePicker = (node: any) => {
|
savePicker = (node: any) => {
|
||||||
this.picker = node;
|
this.picker = node;
|
||||||
}
|
};
|
||||||
|
|
||||||
getDefaultLocale = () => {
|
getDefaultLocale = () => {
|
||||||
const result = {
|
const result = {
|
||||||
@ -103,7 +100,7 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, defaultFor
|
|||||||
...(this.props.locale || {}).lang,
|
...(this.props.locale || {}).lang,
|
||||||
};
|
};
|
||||||
return result;
|
return result;
|
||||||
}
|
};
|
||||||
|
|
||||||
renderPicker = (locale: any, localeCode: string) => {
|
renderPicker = (locale: any, localeCode: string) => {
|
||||||
const props = this.props;
|
const props = this.props;
|
||||||
@ -121,7 +118,7 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, defaultFor
|
|||||||
const rcTimePickerProps = {
|
const rcTimePickerProps = {
|
||||||
...generateShowHourMinuteSecond(timeFormat),
|
...generateShowHourMinuteSecond(timeFormat),
|
||||||
format: timeFormat,
|
format: timeFormat,
|
||||||
use12Hours: (props.showTime && props.showTime.use12Hours),
|
use12Hours: props.showTime && props.showTime.use12Hours,
|
||||||
};
|
};
|
||||||
const columns = getColumns(rcTimePickerProps);
|
const columns = getColumns(rcTimePickerProps);
|
||||||
const timePickerCls = `${prefixCls}-time-picker-column-${columns}`;
|
const timePickerCls = `${prefixCls}-time-picker-column-${columns}`;
|
||||||
@ -152,14 +149,11 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, defaultFor
|
|||||||
onMouseLeave={this.handleMouseLeave}
|
onMouseLeave={this.handleMouseLeave}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<LocaleReceiver
|
<LocaleReceiver componentName="DatePicker" defaultLocale={this.getDefaultLocale}>
|
||||||
componentName="DatePicker"
|
|
||||||
defaultLocale={this.getDefaultLocale}
|
|
||||||
>
|
|
||||||
{this.renderPicker}
|
{this.renderPicker}
|
||||||
</LocaleReceiver>
|
</LocaleReceiver>
|
||||||
);
|
);
|
||||||
|
@ -20,12 +20,16 @@ export default function Divider({
|
|||||||
dashed,
|
dashed,
|
||||||
...restProps
|
...restProps
|
||||||
}: DividerProps) {
|
}: DividerProps) {
|
||||||
const orientationPrefix = (orientation.length > 0) ? '-' + orientation : orientation;
|
const orientationPrefix = orientation.length > 0 ? '-' + orientation : orientation;
|
||||||
const classString = classNames(
|
const classString = classNames(
|
||||||
className, `${prefixCls}-divider`, `${prefixCls}-divider-${type}`, {
|
className,
|
||||||
|
`${prefixCls}-divider`,
|
||||||
|
`${prefixCls}-divider-${type}`,
|
||||||
|
{
|
||||||
[`${prefixCls}-divider-with-text${orientationPrefix}`]: children,
|
[`${prefixCls}-divider-with-text${orientationPrefix}`]: children,
|
||||||
[`${prefixCls}-divider-dashed`]: !!dashed,
|
[`${prefixCls}-divider-dashed`]: !!dashed,
|
||||||
});
|
},
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<div className={classString} {...restProps}>
|
<div className={classString} {...restProps}>
|
||||||
{children && <span className={`${prefixCls}-divider-inner-text`}>{children}</span>}
|
{children && <span className={`${prefixCls}-divider-inner-text`}>{children}</span>}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@import "../../style/themes/default";
|
@import '../../style/themes/default';
|
||||||
@import "../../style/mixins/index";
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
@divider-prefix-cls: ~"@{ant-prefix}-divider";
|
@divider-prefix-cls: ~'@{ant-prefix}-divider';
|
||||||
|
|
||||||
.@{divider-prefix-cls} {
|
.@{divider-prefix-cls} {
|
||||||
.reset-component;
|
.reset-component;
|
||||||
@ -39,7 +39,7 @@
|
|||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
&:before,
|
&:before,
|
||||||
&:after {
|
&:after {
|
||||||
content: "";
|
content: '';
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
@ -5,80 +5,54 @@ import Drawer from '..';
|
|||||||
describe('Drawer', () => {
|
describe('Drawer', () => {
|
||||||
it('render correctly', () => {
|
it('render correctly', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(
|
||||||
<Drawer
|
<Drawer visible width={400} getContainer={false}>
|
||||||
visible
|
|
||||||
width={400}
|
|
||||||
getContainer={false}
|
|
||||||
>
|
|
||||||
Here is content of Drawer
|
Here is content of Drawer
|
||||||
</Drawer>
|
</Drawer>,
|
||||||
);
|
);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('render top drawer', () => {
|
it('render top drawer', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(
|
||||||
<Drawer
|
<Drawer visible height={400} placement="top" getContainer={false}>
|
||||||
visible
|
|
||||||
height={400}
|
|
||||||
placement="top"
|
|
||||||
getContainer={false}
|
|
||||||
>
|
|
||||||
Here is content of Drawer
|
Here is content of Drawer
|
||||||
</Drawer>
|
</Drawer>,
|
||||||
);
|
);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('have a title', () => {
|
it('have a title', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(
|
||||||
<Drawer
|
<Drawer visible title="Test Title" getContainer={false}>
|
||||||
visible
|
|
||||||
title="Test Title"
|
|
||||||
getContainer={false}
|
|
||||||
>
|
|
||||||
Here is content of Drawer
|
Here is content of Drawer
|
||||||
</Drawer>
|
</Drawer>,
|
||||||
);
|
);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('closable is false', () => {
|
it('closable is false', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(
|
||||||
<Drawer
|
<Drawer visible closable={false} getContainer={false}>
|
||||||
visible
|
|
||||||
closable={false}
|
|
||||||
getContainer={false}
|
|
||||||
>
|
|
||||||
Here is content of Drawer
|
Here is content of Drawer
|
||||||
</Drawer>
|
</Drawer>,
|
||||||
);
|
);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('destroyOnClose is true', () => {
|
it('destroyOnClose is true', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(
|
||||||
<Drawer
|
<Drawer destroyOnClose visible={false} getContainer={false}>
|
||||||
destroyOnClose
|
|
||||||
visible={false}
|
|
||||||
getContainer={false}
|
|
||||||
>
|
|
||||||
Here is content of Drawer
|
Here is content of Drawer
|
||||||
</Drawer>
|
</Drawer>,
|
||||||
);
|
);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('className is test_drawer', () => {
|
it('className is test_drawer', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(
|
||||||
<Drawer
|
<Drawer destroyOnClose visible={false} className="test_drawer" getContainer={false}>
|
||||||
destroyOnClose
|
|
||||||
visible={false}
|
|
||||||
className="test_drawer"
|
|
||||||
getContainer={false}
|
|
||||||
>
|
|
||||||
Here is content of Drawer
|
Here is content of Drawer
|
||||||
</Drawer>
|
</Drawer>,
|
||||||
);
|
);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
@ -23,19 +23,14 @@ class DrawerEventTester extends React.Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { visible } = this.state;
|
const { visible } = this.state;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Button onClick={this.open}>open</Button>
|
<Button onClick={this.open}>open</Button>
|
||||||
<Drawer
|
<Drawer visible={visible} onClose={this.onClose} getContainer={false} {...this.props}>
|
||||||
visible={visible}
|
|
||||||
onClose={this.onClose}
|
|
||||||
getContainer={false}
|
|
||||||
{...this.props}
|
|
||||||
>
|
|
||||||
Here is content of Drawer
|
Here is content of Drawer
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</div>
|
</div>
|
||||||
@ -43,7 +38,6 @@ class DrawerEventTester extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
describe('Drawer', () => {
|
describe('Drawer', () => {
|
||||||
it('render correctly', () => {
|
it('render correctly', () => {
|
||||||
const wrapper = mount(<DrawerEventTester />);
|
const wrapper = mount(<DrawerEventTester />);
|
||||||
|
@ -59,9 +59,7 @@ class MultiDrawer extends React.Component {
|
|||||||
onClose={this.onChildrenDrawerClose}
|
onClose={this.onChildrenDrawerClose}
|
||||||
visible={childrenDrawer}
|
visible={childrenDrawer}
|
||||||
>
|
>
|
||||||
<div id="two_drawer_text">
|
<div id="two_drawer_text">This is two-level drawer</div>
|
||||||
This is two-level drawer
|
|
||||||
</div>
|
|
||||||
</Drawer>
|
</Drawer>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
@ -8,9 +8,7 @@ import Icon from '../icon';
|
|||||||
|
|
||||||
const DrawerContext: Context<Drawer | null> = createReactContext(null);
|
const DrawerContext: Context<Drawer | null> = createReactContext(null);
|
||||||
|
|
||||||
type EventType =
|
type EventType = React.MouseEvent<HTMLDivElement> | React.MouseEvent<HTMLButtonElement>;
|
||||||
| React.MouseEvent<HTMLDivElement>
|
|
||||||
| React.MouseEvent<HTMLButtonElement>;
|
|
||||||
|
|
||||||
type getContainerfunc = () => HTMLElement;
|
type getContainerfunc = () => HTMLElement;
|
||||||
|
|
||||||
@ -100,26 +98,26 @@ export default class Drawer extends React.Component<DrawerProps, IDrawerState> {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
onMaskClick = (e: EventType) => {
|
onMaskClick = (e: EventType) => {
|
||||||
if (!this.props.maskClosable) {
|
if (!this.props.maskClosable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.close(e);
|
this.close(e);
|
||||||
}
|
};
|
||||||
|
|
||||||
push = () => {
|
push = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
push: true,
|
push: true,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
pull = () => {
|
pull = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
push: false,
|
push: false,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
onDestoryTransitionEnd = () => {
|
onDestoryTransitionEnd = () => {
|
||||||
const isDestroyOnClose = this.getDestoryOnClose();
|
const isDestroyOnClose = this.getDestoryOnClose();
|
||||||
@ -130,9 +128,9 @@ export default class Drawer extends React.Component<DrawerProps, IDrawerState> {
|
|||||||
this.destoryClose = true;
|
this.destoryClose = true;
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
getDestoryOnClose = () => (this.props.destroyOnClose && !this.props.visible);
|
getDestoryOnClose = () => this.props.destroyOnClose && !this.props.visible;
|
||||||
|
|
||||||
// get drawar push width or height
|
// get drawar push width or height
|
||||||
getPushTransform = (placement?: placementType) => {
|
getPushTransform = (placement?: placementType) => {
|
||||||
@ -142,7 +140,7 @@ export default class Drawer extends React.Component<DrawerProps, IDrawerState> {
|
|||||||
if (placement === 'top' || placement === 'bottom') {
|
if (placement === 'top' || placement === 'bottom') {
|
||||||
return `translateY(${placement === 'top' ? 180 : -180}px)`;
|
return `translateY(${placement === 'top' ? 180 : -180}px)`;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// render drawer body dom
|
// render drawer body dom
|
||||||
renderBody = () => {
|
renderBody = () => {
|
||||||
@ -152,11 +150,13 @@ export default class Drawer extends React.Component<DrawerProps, IDrawerState> {
|
|||||||
this.destoryClose = false;
|
this.destoryClose = false;
|
||||||
const { placement } = this.props;
|
const { placement } = this.props;
|
||||||
|
|
||||||
const containerStyle: React.CSSProperties = placement === 'left'
|
const containerStyle: React.CSSProperties =
|
||||||
|| placement === 'right' ? {
|
placement === 'left' || placement === 'right'
|
||||||
|
? {
|
||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
} : {};
|
}
|
||||||
|
: {};
|
||||||
|
|
||||||
const isDestroyOnClose = this.getDestoryOnClose();
|
const isDestroyOnClose = this.getDestoryOnClose();
|
||||||
|
|
||||||
@ -180,11 +180,7 @@ export default class Drawer extends React.Component<DrawerProps, IDrawerState> {
|
|||||||
let closer;
|
let closer;
|
||||||
if (closable) {
|
if (closable) {
|
||||||
closer = (
|
closer = (
|
||||||
<button
|
<button onClick={this.close} aria-label="Close" className={`${prefixCls}-close`}>
|
||||||
onClick={this.close}
|
|
||||||
aria-label="Close"
|
|
||||||
className={`${prefixCls}-close`}
|
|
||||||
>
|
|
||||||
<span className={`${prefixCls}-close-x`}>
|
<span className={`${prefixCls}-close-x`}>
|
||||||
<Icon type="close" />
|
<Icon type="close" />
|
||||||
</span>
|
</span>
|
||||||
@ -205,7 +201,7 @@ export default class Drawer extends React.Component<DrawerProps, IDrawerState> {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
getRcDrawerStyle = () => {
|
getRcDrawerStyle = () => {
|
||||||
const { zIndex, placement, maskStyle } = this.props;
|
const { zIndex, placement, maskStyle } = this.props;
|
||||||
@ -219,13 +215,25 @@ export default class Drawer extends React.Component<DrawerProps, IDrawerState> {
|
|||||||
...maskStyle,
|
...maskStyle,
|
||||||
zIndex,
|
zIndex,
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
// render Provider for Multi-level drawe
|
// render Provider for Multi-level drawe
|
||||||
renderProvider = (value: Drawer) => {
|
renderProvider = (value: Drawer) => {
|
||||||
const { zIndex, style, placement, className, wrapClassName, width, height, ...rest } = this.props;
|
const {
|
||||||
warning(wrapClassName === undefined, 'wrapClassName is deprecated, please use className instead.');
|
zIndex,
|
||||||
const haveMask = rest.mask ? "" : "no-mask";
|
style,
|
||||||
|
placement,
|
||||||
|
className,
|
||||||
|
wrapClassName,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
...rest
|
||||||
|
} = this.props;
|
||||||
|
warning(
|
||||||
|
wrapClassName === undefined,
|
||||||
|
'wrapClassName is deprecated, please use className instead.',
|
||||||
|
);
|
||||||
|
const haveMask = rest.mask ? '' : 'no-mask';
|
||||||
this.parentDrawer = value;
|
this.parentDrawer = value;
|
||||||
const offsetStyle: any = {};
|
const offsetStyle: any = {};
|
||||||
if (placement === 'left' || placement === 'right') {
|
if (placement === 'left' || placement === 'right') {
|
||||||
@ -250,11 +258,9 @@ export default class Drawer extends React.Component<DrawerProps, IDrawerState> {
|
|||||||
</RcDrawer>
|
</RcDrawer>
|
||||||
</DrawerContext.Provider>
|
</DrawerContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return <DrawerContext.Consumer>{this.renderProvider}</DrawerContext.Consumer>;
|
||||||
<DrawerContext.Consumer>{this.renderProvider}</DrawerContext.Consumer>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user