UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

231 lines (230 loc) 7.63 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 classnames from 'classnames'; import AccordionContext from "./AccordionContext.js"; import { createSpacingClasses } from "../space/SpacingHelper.js"; import { skeletonDOMAttributes, createSkeletonClass } from "../skeleton/SkeletonHelper.js"; function AccordionHeaderTitle({ children = null, ...rest }) { return React.createElement("span", { className: classnames('dnb-accordion__header__title', createSpacingClasses(rest)) }, children); } function AccordionHeaderDescription({ children = null, ...rest }) { return children ? React.createElement("span", { className: classnames('dnb-accordion__header__description', createSpacingClasses(rest)) }, children) : null; } function AccordionHeaderContainer({ children = null, ...rest }) { return children ? React.createElement("span", { className: classnames('dnb-accordion__header__container', createSpacingClasses(rest)) }, children) : null; } function AccordionHeaderIcon({ icon: iconProp, expanded, size = 'medium', icon_position }) { 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 React.createElement("span", { className: 'dnb-accordion__header__icon' + (icon_position ? ` dnb-accordion__header__icon--${icon_position}` : "") }, React.createElement(IconPrimary, { size: size, icon: icon, "aria-hidden": true })); } const accordionHeaderDefaultProps = { icon_size: 'medium' }; export const AccordionHeader = ({ icon_size: icon_size_default = 'medium', ...restOfProps }) => { const props = { icon_size: icon_size_default, ...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, allow_close_all, group } = context; return !group || group && !expanded || allow_close_all; } const extendedProps = extendPropsWithContext(props, accordionHeaderDefaultProps, context); const { id, left_component, expanded, title, description, element, heading, heading_level, icon, icon_size, disabled, skeleton, no_animation, variant } = extendedProps; let { icon_position } = extendedProps; const { children, className, left_component: _left_component, expanded: _expanded, title: _title, description: _description, icon: _icon, icon_size: _icon_size, disabled: _disabled, ...rest } = props; const defaultParts = [React.createElement(AccordionHeaderIcon, { key: "icon", icon: icon, size: icon_size, expanded: context.expanded, icon_position: icon_position }), React.createElement(AccordionHeaderContainer, { key: "container" }, left_component), React.createElement(AccordionHeaderTitle, { key: "title" }, title || (Array.isArray(children) ? children.filter(cur => !React.isValidElement(cur)) : children)), React.createElement(AccordionHeaderDescription, { key: "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 = React.createElement("span", { className: "dnb-accordion__header__wrapper", key: "wrapper" }, wrapperParts); 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 (icon_position === undefined) { const iconIndex = partsToRender.findIndex(c => c.type === AccordionHeaderIcon); if (iconIndex > 1) { icon_position = 'right'; } if (left_component) { icon_position = 'right'; } } const headerParams = { id: `${id}-header`, 'aria-controls': `${id}-content`, 'aria-expanded': context.expanded, role: 'button', tabIndex: 0, className: classnames('dnb-accordion__header', createSkeletonClass('font', skeleton, context), createSpacingClasses(rest), className, context.expanded && 'dnb-accordion__header--expanded' + (isHovering && hasClicked ? " dnb-accordion__header--after-click" : ""), variant && `dnb-accordion__header--${variant}`, icon_position && `dnb-accordion__header--icon-${icon_position}`, !canClick() && 'dnb-accordion__header--prevent-click', description && 'dnb-accordion__header--description', no_animation && '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 && (String(heading) === 'true' || String(heading) === '1')) { headerParams.role = 'heading'; headerParams['aria-level'] = heading_level ? Number(heading_level) : 2; } else if (heading) { headerParams.role = null; Element = heading; } else if (element) { headerParams.role = null; Element = element; } return React.createElement(Element, headerParams, partsToRender); }; AccordionHeader.Container = AccordionHeaderContainer; AccordionHeader.Icon = AccordionHeaderIcon; AccordionHeader.Title = AccordionHeaderTitle; AccordionHeader.Description = AccordionHeaderDescription; AccordionHeader._supportsSpacingProps = true; export default AccordionHeader; //# sourceMappingURL=AccordionHeader.js.map