Skip to content

Commit

Permalink
Merge pull request #1333 from shockey/bug/1332-standalone-menus
Browse files Browse the repository at this point in the history
Bug/1332 standalone menus
  • Loading branch information
shockey authored May 15, 2017
2 parents e19f7d5 + ee483a4 commit aae7b42
Show file tree
Hide file tree
Showing 10 changed files with 213,316 additions and 159 deletions.
143,097 changes: 142,994 additions & 103 deletions dist/swagger-editor-bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/swagger-editor-bundle.js.map

Large diffs are not rendered by default.

47,905 changes: 47,864 additions & 41 deletions dist/swagger-editor-standalone-preset.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/swagger-editor-standalone-preset.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/swagger-editor.js

Large diffs are not rendered by default.

22,295 changes: 22,286 additions & 9 deletions dist/validation.worker.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/validation.worker.js.map

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
},
"dependencies": {
"boron": "^0.2.3",
"classnames": "^2.1.3",
"immutable": "^3.x.x",
"js-yaml": "^3.5.5",
"json-beautify": "^1.0.1",
Expand All @@ -51,6 +52,7 @@
"react-dom": "^15.x",
"react-file-download": "^0.3.2",
"react-redux": "^4.x.x",
"react-transition-group": "^1.1.1",
"redux": "^3.x.x",
"swagger-client": "~3.0.10",
"swagger-ui": "^3.0.9",
Expand Down
164 changes: 164 additions & 0 deletions src/standalone/topbar/DropdownMenu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// Adapted from https://github.com/mlaursen/react-dd-menu/blob/master/src/js/DropdownMenu.js

/* eslint react/no-find-dom-node: 0 */

import React, { PureComponent, PropTypes } from "react"
import ReactDOM from "react-dom"
import CSSTransitionGroup from "react-transition-group/CSSTransitionGroup"
import classnames from "classnames"

const TAB = 9
const SPACEBAR = 32
const ALIGNMENTS = ["center", "right", "left"]
const MENU_SIZES = ["sm", "md", "lg", "xl"]


export default class DropdownMenu extends PureComponent {
static propTypes = {
isOpen: PropTypes.bool.isRequired,
close: PropTypes.func.isRequired,
toggle: PropTypes.node.isRequired,
children: PropTypes.node,
inverse: PropTypes.bool,
align: PropTypes.oneOf(ALIGNMENTS),
animAlign: PropTypes.oneOf(ALIGNMENTS),
textAlign: PropTypes.oneOf(ALIGNMENTS),
menuAlign: PropTypes.oneOf(ALIGNMENTS),
className: PropTypes.string,
size: PropTypes.oneOf(MENU_SIZES),
upwards: PropTypes.bool,
animate: PropTypes.bool,
enterTimeout: PropTypes.number,
leaveTimeout: PropTypes.number,
closeOnInsideClick: PropTypes.bool,
closeOnOutsideClick: PropTypes.bool,
};

static defaultProps = {
inverse: false,
align: "center",
animAlign: null,
textAlign: null,
menuAlign: null,
className: null,
size: null,
upwards: false,
animate: true,
enterTimeout: 150,
leaveTimeout: 150,
closeOnInsideClick: true,
closeOnOutsideClick: true,
};

static MENU_SIZES = MENU_SIZES;
static ALIGNMENTS = ALIGNMENTS;

componentDidUpdate(prevProps) {
if(this.props.isOpen === prevProps.isOpen) {
return
}

const menuItems = ReactDOM.findDOMNode(this).querySelector(".dd-menu > .dd-menu-items")
if(this.props.isOpen && !prevProps.isOpen) {
this.lastWindowClickEvent = this.handleClickOutside
document.addEventListener("click", this.lastWindowClickEvent)
if(this.props.closeOnInsideClick) {
menuItems.addEventListener("click", this.props.close)
}
menuItems.addEventListener("onkeydown", this.close)
} else if(!this.props.isOpen && prevProps.isOpen) {
document.removeEventListener("click", this.lastWindowClickEvent)
if(prevProps.closeOnInsideClick) {
menuItems.removeEventListener("click", this.props.close)
}
menuItems.removeEventListener("onkeydown", this.close)

this.lastWindowClickEvent = null
}
}

componentWillUnmount() {
if(this.lastWindowClickEvent) {
document.removeEventListener("click", this.lastWindowClickEvent)
}
}

close = (e) => {
const key = e.which || e.keyCode
if(key === SPACEBAR) {
this.props.close()
e.preventDefault()
}
};

handleClickOutside = (e) => {
if(!this.props.closeOnOutsideClick) {
return
}

const node = ReactDOM.findDOMNode(this)
let target = e.target

while(target.parentNode) {
if(target === node) {
return
}

target = target.parentNode
}

this.props.close(e)
};

handleKeyDown = (e) => {
const key = e.which || e.keyCode
if(key !== TAB) {
return
}

const items = ReactDOM.findDOMNode(this).querySelectorAll("button,a")
const id = e.shiftKey ? 1 : items.length - 1

if(e.target === items[id]) {
this.props.close(e)
}
};


render() {
const { menuAlign, align, inverse, size, className } = this.props

const menuClassName = classnames(
"dd-menu",
`dd-menu-${menuAlign || align}`,
{ "dd-menu-inverse": inverse },
className,
size ? ("dd-menu-" + size) : null
)

const { textAlign, upwards, animAlign, animate, enterTimeout, leaveTimeout } = this.props

const listClassName = "dd-items-" + (textAlign || align)
const transitionProps = {
transitionName: "grow-from-" + (upwards ? "up-" : "") + (animAlign || align),
component: "div",
className: classnames("dd-menu-items", { "dd-items-upwards": upwards }),
onKeyDown: this.handleKeyDown,
transitionEnter: animate,
transitionLeave: animate,
transitionEnterTimeout: enterTimeout,
transitionLeaveTimeout: leaveTimeout,
}

return (
<div className={menuClassName}>
{this.props.toggle}
<CSSTransitionGroup {...transitionProps}>
{this.props.isOpen &&
<ul key="items" className={listClassName}>{this.props.children}</ul>
}
</CSSTransitionGroup>
</div>
)
}
}
4 changes: 2 additions & 2 deletions src/standalone/topbar/topbar.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { PropTypes } from "react"
import Swagger from "swagger-client"
import "whatwg-fetch"
import DropdownMenu from "react-dd-menu"
import DropdownMenu from "./DropdownMenu"
import Modal from "boron/DropModal"
import downloadFile from "react-file-download"
import YAML from "js-yaml"
Expand Down Expand Up @@ -164,7 +164,7 @@ export default class Topbar extends React.Component {
let stateKey = `is${name}MenuOpen`
let toggleFn = () => this.setState({ [stateKey]: !this.state[stateKey] })
return {
isOpen: this.state[stateKey],
isOpen: !!this.state[stateKey],
close: () => this.setState({ [stateKey]: false }),
align: "left",
toggle: <span className="menu-item" onClick={toggleFn}>{ name }</span>
Expand Down

0 comments on commit aae7b42

Please sign in to comment.