UNPKG

@chayns-components/core

Version:

A set of beautiful React components for developing your own applications with chayns.

282 lines • 10.4 kB
import { AnimatePresence, motion } from 'motion/react'; import React, { forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'; import { useUuid } from '../../../hooks/uuid'; import { AccordionContext } from '../../accordion/Accordion'; import AreaContextProvider, { AreaContext } from '../../area-provider/AreaContextProvider'; import { ListContext } from '../List'; import { handleHorizontalArrowNavigation, handleListItemTabNavigation, handleListItemToggleKey, handleVerticalListGroupNavigation } from '../List.utils'; import ListItemBody from './list-item-body/ListItemBody'; import ListItemHead from './list-item-head/ListItemHead'; import { StyledListItem, StyledListItemTooltip } from './ListItem.styles'; import Tooltip from '../../tooltip/Tooltip'; import { useIsInsideDialog } from '../../../hooks/element'; import { useKeyboardFocusHighlighting } from '../../../hooks/useKeyboardFocusHighlighting'; import { useListItemFocus } from './useListItemFocus'; const ListItem = /*#__PURE__*/forwardRef(({ backgroundColor, careOfLocationId, children, cornerImage, hoverItem, icons, imageBackground, images, isDefaultOpen, isOpen, isTitleGreyed, leftElements, onClick, onClose, onLongPress, onOpen, rightElements, shouldShowTooltipOnTitleOverflow = false, shouldForceBackground = false, shouldForceBottomLine = false, shouldForceHover = false, shouldHideBottomLine = false, shouldOpenImageOnClick = false, shouldHideImageOrIconBackground, shouldHideIndicator = false, shouldPreventLayoutAnimation = false, shouldRenderClosed = false, shouldShowRoundImageOrIcon, shouldShowSeparatorBelow = false, subtitle, title, onImageError, onSizeChange, onTitleInputChange, titleElement, titleInputProps, shouldDisableAnimation = false, cornerElement, isSelected = false, shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlightingProp }, ref) => { const { isAnyItemExpandable, isWrapped, openItemUuid, updateOpenItemUuid, shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlightingContext, listGroupUuid, listItemUuids, registerListItemUuid, unregisterListItemUuid, activeListItemUuid, updateActiveListItemUuid } = useContext(ListContext); const shouldEnableKeyboardHighlighting = shouldEnableKeyboardHighlightingProp ?? shouldEnableKeyboardHighlightingContext; const { isWrapped: isParentAccordionWrapped } = useContext(AccordionContext); const areaProvider = useContext(AreaContext); const isInitialRenderRef = useRef(true); const listItemRef = useRef(null); const isInDialog = useIsInsideDialog(listItemRef); const uuid = useUuid(); const isExpandable = children !== undefined; const isItemOpen = isOpen ?? openItemUuid === uuid; const onCloseRef = useRef(onClose); const onOpenRef = useRef(onOpen); const [shouldEnableTooltip, setShouldEnableTooltip] = useState(false); const [titleWidth, setTitleWidth] = useState(0); const [titleMaxWidth, setTitleMaxWidth] = useState(0); useEffect(() => { onCloseRef.current = onClose; onOpenRef.current = onOpen; }, [isOpen, onClose, onOpen]); useEffect(() => { if (isInitialRenderRef.current) { isInitialRenderRef.current = false; } else if (isItemOpen) { if (typeof onOpenRef.current === 'function') { onOpenRef.current(); } } else if (typeof onCloseRef.current === 'function') { onCloseRef.current(); } }, [isItemOpen]); const handleHeadClick = useCallback(event => { if (isExpandable) { updateOpenItemUuid(uuid); } if (typeof onClick === 'function') { onClick(event); } }, [isExpandable, onClick, updateOpenItemUuid, uuid]); useEffect(() => { if (isDefaultOpen) { updateOpenItemUuid(uuid, { shouldOnlyOpen: true }); } }, [isDefaultOpen, updateOpenItemUuid, uuid]); const isClickable = typeof onClick === 'function' || isExpandable; useEffect(() => { if (typeof onSizeChange === 'function') { onSizeChange({ titleWidth, titleMaxWidth }); } }, [onSizeChange, titleMaxWidth, titleWidth]); useImperativeHandle(ref, () => ({ titleWidth, titleMaxWidth }), [titleMaxWidth, titleWidth]); const handleTitleWidthChange = useCallback((width, maxWidth) => { setTitleWidth(width); setTitleMaxWidth(maxWidth); }, []); const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(shouldEnableKeyboardHighlighting); const isInKeyboardNavigationGroup = shouldEnableKeyboardHighlighting && typeof listGroupUuid === 'string' && typeof updateActiveListItemUuid === 'function'; useEffect(() => { if (shouldEnableKeyboardHighlighting && typeof registerListItemUuid === 'function' && typeof unregisterListItemUuid === 'function') { registerListItemUuid(uuid); return () => { unregisterListItemUuid(uuid); }; } return undefined; }, [shouldEnableKeyboardHighlighting, registerListItemUuid, unregisterListItemUuid, uuid]); const tabIndex = useMemo(() => shouldEnableKeyboardHighlighting ? 0 : -1, [shouldEnableKeyboardHighlighting]); const handleKeyDown = useCallback(event => { const isCurrentListItemTarget = event.currentTarget === event.target; const currentListItemElement = event.currentTarget; const targetElement = event.target; [() => shouldEnableKeyboardHighlighting && handleHorizontalArrowNavigation({ event, currentListItemElement, targetElement, isCurrentListItemTarget }), () => handleListItemTabNavigation({ event, currentListItemElement, targetElement, isCurrentListItemTarget, isInKeyboardNavigationGroup, listItemUuids, currentUuid: uuid, listGroupUuid, updateActiveListItemUuid }), () => handleVerticalListGroupNavigation({ event, isCurrentListItemTarget, isInKeyboardNavigationGroup, listItemUuids, currentUuid: uuid, listGroupUuid, updateActiveListItemUuid }), () => handleListItemToggleKey({ event, isCurrentListItemTarget, isExpandable, isItemOpen, shouldEnableKeyboardHighlighting, toggleItem: () => handleHeadClick(event) })].some(handleKey => handleKey()); }, [handleHeadClick, isExpandable, isInKeyboardNavigationGroup, isItemOpen, listGroupUuid, listItemUuids, shouldEnableKeyboardHighlighting, updateActiveListItemUuid, uuid]); const { isFocusWithinListItem, handleFocus, handleBlur } = useListItemFocus({ uuid, listGroupUuid, isInKeyboardNavigationGroup, updateActiveListItemUuid }); useEffect(() => { if (isInKeyboardNavigationGroup && activeListItemUuid == null && typeof updateActiveListItemUuid === 'function' && listItemUuids?.[0] === uuid) { updateActiveListItemUuid(uuid); } }, [activeListItemUuid, isInKeyboardNavigationGroup, listItemUuids, updateActiveListItemUuid, uuid]); return /*#__PURE__*/React.createElement(StyledListItem, { as: shouldDisableAnimation ? undefined : motion.div, animate: shouldDisableAnimation ? undefined : { height: 'auto', opacity: 1 }, className: "beta-chayns-list-item", exit: shouldDisableAnimation ? undefined : { height: 0, opacity: 0 }, initial: shouldDisableAnimation ? undefined : { height: 0, opacity: 0 }, key: `list-item-${uuid}`, ref: listItemRef, "data-uuid": `${listGroupUuid ?? ''}---${uuid}`, layout: shouldPreventLayoutAnimation || shouldDisableAnimation ? undefined : 'position', $backgroundColor: backgroundColor, $isClickable: isClickable, $isInAccordion: typeof isParentAccordionWrapped === 'boolean' && !areaProvider.shouldDisableListItemPadding, $isOpen: isItemOpen, $isWrapped: isWrapped, $isInDialog: isInDialog, $isSelected: isSelected, $shouldChangeColor: areaProvider.shouldChangeColor, $shouldForceBackground: shouldForceBackground, $shouldForceBottomLine: shouldForceBottomLine, $shouldHideBottomLine: shouldHideBottomLine, $shouldHideIndicator: shouldHideIndicator, $shouldShowSeparatorBelow: shouldShowSeparatorBelow, "data-should-show-keyboard-highlighting": shouldShowKeyboardHighlighting ? 'true' : undefined, tabIndex: tabIndex, onKeyDown: handleKeyDown, onFocus: handleFocus, onBlur: handleBlur }, /*#__PURE__*/React.createElement(Tooltip, { shouldUseFullWidth: true, isDisabled: !shouldShowTooltipOnTitleOverflow || !shouldEnableTooltip, item: /*#__PURE__*/React.createElement(StyledListItemTooltip, { style: { cursor: 'default' }, key: `list-item-tooltip-${uuid}` }, title) }, /*#__PURE__*/React.createElement(ListItemHead, { hoverItem: hoverItem, careOfLocationId: careOfLocationId, cornerElement: cornerElement, cornerImage: cornerImage, icons: icons, imageBackground: imageBackground, images: images, isAnyItemExpandable: isAnyItemExpandable, isExpandable: isExpandable, isOpen: isItemOpen, isTitleGreyed: isTitleGreyed, leftElements: leftElements, onClick: isClickable ? handleHeadClick : undefined, onLongPress: onLongPress, shouldForceHover: shouldForceHover, rightElements: rightElements, shouldHideImageOrIconBackground: shouldHideImageOrIconBackground, shouldHideIndicator: shouldHideIndicator, shouldOpenImageOnClick: shouldOpenImageOnClick, shouldShowRoundImageOrIcon: shouldShowRoundImageOrIcon, subtitle: subtitle, title: title, onTitleInputChange: onTitleInputChange, onTitleWidthChange: handleTitleWidthChange, titleInputProps: titleInputProps, titleElement: titleElement, setShouldEnableTooltip: setShouldEnableTooltip, shouldDisableAnimation: shouldDisableAnimation, onImageError: onImageError })), /*#__PURE__*/React.createElement(AnimatePresence, { initial: false }, isExpandable && (isItemOpen || shouldRenderClosed) && /*#__PURE__*/React.createElement(ListItemBody, { id: uuid, key: `listItemBody-${uuid}`, shouldHideBody: shouldRenderClosed && !isItemOpen }, /*#__PURE__*/React.createElement(AreaContextProvider, null, children)))); }); ListItem.displayName = 'ListItem'; export default ListItem; //# sourceMappingURL=ListItem.js.map