@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
181 lines (180 loc) • 6.29 kB
JavaScript
"use client";
import _extends from "@babel/runtime/helpers/esm/extends";
var _AccordionHeader, _ChevronIcon, _ChevronIcon2, _Hr;
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
import classnames from 'classnames';
import useId from "../../shared/helpers/useId.js";
import { ListContext } from "./ListContext.js";
import ItemContent from "./ItemContent.js";
import FlexItem from "../flex/Item.js";
import HeightAnimation from "../height-animation/HeightAnimation.js";
import Hr from "../../elements/Hr.js";
import { ChevronIcon } from "./ItemAction.js";
import Space from "../space/Space.js";
import { omitSpacingProps, pickSpacingProps } from "../flex/utils.js";
import ItemIcon from "./ItemIcon.js";
import ItemTitle from "./ItemTitle.js";
import { createSkeletonClass } from "../skeleton/SkeletonHelper.js";
import { warn } from "../../shared/component-helper.js";
import Context from "../../shared/Context.js";
const ItemAccordionContext = createContext(undefined);
function ItemAccordion(props) {
const {
className,
onClick,
onChange,
children,
variant,
pending,
disabled,
skeleton,
open = false,
keepInDOM = false,
chevronPosition = 'right',
icon,
title,
id: idProp,
...rest
} = props;
const [openState, setOpen] = useState(open);
const accordionId = useId(idProp);
const inheritedDisabled = useContext(ListContext)?.disabled;
const appliedDisabled = disabled !== null && disabled !== void 0 ? disabled : inheritedDisabled;
const childArray = React.Children.toArray(children);
const hasExplicitHeader = childArray.some(child => React.isValidElement(child) && child.type === AccordionHeader);
useEffect(() => {
setOpen(open);
}, [open]);
const handleToggle = useCallback(event => {
if (!pending) {
setOpen(prev => {
const next = !prev;
onChange?.({
expanded: next
});
return next;
});
onClick?.(event);
}
}, [onClick, onChange, pending]);
return React.createElement(ItemAccordionContext.Provider, {
value: {
openState,
pending,
disabled: appliedDisabled,
keepInDOM,
chevronPosition,
accordionId,
icon,
title,
handleToggle
}
}, React.createElement(ItemContent, _extends({
className: classnames('dnb-list__item__accordion', className, openState && 'dnb-list__item__accordion--open'),
direction: "vertical",
pending: pending,
disabled: appliedDisabled,
skeleton: skeleton,
variant: variant
}, rest), !hasExplicitHeader ? _AccordionHeader || (_AccordionHeader = React.createElement(AccordionHeader, null)) : null, children));
}
ItemAccordion._supportsSpacingProps = true;
function AccordionHeader(props) {
const {
className,
children,
...rest
} = props;
const accordionContext = useContext(ItemAccordionContext);
const context = useContext(Context);
const inheritedSkeleton = useContext(ListContext)?.skeleton;
const isInactive = accordionContext?.pending || accordionContext?.disabled;
const handleClick = useCallback(event => {
if (!isInactive && accordionContext) {
accordionContext.handleToggle(event);
}
}, [accordionContext, isInactive]);
const handleKeyDown = useCallback(event => {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
handleClick(event);
}
}, [handleClick]);
if (!accordionContext) {
warn('List.Item.Accordion.Header should be used inside List.Item.Accordion.');
return null;
}
const {
chevronPosition,
accordionId,
openState,
icon,
title
} = accordionContext;
const content = React.createElement(FlexItem, _extends({
className: classnames('dnb-list__item__accordion__header', className, inheritedSkeleton && createSkeletonClass('font', true), chevronPosition === 'left' && 'dnb-list__item--chevron-left'),
id: `${accordionId}-header`,
role: "button",
"aria-controls": `${accordionId}-content`,
"aria-expanded": openState,
"aria-disabled": isInactive ? true : undefined,
tabIndex: isInactive ? -1 : 0,
onClick: handleClick,
onKeyDown: handleKeyDown
}, rest), chevronPosition === 'left' && (_ChevronIcon || (_ChevronIcon = React.createElement(ChevronIcon, null))), icon && React.createElement(ItemIcon, null, icon), title !== undefined && React.createElement(ItemTitle, null, title), children, chevronPosition === 'right' && (_ChevronIcon2 || (_ChevronIcon2 = React.createElement(ChevronIcon, null))));
if (inheritedSkeleton) {
return React.createElement(Context.Provider, {
value: {
...context,
skeleton: inheritedSkeleton
}
}, content);
}
return content;
}
ItemAccordion.Header = AccordionHeader;
AccordionHeader._supportsSpacingProps = true;
function AccordionContent(props) {
const {
className,
children,
...rest
} = props;
const context = useContext(Context);
const accordionContext = useContext(ItemAccordionContext);
const inheritedSkeleton = useContext(ListContext)?.skeleton;
if (!accordionContext) {
warn('List.Item.Accordion.Content should be used inside List.Item.Accordion.');
return null;
}
const {
openState,
accordionId,
keepInDOM
} = accordionContext;
const spacingProps = pickSpacingProps(rest);
const content = React.createElement(FlexItem, _extends({
className: classnames('dnb-list__item__accordion__content', className, inheritedSkeleton && createSkeletonClass('font', true)),
id: `${accordionId}-content`,
"aria-labelledby": `${accordionId}-header`,
"aria-hidden": !openState
}, omitSpacingProps(rest)), React.createElement(HeightAnimation, {
open: openState,
keepInDOM: keepInDOM
}, _Hr || (_Hr = React.createElement(Hr, {
bottom: false
})), React.createElement(Space, spacingProps, children)));
if (inheritedSkeleton) {
return React.createElement(Context.Provider, {
value: {
...context,
skeleton: inheritedSkeleton
}
}, content);
}
return content;
}
ItemAccordion.Content = AccordionContent;
AccordionContent._supportsSpacingProps = true;
export default ItemAccordion;
//# sourceMappingURL=ItemAccordion.js.map