@chayns-components/core
Version:
A set of beautiful React components for developing your own applications with chayns.
282 lines • 10.4 kB
JavaScript
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