Skip to content

Commit

Permalink
[chore] passing lint...
Browse files Browse the repository at this point in the history
  • Loading branch information
diasbruno committed Jun 15, 2017
1 parent a5cc01b commit ba2c124
Show file tree
Hide file tree
Showing 13 changed files with 347 additions and 277 deletions.
19 changes: 13 additions & 6 deletions .eslintrc.js → .eslintrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
{
"env": {
"es6": true,
"browser": true
Expand All @@ -13,13 +13,20 @@ module.exports = {
"sourceType": "module"
},
"parser": "babel-eslint",
rules: {
"rules": {
"quotes": [0],
"comma-dangle": [2, "only-multiline"],
"max-len": [1, {"code": 140}],
"max-len": [1, {"code": 80}],
"no-unused-expressions": [0],
"no-continue": [0],
"no-plusplus": [0],
"space-before-function-paren": [2, "always"],
"func-names": [0],
"arrow-parens": [0],
"space-before-function-paren": [0],
"import/no-extraneous-dependencies": [2, {"devDependencies": true}],
"jsx-a11y/no-static-element-interactions": [0],
"react/no-find-dom-node": [0],
"react/jsx-closing-bracket-location": [0],
"react/jsx-filename-extension": ["error", {"extensions": [".js"]}]
},
};
}
}
90 changes: 52 additions & 38 deletions lib/components/Modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,37 @@ import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import ExecutionEnvironment from 'exenv';
import ModalPortal from './ModalPortal';
import elementClass from 'element-class';
import ModalPortal from './ModalPortal';
import * as ariaAppHider from '../helpers/ariaAppHider';
import * as refCount from '../helpers/refCount';

const EE = ExecutionEnvironment;
const renderSubtreeIntoContainer = ReactDOM.unstable_renderSubtreeIntoContainer;

const SafeHTMLElement = ExecutionEnvironment.canUseDOM ? window.HTMLElement : {};
let AppElement = ExecutionEnvironment.canUseDOM ? document.body : {appendChild: function() {}};
const SafeHTMLElement = EE.canUseDOM ? window.HTMLElement : {};
const AppElement = EE.canUseDOM ? document.body : { appendChild() {} };

function getParentElement(parentSelector) {
return parentSelector();
}

