mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 02:59:04 +08:00
Merge pull request #18051 from orzyyyy/perf
perf: migrate tslint to eslint
This commit is contained in:
commit
109bd4ecde
56
.eslintrc.js
56
.eslintrc.js
@ -1,5 +1,12 @@
|
||||
const eslintrc = {
|
||||
extends: ['airbnb', 'prettier', 'plugin:jest/recommended'],
|
||||
extends: [
|
||||
'airbnb',
|
||||
'prettier',
|
||||
'plugin:jest/recommended',
|
||||
'plugin:react/recommended',
|
||||
'plugin:import/typescript',
|
||||
'prettier/react',
|
||||
],
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
@ -7,8 +14,22 @@ const eslintrc = {
|
||||
jest: true,
|
||||
es6: true,
|
||||
},
|
||||
parser: 'babel-eslint',
|
||||
plugins: ['markdown', 'react', 'babel', 'jest'],
|
||||
settings: {
|
||||
react: {
|
||||
version: '16.8',
|
||||
},
|
||||
},
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['markdown', 'react', 'babel', 'jest', '@typescript-eslint'],
|
||||
// https://github.com/typescript-eslint/typescript-eslint/issues/46#issuecomment-470486034
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.tsx'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-unused-vars': [2, { args: 'none' }],
|
||||
},
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
'react/jsx-one-expression-per-line': 0,
|
||||
'react/prop-types': 0,
|
||||
@ -29,12 +50,34 @@ const eslintrc = {
|
||||
],
|
||||
},
|
||||
],
|
||||
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx', '.md'] }],
|
||||
'jsx-a11y/no-static-element-interactions': 0,
|
||||
'jsx-a11y/anchor-has-content': 0,
|
||||
'jsx-a11y/click-events-have-key-events': 0,
|
||||
'jsx-a11y/anchor-is-valid': 0,
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
'react/jsx-filename-extension': 0,
|
||||
'prefer-destructuring': 0, // TODO: remove later
|
||||
'consistent-return': 0, // TODO: remove later
|
||||
'no-return-assign': 0, // TODO: remove later
|
||||
'no-param-reassign': 0, // TODO: remove later
|
||||
'react/destructuring-assignment': 0, // TODO: remove later
|
||||
'react/no-did-update-set-state': 0, // TODO: remove later
|
||||
'react/require-default-props': 0,
|
||||
'react/default-props-match-prop-types': 0,
|
||||
'import/no-cycle': 0,
|
||||
'react/no-find-dom-node': 0,
|
||||
'no-underscore-dangle': 0,
|
||||
// label-has-for has been deprecated
|
||||
// https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/label-has-for.md
|
||||
'jsx-a11y/label-has-for': 0,
|
||||
// for (let i = 0; i < len; i++)
|
||||
'no-plusplus': 0,
|
||||
// https://eslint.org/docs/rules/no-continue
|
||||
// labeledLoop is conflicted with `eslint . --fix`
|
||||
'no-continue': 0,
|
||||
'react/display-name': 0,
|
||||
// ban this for Number.isNaN needs polyfill
|
||||
'no-restricted-globals': 0,
|
||||
},
|
||||
};
|
||||
|
||||
@ -56,11 +99,6 @@ if (process.env.RUN_ENV === 'DEMO') {
|
||||
'react/destructuring-assignment': 0,
|
||||
'react/no-multi-comp': 0,
|
||||
'jsx-a11y/href-no-hash': 0,
|
||||
'prefer-destructuring': 0, // TODO: remove later
|
||||
'max-len': 0, // TODO: remove later
|
||||
'consistent-return': 0, // TODO: remove later
|
||||
'no-return-assign': 0, // TODO: remove later
|
||||
'no-param-reassign': 0, // TODO: remove later
|
||||
'import/no-extraneous-dependencies': 0,
|
||||
});
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ const getCollapsedHeight: MotionFunc = () => ({ height: 0, opacity: 0 });
|
||||
const getRealHeight: MotionFunc = node => ({ height: node.scrollHeight, opacity: 1 });
|
||||
const getCurrentHeight: MotionFunc = node => ({ height: node.offsetHeight });
|
||||
|
||||
export const collapseMotion: Motion = {
|
||||
const collapseMotion: Motion = {
|
||||
motionName: 'ant-motion-collapse',
|
||||
onAppearStart: getCollapsedHeight,
|
||||
onEnterStart: getCollapsedHeight,
|
||||
@ -36,3 +36,5 @@ export const collapseMotion: Motion = {
|
||||
onLeaveStart: getCurrentHeight,
|
||||
onLeaveActive: getCollapsedHeight,
|
||||
};
|
||||
|
||||
export default collapseMotion;
|
||||
|
@ -26,6 +26,7 @@ export function throttleByAnimationFrameDecorator() {
|
||||
return {
|
||||
configurable: true,
|
||||
get() {
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
if (definingProperty || this === target.prototype || this.hasOwnProperty(key)) {
|
||||
return fn;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ const inlineStyle: React.CSSProperties = {
|
||||
|
||||
class TransButton extends React.Component<TransButtonProps> {
|
||||
div?: HTMLDivElement;
|
||||
|
||||
lastKeyCode?: number;
|
||||
|
||||
onKeyDown: React.KeyboardEventHandler<HTMLDivElement> = event => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import TransitionEvents from 'css-animation/lib/Event';
|
||||
import raf from '../_util/raf';
|
||||
import raf from './raf';
|
||||
import { ConfigConsumer, ConfigConsumerProps, CSPConfig } from '../config-provider';
|
||||
|
||||
let styleForPesudo: HTMLStyleElement | null;
|
||||
@ -14,24 +14,49 @@ function isHidden(element: HTMLElement) {
|
||||
return !element || element.offsetParent === null;
|
||||
}
|
||||
|
||||
function isNotGrey(color: string) {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\.\d]*)?\)/);
|
||||
if (match && match[1] && match[2] && match[3]) {
|
||||
return !(match[1] === match[2] && match[2] === match[3]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export default class Wave extends React.Component<{ insertExtraNode?: boolean }> {
|
||||
private instance?: {
|
||||
cancel: () => void;
|
||||
};
|
||||
|
||||
private extraNode: HTMLDivElement;
|
||||
|
||||
private clickWaveTimeoutId: number;
|
||||
|
||||
private animationStartId: number;
|
||||
|
||||
private animationStart: boolean = false;
|
||||
|
||||
private destroy: boolean = false;
|
||||
|
||||
private csp?: CSPConfig;
|
||||
|
||||
isNotGrey(color: string) {
|
||||
const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\.\d]*)?\)/);
|
||||
if (match && match[1] && match[2] && match[3]) {
|
||||
return !(match[1] === match[2] && match[2] === match[3]);
|
||||
componentDidMount() {
|
||||
const node = findDOMNode(this) as HTMLElement;
|
||||
if (!node || node.nodeType !== 1) {
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
this.instance = this.bindAnimationEvent(node);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.instance) {
|
||||
this.instance.cancel();
|
||||
}
|
||||
if (this.clickWaveTimeoutId) {
|
||||
clearTimeout(this.clickWaveTimeoutId);
|
||||
}
|
||||
|
||||
this.destroy = true;
|
||||
}
|
||||
|
||||
onClick = (node: HTMLElement, waveColor: string) => {
|
||||
@ -40,7 +65,7 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
}
|
||||
const { insertExtraNode } = this.props;
|
||||
this.extraNode = document.createElement('div');
|
||||
const extraNode = this.extraNode;
|
||||
const { extraNode } = this;
|
||||
extraNode.className = 'ant-click-animating-node';
|
||||
const attributeName = this.getAttributeName();
|
||||
node.setAttribute(attributeName, 'true');
|
||||
@ -50,7 +75,7 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
waveColor &&
|
||||
waveColor !== '#ffffff' &&
|
||||
waveColor !== 'rgb(255, 255, 255)' &&
|
||||
this.isNotGrey(waveColor) &&
|
||||
isNotGrey(waveColor) &&
|
||||
!/rgba\(\d*, \d*, \d*, 0\)/.test(waveColor) && // any transparent rgba color
|
||||
waveColor !== 'transparent'
|
||||
) {
|
||||
@ -75,6 +100,31 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
TransitionEvents.addEndEventListener(node, this.onTransitionEnd);
|
||||
};
|
||||
|
||||
onTransitionStart = (e: AnimationEvent) => {
|
||||
if (this.destroy) return;
|
||||
|
||||
const node = findDOMNode(this) as HTMLElement;
|
||||
if (!e || e.target !== node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.animationStart) {
|
||||
this.resetEffect(node);
|
||||
}
|
||||
};
|
||||
|
||||
onTransitionEnd = (e: AnimationEvent) => {
|
||||
if (!e || e.animationName !== 'fadeEffect') {
|
||||
return;
|
||||
}
|
||||
this.resetEffect(e.target as HTMLElement);
|
||||
};
|
||||
|
||||
getAttributeName() {
|
||||
const { insertExtraNode } = this.props;
|
||||
return insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node';
|
||||
}
|
||||
|
||||
bindAnimationEvent = (node: HTMLElement) => {
|
||||
if (
|
||||
!node ||
|
||||
@ -113,11 +163,6 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
};
|
||||
};
|
||||
|
||||
getAttributeName() {
|
||||
const { insertExtraNode } = this.props;
|
||||
return insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node';
|
||||
}
|
||||
|
||||
resetEffect(node: HTMLElement) {
|
||||
if (!node || node === this.extraNode || !(node instanceof Element)) {
|
||||
return;
|
||||
@ -125,7 +170,11 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
const { insertExtraNode } = this.props;
|
||||
const attributeName = this.getAttributeName();
|
||||
node.setAttribute(attributeName, 'false'); // edge has bug on `removeAttribute` #14466
|
||||
this.removeExtraStyleNode();
|
||||
|
||||
if (styleForPesudo) {
|
||||
styleForPesudo.innerHTML = '';
|
||||
}
|
||||
|
||||
if (insertExtraNode && this.extraNode && node.contains(this.extraNode)) {
|
||||
node.removeChild(this.extraNode);
|
||||
}
|
||||
@ -133,51 +182,6 @@ export default class Wave extends React.Component<{ insertExtraNode?: boolean }>
|
||||
TransitionEvents.removeEndEventListener(node, this.onTransitionEnd);
|
||||
}
|
||||
|
||||
onTransitionStart = (e: AnimationEvent) => {
|
||||
if (this.destroy) return;
|
||||
|
||||
const node = findDOMNode(this) as HTMLElement;
|
||||
if (!e || e.target !== node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.animationStart) {
|
||||
this.resetEffect(node);
|
||||
}
|
||||
};
|
||||
|
||||
onTransitionEnd = (e: AnimationEvent) => {
|
||||
if (!e || e.animationName !== 'fadeEffect') {
|
||||
return;
|
||||
}
|
||||
this.resetEffect(e.target as HTMLElement);
|
||||
};
|
||||
|
||||
removeExtraStyleNode() {
|
||||
if (styleForPesudo) {
|
||||
styleForPesudo.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const node = findDOMNode(this) as HTMLElement;
|
||||
if (!node || node.nodeType !== 1) {
|
||||
return;
|
||||
}
|
||||
this.instance = this.bindAnimationEvent(node);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.instance) {
|
||||
this.instance.cancel();
|
||||
}
|
||||
if (this.clickWaveTimeoutId) {
|
||||
clearTimeout(this.clickWaveTimeoutId);
|
||||
}
|
||||
|
||||
this.destroy = true;
|
||||
}
|
||||
|
||||
renderWave = ({ csp }: ConfigConsumerProps) => {
|
||||
const { children } = this.props;
|
||||
this.csp = csp;
|
||||
|
@ -63,7 +63,9 @@ class Affix extends React.Component<AffixProps, AffixState> {
|
||||
};
|
||||
|
||||
placeholderNode: HTMLDivElement;
|
||||
|
||||
fixedNode: HTMLDivElement;
|
||||
|
||||
private timeout: number;
|
||||
|
||||
// Event handler
|
||||
@ -75,7 +77,7 @@ class Affix extends React.Component<AffixProps, AffixState> {
|
||||
this.timeout = setTimeout(() => {
|
||||
addObserveTarget(target(), this);
|
||||
// Mock Event object.
|
||||
this.updatePosition({} as Event);
|
||||
this.updatePosition();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -93,7 +95,7 @@ class Affix extends React.Component<AffixProps, AffixState> {
|
||||
if (newTarget) {
|
||||
addObserveTarget(newTarget, this);
|
||||
// Mock Event object.
|
||||
this.updatePosition({} as Event);
|
||||
this.updatePosition();
|
||||
}
|
||||
|
||||
this.setState({ prevTarget: newTarget });
|
||||
@ -103,7 +105,7 @@ class Affix extends React.Component<AffixProps, AffixState> {
|
||||
prevProps.offsetTop !== this.props.offsetTop ||
|
||||
prevProps.offsetBottom !== this.props.offsetBottom
|
||||
) {
|
||||
this.updatePosition({} as Event);
|
||||
this.updatePosition();
|
||||
}
|
||||
|
||||
this.measure();
|
||||
@ -132,6 +134,7 @@ class Affix extends React.Component<AffixProps, AffixState> {
|
||||
}
|
||||
return offsetTop;
|
||||
};
|
||||
|
||||
getOffsetBottom = () => {
|
||||
return this.props.offsetBottom;
|
||||
};
|
||||
@ -145,60 +148,6 @@ class Affix extends React.Component<AffixProps, AffixState> {
|
||||
};
|
||||
|
||||
// =================== Measure ===================
|
||||
// Handle realign logic
|
||||
@throttleByAnimationFrameDecorator()
|
||||
updatePosition(event?: Event | null) {
|
||||
this.prepareMeasure(event);
|
||||
}
|
||||
|
||||
@throttleByAnimationFrameDecorator()
|
||||
lazyUpdatePosition(event: Event) {
|
||||
const { target } = this.props;
|
||||
const { affixStyle } = this.state;
|
||||
|
||||
// Check position change before measure to make Safari smooth
|
||||
if (target && affixStyle) {
|
||||
const offsetTop = this.getOffsetTop();
|
||||
const offsetBottom = this.getOffsetBottom();
|
||||
|
||||
const targetNode = target();
|
||||
if (targetNode) {
|
||||
const targetRect = getTargetRect(targetNode);
|
||||
const placeholderReact = getTargetRect(this.placeholderNode);
|
||||
const fixedTop = getFixedTop(placeholderReact, targetRect, offsetTop);
|
||||
const fixedBottom = getFixedBottom(placeholderReact, targetRect, offsetBottom);
|
||||
|
||||
if (
|
||||
(fixedTop !== undefined && affixStyle.top === fixedTop) ||
|
||||
(fixedBottom !== undefined && affixStyle.bottom === fixedBottom)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Directly call prepare measure since it's already throttled.
|
||||
this.prepareMeasure(event);
|
||||
}
|
||||
|
||||
// @ts-ignore TS6133
|
||||
prepareMeasure = (event?: Event | null) => {
|
||||
// event param is used before. Keep compatible ts define here.
|
||||
this.setState({
|
||||
status: AffixStatus.Prepare,
|
||||
affixStyle: undefined,
|
||||
placeholderStyle: undefined,
|
||||
});
|
||||
|
||||
// Test if `updatePosition` called
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
const { onTestUpdatePosition } = this.props as any;
|
||||
if (onTestUpdatePosition) {
|
||||
onTestUpdatePosition();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
measure = () => {
|
||||
const { status, lastAffix } = this.state;
|
||||
const { target, onChange } = this.props;
|
||||
@ -254,6 +203,60 @@ class Affix extends React.Component<AffixProps, AffixState> {
|
||||
this.setState(newState as AffixState);
|
||||
};
|
||||
|
||||
// @ts-ignore TS6133
|
||||
prepareMeasure = () => {
|
||||
// event param is used before. Keep compatible ts define here.
|
||||
this.setState({
|
||||
status: AffixStatus.Prepare,
|
||||
affixStyle: undefined,
|
||||
placeholderStyle: undefined,
|
||||
});
|
||||
|
||||
// Test if `updatePosition` called
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
const { onTestUpdatePosition } = this.props as any;
|
||||
if (onTestUpdatePosition) {
|
||||
onTestUpdatePosition();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Handle realign logic
|
||||
@throttleByAnimationFrameDecorator()
|
||||
updatePosition() {
|
||||
this.prepareMeasure();
|
||||
}
|
||||
|
||||
@throttleByAnimationFrameDecorator()
|
||||
lazyUpdatePosition() {
|
||||
const { target } = this.props;
|
||||
const { affixStyle } = this.state;
|
||||
|
||||
// Check position change before measure to make Safari smooth
|
||||
if (target && affixStyle) {
|
||||
const offsetTop = this.getOffsetTop();
|
||||
const offsetBottom = this.getOffsetBottom();
|
||||
|
||||
const targetNode = target();
|
||||
if (targetNode) {
|
||||
const targetRect = getTargetRect(targetNode);
|
||||
const placeholderReact = getTargetRect(this.placeholderNode);
|
||||
const fixedTop = getFixedTop(placeholderReact, targetRect, offsetTop);
|
||||
const fixedBottom = getFixedBottom(placeholderReact, targetRect, offsetBottom);
|
||||
|
||||
if (
|
||||
(fixedTop !== undefined && affixStyle.top === fixedTop) ||
|
||||
(fixedBottom !== undefined && affixStyle.bottom === fixedBottom)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Directly call prepare measure since it's already throttled.
|
||||
this.prepareMeasure();
|
||||
}
|
||||
|
||||
// =================== Render ===================
|
||||
renderAffix = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { affixStyle, placeholderStyle } = this.state;
|
||||
|
@ -74,9 +74,9 @@ export function addObserveTarget(target: HTMLElement | Window | null, affix: Aff
|
||||
|
||||
// Add listener
|
||||
TRIGGER_EVENTS.forEach(eventName => {
|
||||
entity!.eventHandlers[eventName] = addEventListener(target, eventName, (event: Event) => {
|
||||
entity!.affixList.forEach(affix => {
|
||||
affix.lazyUpdatePosition(event);
|
||||
entity!.eventHandlers[eventName] = addEventListener(target, eventName, () => {
|
||||
entity!.affixList.forEach(targetAffix => {
|
||||
targetAffix.lazyUpdatePosition();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -69,6 +69,7 @@ exports[`renders ./components/alert/demo/banner.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-close-icon"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: close"
|
||||
@ -174,6 +175,7 @@ exports[`renders ./components/alert/demo/closable.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-close-icon"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: close"
|
||||
@ -213,6 +215,7 @@ exports[`renders ./components/alert/demo/closable.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-close-icon"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: close"
|
||||
@ -254,6 +257,7 @@ exports[`renders ./components/alert/demo/close-text.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-close-icon"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="ant-alert-close-text"
|
||||
@ -909,6 +913,7 @@ exports[`renders ./components/alert/demo/smooth-closed.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-alert-close-icon"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: close"
|
||||
|
@ -1,8 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import Animate from 'rc-animate';
|
||||
import Icon, { ThemeType } from '../icon';
|
||||
import classNames from 'classnames';
|
||||
import Icon, { ThemeType } from '../icon';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import getDataOrAriaProps from '../_util/getDataOrAriaProps';
|
||||
import warning from '../_util/warning';
|
||||
@ -119,7 +119,7 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
}
|
||||
|
||||
// use outline icon in alert with description
|
||||
if (!!description) {
|
||||
if (description) {
|
||||
iconTheme = 'outlined';
|
||||
}
|
||||
}
|
||||
@ -143,7 +143,12 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
);
|
||||
|
||||
const closeIcon = closable ? (
|
||||
<span role="button" onClick={this.handleClose} className={`${prefixCls}-close-icon`}>
|
||||
<span
|
||||
role="button"
|
||||
onClick={this.handleClose}
|
||||
className={`${prefixCls}-close-icon`}
|
||||
tabIndex={0}
|
||||
>
|
||||
{closeText ? (
|
||||
<span className={`${prefixCls}-close-text`}>{closeText}</span>
|
||||
) : (
|
||||
|
@ -3,11 +3,11 @@ import * as ReactDOM from 'react-dom';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import addEventListener from 'rc-util/lib/Dom/addEventListener';
|
||||
import raf from 'raf';
|
||||
import Affix from '../affix';
|
||||
import AnchorLink from './AnchorLink';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import getScroll from '../_util/getScroll';
|
||||
import raf from 'raf';
|
||||
|
||||
function getDefaultContainer() {
|
||||
return window;
|
||||
@ -145,11 +145,14 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
};
|
||||
|
||||
private inkNode: HTMLSpanElement;
|
||||
|
||||
// scroll scope's container
|
||||
private scrollContainer: HTMLElement | Window;
|
||||
|
||||
private links: string[] = [];
|
||||
|
||||
private scrollEvent: any;
|
||||
|
||||
private animating: boolean;
|
||||
|
||||
private prefixCls?: string;
|
||||
@ -181,12 +184,6 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
this.handleScroll();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.scrollEvent) {
|
||||
this.scrollEvent.remove();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.scrollEvent) {
|
||||
const { getContainer } = this.props as AnchorDefaultProps;
|
||||
@ -201,28 +198,11 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
this.updateInk();
|
||||
}
|
||||
|
||||
handleScroll = () => {
|
||||
if (this.animating) {
|
||||
return;
|
||||
componentWillUnmount() {
|
||||
if (this.scrollEvent) {
|
||||
this.scrollEvent.remove();
|
||||
}
|
||||
const { activeLink } = this.state;
|
||||
const { offsetTop, bounds } = this.props;
|
||||
const currentActiveLink = this.getCurrentAnchor(offsetTop, bounds);
|
||||
if (activeLink !== currentActiveLink) {
|
||||
this.setState({
|
||||
activeLink: currentActiveLink,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleScrollTo = (link: string) => {
|
||||
const { offsetTop, getContainer } = this.props as AnchorDefaultProps;
|
||||
this.animating = true;
|
||||
this.setState({ activeLink: link });
|
||||
scrollTo(link, offsetTop, getContainer, () => {
|
||||
this.animating = false;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
getCurrentAnchor(offsetTop = 0, bounds = 5): string {
|
||||
const activeLink = '';
|
||||
@ -257,11 +237,38 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
return '';
|
||||
}
|
||||
|
||||
saveInkNode = (node: HTMLSpanElement) => {
|
||||
this.inkNode = node;
|
||||
};
|
||||
|
||||
handleScroll = () => {
|
||||
if (this.animating) {
|
||||
return;
|
||||
}
|
||||
const { activeLink } = this.state;
|
||||
const { offsetTop, bounds } = this.props;
|
||||
const currentActiveLink = this.getCurrentAnchor(offsetTop, bounds);
|
||||
if (activeLink !== currentActiveLink) {
|
||||
this.setState({
|
||||
activeLink: currentActiveLink,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleScrollTo = (link: string) => {
|
||||
const { offsetTop, getContainer } = this.props as AnchorDefaultProps;
|
||||
this.animating = true;
|
||||
this.setState({ activeLink: link });
|
||||
scrollTo(link, offsetTop, getContainer, () => {
|
||||
this.animating = false;
|
||||
});
|
||||
};
|
||||
|
||||
updateInk = () => {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
const prefixCls = this.prefixCls;
|
||||
const { prefixCls } = this;
|
||||
const anchorNode = ReactDOM.findDOMNode(this) as Element;
|
||||
const linkNode = anchorNode.getElementsByClassName(`${prefixCls}-link-title-active`)[0];
|
||||
if (linkNode) {
|
||||
@ -269,10 +276,6 @@ export default class Anchor extends React.Component<AnchorProps, AnchorState> {
|
||||
}
|
||||
};
|
||||
|
||||
saveInkNode = (node: HTMLSpanElement) => {
|
||||
this.inkNode = node;
|
||||
};
|
||||
|
||||
renderAnchor = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
|
@ -9,13 +9,19 @@ export default class InputElement extends React.Component<InputElementProps, any
|
||||
private ele: HTMLInputElement;
|
||||
|
||||
focus = () => {
|
||||
this.ele.focus
|
||||
? this.ele.focus()
|
||||
: (ReactDOM.findDOMNode(this.ele) as HTMLInputElement).focus();
|
||||
if (this.ele.focus) {
|
||||
this.ele.focus();
|
||||
} else {
|
||||
(ReactDOM.findDOMNode(this.ele) as HTMLInputElement).focus();
|
||||
}
|
||||
};
|
||||
|
||||
blur = () => {
|
||||
this.ele.blur ? this.ele.blur() : (ReactDOM.findDOMNode(this.ele) as HTMLInputElement).blur();
|
||||
if (this.ele.blur) {
|
||||
this.ele.blur();
|
||||
} else {
|
||||
(ReactDOM.findDOMNode(this.ele) as HTMLInputElement).blur();
|
||||
}
|
||||
};
|
||||
|
||||
saveRef = (ele: HTMLInputElement) => {
|
||||
|
@ -51,6 +51,7 @@ function isSelectOptionOrSelectOptGroup(child: any): Boolean {
|
||||
|
||||
export default class AutoComplete extends React.Component<AutoCompleteProps, {}> {
|
||||
static Option = Option as React.ClassicComponentClass<OptionProps>;
|
||||
|
||||
static OptGroup = OptGroup as React.ClassicComponentClass<OptGroupProps>;
|
||||
|
||||
static defaultProps = {
|
||||
@ -63,6 +64,10 @@ export default class AutoComplete extends React.Component<AutoCompleteProps, {}>
|
||||
|
||||
private select: any;
|
||||
|
||||
saveSelect = (node: any) => {
|
||||
this.select = node;
|
||||
};
|
||||
|
||||
getInputElement = () => {
|
||||
const { children } = this.props;
|
||||
const element =
|
||||
@ -85,10 +90,6 @@ export default class AutoComplete extends React.Component<AutoCompleteProps, {}>
|
||||
this.select.blur();
|
||||
}
|
||||
|
||||
saveSelect = (node: any) => {
|
||||
this.select = node;
|
||||
};
|
||||
|
||||
renderAutoComplete = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import Icon from '../icon';
|
||||
import classNames from 'classnames';
|
||||
import Icon from '../icon';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
|
||||
export interface AvatarProps {
|
||||
@ -23,7 +23,7 @@ export interface AvatarProps {
|
||||
children?: React.ReactNode;
|
||||
alt?: string;
|
||||
/* callback when img load error */
|
||||
/* return false to prevent Avatar show default fallback behavior, then you can do fallback by your self*/
|
||||
/* return false to prevent Avatar show default fallback behavior, then you can do fallback by your self */
|
||||
onError?: () => boolean;
|
||||
}
|
||||
|
||||
@ -44,8 +44,11 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
||||
};
|
||||
|
||||
private avatarNode: HTMLElement;
|
||||
|
||||
private avatarChildren: HTMLElement;
|
||||
|
||||
private lastChildrenWidth: number;
|
||||
|
||||
private lastNodeWidth: number;
|
||||
|
||||
componentDidMount() {
|
||||
@ -127,7 +130,7 @@ export default class Avatar extends React.Component<AvatarProps, AvatarState> {
|
||||
}
|
||||
: {};
|
||||
|
||||
let children = this.props.children;
|
||||
let { children } = this.props;
|
||||
if (src && isImgExist) {
|
||||
children = <img src={src} srcSet={srcSet} onError={this.handleImgLoadError} alt={alt} />;
|
||||
} else if (icon) {
|
||||
|
@ -12,9 +12,8 @@ const easeInOutCubic = (t: number, b: number, c: number, d: number) => {
|
||||
t /= d / 2;
|
||||
if (t < 1) {
|
||||
return (cc / 2) * t * t * t + b;
|
||||
} else {
|
||||
return (cc / 2) * ((t -= 2) * t * t + 2) + b;
|
||||
}
|
||||
return (cc / 2) * ((t -= 2) * t * t + 2) + b;
|
||||
};
|
||||
|
||||
function noop() {}
|
||||
@ -47,6 +46,29 @@ export default class BackTop extends React.Component<BackTopProps, any> {
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const getTarget = this.props.target || getDefaultTarget;
|
||||
this.scrollEvent = addEventListener(getTarget(), 'scroll', this.handleScroll);
|
||||
this.handleScroll();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.scrollEvent) {
|
||||
this.scrollEvent.remove();
|
||||
}
|
||||
}
|
||||
|
||||
setScrollTop(value: number) {
|
||||
const getTarget = this.props.target || getDefaultTarget;
|
||||
const targetNode = getTarget();
|
||||
if (targetNode === window) {
|
||||
document.body.scrollTop = value;
|
||||
document.documentElement!.scrollTop = value;
|
||||
} else {
|
||||
(targetNode as HTMLElement).scrollTop = value;
|
||||
}
|
||||
}
|
||||
|
||||
getCurrentScrollTop = () => {
|
||||
const getTarget = this.props.target || getDefaultTarget;
|
||||
const targetNode = getTarget();
|
||||
@ -73,17 +95,6 @@ export default class BackTop extends React.Component<BackTopProps, any> {
|
||||
(this.props.onClick || noop)(e);
|
||||
};
|
||||
|
||||
setScrollTop(value: number) {
|
||||
const getTarget = this.props.target || getDefaultTarget;
|
||||
const targetNode = getTarget();
|
||||
if (targetNode === window) {
|
||||
document.body.scrollTop = value;
|
||||
document.documentElement!.scrollTop = value;
|
||||
} else {
|
||||
(targetNode as HTMLElement).scrollTop = value;
|
||||
}
|
||||
}
|
||||
|
||||
handleScroll = () => {
|
||||
const { visibilityHeight, target = getDefaultTarget } = this.props;
|
||||
const scrollTop = getScroll(target(), true);
|
||||
@ -92,18 +103,6 @@ export default class BackTop extends React.Component<BackTopProps, any> {
|
||||
});
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const getTarget = this.props.target || getDefaultTarget;
|
||||
this.scrollEvent = addEventListener(getTarget(), 'scroll', this.handleScroll);
|
||||
this.handleScroll();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.scrollEvent) {
|
||||
this.scrollEvent.remove();
|
||||
}
|
||||
}
|
||||
|
||||
renderBackTop = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, className = '', children } = this.props;
|
||||
const prefixCls = getPrefixCls('back-top', customizePrefixCls);
|
||||
|
@ -1,9 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import { createElement, Component } from 'react';
|
||||
import React, { createElement, Component } from 'react';
|
||||
import omit from 'omit.js';
|
||||
import classNames from 'classnames';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
|
||||
function getNumberArray(num: string | number | undefined | null) {
|
||||
return num
|
||||
@ -18,6 +17,20 @@ function getNumberArray(num: string | number | undefined | null) {
|
||||
: [];
|
||||
}
|
||||
|
||||
function renderNumberList(position: number) {
|
||||
const childrenToReturn: React.ReactElement<any>[] = [];
|
||||
for (let i = 0; i < 30; i++) {
|
||||
const currentClassName = position === i ? 'current' : '';
|
||||
childrenToReturn.push(
|
||||
<p key={i.toString()} className={currentClassName}>
|
||||
{i % 10}
|
||||
</p>,
|
||||
);
|
||||
}
|
||||
|
||||
return childrenToReturn;
|
||||
}
|
||||
|
||||
export interface ScrollNumberProps {
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
@ -62,6 +75,21 @@ class ScrollNumber extends Component<ScrollNumberProps, ScrollNumberState> {
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(_: any, prevState: ScrollNumberState) {
|
||||
this.lastCount = prevState.count;
|
||||
const { animateStarted } = this.state;
|
||||
if (animateStarted) {
|
||||
// eslint-disable-next-line react/no-did-update-set-state
|
||||
this.setState(
|
||||
(__, props) => ({
|
||||
animateStarted: false,
|
||||
count: props.count,
|
||||
}),
|
||||
this.onAnimated,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
getPositionByNum(num: number, i: number) {
|
||||
const { count } = this.state;
|
||||
const currentCount = Math.abs(Number(count));
|
||||
@ -86,20 +114,6 @@ class ScrollNumber extends Component<ScrollNumberProps, ScrollNumberState> {
|
||||
return num;
|
||||
}
|
||||
|
||||
componentDidUpdate(_: any, prevState: ScrollNumberState) {
|
||||
this.lastCount = prevState.count;
|
||||
const { animateStarted } = this.state;
|
||||
if (animateStarted) {
|
||||
this.setState(
|
||||
(__, props) => ({
|
||||
animateStarted: false,
|
||||
count: props.count,
|
||||
}),
|
||||
this.onAnimated,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
onAnimated = () => {
|
||||
const { onAnimated } = this.props;
|
||||
if (onAnimated) {
|
||||
@ -107,20 +121,6 @@ class ScrollNumber extends Component<ScrollNumberProps, ScrollNumberState> {
|
||||
}
|
||||
};
|
||||
|
||||
renderNumberList(position: number) {
|
||||
const childrenToReturn: React.ReactElement<any>[] = [];
|
||||
for (let i = 0; i < 30; i++) {
|
||||
const currentClassName = position === i ? 'current' : '';
|
||||
childrenToReturn.push(
|
||||
<p key={i.toString()} className={currentClassName}>
|
||||
{i % 10}
|
||||
</p>,
|
||||
);
|
||||
}
|
||||
|
||||
return childrenToReturn;
|
||||
}
|
||||
|
||||
renderCurrentNumber(prefixCls: string, num: number | string, i: number) {
|
||||
if (typeof num === 'number') {
|
||||
const position = this.getPositionByNum(num, i);
|
||||
@ -138,7 +138,7 @@ class ScrollNumber extends Component<ScrollNumberProps, ScrollNumberState> {
|
||||
},
|
||||
key: i,
|
||||
},
|
||||
this.renderNumberList(position),
|
||||
renderNumberList(position),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import Animate from 'rc-animate';
|
||||
import omit from 'omit.js';
|
||||
import classNames from 'classnames';
|
||||
import ScrollNumber from './ScrollNumber';
|
||||
import { PresetColorTypes } from '../_util/colors';
|
||||
@ -46,39 +47,6 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
overflowCount: PropTypes.number,
|
||||
};
|
||||
|
||||
getBadgeClassName(prefixCls: string) {
|
||||
const { className, children } = this.props;
|
||||
return classNames(className, prefixCls, {
|
||||
[`${prefixCls}-status`]: this.hasStatus(),
|
||||
[`${prefixCls}-not-a-wrapper`]: !children,
|
||||
}) as string;
|
||||
}
|
||||
|
||||
hasStatus(): boolean {
|
||||
const { status, color } = this.props;
|
||||
return !!status || !!color;
|
||||
}
|
||||
|
||||
isZero() {
|
||||
const numberedDispayCount = this.getNumberedDispayCount();
|
||||
return numberedDispayCount === '0' || numberedDispayCount === 0;
|
||||
}
|
||||
|
||||
isDot() {
|
||||
const { dot } = this.props;
|
||||
const isZero = this.isZero();
|
||||
return (dot && !isZero) || this.hasStatus();
|
||||
}
|
||||
|
||||
isHidden() {
|
||||
const { showZero } = this.props;
|
||||
const displayCount = this.getDispayCount();
|
||||
const isZero = this.isZero();
|
||||
const isDot = this.isDot();
|
||||
const isEmpty = displayCount === null || displayCount === undefined || displayCount === '';
|
||||
return (isEmpty || (isZero && !showZero)) && !isDot;
|
||||
}
|
||||
|
||||
getNumberedDispayCount() {
|
||||
const { count, overflowCount } = this.props;
|
||||
const displayCount =
|
||||
@ -114,6 +82,39 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
: style;
|
||||
}
|
||||
|
||||
getBadgeClassName(prefixCls: string) {
|
||||
const { className, children } = this.props;
|
||||
return classNames(className, prefixCls, {
|
||||
[`${prefixCls}-status`]: this.hasStatus(),
|
||||
[`${prefixCls}-not-a-wrapper`]: !children,
|
||||
}) as string;
|
||||
}
|
||||
|
||||
hasStatus(): boolean {
|
||||
const { status, color } = this.props;
|
||||
return !!status || !!color;
|
||||
}
|
||||
|
||||
isZero() {
|
||||
const numberedDispayCount = this.getNumberedDispayCount();
|
||||
return numberedDispayCount === '0' || numberedDispayCount === 0;
|
||||
}
|
||||
|
||||
isDot() {
|
||||
const { dot } = this.props;
|
||||
const isZero = this.isZero();
|
||||
return (dot && !isZero) || this.hasStatus();
|
||||
}
|
||||
|
||||
isHidden() {
|
||||
const { showZero } = this.props;
|
||||
const displayCount = this.getDispayCount();
|
||||
const isZero = this.isZero();
|
||||
const isDot = this.isDot();
|
||||
const isEmpty = displayCount === null || displayCount === undefined || displayCount === '';
|
||||
return (isEmpty || (isZero && !showZero)) && !isDot;
|
||||
}
|
||||
|
||||
renderStatusText(prefixCls: string) {
|
||||
const { text } = this.props;
|
||||
const hidden = this.isHidden();
|
||||
@ -165,22 +166,24 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
|
||||
renderBadge = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const {
|
||||
count,
|
||||
showZero,
|
||||
prefixCls: customizePrefixCls,
|
||||
scrollNumberPrefixCls: customizeScrollNumberPrefixCls,
|
||||
overflowCount,
|
||||
className,
|
||||
style,
|
||||
children,
|
||||
dot,
|
||||
status,
|
||||
text,
|
||||
offset,
|
||||
title,
|
||||
color,
|
||||
...restProps
|
||||
} = this.props;
|
||||
const omitArr = [
|
||||
'count',
|
||||
'showZero',
|
||||
'overflowCount',
|
||||
'className',
|
||||
'style',
|
||||
'dot',
|
||||
'offset',
|
||||
'title',
|
||||
];
|
||||
|
||||
const prefixCls = getPrefixCls('badge', customizePrefixCls);
|
||||
const scrollNumberPrefixCls = getPrefixCls('scroll-number', customizeScrollNumberPrefixCls);
|
||||
@ -203,7 +206,11 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
const styleWithOffset = this.getStyleWithOffset();
|
||||
const statusTextColor = styleWithOffset && styleWithOffset.color;
|
||||
return (
|
||||
<span {...restProps} className={this.getBadgeClassName(prefixCls)} style={styleWithOffset}>
|
||||
<span
|
||||
{...omit(restProps, omitArr)}
|
||||
className={this.getBadgeClassName(prefixCls)}
|
||||
style={styleWithOffset}
|
||||
>
|
||||
<span className={statusCls} style={statusStyle} />
|
||||
<span style={{ color: statusTextColor }} className={`${prefixCls}-status-text`}>
|
||||
{text}
|
||||
@ -213,7 +220,7 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
}
|
||||
|
||||
return (
|
||||
<span {...restProps} className={this.getBadgeClassName(prefixCls)}>
|
||||
<span {...omit(restProps, omitArr)} className={this.getBadgeClassName(prefixCls)}>
|
||||
{children}
|
||||
<Animate
|
||||
component=""
|
||||
|
@ -1,6 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import React, { cloneElement } from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import { cloneElement } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import BreadcrumbItem from './BreadcrumbItem';
|
||||
import BreadcrumbSeparator from './BreadcrumbSeparator';
|
||||
@ -50,6 +49,7 @@ function defaultItemRender(route: Route, params: any, routes: Route[], paths: st
|
||||
|
||||
export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||
static Item: typeof BreadcrumbItem;
|
||||
|
||||
static Separator: typeof BreadcrumbSeparator;
|
||||
|
||||
static defaultProps = {
|
||||
@ -60,11 +60,10 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||
prefixCls: PropTypes.string,
|
||||
separator: PropTypes.node,
|
||||
routes: PropTypes.array,
|
||||
params: PropTypes.object,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const props = this.props;
|
||||
const { props } = this;
|
||||
warning(
|
||||
!('linkRender' in props || 'nameRender' in props),
|
||||
'Breadcrumb',
|
||||
@ -124,6 +123,7 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
renderBreadcrumb = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
let crumbs;
|
||||
const {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import omit from 'omit.js';
|
||||
import DropDown, { DropDownProps } from '../dropdown/dropdown';
|
||||
import Icon from '../icon';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
@ -26,24 +27,18 @@ export default class BreadcrumbItem extends React.Component<BreadcrumbItemProps,
|
||||
};
|
||||
|
||||
renderBreadcrumbItem = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
separator,
|
||||
children,
|
||||
overlay,
|
||||
...restProps
|
||||
} = this.props;
|
||||
const { prefixCls: customizePrefixCls, separator, children, ...restProps } = this.props;
|
||||
const prefixCls = getPrefixCls('breadcrumb', customizePrefixCls);
|
||||
let link;
|
||||
if ('href' in this.props) {
|
||||
link = (
|
||||
<a className={`${prefixCls}-link`} {...restProps}>
|
||||
<a className={`${prefixCls}-link`} {...omit(restProps, ['overlay'])}>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
link = (
|
||||
<span className={`${prefixCls}-link`} {...restProps}>
|
||||
<span className={`${prefixCls}-link`} {...omit(restProps, ['overlay'])}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
@ -82,6 +77,7 @@ export default class BreadcrumbItem extends React.Component<BreadcrumbItemProps,
|
||||
}
|
||||
return breadcrumbItem;
|
||||
};
|
||||
|
||||
render() {
|
||||
return <ConfigConsumer>{this.renderBreadcrumbItem}</ConfigConsumer>;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ const ButtonGroup: React.SFC<ButtonGroupProps> = props => (
|
||||
break;
|
||||
case 'small':
|
||||
sizeCls = 'sm';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
/* eslint-disable react/button-has-type */
|
||||
import * as React from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
import Group from './button-group';
|
||||
import omit from 'omit.js';
|
||||
import Group from './button-group';
|
||||
import Icon from '../icon';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import Wave from '../_util/wave';
|
||||
@ -15,29 +16,6 @@ function isString(str: any) {
|
||||
return typeof str === 'string';
|
||||
}
|
||||
|
||||
function spaceChildren(children: React.ReactNode, needInserted: boolean) {
|
||||
let isPrevChildPure: boolean = false;
|
||||
const childList: React.ReactNode[] = [];
|
||||
React.Children.forEach(children, child => {
|
||||
const type = typeof child;
|
||||
const isCurrentChildPure = type === 'string' || type === 'number';
|
||||
if (isPrevChildPure && isCurrentChildPure) {
|
||||
const lastIndex = childList.length - 1;
|
||||
const lastChild = childList[lastIndex];
|
||||
childList[lastIndex] = `${lastChild}${child}`;
|
||||
} else {
|
||||
childList.push(child);
|
||||
}
|
||||
|
||||
isPrevChildPure = isCurrentChildPure;
|
||||
});
|
||||
|
||||
// Pass to React.Children.map to auto fill key
|
||||
return React.Children.map(childList, child =>
|
||||
insertSpace(child as React.ReactChild, needInserted),
|
||||
);
|
||||
}
|
||||
|
||||
// Insert one space between two chinese characters automatically.
|
||||
function insertSpace(child: React.ReactChild, needInserted: boolean) {
|
||||
// Check the child if is undefined or null.
|
||||
@ -63,6 +41,29 @@ function insertSpace(child: React.ReactChild, needInserted: boolean) {
|
||||
return child;
|
||||
}
|
||||
|
||||
function spaceChildren(children: React.ReactNode, needInserted: boolean) {
|
||||
let isPrevChildPure: boolean = false;
|
||||
const childList: React.ReactNode[] = [];
|
||||
React.Children.forEach(children, child => {
|
||||
const type = typeof child;
|
||||
const isCurrentChildPure = type === 'string' || type === 'number';
|
||||
if (isPrevChildPure && isCurrentChildPure) {
|
||||
const lastIndex = childList.length - 1;
|
||||
const lastChild = childList[lastIndex];
|
||||
childList[lastIndex] = `${lastChild}${child}`;
|
||||
} else {
|
||||
childList.push(child);
|
||||
}
|
||||
|
||||
isPrevChildPure = isCurrentChildPure;
|
||||
});
|
||||
|
||||
// Pass to React.Children.map to auto fill key
|
||||
return React.Children.map(childList, child =>
|
||||
insertSpace(child as React.ReactChild, needInserted),
|
||||
);
|
||||
}
|
||||
|
||||
const ButtonTypes = tuple('default', 'primary', 'ghost', 'dashed', 'danger', 'link');
|
||||
export type ButtonType = (typeof ButtonTypes)[number];
|
||||
const ButtonShapes = tuple('circle', 'circle-outline', 'round');
|
||||
@ -110,6 +111,7 @@ interface ButtonState {
|
||||
|
||||
class Button extends React.Component<ButtonProps, ButtonState> {
|
||||
static Group: typeof Group;
|
||||
|
||||
static __ANT_BUTTON = true;
|
||||
|
||||
static defaultProps = {
|
||||
@ -142,6 +144,7 @@ class Button extends React.Component<ButtonProps, ButtonState> {
|
||||
}
|
||||
|
||||
private delayTimeout: number;
|
||||
|
||||
private buttonNode: HTMLElement | null;
|
||||
|
||||
constructor(props: ButtonProps) {
|
||||
@ -166,9 +169,8 @@ class Button extends React.Component<ButtonProps, ButtonState> {
|
||||
const { loading } = this.props;
|
||||
if (loading && typeof loading !== 'boolean' && loading.delay) {
|
||||
this.delayTimeout = window.setTimeout(() => this.setState({ loading }), loading.delay);
|
||||
} else if (prevProps.loading === this.props.loading) {
|
||||
return;
|
||||
} else {
|
||||
} else if (prevProps.loading !== this.props.loading) {
|
||||
// eslint-disable-next-line react/no-did-update-set-state
|
||||
this.setState({ loading });
|
||||
}
|
||||
}
|
||||
@ -183,6 +185,17 @@ class Button extends React.Component<ButtonProps, ButtonState> {
|
||||
this.buttonNode = node;
|
||||
};
|
||||
|
||||
handleClick: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement> = e => {
|
||||
const { loading } = this.state;
|
||||
const { onClick } = this.props;
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
if (onClick) {
|
||||
(onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)(e);
|
||||
}
|
||||
};
|
||||
|
||||
fixTwoCNChar() {
|
||||
// Fix for HOC usage like <FormatMessage />
|
||||
if (!this.buttonNode) {
|
||||
@ -202,17 +215,6 @@ class Button extends React.Component<ButtonProps, ButtonState> {
|
||||
}
|
||||
}
|
||||
|
||||
handleClick: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement> = e => {
|
||||
const { loading } = this.state;
|
||||
const { onClick } = this.props;
|
||||
if (!!loading) {
|
||||
return;
|
||||
}
|
||||
if (onClick) {
|
||||
(onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)(e);
|
||||
}
|
||||
};
|
||||
|
||||
isNeedInserted() {
|
||||
const { icon, children } = this.props;
|
||||
return React.Children.count(children) === 1 && !icon;
|
||||
@ -228,7 +230,6 @@ class Button extends React.Component<ButtonProps, ButtonState> {
|
||||
children,
|
||||
icon,
|
||||
ghost,
|
||||
loading: _loadingProp,
|
||||
block,
|
||||
...rest
|
||||
} = this.props;
|
||||
@ -289,7 +290,7 @@ class Button extends React.Component<ButtonProps, ButtonState> {
|
||||
|
||||
const buttonNode = (
|
||||
<button
|
||||
{...(otherProps as NativeButtonProps)}
|
||||
{...(omit(otherProps, ['loading']) as NativeButtonProps)}
|
||||
type={htmlType}
|
||||
className={classes}
|
||||
onClick={this.handleClick}
|
||||
|
@ -3,8 +3,20 @@ import * as moment from 'moment';
|
||||
import Select from '../select';
|
||||
import { Group, Button, RadioChangeEvent } from '../radio';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
function getMonthsLocale(value: moment.Moment) {
|
||||
const current = value.clone();
|
||||
const localeData = value.localeData();
|
||||
const months: any[] = [];
|
||||
for (let i = 0; i < 12; i++) {
|
||||
current.month(i);
|
||||
months.push(localeData.monthsShort(current));
|
||||
}
|
||||
return months;
|
||||
}
|
||||
|
||||
export interface RenderHeader {
|
||||
value: moment.Moment;
|
||||
onChange?: (value: moment.Moment) => void;
|
||||
@ -63,17 +75,6 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
);
|
||||
}
|
||||
|
||||
getMonthsLocale(value: moment.Moment) {
|
||||
const current = value.clone();
|
||||
const localeData = value.localeData();
|
||||
const months: any[] = [];
|
||||
for (let i = 0; i < 12; i++) {
|
||||
current.month(i);
|
||||
months.push(localeData.monthsShort(current));
|
||||
}
|
||||
return months;
|
||||
}
|
||||
|
||||
getMonthSelectElement(prefixCls: string, month: number, months: number[]) {
|
||||
const { fullscreen, validRange, value } = this.props;
|
||||
const options: React.ReactElement<any>[] = [];
|
||||
@ -124,7 +125,7 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
}
|
||||
}
|
||||
|
||||
const onValueChange = this.props.onValueChange;
|
||||
const { onValueChange } = this.props;
|
||||
if (onValueChange) {
|
||||
onValueChange(newValue);
|
||||
}
|
||||
@ -133,7 +134,7 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
onMonthChange = (month: string) => {
|
||||
const newValue = this.props.value.clone();
|
||||
newValue.month(parseInt(month, 10));
|
||||
const onValueChange = this.props.onValueChange;
|
||||
const { onValueChange } = this.props;
|
||||
if (onValueChange) {
|
||||
onValueChange(newValue);
|
||||
}
|
||||
@ -144,7 +145,7 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
};
|
||||
|
||||
onTypeChange = (type: string) => {
|
||||
const onTypeChange = this.props.onTypeChange;
|
||||
const { onTypeChange } = this.props;
|
||||
if (onTypeChange) {
|
||||
onTypeChange(type);
|
||||
}
|
||||
@ -161,7 +162,7 @@ export default class Header extends React.Component<HeaderProps, any> {
|
||||
const yearReactNode = this.getYearSelectElement(prefixCls, value.year());
|
||||
const monthReactNode =
|
||||
type === 'month'
|
||||
? this.getMonthSelectElement(prefixCls, value.month(), this.getMonthsLocale(value))
|
||||
? this.getMonthSelectElement(prefixCls, value.month(), getMonthsLocale(value))
|
||||
: null;
|
||||
return {
|
||||
yearReactNode,
|
||||
|
@ -2,12 +2,12 @@ import * as React from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import * as moment from 'moment';
|
||||
import FullCalendar from 'rc-calendar/lib/FullCalendar';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
import Header, { HeaderRender } from './Header';
|
||||
import enUS from './locale/en_US';
|
||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import interopDefault from '../_util/interopDefault';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
|
||||
export { HeaderProps } from './Header';
|
||||
|
||||
@ -104,47 +104,6 @@ class Calendar extends React.Component<CalendarProps, CalendarState> {
|
||||
};
|
||||
}
|
||||
|
||||
monthCellRender = (value: moment.Moment) => {
|
||||
const { monthCellRender = noop as Function } = this.props;
|
||||
const { prefixCls } = this;
|
||||
return (
|
||||
<div className={`${prefixCls}-month`}>
|
||||
<div className={`${prefixCls}-value`}>{value.localeData().monthsShort(value)}</div>
|
||||
<div className={`${prefixCls}-content`}>{monthCellRender(value)}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
dateCellRender = (value: moment.Moment) => {
|
||||
const { dateCellRender = noop as Function } = this.props;
|
||||
const { prefixCls } = this;
|
||||
return (
|
||||
<div className={`${prefixCls}-date`}>
|
||||
<div className={`${prefixCls}-value`}>{zerofixed(value.date())}</div>
|
||||
<div className={`${prefixCls}-content`}>{dateCellRender(value)}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
setValue = (value: moment.Moment, way: 'select' | 'changePanel') => {
|
||||
const prevValue = this.props.value || this.state.value;
|
||||
const { mode } = this.state;
|
||||
|
||||
if (!('value' in this.props)) {
|
||||
this.setState({ value });
|
||||
}
|
||||
if (way === 'select') {
|
||||
if (prevValue && prevValue.month() !== value.month()) {
|
||||
this.onPanelChange(value, mode);
|
||||
}
|
||||
if (this.props.onSelect) {
|
||||
this.props.onSelect(value);
|
||||
}
|
||||
} else if (way === 'changePanel') {
|
||||
this.onPanelChange(value, mode);
|
||||
}
|
||||
};
|
||||
|
||||
onHeaderValueChange = (value: moment.Moment) => {
|
||||
this.setValue(value, 'changePanel');
|
||||
};
|
||||
@ -168,6 +127,25 @@ class Calendar extends React.Component<CalendarProps, CalendarState> {
|
||||
this.setValue(value, 'select');
|
||||
};
|
||||
|
||||
setValue = (value: moment.Moment, way: 'select' | 'changePanel') => {
|
||||
const prevValue = this.props.value || this.state.value;
|
||||
const { mode } = this.state;
|
||||
|
||||
if (!('value' in this.props)) {
|
||||
this.setState({ value });
|
||||
}
|
||||
if (way === 'select') {
|
||||
if (prevValue && prevValue.month() !== value.month()) {
|
||||
this.onPanelChange(value, mode);
|
||||
}
|
||||
if (this.props.onSelect) {
|
||||
this.props.onSelect(value);
|
||||
}
|
||||
} else if (way === 'changePanel') {
|
||||
this.onPanelChange(value, mode);
|
||||
}
|
||||
};
|
||||
|
||||
getDateRange = (
|
||||
validRange: [moment.Moment, moment.Moment],
|
||||
disabledDate?: (current: moment.Moment) => boolean,
|
||||
@ -195,6 +173,28 @@ class Calendar extends React.Component<CalendarProps, CalendarState> {
|
||||
return result;
|
||||
};
|
||||
|
||||
monthCellRender = (value: moment.Moment) => {
|
||||
const { monthCellRender = noop as Function } = this.props;
|
||||
const { prefixCls } = this;
|
||||
return (
|
||||
<div className={`${prefixCls}-month`}>
|
||||
<div className={`${prefixCls}-value`}>{value.localeData().monthsShort(value)}</div>
|
||||
<div className={`${prefixCls}-content`}>{monthCellRender(value)}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
dateCellRender = (value: moment.Moment) => {
|
||||
const { dateCellRender = noop as Function } = this.props;
|
||||
const { prefixCls } = this;
|
||||
return (
|
||||
<div className={`${prefixCls}-date`}>
|
||||
<div className={`${prefixCls}-value`}>{zerofixed(value.date())}</div>
|
||||
<div className={`${prefixCls}-content`}>{dateCellRender(value)}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
renderCalendar = (locale: any, localeCode: string) => {
|
||||
const { state, props } = this;
|
||||
const { value, mode } = state;
|
||||
@ -213,7 +213,7 @@ class Calendar extends React.Component<CalendarProps, CalendarState> {
|
||||
const monthCellRender = monthFullCellRender || this.monthCellRender;
|
||||
const dateCellRender = dateFullCellRender || this.dateCellRender;
|
||||
|
||||
let disabledDate = props.disabledDate;
|
||||
let { disabledDate } = props;
|
||||
|
||||
if (props.validRange) {
|
||||
disabledDate = this.getDateRange(props.validRange, disabledDate);
|
||||
|
@ -46,7 +46,11 @@ class App extends React.Component {
|
||||
|
||||
<Card
|
||||
style={{ width: 300, marginTop: 16 }}
|
||||
actions={[<Icon type="setting" />, <Icon type="edit" />, <Icon type="ellipsis" />]}
|
||||
actions={[
|
||||
<Icon type="setting" key="setting" />,
|
||||
<Icon type="edit" key="edit" />,
|
||||
<Icon type="ellipsis" key="ellipsis" />,
|
||||
]}
|
||||
>
|
||||
<Skeleton loading={loading} avatar active>
|
||||
<Meta
|
||||
|
@ -27,7 +27,11 @@ ReactDOM.render(
|
||||
src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"
|
||||
/>
|
||||
}
|
||||
actions={[<Icon type="setting" />, <Icon type="edit" />, <Icon type="ellipsis" />]}
|
||||
actions={[
|
||||
<Icon type="setting" key="setting" />,
|
||||
<Icon type="edit" key="edit" />,
|
||||
<Icon type="ellipsis" key="ellipsis" />,
|
||||
]}
|
||||
>
|
||||
<Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
|
@ -10,6 +10,16 @@ import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import warning from '../_util/warning';
|
||||
import { Omit } from '../_util/type';
|
||||
|
||||
function getAction(actions: React.ReactNode[]) {
|
||||
const actionList = actions.map((action, index) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<li style={{ width: `${100 / actions.length}%` }} key={`action-${index}`}>
|
||||
<span>{action}</span>
|
||||
</li>
|
||||
));
|
||||
return actionList;
|
||||
}
|
||||
|
||||
export { CardGridProps } from './Grid';
|
||||
export { CardMetaProps } from './Meta';
|
||||
|
||||
@ -48,6 +58,7 @@ export interface CardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 't
|
||||
|
||||
export default class Card extends React.Component<CardProps, {}> {
|
||||
static Grid: typeof Grid = Grid;
|
||||
|
||||
static Meta: typeof Meta = Meta;
|
||||
|
||||
componentDidMount() {
|
||||
@ -65,6 +76,15 @@ export default class Card extends React.Component<CardProps, {}> {
|
||||
}
|
||||
}
|
||||
|
||||
// For 2.x compatible
|
||||
getCompatibleHoverable() {
|
||||
const { noHovering, hoverable } = this.props;
|
||||
if ('noHovering' in this.props) {
|
||||
return !noHovering || hoverable;
|
||||
}
|
||||
return !!hoverable;
|
||||
}
|
||||
|
||||
onTabChange = (key: string) => {
|
||||
if (this.props.onTabChange) {
|
||||
this.props.onTabChange(key);
|
||||
@ -81,24 +101,6 @@ export default class Card extends React.Component<CardProps, {}> {
|
||||
return containGrid;
|
||||
}
|
||||
|
||||
getAction(actions: React.ReactNode[]) {
|
||||
const actionList = actions.map((action, index) => (
|
||||
<li style={{ width: `${100 / actions.length}%` }} key={`action-${index}`}>
|
||||
<span>{action}</span>
|
||||
</li>
|
||||
));
|
||||
return actionList;
|
||||
}
|
||||
|
||||
// For 2.x compatible
|
||||
getCompatibleHoverable() {
|
||||
const { noHovering, hoverable } = this.props;
|
||||
if ('noHovering' in this.props) {
|
||||
return !noHovering || hoverable;
|
||||
}
|
||||
return !!hoverable;
|
||||
}
|
||||
|
||||
renderCard = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
@ -106,8 +108,6 @@ export default class Card extends React.Component<CardProps, {}> {
|
||||
extra,
|
||||
headStyle = {},
|
||||
bodyStyle = {},
|
||||
noHovering,
|
||||
hoverable,
|
||||
title,
|
||||
loading,
|
||||
bordered = true,
|
||||
@ -221,9 +221,9 @@ export default class Card extends React.Component<CardProps, {}> {
|
||||
);
|
||||
const actionDom =
|
||||
actions && actions.length ? (
|
||||
<ul className={`${prefixCls}-actions`}>{this.getAction(actions)}</ul>
|
||||
<ul className={`${prefixCls}-actions`}>{getAction(actions)}</ul>
|
||||
) : null;
|
||||
const divProps = omit(others, ['onTabChange']);
|
||||
const divProps = omit(others, ['onTabChange', 'noHovering', 'hoverable']);
|
||||
return (
|
||||
<div {...divProps} className={classString}>
|
||||
{head}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { Settings } from 'react-slick';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import warning from '../_util/warning';
|
||||
|
||||
// matchMedia polyfill for
|
||||
@ -85,6 +85,20 @@ export default class Carousel extends React.Component<CarouselProps, {}> {
|
||||
}
|
||||
}
|
||||
|
||||
getDotPosition(): DotPosition {
|
||||
if (this.props.dotPosition) {
|
||||
return this.props.dotPosition;
|
||||
}
|
||||
if ('vertical' in this.props) {
|
||||
return this.props.vertical ? 'right' : 'bottom';
|
||||
}
|
||||
return 'bottom';
|
||||
}
|
||||
|
||||
saveSlick = (node: any) => {
|
||||
this.slick = node;
|
||||
};
|
||||
|
||||
onWindowResized = () => {
|
||||
// Fix https://github.com/ant-design/ant-design/issues/2550
|
||||
const { autoplay } = this.props;
|
||||
@ -93,10 +107,6 @@ export default class Carousel extends React.Component<CarouselProps, {}> {
|
||||
}
|
||||
};
|
||||
|
||||
saveSlick = (node: any) => {
|
||||
this.slick = node;
|
||||
};
|
||||
|
||||
next() {
|
||||
this.slick.slickNext();
|
||||
}
|
||||
@ -109,15 +119,6 @@ export default class Carousel extends React.Component<CarouselProps, {}> {
|
||||
this.slick.slickGoTo(slide, dontAnimate);
|
||||
}
|
||||
|
||||
getDotPosition(): DotPosition {
|
||||
if (this.props.dotPosition) {
|
||||
return this.props.dotPosition;
|
||||
} else if ('vertical' in this.props) {
|
||||
return this.props.vertical ? 'right' : 'bottom';
|
||||
}
|
||||
return 'bottom';
|
||||
}
|
||||
|
||||
renderCarousel = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const props = {
|
||||
...this.props,
|
||||
|
@ -1218,7 +1218,7 @@ exports[`Cascader should render not found content 1`] = `
|
||||
>
|
||||
<Empty
|
||||
className="ant-empty-small"
|
||||
image={<_default />}
|
||||
image={<Simple />}
|
||||
>
|
||||
<LocaleReceiver
|
||||
componentName="Empty"
|
||||
@ -1229,7 +1229,7 @@ exports[`Cascader should render not found content 1`] = `
|
||||
<div
|
||||
className="ant-empty-image"
|
||||
>
|
||||
<_default>
|
||||
<Simple>
|
||||
<svg
|
||||
height="41"
|
||||
viewBox="0 0 64 41"
|
||||
@ -1262,7 +1262,7 @@ exports[`Cascader should render not found content 1`] = `
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</_default>
|
||||
</Simple>
|
||||
</div>
|
||||
<p
|
||||
className="ant-empty-description"
|
||||
@ -1541,7 +1541,7 @@ exports[`Cascader should show not found content when options.length is 0 1`] = `
|
||||
>
|
||||
<Empty
|
||||
className="ant-empty-small"
|
||||
image={<_default />}
|
||||
image={<Simple />}
|
||||
>
|
||||
<LocaleReceiver
|
||||
componentName="Empty"
|
||||
@ -1552,7 +1552,7 @@ exports[`Cascader should show not found content when options.length is 0 1`] = `
|
||||
<div
|
||||
className="ant-empty-image"
|
||||
>
|
||||
<_default>
|
||||
<Simple>
|
||||
<svg
|
||||
height="41"
|
||||
viewBox="0 0 64 41"
|
||||
@ -1585,7 +1585,7 @@ exports[`Cascader should show not found content when options.length is 0 1`] = `
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</_default>
|
||||
</Simple>
|
||||
</div>
|
||||
<p
|
||||
className="ant-empty-description"
|
||||
|
@ -72,13 +72,13 @@ export interface CascaderProps {
|
||||
popupClassName?: string;
|
||||
/** 浮层预设位置:`bottomLeft` `bottomRight` `topLeft` `topRight` */
|
||||
popupPlacement?: string;
|
||||
/** 输入框占位文本*/
|
||||
/** 输入框占位文本 */
|
||||
placeholder?: string;
|
||||
/** 输入框大小,可选 `large` `default` `small` */
|
||||
size?: string;
|
||||
/** 禁用*/
|
||||
/** 禁用 */
|
||||
disabled?: boolean;
|
||||
/** 是否支持清除*/
|
||||
/** 是否支持清除 */
|
||||
allowClear?: boolean;
|
||||
showSearch?: boolean | ShowSearchType;
|
||||
notFoundContent?: React.ReactNode;
|
||||
@ -262,6 +262,34 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
};
|
||||
}
|
||||
|
||||
setValue = (value: string[], selectedOptions: CascaderOptionType[] = []) => {
|
||||
if (!('value' in this.props)) {
|
||||
this.setState({ value });
|
||||
}
|
||||
const { onChange } = this.props;
|
||||
if (onChange) {
|
||||
onChange(value, selectedOptions);
|
||||
}
|
||||
};
|
||||
|
||||
getLabel() {
|
||||
const { options, displayRender = defaultDisplayRender as Function } = this.props;
|
||||
const names = getFilledFieldNames(this.props);
|
||||
const { value } = this.state;
|
||||
const unwrappedValue = Array.isArray(value[0]) ? value[0] : value;
|
||||
const selectedOptions: CascaderOptionType[] = arrayTreeFilter(
|
||||
options,
|
||||
(o: CascaderOptionType, level: number) => o[names.value] === unwrappedValue[level],
|
||||
{ childrenKeyName: names.children },
|
||||
);
|
||||
const label = selectedOptions.map(o => o[names.label]);
|
||||
return displayRender(label, selectedOptions);
|
||||
}
|
||||
|
||||
saveInput = (node: Input) => {
|
||||
this.input = node;
|
||||
};
|
||||
|
||||
handleChange = (value: any, selectedOptions: CascaderOptionType[]) => {
|
||||
this.setState({ inputValue: '' });
|
||||
if (selectedOptions[0].__IS_FILTERED_OPTION) {
|
||||
@ -282,7 +310,7 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
}));
|
||||
}
|
||||
|
||||
const onPopupVisibleChange = this.props.onPopupVisibleChange;
|
||||
const { onPopupVisibleChange } = this.props;
|
||||
if (onPopupVisibleChange) {
|
||||
onPopupVisibleChange(popupVisible);
|
||||
}
|
||||
@ -317,30 +345,6 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
this.setState({ inputValue });
|
||||
};
|
||||
|
||||
setValue = (value: string[], selectedOptions: CascaderOptionType[] = []) => {
|
||||
if (!('value' in this.props)) {
|
||||
this.setState({ value });
|
||||
}
|
||||
const onChange = this.props.onChange;
|
||||
if (onChange) {
|
||||
onChange(value, selectedOptions);
|
||||
}
|
||||
};
|
||||
|
||||
getLabel() {
|
||||
const { options, displayRender = defaultDisplayRender as Function } = this.props;
|
||||
const names = getFilledFieldNames(this.props);
|
||||
const value = this.state.value;
|
||||
const unwrappedValue = Array.isArray(value[0]) ? value[0] : value;
|
||||
const selectedOptions: CascaderOptionType[] = arrayTreeFilter(
|
||||
options,
|
||||
(o: CascaderOptionType, level: number) => o[names.value] === unwrappedValue[level],
|
||||
{ childrenKeyName: names.children },
|
||||
);
|
||||
const label = selectedOptions.map(o => o[names.label]);
|
||||
return displayRender(label, selectedOptions);
|
||||
}
|
||||
|
||||
clearSelection = (e: React.MouseEvent<HTMLElement>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@ -417,10 +421,6 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
this.input.blur();
|
||||
}
|
||||
|
||||
saveInput = (node: Input) => {
|
||||
this.input = node;
|
||||
};
|
||||
|
||||
renderCascader = (
|
||||
{ getPopupContainer: getContextPopupContainer, getPrefixCls, renderEmpty }: ConfigConsumerProps,
|
||||
locale: CascaderLocale,
|
||||
@ -495,7 +495,7 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
'filedNames', // For old compatibility
|
||||
]);
|
||||
|
||||
let options = props.options;
|
||||
let { options } = props;
|
||||
if (options.length > 0) {
|
||||
if (state.inputValue) {
|
||||
options = this.generateFilteredOptions(prefixCls, renderEmpty);
|
||||
@ -524,8 +524,7 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
dropdownMenuColumnStyle.height = 'auto'; // Height of one row.
|
||||
}
|
||||
// The default value of `matchInputWidth` is `true`
|
||||
const resultListMatchInputWidth =
|
||||
(showSearch as ShowSearchType).matchInputWidth === false ? false : true;
|
||||
const resultListMatchInputWidth = (showSearch as ShowSearchType).matchInputWidth !== false;
|
||||
if (resultListMatchInputWidth && (state.inputValue || isNotFound) && this.input) {
|
||||
dropdownMenuColumnStyle.width = this.input.input.offsetWidth;
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ export interface CheckboxChangeEvent {
|
||||
|
||||
class Checkbox extends React.Component<CheckboxProps, {}> {
|
||||
static Group: typeof CheckboxGroup;
|
||||
|
||||
static defaultProps = {
|
||||
indeterminate: false,
|
||||
};
|
||||
@ -65,6 +66,18 @@ class Checkbox extends React.Component<CheckboxProps, {}> {
|
||||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate(
|
||||
nextProps: CheckboxProps,
|
||||
nextState: {},
|
||||
nextContext: CheckboxGroupContext,
|
||||
) {
|
||||
return (
|
||||
!shallowEqual(this.props, nextProps) ||
|
||||
!shallowEqual(this.state, nextState) ||
|
||||
!shallowEqual(this.context.checkboxGroup, nextContext.checkboxGroup)
|
||||
);
|
||||
}
|
||||
|
||||
componentDidUpdate({ value: prevValue }: CheckboxProps) {
|
||||
const { value } = this.props;
|
||||
const { checkboxGroup = {} } = this.context || {};
|
||||
@ -82,17 +95,9 @@ class Checkbox extends React.Component<CheckboxProps, {}> {
|
||||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate(
|
||||
nextProps: CheckboxProps,
|
||||
nextState: {},
|
||||
nextContext: CheckboxGroupContext,
|
||||
) {
|
||||
return (
|
||||
!shallowEqual(this.props, nextProps) ||
|
||||
!shallowEqual(this.state, nextState) ||
|
||||
!shallowEqual(this.context.checkboxGroup, nextContext.checkboxGroup)
|
||||
);
|
||||
}
|
||||
saveCheckbox = (node: any) => {
|
||||
this.rcCheckbox = node;
|
||||
};
|
||||
|
||||
focus() {
|
||||
this.rcCheckbox.focus();
|
||||
@ -102,10 +107,6 @@ class Checkbox extends React.Component<CheckboxProps, {}> {
|
||||
this.rcCheckbox.blur();
|
||||
}
|
||||
|
||||
saveCheckbox = (node: any) => {
|
||||
this.rcCheckbox = node;
|
||||
};
|
||||
|
||||
renderCheckbox = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { props, context } = this;
|
||||
const {
|
||||
@ -141,6 +142,7 @@ class Checkbox extends React.Component<CheckboxProps, {}> {
|
||||
[`${prefixCls}-indeterminate`]: indeterminate,
|
||||
});
|
||||
return (
|
||||
// eslint-disable-next-line jsx-a11y/label-has-associated-control
|
||||
<label
|
||||
className={classString}
|
||||
style={style}
|
||||
|
@ -96,18 +96,6 @@ class CheckboxGroup extends React.Component<CheckboxGroupProps, CheckboxGroupSta
|
||||
return !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState);
|
||||
}
|
||||
|
||||
registerValue = (value: string) => {
|
||||
this.setState(({ registeredValues }) => ({
|
||||
registeredValues: [...registeredValues, value],
|
||||
}));
|
||||
};
|
||||
|
||||
cancelValue = (value: string) => {
|
||||
this.setState(({ registeredValues }) => ({
|
||||
registeredValues: registeredValues.filter(val => val !== value),
|
||||
}));
|
||||
};
|
||||
|
||||
getOptions() {
|
||||
const { options } = this.props;
|
||||
// https://github.com/Microsoft/TypeScript/issues/7960
|
||||
@ -122,6 +110,18 @@ class CheckboxGroup extends React.Component<CheckboxGroupProps, CheckboxGroupSta
|
||||
});
|
||||
}
|
||||
|
||||
cancelValue = (value: string) => {
|
||||
this.setState(({ registeredValues }) => ({
|
||||
registeredValues: registeredValues.filter(val => val !== value),
|
||||
}));
|
||||
};
|
||||
|
||||
registerValue = (value: string) => {
|
||||
this.setState(({ registeredValues }) => ({
|
||||
registeredValues: [...registeredValues, value],
|
||||
}));
|
||||
};
|
||||
|
||||
toggleOption = (option: CheckboxOptionType) => {
|
||||
const { registeredValues } = this.state;
|
||||
const optionIndex = this.state.value.indexOf(option.value);
|
||||
@ -134,7 +134,7 @@ class CheckboxGroup extends React.Component<CheckboxGroupProps, CheckboxGroupSta
|
||||
if (!('value' in this.props)) {
|
||||
this.setState({ value });
|
||||
}
|
||||
const onChange = this.props.onChange;
|
||||
const { onChange } = this.props;
|
||||
if (onChange) {
|
||||
const options = this.getOptions();
|
||||
onChange(
|
||||
@ -157,7 +157,7 @@ class CheckboxGroup extends React.Component<CheckboxGroupProps, CheckboxGroupSta
|
||||
|
||||
const domProps = omit(restProps, ['children', 'defaultValue', 'value', 'onChange', 'disabled']);
|
||||
|
||||
let children = props.children;
|
||||
let { children } = props;
|
||||
if (options && options.length > 0) {
|
||||
children = this.getOptions().map(option => (
|
||||
<Checkbox
|
||||
|
@ -230,6 +230,7 @@ exports[`renders ./components/comment/demo/list.md correctly 1`] = `
|
||||
class="ant-comment-avatar"
|
||||
>
|
||||
<img
|
||||
alt="comment-avatar"
|
||||
src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
|
||||
/>
|
||||
</div>
|
||||
@ -283,6 +284,7 @@ exports[`renders ./components/comment/demo/list.md correctly 1`] = `
|
||||
class="ant-comment-avatar"
|
||||
>
|
||||
<img
|
||||
alt="comment-avatar"
|
||||
src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
|
||||
/>
|
||||
</div>
|
||||
|
@ -44,7 +44,7 @@ class App extends React.Component {
|
||||
const { likes, dislikes, action } = this.state;
|
||||
|
||||
const actions = [
|
||||
<span>
|
||||
<span key="comment-basic-like">
|
||||
<Tooltip title="Like">
|
||||
<Icon
|
||||
type="like"
|
||||
@ -54,7 +54,7 @@ class App extends React.Component {
|
||||
</Tooltip>
|
||||
<span style={{ paddingLeft: 8, cursor: 'auto' }}>{likes}</span>
|
||||
</span>,
|
||||
<span>
|
||||
<span key=' key="comment-basic-dislike"'>
|
||||
<Tooltip title="Dislike">
|
||||
<Icon
|
||||
type="dislike"
|
||||
@ -64,7 +64,7 @@ class App extends React.Component {
|
||||
</Tooltip>
|
||||
<span style={{ paddingLeft: 8, cursor: 'auto' }}>{dislikes}</span>
|
||||
</span>,
|
||||
<span>Reply to</span>,
|
||||
<span key="comment-basic-reply-to">Reply to</span>,
|
||||
];
|
||||
|
||||
return (
|
||||
|
@ -19,7 +19,7 @@ import moment from 'moment';
|
||||
|
||||
const data = [
|
||||
{
|
||||
actions: [<span>Reply to</span>],
|
||||
actions: [<span key="comment-list-reply-to-0">Reply to</span>],
|
||||
author: 'Han Solo',
|
||||
avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png',
|
||||
content: (
|
||||
@ -44,7 +44,7 @@ const data = [
|
||||
),
|
||||
},
|
||||
{
|
||||
actions: [<span>Reply to</span>],
|
||||
actions: [<span key="comment-list-reply-to-0">Reply to</span>],
|
||||
author: 'Han Solo',
|
||||
avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png',
|
||||
content: (
|
||||
|
@ -18,7 +18,7 @@ import { Comment, Avatar } from 'antd';
|
||||
|
||||
const ExampleComment = ({ children }) => (
|
||||
<Comment
|
||||
actions={[<span>Reply to</span>]}
|
||||
actions={[<span key="comment-nested-reply-to">Reply to</span>]}
|
||||
author={<a>Han Solo</a>}
|
||||
avatar={
|
||||
<Avatar
|
||||
|
@ -2,6 +2,15 @@ import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
|
||||
function getAction(actions: React.ReactNode[]) {
|
||||
if (!actions || !actions.length) {
|
||||
return null;
|
||||
}
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
const actionList = actions.map((action, index) => <li key={`action-${index}`}>{action}</li>);
|
||||
return actionList;
|
||||
}
|
||||
|
||||
export interface CommentProps {
|
||||
/** List of action items rendered below the comment content */
|
||||
actions?: Array<React.ReactNode>;
|
||||
@ -24,14 +33,6 @@ export interface CommentProps {
|
||||
}
|
||||
|
||||
export default class Comment extends React.Component<CommentProps, {}> {
|
||||
getAction(actions: React.ReactNode[]) {
|
||||
if (!actions || !actions.length) {
|
||||
return null;
|
||||
}
|
||||
const actionList = actions.map((action, index) => <li key={`action-${index}`}>{action}</li>);
|
||||
return actionList;
|
||||
}
|
||||
|
||||
renderNested = (prefixCls: string, children: any) => {
|
||||
return <div className={classNames(`${prefixCls}-nested`)}>{children}</div>;
|
||||
};
|
||||
@ -54,13 +55,13 @@ export default class Comment extends React.Component<CommentProps, {}> {
|
||||
|
||||
const avatarDom = (
|
||||
<div className={`${prefixCls}-avatar`}>
|
||||
{typeof avatar === 'string' ? <img src={avatar} /> : avatar}
|
||||
{typeof avatar === 'string' ? <img src={avatar} alt="comment-avatar" /> : avatar}
|
||||
</div>
|
||||
);
|
||||
|
||||
const actionDom =
|
||||
actions && actions.length ? (
|
||||
<ul className={`${prefixCls}-actions`}>{this.getAction(actions)}</ul>
|
||||
<ul className={`${prefixCls}-actions`}>{getAction(actions)}</ul>
|
||||
) : null;
|
||||
|
||||
const authorContent = (
|
||||
|
@ -1,3 +1,6 @@
|
||||
// TODO: remove this lint
|
||||
// SFC has specified a displayName, but not worked.
|
||||
/* eslint-disable react/display-name */
|
||||
import * as React from 'react';
|
||||
import createReactContext from '@ant-design/create-react-context';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import Icon from '../icon';
|
||||
import classNames from 'classnames';
|
||||
import Icon from '../icon';
|
||||
|
||||
export default function InputIcon(props: { suffixIcon: React.ReactNode; prefixCls: string }) {
|
||||
const { suffixIcon, prefixCls } = props;
|
||||
|
@ -30,10 +30,9 @@ function getShowDateFromValue(value: RangePickerValue, mode?: string | string[])
|
||||
}
|
||||
if (mode && mode[0] === 'month') {
|
||||
return [start, end] as RangePickerValue;
|
||||
} else {
|
||||
const newEnd = end && end.isSame(start, 'month') ? end.clone().add(1, 'month') : end;
|
||||
return [start, newEnd] as RangePickerValue;
|
||||
}
|
||||
const newEnd = end && end.isSame(start, 'month') ? end.clone().add(1, 'month') : end;
|
||||
return [start, newEnd] as RangePickerValue;
|
||||
}
|
||||
|
||||
function pickerValueAdapter(
|
||||
@ -102,7 +101,9 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
||||
}
|
||||
|
||||
private picker: HTMLSpanElement;
|
||||
|
||||
private prefixCls?: string;
|
||||
|
||||
private tagPrefixCls?: string;
|
||||
|
||||
constructor(props: any) {
|
||||
@ -133,6 +134,17 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
||||
}
|
||||
}
|
||||
|
||||
setValue(value: RangePickerValue, hidePanel?: boolean) {
|
||||
this.handleChange(value);
|
||||
if ((hidePanel || !this.props.showTime) && !('open' in this.props)) {
|
||||
this.setState({ open: false });
|
||||
}
|
||||
}
|
||||
|
||||
savePicker = (node: HTMLSpanElement) => {
|
||||
this.picker = node;
|
||||
};
|
||||
|
||||
clearSelection = (e: React.MouseEvent<HTMLElement>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@ -143,7 +155,7 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
||||
clearHoverValue = () => this.setState({ hoverValue: [] });
|
||||
|
||||
handleChange = (value: RangePickerValue) => {
|
||||
const props = this.props;
|
||||
const { props } = this;
|
||||
if (!('value' in props)) {
|
||||
this.setState(({ showDate }) => ({
|
||||
value,
|
||||
@ -210,13 +222,6 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
||||
}
|
||||
};
|
||||
|
||||
setValue(value: RangePickerValue, hidePanel?: boolean) {
|
||||
this.handleChange(value);
|
||||
if ((hidePanel || !this.props.showTime) && !('open' in this.props)) {
|
||||
this.setState({ open: false });
|
||||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.picker.focus();
|
||||
}
|
||||
@ -225,10 +230,6 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
||||
this.picker.blur();
|
||||
}
|
||||
|
||||
savePicker = (node: HTMLSpanElement) => {
|
||||
this.picker = node;
|
||||
};
|
||||
|
||||
renderFooter = () => {
|
||||
const { ranges, renderExtraFooter } = this.props;
|
||||
const { prefixCls, tagPrefixCls } = this;
|
||||
|
@ -39,6 +39,7 @@ class WeekPicker extends React.Component<any, WeekPickerState> {
|
||||
}
|
||||
|
||||
private input: any;
|
||||
|
||||
private prefixCls?: string;
|
||||
|
||||
constructor(props: any) {
|
||||
@ -62,6 +63,10 @@ class WeekPicker extends React.Component<any, WeekPickerState> {
|
||||
}
|
||||
}
|
||||
|
||||
saveInput = (node: any) => {
|
||||
this.input = node;
|
||||
};
|
||||
|
||||
weekDateRender = (current: any) => {
|
||||
const selectedValue = this.state.value;
|
||||
const { prefixCls } = this;
|
||||
@ -105,13 +110,6 @@ class WeekPicker extends React.Component<any, WeekPickerState> {
|
||||
this.handleChange(null);
|
||||
};
|
||||
|
||||
renderFooter = (...args: any[]) => {
|
||||
const { prefixCls, renderExtraFooter } = this.props;
|
||||
return renderExtraFooter ? (
|
||||
<div className={`${prefixCls}-footer-extra`}>{renderExtraFooter(...args)}</div>
|
||||
) : null;
|
||||
};
|
||||
|
||||
focus() {
|
||||
this.input.focus();
|
||||
}
|
||||
@ -120,8 +118,11 @@ class WeekPicker extends React.Component<any, WeekPickerState> {
|
||||
this.input.blur();
|
||||
}
|
||||
|
||||
saveInput = (node: any) => {
|
||||
this.input = node;
|
||||
renderFooter = (...args: any[]) => {
|
||||
const { prefixCls, renderExtraFooter } = this.props;
|
||||
return renderExtraFooter ? (
|
||||
<div className={`${prefixCls}-footer-extra`}>{renderExtraFooter(...args)}</div>
|
||||
) : null;
|
||||
};
|
||||
|
||||
renderWeekPicker = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
|
@ -78,12 +78,8 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
||||
}
|
||||
}
|
||||
|
||||
renderFooter = (...args: any[]) => {
|
||||
const { renderExtraFooter } = this.props;
|
||||
const { prefixCls } = this;
|
||||
return renderExtraFooter ? (
|
||||
<div className={`${prefixCls}-footer-extra`}>{renderExtraFooter(...args)}</div>
|
||||
) : null;
|
||||
saveInput = (node: any) => {
|
||||
this.input = node;
|
||||
};
|
||||
|
||||
clearSelection = (e: React.MouseEvent<HTMLElement>) => {
|
||||
@ -126,8 +122,12 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
||||
this.input.blur();
|
||||
}
|
||||
|
||||
saveInput = (node: any) => {
|
||||
this.input = node;
|
||||
renderFooter = (...args: any[]) => {
|
||||
const { renderExtraFooter } = this.props;
|
||||
const { prefixCls } = this;
|
||||
return renderExtraFooter ? (
|
||||
<div className={`${prefixCls}-footer-extra`}>{renderExtraFooter(...args)}</div>
|
||||
) : null;
|
||||
};
|
||||
|
||||
renderPicker = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
@ -272,5 +272,6 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
||||
}
|
||||
}
|
||||
polyfill(CalenderWrapper);
|
||||
|
||||
return CalenderWrapper;
|
||||
}
|
||||
|
@ -89,6 +89,22 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, pickerType
|
||||
}
|
||||
}
|
||||
|
||||
savePicker = (node: any) => {
|
||||
this.picker = node;
|
||||
};
|
||||
|
||||
getDefaultLocale = () => {
|
||||
const result = {
|
||||
...enUS,
|
||||
...this.props.locale,
|
||||
};
|
||||
result.lang = {
|
||||
...result.lang,
|
||||
...(this.props.locale || {}).lang,
|
||||
};
|
||||
return result;
|
||||
};
|
||||
|
||||
handleOpenChange = (open: boolean) => {
|
||||
const { onOpenChange } = this.props;
|
||||
onOpenChange(open);
|
||||
@ -130,22 +146,6 @@ export default function wrapPicker(Picker: React.ComponentClass<any>, pickerType
|
||||
this.picker.blur();
|
||||
}
|
||||
|
||||
savePicker = (node: any) => {
|
||||
this.picker = node;
|
||||
};
|
||||
|
||||
getDefaultLocale = () => {
|
||||
const result = {
|
||||
...enUS,
|
||||
...this.props.locale,
|
||||
};
|
||||
result.lang = {
|
||||
...result.lang,
|
||||
...(this.props.locale || {}).lang,
|
||||
};
|
||||
return result;
|
||||
};
|
||||
|
||||
renderPicker = (locale: any, localeCode: string) => {
|
||||
const { format, showTime } = this.props;
|
||||
const mergedPickerType = showTime ? `${pickerType}Time` : pickerType;
|
||||
|
@ -156,13 +156,17 @@ class Descriptions extends React.Component<
|
||||
size: 'default',
|
||||
column: defaultColumnMap,
|
||||
};
|
||||
|
||||
static Item: typeof DescriptionsItem = DescriptionsItem;
|
||||
|
||||
state: {
|
||||
screens: BreakpointMap;
|
||||
} = {
|
||||
screens: {},
|
||||
};
|
||||
|
||||
token: string;
|
||||
|
||||
componentDidMount() {
|
||||
const { column } = this.props;
|
||||
this.token = ResponsiveObserve.subscribe(screens => {
|
||||
@ -189,7 +193,7 @@ class Descriptions extends React.Component<
|
||||
}
|
||||
}
|
||||
}
|
||||
//If the configuration is not an object, it is a number, return number
|
||||
// If the configuration is not an object, it is a number, return number
|
||||
if (typeof column === 'number') {
|
||||
return column as number;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ const Divider: React.SFC<DividerProps> = props => (
|
||||
...restProps
|
||||
} = props;
|
||||
const prefixCls = getPrefixCls('divider', customizePrefixCls);
|
||||
const orientationPrefix = orientation.length > 0 ? '-' + orientation : orientation;
|
||||
const orientationPrefix = orientation.length > 0 ? `-${orientation}` : orientation;
|
||||
const classString = classNames(className, prefixCls, `${prefixCls}-${type}`, {
|
||||
[`${prefixCls}-with-text${orientationPrefix}`]: children,
|
||||
[`${prefixCls}-dashed`]: !!dashed,
|
||||
|
@ -75,7 +75,14 @@ class App extends React.Component {
|
||||
]}
|
||||
bordered
|
||||
renderItem={item => (
|
||||
<List.Item key={item.id} actions={[<a onClick={this.showDrawer}>View Profile</a>]}>
|
||||
<List.Item
|
||||
key={item.id}
|
||||
actions={[
|
||||
<a onClick={this.showDrawer} key={`a-${item.id}`}>
|
||||
View Profile
|
||||
</a>,
|
||||
]}
|
||||
>
|
||||
<List.Item.Meta
|
||||
avatar={
|
||||
<Avatar src="https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png" />
|
||||
|
@ -1,8 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import RcDrawer from 'rc-drawer';
|
||||
import createReactContext from '@ant-design/create-react-context';
|
||||
import warning from '../_util/warning';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import warning from '../_util/warning';
|
||||
import Icon from '../icon';
|
||||
import { withConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { tuple } from '../_util/type';
|
||||
@ -159,6 +160,7 @@ class Drawer extends React.Component<DrawerProps & ConfigConsumerProps, IDrawerS
|
||||
const { closable, prefixCls, onClose } = this.props;
|
||||
return (
|
||||
closable && (
|
||||
// eslint-disable-next-line react/button-has-type
|
||||
<button onClick={onClose} aria-label="Close" className={`${prefixCls}-close`}>
|
||||
<Icon type="close" />
|
||||
</button>
|
||||
@ -208,27 +210,12 @@ class Drawer extends React.Component<DrawerProps & ConfigConsumerProps, IDrawerS
|
||||
renderProvider = (value: Drawer) => {
|
||||
const {
|
||||
prefixCls,
|
||||
zIndex,
|
||||
style,
|
||||
placement,
|
||||
className,
|
||||
wrapClassName,
|
||||
width,
|
||||
height,
|
||||
closable,
|
||||
destroyOnClose,
|
||||
mask,
|
||||
bodyStyle,
|
||||
title,
|
||||
push,
|
||||
visible,
|
||||
// ConfigConsumerProps
|
||||
getPopupContainer,
|
||||
rootPrefixCls,
|
||||
getPrefixCls,
|
||||
renderEmpty,
|
||||
csp,
|
||||
autoInsertSpaceInButton,
|
||||
...rest
|
||||
} = this.props;
|
||||
warning(
|
||||
@ -248,7 +235,22 @@ class Drawer extends React.Component<DrawerProps & ConfigConsumerProps, IDrawerS
|
||||
<DrawerContext.Provider value={this}>
|
||||
<RcDrawer
|
||||
handler={false}
|
||||
{...rest}
|
||||
{...omit(rest, [
|
||||
'zIndex',
|
||||
'style',
|
||||
'closable',
|
||||
'destroyOnClose',
|
||||
'bodyStyle',
|
||||
'title',
|
||||
'push',
|
||||
'visible',
|
||||
'getPopupContainer',
|
||||
'rootPrefixCls',
|
||||
'getPrefixCls',
|
||||
'renderEmpty',
|
||||
'csp',
|
||||
'autoInsertSpaceInButton',
|
||||
])}
|
||||
{...offsetStyle}
|
||||
prefixCls={prefixCls}
|
||||
open={this.props.visible}
|
||||
|
@ -54,6 +54,7 @@ export interface DropDownProps {
|
||||
|
||||
export default class Dropdown extends React.Component<DropDownProps, any> {
|
||||
static Button: typeof DropdownButton;
|
||||
|
||||
static defaultProps = {
|
||||
mouseEnterDelay: 0.15,
|
||||
mouseLeaveDelay: 0.1,
|
||||
@ -90,7 +91,7 @@ export default class Dropdown extends React.Component<DropDownProps, any> {
|
||||
warning(
|
||||
!overlayProps.mode || overlayProps.mode === 'vertical',
|
||||
'Dropdown',
|
||||
`mode="${overlayProps.mode}" is not supported for Dropdown\'s Menu.`,
|
||||
`mode="${overlayProps.mode}" is not supported for Dropdown's Menu.`,
|
||||
);
|
||||
|
||||
// menu cannot be selectable in dropdown defaultly
|
||||
|
@ -475,6 +475,7 @@ exports[`renders ./components/empty/demo/config-provider.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-table ant-table-default ant-table-empty ant-table-scroll-position-left"
|
||||
style="margin-top:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-table-content"
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export default () => (
|
||||
const Empty = () => (
|
||||
<svg width="184" height="152" viewBox="0 0 184 152" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<g transform="translate(24 31.67)">
|
||||
@ -34,3 +34,5 @@ export default () => (
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default Empty;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export default () => (
|
||||
const Simple = () => (
|
||||
<svg width="64" height="41" viewBox="0 0 64 41" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0 1)" fill="none" fillRule="evenodd">
|
||||
<ellipse fill="#F5F5F5" cx="32" cy="33" rx="32" ry="7" />
|
||||
@ -14,3 +14,5 @@ export default () => (
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default Simple;
|
||||
|
@ -91,7 +91,7 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
} else if (React.isValidElement(e.message)) {
|
||||
node = e.message;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
return node ? React.cloneElement(node, { key: index }) : e.message;
|
||||
}),
|
||||
);
|
||||
@ -151,6 +151,40 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
return this.getChildProp(FIELD_DATA_PROP);
|
||||
}
|
||||
|
||||
getValidateStatus() {
|
||||
const onlyControl = this.getOnlyControl();
|
||||
if (!onlyControl) {
|
||||
return '';
|
||||
}
|
||||
const field = this.getField();
|
||||
if (field.validating) {
|
||||
return 'validating';
|
||||
}
|
||||
if (field.errors) {
|
||||
return 'error';
|
||||
}
|
||||
const fieldValue = 'value' in field ? field.value : this.getMeta().initialValue;
|
||||
if (fieldValue !== undefined && fieldValue !== null && fieldValue !== '') {
|
||||
return 'success';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
// Resolve duplicated ids bug between different forms
|
||||
// https://github.com/ant-design/ant-design/issues/7351
|
||||
onLabelClick = () => {
|
||||
const id = this.props.id || this.getId();
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formItemNode = ReactDOM.findDOMNode(this) as Element;
|
||||
const control = formItemNode.querySelector(`[id="${id}"]`) as HTMLElement;
|
||||
if (control && control.focus) {
|
||||
control.focus();
|
||||
}
|
||||
};
|
||||
|
||||
onHelpAnimEnd = (_key: string, helpShow: boolean) => {
|
||||
this.helpShow = helpShow;
|
||||
if (!helpShow) {
|
||||
@ -158,6 +192,24 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
}
|
||||
};
|
||||
|
||||
isRequired() {
|
||||
const { required } = this.props;
|
||||
if (required !== undefined) {
|
||||
return required;
|
||||
}
|
||||
if (this.getOnlyControl()) {
|
||||
const meta = this.getMeta() || {};
|
||||
const validate = meta.validate || [];
|
||||
|
||||
return validate
|
||||
.filter((item: any) => !!item.rules)
|
||||
.some((item: any) => {
|
||||
return item.rules.some((rule: any) => rule.required);
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
renderHelp(prefixCls: string) {
|
||||
const help = this.getHelpMessage();
|
||||
const children = help ? (
|
||||
@ -186,25 +238,6 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
return extra ? <div className={`${prefixCls}-extra`}>{extra}</div> : null;
|
||||
}
|
||||
|
||||
getValidateStatus() {
|
||||
const onlyControl = this.getOnlyControl();
|
||||
if (!onlyControl) {
|
||||
return '';
|
||||
}
|
||||
const field = this.getField();
|
||||
if (field.validating) {
|
||||
return 'validating';
|
||||
}
|
||||
if (field.errors) {
|
||||
return 'error';
|
||||
}
|
||||
const fieldValue = 'value' in field ? field.value : this.getMeta().initialValue;
|
||||
if (fieldValue !== undefined && fieldValue !== null && fieldValue !== '') {
|
||||
return 'success';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
renderValidateWrapper(
|
||||
prefixCls: string,
|
||||
c1: React.ReactNode,
|
||||
@ -293,39 +326,6 @@ export default class FormItem extends React.Component<FormItemProps, any> {
|
||||
);
|
||||
}
|
||||
|
||||
isRequired() {
|
||||
const { required } = this.props;
|
||||
if (required !== undefined) {
|
||||
return required;
|
||||
}
|
||||
if (this.getOnlyControl()) {
|
||||
const meta = this.getMeta() || {};
|
||||
const validate = meta.validate || [];
|
||||
|
||||
return validate
|
||||
.filter((item: any) => !!item.rules)
|
||||
.some((item: any) => {
|
||||
return item.rules.some((rule: any) => rule.required);
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Resolve duplicated ids bug between different forms
|
||||
// https://github.com/ant-design/ant-design/issues/7351
|
||||
onLabelClick = () => {
|
||||
const id = this.props.id || this.getId();
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formItemNode = ReactDOM.findDOMNode(this) as Element;
|
||||
const control = formItemNode.querySelector(`[id="${id}"]`) as HTMLElement;
|
||||
if (control && control.focus) {
|
||||
control.focus();
|
||||
}
|
||||
};
|
||||
|
||||
renderLabel(prefixCls: string) {
|
||||
return (
|
||||
<FormContext.Consumer key="label">
|
||||
|
@ -81,7 +81,7 @@ describe('Form', () => {
|
||||
|
||||
myForm.setFields({
|
||||
account: {
|
||||
errors: [<div>Error 1</div>, <div>Error 2</div>],
|
||||
errors: [<div key="error-1">Error 1</div>, <div key="error-2">Error 2</div>],
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -53,7 +53,7 @@ class PriceInput extends React.Component {
|
||||
|
||||
handleNumberChange = e => {
|
||||
const number = parseInt(e.target.value || 0, 10);
|
||||
if (Number.isNaN(number)) {
|
||||
if (isNaN(number)) {
|
||||
return;
|
||||
}
|
||||
if (!('value' in this.props)) {
|
||||
|
@ -50,7 +50,7 @@ export default class Col extends React.Component<ColProps, {}> {
|
||||
};
|
||||
|
||||
renderCol = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const props: any = this.props;
|
||||
const { props } = this;
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
span,
|
||||
@ -66,13 +66,14 @@ export default class Col extends React.Component<ColProps, {}> {
|
||||
let sizeClassObj = {};
|
||||
['xs', 'sm', 'md', 'lg', 'xl', 'xxl'].forEach(size => {
|
||||
let sizeProps: ColSize = {};
|
||||
if (typeof props[size] === 'number') {
|
||||
sizeProps.span = props[size];
|
||||
} else if (typeof props[size] === 'object') {
|
||||
sizeProps = props[size] || {};
|
||||
const propSize = (props as any)[size];
|
||||
if (typeof propSize === 'number') {
|
||||
sizeProps.span = propSize;
|
||||
} else if (typeof propSize === 'object') {
|
||||
sizeProps = propSize || {};
|
||||
}
|
||||
|
||||
delete others[size];
|
||||
delete (others as any)[size];
|
||||
|
||||
sizeClassObj = {
|
||||
...sizeClassObj,
|
||||
@ -100,7 +101,7 @@ export default class Col extends React.Component<ColProps, {}> {
|
||||
return (
|
||||
<RowContext.Consumer>
|
||||
{({ gutter }) => {
|
||||
let style = others.style;
|
||||
let { style } = others;
|
||||
if (gutter! > 0) {
|
||||
style = {
|
||||
paddingLeft: gutter! / 2,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import RowContext from './RowContext';
|
||||
import { tuple } from '../_util/type';
|
||||
import ResponsiveObserve, {
|
||||
@ -42,7 +42,9 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
state: RowState = {
|
||||
screens: {},
|
||||
};
|
||||
|
||||
token: string;
|
||||
|
||||
componentDidMount() {
|
||||
this.token = ResponsiveObserve.subscribe(screens => {
|
||||
if (typeof this.props.gutter === 'object') {
|
||||
@ -50,9 +52,11 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
ResponsiveObserve.unsubscribe(this.token);
|
||||
}
|
||||
|
||||
getGutter(): number | undefined {
|
||||
const { gutter } = this.props;
|
||||
if (typeof gutter === 'object') {
|
||||
@ -65,6 +69,7 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
}
|
||||
return gutter as number;
|
||||
}
|
||||
|
||||
renderRow = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
|
@ -61,9 +61,9 @@
|
||||
}
|
||||
|
||||
.@{ant-prefix}-col {
|
||||
position: relative;
|
||||
// Prevent columns from collapsing when empty
|
||||
min-height: 1px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.make-grid-columns();
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Icon, { IconProps } from './index';
|
||||
import * as React from 'react';
|
||||
import Icon, { IconProps } from './index';
|
||||
|
||||
const customCache = new Set<string>();
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable camelcase */
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import * as allIcons from '@ant-design/icons/lib/dist';
|
||||
@ -18,7 +19,27 @@ import { getTwoToneColor, setTwoToneColor } from './twoTonePrimaryColor';
|
||||
ReactIcon.add(...Object.keys(allIcons).map(key => (allIcons as any)[key]));
|
||||
setTwoToneColor('#1890ff');
|
||||
let defaultTheme: ThemeType = 'outlined';
|
||||
let dangerousTheme: ThemeType | undefined = undefined;
|
||||
let dangerousTheme: ThemeType | undefined;
|
||||
|
||||
function unstable_ChangeThemeOfIconsDangerously(theme?: ThemeType) {
|
||||
warning(
|
||||
false,
|
||||
'Icon',
|
||||
`You are using the unstable method 'Icon.unstable_ChangeThemeOfAllIconsDangerously', ` +
|
||||
`make sure that all the icons with theme '${theme}' display correctly.`,
|
||||
);
|
||||
dangerousTheme = theme;
|
||||
}
|
||||
|
||||
function unstable_ChangeDefaultThemeOfIcons(theme: ThemeType) {
|
||||
warning(
|
||||
false,
|
||||
'Icon',
|
||||
`You are using the unstable method 'Icon.unstable_ChangeDefaultThemeOfIcons', ` +
|
||||
`make sure that all the icons with theme '${theme}' display correctly.`,
|
||||
);
|
||||
defaultTheme = theme;
|
||||
}
|
||||
|
||||
export interface TransferLocale {
|
||||
icon: string;
|
||||
@ -196,26 +217,6 @@ const Icon: IconComponent<IconProps> = props => {
|
||||
);
|
||||
};
|
||||
|
||||
function unstable_ChangeThemeOfIconsDangerously(theme?: ThemeType) {
|
||||
warning(
|
||||
false,
|
||||
'Icon',
|
||||
`You are using the unstable method 'Icon.unstable_ChangeThemeOfAllIconsDangerously', ` +
|
||||
`make sure that all the icons with theme '${theme}' display correctly.`,
|
||||
);
|
||||
dangerousTheme = theme;
|
||||
}
|
||||
|
||||
function unstable_ChangeDefaultThemeOfIcons(theme: ThemeType) {
|
||||
warning(
|
||||
false,
|
||||
'Icon',
|
||||
`You are using the unstable method 'Icon.unstable_ChangeDefaultThemeOfIcons', ` +
|
||||
`make sure that all the icons with theme '${theme}' display correctly.`,
|
||||
);
|
||||
defaultTheme = theme;
|
||||
}
|
||||
|
||||
Icon.createFromIconfontCN = createFromIconfontCN;
|
||||
Icon.getTwoToneColor = getTwoToneColor;
|
||||
Icon.setTwoToneColor = setTwoToneColor;
|
||||
|
@ -39,8 +39,11 @@ export interface InputProps
|
||||
|
||||
class Input extends React.Component<InputProps, any> {
|
||||
static Group: typeof Group;
|
||||
|
||||
static Search: typeof Search;
|
||||
|
||||
static TextArea: typeof TextArea;
|
||||
|
||||
static Password: typeof Password;
|
||||
|
||||
static defaultProps = {
|
||||
@ -88,6 +91,10 @@ class Input extends React.Component<InputProps, any> {
|
||||
};
|
||||
}
|
||||
|
||||
// Since polyfill `getSnapshotBeforeUpdate` need work with `componentDidUpdate`.
|
||||
// We keep an empty function here.
|
||||
componentDidUpdate() {}
|
||||
|
||||
getSnapshotBeforeUpdate(prevProps: InputProps) {
|
||||
if (hasPrefixSuffix(prevProps) !== hasPrefixSuffix(this.props)) {
|
||||
warning(
|
||||
@ -99,32 +106,6 @@ class Input extends React.Component<InputProps, any> {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Since polyfill `getSnapshotBeforeUpdate` need work with `componentDidUpdate`.
|
||||
// We keep an empty function here.
|
||||
componentDidUpdate() {}
|
||||
|
||||
handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
const { onPressEnter, onKeyDown } = this.props;
|
||||
if (e.keyCode === 13 && onPressEnter) {
|
||||
onPressEnter(e);
|
||||
}
|
||||
if (onKeyDown) {
|
||||
onKeyDown(e);
|
||||
}
|
||||
};
|
||||
|
||||
focus() {
|
||||
this.input.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.input.blur();
|
||||
}
|
||||
|
||||
select() {
|
||||
this.input.select();
|
||||
}
|
||||
|
||||
getInputClassName(prefixCls: string) {
|
||||
const { size, disabled } = this.props;
|
||||
return classNames(prefixCls, {
|
||||
@ -134,10 +115,6 @@ class Input extends React.Component<InputProps, any> {
|
||||
});
|
||||
}
|
||||
|
||||
saveInput = (node: HTMLInputElement) => {
|
||||
this.input = node;
|
||||
};
|
||||
|
||||
setValue(
|
||||
value: string,
|
||||
e: React.ChangeEvent<HTMLInputElement> | React.MouseEvent<HTMLElement, MouseEvent>,
|
||||
@ -166,6 +143,20 @@ class Input extends React.Component<InputProps, any> {
|
||||
}
|
||||
}
|
||||
|
||||
saveInput = (node: HTMLInputElement) => {
|
||||
this.input = node;
|
||||
};
|
||||
|
||||
handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
const { onPressEnter, onKeyDown } = this.props;
|
||||
if (e.keyCode === 13 && onPressEnter) {
|
||||
onPressEnter(e);
|
||||
}
|
||||
if (onKeyDown) {
|
||||
onKeyDown(e);
|
||||
}
|
||||
};
|
||||
|
||||
handleReset = (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
||||
this.setValue('', e, () => {
|
||||
this.focus();
|
||||
@ -176,6 +167,18 @@ class Input extends React.Component<InputProps, any> {
|
||||
this.setValue(e.target.value, e);
|
||||
};
|
||||
|
||||
focus() {
|
||||
this.input.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.input.blur();
|
||||
}
|
||||
|
||||
select() {
|
||||
this.input.select();
|
||||
}
|
||||
|
||||
renderClearIcon(prefixCls: string) {
|
||||
const { allowClear } = this.props;
|
||||
const { value } = this.state;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import Input, { InputProps } from './Input';
|
||||
import Icon from '../icon';
|
||||
|
||||
@ -31,9 +32,7 @@ export default class Password extends React.Component<PasswordProps, PasswordSta
|
||||
};
|
||||
|
||||
onChange = () => {
|
||||
this.setState({
|
||||
visible: !this.state.visible,
|
||||
});
|
||||
this.setState(({ visible }) => ({ visible: !visible }));
|
||||
};
|
||||
|
||||
getIcon() {
|
||||
@ -59,7 +58,6 @@ export default class Password extends React.Component<PasswordProps, PasswordSta
|
||||
prefixCls,
|
||||
inputPrefixCls,
|
||||
size,
|
||||
suffix,
|
||||
visibilityToggle,
|
||||
...restProps
|
||||
} = this.props;
|
||||
@ -69,7 +67,7 @@ export default class Password extends React.Component<PasswordProps, PasswordSta
|
||||
});
|
||||
return (
|
||||
<Input
|
||||
{...restProps}
|
||||
{...omit(restProps, ['suffix'])}
|
||||
type={this.state.visible ? 'text' : 'password'}
|
||||
size={size}
|
||||
className={inputClassName}
|
||||
|
@ -21,6 +21,10 @@ export default class Search extends React.Component<SearchProps, any> {
|
||||
|
||||
private input: Input;
|
||||
|
||||
saveInput = (node: Input) => {
|
||||
this.input = node;
|
||||
};
|
||||
|
||||
onSearch = (e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLInputElement>) => {
|
||||
const { onSearch } = this.props;
|
||||
if (onSearch) {
|
||||
@ -37,10 +41,6 @@ export default class Search extends React.Component<SearchProps, any> {
|
||||
this.input.blur();
|
||||
}
|
||||
|
||||
saveInput = (node: Input) => {
|
||||
this.input = node;
|
||||
};
|
||||
|
||||
renderSuffix = (prefixCls: string) => {
|
||||
const { suffix, enterButton } = this.props;
|
||||
if (enterButton) return suffix;
|
||||
|
@ -28,6 +28,7 @@ export interface TextAreaState {
|
||||
|
||||
class TextArea extends React.Component<TextAreaProps, TextAreaState> {
|
||||
nextFrameActionId: number;
|
||||
|
||||
resizeFrameId: number;
|
||||
|
||||
state = {
|
||||
@ -53,32 +54,8 @@ class TextArea extends React.Component<TextAreaProps, TextAreaState> {
|
||||
raf.cancel(this.resizeFrameId);
|
||||
}
|
||||
|
||||
resizeOnNextFrame = () => {
|
||||
raf.cancel(this.nextFrameActionId);
|
||||
this.nextFrameActionId = raf(this.resizeTextarea);
|
||||
};
|
||||
|
||||
focus() {
|
||||
this.textAreaRef.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.textAreaRef.blur();
|
||||
}
|
||||
|
||||
resizeTextarea = () => {
|
||||
const { autosize } = this.props;
|
||||
if (!autosize || !this.textAreaRef) {
|
||||
return;
|
||||
}
|
||||
const { minRows, maxRows } = autosize as AutoSizeType;
|
||||
const textareaStyles = calculateNodeHeight(this.textAreaRef, false, minRows, maxRows);
|
||||
this.setState({ textareaStyles, resizing: true }, () => {
|
||||
raf.cancel(this.resizeFrameId);
|
||||
this.resizeFrameId = raf(() => {
|
||||
this.setState({ resizing: false });
|
||||
});
|
||||
});
|
||||
saveTextAreaRef = (textArea: HTMLTextAreaElement) => {
|
||||
this.textAreaRef = textArea;
|
||||
};
|
||||
|
||||
handleTextareaChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
@ -101,10 +78,34 @@ class TextArea extends React.Component<TextAreaProps, TextAreaState> {
|
||||
}
|
||||
};
|
||||
|
||||
saveTextAreaRef = (textArea: HTMLTextAreaElement) => {
|
||||
this.textAreaRef = textArea;
|
||||
resizeOnNextFrame = () => {
|
||||
raf.cancel(this.nextFrameActionId);
|
||||
this.nextFrameActionId = raf(this.resizeTextarea);
|
||||
};
|
||||
|
||||
resizeTextarea = () => {
|
||||
const { autosize } = this.props;
|
||||
if (!autosize || !this.textAreaRef) {
|
||||
return;
|
||||
}
|
||||
const { minRows, maxRows } = autosize as AutoSizeType;
|
||||
const textareaStyles = calculateNodeHeight(this.textAreaRef, false, minRows, maxRows);
|
||||
this.setState({ textareaStyles, resizing: true }, () => {
|
||||
raf.cancel(this.resizeFrameId);
|
||||
this.resizeFrameId = raf(() => {
|
||||
this.setState({ resizing: false });
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
focus() {
|
||||
this.textAreaRef.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.textAreaRef.blur();
|
||||
}
|
||||
|
||||
renderTextArea = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { textareaStyles, resizing } = this.state;
|
||||
const { prefixCls: customizePrefixCls, className, disabled, autosize } = this.props;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
/* eslint-disable import/no-unresolved */
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import Form from '../../form';
|
||||
import Input from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
|
@ -124,10 +124,10 @@ export default function calculateNodeHeight(
|
||||
|
||||
if (boxSizing === 'border-box') {
|
||||
// border-box: add border, since height = content + padding + border
|
||||
height = height + borderSize;
|
||||
height += borderSize;
|
||||
} else if (boxSizing === 'content-box') {
|
||||
// remove padding, since height = content
|
||||
height = height - paddingSize;
|
||||
height -= paddingSize;
|
||||
}
|
||||
|
||||
if (minRows !== null || maxRows !== null) {
|
||||
|
@ -36,7 +36,7 @@ class NumericInput extends React.Component {
|
||||
onChange = e => {
|
||||
const { value } = e.target;
|
||||
const reg = /^-?(0|[1-9][0-9]*)(\.[0-9]*)?$/;
|
||||
if ((!Number.isNaN(value) && reg.test(value)) || value === '' || value === '-') {
|
||||
if ((!isNaN(value) && reg.test(value)) || value === '' || value === '-') {
|
||||
this.props.onChange(value);
|
||||
}
|
||||
};
|
||||
|
@ -40,6 +40,7 @@
|
||||
background-color: @input-disabled-bg;
|
||||
cursor: not-allowed;
|
||||
opacity: 1;
|
||||
|
||||
&:hover {
|
||||
.hover(@input-border-color);
|
||||
}
|
||||
@ -116,6 +117,7 @@
|
||||
|
||||
> [class*='col-'] {
|
||||
padding-right: 8px;
|
||||
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
@ -147,10 +149,12 @@
|
||||
width: 100%;
|
||||
margin-bottom: 0;
|
||||
text-align: inherit;
|
||||
|
||||
&:focus {
|
||||
z-index: 1; // Fix https://gw.alipayobjects.com/zos/rmsportal/DHNpoqfMXSfrSnlZvhsJ.png
|
||||
border-right-width: 1px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
z-index: 1;
|
||||
border-right-width: 1px;
|
||||
@ -229,6 +233,7 @@
|
||||
&-addon:first-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
&-addon:last-child {
|
||||
border-left: 0;
|
||||
}
|
||||
@ -280,9 +285,11 @@
|
||||
> .@{inputClass} {
|
||||
&:not(:first-child):not(:last-child) {
|
||||
border-right-width: @border-width-base;
|
||||
|
||||
&:hover {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
z-index: 1;
|
||||
}
|
||||
@ -315,9 +322,11 @@
|
||||
& > .@{ant-prefix}-time-picker .@{ant-prefix}-time-picker-input {
|
||||
border-right-width: @border-width-base;
|
||||
border-radius: 0;
|
||||
|
||||
&:hover {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
z-index: 1;
|
||||
}
|
||||
@ -383,6 +392,7 @@
|
||||
color: @input-color;
|
||||
line-height: 0;
|
||||
transform: translateY(-50%);
|
||||
|
||||
:not(.anticon) {
|
||||
line-height: @line-height-base;
|
||||
}
|
||||
@ -403,6 +413,7 @@
|
||||
.@{inputClass}:not(:last-child) {
|
||||
padding-right: @input-padding-horizontal-base + @input-affix-width;
|
||||
}
|
||||
|
||||
&.@{inputClass}-affix-wrapper-with-clear-btn .@{inputClass}:not(:last-child) {
|
||||
padding-right: @input-padding-horizontal-base + @input-affix-with-clear-btn-width;
|
||||
}
|
||||
|
@ -1,6 +1,13 @@
|
||||
import createContext, { Context } from '@ant-design/create-react-context';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
|
||||
import * as React from 'react';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import { LayoutContext, LayoutContextProps } from './layout';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import Icon from '../icon';
|
||||
import isNumeric from '../_util/isNumeric';
|
||||
|
||||
// matchMedia polyfill for
|
||||
// https://github.com/WickyNilliams/enquire.js/issues/82
|
||||
@ -16,13 +23,6 @@ if (typeof window !== 'undefined') {
|
||||
window.matchMedia = window.matchMedia || matchMediaPolyfill;
|
||||
}
|
||||
|
||||
import * as React from 'react';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import Icon from '../icon';
|
||||
import isNumeric from '../_util/isNumeric';
|
||||
|
||||
const dimensionMap = {
|
||||
xs: '480px',
|
||||
sm: '576px',
|
||||
@ -95,6 +95,7 @@ class InternalSider extends React.Component<InternalSideProps, SiderState> {
|
||||
}
|
||||
|
||||
private mql: MediaQueryList;
|
||||
|
||||
private uniqueId: string;
|
||||
|
||||
constructor(props: InternalSideProps) {
|
||||
@ -169,7 +170,7 @@ class InternalSider extends React.Component<InternalSideProps, SiderState> {
|
||||
};
|
||||
|
||||
belowShowChange = () => {
|
||||
this.setState({ belowShow: !this.state.belowShow });
|
||||
this.setState(({ belowShow }) => ({ belowShow: !belowShow }));
|
||||
};
|
||||
|
||||
renderSider = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
@ -266,6 +267,7 @@ class InternalSider extends React.Component<InternalSideProps, SiderState> {
|
||||
|
||||
polyfill(InternalSider);
|
||||
|
||||
// eslint-disable-next-line react/prefer-stateless-function
|
||||
export default class Sider extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
|
@ -31,11 +31,14 @@ interface BasicPropsWithTagName extends BasicProps {
|
||||
}
|
||||
|
||||
function generator({ suffixCls, tagName }: GeneratorProps) {
|
||||
return (BasicComponent: React.ComponentClass<BasicPropsWithTagName>): any => {
|
||||
return (BasicComponent: any) => {
|
||||
return class Adapter extends React.Component<BasicProps, any> {
|
||||
static Header: any;
|
||||
|
||||
static Footer: any;
|
||||
|
||||
static Content: any;
|
||||
|
||||
static Sider: any;
|
||||
|
||||
renderComponent = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
@ -52,13 +55,11 @@ function generator({ suffixCls, tagName }: GeneratorProps) {
|
||||
};
|
||||
}
|
||||
|
||||
class Basic extends React.Component<BasicPropsWithTagName, any> {
|
||||
render() {
|
||||
const { prefixCls, className, children, tagName, ...others } = this.props;
|
||||
const classString = classNames(className, prefixCls);
|
||||
return React.createElement(tagName, { className: classString, ...others }, children);
|
||||
}
|
||||
}
|
||||
const Basic = (props: BasicPropsWithTagName) => {
|
||||
const { prefixCls, className, children, tagName, ...others } = props;
|
||||
const classString = classNames(className, prefixCls);
|
||||
return React.createElement(tagName, { className: classString, ...others }, children);
|
||||
};
|
||||
|
||||
interface BasicLayoutState {
|
||||
siders: string[];
|
||||
|
@ -106,6 +106,7 @@ export default class Item extends React.Component<ListItemProps, any> {
|
||||
const actionsContent = actions && actions.length > 0 && (
|
||||
<ul className={`${prefixCls}-item-action`} key="actions">
|
||||
{actions.map((action: React.ReactNode, i: number) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<li key={`${prefixCls}-item-action-${i}`}>
|
||||
{action}
|
||||
{i !== actions.length - 1 && <em className={`${prefixCls}-item-action-split`} />}
|
||||
|
@ -109,7 +109,11 @@ describe('List Item Layout', () => {
|
||||
<List
|
||||
dataSource={data}
|
||||
renderItem={item => (
|
||||
<List.Item key={item.title} actions={[<a>Action</a>]} extra={<span>{item.extra}</span>}>
|
||||
<List.Item
|
||||
key={item.title}
|
||||
actions={[<a key="action">Action</a>]}
|
||||
extra={<span>{item.extra}</span>}
|
||||
>
|
||||
<List.Item.Meta
|
||||
title={<a href={item.href}>{item.title}</a>}
|
||||
description={item.description}
|
||||
|
@ -98,7 +98,9 @@ class LoadMoreList extends React.Component {
|
||||
loadMore={loadMore}
|
||||
dataSource={list}
|
||||
renderItem={item => (
|
||||
<List.Item actions={[<a>edit</a>, <a>more</a>]}>
|
||||
<List.Item
|
||||
actions={[<a key="list-loadmore-edit">edit</a>, <a key="list-loadmore-more">more</a>]}
|
||||
>
|
||||
<Skeleton avatar title={false} loading={item.loading} active>
|
||||
<List.Item.Meta
|
||||
avatar={
|
||||
|
@ -56,9 +56,9 @@ ReactDOM.render(
|
||||
<List.Item
|
||||
key={item.title}
|
||||
actions={[
|
||||
<IconText type="star-o" text="156" />,
|
||||
<IconText type="like-o" text="156" />,
|
||||
<IconText type="message" text="2" />,
|
||||
<IconText type="star-o" text="156" key="list-vertical-star-o" />,
|
||||
<IconText type="like-o" text="156" key="list-vertical-like-o" />,
|
||||
<IconText type="message" text="2" key="list-vertical-message" />,
|
||||
]}
|
||||
extra={
|
||||
<img
|
||||
|
@ -1,10 +1,10 @@
|
||||
import * as React from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { SpinProps } from '../spin';
|
||||
import omit from 'omit.js';
|
||||
import Spin, { SpinProps } from '../spin';
|
||||
import { ConfigConsumer, ConfigConsumerProps, RenderEmptyHandler } from '../config-provider';
|
||||
|
||||
import Spin from '../spin';
|
||||
import Pagination, { PaginationConfig } from '../pagination';
|
||||
import { Row } from '../grid';
|
||||
|
||||
@ -174,12 +174,9 @@ export default class List<T> extends React.Component<ListProps<T>, ListState> {
|
||||
grid,
|
||||
dataSource = [],
|
||||
size,
|
||||
rowKey,
|
||||
renderItem,
|
||||
header,
|
||||
footer,
|
||||
loading,
|
||||
locale,
|
||||
...rest
|
||||
} = this.props;
|
||||
|
||||
@ -201,6 +198,7 @@ export default class List<T> extends React.Component<ListProps<T>, ListState> {
|
||||
break;
|
||||
case 'small':
|
||||
sizeCls = 'sm';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -273,7 +271,7 @@ export default class List<T> extends React.Component<ListProps<T>, ListState> {
|
||||
const paginationPosition = paginationProps.position || 'bottom';
|
||||
|
||||
return (
|
||||
<div className={classString} {...rest}>
|
||||
<div className={classString} {...omit(rest, ['rowKey', 'renderItem', 'locale'])}>
|
||||
{(paginationPosition === 'top' || paginationPosition === 'both') && paginationContent}
|
||||
{header && <div className={`${prefixCls}-header`}>{header}</div>}
|
||||
<Spin {...loadingProp}>
|
||||
|
@ -118,7 +118,9 @@ describe('Mention', () => {
|
||||
if (process.env.REACT === '15') {
|
||||
return;
|
||||
}
|
||||
const wrapper = mount(<Mention defaultSuggestions={[<Mention.Nav value="light" />]} />);
|
||||
const wrapper = mount(
|
||||
<Mention defaultSuggestions={[<Mention.Nav key="light" value="light" />]} />,
|
||||
);
|
||||
wrapper.find('DraftEditorContents').simulate('focus');
|
||||
const ed = wrapper.find('.public-DraftEditor-content');
|
||||
ed.simulate('beforeInput', { data: '@l' });
|
||||
|
@ -54,7 +54,12 @@ class CustomNavMention extends React.Component {
|
||||
item => item.name.toLowerCase().indexOf(searchValue) !== -1,
|
||||
);
|
||||
const suggestions = filtered.map(suggestion => (
|
||||
<Nav value={suggestion.name} data={suggestion} disabled={suggestion.disabled}>
|
||||
<Nav
|
||||
value={suggestion.name}
|
||||
data={suggestion}
|
||||
disabled={suggestion.disabled}
|
||||
key="mention-avatar"
|
||||
>
|
||||
<Avatar
|
||||
src={suggestion.icon}
|
||||
size="small"
|
||||
|
@ -43,7 +43,7 @@ class CustomNavMention extends React.Component {
|
||||
item => item.name.toLowerCase().indexOf(searchValue) !== -1,
|
||||
);
|
||||
const suggestions = filtered.map(suggestion => (
|
||||
<Nav value={suggestion.name} data={suggestion}>
|
||||
<Nav value={suggestion.name} data={suggestion} key={suggestion.name}>
|
||||
<span>
|
||||
{suggestion.name} - {suggestion.type}
|
||||
</span>
|
||||
|
@ -42,17 +42,22 @@ export interface MentionState {
|
||||
|
||||
class Mention extends React.Component<MentionProps, MentionState> {
|
||||
static getMentions = getMentions;
|
||||
|
||||
static defaultProps = {
|
||||
notFoundContent: 'No matches found',
|
||||
loading: false,
|
||||
multiLines: false,
|
||||
placement: 'bottom' as MentionPlacement,
|
||||
};
|
||||
|
||||
static Nav = Nav;
|
||||
|
||||
static toString = toString;
|
||||
|
||||
static toContentState = toEditorState;
|
||||
|
||||
private mentionEle: any;
|
||||
|
||||
constructor(props: MentionProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@ -67,6 +72,10 @@ class Mention extends React.Component<MentionProps, MentionState> {
|
||||
);
|
||||
}
|
||||
|
||||
mentionRef = (ele: any) => {
|
||||
this.mentionEle = ele;
|
||||
};
|
||||
|
||||
onSearchChange = (value: string, prefix: string) => {
|
||||
if (this.props.onSearchChange) {
|
||||
return this.props.onSearchChange(value, prefix);
|
||||
@ -80,22 +89,6 @@ class Mention extends React.Component<MentionProps, MentionState> {
|
||||
}
|
||||
};
|
||||
|
||||
defaultSearchChange(value: string): void {
|
||||
const searchValue = value.toLowerCase();
|
||||
const filteredSuggestions = (this.props.defaultSuggestions || []).filter(suggestion => {
|
||||
if (typeof suggestion === 'string') {
|
||||
return suggestion.toLowerCase().indexOf(searchValue) !== -1;
|
||||
} else if (suggestion.type && suggestion.type === Nav) {
|
||||
return suggestion.props.value
|
||||
? suggestion.props.value.toLowerCase().indexOf(searchValue) !== -1
|
||||
: true;
|
||||
}
|
||||
});
|
||||
this.setState({
|
||||
filteredSuggestions,
|
||||
});
|
||||
}
|
||||
|
||||
onFocus = (ev: React.FocusEvent<HTMLElement>) => {
|
||||
this.setState({
|
||||
focus: true,
|
||||
@ -118,9 +111,24 @@ class Mention extends React.Component<MentionProps, MentionState> {
|
||||
this.mentionEle._editor.focusEditor();
|
||||
};
|
||||
|
||||
mentionRef = (ele: any) => {
|
||||
this.mentionEle = ele;
|
||||
};
|
||||
defaultSearchChange(value: string): void {
|
||||
const searchValue = value.toLowerCase();
|
||||
const filteredSuggestions = (this.props.defaultSuggestions || []).filter(suggestion => {
|
||||
if (typeof suggestion === 'string') {
|
||||
return suggestion.toLowerCase().indexOf(searchValue) !== -1;
|
||||
}
|
||||
if (suggestion.type && suggestion.type === Nav) {
|
||||
return suggestion.props.value
|
||||
? suggestion.props.value.toLowerCase().indexOf(searchValue) !== -1
|
||||
: true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
this.setState({
|
||||
filteredSuggestions,
|
||||
});
|
||||
}
|
||||
|
||||
renderMention = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
|
@ -4,11 +4,10 @@ import * as React from 'react';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
import RcMentions from 'rc-mentions';
|
||||
import { MentionsProps as RcMentionsProps } from 'rc-mentions/lib/Mentions';
|
||||
import { OptionProps as RcOptionProps } from 'rc-mentions/lib/Option';
|
||||
import Spin from '../spin';
|
||||
import { ConfigConsumer, ConfigConsumerProps, RenderEmptyHandler } from '../config-provider';
|
||||
|
||||
const Option: React.FunctionComponent<RcOptionProps> = RcMentions.Option;
|
||||
const { Option } = RcMentions;
|
||||
|
||||
function loadingFilterOption() {
|
||||
return true;
|
||||
@ -109,7 +108,7 @@ class Mentions extends React.Component<MentionProps, MentionState> {
|
||||
const { children, loading } = this.props;
|
||||
if (loading) {
|
||||
return (
|
||||
<Option value={'ANTD_SEARCHING'} disabled>
|
||||
<Option value="ANTD_SEARCHING" disabled>
|
||||
<Spin size="small" />
|
||||
</Option>
|
||||
);
|
||||
|
@ -24,6 +24,7 @@ export interface MenuItemProps
|
||||
|
||||
export default class MenuItem extends React.Component<MenuItemProps> {
|
||||
static isMenuItem = true;
|
||||
|
||||
private menuItem: this;
|
||||
|
||||
onKeyDown = (e: React.MouseEvent<HTMLElement>) => {
|
||||
|
@ -26,8 +26,10 @@ class SubMenu extends React.Component<SubMenuProps, any> {
|
||||
static contextTypes = {
|
||||
antdMenuTheme: PropTypes.string,
|
||||
};
|
||||
|
||||
// fix issue:https://github.com/ant-design/ant-design/issues/8666
|
||||
static isSubMenu = 1;
|
||||
|
||||
private subMenu: any;
|
||||
|
||||
onKeyDown = (e: React.MouseEvent<HTMLElement>) => {
|
||||
|
@ -2,12 +2,12 @@ import * as React from 'react';
|
||||
import RcMenu, { Divider, ItemGroup } from 'rc-menu';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
import SubMenu from './SubMenu';
|
||||
import Item from './MenuItem';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import animation from '../_util/openAnimation';
|
||||
import warning from '../_util/warning';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
import { SiderContext, SiderContextProps } from '../layout/Sider';
|
||||
import raf from '../_util/raf';
|
||||
import MenuContext, { MenuTheme } from './MenuContext';
|
||||
@ -169,15 +169,46 @@ class InternalMenu extends React.Component<InternalMenuProps, MenuState> {
|
||||
raf.cancel(this.mountRafId);
|
||||
}
|
||||
|
||||
restoreModeVerticalFromInline() {
|
||||
const { switchingModeFromInline } = this.state;
|
||||
if (switchingModeFromInline) {
|
||||
this.setState({
|
||||
switchingModeFromInline: false,
|
||||
});
|
||||
setOpenKeys(openKeys: string[]) {
|
||||
if (!('openKeys' in this.props)) {
|
||||
this.setState({ openKeys });
|
||||
}
|
||||
}
|
||||
|
||||
getRealMenuMode() {
|
||||
const inlineCollapsed = this.getInlineCollapsed();
|
||||
if (this.state.switchingModeFromInline && inlineCollapsed) {
|
||||
return 'inline';
|
||||
}
|
||||
const { mode } = this.props;
|
||||
return inlineCollapsed ? 'vertical' : mode;
|
||||
}
|
||||
|
||||
getInlineCollapsed() {
|
||||
const { inlineCollapsed } = this.props;
|
||||
if (this.props.siderCollapsed !== undefined) {
|
||||
return this.props.siderCollapsed;
|
||||
}
|
||||
return inlineCollapsed;
|
||||
}
|
||||
|
||||
getMenuOpenAnimation(menuMode: MenuMode) {
|
||||
const { openAnimation, openTransitionName } = this.props;
|
||||
let menuOpenAnimation = openAnimation || openTransitionName;
|
||||
if (openAnimation === undefined && openTransitionName === undefined) {
|
||||
if (menuMode === 'horizontal') {
|
||||
menuOpenAnimation = 'slide-up';
|
||||
} else if (menuMode === 'inline') {
|
||||
menuOpenAnimation = animation;
|
||||
} else {
|
||||
// When mode switch from inline
|
||||
// submenu should hide without animation
|
||||
menuOpenAnimation = this.state.switchingModeFromInline ? '' : 'zoom-big';
|
||||
}
|
||||
}
|
||||
return menuOpenAnimation;
|
||||
}
|
||||
|
||||
// Restore vertical mode when menu is collapsed responsively when mounted
|
||||
// https://github.com/ant-design/ant-design/issues/13104
|
||||
// TODO: not a perfect solution, looking a new way to avoid setting switchingModeFromInline in this situation
|
||||
@ -229,50 +260,15 @@ class InternalMenu extends React.Component<InternalMenuProps, MenuState> {
|
||||
}
|
||||
};
|
||||
|
||||
setOpenKeys(openKeys: string[]) {
|
||||
if (!('openKeys' in this.props)) {
|
||||
this.setState({ openKeys });
|
||||
restoreModeVerticalFromInline() {
|
||||
const { switchingModeFromInline } = this.state;
|
||||
if (switchingModeFromInline) {
|
||||
this.setState({
|
||||
switchingModeFromInline: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getRealMenuMode() {
|
||||
const inlineCollapsed = this.getInlineCollapsed();
|
||||
if (this.state.switchingModeFromInline && inlineCollapsed) {
|
||||
return 'inline';
|
||||
}
|
||||
const { mode } = this.props;
|
||||
return inlineCollapsed ? 'vertical' : mode;
|
||||
}
|
||||
|
||||
getInlineCollapsed() {
|
||||
const { inlineCollapsed } = this.props;
|
||||
if (this.props.siderCollapsed !== undefined) {
|
||||
return this.props.siderCollapsed;
|
||||
}
|
||||
return inlineCollapsed;
|
||||
}
|
||||
|
||||
getMenuOpenAnimation(menuMode: MenuMode) {
|
||||
const { openAnimation, openTransitionName } = this.props;
|
||||
let menuOpenAnimation = openAnimation || openTransitionName;
|
||||
if (openAnimation === undefined && openTransitionName === undefined) {
|
||||
if (menuMode === 'horizontal') {
|
||||
menuOpenAnimation = 'slide-up';
|
||||
} else if (menuMode === 'inline') {
|
||||
menuOpenAnimation = animation;
|
||||
} else {
|
||||
// When mode switch from inline
|
||||
// submenu should hide without animation
|
||||
if (this.state.switchingModeFromInline) {
|
||||
menuOpenAnimation = '';
|
||||
} else {
|
||||
menuOpenAnimation = 'zoom-big';
|
||||
}
|
||||
}
|
||||
}
|
||||
return menuOpenAnimation;
|
||||
}
|
||||
|
||||
renderMenu = ({ getPopupContainer, getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { mounted } = this.state;
|
||||
const { prefixCls: customizePrefixCls, className, theme, collapsedWidth } = this.props;
|
||||
@ -339,8 +335,11 @@ polyfill(InternalMenu);
|
||||
// We should keep this as ref-able
|
||||
export default class Menu extends React.Component<MenuProps, {}> {
|
||||
static Divider = Divider;
|
||||
|
||||
static Item = Item;
|
||||
|
||||
static SubMenu = SubMenu;
|
||||
|
||||
static ItemGroup = ItemGroup;
|
||||
|
||||
render() {
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* global Promise */
|
||||
import * as React from 'react';
|
||||
import Notification from 'rc-notification';
|
||||
import Icon from '../icon';
|
||||
@ -78,6 +77,7 @@ function notice(args: ArgsProps): MessageType {
|
||||
const iconNode = (
|
||||
<Icon type={iconType} theme={iconType === 'loading' ? 'outlined' : 'filled'} />
|
||||
);
|
||||
const switchIconNode = iconType ? iconNode : '';
|
||||
instance.notice({
|
||||
key: target,
|
||||
duration,
|
||||
@ -88,7 +88,7 @@ function notice(args: ArgsProps): MessageType {
|
||||
args.type ? ` ${prefixCls}-${args.type}` : ''
|
||||
}`}
|
||||
>
|
||||
{args.icon ? args.icon : iconType ? iconNode : ''}
|
||||
{args.icon ? args.icon : switchIconNode}
|
||||
<span>{args.content}</span>
|
||||
</div>
|
||||
),
|
||||
@ -159,7 +159,7 @@ const api: any = {
|
||||
onClose = duration;
|
||||
duration = undefined;
|
||||
}
|
||||
return api.open({ content, duration: duration, type, onClose });
|
||||
return api.open({ content, duration, type, onClose });
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -71,7 +71,7 @@ export default class ActionButton extends React.Component<ActionButtonProps, Act
|
||||
|
||||
render() {
|
||||
const { type, children, buttonProps } = this.props;
|
||||
const loading = this.state.loading;
|
||||
const { loading } = this.state;
|
||||
return (
|
||||
<Button type={type} onClick={this.onClick} loading={loading} {...buttonProps}>
|
||||
{children}
|
||||
|
@ -31,34 +31,34 @@ if (typeof window !== 'undefined' && window.document && window.document.document
|
||||
}
|
||||
|
||||
export interface ModalProps {
|
||||
/** 对话框是否可见*/
|
||||
/** 对话框是否可见 */
|
||||
visible?: boolean;
|
||||
/** 确定按钮 loading*/
|
||||
/** 确定按钮 loading */
|
||||
confirmLoading?: boolean;
|
||||
/** 标题*/
|
||||
/** 标题 */
|
||||
title?: React.ReactNode | string;
|
||||
/** 是否显示右上角的关闭按钮*/
|
||||
/** 是否显示右上角的关闭按钮 */
|
||||
closable?: boolean;
|
||||
/** 点击确定回调*/
|
||||
/** 点击确定回调 */
|
||||
onOk?: (e: React.MouseEvent<HTMLElement>) => void;
|
||||
/** 点击模态框右上角叉、取消按钮、Props.maskClosable 值为 true 时的遮罩层或键盘按下 Esc 时的回调*/
|
||||
/** 点击模态框右上角叉、取消按钮、Props.maskClosable 值为 true 时的遮罩层或键盘按下 Esc 时的回调 */
|
||||
onCancel?: (e: React.MouseEvent<HTMLElement>) => void;
|
||||
afterClose?: () => void;
|
||||
/** 垂直居中 */
|
||||
centered?: boolean;
|
||||
/** 宽度*/
|
||||
/** 宽度 */
|
||||
width?: string | number;
|
||||
/** 底部内容*/
|
||||
/** 底部内容 */
|
||||
footer?: React.ReactNode;
|
||||
/** 确认按钮文字*/
|
||||
/** 确认按钮文字 */
|
||||
okText?: React.ReactNode;
|
||||
/** 确认按钮类型*/
|
||||
/** 确认按钮类型 */
|
||||
okType?: ButtonType;
|
||||
/** 取消按钮文字*/
|
||||
/** 取消按钮文字 */
|
||||
cancelText?: React.ReactNode;
|
||||
/** 点击蒙层是否允许关闭*/
|
||||
/** 点击蒙层是否允许关闭 */
|
||||
maskClosable?: boolean;
|
||||
/** 强制渲染 Modal*/
|
||||
/** 强制渲染 Modal */
|
||||
forceRender?: boolean;
|
||||
okButtonProps?: NativeButtonProps;
|
||||
cancelButtonProps?: NativeButtonProps;
|
||||
@ -129,11 +129,17 @@ export interface ModalLocale {
|
||||
|
||||
export default class Modal extends React.Component<ModalProps, {}> {
|
||||
static info: ModalFunc;
|
||||
|
||||
static success: ModalFunc;
|
||||
|
||||
static error: ModalFunc;
|
||||
|
||||
static warn: ModalFunc;
|
||||
|
||||
static warning: ModalFunc;
|
||||
|
||||
static confirm: ModalFunc;
|
||||
|
||||
static destroyAll: () => void;
|
||||
|
||||
static defaultProps = {
|
||||
@ -161,14 +167,14 @@ export default class Modal extends React.Component<ModalProps, {}> {
|
||||
};
|
||||
|
||||
handleCancel = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const onCancel = this.props.onCancel;
|
||||
const { onCancel } = this.props;
|
||||
if (onCancel) {
|
||||
onCancel(e);
|
||||
}
|
||||
};
|
||||
|
||||
handleOk = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const onOk = this.props.onOk;
|
||||
const { onOk } = this.props;
|
||||
if (onOk) {
|
||||
onOk(e);
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
prefixCls={prefixCls}
|
||||
className={classString}
|
||||
wrapClassName={classNames({ [`${contentPrefixCls}-centered`]: !!props.centered })}
|
||||
onCancel={close.bind(this, { triggerCancel: true })}
|
||||
onCancel={() => close({ triggerCancel: true })}
|
||||
visible={visible}
|
||||
title=""
|
||||
transitionName={transitionName}
|
||||
@ -123,8 +123,32 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
export default function confirm(config: ModalFuncProps) {
|
||||
const div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
let currentConfig = { ...config, close, visible: true } as any;
|
||||
|
||||
function destroy(...args: any[]) {
|
||||
const unmountResult = ReactDOM.unmountComponentAtNode(div);
|
||||
if (unmountResult && div.parentNode) {
|
||||
div.parentNode.removeChild(div);
|
||||
}
|
||||
const triggerCancel = args.some(param => param && param.triggerCancel);
|
||||
if (config.onCancel && triggerCancel) {
|
||||
config.onCancel(...args);
|
||||
}
|
||||
for (let i = 0; i < destroyFns.length; i++) {
|
||||
const fn = destroyFns[i];
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
if (fn === close) {
|
||||
destroyFns.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function render(props: any) {
|
||||
ReactDOM.render(<ConfirmDialog {...props} getContainer={false} />, div);
|
||||
}
|
||||
|
||||
function close(...args: any[]) {
|
||||
currentConfig = {
|
||||
...currentConfig,
|
||||
@ -146,28 +170,6 @@ export default function confirm(config: ModalFuncProps) {
|
||||
render(currentConfig);
|
||||
}
|
||||
|
||||
function destroy(...args: any[]) {
|
||||
const unmountResult = ReactDOM.unmountComponentAtNode(div);
|
||||
if (unmountResult && div.parentNode) {
|
||||
div.parentNode.removeChild(div);
|
||||
}
|
||||
const triggerCancel = args.some(param => param && param.triggerCancel);
|
||||
if (config.onCancel && triggerCancel) {
|
||||
config.onCancel(...args);
|
||||
}
|
||||
for (let i = 0; i < destroyFns.length; i++) {
|
||||
const fn = destroyFns[i];
|
||||
if (fn === close) {
|
||||
destroyFns.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function render(props: any) {
|
||||
ReactDOM.render(<ConfirmDialog {...props} getContainer={false}/>, div);
|
||||
}
|
||||
|
||||
render(currentConfig);
|
||||
|
||||
destroyFns.push(close);
|
||||
|
@ -6,6 +6,16 @@ import Icon from '../icon';
|
||||
export { ActionButtonProps } from './ActionButton';
|
||||
export { ModalProps, ModalFuncProps } from './Modal';
|
||||
|
||||
function modalWarn(props: ModalFuncProps) {
|
||||
const config = {
|
||||
type: 'warning',
|
||||
icon: <Icon type="exclamation-circle" />,
|
||||
okCancel: false,
|
||||
...props,
|
||||
};
|
||||
return confirm(config);
|
||||
}
|
||||
|
||||
Modal.info = function(props: ModalFuncProps) {
|
||||
const config = {
|
||||
type: 'info',
|
||||
@ -36,15 +46,9 @@ Modal.error = function(props: ModalFuncProps) {
|
||||
return confirm(config);
|
||||
};
|
||||
|
||||
Modal.warning = Modal.warn = function(props: ModalFuncProps) {
|
||||
const config = {
|
||||
type: 'warning',
|
||||
icon: <Icon type="exclamation-circle" />,
|
||||
okCancel: false,
|
||||
...props,
|
||||
};
|
||||
return confirm(config);
|
||||
};
|
||||
Modal.warning = modalWarn;
|
||||
|
||||
Modal.warn = modalWarn;
|
||||
|
||||
Modal.confirm = function(props: ModalFuncProps) {
|
||||
const config = {
|
||||
|
@ -108,7 +108,7 @@ function getNotificationInstance(
|
||||
className: `${prefixCls}-${placement}`,
|
||||
style: getPlacementStyle(placement, top, bottom),
|
||||
getContainer,
|
||||
closeIcon: <Icon className={`${prefixCls}-close-icon`} type={'close'} />,
|
||||
closeIcon: <Icon className={`${prefixCls}-close-icon`} type="close" />,
|
||||
},
|
||||
(notification: any) => {
|
||||
notificationInstance[cacheKey] = notification;
|
||||
|
@ -44,7 +44,8 @@ class Popconfirm extends React.Component<PopconfirmProps, PopconfirmState> {
|
||||
static getDerivedStateFromProps(nextProps: PopconfirmProps) {
|
||||
if ('visible' in nextProps) {
|
||||
return { visible: nextProps.visible };
|
||||
} else if ('defaultVisible' in nextProps) {
|
||||
}
|
||||
if ('defaultVisible' in nextProps) {
|
||||
return { visible: nextProps.defaultVisible };
|
||||
}
|
||||
return null;
|
||||
@ -91,7 +92,7 @@ class Popconfirm extends React.Component<PopconfirmProps, PopconfirmState> {
|
||||
};
|
||||
|
||||
setVisible(visible: boolean, e?: React.MouseEvent<HTMLButtonElement>) {
|
||||
const props = this.props;
|
||||
const { props } = this;
|
||||
if (!('visible' in props)) {
|
||||
this.setState({ visible });
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ interface LineProps extends ProgressProps {
|
||||
*/
|
||||
export const sortGradient = (gradients: ProgressGradient) => {
|
||||
let tempArr = [];
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const [key, value] of Object.entries(gradients)) {
|
||||
const formatKey = parseFloat(key.replace(/%/g, ''));
|
||||
if (isNaN(formatKey)) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import * as PropTypes from 'prop-types';
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import Icon from '../icon';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import { tuple } from '../_util/type';
|
||||
@ -98,26 +99,8 @@ export default class Progress extends React.Component<ProgressProps> {
|
||||
}
|
||||
|
||||
renderProgress = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const props = this.props;
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
className,
|
||||
percent = 0,
|
||||
status,
|
||||
format,
|
||||
trailColor,
|
||||
size,
|
||||
successPercent,
|
||||
type,
|
||||
strokeWidth,
|
||||
width,
|
||||
showInfo,
|
||||
gapDegree = 0,
|
||||
gapPosition,
|
||||
strokeColor,
|
||||
strokeLinecap = 'round',
|
||||
...restProps
|
||||
} = props;
|
||||
const { props } = this;
|
||||
const { prefixCls: customizePrefixCls, className, size, type, showInfo, ...restProps } = props;
|
||||
const prefixCls = getPrefixCls('progress', customizePrefixCls);
|
||||
const progressStatus = this.getProgressStatus();
|
||||
const progressInfo = this.renderProcessInfo(prefixCls, progressStatus);
|
||||
@ -149,7 +132,22 @@ export default class Progress extends React.Component<ProgressProps> {
|
||||
);
|
||||
|
||||
return (
|
||||
<div {...restProps} className={classString}>
|
||||
<div
|
||||
{...omit(restProps, [
|
||||
'status',
|
||||
'format',
|
||||
'trailColor',
|
||||
'successPercent',
|
||||
'strokeWidth',
|
||||
'width',
|
||||
'gapDegree',
|
||||
'gapPosition',
|
||||
'strokeColor',
|
||||
'strokeLinecap',
|
||||
'percent',
|
||||
])}
|
||||
className={classString}
|
||||
>
|
||||
{progress}
|
||||
</div>
|
||||
);
|
||||
|
@ -34,10 +34,10 @@
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
background-color: @progress-remaining-color;
|
||||
border-radius: @progress-radius;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&-circle-trail {
|
||||
|
@ -38,14 +38,14 @@ class RadioGroup extends React.Component<RadioGroupProps, RadioGroupState> {
|
||||
return {
|
||||
value: nextProps.value,
|
||||
};
|
||||
} else {
|
||||
const checkedValue = getCheckedValue(nextProps.children);
|
||||
if (checkedValue) {
|
||||
return {
|
||||
value: checkedValue.value,
|
||||
};
|
||||
}
|
||||
}
|
||||
const checkedValue = getCheckedValue(nextProps.children);
|
||||
if (checkedValue) {
|
||||
return {
|
||||
value: checkedValue.value,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -89,14 +89,14 @@ class RadioGroup extends React.Component<RadioGroupProps, RadioGroupState> {
|
||||
});
|
||||
}
|
||||
|
||||
const onChange = this.props.onChange;
|
||||
const { onChange } = this.props;
|
||||
if (onChange && value !== lastValue) {
|
||||
onChange(ev);
|
||||
}
|
||||
};
|
||||
|
||||
renderGroup = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const props = this.props;
|
||||
const { props } = this;
|
||||
const { prefixCls: customizePrefixCls, className = '', options, buttonStyle } = props;
|
||||
const prefixCls = getPrefixCls('radio', customizePrefixCls);
|
||||
const groupPrefixCls = `${prefixCls}-group`;
|
||||
@ -109,17 +109,16 @@ class RadioGroup extends React.Component<RadioGroupProps, RadioGroupState> {
|
||||
className,
|
||||
);
|
||||
|
||||
let children: React.ReactChildren[] | React.ReactElement<any>[] | React.ReactNode =
|
||||
props.children;
|
||||
let { children } = props;
|
||||
|
||||
// 如果存在 options, 优先使用
|
||||
if (options && options.length > 0) {
|
||||
children = options.map((option, index) => {
|
||||
children = options.map(option => {
|
||||
if (typeof option === 'string') {
|
||||
// 此处类型自动推导为 string
|
||||
return (
|
||||
<Radio
|
||||
key={index}
|
||||
key={option}
|
||||
prefixCls={prefixCls}
|
||||
disabled={this.props.disabled}
|
||||
value={option}
|
||||
@ -128,20 +127,19 @@ class RadioGroup extends React.Component<RadioGroupProps, RadioGroupState> {
|
||||
{option}
|
||||
</Radio>
|
||||
);
|
||||
} else {
|
||||
// 此处类型自动推导为 { label: string value: string }
|
||||
return (
|
||||
<Radio
|
||||
key={index}
|
||||
prefixCls={prefixCls}
|
||||
disabled={option.disabled || this.props.disabled}
|
||||
value={option.value}
|
||||
checked={this.state.value === option.value}
|
||||
>
|
||||
{option.label}
|
||||
</Radio>
|
||||
);
|
||||
}
|
||||
// 此处类型自动推导为 { label: string value: string }
|
||||
return (
|
||||
<Radio
|
||||
key={`radio-group-value-options-${option.value}`}
|
||||
prefixCls={prefixCls}
|
||||
disabled={option.disabled || this.props.disabled}
|
||||
value={option.value}
|
||||
checked={this.state.value === option.value}
|
||||
>
|
||||
{option.label}
|
||||
</Radio>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
|
||||
export default class Radio extends React.Component<RadioProps, {}> {
|
||||
static Group: typeof RadioGroup;
|
||||
|
||||
static Button: typeof RadioButton;
|
||||
|
||||
static defaultProps = {
|
||||
@ -32,14 +33,6 @@ export default class Radio extends React.Component<RadioProps, {}> {
|
||||
);
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.rcCheckbox.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.rcCheckbox.blur();
|
||||
}
|
||||
|
||||
saveCheckbox = (node: any) => {
|
||||
this.rcCheckbox = node;
|
||||
};
|
||||
@ -54,6 +47,14 @@ export default class Radio extends React.Component<RadioProps, {}> {
|
||||
}
|
||||
};
|
||||
|
||||
focus() {
|
||||
this.rcCheckbox.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.rcCheckbox.blur();
|
||||
}
|
||||
|
||||
renderRadio = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { props, context } = this;
|
||||
const { prefixCls: customizePrefixCls, className, children, style, ...restProps } = props;
|
||||
@ -73,6 +74,7 @@ export default class Radio extends React.Component<RadioProps, {}> {
|
||||
});
|
||||
|
||||
return (
|
||||
// eslint-disable-next-line jsx-a11y/label-has-associated-control
|
||||
<label
|
||||
className={wrapperClassString}
|
||||
style={style}
|
||||
|
@ -38,14 +38,6 @@ export default class Rate extends React.Component<RateProps, any> {
|
||||
|
||||
private rcRate: any;
|
||||
|
||||
focus() {
|
||||
this.rcRate.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.rcRate.blur();
|
||||
}
|
||||
|
||||
saveRate = (node: any) => {
|
||||
this.rcRate = node;
|
||||
};
|
||||
@ -57,6 +49,14 @@ export default class Rate extends React.Component<RateProps, any> {
|
||||
return <Tooltip title={tooltips[index]}>{node}</Tooltip>;
|
||||
};
|
||||
|
||||
focus() {
|
||||
this.rcRate.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.rcRate.blur();
|
||||
}
|
||||
|
||||
renderRate = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
const { prefixCls, ...restProps } = this.props;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export default () => (
|
||||
const NoFound = () => (
|
||||
<svg width="252" height="294">
|
||||
<defs>
|
||||
<path d="M0 .387h251.772v251.772H0z" />
|
||||
@ -282,3 +282,5 @@ export default () => (
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default NoFound;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export default () => (
|
||||
const ServerError = () => (
|
||||
<svg width="254" height="294">
|
||||
<defs>
|
||||
<path d="M0 .335h253.49v253.49H0z" />
|
||||
@ -327,3 +327,5 @@ export default () => (
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default ServerError;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export default () => (
|
||||
const Unauthorized = () => (
|
||||
<svg width="251" height="294">
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<path
|
||||
@ -276,3 +276,5 @@ export default () => (
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default Unauthorized;
|
||||
|
@ -2,8 +2,8 @@ import * as React from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import RcSelect, { Option, OptGroup } from 'rc-select';
|
||||
import classNames from 'classnames';
|
||||
import { ConfigConsumer, ConfigConsumerProps, RenderEmptyHandler } from '../config-provider';
|
||||
import omit from 'omit.js';
|
||||
import { ConfigConsumer, ConfigConsumerProps, RenderEmptyHandler } from '../config-provider';
|
||||
import warning from '../_util/warning';
|
||||
import Icon from '../icon';
|
||||
import { tuple } from '../_util/type';
|
||||
@ -57,10 +57,7 @@ export interface SelectProps<T = SelectValue> extends AbstractSelectProps {
|
||||
mode?: 'default' | 'multiple' | 'tags' | 'combobox' | string;
|
||||
optionLabelProp?: string;
|
||||
firstActiveValue?: string | string[];
|
||||
onChange?: (
|
||||
value: T,
|
||||
option: React.ReactElement<any> | React.ReactElement<any>[],
|
||||
) => void;
|
||||
onChange?: (value: T, option: React.ReactElement<any> | React.ReactElement<any>[]) => void;
|
||||
onSelect?: (value: T extends (infer I)[] ? I : T, option: React.ReactElement<any>) => void;
|
||||
onDeselect?: (value: T extends (infer I)[] ? I : T) => void;
|
||||
onBlur?: (value: T) => void;
|
||||
@ -117,6 +114,7 @@ const SelectPropTypes = {
|
||||
|
||||
export default class Select<T = SelectValue> extends React.Component<SelectProps<T>, {}> {
|
||||
static Option = Option as React.ClassicComponentClass<OptionProps>;
|
||||
|
||||
static OptGroup = OptGroup as React.ClassicComponentClass<OptGroupProps>;
|
||||
|
||||
static SECRET_COMBOBOX_MODE_DO_NOT_USE = 'SECRET_COMBOBOX_MODE_DO_NOT_USE';
|
||||
@ -143,18 +141,6 @@ export default class Select<T = SelectValue> extends React.Component<SelectProps
|
||||
);
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.rcSelect.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.rcSelect.blur();
|
||||
}
|
||||
|
||||
saveSelect = (node: any) => {
|
||||
this.rcSelect = node;
|
||||
};
|
||||
|
||||
getNotFoundContent(renderEmpty: RenderEmptyHandler) {
|
||||
const { notFoundContent } = this.props;
|
||||
if (notFoundContent !== undefined) {
|
||||
@ -176,6 +162,18 @@ export default class Select<T = SelectValue> extends React.Component<SelectProps
|
||||
// // return notFoundContent === undefined ? locale.notFoundContent : notFoundContent;
|
||||
}
|
||||
|
||||
saveSelect = (node: any) => {
|
||||
this.rcSelect = node;
|
||||
};
|
||||
|
||||
focus() {
|
||||
this.rcSelect.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.rcSelect.blur();
|
||||
}
|
||||
|
||||
isCombobox() {
|
||||
const { mode } = this.props;
|
||||
return mode === 'combobox' || mode === Select.SECRET_COMBOBOX_MODE_DO_NOT_USE;
|
||||
|
@ -9,6 +9,7 @@ export interface SkeletonAvatarProps {
|
||||
shape?: 'circle' | 'square';
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/prefer-stateless-function
|
||||
class SkeletonAvatar extends React.Component<SkeletonAvatarProps, any> {
|
||||
static defaultProps: Partial<SkeletonAvatarProps> = {
|
||||
size: 'large',
|
||||
|
@ -27,6 +27,7 @@ class Paragraph extends React.Component<SkeletonParagraphProps, {}> {
|
||||
render() {
|
||||
const { prefixCls, className, style, rows } = this.props;
|
||||
const rowList = [...Array(rows)].map((_, index) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<li key={index} style={{ width: this.getWidth(index) }} />
|
||||
));
|
||||
return (
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable jsx-a11y/heading-has-content */
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
@ -8,12 +9,8 @@ export interface SkeletonTitleProps {
|
||||
width?: number | string;
|
||||
}
|
||||
|
||||
class Title extends React.Component<SkeletonTitleProps, any> {
|
||||
render() {
|
||||
const { prefixCls, className, width, style } = this.props;
|
||||
|
||||
return <h3 className={classNames(prefixCls, className)} style={{ width, ...style }} />;
|
||||
}
|
||||
}
|
||||
const Title = ({ prefixCls, className, width, style }: SkeletonTitleProps) => (
|
||||
<h3 className={classNames(prefixCls, className)} style={{ width, ...style }} />
|
||||
);
|
||||
|
||||
export default Title;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user