@chayns-components/core
Version:
A set of beautiful React components for developing your own applications with chayns.
192 lines • 6.52 kB
JavaScript
import { AnimatePresence, MotionConfig } from 'motion/react';
import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
import { useUuid } from '../../hooks/uuid';
import { AreaContext } from '../area-provider/AreaContextProvider';
import AccordionBody from './accordion-body/AccordionBody';
import { AccordionGroupContext } from './accordion-group/AccordionGroup';
import AccordionHead from './accordion-head/AccordionHead';
import { AccordionWrappedContext } from './accordion-provider/AccordionContextProvider';
import { StyledMotionAccordion } from './Accordion.styles';
export const AccordionContext = /*#__PURE__*/React.createContext({
isWrapped: undefined
});
const Accordion = _ref => {
let {
bodyMaxHeight,
children,
icon,
isDefaultOpen = false,
isDisabled = false,
isFixed = false,
isOpened,
isTitleGreyed = false,
onBodyScroll,
onClose,
onHoverEnd,
onHoverStart,
onOpen,
onSearchChange,
rightElement,
searchPlaceholder,
searchValue,
shouldForceBackground = false,
shouldHideBackground = false,
shouldRenderClosed = false,
shouldRotateIcon = true,
shouldHideBottomLine = false,
title,
titleElement,
onTitleInputChange,
titleInputProps,
titleColor,
onBodyAnimationComplete
} = _ref;
const {
isWrapped: groupIsWrapped,
openAccordionUuid,
accordionGroupUuid,
accordionUuids,
updateOpenAccordionUuid
} = useContext(AccordionGroupContext);
const {
isWrapped: isParentWrapped
} = useContext(AccordionContext);
const {
isWrapped: contextIsWrapped
} = useContext(AccordionWrappedContext);
const isWrapped = useMemo(() => groupIsWrapped ?? contextIsWrapped, [contextIsWrapped, groupIsWrapped]);
const [isAccordionOpen, setIsAccordionOpen] = useState(isDefaultOpen ?? isOpened);
const uuid = useUuid();
const isInitialRenderRef = useRef(true);
const isInGroup = typeof updateOpenAccordionUuid === 'function';
const isOpen = isInGroup ? openAccordionUuid === uuid : isAccordionOpen;
const isOpenRef = useRef(isOpen);
const onCloseRef = useRef(onClose);
const onOpenRef = useRef(onOpen);
const isLastAccordion = useMemo(() => accordionUuids ? accordionUuids[accordionUuids.length - 1] === uuid : false, [accordionUuids, uuid]);
useEffect(() => {
isOpenRef.current = isOpen;
onCloseRef.current = onClose;
onOpenRef.current = onOpen;
}, [isOpen, onClose, onOpen]);
const handleHeadClick = useCallback(() => {
if (isDisabled) {
return;
}
if (typeof updateOpenAccordionUuid === 'function') {
updateOpenAccordionUuid(uuid);
}
setIsAccordionOpen(currentIsAccordionOpen => !currentIsAccordionOpen);
}, [isDisabled, updateOpenAccordionUuid, uuid]);
useEffect(() => {
if (isDisabled && isOpen) {
if (typeof updateOpenAccordionUuid === 'function') {
updateOpenAccordionUuid(uuid);
}
setIsAccordionOpen(currentIsAccordionOpen => !currentIsAccordionOpen);
}
}, [isDisabled, isOpen, updateOpenAccordionUuid, uuid]);
useEffect(() => {
if (isInitialRenderRef.current) {
isInitialRenderRef.current = false;
} else if (isOpen) {
if (typeof onOpenRef.current === 'function') {
onOpenRef.current();
}
} else if (typeof onCloseRef.current === 'function') {
onCloseRef.current();
}
}, [isOpen]);
useEffect(() => {
if (isDefaultOpen) {
if (typeof updateOpenAccordionUuid === 'function') {
updateOpenAccordionUuid(uuid, {
shouldOnlyOpen: true
});
} else {
setIsAccordionOpen(true);
}
}
}, [isDefaultOpen, updateOpenAccordionUuid, uuid]);
useEffect(() => {
if (typeof isOpened === 'boolean') {
if (typeof updateOpenAccordionUuid === 'function' && isOpened !== isOpenRef.current) {
updateOpenAccordionUuid(uuid);
} else {
setIsAccordionOpen(isOpened);
}
}
}, [isOpened, updateOpenAccordionUuid, uuid]);
const accordionContextProviderValue = useMemo(() => ({
isWrapped: isWrapped === true
}), [isWrapped]);
const areaContextProviderValue = useMemo(() => ({
shouldChangeColor: !shouldHideBackground
}), [shouldHideBackground]);
const accordionWrappedContextProviderValue = useMemo(() => ({
isWrapped: true
}), []);
return /*#__PURE__*/React.createElement(StyledMotionAccordion, {
animate: {
height: 'auto',
opacity: 1
},
"data-uuid": `${accordionGroupUuid ?? ''}---${uuid}`,
className: "beta-chayns-accordion",
exit: {
height: 0,
opacity: 0
},
initial: {
height: 0,
opacity: 0
},
$isOpen: isOpen,
$shouldShowLines: !isLastAccordion || !isWrapped,
$isParentWrapped: isParentWrapped,
$isWrapped: isWrapped,
$shouldForceBackground: shouldForceBackground,
$shouldHideBackground: shouldHideBackground,
$shouldHideBottomLine: shouldHideBottomLine,
onMouseEnter: onHoverStart,
onMouseLeave: onHoverEnd
}, /*#__PURE__*/React.createElement(AccordionContext.Provider, {
value: accordionContextProviderValue
}, /*#__PURE__*/React.createElement(MotionConfig, {
transition: {
type: 'tween'
}
}, /*#__PURE__*/React.createElement(AccordionHead, {
uuid: uuid,
icon: icon,
isOpen: isOpen,
isFixed: isFixed,
isTitleGreyed: isTitleGreyed || isDisabled,
isWrapped: isWrapped === true,
onClick: handleHeadClick,
onSearchChange: onSearchChange,
rightElement: rightElement,
searchPlaceholder: searchPlaceholder,
searchValue: searchValue,
shouldRotateIcon: shouldRotateIcon,
title: title,
titleElement: titleElement,
onTitleInputChange: onTitleInputChange,
titleInputProps: titleInputProps,
titleColor: titleColor
}), /*#__PURE__*/React.createElement(AnimatePresence, {
initial: false
}, (isOpen || shouldRenderClosed) && /*#__PURE__*/React.createElement(AccordionBody, {
maxHeight: bodyMaxHeight,
onScroll: onBodyScroll,
onAnimationComplete: onBodyAnimationComplete,
shouldHideBody: shouldRenderClosed && !isOpen
}, /*#__PURE__*/React.createElement(AccordionWrappedContext.Provider, {
value: accordionWrappedContextProviderValue
}, /*#__PURE__*/React.createElement(AreaContext.Provider, {
value: areaContextProviderValue
}, children)))))));
};
Accordion.displayName = 'Accordion';
export default Accordion;
//# sourceMappingURL=Accordion.js.map