@nex-ui/react
Version:
🎉 A beautiful, modern, and reliable React component library.
261 lines (255 loc) • 8.94 kB
JavaScript
"use client";
'use strict';
var jsxRuntime = require('react/jsx-runtime');
var m = require('motion/react-m');
var hooks = require('@nex-ui/hooks');
var icons = require('@nex-ui/icons');
var react$1 = require('motion/react');
var react = require('react');
var AccordionContext = require('./AccordionContext.cjs');
var useDefaultProps = require('../utils/useDefaultProps.cjs');
var useStyles = require('../utils/useStyles.cjs');
var useSlotClasses = require('../utils/useSlotClasses.cjs');
var useSlot = require('../utils/useSlot.cjs');
var ButtonBase = require('../buttonBase/ButtonBase.cjs');
var index = require('../utils/motionFeatures/index.cjs');
var accordion = require('../../theme/recipes/accordion.cjs');
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var m__namespace = /*#__PURE__*/_interopNamespace(m);
const contentMotionVariants = {
expanded: {
opacity: 1,
height: 'auto',
transition: {
opacity: {
delay: 0.1
},
ease: 'easeInOut',
duration: 0.2
}
},
collapsed: {
opacity: 0,
height: 0,
transition: {
ease: 'easeInOut',
duration: 0.2
}
}
};
const indicatorMotionVariants = {
expanded: {
rotate: 180,
transition: {
duration: 0.2
}
},
collapsed: {
rotate: 0,
transition: {
duration: 0.2
}
}
};
const slots = [
'root',
'heading',
'trigger',
'content',
'indicator'
];
const useSlotAriaProps = (ownerState)=>{
const { itemKey, expanded, slotProps } = ownerState;
const id = react.useId();
return react.useMemo(()=>{
const triggerProps = slotProps?.trigger || {};
const contentProps = slotProps?.content || {};
const indicatorProps = slotProps?.indicator || {};
const triggerId = triggerProps.id ?? id;
const contentId = contentProps.id ?? `panel-${itemKey}-content`;
const trigger = {
id: triggerId,
'aria-expanded': triggerProps['aria-expanded'] ?? expanded,
'aria-controls': triggerProps['aria-controls'] ?? contentId
};
const content = {
id: contentId,
role: contentProps.role ?? 'region',
'aria-labelledby': contentProps['aria-labelledby'] ?? triggerId
};
const indicator = {
'aria-hidden': indicatorProps['aria-hidden'] ?? true
};
return {
trigger,
content,
indicator
};
}, [
expanded,
id,
itemKey,
slotProps?.content,
slotProps?.indicator,
slotProps?.trigger
]);
};
const AccordionItem = (inProps)=>{
const defaultKey = react.useId();
const props = useDefaultProps.useDefaultProps({
name: 'AccordionItem',
props: inProps
});
const { variant, toggleExpandedKey, expandedKeys, disabledKeys, disabled: defaultDisabled, indicator: defaultIndicator, motionProps: defaultMotionProps, keepMounted: defaultKeepMounted, hideIndicator: defaultHideIndicator, indicatorMotionProps: defaultIndicatorMotionProps } = AccordionContext.useAccordionGroup();
const { children, title, slotProps, classNames, indicatorMotionProps = defaultIndicatorMotionProps, motionProps = defaultMotionProps, hideIndicator = defaultHideIndicator, keepMounted = defaultKeepMounted, indicator = defaultIndicator, itemKey = defaultKey, disabled = disabledKeys.includes(itemKey) || defaultDisabled, ...remainingProps } = props;
const expanded = expandedKeys.includes(itemKey);
const ownerState = {
...props,
variant,
itemKey,
expanded,
indicator,
keepMounted,
hideIndicator,
disabled,
motionProps
};
const styles = useStyles.useStyles({
name: 'AccordionItem',
ownerState,
recipe: accordion.accordionItemRecipe
});
const slotClasses = useSlotClasses.useSlotClasses({
name: 'AccordionItem',
slots,
classNames
});
const slotAriaProps = useSlotAriaProps(ownerState);
const animate = expanded ? 'expanded' : 'collapsed';
// Skip initial animation when first rendering and the item is expanded
const motionInitialRef = react.useRef(animate);
if (motionInitialRef.current === 'expanded' && !expanded) {
// Restore open animation for subsequent renders
motionInitialRef.current = 'collapsed';
}
const contentMotionProps = keepMounted ? {
animate,
initial: motionInitialRef.current,
variants: contentMotionVariants,
style: {
overflow: 'hidden'
}
} : {
variants: contentMotionVariants,
initial: motionInitialRef.current,
animate: 'expanded',
exit: 'collapsed',
style: {
overflow: 'hidden'
}
};
const [AccordionItemRoot, getAccordionItemRootProps] = useSlot.useSlot({
elementType: 'div',
externalForwardedProps: remainingProps,
style: styles.root,
classNames: slotClasses.root,
dataAttrs: {
keepMounted,
hideIndicator,
disabled,
state: animate
}
});
const [AccordionItemHeading, getAccordionItemHeadingProps] = useSlot.useSlot({
elementType: 'h3',
externalSlotProps: slotProps?.heading,
style: styles.heading,
classNames: slotClasses.heading
});
const handleClick = hooks.useEvent(()=>{
toggleExpandedKey(itemKey);
});
const [AccordionItemTrigger, getAccordionItemTriggerProps] = useSlot.useSlot({
elementType: ButtonBase.ButtonBase,
externalSlotProps: slotProps?.trigger,
style: styles.trigger,
classNames: slotClasses.trigger,
a11y: slotAriaProps.trigger,
shouldForwardComponent: false,
additionalProps: {
disabled,
onClick: handleClick
}
});
const [AccordionItemContent, getAccordionItemContentProps] = useSlot.useSlot({
elementType: 'div',
externalSlotProps: slotProps?.content,
style: styles.content,
classNames: slotClasses.content,
a11y: slotAriaProps.content
});
const [AccordionItemIndicator, getAccordionItemIndicatorProps] = useSlot.useSlot({
elementType: m__namespace.span,
externalSlotProps: slotProps?.indicator,
style: styles.indicator,
classNames: slotClasses.indicator,
a11y: slotAriaProps.indicator,
additionalProps: {
animate,
variants: indicatorMotionVariants,
initial: animate,
...indicatorMotionProps
}
});
return /*#__PURE__*/ jsxRuntime.jsx(react$1.LazyMotion, {
features: index.motionFeatures,
children: /*#__PURE__*/ jsxRuntime.jsxs(AccordionItemRoot, {
...getAccordionItemRootProps(),
children: [
/*#__PURE__*/ jsxRuntime.jsx(AccordionItemHeading, {
...getAccordionItemHeadingProps(),
children: /*#__PURE__*/ jsxRuntime.jsxs(AccordionItemTrigger, {
...getAccordionItemTriggerProps(),
children: [
/*#__PURE__*/ jsxRuntime.jsx("span", {
children: title
}),
!hideIndicator && /*#__PURE__*/ jsxRuntime.jsx(AccordionItemIndicator, {
...getAccordionItemIndicatorProps(),
children: indicator ?? /*#__PURE__*/ jsxRuntime.jsx(icons.ChevronDownOutlined, {})
})
]
})
}),
/*#__PURE__*/ jsxRuntime.jsx(react$1.AnimatePresence, {
children: (keepMounted || expanded) && /*#__PURE__*/ jsxRuntime.jsx(m__namespace.div, {
...contentMotionProps,
...motionProps,
children: /*#__PURE__*/ jsxRuntime.jsx(AccordionItemContent, {
...getAccordionItemContentProps(),
children: children
})
})
})
]
})
});
};
AccordionItem.displayName = 'AccordionItem';
exports.AccordionItem = AccordionItem;