export default class Modal extends Component {
static setAppElement = function(element) {
AppElement = ariaAppHider.setElement(element);
};
static setAppElement(element) {
ariaAppHider.setElement(element || AppElement);
}

static injectCSS = function() {
"production" !== process.env.NODE_ENV
&& console.warn('React-Modal: injectCSS has been deprecated ' +
'and no longer has any effect. It will be removed in a later version');
};
/* eslint-disable no-console */
static injectCSS() {
(process.env.NODE_ENV !== "production")
&& console.warn(
'React-Modal: injectCSS has been deprecated ' +
'and no longer has any effect. It will be removed in a later version'
);
}
/* eslint-enable no-console */

/* eslint-disable react/no-unused-prop-types */
static propTypes = {
isOpen: PropTypes.bool.isRequired,
style: PropTypes.shape({
Expand All @@ -35,6 +41,14 @@ export default class Modal extends Component {
}),
portalClassName: PropTypes.string,
bodyOpenClassName: PropTypes.string,
className: PropTypes.oneOfType([
PropTypes.String,
PropTypes.object
]),
overlayClassName: PropTypes.oneOfType([
PropTypes.String,
PropTypes.object
]),
appElement: PropTypes.instanceOf(SafeHTMLElement),
onAfterOpen: PropTypes.func,
onRequestClose: PropTypes.func,
Expand All @@ -45,6 +59,7 @@ export default class Modal extends Component {
role: PropTypes.string,
contentLabel: PropTypes.string.isRequired
};
/* eslint-enable react/no-unused-prop-types */

static defaultProps = {
isOpen: false,
Expand All @@ -53,31 +68,31 @@ export default class Modal extends Component {
ariaHideApp: true,
closeTimeoutMS: 0,
shouldCloseOnOverlayClick: true,
parentSelector: function () { return document.body; }
parentSelector() { return document.body; }
};

static defaultStyles = {
overlay: {
position : 'fixed',
top : 0,
left : 0,
right : 0,
bottom : 0,
backgroundColor : 'rgba(255, 255, 255, 0.75)'
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(255, 255, 255, 0.75)'
},
content: {
position : 'absolute',
top : '40px',
left : '40px',
right : '40px',
bottom : '40px',
border : '1px solid #ccc',
background : '#fff',
overflow : 'auto',
WebkitOverflowScrolling : 'touch',
borderRadius : '4px',
outline : 'none',
padding : '20px'
position: 'absolute',
top: '40px',
left: '40px',
right: '40px',
bottom: '40px',
border: '1px solid #ccc',
background: '#fff',
overflow: 'auto',
WebkitOverflowScrolling: 'touch',
borderRadius: '4px',
outline: 'none',
padding: '20px'
}
};

Expand All @@ -92,12 +107,6 @@ export default class Modal extends Component {
this.renderPortal(this.props);
}

componentWillUpdate(newProps) {
if(newProps.portalClassName !== this.props.portalClassName) {
this.node.className = newProps.portalClassName;
}
}

componentWillReceiveProps(newProps) {
if (newProps.isOpen) refCount.add(this);
if (!newProps.isOpen) refCount.remove(this);
Expand All @@ -112,6 +121,12 @@ export default class Modal extends Component {
this.renderPortal(newProps);
}

componentWillUpdate(newProps) {
if (newProps.portalClassName !== this.props.portalClassName) {
this.node.className = newProps.portalClassName;
}
}

componentWillUnmount() {
if (!this.node) return;

Expand All @@ -132,8 +147,7 @@ export default class Modal extends Component {
this.portal.closeWithTimeout();
}

const that = this;
setTimeout(function() { that.removePortal(); }, closesAt - now);
setTimeout(() => this.removePortal, closesAt - now);
} else {
this.removePortal();
}
Expand Down
128 changes: 79 additions & 49 deletions lib/components/ModalPortal.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Component } from 'react';
import { PropTypes } from 'prop-types';
import * as focusManager from '../helpers/focusManager';
import { scopeTab } from '../helpers/scopeTab';
import scopeTab from '../helpers/scopeTab';

// so that our CSS is statically analyzable
const CLASS_NAMES = {
Expand All @@ -19,6 +20,33 @@ export default class ModalPortal extends Component {
}
};

static propTypes = {
isOpen: PropTypes.bool.isRequired,
defaultStyles: PropTypes.shape({
content: PropTypes.object,
overlay: PropTypes.object
}),
style: PropTypes.shape({
content: PropTypes.object,
overlay: PropTypes.object
}),
className: PropTypes.oneOfType([
PropTypes.String,
PropTypes.object
]),
overlayClassName: PropTypes.oneOfType([
PropTypes.String,
PropTypes.object
]),
onAfterOpen: PropTypes.func,
onRequestClose: PropTypes.func,
closeTimeoutMS: PropTypes.number,
shouldCloseOnOverlayClick: PropTypes.bool,
role: PropTypes.string,
contentLabel: PropTypes.string,
children: PropTypes.node
};

constructor(props) {
super(props);

Expand All @@ -38,10 +66,6 @@ export default class ModalPortal extends Component {
}
}

componentWillUnmount() {
clearTimeout(this.closeTimer);
}

componentWillReceiveProps(newProps) {
// Focus only needs to be set once when the modal is being opened
if (!this.props.isOpen && newProps.isOpen) {
Expand All @@ -59,6 +83,10 @@ export default class ModalPortal extends Component {
}
}

componentWillUnmount() {
clearTimeout(this.closeTimer);
}

setFocusAfterRender = focus => {
this.focusAfterRender = focus;
}
Expand Down Expand Up @@ -93,17 +121,16 @@ export default class ModalPortal extends Component {
}
}

focusContent = () => {
// Don't steal focus from inner elements
if (!this.contentHasFocus()) {
this.refs.content.focus();
}
}
// Don't steal focus from inner elements
focusContent = () => (!this.contentHasFocus()) && this.content.focus();

closeWithTimeout = () => {
const closesAt = Date.now() + this.props.closeTimeoutMS;
this.setState({ beforeClose: true, closesAt: closesAt }, () => {
this.closeTimer = setTimeout(this.closeWithoutTimeout, this.state.closesAt - Date.now());
this.setState({ beforeClose: true, closesAt }, () => {
this.closeTimer = setTimeout(
this.closeWithoutTimeout,
this.state.closesAt - Date.now()
);
});
}

Expand All @@ -117,10 +144,10 @@ export default class ModalPortal extends Component {
}

handleKeyDown = event => {
if (event.keyCode == TAB_KEY) {
scopeTab(this.refs.content, event);
if (event.keyCode === TAB_KEY) {
scopeTab(this.content, event);
}
if (event.keyCode == ESC_KEY) {
if (event.keyCode === ESC_KEY) {
event.preventDefault();
this.requestClose(event);
}
Expand All @@ -145,53 +172,56 @@ export default class ModalPortal extends Component {
this.shouldClose = false;
}

requestClose = event => {
if (this.ownerHandlesClose()) {
this.props.onRequestClose(event);
}
}
requestClose = event =>
this.ownerHandlesClose() && this.props.onRequestClose(event);

ownerHandlesClose = () => {
return this.props.onRequestClose;
}
ownerHandlesClose = () =>
this.props.onRequestClose;

shouldBeClosed = () => {
return !this.state.isOpen && !this.state.beforeClose;
}
shouldBeClosed = () =>
!this.state.isOpen && !this.state.beforeClose;

contentHasFocus = () => {
return document.activeElement === this.refs.content || this.refs.content.contains(document.activeElement);
}
contentHasFocus = () =>
document.activeElement === this.content ||
this.content.contains(document.activeElement);

buildClassName = (which, additional) => {
const classNames = (typeof additional === 'object') ? additional : {
base: CLASS_NAMES[which],
afterOpen: CLASS_NAMES[which] + "--after-open",
beforeClose: CLASS_NAMES[which] + "--before-close"
afterOpen: `${CLASS_NAMES[which]}--after-open`,
beforeClose: `${CLASS_NAMES[which]}--before-close`
};
let className = classNames.base;
if (this.state.afterOpen) { className += " " + classNames.afterOpen; }
if (this.state.beforeClose) { className += " " + classNames.beforeClose; }
return (typeof additional === 'string' && additional) ? [className, additional].join(" ") : className;
if (this.state.afterOpen) {
className = `${className} ${classNames.afterOpen}`;
}
if (this.state.beforeClose) {
className = `${className} ${classNames.beforeClose}`;
}
return (typeof additional === 'string' && additional) ?
`${className} ${additional}` : className;
}

render() {
const contentStyles = this.props.className ? {} : this.props.defaultStyles.content;
const overlayStyles = this.props.overlayClassName ? {} : this.props.defaultStyles.overlay;
const { className, overlayClassName, defaultStyles } = this.props;
const contentStyles = className ? {} : defaultStyles.content;
const overlayStyles = overlayClassName ? {} : defaultStyles.overlay;

return this.shouldBeClosed() ? <div /> : (
<div ref="overlay"
className={this.buildClassName('overlay', this.props.overlayClassName)}
style={{ ...overlayStyles, ...this.props.style.overlay }}
onClick={this.handleOverlayOnClick}>
<div ref="content"
style={{ ...contentStyles, ...this.props.style.content }}
className={this.buildClassName('content', this.props.className)}
tabIndex="-1"
onKeyDown={this.handleKeyDown}
onClick={this.handleContentOnClick}
role={this.props.role}
aria-label={this.props.contentLabel}>
<div
ref={overlay => { this.overlay = overlay; }}
className={this.buildClassName('overlay', overlayClassName)}
style={{ ...overlayStyles, ...this.props.style.overlay }}
onClick={this.handleOverlayOnClick}>
<div
ref={content => { this.content = content; }}
style={{ ...contentStyles, ...this.props.style.content }}
className={this.buildClassName('content', className)}
tabIndex="-1"
onKeyDown={this.handleKeyDown}
onClick={this.handleContentOnClick}
role={this.props.role}
aria-label={this.props.contentLabel}>
{this.props.children}
</div>
</div>
Expand Down
Loading

0 comments on commit ba2c124

Please sign in to comment.