diff options
author | Samy Pesse <samypesse@gmail.com> | 2016-10-13 13:35:59 +0200 |
---|---|---|
committer | Samy Pesse <samypesse@gmail.com> | 2016-10-13 13:35:59 +0200 |
commit | da8c78b3c82bcf8c5e3dad2701fedb21fc10b0b4 (patch) | |
tree | ce5c6d7086d2c3f8a96bd29ea9c72bdf336b3e08 | |
parent | c42c5897fee1841d2be0207faeda81bc42f250e2 (diff) | |
download | gitbook-da8c78b3c82bcf8c5e3dad2701fedb21fc10b0b4.zip gitbook-da8c78b3c82bcf8c5e3dad2701fedb21fc10b0b4.tar.gz gitbook-da8c78b3c82bcf8c5e3dad2701fedb21fc10b0b4.tar.bz2 |
Refactor Backdrop, Hotkeys and Dropdown
-rw-r--r-- | packages/gitbook-core/src/components/Backdrop.js | 34 | ||||
-rw-r--r-- | packages/gitbook-core/src/components/Dropdown.js | 57 | ||||
-rw-r--r-- | packages/gitbook-core/src/components/HotKeys.js | 53 | ||||
-rw-r--r-- | packages/gitbook-core/src/index.js | 2 | ||||
-rw-r--r-- | packages/gitbook-plugin-sharing/src/components/ShareButton.js | 25 |
5 files changed, 97 insertions, 74 deletions
diff --git a/packages/gitbook-core/src/components/Backdrop.js b/packages/gitbook-core/src/components/Backdrop.js index 18f3c4d..7b34b0d 100644 --- a/packages/gitbook-core/src/components/Backdrop.js +++ b/packages/gitbook-core/src/components/Backdrop.js @@ -1,17 +1,19 @@ -const React = require('react'); +const React = require('react'); +const HotKeys = require('./HotKeys'); /** * Backdrop for modals, dropdown, etc. that covers the whole screen - * and handles click. + * and handles click and pressing escape. * - * <Backdrop onClick={onCloseModal} /> + * <Backdrop onClose={onCloseModal} /> */ const Backdrop = React.createClass({ propTypes: { - // Callback when backdrop is clicked - onClick: React.PropTypes.func.isRequired, + // Callback when backdrop is closed + onClose: React.PropTypes.func.isRequired, // Z-index for the backdrop - zIndex: React.PropTypes.number + zIndex: React.PropTypes.number, + children: React.PropTypes.node }, getDefaultProps() { @@ -20,8 +22,17 @@ const Backdrop = React.createClass({ }; }, + onClick(event) { + const { onClose } = this.props; + + event.preventDefault(); + event.stopPropagation(); + + onClose(); + }, + render() { - const { zIndex, onClick } = this.props; + const { zIndex, children, onClose } = this.props; const style = { zIndex, position: 'fixed', @@ -30,8 +41,15 @@ const Backdrop = React.createClass({ width: '100%', height: '100%' }; + const keyMap = { + 'escape': onClose + }; - return <div style={style} onClick={onClick}></div>; + return ( + <HotKeys keyMap={keyMap}> + <div style={style} onClick={this.onClick}>{children}</div> + </HotKeys> + ); } }); diff --git a/packages/gitbook-core/src/components/Dropdown.js b/packages/gitbook-core/src/components/Dropdown.js index f43a6fc..68fb619 100644 --- a/packages/gitbook-core/src/components/Dropdown.js +++ b/packages/gitbook-core/src/components/Dropdown.js @@ -1,8 +1,6 @@ const React = require('react'); const classNames = require('classnames'); -const Backdrop = require('./Backdrop'); - /** * Dropdown to display a menu * @@ -10,7 +8,7 @@ const Backdrop = require('./Backdrop'); * * <Button /> * - * <Dropdown.Menu open={this.state.open}> + * <Dropdown.Menu> * <Dropdown.Item href={...}> ... </Dropdown.Item> * <Dropdown.Item onClick={...}> ... </Dropdown.Item> * @@ -27,21 +25,22 @@ const Backdrop = require('./Backdrop'); const DropdownContainer = React.createClass({ propTypes: { className: React.PropTypes.string, - span: React.PropTypes.bool, children: React.PropTypes.node }, render() { - let { className, span, children } = this.props; + let { className, children } = this.props; className = classNames( 'GitBook-Dropdown', className ); - return span ? - <span className={className}>{children}</span> - : <div className={className}>{children}</div>; + return ( + <div className={className}> + {children} + </div> + ); } }); @@ -56,31 +55,34 @@ const DropdownItem = React.createClass({ href: React.PropTypes.string }, - onClick(e) { - if (!this.props.href) { - e.preventDefault(); - e.stopPropagation(); + onClick(event) { + const { onClick, href } = this.props; + + if (href) { + return; + } + + event.preventDefault(); + event.stopPropagation(); - if (this.props.onClick) this.props.onClick(); + if (onClick) { + onClick(); } }, render() { const { children, href, - onClick, // eslint-disable-line no-unused-vars ...otherProps } = this.props; + delete otherProps.onCLick; - let inner = [], submenu = []; - submenu = filterChildren(children, isDropdownMenu); - inner = filterChildren(children, (child) => !isDropdownMenu(child)); + const submenu = filterChildren(children, isDropdownMenu); + const inner = filterChildren(children, (child) => !isDropdownMenu(child)); return ( <li className="GitBook-DropdownItem"> - <a href={href || '#'} - onClick={this.onClick} - {...otherProps} > + <a href={href || '#'} onClick={this.onClick} {...otherProps} > {inner} </a> {submenu} @@ -108,20 +110,16 @@ function filterChildren(children, predicate) { const DropdownMenu = React.createClass({ propTypes: { className: React.PropTypes.string, - children: React.PropTypes.node, - open: React.PropTypes.bool + children: React.PropTypes.node }, render() { - const { open } = this.props; - const className = classNames( - 'GitBook-DropdownMenu', - { 'GitBook-DropdownMenu-open': open } - ); + let { className, children } = this.props; + className = classNames('GitBook-DropdownMenu', className); return ( <ul className={className}> - {this.props.children} + {children} </ul> ); } @@ -134,8 +132,7 @@ function isDropdownMenu(child) { const Dropdown = { Item: DropdownItem, Menu: DropdownMenu, - Container: DropdownContainer, - Backdrop + Container: DropdownContainer }; module.exports = Dropdown; diff --git a/packages/gitbook-core/src/components/HotKeys.js b/packages/gitbook-core/src/components/HotKeys.js index c2c67c8..0d6fb8d 100644 --- a/packages/gitbook-core/src/components/HotKeys.js +++ b/packages/gitbook-core/src/components/HotKeys.js @@ -1,52 +1,55 @@ const React = require('react'); const Mousetrap = require('mousetrap'); -const { string, node, func, shape, arrayOf } = React.PropTypes; - -const bindingShape = shape({ - // A key "escape", a combination of key "mod+s", or a key sequence "ctrl+x ctrl+s" - key: string.isRequired, - // function (event) {} - handler: func.isRequired -}); +const { Map } = require('immutable'); /** * Defines hotkeys globally when this component is mounted. * - * keymap = [{ - * key: 'escape', - * handler: (e) => quit() - * }, { - * key: 'mod+s', - * handler: (e) => save() - * }] + * keyMap = { + * 'escape': (e) => quit() + * 'mod+s': (e) => save() + * } * - * <HotKeys keymap={keymap}> + * <HotKeys keyMap={keyMap}> * < ... /> * </HotKeys> */ const HotKeys = React.createClass({ propTypes: { - children: node.isRequired, - keymap: arrayOf(bindingShape) + children: React.PropTypes.node.isRequired, + keyMap: React.PropTypes.objectOf(React.PropTypes.func) }, getDefaultProps() { - return { keymap: [] }; + return { keyMap: [] }; }, - componentDidMount() { - this.props.keymap.forEach((binding) => { - Mousetrap.bind(binding.key, binding.handler); + updateBindings(keyMap) { + Map(keyMap).forEach((handler, key) => { + Mousetrap.bind(key, handler); }); }, - componentWillUnmount() { - this.props.keymap.forEach((binding) => { - Mousetrap.unbind(binding.key, binding.handler); + clearBindings(keyMap) { + Map(keyMap).forEach((handler, key) => { + Mousetrap.unbind(key, handler); }); }, + componentDidMount() { + this.updateBindings(this.props.keyMap); + }, + + componentDidUpdate(prevProps) { + this.clearBindings(prevProps.keyMap); + this.updateBindings(this.props.keyMap); + }, + + componentWillUnmount() { + this.clearBindings(this.props.keyMap); + }, + render() { // Simply render the only child return React.Children.only(this.props.children); diff --git a/packages/gitbook-core/src/index.js b/packages/gitbook-core/src/index.js index f820599..840fffb 100644 --- a/packages/gitbook-core/src/index.js +++ b/packages/gitbook-core/src/index.js @@ -16,6 +16,7 @@ const HotKeys = require('./components/HotKeys'); const Button = require('./components/Button'); const ButtonGroup = require('./components/ButtonGroup'); const Dropdown = require('./components/Dropdown'); +const Backdrop = require('./components/Backdrop'); const I18nProvider = require('./components/I18nProvider'); const ACTIONS = require('./actions/TYPES'); @@ -56,6 +57,7 @@ module.exports = { Button, ButtonGroup, Dropdown, + Backdrop, // Utilities Shapes, // Librairies diff --git a/packages/gitbook-plugin-sharing/src/components/ShareButton.js b/packages/gitbook-plugin-sharing/src/components/ShareButton.js index 5a6cd6e..6757d67 100644 --- a/packages/gitbook-plugin-sharing/src/components/ShareButton.js +++ b/packages/gitbook-plugin-sharing/src/components/ShareButton.js @@ -1,5 +1,5 @@ const GitBook = require('gitbook-core'); -const { React, Dropdown } = GitBook; +const { React, Dropdown, Backdrop } = GitBook; const SITES = require('../SITES'); @@ -15,17 +15,13 @@ const ShareButton = React.createClass({ }, onToggle() { - this.setState({ open: !this.state.open }); + const { open } = this.state; + this.setState({ open: !open }); }, render() { const { siteIds, onShare } = this.props; - - const items = siteIds.map((id) => ( - <Dropdown.Item onClick={() => onShare(SITES[id])} key={id}> - {SITES[id].label} - </Dropdown.Item> - )); + const { open } = this.state; return ( <Dropdown.Container> @@ -33,9 +29,16 @@ const ShareButton = React.createClass({ <GitBook.Icon id="share-alt" /> </GitBook.Button> - <Dropdown.Menu open={this.state.open}> - {items} - </Dropdown.Menu> + {open ? ( + <Backdrop onClose={this.onToggle}> + <Dropdown.Menu> + {siteIds.map((id) => ( + <Dropdown.Item onClick={() => onShare(SITES[id])} key={id}> + {SITES[id].label} + </Dropdown.Item> + ))} + </Dropdown.Menu> + </Backdrop>) : null} </Dropdown.Container> ); } |