diff --git a/docs/examples/ModalStatic.js b/docs/examples/ModalStatic.js new file mode 100644 index 0000000000..e073616bc2 --- /dev/null +++ b/docs/examples/ModalStatic.js @@ -0,0 +1,22 @@ + +const modalInstance = ( +
A modal dialog component
+diff --git a/docs/src/Samples.js b/docs/src/Samples.js index a3ceda963a..fc58d7ed58 100644 --- a/docs/src/Samples.js +++ b/docs/src/Samples.js @@ -34,6 +34,7 @@ export default { PanelGroupUncontrolled: require('fs').readFileSync(__dirname + '/../examples/PanelGroupUncontrolled.js', 'utf8'), PanelGroupAccordion: require('fs').readFileSync(__dirname + '/../examples/PanelGroupAccordion.js', 'utf8'), Modal: require('fs').readFileSync(__dirname + '/../examples/Modal.js', 'utf8'), + ModalStatic: require('fs').readFileSync(__dirname + '/../examples/ModalStatic.js', 'utf8'), ModalContained: require('fs').readFileSync(__dirname + '/../examples/ModalContained.js', 'utf8'), ModalDefaultSizing: require('fs').readFileSync(__dirname + '/../examples/ModalDefaultSizing.js', 'utf8'), ModalCustomSizing: require('fs').readFileSync(__dirname + '/../examples/ModalCustomSizing.js', 'utf8'), diff --git a/src/Modal.js b/src/Modal.js index 417e53fda4..c98041b5e8 100644 --- a/src/Modal.js +++ b/src/Modal.js @@ -1,15 +1,13 @@ /*eslint-disable react/prop-types */ import React, { cloneElement } from 'react'; - import classNames from 'classnames'; -import createChainedFunction from './utils/createChainedFunction'; -import BootstrapMixin from './BootstrapMixin'; import domUtils from './utils/domUtils'; import EventListener from './utils/EventListener'; +import createChainedFunction from './utils/createChainedFunction'; import Portal from './Portal'; import Fade from './Fade'; - +import Dialog from './ModalDialog'; import Body from './ModalBody'; import Header from './ModalHeader'; import Title from './ModalTitle'; @@ -93,12 +91,11 @@ function getScrollbarSize(){ return scrollbarSize; } - -const ModalMarkup = React.createClass({ - - mixins: [ BootstrapMixin ], - +const Modal = React.createClass({ propTypes: { + ...Portal.propTypes, + ...Dialog.propTypes, + /** * Include a backdrop component. Specify 'static' for a backdrop that doesn't trigger an "onHide" when clicked. */ @@ -112,17 +109,6 @@ const ModalMarkup = React.createClass({ * Open and close the Modal with a slide and fade animation. */ animation: React.PropTypes.bool, - /** - * A Callback fired when the header closeButton or non-static backdrop is clicked. - * @type {function} - * @required - */ - onHide: React.PropTypes.func.isRequired, - - /** - * A css class to apply to the Modal dialog DOM node. - */ - dialogClassName: React.PropTypes.string, /** * When `true` The modal will automatically shift focus to itself when it opens, and replace it to the last focused element when it closes. @@ -138,62 +124,77 @@ const ModalMarkup = React.createClass({ enforceFocus: React.PropTypes.bool }, - getDefaultProps() { + getDefaultProps(){ return { bsClass: 'modal', + show: false, + animation: true, backdrop: true, keyboard: true, - animation: true, - closeButton: true, - autoFocus: true, enforceFocus: true }; }, getInitialState(){ - return { }; + return {exited: !this.props.show}; }, render() { - let state = this.state; - let modalStyle = { ...state.dialogStyles, display: 'block'}; - let dialogClasses = this.getBsClassSet(); + let { children, animation, backdrop, ...props } = this.props; + let { onExit, onExiting, onEnter, onEntering, onEntered } = props; - delete dialogClasses.modal; - dialogClasses['modal-dialog'] = true; + let show = !!props.show; - let classes = { - modal: true, - in: this.props.show && !this.props.animation - }; + const mountModal = show || (animation && !this.state.exited); + if (!mountModal) { + return null; + } let modal = ( -