@coreui/react
Version:
UI Components Library for React.js
177 lines (174 loc) • 8.29 kB
JavaScript
import { __rest } from '../../node_modules/tslib/tslib.es6.js';
import React, { forwardRef, useRef, useState, useEffect, useMemo } from 'react';
import PropTypes from 'prop-types';
import classNames from '../../_virtual/index.js';
import { useForkedRef } from '../../hooks/useForkedRef.js';
import '@popperjs/core';
import { colorPropType } from '../../props.js';
const SELECTOR_FOCUSABLE_ITEMS = '[data-coreui-chip-focusable="true"]:not(.disabled)';
const CChip = forwardRef((_a, ref) => {
var { active, ariaRemoveLabel = 'Remove', children, as: Component = 'span', className, clickable, color, disabled, onClick, onDeselect, onKeyDown, onRemove, onSelect, onSelectedChange, removable, removeIcon, selectable, selected, size, tabIndex, variant } = _a, rest = __rest(_a, ["active", "ariaRemoveLabel", "children", "as", "className", "clickable", "color", "disabled", "onClick", "onDeselect", "onKeyDown", "onRemove", "onSelect", "onSelectedChange", "removable", "removeIcon", "selectable", "selected", "size", "tabIndex", "variant"]);
const chipRef = useRef(null);
const forkedRef = useForkedRef(ref, chipRef);
const isSelectedControlled = selected !== undefined;
const [_selected, setSelected] = useState(Boolean(selected));
const selectedState = isSelectedControlled ? Boolean(selected) : _selected;
useEffect(() => {
if (isSelectedControlled) {
setSelected(Boolean(selected));
}
}, [isSelectedControlled, selected]);
const isFocusable = useMemo(() => Boolean(!disabled && (selectable || removable)), [disabled, selectable, removable]);
const getFocusableSibling = (shouldGetNext) => {
var _a;
const currentElement = chipRef.current;
if (!(currentElement === null || currentElement === void 0 ? void 0 : currentElement.parentElement)) {
return null;
}
const chips = Array.from(currentElement.parentElement.querySelectorAll(SELECTOR_FOCUSABLE_ITEMS));
const index = chips.indexOf(currentElement);
if (index === -1 || chips.length <= 1) {
return null;
}
const targetIndex = shouldGetNext ? index + 1 : index - 1;
return (_a = chips[targetIndex]) !== null && _a !== void 0 ? _a : null;
};
const navigateToEdge = (targetIndex) => {
const currentElement = chipRef.current;
if (!(currentElement === null || currentElement === void 0 ? void 0 : currentElement.parentElement)) {
return;
}
const chips = Array.from(currentElement.parentElement.querySelectorAll(SELECTOR_FOCUSABLE_ITEMS));
const edgeChip = targetIndex === -1 ? chips[chips.length - 1] : chips[0];
edgeChip === null || edgeChip === void 0 ? void 0 : edgeChip.focus();
};
const setSelectableState = (nextSelected, event) => {
if (!selectable || disabled || nextSelected === selectedState) {
return;
}
if (!isSelectedControlled) {
setSelected(nextSelected);
}
if (nextSelected) {
onSelect === null || onSelect === void 0 ? void 0 : onSelect(event);
}
else {
onDeselect === null || onDeselect === void 0 ? void 0 : onDeselect(event);
}
onSelectedChange === null || onSelectedChange === void 0 ? void 0 : onSelectedChange(nextSelected, event);
};
const toggleSelectedState = (event) => {
setSelectableState(!selectedState, event);
};
const handleRemove = (event) => {
onRemove === null || onRemove === void 0 ? void 0 : onRemove(event);
};
const handleRemoveClick = (event) => {
event.stopPropagation();
handleRemove(event);
};
const handleClick = (event) => {
if (disabled) {
return;
}
if (event.target.closest('.chip-remove')) {
return;
}
if (selectable) {
toggleSelectedState(event);
}
onClick === null || onClick === void 0 ? void 0 : onClick(event);
};
const handleKeyDown = (event) => {
if (disabled) {
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
return;
}
switch (event.key) {
case 'Enter':
case ' ':
case 'Spacebar': {
if (selectable) {
event.preventDefault();
toggleSelectedState(event);
}
break;
}
case 'Backspace':
case 'Delete': {
if (removable) {
event.preventDefault();
const sibling = getFocusableSibling(false) || getFocusableSibling(true);
sibling === null || sibling === void 0 ? void 0 : sibling.focus();
handleRemove(event);
}
break;
}
case 'ArrowLeft': {
event.preventDefault();
const sibling = getFocusableSibling(false);
sibling === null || sibling === void 0 ? void 0 : sibling.focus();
if (selectedState && event.shiftKey) {
sibling === null || sibling === void 0 ? void 0 : sibling.dispatchEvent(new CustomEvent('coreui-chip-select'));
}
break;
}
case 'ArrowRight': {
event.preventDefault();
const sibling = getFocusableSibling(true);
sibling === null || sibling === void 0 ? void 0 : sibling.focus();
if (selectedState && event.shiftKey) {
sibling === null || sibling === void 0 ? void 0 : sibling.dispatchEvent(new CustomEvent('coreui-chip-select'));
}
break;
}
case 'Home': {
event.preventDefault();
navigateToEdge(0);
break;
}
case 'End': {
event.preventDefault();
navigateToEdge(-1);
break;
}
// No default
}
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
};
return (React.createElement(Component, Object.assign({ className: classNames('chip', {
active: selectable ? selectedState : active,
disabled,
[`chip-${color}`]: color,
[`chip-${size}`]: size,
'chip-clickable': clickable || selectable || Boolean(onClick),
'chip-outline': variant === 'outline',
}, className), "data-coreui-chip-focusable": isFocusable || undefined }, (disabled && { 'aria-disabled': true }), (selectable && { 'aria-selected': selectedState }), (isFocusable && tabIndex === undefined && { tabIndex: 0 }), { onClick: handleClick, onKeyDown: handleKeyDown }, (Component === 'button' && { disabled }), rest, { ref: forkedRef }),
children,
removable && (React.createElement("button", { type: "button", className: "chip-remove", "aria-label": ariaRemoveLabel, onClick: handleRemoveClick, tabIndex: -1, disabled: disabled }, removeIcon !== null && removeIcon !== void 0 ? removeIcon : (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" },
React.createElement("line", { x1: "4", y1: "4", x2: "12", y2: "12" }),
React.createElement("line", { x1: "12", y1: "4", x2: "4", y2: "12" })))))));
});
CChip.propTypes = {
active: PropTypes.bool,
ariaRemoveLabel: PropTypes.string,
as: PropTypes.elementType,
children: PropTypes.node,
className: PropTypes.string,
clickable: PropTypes.bool,
color: colorPropType,
disabled: PropTypes.bool,
onDeselect: PropTypes.func,
onRemove: PropTypes.func,
onSelect: PropTypes.func,
onSelectedChange: PropTypes.func,
removable: PropTypes.bool,
removeIcon: PropTypes.node,
selectable: PropTypes.bool,
selected: PropTypes.bool,
size: PropTypes.oneOf(['sm', 'lg']),
variant: PropTypes.oneOf(['outline']),
};
CChip.displayName = 'CChip';
export { CChip };
//# sourceMappingURL=CChip.js.map