UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

247 lines (246 loc) 7.59 kB
"use client"; import _pushInstanceProperty from "core-js-pure/stable/instance/push.js"; import React, { useContext, useState } from 'react'; import { validateDOMAttributes, extendPropsWithContext } from "../../shared/component-helper.js"; import IconPrimary from "../icon-primary/IconPrimary.js"; import clsx from 'clsx'; import AccordionContext from "./AccordionContext.js"; import { applySpacing } from "../space/SpacingUtils.js"; import { skeletonDOMAttributes, createSkeletonClass } from "../skeleton/SkeletonHelper.js"; import withComponentMarkers from "../../shared/helpers/withComponentMarkers.js"; import { jsx as _jsx } from "react/jsx-runtime"; function AccordionHeaderTitle({ children = null, ...rest }) { return _jsx("span", { ...applySpacing(rest, { className: 'dnb-accordion__header__title' }), children: children }); } function AccordionHeaderDescription({ children = null, ...rest }) { return children ? _jsx("span", { ...applySpacing(rest, { className: 'dnb-accordion__header__description' }), children: children }) : null; } function AccordionHeaderContainer({ children = null, ...rest }) { return children ? _jsx("span", { ...applySpacing(rest, { className: 'dnb-accordion__header__container' }), children: children }) : null; } function AccordionHeaderIcon({ icon: iconProp, expanded, size = 'medium', iconPosition }) { const icon = iconProp && typeof iconProp === 'object' && 'expanded' in iconProp && typeof (iconProp === null || iconProp === void 0 ? void 0 : iconProp.expanded) !== 'undefined' ? iconProp[expanded ? 'expanded' : 'closed'] : iconProp || 'chevron-down'; return _jsx("span", { className: 'dnb-accordion__header__icon' + (iconPosition ? ` dnb-accordion__header__icon--${iconPosition}` : ""), children: _jsx(IconPrimary, { size: size, icon: icon, "aria-hidden": true }) }); } const accordionHeaderDefaultProps = { iconSize: 'medium' }; export const AccordionHeader = ({ iconSize: iconSizeDefault = 'medium', ...restOfProps }) => { const props = { iconSize: iconSizeDefault, ...restOfProps }; const [isHovering, setIsHovering] = useState(false); const [hasClicked, setHasClicked] = useState(false); const context = useContext(AccordionContext); function onKeyDownHandler(event) { const keyPressed = event.key; if (keyPressed === 'Enter' || keyPressed === ' ') { event.preventDefault(); onClickHandler(event); } } function onClickHandler(event) { const { id, group } = context; if (canClick()) { const expanded = !context.expanded; context.callOnChange({ id, group, expanded, event }); setHasClicked(true); } } function onMouseOverHandler() { setIsHovering(true); } function onMouseOutHandler() { setIsHovering(false); setHasClicked(false); } function canClick() { const { expanded, allowCloseAll, group } = context; return !group || group && !expanded || allowCloseAll; } const extendedProps = extendPropsWithContext(props, accordionHeaderDefaultProps, context); const { id, leftComponent, expanded, title, description, element, heading, headingLevel, icon, iconSize, disabled, skeleton, noAnimation, variant } = extendedProps; let { iconPosition } = extendedProps; const { children, className, leftComponent: _leftComponent, expanded: _expanded, title: _title, description: _description, icon: _icon, iconSize: _iconSize, disabled: _disabled, ...rest } = props; const defaultParts = [_jsx(AccordionHeaderIcon, { icon: icon, size: iconSize, expanded: context.expanded, iconPosition: iconPosition }, "icon"), _jsx(AccordionHeaderContainer, { children: leftComponent }, "container"), _jsx(AccordionHeaderTitle, { children: title || (Array.isArray(children) ? children.filter(cur => !React.isValidElement(cur)) : children) }, "title"), _jsx(AccordionHeaderDescription, { children: description }, "description")]; if (Array.isArray(children)) { const removeParts = []; children.forEach(cur => { if (React.isValidElement(cur)) { const part = defaultParts.find(c => c.type === cur.type); if (part) { _pushInstanceProperty(removeParts).call(removeParts, part); } _pushInstanceProperty(defaultParts).call(defaultParts, cur); } }); removeParts.forEach(part => { const index = defaultParts.findIndex(c => c === part); if (index > -1) { defaultParts.splice(index, 1); } }); } const partsToRender = []; const wrapperParts = []; const wrapperComp = _jsx("span", { className: "dnb-accordion__header__wrapper", children: wrapperParts }, "wrapper"); defaultParts.forEach(part => { if (React.isValidElement(part) && (part.type === AccordionHeaderTitle || part.type === AccordionHeaderDescription)) { _pushInstanceProperty(wrapperParts).call(wrapperParts, part); if (partsToRender.findIndex(c => c === wrapperComp) === -1) { _pushInstanceProperty(partsToRender).call(partsToRender, wrapperComp); } } else { _pushInstanceProperty(partsToRender).call(partsToRender, part); } }); if (iconPosition === undefined) { const iconIndex = partsToRender.findIndex(c => c.type === AccordionHeaderIcon); if (iconIndex > 1) { iconPosition = 'right'; } if (leftComponent) { iconPosition = 'right'; } } const headerParams = applySpacing(rest, { id: `${id}-header`, 'aria-controls': `${id}-content`, 'aria-expanded': context.expanded, role: 'button', tabIndex: 0, className: clsx('dnb-accordion__header', createSkeletonClass('font', skeleton, context), className, context.expanded && 'dnb-accordion__header--expanded' + (isHovering && hasClicked ? " dnb-accordion__header--after-click" : ""), variant && `dnb-accordion__header--${variant}`, iconPosition && `dnb-accordion__header--icon-${iconPosition}`, !canClick() && 'dnb-accordion__header--prevent-click', description && 'dnb-accordion__header--description', noAnimation && 'dnb-accordion__header--no-animation'), disabled, ...rest }); if (disabled || skeleton) { headerParams.tabIndex = -1; headerParams.disabled = true; headerParams['aria-disabled'] = true; } else { headerParams.onClick = onClickHandler; headerParams.onKeyDown = onKeyDownHandler; headerParams.onMouseOver = onMouseOverHandler; headerParams.onMouseOut = onMouseOutHandler; } skeletonDOMAttributes(headerParams, skeleton, context); validateDOMAttributes(props, headerParams); let Element = 'div'; if (heading === true) { headerParams.role = 'heading'; headerParams['aria-level'] = headingLevel ? Number(headingLevel) : 2; } else if (heading) { headerParams.role = null; Element = heading; } else if (element) { headerParams.role = null; Element = element; } return _jsx(Element, { ...headerParams, children: partsToRender }); }; AccordionHeader.Container = AccordionHeaderContainer; AccordionHeader.Icon = AccordionHeaderIcon; AccordionHeader.Title = AccordionHeaderTitle; AccordionHeader.Description = AccordionHeaderDescription; withComponentMarkers(AccordionHeader, { _supportsSpacingProps: true }); export default AccordionHeader; //# sourceMappingURL=AccordionHeader.js.map