Repository URL to install this package:
|
Version:
3.0.6-working.1 ▾
|
import React from 'react'
import { findDOMNode } from 'react-dom'
import ally from '@skava/ally'
import { isObj, isFunction } from 'exotic'
import { observer } from 'xmobx/mobx-react'
import { Overlay } from 'atoms/Overlay'
import { Portal } from 'features/Portal'
import CloseButton from '../CloseButton'
import { Provider, ModalContextProviderProps, Consumer } from '../ModalContext'
import { StyledDialog, ModalTitle, ModalBox } from './styled'
import { Handle, ModalOrganismProps } from './typings'
import { ModalBoxWrap } from './styled'
// const Disabled = ally.maintain.disabled
const Hidden = ally.maintain.hidden
const TabFocus = ally.maintain.tabFocus
const FirstTab = ally.query.firstTabbable
const Key = ally.when.key
/**
* @see https://christianheilmann.com/2015/08/30/quicky-fading-in-a-newly-created-element-using-css/
*/
@observer
class ModalOrganism extends React.Component<ModalOrganismProps> {
/**
* @deprecated
*/
static get Title() {
console.warn(
'@deprecated - do not use Modal.Title - import { ModalTitle } '
)
return ModalTitle
}
/**
* @deprecated
*/
static get CloseButton() {
console.warn(
'@deprecated - do not use Modal.CloseButton - import { ModalCloseButton } '
)
return CloseButton
}
static get Box() {
console.warn('@deprecated - do not use Modal.Box - import { ModalBox } ')
return ModalBox
}
static get ModalContext() {
console.warn(
'@deprecated - do not use Modal.ModalContext - import { Provider } '
)
return (props: any) => <Provider {...props} />
}
static defaultProps = {
controller: {},
isDefaultFocus: true,
}
/**
* @todo why is this still here? just wcag?
* do not use isHidden
* @todo @name isVisible
*/
state = {
isHidden: true,
}
bodyDOM: HTMLElement | null
dialog: HTMLElement | null
disabledHandle: Handle
focusHandle: Handle
hiddenHandler: Handle
keyHandler: Handle
focusedElementBeforeDialogOpened: Element | null
/* eslint-disable max-statements, react/no-find-dom-node, react/no-did-mount-set-state, react/no-set-state */
componentDidMount() {
this.setState({
isHidden: false,
})
this.bodyDOM = document.body
this.bodyDOM.classList.add('no-scroll')
this.focusedElementBeforeDialogOpened = document.activeElement
try {
const dialogDOM = findDOMNode(this.dialog)
// this.disabledHandle = Disabled({ filter: dialogDOM })
this.focusHandle = TabFocus({ context: dialogDOM })
this.hiddenHandler = Hidden({ filter: '#modal' })
const element = FirstTab({ context: dialogDOM, defaultToContext: true })
this.keyHandler = Key({
escape: (event: KeyboardEvent, disengage: () => void) => {
event.preventDefault()
console.debug('pressed escape')
disengage()
},
})
if (
isObj(element) &&
isFunction(element.focus) &&
this.props.isDefaultFocus
) {
element.focus()
}
} catch (allyException) {
console.error(allyException)
}
}
componentWillUnmount() {
try {
this.bodyDOM.classList.remove('no-scroll')
// this.disabledHandle.disengage()
this.focusHandle.disengage()
this.hiddenHandler.disengage()
this.keyHandler.disengage()
if (isObj(this.focusedElementBeforeDialogOpened)) {
this.focusedElementBeforeDialogOpened.focus()
}
} catch (allyException) {
console.error(allyException)
}
}
setRef = dom => {
this.dialog = dom
}
/**
* @todo probably want <Portal> here for id="modal"...
*/
renderContext = (context: ModalContextProviderProps) => {
const allProps = { ...this.props, ...context }
const {
className,
isDefaultFocus,
controller,
onClose,
state,
children,
...remainingProps
} = allProps
/**
* @todo renderOverlay, renderDialog, renderWrap, renderBoxWrap
* @todo renderBox, renderCloseButton
* @todo add `nowrap` for Portal...
*
* @todo innerRef={this.setRef} < currently using react findDOMNode
*/
return (
<Portal id="modal" className={className}>
<Overlay key="o" isVisible={state!.isVisible} onClick={onClose} />
<StyledDialog
open={state!.isVisible}
isVisible={state!.isVisible}
className={className}
{...remainingProps}
>
<ModalBoxWrap>{children}</ModalBoxWrap>
</StyledDialog>
</Portal>
)
}
render() {
return <Consumer>{this.renderContext}</Consumer>
}
}
export { ModalOrganism, ModalOrganism as Modal }
export default ModalOrganism