UNPKG

9.77 kBJavaScriptView Raw
1import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
2import _extends from 'babel-runtime/helpers/extends';
3import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
4import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
5import _inherits from 'babel-runtime/helpers/inherits';
6
7var _class, _temp;
8
9import React, { Component } from 'react';
10import PropTypes from 'prop-types';
11import classNames from 'classnames';
12import Animate from '../animate';
13import Icon from '../icon';
14import { func, KEYCODE, obj, support } from '../util';
15import zhCN from '../locale/zh-cn';
16import ConfigProvider from '../config-provider';
17
18var noop = func.noop,
19 bindCtx = func.bindCtx;
20
21
22var PRESET_COLOR_REG = /blue|green|orange|red|turquoise|yellow/;
23
24/**
25 * Tag
26 */
27var Tag = (_temp = _class = function (_Component) {
28 _inherits(Tag, _Component);
29
30 function Tag(props) {
31 _classCallCheck(this, Tag);
32
33 var _this = _possibleConstructorReturn(this, _Component.call(this, props));
34
35 _this.onKeyDown = function (e) {
36 // 针对无障碍化要求 添加键盘SPACE事件
37 var _this$props = _this.props,
38 closable = _this$props.closable,
39 closeArea = _this$props.closeArea,
40 onClick = _this$props.onClick,
41 disabled = _this$props.disabled;
42
43 if (e.keyCode !== KEYCODE.SPACE || disabled) {
44 return;
45 }
46
47 e.preventDefault();
48 e.stopPropagation();
49
50 if (closable) {
51 _this.handleClose(closeArea);
52 } else {
53 typeof onClick === 'function' && onClick(e);
54 }
55 };
56
57 _this.state = {
58 visible: true
59 };
60
61 bindCtx(_this, ['handleBodyClick', 'handleTailClick', 'handleAnimationInit', 'handleAnimationEnd', 'renderTailNode']);
62 return _this;
63 }
64
65 Tag.prototype.componentWillUnmount = function componentWillUnmount() {
66 this.__destroyed = true;
67 };
68
69 Tag.prototype.handleClose = function handleClose(from) {
70 var _this2 = this;
71
72 var _props = this.props,
73 animation = _props.animation,
74 onClose = _props.onClose;
75
76 var hasAnimation = support.animation && animation;
77
78 // 先执行回调
79 var result = onClose(from, this.tagNode);
80
81 // 如果回调函数返回 false,则阻止关闭行为
82 if (result !== false && !this.__destroyed) {
83 this.setState({
84 visible: false
85 }, function () {
86 // 如果没有动画,则直接执行 afterClose
87 !hasAnimation && _this2.props.afterClose(_this2.tagNode);
88 });
89 }
90 };
91
92 // 标签体点击
93
94
95 Tag.prototype.handleBodyClick = function handleBodyClick(e) {
96 var _props2 = this.props,
97 closable = _props2.closable,
98 closeArea = _props2.closeArea,
99 onClick = _props2.onClick;
100
101 var node = e.currentTarget;
102
103 if (node && (node === e.target || node.contains(e.target))) {
104 if (closable && closeArea === 'tag') {
105 this.handleClose('tag');
106 }
107
108 if (typeof onClick === 'function') {
109 return onClick(e);
110 }
111 }
112 };
113
114 Tag.prototype.handleTailClick = function handleTailClick(e) {
115 e && e.preventDefault();
116 e && e.stopPropagation();
117
118 this.handleClose('tail');
119 };
120
121 Tag.prototype.handleAnimationInit = function handleAnimationInit(node) {
122 this.props.afterAppear(node);
123 };
124
125 Tag.prototype.handleAnimationEnd = function handleAnimationEnd(node) {
126 this.props.afterClose(node);
127 };
128
129 Tag.prototype.renderAnimatedTag = function renderAnimatedTag(children, animationName) {
130 return React.createElement(
131 Animate,
132 {
133 animation: animationName,
134 afterAppear: this.handleAnimationInit,
135 afterLeave: this.handleAnimationEnd
136 },
137 children
138 );
139 };
140
141 Tag.prototype.renderTailNode = function renderTailNode() {
142 var _props3 = this.props,
143 prefix = _props3.prefix,
144 closable = _props3.closable,
145 locale = _props3.locale;
146
147
148 if (!closable) {
149 return null;
150 }
151
152 return React.createElement(
153 'span',
154 {
155 className: prefix + 'tag-close-btn',
156 onClick: this.handleTailClick,
157 role: 'button',
158 'aria-label': locale.delete
159 },
160 React.createElement(Icon, { type: 'close' })
161 );
162 };
163
164 Tag.prototype.isPresetColor = function isPresetColor() {
165 var color = this.props.color;
166
167
168 if (!color) {
169 return false;
170 }
171
172 return PRESET_COLOR_REG.test(color);
173 };
174
175 Tag.prototype.getTagStyle = function getTagStyle() {
176 var _props4 = this.props,
177 _props4$color = _props4.color,
178 color = _props4$color === undefined ? '' : _props4$color,
179 style = _props4.style;
180
181 var isPresetColor = this.isPresetColor();
182 var customColorStyle = {
183 backgroundColor: color,
184 borderColor: color,
185 color: '#fff'
186 };
187
188 return _extends({}, color && !isPresetColor ? customColorStyle : null, style);
189 };
190
191 Tag.prototype.render = function render() {
192 var _classNames,
193 _this3 = this;
194
195 var _props5 = this.props,
196 prefix = _props5.prefix,
197 type = _props5.type,
198 size = _props5.size,
199 color = _props5.color,
200 _shape = _props5._shape,
201 closable = _props5.closable,
202 closeArea = _props5.closeArea,
203 className = _props5.className,
204 children = _props5.children,
205 animation = _props5.animation,
206 disabled = _props5.disabled,
207 rtl = _props5.rtl;
208 var visible = this.state.visible;
209
210 var isPresetColor = this.isPresetColor();
211 var others = obj.pickOthers(Tag.propTypes, this.props);
212 // eslint-disable-next-line no-unused-vars
213
214 var style = others.style,
215 otherTagProps = _objectWithoutProperties(others, ['style']);
216
217 var shape = closable ? 'closable' : _shape;
218 var bodyClazz = classNames([prefix + 'tag', prefix + 'tag-' + shape, prefix + 'tag-' + size], (_classNames = {}, _classNames[prefix + 'tag-level-' + type] = !color, _classNames[prefix + 'tag-closable'] = closable, _classNames[prefix + 'tag-body-pointer'] = closable && closeArea === 'tag', _classNames[prefix + 'tag-' + color] = color && isPresetColor && type === 'primary', _classNames[prefix + 'tag-' + color + '-inverse'] = color && isPresetColor && type === 'normal', _classNames), className);
219
220 // close btn
221 var tailNode = this.renderTailNode();
222 // tag node
223 var tagNode = !visible ? null : React.createElement(
224 'div',
225 _extends({
226 className: bodyClazz,
227 onClick: this.handleBodyClick,
228 onKeyDown: this.onKeyDown,
229 tabIndex: disabled ? '' : '0',
230 role: 'button',
231 'aria-disabled': disabled,
232 disabled: disabled,
233 dir: rtl ? 'rtl' : undefined,
234 ref: function ref(n) {
235 return _this3.tagNode = n;
236 },
237 style: this.getTagStyle()
238 }, otherTagProps),
239 React.createElement(
240 'span',
241 { className: prefix + 'tag-body' },
242 children
243 ),
244 tailNode
245 );
246
247 if (animation && support.animation) {
248 return this.renderAnimatedTag(tagNode, prefix + 'tag-zoom');
249 }
250
251 // 未开启或不支持动画
252 return tagNode;
253 };
254
255 return Tag;
256}(Component), _class.propTypes = {
257 /**
258 * 标签类名前缀,提供给二次开发者用
259 * @default next-
260 */
261 prefix: PropTypes.string,
262 /**
263 * 标签的类型
264 * @enumdesc 普通, 主要
265 */
266 type: PropTypes.oneOf(['normal', 'primary']),
267 /**
268 * 标签的尺寸(large 尺寸为兼容表单场景 large = medium)
269 * @enumdesc 小, 中, 大
270 */
271 size: PropTypes.oneOf(['small', 'medium', 'large']),
272
273 /**
274 * 标签颜色, 目前支持:blue、 green、 orange、red、 turquoise、 yellow 和 hex 颜色值 (`color keywords`作为 Tag 组件的保留字,请勿直接使用 ), `1.19.0` 以上版本生效
275 */
276 color: PropTypes.string,
277 /**
278 * 是否开启动效
279 */
280 animation: PropTypes.bool,
281 closeArea: PropTypes.oneOf(['tag', 'tail']),
282 closable: PropTypes.bool,
283 onClose: PropTypes.func,
284 afterClose: PropTypes.func,
285 /**
286 * 标签出现动画结束后执行的回调
287 */
288 afterAppear: PropTypes.func,
289 className: PropTypes.any,
290 children: PropTypes.node,
291 /**
292 * 点击回调
293 */
294 onClick: PropTypes.func,
295 _shape: PropTypes.oneOf(['default', 'closable', 'checkable']),
296 disabled: PropTypes.bool,
297 rtl: PropTypes.bool,
298 locale: PropTypes.object
299}, _class.defaultProps = {
300 prefix: 'next-',
301 type: 'normal',
302 size: 'medium',
303 closeArea: 'tail',
304 animation: false,
305 onClose: noop,
306 afterClose: noop,
307 afterAppear: noop,
308 onClick: noop,
309 _shape: 'default',
310 disabled: false,
311 rtl: false,
312 locale: zhCN.Tag
313}, _temp);
314Tag.displayName = 'Tag';
315
316
317export default ConfigProvider.config(Tag);
\No newline at end of file