diff --git a/.eslintrc b/.eslintrc.js
similarity index 84%
rename from .eslintrc
rename to .eslintrc.js
index 33105a65..7cc1609c 100644
--- a/.eslintrc
+++ b/.eslintrc.js
@@ -1,9 +1,11 @@
-{
+module.exports = {
"env": {
"es6": true,
"browser": true
},
+
"parser": "babel-eslint",
+
"parserOptions": {
"ecmaVersion": 7,
"ecmaFeatures": {
@@ -11,6 +13,7 @@
},
"sourceType": "module"
},
+
"settings": {
"react": {
"createClass": "createReactClass",
@@ -19,10 +22,15 @@
},
"propWrapperFunctions": [ "forbidExtraProps" ]
},
- "extends": ["eslint:recommended", "plugin:react/recommended"],
+
+ "extends": ["eslint:recommended", "plugin:react/recommended", "prettier"],
+
+ "plugins": ["prettier"],
+
"globals": {
"process": true
},
+
"rules": {
"quotes": [0],
"comma-dangle": [2, "only-multiline"],
@@ -34,6 +42,7 @@
"arrow-parens": [0],
"space-before-function-paren": [0],
"jsx-a11y/no-static-element-interactions": [0],
+ "prettier/prettier": "error",
"react/no-find-dom-node": [0],
"react/jsx-closing-bracket-location": [0],
"react/require-default-props": 0
diff --git a/package.json b/package.json
index da8b4420..de858454 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
"scripts": {
"start": "./node_modules/.bin/webpack-dev-server --inline --host 127.0.0.1 --content-base examples/",
"test": "cross-env NODE_ENV=test karma start",
- "lint": "eslint src/ spec/"
+ "lint": "eslint src/ specs/"
},
"authors": [
"Ryan Florence"
@@ -33,7 +33,9 @@
"coveralls": "^2.13.1",
"cross-env": "^5.0.1",
"eslint": "^4.8.0",
+ "eslint-config-prettier": "^2.6.0",
"eslint-plugin-jsx-a11y": "^6.0.2",
+ "eslint-plugin-prettier": "^2.3.1",
"eslint-plugin-react": "^7.4.0",
"gitbook-cli": "^2.3.0",
"istanbul-instrumenter-loader": "^3.0.0",
@@ -47,6 +49,7 @@
"karma-webpack": "^2.0.4",
"mocha": "3.5.3",
"npm-run-all": "^4.1.1",
+ "prettier": "^1.7.4",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-router": "^4.2.0",
diff --git a/specs/Modal.events.spec.js b/specs/Modal.events.spec.js
index 7d31aa66..c12d7016 100644
--- a/specs/Modal.events.spec.js
+++ b/specs/Modal.events.spec.js
@@ -1,44 +1,48 @@
/* eslint-env mocha */
-import 'should';
-import sinon from 'sinon';
-import React from 'react';
-import ReactDOM from 'react-dom';
-import TestUtils from 'react-dom/test-utils';
-import Modal from '../src/components/Modal.js';
+import "should";
+import sinon from "sinon";
import {
- moverlay, mcontent,
- clickAt, mouseDownAt, mouseUpAt, escKeyDown, tabKeyDown,
- renderModal, emptyDOM
-} from './helper';
+ moverlay,
+ mcontent,
+ clickAt,
+ mouseDownAt,
+ mouseUpAt,
+ escKeyDown,
+ tabKeyDown,
+ renderModal,
+ emptyDOM
+} from "./helper";
export default () => {
- afterEach('Unmount modal', emptyDOM);
+ afterEach("Unmount modal", emptyDOM);
- it('should trigger the onAfterOpen callback', () => {
+ it("should trigger the onAfterOpen callback", () => {
const afterOpenCallback = sinon.spy();
renderModal({ isOpen: true, onAfterOpen: afterOpenCallback });
afterOpenCallback.called.should.be.ok();
});
- it('keeps focus inside the modal when child has no tabbable elements', () => {
+ it("keeps focus inside the modal when child has no tabbable elements", () => {
let tabPrevented = false;
- const modal = renderModal({ isOpen: true }, 'hello');
+ const modal = renderModal({ isOpen: true }, "hello");
const content = mcontent(modal);
document.activeElement.should.be.eql(content);
tabKeyDown(content, {
- preventDefault() { tabPrevented = true; }
+ preventDefault() {
+ tabPrevented = true;
+ }
});
tabPrevented.should.be.eql(true);
});
- it('handles case when child has no tabbable elements', () => {
- const modal = renderModal({ isOpen: true }, 'hello');
+ it("handles case when child has no tabbable elements", () => {
+ const modal = renderModal({ isOpen: true }, "hello");
const content = mcontent(modal);
tabKeyDown(content);
document.activeElement.should.be.eql(content);
});
- it('should close on Esc key event', () => {
+ it("should close on Esc key event", () => {
const requestCloseCallback = sinon.spy();
const modal = renderModal({
isOpen: true,
@@ -52,8 +56,8 @@ export default () => {
ev.should.be.ok();
});
- describe('shouldCloseOnoverlayClick', () => {
- it('when false, click on overlay should not close', () => {
+ describe("shouldCloseOnoverlayClick", () => {
+ it("when false, click on overlay should not close", () => {
const requestCloseCallback = sinon.spy();
const modal = renderModal({
isOpen: true,
@@ -64,7 +68,7 @@ export default () => {
requestCloseCallback.called.should.not.be.ok();
});
- it('when true, click on overlay must close', () => {
+ it("when true, click on overlay must close", () => {
const requestCloseCallback = sinon.spy();
const modal = renderModal({
isOpen: true,
@@ -75,7 +79,7 @@ export default () => {
requestCloseCallback.called.should.be.ok();
});
- it('overlay mouse down and content mouse up, should not close', () => {
+ it("overlay mouse down and content mouse up, should not close", () => {
const requestCloseCallback = sinon.spy();
const modal = renderModal({
isOpen: true,
@@ -87,7 +91,7 @@ export default () => {
requestCloseCallback.called.should.not.be.ok();
});
- it('content mouse down and overlay mouse up, should not close', () => {
+ it("content mouse down and overlay mouse up, should not close", () => {
const requestCloseCallback = sinon.spy();
const modal = renderModal({
isOpen: true,
@@ -100,20 +104,20 @@ export default () => {
});
});
- it('should not stop event propagation', () => {
+ it("should not stop event propagation", () => {
let hasPropagated = false;
const modal = renderModal({
isOpen: true,
shouldCloseOnOverlayClick: true
});
- window.addEventListener('click', () => {
+ window.addEventListener("click", () => {
hasPropagated = true;
});
- moverlay(modal).dispatchEvent(new MouseEvent('click', { bubbles: true }));
+ moverlay(modal).dispatchEvent(new MouseEvent("click", { bubbles: true }));
hasPropagated.should.be.ok();
});
- it('verify event passing on overlay click', () => {
+ it("verify event passing on overlay click", () => {
const requestCloseCallback = sinon.spy();
const modal = renderModal({
isOpen: true,
@@ -123,7 +127,7 @@ export default () => {
// click the overlay
clickAt(moverlay(modal), {
// Used to test that this was the event received
- fakeData: 'ABC'
+ fakeData: "ABC"
});
requestCloseCallback.called.should.be.ok();
// Check if event is passed to onRequestClose callback.
diff --git a/specs/Modal.spec.js b/specs/Modal.spec.js
index e8b637f1..5da1371a 100644
--- a/specs/Modal.spec.js
+++ b/specs/Modal.spec.js
@@ -1,44 +1,47 @@
/* eslint-env mocha */
-import 'should';
-import should from 'should';
-import React, { Component } from 'react';
-import ReactDOM from 'react-dom';
-import TestUtils from 'react-dom/test-utils';
-import Modal from 'react-modal';
-import * as ariaAppHider from 'react-modal/helpers/ariaAppHider';
+import "should";
+import should from "should";
+import React, { Component } from "react";
+import ReactDOM from "react-dom";
+import Modal from "react-modal";
+import * as ariaAppHider from "react-modal/helpers/ariaAppHider";
import {
isBodyWithReactModalOpenClass,
contentAttribute,
- mcontent, moverlay,
+ mcontent,
+ moverlay,
escKeyDown,
- renderModal, unmountModal, emptyDOM
-} from './helper';
+ renderModal,
+ unmountModal,
+ emptyDOM
+} from "./helper";
export default () => {
- afterEach('check if test cleaned up rendered modals', emptyDOM);
+ afterEach("check if test cleaned up rendered modals", emptyDOM);
- it('scopes tab navigation to the modal');
- it('focuses the last focused element when tabbing in from browser chrome');
- it('renders children [tested indirectly]');
+ it("scopes tab navigation to the modal");
+ it("focuses the last focused element when tabbing in from browser chrome");
+ it("renders children [tested indirectly]");
- it('can be open initially', () => {
- const modal = renderModal({ isOpen: true }, 'hello');
+ it("can be open initially", () => {
+ const modal = renderModal({ isOpen: true }, "hello");
mcontent(modal).should.be.ok();
});
- it('can be closed initially', () => {
- const modal = renderModal({}, 'hello');
+ it("can be closed initially", () => {
+ const modal = renderModal({}, "hello");
should(ReactDOM.findDOMNode(mcontent(modal))).not.be.ok();
});
- it('doesn\'t render the portal if modal is closed', () => {
- const modal = renderModal({}, 'hello');
+ it("doesn't render the portal if modal is closed", () => {
+ const modal = renderModal({}, "hello");
should(ReactDOM.findDOMNode(modal.portal)).not.be.ok();
});
- it('has default props', () => {
- const node = document.createElement('div');
- Modal.setAppElement(document.createElement('div'));
+ it("has default props", () => {
+ const node = document.createElement("div");
+ Modal.setAppElement(document.createElement("div"));
+ // eslint-disable-next-line react/no-render-return-value
const modal = ReactDOM.render(, node);
const props = modal.props;
props.isOpen.should.not.be.ok();
@@ -48,21 +51,19 @@ export default () => {
props.shouldCloseOnOverlayClick.should.be.ok();
ReactDOM.unmountComponentAtNode(node);
ariaAppHider.resetForTesting();
- Modal.setAppElement(document.body); // restore default
+ Modal.setAppElement(document.body); // restore default
});
- it('accepts appElement as a prop', () => {
- const el = document.createElement('div');
- const node = document.createElement('div');
- ReactDOM.render((
-
- ), node);
- el.getAttribute('aria-hidden').should.be.eql('true');
+ it("accepts appElement as a prop", () => {
+ const el = document.createElement("div");
+ const node = document.createElement("div");
+ ReactDOM.render(, node);
+ el.getAttribute("aria-hidden").should.be.eql("true");
ReactDOM.unmountComponentAtNode(node);
});
- it('renders into the body, not in context', () => {
- const node = document.createElement('div');
+ it("renders into the body, not in context", () => {
+ const node = document.createElement("div");
class App extends Component {
render() {
return (
@@ -76,47 +77,48 @@ export default () => {
}
Modal.setAppElement(node);
ReactDOM.render(, node);
- document.body.querySelector(
- '.ReactModalPortal'
- ).parentNode.should.be.eql(
- document.body
- );
+ document.body
+ .querySelector(".ReactModalPortal")
+ .parentNode.should.be.eql(document.body);
ReactDOM.unmountComponentAtNode(node);
});
- it ('default parentSelector should be document.body.', () => {
+ it("default parentSelector should be document.body.", () => {
const modal = renderModal({ isOpen: true });
modal.props.parentSelector().should.be.eql(document.body);
});
- it('renders the modal content with a dialog aria role when provided ', () => {
- const child = 'I am a child of Modal, and he has sent me here...';
- const modal = renderModal({ isOpen: true, role: 'dialog' }, child);
- contentAttribute(modal, 'role').should.be.eql('dialog');
+ it("renders the modal content with a dialog aria role when provided ", () => {
+ const child = "I am a child of Modal, and he has sent me here...";
+ const modal = renderModal({ isOpen: true, role: "dialog" }, child);
+ contentAttribute(modal, "role").should.be.eql("dialog");
});
- it('sets aria-label based on the contentLabel prop', () => {
- const child = 'I am a child of Modal, and he has sent me here...';
- const modal = renderModal({
- isOpen: true,
- contentLabel: 'Special Modal'
- }, child);
+ it("sets aria-label based on the contentLabel prop", () => {
+ const child = "I am a child of Modal, and he has sent me here...";
+ const modal = renderModal(
+ {
+ isOpen: true,
+ contentLabel: "Special Modal"
+ },
+ child
+ );
- contentAttribute(modal, 'aria-label').should.be.eql('Special Modal');
+ contentAttribute(modal, "aria-label").should.be.eql("Special Modal");
});
- it('removes the portal node', () => {
- const modal = renderModal({ isOpen: true }, 'hello');
+ it("removes the portal node", () => {
+ renderModal({ isOpen: true }, "hello");
unmountModal();
- should(document.querySelector('.ReactModalPortal')).not.be.ok();
+ should(document.querySelector(".ReactModalPortal")).not.be.ok();
});
- it('removes the portal node after closeTimeoutMS', done => {
+ it("removes the portal node after closeTimeoutMS", done => {
const closeTimeoutMS = 100;
- renderModal({ isOpen: true, closeTimeoutMS }, 'hello');
+ renderModal({ isOpen: true, closeTimeoutMS }, "hello");
function checkDOM(count) {
- const portal = document.querySelectorAll('.ReactModalPortal');
+ const portal = document.querySelectorAll(".ReactModalPortal");
portal.length.should.be.eql(count);
}
@@ -132,132 +134,145 @@ export default () => {
}, closeTimeoutMS);
});
- it('focuses the modal content by default', () => {
+ it("focuses the modal content by default", () => {
const modal = renderModal({ isOpen: true }, null);
document.activeElement.should.be.eql(mcontent(modal));
});
- it('does not focus the modal content when shouldFocusAfterRender is false', () => {
- const modal = renderModal({ isOpen: true, shouldFocusAfterRender: false }, null);
+ it("does not focus the modal content when shouldFocusAfterRender is false", () => {
+ const modal = renderModal(
+ { isOpen: true, shouldFocusAfterRender: false },
+ null
+ );
document.activeElement.should.not.be.eql(mcontent(modal));
});
- it('give back focus to previous element or modal.', done => {
- function cleanup () {
+ it("give back focus to previous element or modal.", done => {
+ function cleanup() {
unmountModal();
done();
}
- const modalA = renderModal({
- isOpen: true,
- className: 'modal-a',
- onRequestClose: cleanup
- }, null);
+ const modalA = renderModal(
+ {
+ isOpen: true,
+ className: "modal-a",
+ onRequestClose: cleanup
+ },
+ null
+ );
const modalContent = mcontent(modalA);
document.activeElement.should.be.eql(modalContent);
- const modalB = renderModal({
- isOpen: true,
- className: 'modal-b',
- onRequestClose() {
- const modalContent = mcontent(modalB);
- document.activeElement.should.be.eql(mcontent(modalA));
- escKeyDown(modalContent);
- document.activeElement.should.be.eql(modalContent);
- }
- }, null);
+ const modalB = renderModal(
+ {
+ isOpen: true,
+ className: "modal-b",
+ onRequestClose() {
+ const modalContent = mcontent(modalB);
+ document.activeElement.should.be.eql(mcontent(modalA));
+ escKeyDown(modalContent);
+ document.activeElement.should.be.eql(modalContent);
+ }
+ },
+ null
+ );
escKeyDown(modalContent);
});
- xit('does not steel focus when a descendent is already focused', () => {
+ xit("does not steel focus when a descendent is already focused", () => {
let content;
const input = (
- { el && el.focus(); content = el; }} />
+ {
+ el && el.focus();
+ content = el;
+ }}
+ />
);
renderModal({ isOpen: true }, input, () => {
document.activeElement.should.be.eql(content);
});
});
- it('supports portalClassName', () => {
+ it("supports portalClassName", () => {
const modal = renderModal({
isOpen: true,
- portalClassName: 'myPortalClass'
+ portalClassName: "myPortalClass"
});
- modal.node.className.includes('myPortalClass').should.be.ok();
+ modal.node.className.includes("myPortalClass").should.be.ok();
});
- it('supports custom className', () => {
- const modal = renderModal({ isOpen: true, className: 'myClass' });
- mcontent(modal).className.includes('myClass').should.be.ok();
+ it("supports custom className", () => {
+ const modal = renderModal({ isOpen: true, className: "myClass" });
+ mcontent(modal)
+ .className.includes("myClass")
+ .should.be.ok();
});
- it('supports overlayClassName', () => {
+ it("supports overlayClassName", () => {
const modal = renderModal({
isOpen: true,
- overlayClassName: 'myOverlayClass'
+ overlayClassName: "myOverlayClass"
});
- moverlay(modal).className.includes('myOverlayClass').should.be.ok();
+ moverlay(modal)
+ .className.includes("myOverlayClass")
+ .should.be.ok();
});
- it('overrides content classes with custom object className', () => {
+ it("overrides content classes with custom object className", () => {
const modal = renderModal({
isOpen: true,
className: {
- base: 'myClass',
- afterOpen: 'myClass_after-open',
- beforeClose: 'myClass_before-close'
+ base: "myClass",
+ afterOpen: "myClass_after-open",
+ beforeClose: "myClass_before-close"
}
});
- mcontent(modal).className.should.be.eql(
- 'myClass myClass_after-open'
- );
+ mcontent(modal).className.should.be.eql("myClass myClass_after-open");
unmountModal();
});
- it('overrides overlay classes with custom object overlayClassName', () => {
+ it("overrides overlay classes with custom object overlayClassName", () => {
const modal = renderModal({
isOpen: true,
overlayClassName: {
- base: 'myOverlayClass',
- afterOpen: 'myOverlayClass_after-open',
- beforeClose: 'myOverlayClass_before-close'
+ base: "myOverlayClass",
+ afterOpen: "myOverlayClass_after-open",
+ beforeClose: "myOverlayClass_before-close"
}
});
moverlay(modal).className.should.be.eql(
- 'myOverlayClass myOverlayClass_after-open'
+ "myOverlayClass myOverlayClass_after-open"
);
unmountModal();
});
- it('supports overriding react modal open class in document.body.', () => {
- const modal = renderModal({
- isOpen: true,
- bodyOpenClassName: 'custom-modal-open'
- });
- (document.body.className.indexOf('custom-modal-open') > -1).should.be.ok();
+ it("supports overriding react modal open class in document.body.", () => {
+ renderModal({ isOpen: true, bodyOpenClassName: "custom-modal-open" });
+ (document.body.className.indexOf("custom-modal-open") > -1).should.be.ok();
});
- it('don\'t append class to document.body if modal is not open', () => {
+ it("don't append class to document.body if modal is not open", () => {
renderModal({ isOpen: false });
isBodyWithReactModalOpenClass().should.not.be.ok();
unmountModal();
});
- it('append class to document.body if modal is open', () => {
+ it("append class to document.body if modal is open", () => {
renderModal({ isOpen: true });
isBodyWithReactModalOpenClass().should.be.ok();
unmountModal();
});
- it('removes class from document.body when unmounted without closing', () => {
+ it("removes class from document.body when unmounted without closing", () => {
renderModal({ isOpen: true });
unmountModal();
isBodyWithReactModalOpenClass().should.not.be.ok();
});
- it('remove class from document.body when no modals opened', () => {
+ it("remove class from document.body when no modals opened", () => {
renderModal({ isOpen: true });
renderModal({ isOpen: true });
isBodyWithReactModalOpenClass().should.be.ok();
@@ -267,93 +282,94 @@ export default () => {
isBodyWithReactModalOpenClass().should.not.be.ok();
});
- it('supports adding/removing multiple document.body classes', () => {
+ it("supports adding/removing multiple document.body classes", () => {
renderModal({
isOpen: true,
- bodyOpenClassName: 'A B C'
+ bodyOpenClassName: "A B C"
});
- document.body.classList.contains('A', 'B', 'C').should.be.ok();
+ document.body.classList.contains("A", "B", "C").should.be.ok();
unmountModal();
- document.body.classList.contains('A', 'B', 'C').should.not.be.ok();
+ document.body.classList.contains("A", "B", "C").should.not.be.ok();
});
- it('does not remove shared classes if more than one modal is open', () => {
+ it("does not remove shared classes if more than one modal is open", () => {
renderModal({
isOpen: true,
- bodyOpenClassName: 'A'
+ bodyOpenClassName: "A"
});
renderModal({
isOpen: true,
- bodyOpenClassName: 'A B'
+ bodyOpenClassName: "A B"
});
- isBodyWithReactModalOpenClass('A B').should.be.ok();
+ isBodyWithReactModalOpenClass("A B").should.be.ok();
unmountModal();
- isBodyWithReactModalOpenClass('A B').should.not.be.ok();
- isBodyWithReactModalOpenClass('A').should.be.ok();
+ isBodyWithReactModalOpenClass("A B").should.not.be.ok();
+ isBodyWithReactModalOpenClass("A").should.be.ok();
unmountModal();
- isBodyWithReactModalOpenClass('A').should.not.be.ok();
+ isBodyWithReactModalOpenClass("A").should.not.be.ok();
});
- it('should not add classes to document.body for unopened modals', () => {
+ it("should not add classes to document.body for unopened modals", () => {
renderModal({ isOpen: true });
isBodyWithReactModalOpenClass().should.be.ok();
- renderModal({ isOpen: false, bodyOpenClassName: 'testBodyClass' });
- isBodyWithReactModalOpenClass('testBodyClass').should.not.be.ok();
+ renderModal({ isOpen: false, bodyOpenClassName: "testBodyClass" });
+ isBodyWithReactModalOpenClass("testBodyClass").should.not.be.ok();
});
- it('should not remove classes from document.body when rendering unopened modal', () => {
+ it("should not remove classes from document.body when rendering unopened modal", () => {
renderModal({ isOpen: true });
isBodyWithReactModalOpenClass().should.be.ok();
- renderModal({ isOpen: false, bodyOpenClassName: 'testBodyClass' });
+ renderModal({ isOpen: false, bodyOpenClassName: "testBodyClass" });
renderModal({ isOpen: false });
- isBodyWithReactModalOpenClass('testBodyClass').should.not.be.ok();
+ isBodyWithReactModalOpenClass("testBodyClass").should.not.be.ok();
isBodyWithReactModalOpenClass().should.be.ok();
renderModal({ isOpen: false });
renderModal({ isOpen: false });
isBodyWithReactModalOpenClass().should.be.ok();
});
- it('additional aria attributes', () => {
- const modal = renderModal({ isOpen: true, aria: { labelledby: "a" }}, 'hello');
- mcontent(modal).getAttribute('aria-labelledby').should.be.eql("a");
+ it("additional aria attributes", () => {
+ const modal = renderModal(
+ { isOpen: true, aria: { labelledby: "a" } },
+ "hello"
+ );
+ mcontent(modal)
+ .getAttribute("aria-labelledby")
+ .should.be.eql("a");
unmountModal();
});
- it('adding/removing aria-hidden without an appElement will try to fallback to document.body', () => {
+ it("adding/removing aria-hidden without an appElement will try to fallback to document.body", () => {
ariaAppHider.documentNotReadyOrSSRTesting();
- const node = document.createElement('div');
- ReactDOM.render((
-
- ), node);
- document.body.getAttribute('aria-hidden').should.be.eql('true');
+ const node = document.createElement("div");
+ ReactDOM.render(, node);
+ document.body.getAttribute("aria-hidden").should.be.eql("true");
ReactDOM.unmountComponentAtNode(node);
- should(document.body.getAttribute('aria-hidden')).not.be.ok();
+ should(document.body.getAttribute("aria-hidden")).not.be.ok();
});
- it('raise an exception if appElement is a selector and no elements were found.', () => {
- should(() => ariaAppHider.setElement('.test')).throw();
+ it("raise an exception if appElement is a selector and no elements were found.", () => {
+ should(() => ariaAppHider.setElement(".test")).throw();
});
- it('removes aria-hidden from appElement when unmounted w/o closing', () => {
- const el = document.createElement('div');
- const node = document.createElement('div');
- ReactDOM.render((
-
- ), node);
- el.getAttribute('aria-hidden').should.be.eql('true');
+ it("removes aria-hidden from appElement when unmounted w/o closing", () => {
+ const el = document.createElement("div");
+ const node = document.createElement("div");
+ ReactDOM.render(, node);
+ el.getAttribute("aria-hidden").should.be.eql("true");
ReactDOM.unmountComponentAtNode(node);
- should(el.getAttribute('aria-hidden')).not.be.ok();
+ should(el.getAttribute("aria-hidden")).not.be.ok();
});
- it('adds --after-open for animations', () => {
+ it("adds --after-open for animations", () => {
const modal = renderModal({ isOpen: true });
const rg = /--after-open/i;
rg.test(mcontent(modal).className).should.be.ok();
rg.test(moverlay(modal).className).should.be.ok();
});
- it('adds --before-close for animations', () => {
+ it("adds --before-close for animations", () => {
const closeTimeoutMS = 50;
const modal = renderModal({
isOpen: true,
@@ -368,7 +384,7 @@ export default () => {
modal.portal.closeWithoutTimeout();
});
- it('should not be open after close with time out and reopen it', () => {
+ it("should not be open after close with time out and reopen it", () => {
const modal = renderModal({
isOpen: true,
closeTimeoutMS: 2000,
@@ -380,26 +396,26 @@ export default () => {
modal.portal.state.isOpen.should.not.be.ok();
});
- it('verify default prop of shouldCloseOnOverlayClick', () => {
+ it("verify default prop of shouldCloseOnOverlayClick", () => {
const modal = renderModal({ isOpen: true });
modal.props.shouldCloseOnOverlayClick.should.be.ok();
});
- it('verify prop of shouldCloseOnOverlayClick', () => {
+ it("verify prop of shouldCloseOnOverlayClick", () => {
const modalOpts = { isOpen: true, shouldCloseOnOverlayClick: false };
const modal = renderModal(modalOpts);
modal.props.shouldCloseOnOverlayClick.should.not.be.ok();
});
- it('keeps the modal in the DOM until closeTimeoutMS elapses', done => {
+ it("keeps the modal in the DOM until closeTimeoutMS elapses", done => {
const closeTimeoutMS = 100;
const modal = renderModal({ isOpen: true, closeTimeoutMS });
modal.portal.closeWithTimeout();
function checkDOM(count) {
- const overlay = document.querySelectorAll('.ReactModal__Overlay');
- const content = document.querySelectorAll('.ReactModal__Content');
+ const overlay = document.querySelectorAll(".ReactModal__Overlay");
+ const content = document.querySelectorAll(".ReactModal__Content");
overlay.length.should.be.eql(count);
content.length.should.be.eql(count);
}
@@ -414,23 +430,25 @@ export default () => {
}, closeTimeoutMS);
});
- xit('shouldn\'t throw if forcibly unmounted during mounting', () => {
+ xit("shouldn't throw if forcibly unmounted during mounting", () => {
/* eslint-disable camelcase, react/prop-types */
class Wrapper extends Component {
- constructor (props) {
+ constructor(props) {
super(props);
this.state = { error: false };
}
- unstable_handleError () {
+ unstable_handleError() {
this.setState({ error: true });
}
- render () {
- return this.state.error ? null :
{ this.props.children }
;
+ render() {
+ return this.state.error ? null : {this.props.children}
;
}
}
/* eslint-enable camelcase, react/prop-types */
- const Throw = () => { throw new Error('reason'); };
+ const Throw = () => {
+ throw new Error("reason");
+ };
const TestCase = () => (
@@ -438,17 +456,18 @@ export default () => {
);
- const currentDiv = document.createElement('div');
+ const currentDiv = document.createElement("div");
document.body.appendChild(currentDiv);
+ // eslint-disable-next-line react/no-render-return-value
const mount = () => ReactDOM.render(, currentDiv);
mount.should.not.throw();
document.body.removeChild(currentDiv);
});
- it('verify that portalClassName is refreshed on component update', () => {
- const node = document.createElement('div');
+ it("verify that portalClassName is refreshed on component update", () => {
+ const node = document.createElement("div");
let modal = null;
class App extends Component {
@@ -458,7 +477,7 @@ export default () => {
}
componentDidMount() {
- modal.node.className.should.be.eql('myPortalClass');
+ modal.node.className.should.be.eql("myPortalClass");
this.setState({
testHasChanged: true
@@ -466,19 +485,24 @@ export default () => {
}
componentDidUpdate() {
- modal.node.className.should.be.eql('myPortalClass-modifier');
+ modal.node.className.should.be.eql("myPortalClass-modifier");
}
render() {
- const portalClassName = this.state.testHasChanged === true ?
- 'myPortalClass-modifier' : 'myPortalClass';
+ const portalClassName =
+ this.state.testHasChanged === true
+ ? "myPortalClass-modifier"
+ : "myPortalClass";
return (
{ modal = modalComponent; }}
+ ref={modalComponent => {
+ modal = modalComponent;
+ }}
isOpen
- portalClassName={portalClassName}>
+ portalClassName={portalClassName}
+ >
Test
diff --git a/specs/Modal.style.spec.js b/specs/Modal.style.spec.js
index 59a8ddf5..2b17355f 100644
--- a/specs/Modal.style.spec.js
+++ b/specs/Modal.style.spec.js
@@ -1,62 +1,53 @@
/* eslint-env mocha */
-import 'should';
-import React from 'react';
-import ReactDOM from 'react-dom';
-import TestUtils from 'react-dom/test-utils';
-import Modal from 'react-modal';
-import * as ariaAppHider from 'react-modal/helpers/ariaAppHider';
-import {
- mcontent, moverlay,
- renderModal, emptyDOM
-} from './helper';
+import "should";
+import Modal from "react-modal";
+import { mcontent, moverlay, renderModal, emptyDOM } from "./helper";
export default () => {
- afterEach('Unmount modal', emptyDOM);
+ afterEach("Unmount modal", emptyDOM);
- it('overrides the default styles when a custom classname is used', () => {
- const modal = renderModal({ isOpen: true, className: 'myClass' });
- mcontent(modal).style.top.should.be.eql('');
+ it("overrides the default styles when a custom classname is used", () => {
+ const modal = renderModal({ isOpen: true, className: "myClass" });
+ mcontent(modal).style.top.should.be.eql("");
});
- it('overrides the default styles when a custom overlayClassName is used',
- () => {
- const modal = renderModal({
- isOpen: true,
- overlayClassName: 'myOverlayClass'
- });
- moverlay(modal).style.backgroundColor.should.be.eql('');
- }
- );
+ it("overrides the default styles when a custom overlayClassName is used", () => {
+ const modal = renderModal({
+ isOpen: true,
+ overlayClassName: "myOverlayClass"
+ });
+ moverlay(modal).style.backgroundColor.should.be.eql("");
+ });
- it('supports adding style to the modal contents', () => {
- const style = { content: { width: '20px' } };
+ it("supports adding style to the modal contents", () => {
+ const style = { content: { width: "20px" } };
const modal = renderModal({ isOpen: true, style });
- mcontent(modal).style.width.should.be.eql('20px');
+ mcontent(modal).style.width.should.be.eql("20px");
});
- it('supports overriding style on the modal contents', () => {
- const style = { content: { position: 'static' } };
+ it("supports overriding style on the modal contents", () => {
+ const style = { content: { position: "static" } };
const modal = renderModal({ isOpen: true, style });
- mcontent(modal).style.position.should.be.eql('static');
+ mcontent(modal).style.position.should.be.eql("static");
});
- it('supports adding style on the modal overlay', () => {
- const style = { overlay: { width: '75px' } };
+ it("supports adding style on the modal overlay", () => {
+ const style = { overlay: { width: "75px" } };
const modal = renderModal({ isOpen: true, style });
- moverlay(modal).style.width.should.be.eql('75px');
+ moverlay(modal).style.width.should.be.eql("75px");
});
- it('supports overriding style on the modal overlay', () => {
- const style = { overlay: { position: 'static' } };
+ it("supports overriding style on the modal overlay", () => {
+ const style = { overlay: { position: "static" } };
const modal = renderModal({ isOpen: true, style });
- moverlay(modal).style.position.should.be.eql('static');
+ moverlay(modal).style.position.should.be.eql("static");
});
- it('supports overriding the default styles', () => {
+ it("supports overriding the default styles", () => {
const previousStyle = Modal.defaultStyles.content.position;
// Just in case the default style is already relative,
// check that we can change it
- const newStyle = previousStyle === 'relative' ? 'static' : 'relative';
+ const newStyle = previousStyle === "relative" ? "static" : "relative";
Modal.defaultStyles.content.position = newStyle;
const modal = renderModal({ isOpen: true });
modal.portal.content.style.position.should.be.eql(newStyle);
diff --git a/specs/helper.js b/specs/helper.js
index 0af99a26..e840ae97 100644
--- a/specs/helper.js
+++ b/specs/helper.js
@@ -1,7 +1,7 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import Modal, { bodyOpenClassName } from '../src/components/Modal';
-import TestUtils from 'react-dom/test-utils';
+import React from "react";
+import ReactDOM from "react-dom";
+import Modal, { bodyOpenClassName } from "../src/components/Modal";
+import TestUtils from "react-dom/test-utils";
const divStack = [];
@@ -10,7 +10,7 @@ const divStack = [];
*/
if (!String.prototype.includes) {
String.prototype.includes = function(search, start) {
- if (typeof start !== 'number') {
+ if (typeof start !== "number") {
start = 0;
}
@@ -51,43 +51,51 @@ const getModalAttribute = component => (instance, attr) =>
* @param {React} A react instance.
* @return {DOMElement}
*/
-const modalComponent = component => instance =>
- instance.portal[component];
+const modalComponent = component => instance => instance.portal[component];
/**
* Returns the modal content.
* @param {Modal} modal Modal instance.
* @return {DOMElement}
*/
-export const mcontent = modalComponent('content');
+export const mcontent = modalComponent("content");
/**
* Returns the modal overlay.
* @param {Modal} modal Modal instance.
* @return {DOMElement}
*/
-export const moverlay = modalComponent('overlay');
+export const moverlay = modalComponent("overlay");
/**
* Return an attribute of modal content.
* @param {Modal} modal Modal instance.
* @return {String}
*/
-export const contentAttribute = getModalAttribute('content');
+export const contentAttribute = getModalAttribute("content");
/**
* Return an attribute of modal overlay.
* @param {Modal} modal Modal instance.
* @return {String}
*/
-export const overlayAttribute = getModalAttribute('overlay');
+export const overlayAttribute = getModalAttribute("overlay");
const Simulate = TestUtils.Simulate;
const dispatchMockEvent = eventCtor => (key, code) => (element, opts) =>
- eventCtor(element, Object.assign({}, {
- key: key, keyCode: code, which: code
- }, opts));
+ eventCtor(
+ element,
+ Object.assign(
+ {},
+ {
+ key: key,
+ keyCode: code,
+ which: code
+ },
+ opts
+ )
+ );
const dispatchMockKeyDownEvent = dispatchMockEvent(Simulate.keyDown);
@@ -114,13 +122,16 @@ export const mouseDownAt = Simulate.mouseDown;
export const renderModal = function(props, children, callback) {
props.ariaHideApp = false;
- const currentDiv = document.createElement('div');
+ const currentDiv = document.createElement("div");
divStack.push(currentDiv);
document.body.appendChild(currentDiv);
+ // eslint-disable-next-line react/no-render-return-value
return ReactDOM.render(
- {children}
- , currentDiv, callback);
+ {children},
+ currentDiv,
+ callback
+ );
};
export const unmountModal = function() {
diff --git a/specs/index.js b/specs/index.js
index 9fdd1f47..f640547c 100644
--- a/specs/index.js
+++ b/specs/index.js
@@ -1,9 +1,9 @@
/* eslint-env mocha */
-import ModalState from './Modal.spec';
-import ModalEvents from './Modal.events.spec';
-import ModalStyle from './Modal.style.spec';
+import ModalState from "./Modal.spec";
+import ModalEvents from "./Modal.events.spec";
+import ModalStyle from "./Modal.style.spec";
-describe('State', ModalState);
-describe('Style', ModalStyle);
-describe('Events', ModalEvents);
+describe("State", ModalState);
+describe("Style", ModalStyle);
+describe("Events", ModalEvents);
diff --git a/src/components/Modal.js b/src/components/Modal.js
index 8fbfdf44..104d83a0 100644
--- a/src/components/Modal.js
+++ b/src/components/Modal.js
@@ -1,19 +1,17 @@
-import React, { Component } from 'react';
-import ReactDOM from 'react-dom';
-import PropTypes from 'prop-types';
-import ModalPortal from './ModalPortal';
-import * as ariaAppHider from '../helpers/ariaAppHider';
-import SafeHTMLElement, {
- canUseDOM
-} from '../helpers/safeHTMLElement';
-
-export const portalClassName = 'ReactModalPortal';
-export const bodyOpenClassName = 'ReactModal__Body--open';
+import React, { Component } from "react";
+import ReactDOM from "react-dom";
+import PropTypes from "prop-types";
+import ModalPortal from "./ModalPortal";
+import * as ariaAppHider from "../helpers/ariaAppHider";
+import SafeHTMLElement, { canUseDOM } from "../helpers/safeHTMLElement";
+
+export const portalClassName = "ReactModalPortal";
+export const bodyOpenClassName = "ReactModal__Body--open";
const isReact16 = ReactDOM.createPortal !== undefined;
-const createPortal = isReact16 ?
- ReactDOM.createPortal :
- ReactDOM.unstable_renderSubtreeIntoContainer;
+const createPortal = isReact16
+ ? ReactDOM.createPortal
+ : ReactDOM.unstable_renderSubtreeIntoContainer;
function getParentElement(parentSelector) {
return parentSelector();
@@ -33,14 +31,8 @@ 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
- ]),
+ className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
+ overlayClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
appElement: PropTypes.instanceOf(SafeHTMLElement),
onAfterOpen: PropTypes.func,
onRequestClose: PropTypes.func,
@@ -63,31 +55,33 @@ export default class Modal extends Component {
closeTimeoutMS: 0,
shouldFocusAfterRender: true,
shouldCloseOnOverlayClick: true,
- parentSelector() { return document.body; }
+ parentSelector() {
+ return document.body;
+ }
};
static defaultStyles = {
overlay: {
- position: 'fixed',
+ position: "fixed",
top: 0,
left: 0,
right: 0,
bottom: 0,
- backgroundColor: 'rgba(255, 255, 255, 0.75)'
+ 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"
}
};
@@ -95,14 +89,14 @@ export default class Modal extends Component {
if (!canUseDOM) return;
if (!isReact16) {
- this.node = document.createElement('div');
+ this.node = document.createElement("div");
}
this.node.className = this.props.portalClassName;
const parent = getParentElement(this.props.parentSelector);
parent.appendChild(this.node);
- (!isReact16) && this.renderPortal(this.props);
+ !isReact16 && this.renderPortal(this.props);
}
componentWillReceiveProps(newProps) {
@@ -119,7 +113,7 @@ export default class Modal extends Component {
newParent.appendChild(this.node);
}
- (!isReact16) && this.renderPortal(newProps);
+ !isReact16 && this.renderPortal(newProps);
}
componentWillUpdate(newProps) {
@@ -134,9 +128,10 @@ export default class Modal extends Component {
const state = this.portal.state;
const now = Date.now();
- const closesAt = state.isOpen && this.props.closeTimeoutMS
- && (state.closesAt
- || now + this.props.closeTimeoutMS);
+ const closesAt =
+ state.isOpen &&
+ this.props.closeTimeoutMS &&
+ (state.closesAt || now + this.props.closeTimeoutMS);
if (closesAt) {
if (!state.beforeClose) {
@@ -150,19 +145,23 @@ export default class Modal extends Component {
}
removePortal = () => {
- (!isReact16) && ReactDOM.unmountComponentAtNode(this.node);
+ !isReact16 && ReactDOM.unmountComponentAtNode(this.node);
const parent = getParentElement(this.props.parentSelector);
parent.removeChild(this.node);
- }
+ };
- portalRef = ref => { this.portal = ref; }
+ portalRef = ref => {
+ this.portal = ref;
+ };
renderPortal = props => {
- const portal = createPortal(this, (
-
- ), this.node);
+ const portal = createPortal(
+ this,
+ ,
+ this.node
+ );
this.portalRef(portal);
- }
+ };
render() {
if (!canUseDOM || !isReact16) {
@@ -170,13 +169,15 @@ export default class Modal extends Component {
}
if (!this.node && isReact16) {
- this.node = document.createElement('div');
+ this.node = document.createElement("div");
}
return createPortal(
- ,
+ ,
this.node
);
}
diff --git a/src/components/ModalPortal.js b/src/components/ModalPortal.js
index 269fc34b..5aeb7b5c 100644
--- a/src/components/ModalPortal.js
+++ b/src/components/ModalPortal.js
@@ -1,16 +1,16 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import * as focusManager from '../helpers/focusManager';
-import scopeTab from '../helpers/scopeTab';
-import * as ariaAppHider from '../helpers/ariaAppHider';
-import * as refCount from '../helpers/refCount';
-import * as bodyClassList from '../helpers/bodyClassList';
-import SafeHTMLElement from '../helpers/safeHTMLElement';
+import React, { Component } from "react";
+import { PropTypes } from "prop-types";
+import * as focusManager from "../helpers/focusManager";
+import scopeTab from "../helpers/scopeTab";
+import * as ariaAppHider from "../helpers/ariaAppHider";
+import * as refCount from "../helpers/refCount";
+import * as bodyClassList from "../helpers/bodyClassList";
+import SafeHTMLElement from "../helpers/safeHTMLElement";
// so that our CSS is statically analyzable
const CLASS_NAMES = {
- overlay: 'ReactModal__Overlay',
- content: 'ReactModal__Content'
+ overlay: "ReactModal__Overlay",
+ content: "ReactModal__Content"
};
const TAB_KEY = 9;
@@ -34,14 +34,8 @@ export default class ModalPortal extends Component {
content: PropTypes.object,
overlay: PropTypes.object
}),
- className: PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.object
- ]),
- overlayClassName: PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.object
- ]),
+ className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
+ overlayClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
bodyOpenClassName: PropTypes.string,
ariaHideApp: PropTypes.bool,
appElement: PropTypes.instanceOf(SafeHTMLElement),
@@ -82,7 +76,7 @@ export default class ModalPortal extends Component {
// eslint-disable-next-line no-console
console.warn(
'React-Modal: "bodyOpenClassName" prop has been modified. ' +
- 'This may cause unexpected behavior when multiple modals are open.'
+ "This may cause unexpected behavior when multiple modals are open."
);
}
}
@@ -107,17 +101,17 @@ export default class ModalPortal extends Component {
clearTimeout(this.closeTimer);
}
- setFocusAfterRender = (focus) => {
+ setFocusAfterRender = focus => {
this.focusAfterRender = this.props.shouldFocusAfterRender && focus;
- }
+ };
- setOverlayRef = (overlay) => {
+ setOverlayRef = overlay => {
this.overlay = overlay;
- }
+ };
- setContentRef = (content) => {
+ setContentRef = content => {
this.content = content;
- }
+ };
beforeOpen() {
const { appElement, ariaHideApp, bodyOpenClassName } = this.props;
@@ -142,7 +136,7 @@ export default class ModalPortal extends Component {
afterClose = () => {
focusManager.returnFocus();
focusManager.teardownScopedFocus();
- }
+ };
open = () => {
this.beforeOpen();
@@ -160,7 +154,7 @@ export default class ModalPortal extends Component {
}
});
}
- }
+ };
close = () => {
this.beforeClose();
@@ -169,11 +163,11 @@ export default class ModalPortal extends Component {
} else {
this.closeWithoutTimeout();
}
- }
+ };
// Don't steal focus from inner elements
focusContent = () =>
- (this.content && !this.contentHasFocus()) && this.content.focus();
+ this.content && !this.contentHasFocus() && this.content.focus();
closeWithTimeout = () => {
const closesAt = Date.now() + this.props.closeTimeoutMS;
@@ -183,16 +177,19 @@ export default class ModalPortal extends Component {
this.state.closesAt - Date.now()
);
});
- }
+ };
closeWithoutTimeout = () => {
- this.setState({
- beforeClose: false,
- isOpen: false,
- afterOpen: false,
- closesAt: null
- }, this.afterClose);
- }
+ this.setState(
+ {
+ beforeClose: false,
+ isOpen: false,
+ afterOpen: false,
+ closesAt: null
+ },
+ this.afterClose
+ );
+ };
handleKeyDown = event => {
if (event.keyCode === TAB_KEY) {
@@ -202,7 +199,7 @@ export default class ModalPortal extends Component {
event.preventDefault();
this.requestClose(event);
}
- }
+ };
handleOverlayOnClick = event => {
if (this.shouldClose === null) {
@@ -218,50 +215,51 @@ export default class ModalPortal extends Component {
}
this.shouldClose = null;
this.moveFromContentToOverlay = null;
- }
+ };
handleOverlayOnMouseUp = () => {
if (this.moveFromContentToOverlay === null) {
this.shouldClose = false;
}
- }
+ };
handleContentOnMouseUp = () => {
this.shouldClose = false;
- }
+ };
handleOverlayOnMouseDown = () => {
this.moveFromContentToOverlay = false;
- }
+ };
handleContentOnClick = () => {
this.shouldClose = false;
- }
+ };
handleContentOnMouseDown = () => {
this.shouldClose = false;
this.moveFromContentToOverlay = false;
- }
+ };
requestClose = event =>
this.ownerHandlesClose() && this.props.onRequestClose(event);
- ownerHandlesClose = () =>
- this.props.onRequestClose;
+ ownerHandlesClose = () => this.props.onRequestClose;
- shouldBeClosed = () =>
- !this.state.isOpen && !this.state.beforeClose;
+ shouldBeClosed = () => !this.state.isOpen && !this.state.beforeClose;
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`
- };
+ const classNames =
+ typeof additional === "object"
+ ? additional
+ : {
+ base: CLASS_NAMES[which],
+ afterOpen: `${CLASS_NAMES[which]}--after-open`,
+ beforeClose: `${CLASS_NAMES[which]}--before-close`
+ };
let className = classNames.base;
if (this.state.afterOpen) {
className = `${className} ${classNames.afterOpen}`;
@@ -269,14 +267,16 @@ export default class ModalPortal extends Component {
if (this.state.beforeClose) {
className = `${className} ${classNames.beforeClose}`;
}
- return (typeof additional === 'string' && additional) ?
- `${className} ${additional}` : className;
- }
+ return typeof additional === "string" && additional
+ ? `${className} ${additional}`
+ : className;
+ };
- ariaAttributes = items => Object.keys(items).reduce((acc, name) => {
- acc[`aria-${name}`] = items[name];
- return acc;
- }, {});
+ ariaAttributes = items =>
+ Object.keys(items).reduce((acc, name) => {
+ acc[`aria-${name}`] = items[name];
+ return acc;
+ }, {});
render() {
const { className, overlayClassName, defaultStyles } = this.props;
@@ -286,15 +286,16 @@ export default class ModalPortal extends Component {
return this.shouldBeClosed() ? null : (
+ onMouseUp={this.handleOverlayOnMouseUp}
+ >
+ {...this.ariaAttributes(this.props.aria || {})}
+ >
{this.props.children}
diff --git a/src/helpers/ariaAppHider.js b/src/helpers/ariaAppHider.js
index 135bc8c7..f93b896a 100644
--- a/src/helpers/ariaAppHider.js
+++ b/src/helpers/ariaAppHider.js
@@ -10,10 +10,10 @@ export function assertNodeList(nodeList, selector) {
export function setElement(element) {
let useElement = element;
- if (typeof useElement === 'string') {
+ if (typeof useElement === "string") {
const el = document.querySelectorAll(useElement);
assertNodeList(el, useElement);
- useElement = 'length' in el ? el[0] : el;
+ useElement = "length" in el ? el[0] : el;
}
globalElement = useElement || globalElement;
return globalElement;
@@ -41,12 +41,12 @@ export function validateElement(appElement) {
export function hide(appElement) {
validateElement(appElement);
- (appElement || globalElement).setAttribute('aria-hidden', 'true');
+ (appElement || globalElement).setAttribute("aria-hidden", "true");
}
export function show(appElement) {
validateElement(appElement);
- (appElement || globalElement).removeAttribute('aria-hidden');
+ (appElement || globalElement).removeAttribute("aria-hidden");
}
export function documentNotReadyOrSSRTesting() {
diff --git a/src/helpers/bodyClassList.js b/src/helpers/bodyClassList.js
index eea672a2..19b98628 100644
--- a/src/helpers/bodyClassList.js
+++ b/src/helpers/bodyClassList.js
@@ -1,19 +1,19 @@
-import * as refCount from './refCount';
+import * as refCount from "./refCount";
-export function add (bodyClass) {
+export function add(bodyClass) {
// Increment class(es) on refCount tracker and add class(es) to body
bodyClass
- .split(' ')
+ .split(" ")
.map(refCount.add)
.forEach(className => document.body.classList.add(className));
}
-export function remove (bodyClass) {
+export function remove(bodyClass) {
const classListMap = refCount.get();
// Decrement class(es) from the refCount tracker
// and remove unused class(es) from body
bodyClass
- .split(' ')
+ .split(" ")
.map(refCount.remove)
.filter(className => classListMap[className] === 0)
.forEach(className => document.body.classList.remove(className));
diff --git a/src/helpers/focusManager.js b/src/helpers/focusManager.js
index f4ff69fc..d3cecdc8 100644
--- a/src/helpers/focusManager.js
+++ b/src/helpers/focusManager.js
@@ -1,4 +1,4 @@
-import findTabbable from '../helpers/tabbable';
+import findTabbable from "../helpers/tabbable";
const focusLaterElements = [];
let modalElement = null;
@@ -23,7 +23,7 @@ export function handleFocus() {
if (modalElement.contains(document.activeElement)) {
return;
}
- const el = (findTabbable(modalElement)[0] || modalElement);
+ const el = findTabbable(modalElement)[0] || modalElement;
el.focus();
}, 0);
}
@@ -41,11 +41,13 @@ export function returnFocus() {
toFocus.focus();
return;
} catch (e) {
- console.warn([
- 'You tried to return focus to',
- toFocus,
- 'but it is not in the DOM anymore'
- ].join(" "));
+ console.warn(
+ [
+ "You tried to return focus to",
+ toFocus,
+ "but it is not in the DOM anymore"
+ ].join(" ")
+ );
}
}
/* eslint-enable no-console */
@@ -54,11 +56,11 @@ export function setupScopedFocus(element) {
modalElement = element;
if (window.addEventListener) {
- window.addEventListener('blur', handleBlur, false);
- document.addEventListener('focus', handleFocus, true);
+ window.addEventListener("blur", handleBlur, false);
+ document.addEventListener("focus", handleFocus, true);
} else {
- window.attachEvent('onBlur', handleBlur);
- document.attachEvent('onFocus', handleFocus);
+ window.attachEvent("onBlur", handleBlur);
+ document.attachEvent("onFocus", handleFocus);
}
}
@@ -66,10 +68,10 @@ export function teardownScopedFocus() {
modalElement = null;
if (window.addEventListener) {
- window.removeEventListener('blur', handleBlur);
- document.removeEventListener('focus', handleFocus);
+ window.removeEventListener("blur", handleBlur);
+ document.removeEventListener("focus", handleFocus);
} else {
- window.detachEvent('onBlur', handleBlur);
- document.detachEvent('onFocus', handleFocus);
+ window.detachEvent("onBlur", handleBlur);
+ document.detachEvent("onFocus", handleFocus);
}
}
diff --git a/src/helpers/refCount.js b/src/helpers/refCount.js
index fe6ade16..033c3192 100644
--- a/src/helpers/refCount.js
+++ b/src/helpers/refCount.js
@@ -21,6 +21,8 @@ export function remove(bodyClass) {
}
export function totalCount() {
- return Object.keys(classListMap)
- .reduce((acc, curr) => acc + classListMap[curr], 0);
+ return Object.keys(classListMap).reduce(
+ (acc, curr) => acc + classListMap[curr],
+ 0
+ );
}
diff --git a/src/helpers/safeHTMLElement.js b/src/helpers/safeHTMLElement.js
index 3798072d..5f650887 100644
--- a/src/helpers/safeHTMLElement.js
+++ b/src/helpers/safeHTMLElement.js
@@ -1,4 +1,4 @@
-import ExecutionEnvironment from 'exenv';
+import ExecutionEnvironment from "exenv";
const EE = ExecutionEnvironment;
diff --git a/src/helpers/scopeTab.js b/src/helpers/scopeTab.js
index 9e5f180f..53a86fc0 100644
--- a/src/helpers/scopeTab.js
+++ b/src/helpers/scopeTab.js
@@ -1,4 +1,4 @@
-import findTabbable from './tabbable';
+import findTabbable from "./tabbable";
export default function scopeTab(node, event) {
const tabbable = findTabbable(node);
@@ -7,11 +7,10 @@ export default function scopeTab(node, event) {
return;
}
const finalTabbable = tabbable[event.shiftKey ? 0 : tabbable.length - 1];
- const leavingFinalTabbable = (
+ const leavingFinalTabbable =
finalTabbable === document.activeElement ||
- // handle immediate shift+tab after opening with mouse
- node === document.activeElement
- );
+ // handle immediate shift+tab after opening with mouse
+ node === document.activeElement;
if (!leavingFinalTabbable) return;
event.preventDefault();
const target = tabbable[event.shiftKey ? tabbable.length - 1 : 0];
diff --git a/src/helpers/tabbable.js b/src/helpers/tabbable.js
index 905d17b4..dc3c50b4 100644
--- a/src/helpers/tabbable.js
+++ b/src/helpers/tabbable.js
@@ -13,8 +13,9 @@
const tabbableNode = /input|select|textarea|button|object/;
function hidden(el) {
- return (el.offsetWidth <= 0 && el.offsetHeight <= 0) ||
- el.style.display === 'none';
+ return (
+ (el.offsetWidth <= 0 && el.offsetHeight <= 0) || el.style.display === "none"
+ );
}
function visible(element) {
@@ -29,20 +30,19 @@ function visible(element) {
function focusable(element, isTabIndexNotNaN) {
const nodeName = element.nodeName.toLowerCase();
- const res = ((tabbableNode.test(nodeName)) && !element.disabled) ||
- (nodeName === "a" ? element.href || isTabIndexNotNaN : isTabIndexNotNaN);
+ const res =
+ (tabbableNode.test(nodeName) && !element.disabled) ||
+ (nodeName === "a" ? element.href || isTabIndexNotNaN : isTabIndexNotNaN);
return res && visible(element);
}
function tabbable(element) {
- let tabIndex = element.getAttribute('tabindex');
+ let tabIndex = element.getAttribute("tabindex");
if (tabIndex === null) tabIndex = undefined;
const isTabIndexNaN = isNaN(tabIndex);
return (isTabIndexNaN || tabIndex >= 0) && focusable(element, !isTabIndexNaN);
}
export default function findTabbableDescendants(element) {
- return [].slice.call(
- element.querySelectorAll('*'), 0
- ).filter(tabbable);
+ return [].slice.call(element.querySelectorAll("*"), 0).filter(tabbable);
}
diff --git a/src/index.js b/src/index.js
index 8ecf0994..0235bbfb 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,3 +1,3 @@
-import Modal from './components/Modal';
+import Modal from "./components/Modal";
export default Modal;