1 | import _extends from "@babel/runtime/helpers/esm/extends";
|
2 | import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
3 | import * as React from 'react';
|
4 | import PropTypes from 'prop-types';
|
5 | import clsx from 'clsx';
|
6 | import CancelIcon from '../internal/svg-icons/Cancel';
|
7 | import withStyles from '../styles/withStyles';
|
8 | import { emphasize, alpha } from '../styles/colorManipulator';
|
9 | import useForkRef from '../utils/useForkRef';
|
10 | import unsupportedProp from '../utils/unsupportedProp';
|
11 | import capitalize from '../utils/capitalize';
|
12 | import ButtonBase from '../ButtonBase';
|
13 | export const styles = theme => {
|
14 | const backgroundColor = theme.palette.type === 'light' ? theme.palette.grey[300] : theme.palette.grey[700];
|
15 | const deleteIconColor = alpha(theme.palette.text.primary, 0.26);
|
16 | return {
|
17 |
|
18 | root: {
|
19 | fontFamily: theme.typography.fontFamily,
|
20 | fontSize: theme.typography.pxToRem(13),
|
21 | display: 'inline-flex',
|
22 | alignItems: 'center',
|
23 | justifyContent: 'center',
|
24 | height: 32,
|
25 | color: theme.palette.getContrastText(backgroundColor),
|
26 | backgroundColor,
|
27 | borderRadius: 32 / 2,
|
28 | whiteSpace: 'nowrap',
|
29 | transition: theme.transitions.create(['background-color', 'box-shadow']),
|
30 |
|
31 | cursor: 'default',
|
32 |
|
33 | outline: 0,
|
34 | textDecoration: 'none',
|
35 | border: 'none',
|
36 |
|
37 | padding: 0,
|
38 |
|
39 | verticalAlign: 'middle',
|
40 | boxSizing: 'border-box',
|
41 | '&$disabled': {
|
42 | opacity: 0.5,
|
43 | pointerEvents: 'none'
|
44 | },
|
45 | '& $avatar': {
|
46 | marginLeft: 5,
|
47 | marginRight: -6,
|
48 | width: 24,
|
49 | height: 24,
|
50 | color: theme.palette.type === 'light' ? theme.palette.grey[700] : theme.palette.grey[300],
|
51 | fontSize: theme.typography.pxToRem(12)
|
52 | },
|
53 | '& $avatarColorPrimary': {
|
54 | color: theme.palette.primary.contrastText,
|
55 | backgroundColor: theme.palette.primary.dark
|
56 | },
|
57 | '& $avatarColorSecondary': {
|
58 | color: theme.palette.secondary.contrastText,
|
59 | backgroundColor: theme.palette.secondary.dark
|
60 | },
|
61 | '& $avatarSmall': {
|
62 | marginLeft: 4,
|
63 | marginRight: -4,
|
64 | width: 18,
|
65 | height: 18,
|
66 | fontSize: theme.typography.pxToRem(10)
|
67 | }
|
68 | },
|
69 |
|
70 |
|
71 | sizeSmall: {
|
72 | height: 24
|
73 | },
|
74 |
|
75 |
|
76 | colorPrimary: {
|
77 | backgroundColor: theme.palette.primary.main,
|
78 | color: theme.palette.primary.contrastText
|
79 | },
|
80 |
|
81 |
|
82 | colorSecondary: {
|
83 | backgroundColor: theme.palette.secondary.main,
|
84 | color: theme.palette.secondary.contrastText
|
85 | },
|
86 |
|
87 |
|
88 | disabled: {},
|
89 |
|
90 |
|
91 | clickable: {
|
92 | userSelect: 'none',
|
93 | WebkitTapHighlightColor: 'transparent',
|
94 | cursor: 'pointer',
|
95 | '&:hover, &:focus': {
|
96 | backgroundColor: emphasize(backgroundColor, 0.08)
|
97 | },
|
98 | '&:active': {
|
99 | boxShadow: theme.shadows[1]
|
100 | }
|
101 | },
|
102 |
|
103 |
|
104 | clickableColorPrimary: {
|
105 | '&:hover, &:focus': {
|
106 | backgroundColor: emphasize(theme.palette.primary.main, 0.08)
|
107 | }
|
108 | },
|
109 |
|
110 |
|
111 | clickableColorSecondary: {
|
112 | '&:hover, &:focus': {
|
113 | backgroundColor: emphasize(theme.palette.secondary.main, 0.08)
|
114 | }
|
115 | },
|
116 |
|
117 |
|
118 | deletable: {
|
119 | '&:focus': {
|
120 | backgroundColor: emphasize(backgroundColor, 0.08)
|
121 | }
|
122 | },
|
123 |
|
124 |
|
125 | deletableColorPrimary: {
|
126 | '&:focus': {
|
127 | backgroundColor: emphasize(theme.palette.primary.main, 0.2)
|
128 | }
|
129 | },
|
130 |
|
131 |
|
132 | deletableColorSecondary: {
|
133 | '&:focus': {
|
134 | backgroundColor: emphasize(theme.palette.secondary.main, 0.2)
|
135 | }
|
136 | },
|
137 |
|
138 |
|
139 | outlined: {
|
140 | backgroundColor: 'transparent',
|
141 | border: `1px solid ${theme.palette.type === 'light' ? 'rgba(0, 0, 0, 0.23)' : 'rgba(255, 255, 255, 0.23)'}`,
|
142 | '$clickable&:hover, $clickable&:focus, $deletable&:focus': {
|
143 | backgroundColor: alpha(theme.palette.text.primary, theme.palette.action.hoverOpacity)
|
144 | },
|
145 | '& $avatar': {
|
146 | marginLeft: 4
|
147 | },
|
148 | '& $avatarSmall': {
|
149 | marginLeft: 2
|
150 | },
|
151 | '& $icon': {
|
152 | marginLeft: 4
|
153 | },
|
154 | '& $iconSmall': {
|
155 | marginLeft: 2
|
156 | },
|
157 | '& $deleteIcon': {
|
158 | marginRight: 5
|
159 | },
|
160 | '& $deleteIconSmall': {
|
161 | marginRight: 3
|
162 | }
|
163 | },
|
164 |
|
165 |
|
166 | outlinedPrimary: {
|
167 | color: theme.palette.primary.main,
|
168 | border: `1px solid ${theme.palette.primary.main}`,
|
169 | '$clickable&:hover, $clickable&:focus, $deletable&:focus': {
|
170 | backgroundColor: alpha(theme.palette.primary.main, theme.palette.action.hoverOpacity)
|
171 | }
|
172 | },
|
173 |
|
174 |
|
175 | outlinedSecondary: {
|
176 | color: theme.palette.secondary.main,
|
177 | border: `1px solid ${theme.palette.secondary.main}`,
|
178 | '$clickable&:hover, $clickable&:focus, $deletable&:focus': {
|
179 | backgroundColor: alpha(theme.palette.secondary.main, theme.palette.action.hoverOpacity)
|
180 | }
|
181 | },
|
182 |
|
183 |
|
184 |
|
185 | avatar: {},
|
186 |
|
187 |
|
188 | avatarSmall: {},
|
189 |
|
190 |
|
191 | avatarColorPrimary: {},
|
192 |
|
193 |
|
194 | avatarColorSecondary: {},
|
195 |
|
196 |
|
197 | icon: {
|
198 | color: theme.palette.type === 'light' ? theme.palette.grey[700] : theme.palette.grey[300],
|
199 | marginLeft: 5,
|
200 | marginRight: -6
|
201 | },
|
202 |
|
203 |
|
204 | iconSmall: {
|
205 | width: 18,
|
206 | height: 18,
|
207 | marginLeft: 4,
|
208 | marginRight: -4
|
209 | },
|
210 |
|
211 |
|
212 | iconColorPrimary: {
|
213 | color: 'inherit'
|
214 | },
|
215 |
|
216 |
|
217 | iconColorSecondary: {
|
218 | color: 'inherit'
|
219 | },
|
220 |
|
221 |
|
222 | label: {
|
223 | overflow: 'hidden',
|
224 | textOverflow: 'ellipsis',
|
225 | paddingLeft: 12,
|
226 | paddingRight: 12,
|
227 | whiteSpace: 'nowrap'
|
228 | },
|
229 |
|
230 |
|
231 | labelSmall: {
|
232 | paddingLeft: 8,
|
233 | paddingRight: 8
|
234 | },
|
235 |
|
236 |
|
237 | deleteIcon: {
|
238 | WebkitTapHighlightColor: 'transparent',
|
239 | color: deleteIconColor,
|
240 | height: 22,
|
241 | width: 22,
|
242 | cursor: 'pointer',
|
243 | margin: '0 5px 0 -6px',
|
244 | '&:hover': {
|
245 | color: alpha(deleteIconColor, 0.4)
|
246 | }
|
247 | },
|
248 |
|
249 |
|
250 | deleteIconSmall: {
|
251 | height: 16,
|
252 | width: 16,
|
253 | marginRight: 4,
|
254 | marginLeft: -4
|
255 | },
|
256 |
|
257 |
|
258 | deleteIconColorPrimary: {
|
259 | color: alpha(theme.palette.primary.contrastText, 0.7),
|
260 | '&:hover, &:active': {
|
261 | color: theme.palette.primary.contrastText
|
262 | }
|
263 | },
|
264 |
|
265 |
|
266 | deleteIconColorSecondary: {
|
267 | color: alpha(theme.palette.secondary.contrastText, 0.7),
|
268 | '&:hover, &:active': {
|
269 | color: theme.palette.secondary.contrastText
|
270 | }
|
271 | },
|
272 |
|
273 |
|
274 | deleteIconOutlinedColorPrimary: {
|
275 | color: alpha(theme.palette.primary.main, 0.7),
|
276 | '&:hover, &:active': {
|
277 | color: theme.palette.primary.main
|
278 | }
|
279 | },
|
280 |
|
281 |
|
282 | deleteIconOutlinedColorSecondary: {
|
283 | color: alpha(theme.palette.secondary.main, 0.7),
|
284 | '&:hover, &:active': {
|
285 | color: theme.palette.secondary.main
|
286 | }
|
287 | }
|
288 | };
|
289 | };
|
290 |
|
291 | function isDeleteKeyboardEvent(keyboardEvent) {
|
292 | return keyboardEvent.key === 'Backspace' || keyboardEvent.key === 'Delete';
|
293 | }
|
294 |
|
295 |
|
296 |
|
297 |
|
298 |
|
299 | const Chip = React.forwardRef(function Chip(props, ref) {
|
300 | const {
|
301 | avatar: avatarProp,
|
302 | classes,
|
303 | className,
|
304 | clickable: clickableProp,
|
305 | color = 'default',
|
306 | component: ComponentProp,
|
307 | deleteIcon: deleteIconProp,
|
308 | disabled = false,
|
309 | icon: iconProp,
|
310 | label,
|
311 | onClick,
|
312 | onDelete,
|
313 | onKeyDown,
|
314 | onKeyUp,
|
315 | size = 'medium',
|
316 | variant = 'default'
|
317 | } = props,
|
318 | other = _objectWithoutPropertiesLoose(props, ["avatar", "classes", "className", "clickable", "color", "component", "deleteIcon", "disabled", "icon", "label", "onClick", "onDelete", "onKeyDown", "onKeyUp", "size", "variant"]);
|
319 |
|
320 | const chipRef = React.useRef(null);
|
321 | const handleRef = useForkRef(chipRef, ref);
|
322 |
|
323 | const handleDeleteIconClick = event => {
|
324 |
|
325 | event.stopPropagation();
|
326 |
|
327 | if (onDelete) {
|
328 | onDelete(event);
|
329 | }
|
330 | };
|
331 |
|
332 | const handleKeyDown = event => {
|
333 |
|
334 | if (event.currentTarget === event.target && isDeleteKeyboardEvent(event)) {
|
335 |
|
336 |
|
337 | event.preventDefault();
|
338 | }
|
339 |
|
340 | if (onKeyDown) {
|
341 | onKeyDown(event);
|
342 | }
|
343 | };
|
344 |
|
345 | const handleKeyUp = event => {
|
346 |
|
347 | if (event.currentTarget === event.target) {
|
348 | if (onDelete && isDeleteKeyboardEvent(event)) {
|
349 | onDelete(event);
|
350 | } else if (event.key === 'Escape' && chipRef.current) {
|
351 | chipRef.current.blur();
|
352 | }
|
353 | }
|
354 |
|
355 | if (onKeyUp) {
|
356 | onKeyUp(event);
|
357 | }
|
358 | };
|
359 |
|
360 | const clickable = clickableProp !== false && onClick ? true : clickableProp;
|
361 | const small = size === 'small';
|
362 | const Component = ComponentProp || (clickable ? ButtonBase : 'div');
|
363 | const moreProps = Component === ButtonBase ? {
|
364 | component: 'div'
|
365 | } : {};
|
366 | let deleteIcon = null;
|
367 |
|
368 | if (onDelete) {
|
369 | const customClasses = clsx(color !== 'default' && (variant === "default" ? classes[`deleteIconColor${capitalize(color)}`] : classes[`deleteIconOutlinedColor${capitalize(color)}`]), small && classes.deleteIconSmall);
|
370 | deleteIcon = deleteIconProp && React.isValidElement(deleteIconProp) ? React.cloneElement(deleteIconProp, {
|
371 | className: clsx(deleteIconProp.props.className, classes.deleteIcon, customClasses),
|
372 | onClick: handleDeleteIconClick
|
373 | }) : React.createElement(CancelIcon, {
|
374 | className: clsx(classes.deleteIcon, customClasses),
|
375 | onClick: handleDeleteIconClick
|
376 | });
|
377 | }
|
378 |
|
379 | let avatar = null;
|
380 |
|
381 | if (avatarProp && React.isValidElement(avatarProp)) {
|
382 | avatar = React.cloneElement(avatarProp, {
|
383 | className: clsx(classes.avatar, avatarProp.props.className, small && classes.avatarSmall, color !== 'default' && classes[`avatarColor${capitalize(color)}`])
|
384 | });
|
385 | }
|
386 |
|
387 | let icon = null;
|
388 |
|
389 | if (iconProp && React.isValidElement(iconProp)) {
|
390 | icon = React.cloneElement(iconProp, {
|
391 | className: clsx(classes.icon, iconProp.props.className, small && classes.iconSmall, color !== 'default' && classes[`iconColor${capitalize(color)}`])
|
392 | });
|
393 | }
|
394 |
|
395 | if (process.env.NODE_ENV !== 'production') {
|
396 | if (avatar && icon) {
|
397 | console.error('Material-UI: The Chip component can not handle the avatar ' + 'and the icon prop at the same time. Pick one.');
|
398 | }
|
399 | }
|
400 |
|
401 | return React.createElement(Component, _extends({
|
402 | role: clickable || onDelete ? 'button' : undefined,
|
403 | className: clsx(classes.root, className, color !== 'default' && [classes[`color${capitalize(color)}`], clickable && classes[`clickableColor${capitalize(color)}`], onDelete && classes[`deletableColor${capitalize(color)}`]], variant !== "default" && [classes.outlined, {
|
404 | 'primary': classes.outlinedPrimary,
|
405 | 'secondary': classes.outlinedSecondary
|
406 | }[color]], disabled && classes.disabled, small && classes.sizeSmall, clickable && classes.clickable, onDelete && classes.deletable),
|
407 | "aria-disabled": disabled ? true : undefined,
|
408 | tabIndex: clickable || onDelete ? 0 : undefined,
|
409 | onClick: onClick,
|
410 | onKeyDown: handleKeyDown,
|
411 | onKeyUp: handleKeyUp,
|
412 | ref: handleRef
|
413 | }, moreProps, other), avatar || icon, React.createElement("span", {
|
414 | className: clsx(classes.label, small && classes.labelSmall)
|
415 | }, label), deleteIcon);
|
416 | });
|
417 | process.env.NODE_ENV !== "production" ? Chip.propTypes = {
|
418 |
|
419 |
|
420 |
|
421 |
|
422 |
|
423 | |
424 |
|
425 |
|
426 | avatar: PropTypes.element,
|
427 |
|
428 | |
429 |
|
430 |
|
431 |
|
432 | children: unsupportedProp,
|
433 |
|
434 | |
435 |
|
436 |
|
437 |
|
438 | classes: PropTypes.object,
|
439 |
|
440 | |
441 |
|
442 |
|
443 | className: PropTypes.string,
|
444 |
|
445 | |
446 |
|
447 |
|
448 |
|
449 |
|
450 |
|
451 |
|
452 | clickable: PropTypes.bool,
|
453 |
|
454 | |
455 |
|
456 |
|
457 | color: PropTypes.oneOf(['default', 'primary', 'secondary']),
|
458 |
|
459 | |
460 |
|
461 |
|
462 |
|
463 | component: PropTypes
|
464 |
|
465 | .elementType,
|
466 |
|
467 | |
468 |
|
469 |
|
470 | deleteIcon: PropTypes.element,
|
471 |
|
472 | |
473 |
|
474 |
|
475 | disabled: PropTypes.bool,
|
476 |
|
477 | |
478 |
|
479 |
|
480 | icon: PropTypes.element,
|
481 |
|
482 | |
483 |
|
484 |
|
485 | label: PropTypes.node,
|
486 |
|
487 | |
488 |
|
489 |
|
490 | onClick: PropTypes.func,
|
491 |
|
492 | |
493 |
|
494 |
|
495 |
|
496 | onDelete: PropTypes.func,
|
497 |
|
498 | |
499 |
|
500 |
|
501 | onKeyDown: PropTypes.func,
|
502 |
|
503 | |
504 |
|
505 |
|
506 | onKeyUp: PropTypes.func,
|
507 |
|
508 | |
509 |
|
510 |
|
511 | size: PropTypes.oneOf(['medium', 'small']),
|
512 |
|
513 | |
514 |
|
515 |
|
516 | variant: PropTypes.oneOf(['default', 'outlined'])
|
517 | } : void 0;
|
518 | export default withStyles(styles, {
|
519 | name: 'MuiChip'
|
520 | })(Chip); |
\ | No newline at end of file |