1 | import React from 'react';
|
2 | import PropTypes from 'prop-types';
|
3 | import classNames from 'classnames';
|
4 | import { mapToCssModules, tagPropType } from './utils';
|
5 |
|
6 | const propTypes = {
|
7 | active: PropTypes.bool,
|
8 | 'aria-label': PropTypes.string,
|
9 | block: PropTypes.bool,
|
10 | color: PropTypes.string,
|
11 | disabled: PropTypes.bool,
|
12 | outline: PropTypes.bool,
|
13 | tag: tagPropType,
|
14 | innerRef: PropTypes.oneOfType([PropTypes.object, PropTypes.func, PropTypes.string]),
|
15 | onClick: PropTypes.func,
|
16 | size: PropTypes.string,
|
17 | children: PropTypes.node,
|
18 | className: PropTypes.string,
|
19 | cssModule: PropTypes.object,
|
20 | close: PropTypes.bool,
|
21 | };
|
22 |
|
23 | const defaultProps = {
|
24 | color: 'secondary',
|
25 | tag: 'button',
|
26 | };
|
27 |
|
28 | class Button extends React.Component {
|
29 | constructor(props) {
|
30 | super(props);
|
31 |
|
32 | this.onClick = this.onClick.bind(this);
|
33 | }
|
34 |
|
35 | onClick(e) {
|
36 | if (this.props.disabled) {
|
37 | e.preventDefault();
|
38 | return;
|
39 | }
|
40 |
|
41 | if (this.props.onClick) {
|
42 | this.props.onClick(e);
|
43 | }
|
44 | }
|
45 |
|
46 | render() {
|
47 | let {
|
48 | active,
|
49 | 'aria-label': ariaLabel,
|
50 | block,
|
51 | className,
|
52 | close,
|
53 | cssModule,
|
54 | color,
|
55 | outline,
|
56 | size,
|
57 | tag: Tag,
|
58 | innerRef,
|
59 | ...attributes
|
60 | } = this.props;
|
61 |
|
62 | if (close && typeof attributes.children === 'undefined') {
|
63 | attributes.children = <span aria-hidden>×</span>;
|
64 | }
|
65 |
|
66 | const btnOutlineColor = `btn${outline ? '-outline' : ''}-${color}`;
|
67 |
|
68 | const classes = mapToCssModules(classNames(
|
69 | className,
|
70 | { close },
|
71 | close || 'btn',
|
72 | close || btnOutlineColor,
|
73 | size ? `btn-${size}` : false,
|
74 | block ? 'btn-block' : false,
|
75 | { active, disabled: this.props.disabled }
|
76 | ), cssModule);
|
77 |
|
78 | if (attributes.href && Tag === 'button') {
|
79 | Tag = 'a';
|
80 | }
|
81 |
|
82 | const defaultAriaLabel = close ? 'Close' : null;
|
83 |
|
84 | return (
|
85 | <Tag
|
86 | type={(Tag === 'button' && attributes.onClick) ? 'button' : undefined}
|
87 | {...attributes}
|
88 | className={classes}
|
89 | ref={innerRef}
|
90 | onClick={this.onClick}
|
91 | aria-label={ariaLabel || defaultAriaLabel}
|
92 | />
|
93 | );
|
94 | }
|
95 | }
|
96 |
|
97 | Button.propTypes = propTypes;
|
98 | Button.defaultProps = defaultProps;
|
99 |
|
100 | export default Button;
|