1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/open-hand-choerodon-ui

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Это зеркальный репозиторий, синхронизируется ежедневно с исходного репозитория.
Клонировать/Скачать
Button.tsx 9.4 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
HughHzWu Отправлено 3 лет назад abbabfc
import React, {
AnchorHTMLAttributes,
ButtonHTMLAttributes,
Children,
cloneElement,
MouseEventHandler,
PureComponent,
ReactElement,
ReactNode,
} from 'react';
import { findDOMNode } from 'react-dom';
import classNames from 'classnames';
import omit from 'lodash/omit';
import noop from 'lodash/noop';
import isNil from 'lodash/isNil';
import isString from 'lodash/isString';
import getReactNodeText from 'choerodon-ui/pro/lib/_util/getReactNodeText';
import { ButtonTooltip } from 'choerodon-ui/pro/lib/button/enum';
import isOverflow from 'choerodon-ui/pro/lib/overflow-tip/util';
import { hide, show } from 'choerodon-ui/pro/lib/tooltip/singleton';
import Icon from '../icon';
import Group from './ButtonGroup';
import Ripple from '../ripple';
import { Size } from '../_util/enum';
import { ProgressType } from '../progress/enum';
import Progress from '../progress';
import ConfigContext, { ConfigContextValue } from '../config-provider/ConfigContext';
const rxTwoCNChar = /^[\u4e00-\u9fa5]{2}$/;
const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar);
// Insert one space between two chinese characters automatically.
function insertSpace(child: React.ReactChild, needInserted: boolean) {
// Check the child if is undefined or null.
if (isNil(child)) {
return;
}
const SPACE = needInserted ? ' ' : '';
// strictNullChecks oops.
if (typeof child !== 'string' && typeof child !== 'number' &&
isString(child.type) && isTwoCNChar(child.props.children)) {
return cloneElement(child, {},
child.props.children.split('').join(SPACE));
}
if (typeof child === 'string') {
if (isTwoCNChar(child)) {
child = child.split('').join(SPACE);
}
return <span>{child}</span>;
}
return child;
}
function defaultRenderIcon(type: string) {
return <Icon type={type} />;
}
export type ButtonType = 'default' | 'primary' | 'ghost' | 'dashed' | 'danger';
export type ButtonShape = 'circle' | 'circle-outline';
export type ButtonFuncType = 'raised' | 'flat';
export type ButtonHTMLType = 'submit' | 'button' | 'reset';
export interface BaseButtonProps {
type?: ButtonType;
htmlType?: string;
icon?: string;
shape?: ButtonShape;
size?: Size;
onClick?: MouseEventHandler<HTMLElement>;
loading?: boolean | { delay?: number };
prefixCls?: string;
className?: string;
ghost?: boolean;
twoCNChar?: boolean;
rippleDisabled?: boolean;
funcType?: ButtonFuncType;
children?: ReactNode;
renderIcon?: (type: string) => ReactElement;
}
export type AnchorButtonProps = {
href: string;
target?: string;
} & BaseButtonProps &
Omit<AnchorHTMLAttributes<any>, 'type' | 'onClick'>;
export type NativeButtonProps = {
htmlType?: ButtonHTMLType;
} & BaseButtonProps &
Omit<ButtonHTMLAttributes<any>, 'type' | 'onClick'>;
export type ButtonProps = Partial<AnchorButtonProps & NativeButtonProps>;
export default class Button extends PureComponent<ButtonProps, any> {
static displayName = 'Button';
static get contextType(): typeof ConfigContext {
return ConfigContext;
}
static Group: typeof Group;
static __C7N_BUTTON = true;
static defaultProps = {
loading: false,
ghost: false,
funcType: 'flat',
};
context: ConfigContextValue;
timeout: number;
delayTimeout: number;
element: HTMLButtonElement | null;
isTooltipShown?: boolean;
saveRef = (element) => {
this.element = element;
};
constructor(props: ButtonProps) {
super(props);
this.state = {
loading: props.loading,
clicked: false,
hasTwoCNChar: false,
};
}
componentDidMount() {
this.fixTwoCNChar();
}
componentWillReceiveProps(nextProps: ButtonProps) {
const { loading: currentLoading } = this.props;
const { loading } = nextProps;
if (currentLoading) {
clearTimeout(this.delayTimeout);
}
if (typeof loading !== 'boolean' && loading && loading.delay) {
this.delayTimeout = window.setTimeout(() => this.setState({ loading }), loading.delay);
} else {
this.setState({ loading });
}
}
componentDidUpdate() {
this.fixTwoCNChar();
}
componentWillUnmount() {
if (this.timeout) {
clearTimeout(this.timeout);
}
if (this.delayTimeout) {
clearTimeout(this.delayTimeout);
}
}
fixTwoCNChar() {
const { twoCNChar } = this.props;
if (twoCNChar) {
// Fix for HOC usage like <FormatMessage />
const node = (findDOMNode(this) as HTMLElement);
const buttonText = node.textContent || node.innerText;
const { hasTwoCNChar } = this.state;
if (this.isNeedInserted() && isTwoCNChar(buttonText)) {
if (!hasTwoCNChar) {
this.setState({
hasTwoCNChar: true,
});
}
} else if (hasTwoCNChar) {
this.setState({
hasTwoCNChar: false,
});
}
}
}
handleClick: MouseEventHandler<HTMLButtonElement | HTMLAnchorElement> = e => {
// Add click effect
this.setState({ clicked: true });
clearTimeout(this.timeout);
this.timeout = window.setTimeout(() => this.setState({ clicked: false }), 500);
const { getConfig } = this.context;
const onButtonClick = getConfig('onButtonClick');
if (onButtonClick) {
const { target } = e;
const { children, icon } = this.props;
const promise = Promise.resolve(target && (target as HTMLButtonElement | HTMLAnchorElement).textContent || getReactNodeText(children));
promise.then(title => onButtonClick({ icon, title }));
}
const { onClick } = this.props;
if (onClick) {
onClick(e);
}
};
handleMouseEnter: MouseEventHandler<HTMLButtonElement | HTMLAnchorElement> = (e) => {
const { getTooltip, getTooltipTheme, getTooltipPlacement } = this.context;
const { children } = this.props;
const tooltip = getTooltip('button');
const { element } = this;
if (element && (tooltip === ButtonTooltip.always || (tooltip === ButtonTooltip.overflow && isOverflow(element)))) {
show(element, {
title: children,
theme: getTooltipTheme('button'),
placement: getTooltipPlacement('button'),
});
this.isTooltipShown = true;
}
const { onMouseEnter = noop } = this.props;
onMouseEnter(e);
};
handleMouseLeave: MouseEventHandler<HTMLButtonElement | HTMLAnchorElement> = (e) => {
hide();
const { onMouseLeave = noop } = this.props;
onMouseLeave(e);
};
isNeedInserted() {
const { icon, children } = this.props;
return Children.count(children) === 1 && !icon;
}
render() {
const {
prefixCls: customizePrefixCls,
type,
shape,
size,
className,
htmlType,
children,
icon,
ghost,
funcType,
disabled,
rippleDisabled,
renderIcon = defaultRenderIcon,
...others
} = this.props;
const { loading, clicked, hasTwoCNChar } = this.state;
const { getPrefixCls, getTooltip } = this.context;
const prefixCls = getPrefixCls('btn', customizePrefixCls);
const tooltip = getTooltip('button');
if (tooltip && [ButtonTooltip.always, ButtonTooltip.overflow].includes(tooltip)) {
others.onMouseEnter = this.handleMouseEnter;
others.onMouseLeave = this.handleMouseLeave;
}
// large => lg
// small => sm
let sizeCls = '';
switch (size) {
case Size.large:
sizeCls = 'lg';
break;
case Size.small:
sizeCls = 'sm';
break;
default:
}
const ComponentProp = others.href ? 'a' : 'button';
const classes = classNames(prefixCls, className, {
[`${prefixCls}-${type}`]: type,
[`${prefixCls}-${shape}`]: shape,
[`${prefixCls}-${sizeCls}`]: sizeCls,
[`${prefixCls}-icon-only`]: !children && icon,
[`${prefixCls}-loading`]: loading,
[`${prefixCls}-clicked`]: clicked,
[`${prefixCls}-background-ghost`]: ghost,
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar,
[`${prefixCls}-${funcType}`]: funcType,
});
const iconNode = loading ? (
<Progress key="loading" type={ProgressType.loading} size={Size.small} />
) : icon ? renderIcon(icon) : null;
const kids =
children || children === 0
? Children.map(children, (child: any) => insertSpace(child, this.isNeedInserted())) : null;
const { style, onMouseEnter, onMouseLeave, ...otherProps } = others;
const useWrapper = disabled && ComponentProp === 'button' && (onMouseEnter || onMouseLeave);
const button = (
<Ripple disabled={rippleDisabled || disabled}>
<ComponentProp
disabled={disabled}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
{...omit(otherProps, ['loading', 'twoCNChar'])}
// 如果没有href属性,则表示组件使用button标签,type为'submit' | 'reset' | 'button'
type={
others.href ? undefined : (htmlType as ButtonHTMLAttributes<any>['type']) || 'button'
}
style={useWrapper ? undefined : style}
className={useWrapper ? undefined : classes}
onClick={loading ? undefined : this.handleClick}
ref={this.saveRef}
>
{iconNode}{kids}
</ComponentProp>
</Ripple>
);
return useWrapper ? (
<span
// @ts-ignore
disabled
style={style}
className={classNames(classes, `${prefixCls}-disabled-wrapper`)}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
{button}
</span>
) : button;
}
}

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/open-hand-choerodon-ui.git
git@gitlife.ru:oschina-mirror/open-hand-choerodon-ui.git
oschina-mirror
open-hand-choerodon-ui
open-hand-choerodon-ui
master