'use client'; import * as React from 'react'; import { useHasParentContext } from '@fluentui/react-context-selector'; import { useModalAttributes } from '@fluentui/react-tabster'; import { presenceMotionSlot } from '@fluentui/react-motion'; import { useControllableState, useEventCallback, useId } from '@fluentui/react-utilities'; import { useFocusFirstElement } from '../../utils'; import { DialogContext } from '../../contexts'; import { DialogSurfaceMotion } from '../DialogSurfaceMotion'; /** * Create the state required to render Dialog. * * The returned state can be modified with hooks such as useDialogStyles_unstable, * before being passed to renderDialog_unstable. * * @param props - props from this instance of Dialog */ export const useDialog_unstable = (props)=>{ const { children, modalType = 'modal', onOpenChange, inertTrapFocus = false, unmountOnClose = true } = props; const dialogTitleId = useId('dialog-title-'); const [trigger, content] = childrenToTriggerAndContent(children); const [open, setOpen] = useControllableState({ state: props.open, defaultState: props.defaultOpen, initialState: false }); const requestOpenChange = useEventCallback((data)=>{ onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(data.event, data); // if user prevents default then do not change state value // otherwise updates state value and trigger reference to the element that caused the opening if (!data.event.isDefaultPrevented()) { setOpen(data.open); } }); const dialogRef = useFocusFirstElement(open, modalType); const { modalAttributes, triggerAttributes } = useModalAttributes({ trapFocus: modalType !== 'non-modal', legacyTrapFocus: !inertTrapFocus }); const isNestedDialog = useHasParentContext(DialogContext); return { components: { surfaceMotion: DialogSurfaceMotion }, inertTrapFocus, open, modalType, content, trigger, requestOpenChange, dialogTitleId, isNestedDialog, unmountOnClose, dialogRef, modalAttributes, triggerAttributes, surfaceMotion: presenceMotionSlot(props.surfaceMotion, { elementType: DialogSurfaceMotion, defaultProps: { visible: open, appear: unmountOnClose, unmountOnExit: unmountOnClose } }) }; }; /** * Extracts trigger and content from children */ function childrenToTriggerAndContent(children) { const childrenArray = React.Children.toArray(children); if (process.env.NODE_ENV !== 'production') { if (childrenArray.length !== 1 && childrenArray.length !== 2) { // eslint-disable-next-line no-console console.warn(`@fluentui/react-dialog [useDialog]: Dialog must contain at least one child , and at most two children (in this order).`); } } switch(childrenArray.length){ // case where there's a trigger followed by content case 2: return childrenArray; // case where there's only content case 1: return [ undefined, childrenArray[0] ]; // unknown case default: return [ undefined, undefined ]; } }