UNPKG

@chayns-components/core

Version:

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

327 lines (326 loc) • 14.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.AccordionContext = void 0; var _react = require("motion/react"); var _react2 = _interopRequireWildcard(require("react")); var _uuid = require("../../hooks/uuid"); var _useKeyboardFocusHighlighting = require("../../hooks/useKeyboardFocusHighlighting"); var _AreaContextProvider = require("../area-provider/AreaContextProvider"); var _ColorSchemeProvider = require("../color-scheme-provider/ColorSchemeProvider"); var _AccordionBody = _interopRequireDefault(require("./accordion-body/AccordionBody")); var _AccordionGroup = require("./accordion-group/AccordionGroup"); var _AccordionHead = _interopRequireDefault(require("./accordion-head/AccordionHead")); var _AccordionContextProvider = require("./accordion-provider/AccordionContextProvider"); var _Accordion = require("./Accordion.styles"); var _ref = require("../../hooks/ref"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } const AccordionContext = exports.AccordionContext = /*#__PURE__*/_react2.default.createContext({ isWrapped: undefined }); const Accordion = ({ bodyMaxHeight, children, icon, isDefaultOpen = false, isDisabled = false, isFixed = false, isOpened, isTitleGreyed = false, onBodyScroll, onClose, onHoverEnd, onHoverStart, onOpen, onSearchChange, rightElement, searchPlaceholder, searchValue, shouldForceBackground = false, shouldForceBottomLine = false, shouldHideBackground = false, shouldRenderClosed = false, shouldRotateIcon = true, shouldHideBottomLine = false, title, titleElement, onTitleInputChange, titleInputProps, shouldSkipAnimation: shouldSkipAnimationProp = false, colors, shouldIndex = false, onBodyAnimationComplete, shouldEnableKeyboardHighlighting }) => { const { isWrapped: groupIsWrapped, openAccordionUuid, accordionGroupUuid, accordionUuids, updateOpenAccordionUuid, activeAccordionUuid, updateActiveAccordionUuid, registerAccordionUuid, unregisterAccordionUuid } = (0, _react2.useContext)(_AccordionGroup.AccordionGroupContext); const { isWrapped: isParentWrapped } = (0, _react2.useContext)(AccordionContext); const { isWrapped: contextIsWrapped } = (0, _react2.useContext)(_AccordionContextProvider.AccordionWrappedContext); const colorScheme = (0, _ColorSchemeProvider.useColorScheme)(); const shouldEnableKeyboardHighlightingEffective = shouldEnableKeyboardHighlighting ?? (colorScheme === null || colorScheme === void 0 ? void 0 : colorScheme.shouldEnableKeyboardHighlighting) ?? false; const isWrapped = (0, _react2.useMemo)(() => groupIsWrapped ?? contextIsWrapped, [contextIsWrapped, groupIsWrapped]); const [isAccordionOpen, setIsAccordionOpen] = (0, _react2.useState)(isDefaultOpen ?? isOpened); const [isGroupFocusWithin, setIsGroupFocusWithin] = (0, _react2.useState)(false); const uuid = (0, _uuid.useUuid)(); const isInitialRenderRef = (0, _react2.useRef)(true); const initialRenderSkipRef = (0, _ref.useInitialRenderRef)(true); const shouldSkipAnimation = shouldSkipAnimationProp ?? (initialRenderSkipRef.current && isDefaultOpen); const isInGroup = shouldSkipAnimation ? false : typeof updateOpenAccordionUuid === 'function'; const isOpen = isInGroup ? openAccordionUuid === uuid : isAccordionOpen; const isOpenRef = (0, _react2.useRef)(isOpen); const onCloseRef = (0, _react2.useRef)(onClose); const onOpenRef = (0, _react2.useRef)(onOpen); const shouldShowKeyboardHighlighting = (0, _useKeyboardFocusHighlighting.useKeyboardFocusHighlighting)(shouldEnableKeyboardHighlightingEffective); const isKeyboardFocusable = !isDisabled && (shouldIndex || shouldEnableKeyboardHighlightingEffective); const isInKeyboardNavigationGroup = isKeyboardFocusable && typeof updateActiveAccordionUuid === 'function' && typeof accordionGroupUuid === 'string'; (0, _react2.useEffect)(() => { if (typeof accordionGroupUuid === 'string' && typeof registerAccordionUuid === 'function' && typeof unregisterAccordionUuid === 'function') { registerAccordionUuid(uuid); return () => { unregisterAccordionUuid(uuid); }; } return undefined; }, [accordionGroupUuid, registerAccordionUuid, unregisterAccordionUuid, uuid]); const isLastAccordion = (0, _react2.useMemo)(() => accordionUuids ? accordionUuids[accordionUuids.length - 1] === uuid : false, [accordionUuids, uuid]); (0, _react2.useEffect)(() => { isOpenRef.current = isOpen; onCloseRef.current = onClose; onOpenRef.current = onOpen; }, [isOpen, onClose, onOpen]); const handleHeadClick = (0, _react2.useCallback)(() => { if (isDisabled) { return; } if (isKeyboardFocusable && typeof updateActiveAccordionUuid === 'function') { updateActiveAccordionUuid(uuid); } if (typeof updateOpenAccordionUuid === 'function') { updateOpenAccordionUuid(uuid); } setIsAccordionOpen(currentIsAccordionOpen => !currentIsAccordionOpen); }, [isDisabled, isKeyboardFocusable, updateActiveAccordionUuid, updateOpenAccordionUuid, uuid]); (0, _react2.useEffect)(() => { if (isDisabled && isOpen) { if (typeof updateOpenAccordionUuid === 'function') { updateOpenAccordionUuid(uuid); } setIsAccordionOpen(currentIsAccordionOpen => !currentIsAccordionOpen); } }, [isDisabled, isOpen, updateOpenAccordionUuid, uuid]); (0, _react2.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]); (0, _react2.useEffect)(() => { if (isDefaultOpen) { if (typeof updateOpenAccordionUuid === 'function') { updateOpenAccordionUuid(uuid, { shouldOnlyOpen: true }); } else { setIsAccordionOpen(true); } } }, [isDefaultOpen, updateOpenAccordionUuid, uuid]); (0, _react2.useEffect)(() => { if (typeof isOpened === 'boolean') { if (typeof updateOpenAccordionUuid === 'function' && isOpened !== isOpenRef.current) { updateOpenAccordionUuid(uuid); } else { setIsAccordionOpen(isOpened); } } }, [isOpened, updateOpenAccordionUuid, uuid]); const accordionContextProviderValue = (0, _react2.useMemo)(() => ({ isWrapped: isWrapped === true }), [isWrapped]); const areaContextProviderValue = (0, _react2.useMemo)(() => ({ shouldChangeColor: !shouldHideBackground }), [shouldHideBackground]); const accordionWrappedContextProviderValue = (0, _react2.useMemo)(() => ({ isWrapped: true }), []); const initialAnimation = (0, _react2.useMemo)(() => { if (shouldSkipAnimation) { return { height: 'auto', opacity: 1 }; } return isOpen ? { height: 'auto', opacity: 1 } : { height: 0, opacity: 0 }; }, [isOpen, shouldSkipAnimation]); const tabIndex = (0, _react2.useMemo)(() => isKeyboardFocusable ? 0 : -1, [isKeyboardFocusable]); const handleKeyDown = (0, _react2.useCallback)(e => { const isCurrentAccordionTarget = e.currentTarget === e.target; if (isCurrentAccordionTarget && isInKeyboardNavigationGroup && accordionUuids !== null && accordionUuids !== void 0 && accordionUuids.length && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) { const currentIndex = accordionUuids.indexOf(uuid); if (currentIndex !== -1) { const nextIndex = e.key === 'ArrowDown' ? (currentIndex + 1) % accordionUuids.length : (currentIndex - 1 + accordionUuids.length) % accordionUuids.length; const nextAccordionUuid = accordionUuids[nextIndex]; if (nextAccordionUuid && nextAccordionUuid !== uuid) { const nextAccordionElement = document.querySelector(`[data-uuid="${accordionGroupUuid}---${nextAccordionUuid}"]`); if (nextAccordionElement) { updateActiveAccordionUuid(nextAccordionUuid); nextAccordionElement.focus(); return; } } } } if (isCurrentAccordionTarget && (e.key === 'Enter' || e.key === ' ') && isKeyboardFocusable) { handleHeadClick(); } if (isCurrentAccordionTarget && e.key === 'ArrowRight' && isKeyboardFocusable && !isOpen) { e.preventDefault(); handleHeadClick(); } if (isCurrentAccordionTarget && (e.key === 'Escape' || e.key === 'ArrowLeft')) { if (isOpen && isKeyboardFocusable) { e.preventDefault(); handleHeadClick(); return; } if (isInKeyboardNavigationGroup && typeof updateActiveAccordionUuid === 'function') { var _e$currentTarget$pare; e.preventDefault(); updateActiveAccordionUuid(undefined); let parentAccordion = (_e$currentTarget$pare = e.currentTarget.parentElement) === null || _e$currentTarget$pare === void 0 ? void 0 : _e$currentTarget$pare.closest('.beta-chayns-accordion'); while (parentAccordion) { var _parentAccordion$getA, _parentAccordion$pare; const parentGroupId = (_parentAccordion$getA = parentAccordion.getAttribute('data-uuid')) === null || _parentAccordion$getA === void 0 ? void 0 : _parentAccordion$getA.split('---')[0]; if (parentGroupId !== accordionGroupUuid) { parentAccordion.focus(); break; } parentAccordion = (_parentAccordion$pare = parentAccordion.parentElement) === null || _parentAccordion$pare === void 0 ? void 0 : _parentAccordion$pare.closest('.beta-chayns-accordion'); } } } }, [accordionGroupUuid, accordionUuids, handleHeadClick, isInKeyboardNavigationGroup, isKeyboardFocusable, isOpen, updateActiveAccordionUuid, uuid]); const handleFocus = (0, _react2.useCallback)(e => { if (e.currentTarget === e.target && isInKeyboardNavigationGroup && typeof updateActiveAccordionUuid === 'function') { setIsGroupFocusWithin(true); updateActiveAccordionUuid(uuid); } }, [isInKeyboardNavigationGroup, updateActiveAccordionUuid, uuid]); const handleBlur = (0, _react2.useCallback)(e => { if (isInKeyboardNavigationGroup && typeof updateActiveAccordionUuid === 'function' && typeof accordionGroupUuid === 'string') { const nextFocusedElement = e.relatedTarget; const currentGroupElement = e.currentTarget; if (!nextFocusedElement || !currentGroupElement.contains(nextFocusedElement)) { setIsGroupFocusWithin(false); updateActiveAccordionUuid(undefined); } } }, [accordionGroupUuid, isInKeyboardNavigationGroup, updateActiveAccordionUuid]); (0, _react2.useEffect)(() => { if (!isInKeyboardNavigationGroup) { setIsGroupFocusWithin(false); } else if (activeAccordionUuid == null && typeof updateActiveAccordionUuid === 'function' && (accordionUuids === null || accordionUuids === void 0 ? void 0 : accordionUuids[0]) === uuid) { updateActiveAccordionUuid(uuid); } }, [accordionUuids, activeAccordionUuid, isInKeyboardNavigationGroup, updateActiveAccordionUuid, uuid]); return /*#__PURE__*/_react2.default.createElement(_Accordion.StyledMotionAccordion, { animate: { height: 'auto', opacity: 1 }, "data-uuid": `${accordionGroupUuid ?? ''}---${uuid}`, className: "beta-chayns-accordion", exit: { height: 0, opacity: 0 }, initial: initialAnimation, $isOpen: isOpen, tabIndex: tabIndex, $shouldShowLines: !isLastAccordion || !isWrapped, $isParentWrapped: isParentWrapped, $isWrapped: isWrapped, $shouldForceBackground: shouldForceBackground, $shouldForceBottomLine: shouldForceBottomLine, $shouldHideBackground: shouldHideBackground, $shouldHideBottomLine: shouldHideBottomLine, $bottomBorderColor: colors === null || colors === void 0 ? void 0 : colors.borderBottomColor, $shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlightingEffective, $shouldShowKeyboardHighlighting: shouldShowKeyboardHighlighting, onKeyDown: handleKeyDown, onFocus: handleFocus, onBlur: handleBlur, onMouseEnter: onHoverStart, onMouseLeave: onHoverEnd, transition: { duration: shouldSkipAnimation ? 0 : 0.25 } }, /*#__PURE__*/_react2.default.createElement(AccordionContext.Provider, { value: accordionContextProviderValue }, /*#__PURE__*/_react2.default.createElement(_react.MotionConfig, { transition: { type: 'tween' } }, /*#__PURE__*/_react2.default.createElement(_AccordionHead.default, { uuid: uuid, icon: icon, isOpen: isOpen, shouldSkipAnimation: shouldSkipAnimation, 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: colors === null || colors === void 0 ? void 0 : colors.titleColor, shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlightingEffective }), /*#__PURE__*/_react2.default.createElement(_react.AnimatePresence, { initial: false }, (isOpen || shouldRenderClosed) && /*#__PURE__*/_react2.default.createElement(_AccordionBody.default, { shouldSkipAnimation: shouldSkipAnimation, maxHeight: bodyMaxHeight, onScroll: onBodyScroll, onAnimationComplete: onBodyAnimationComplete, shouldHideBody: shouldRenderClosed && !isOpen }, /*#__PURE__*/_react2.default.createElement(_AccordionContextProvider.AccordionWrappedContext.Provider, { value: accordionWrappedContextProviderValue }, /*#__PURE__*/_react2.default.createElement(_AreaContextProvider.AreaContext.Provider, { value: areaContextProviderValue }, children))))))); }; Accordion.displayName = 'Accordion'; var _default = exports.default = Accordion; //# sourceMappingURL=Accordion.js.map