UNPKG

@wix/design-system

Version:

@wix/design-system

144 lines 6.95 kB
import React, { forwardRef, useImperativeHandle, useMemo, useEffect, } from 'react'; import PropTypes from 'prop-types'; import { AddItemLarge, AddItemMedium, AddItemSmall, AddMedia, } from '@wix/wix-ui-icons-common/system'; import { Add } from '@wix/wix-ui-icons-common'; import { useFocusRing } from '../providers/useFocusRing/useFocusRing'; import { useId } from '../utils/useId'; import Tooltip from '../Tooltip'; import Text from '../Text'; import Image from '../Image'; import { dataHooks } from './constants'; import { st, classes } from './AddItem.st.css.js'; import deprecationLog from '../utils/deprecationLog'; const AddItemButtonIcons = { tiny: ({ className }) => (React.createElement(Add, { "data-hook": dataHooks.defaultIcon, className: className, width: "24", height: "24" })), small: () => React.createElement(AddItemSmall, { "data-hook": dataHooks.defaultIcon }), medium: () => React.createElement(AddItemMedium, { "data-hook": dataHooks.defaultIcon }), large: () => React.createElement(AddItemLarge, { "data-hook": dataHooks.defaultIcon }), image: ({ className }) => (React.createElement(AddMedia, { "data-hook": dataHooks.defaultIcon, className: className, width: "31", height: "31" })), }; const illustrationDimensions = { tiny: { height: 24, width: 24 }, small: { height: 60, width: 60 }, medium: { height: 120, width: 120 }, large: { height: 120, width: 120 }, }; const tooltipPlacementByAlignment = { left: 'top-start', right: 'top-end', center: 'top', }; const AddItem = forwardRef(({ theme = 'dashes', // TODO: add default skin size = 'tiny', alignItems = 'center', removePadding = false, borderRadius, disabled, className, onClick, ariaLabel, icon, children, subtitle, dataHook, tooltipProps, tooltipContent, showIcon = true, ...props }, ref) => { const skin = props.skin || theme; const buttonRef = React.useRef(null); useEffect(() => { if (theme) { deprecationLog('<AddItem/> - prop "theme" is deprecated and will be removed in next major release, please use "skin" property instead.'); } }, [theme]); useImperativeHandle(ref, () => ({ focus: () => { buttonRef.current?.focus(); }, blur: () => { buttonRef.current?.blur(); }, })); const iconElement = useMemo(() => { if (!showIcon) { return; } if (!icon) { const isImageIcon = skin === 'image'; const Icon = AddItemButtonIcons[isImageIcon ? 'image' : size]; return React.createElement(Icon, { className: classes.icon }); } if (typeof icon === 'string') { return (React.createElement(Image, { className: classes.illustration, fit: "contain", src: icon, ...illustrationDimensions[size] })); } return icon; }, [icon, size, skin, showIcon]); const textElement = useMemo(() => { if (!children || skin === 'image') { return; } const textSize = size === 'tiny' ? 'small' : 'medium'; return (React.createElement("div", { className: st(classes.textWrapper, { size }) }, typeof children === 'function' ? (children()) : (React.createElement(Text, { className: classes.textContent, weight: "thin", skin: "standard", size: textSize, dataHook: dataHooks.itemText, ellipsis: true }, children)))); }, [children, size, skin]); const subtitleElement = useMemo(() => { return (subtitle && (React.createElement(Text, { className: st(classes.subtitle, { size }), size: "small", dataHook: dataHooks.itemSubtitle }, subtitle))); }, [subtitle, size]); const commonButtonProps = { className, onClick, disabled, skin, size, ariaLabel, borderRadius, removePadding, alignItems, icon: iconElement, text: textElement, subtitle: subtitleElement, }; // TODO: remove this once we deprecate content usage thhrough tooltip // @ts-expect-error const tooltip = tooltipContent || tooltipProps?.content; const tooltipId = useId('additem-tooltip_'); return (React.createElement("div", { style: { width: '100%', height: '100%' }, "data-hook": dataHook }, tooltip && (React.createElement(Tooltip, { content: tooltip, className: classes.tooltip, flip: skin === 'image', moveBy: { y: skin === 'image' ? -12 : 0 }, dataHook: dataHooks.itemTooltip, placement: tooltipPlacementByAlignment[alignItems], "aria-describedby": tooltipId, ...tooltipProps }, ({ onFocus, onBlur }) => (React.createElement(AddItemButton, { ref: buttonRef, ariaDescribedBy: tooltipId, ...commonButtonProps, onFocus: onFocus, onBlur: onBlur })))), !tooltip && React.createElement(AddItemButton, { ref: buttonRef, ...commonButtonProps }))); }); const AddItemButton = forwardRef(({ className, onClick, disabled, size, ariaLabel, borderRadius, alignItems = 'center', newColorsBranding, removePadding, skin, icon, text, subtitle, ariaDescribedBy, onFocus, onBlur, }, ref) => { const { isFocusVisible, focusProps } = useFocusRing(); return (React.createElement("button", { ref: ref, "data-hook": dataHooks.addItem, className: st(classes.root, { skin, size, removePadding, borderRadius, disabled, alignItems, newColorsBranding, 'focus-visible': isFocusVisible, }, className), style: { borderRadius }, disabled: disabled, type: "button", onClick: onClick, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, ...focusProps, onFocus: e => { focusProps.onFocus?.(e); onFocus?.(e); }, onBlur: e => { focusProps.onBlur?.(e); onBlur?.(e); } }, React.createElement("div", { className: st(classes.contentContainer, { skin, size, alignItems, disabled, }) }, React.createElement("div", { className: st(classes.content, { size }) }, icon, text), subtitle))); }); AddItem.displayName = 'AddItem'; AddItem.propTypes = { children: PropTypes.any, disabled: PropTypes.bool, skin: PropTypes.oneOf(['dashes', 'plain', 'filled', 'image']), theme: PropTypes.oneOf(['dashes', 'plain', 'filled', 'image']), alignItems: PropTypes.oneOf(['center', 'right', 'left']), size: PropTypes.oneOf(['large', 'medium', 'small', 'tiny']), onClick: PropTypes.func, dataHook: PropTypes.string, className: PropTypes.string, tooltipContent: PropTypes.any, tooltipProps: PropTypes.object, showIcon: PropTypes.bool, removePadding: PropTypes.bool, borderRadius: PropTypes.string, ariaLabel: PropTypes.string, subtitle: PropTypes.any, icon: PropTypes.any, }; export default AddItem; //# sourceMappingURL=AddItem.js.map