UNPKG

@syncfusion/react-buttons

Version:

Syncfusion React Buttons package is a feature-rich collection of UI components including Button, CheckBox, RadioButton, Switch, Chip, and more for building modern, interactive React applications.

124 lines (123 loc) 6.3 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { forwardRef, useImperativeHandle, useLayoutEffect, useRef, useState } from 'react'; import { preRender, useProviderContext, SvgIcon, useRippleEffect } from '@syncfusion/react-base'; import * as React from 'react'; /** * The Chip component represents information in a compact form, such as entity attribute, text, or action. * * ```typescript * import { Chip } from "@syncfusion/react-buttons"; * * <Chip color="Primary" removable={true}>Anne</Chip> * ``` */ export const Chip = React.memo(forwardRef((props, ref) => { const { value, text, avatar, leadingIcon, trailingIcon, className, disabled = false, leadingIconUrl, trailingIconUrl, children, removable, variant = 'Filled', color, onDelete, onClick, ...otherProps } = props; const publicAPI = { value, text, avatar, leadingIcon, trailingIcon, disabled, leadingIconUrl, trailingIconUrl, removable, variant, color }; const chipRef = useRef(null); const [isFocused, setIsFocused] = useState(false); const { dir, ripple } = useProviderContext(); const closeIcon = 'M10.5858 12.0001L2.58575 4.00003L3.99997 2.58582L12 10.5858L20 2.58582L21.4142 4.00003L13.4142 12.0001L21.4142 20L20 21.4142L12 13.4143L4.00003 21.4142L2.58581 20L10.5858 12.0001Z'; const selectIcon = 'M21.4142 6L9.00003 18.4142L2.58582 12L4.00003 10.5858L9.00003 15.5858L20 4.58578L21.4142 6Z'; const IconClasses = 'sf-content-center sf-overflow-hidden'; const { rippleMouseDown, Ripple } = useRippleEffect(ripple); useLayoutEffect(() => { preRender('chip'); }, []); useImperativeHandle(ref, () => ({ ...publicAPI, element: chipRef.current })); const handleDelete = React.useCallback((e) => { if (!removable) { return; } e.stopPropagation(); const eventArgs = { event: e, data: props }; if (onDelete) { onDelete(eventArgs); } }, [onDelete, text, props]); const handleSpanDelete = React.useCallback((e) => { if (removable) { handleDelete(e); } }, [removable, handleDelete]); const handleClick = React.useCallback((e) => { if (onClick) { onClick(e); } }, [onClick, text, props]); const handleKeyDown = React.useCallback((e) => { switch (e.key) { case 'Enter': case ' ': e.preventDefault(); handleClick(e); break; case 'Delete': case 'Backspace': if (removable) { e.preventDefault(); handleDelete(e); } break; } }, [removable, handleClick, handleDelete]); const handleFocus = React.useCallback(() => { setIsFocused(true); }, []); const handleBlur = React.useCallback(() => { setIsFocused(false); }, []); const chipClassName = React.useMemo(() => { if (className?.includes('sf-chip')) { return className; } return [ 'sf-chip sf-control sf-chip-list', className, disabled ? `sf-disabled sf-chip-${color ? 'variant' : 'invariant'}-disabled` : '', dir === 'rtl' ? 'sf-rtl' : '', avatar ? 'sf-chip-avatar-wrap' : leadingIcon ? 'sf-chip-icon-wrap' : '', isFocused ? 'sf-focused' : '', variant === 'Outlined' ? 'sf-outline' : '', color ? `sf-${color.toLowerCase()}` : '', avatar || leadingIcon || leadingIconUrl ? 'sf-chip-has-icon' : '' ].filter(Boolean).join(' '); }, [className, disabled, dir, avatar, leadingIcon, isFocused, variant, color]); const avatarClasses = React.useMemo(() => { return [ 'sf-chip-avatar', IconClasses, typeof avatar === 'string' ? avatar : '' ].filter(Boolean).join(' '); }, [avatar]); const trailingIconClasses = React.useMemo(() => { return [ trailingIconUrl && !removable ? 'sf-chip-trailing-url' : 'sf-chip-delete', IconClasses, removable ? 'sf-dlt-btn' : (typeof trailingIcon === 'string' ? trailingIcon : '') ].filter(Boolean).join(' '); }, [trailingIconUrl, removable, trailingIcon]); return (_jsxs("div", { ref: chipRef, className: chipClassName, tabIndex: disabled ? -1 : 0, role: "button", "aria-disabled": disabled ? 'true' : 'false', "aria-label": text ? text : undefined, "data-value": value ? value.toString() : undefined, onClick: handleClick, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown, onMouseDown: rippleMouseDown, ...otherProps, children: [chipClassName.includes('sf-selectable') && (_jsx("span", { className: 'sf-chip-selectable-icon sf-content-center', children: _jsx(SvgIcon, { d: selectIcon }) })), (avatar) && (_jsx("span", { className: avatarClasses, children: typeof avatar !== 'string' && avatar })), (leadingIcon && !avatar) && (typeof leadingIcon === 'string' ? _jsx("span", { className: `sf-chip-icon ${leadingIcon} ${IconClasses}` }) : _jsx("span", { className: `sf-chip-icon ${IconClasses}`, children: leadingIcon })), (leadingIconUrl && !leadingIcon && !avatar) && (_jsx("span", { className: `sf-chip-avatar sf-chip-image ${IconClasses}`, children: leadingIconUrl && (_jsx("img", { className: 'sf-chip-leading-image', src: leadingIconUrl, alt: "leading image" })) })), children ? (_jsx("div", { className: "sf-chip-template sf-display-inline-flex", children: children })) : text ? (_jsx("span", { className: "sf-chip-text sf-ellipsis", children: text })) : null, (trailingIcon || trailingIconUrl || removable) && (_jsxs("span", { className: trailingIconClasses, onClick: handleSpanDelete, children: [removable && (_jsx(SvgIcon, { d: closeIcon })), !removable && typeof trailingIcon !== 'string' && trailingIcon, !removable && trailingIconUrl && (_jsx("img", { className: 'sf-chip-trailing-image', src: trailingIconUrl, alt: "trailing image" }))] })), ripple && _jsx(Ripple, {})] })); })); export default Chip;