@nex-ui/react
Version:
🎉 A beautiful, modern, and reliable React component library.
72 lines (69 loc) • 2.11 kB
JavaScript
"use client";
import { jsx } from 'react/jsx-runtime';
import { useState, useEffect, useMemo } from 'react';
import { defineRecipe } from '@nex-ui/system';
import { useModal } from './ModalContext.mjs';
import { useModalManager } from './ModalManager.mjs';
import { useSlot } from '../utils/useSlot.mjs';
import { FocusTrap } from '../focusTrap/FocusTrap.mjs';
const recipe = defineRecipe({
base: {
width: 'full',
position: 'relative',
display: 'flex',
flexDirection: 'column',
outline: 'none',
bg: 'content'
}
});
const style = recipe();
const useAriaProps = (props)=>{
const { modalContentId, modalHeaderId, modalBodyId } = useModal();
const { tabIndex = -1, id = modalContentId, 'aria-labelledby': labelledBy = modalHeaderId, 'aria-describedby': describedBy = modalBodyId } = props;
return useMemo(()=>{
return {
tabIndex,
id,
'aria-labelledby': labelledBy,
'aria-describedby': describedBy
};
}, [
describedBy,
id,
labelledBy,
tabIndex
]);
};
const ModalContent = (inProps)=>{
const props = inProps;
const ctx = useModal();
const [paused, setPaused] = useState(false);
const modalManager = useModalManager();
const { isTopmostModal } = ctx;
const ariaProps = useAriaProps(props);
const [ModalContentRoot, getModalContentRootProps] = useSlot({
style,
elementType: 'section',
externalForwardedProps: props,
a11y: ariaProps
});
useEffect(()=>{
const unsubscribe = modalManager.subscribe(()=>{
setPaused(!isTopmostModal?.());
});
return unsubscribe;
}, [
isTopmostModal,
modalManager
]);
return /*#__PURE__*/ jsx(FocusTrap, {
active: ctx.open,
restoreFocus: ctx.restoreFocus,
paused: paused,
children: /*#__PURE__*/ jsx(ModalContentRoot, {
...getModalContentRootProps()
})
});
};
ModalContent.displayName = 'ModalContent';
export { ModalContent };