Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | 1x 84x 84x 84x 84x 48x 28x 48x 20x 20x 84x 84x 84x 3x 3x 3x 3x 84x 1x 1x | import {useEffect, useRef, useState} from 'react' import PropTypes from 'prop-types' import {Root as RadixRoot} from '@radix-ui/react-dialog' import useControlledState from '@s-ui/react-hooks/lib/useControlledState' import ModalContext from './context/index.js' import {useDelayedRender} from './hooks/index.js' import {ANIMATION_ENTER_DELAY, ANIMATION_EXIT_DELAY} from './config.js' /** Contains all the parts of a dialog. React context of contained Modal **/ const Root = ({ defaultIsOpen = false, isOpen, onOpen, onOpenDelayed, onClose, onCloseDelayed, onOpenToggle, modal = true, children, ...props }) => { const [open, setOpen] = useControlledState(isOpen, defaultIsOpen) const activeElementRef = useRef() const [forceMount, setForceMount] = useState(undefined) const [animation, setAnimation] = useState(undefined) /** * This function captures the active element when the Dialog is opened * and sets focus back to it when the Dialog is closed. */ function handleActiveElementFocus() { if (isOpen && document.activeElement) { activeElementRef.current = document.activeElement } if (!isOpen) { setTimeout(() => { Eif (!(activeElementRef.current instanceof HTMLElement)) return activeElementRef.current.focus() }, 0) } } useEffect(handleActiveElementFocus, [open]) const {isMounted, isRendered} = useDelayedRender(open, { enterDelay: ANIMATION_ENTER_DELAY, exitDelay: ANIMATION_EXIT_DELAY, onEnterDelayed: onOpenDelayed, onExitDelayed: onCloseDelayed }) const onOpenChange = open => { const dialogEvent = new Event(open ? 'onOpenDialog' : 'onCloseDialog') setOpen(open) open ? typeof onOpen === 'function' && onOpen(dialogEvent, {isOpen: open}) : typeof onClose === 'function' && onClose(dialogEvent, {isOpen: open}) typeof onOpenToggle === 'function' && onOpenToggle(dialogEvent, {isOpen: open}) } return ( <ModalContext.Provider value={{ isOpen: open, forceMount, setForceMount, animation, hasAnimation: animation !== 'none', setAnimation, isMounted, isRendered }} > <RadixRoot defaultOpen={defaultIsOpen} open={open} onOpenChange={onOpenChange} modal={modal} {...props}> {children} </RadixRoot> </ModalContext.Provider> ) } Root.displayName = 'MoleculeModal.Root' Root.propTypes = { /** The open state of the modal when it is initially rendered. Use when you do not need to control its open state. */ defaultIsOpen: PropTypes.bool, /** The controlled open state of the modal. Must be used in conjunction with onOpenChange. **/ isOpen: PropTypes.bool, /** Event handler called when the open state of the modal changes. **/ onOpenToggle: PropTypes.func, /** Event handler called when the open the modal gets opened. **/ onOpen: PropTypes.func, /** Event handler called when the open modal animation ended. **/ onOpenDelayed: PropTypes.func, /** Event handler called when the open the modal gets closed. **/ onClose: PropTypes.func, /** Event handler called when the close modal animation ended. **/ onCloseDelayed: PropTypes.func, /** The modality of the dialog. When set to true, interaction with outside elements will be disabled and only dialog content will be visible to screen readers. **/ modal: PropTypes.bool, /** The children of the modal. **/ children: PropTypes.node } export default Root |