react-focus-trap
Advanced tools
Comparing version 0.4.0 to 0.5.0
# CHANGELOG | ||
## 0.5.0 | ||
- Addresses some issues with screen readers after conducting testing | ||
with VoiceOver | ||
## 0.4.0 | ||
- More sensible defaults. See readme. | ||
- More sensible defaults. See readme | ||
## 0.3.0 | ||
- Add the ability to configure inner container element className with the 'className' property | ||
- Add the ability to configure inner container element className with | ||
the 'className' property | ||
@@ -14,3 +20,4 @@ ## 0.2.0 | ||
- Add handling for when element is not defined | ||
- Added the ability to set the inner container element using the `element` property | ||
- Added the ability to set the inner container element using the | ||
`element` property | ||
@@ -17,0 +24,0 @@ ## 0.1.1 |
@@ -1,1 +0,1 @@ | ||
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("react"));else if("function"==typeof define&&define.amd)define(["react"],t);else{var o=t("object"==typeof exports?require("react"):e.react);for(var s in o)("object"==typeof exports?exports:e)[s]=o[s]}}(this,function(e){return function(e){function t(s){if(o[s])return o[s].exports;var r=o[s]={exports:{},id:s,loaded:!1};return e[s].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var o={};return t.m=e,t.c=o,t.p="",t(0)}([function(e,t,o){"use strict";var s=o(1),r=o(2);e.exports=r.createClass({displayName:"exports",mixins:[s],propTypes:{active:r.PropTypes.bool,onExit:r.PropTypes.func.isRequired,role:r.PropTypes.string.isRequired},getDefaultProps:function(){return{active:!1,className:"focus-trap-inner",element:"div",role:"dialog"}},getBackdrop:function(){return r.createElement("div",{className:"focus-trap-backdrop","aria-hidden":!0,onClick:this.props.onExit})},getInner:function(){var e=this.props,t=e.className,o=e.element,s=e.children;return r.createElement(o,{className:t},s)},render:function(){var e=this.props,t=e.active,o=e.role;return t?r.createElement("div",{className:"focus-trap",tabIndex:"0",role:o,onKeyUp:this._onKeyUp},this.getBackdrop(),this.getInner()):null},_onKeyUp:function(e){"Escape"===e.key&&this.props.onExit()}})},function(e,t,o){"use strict";e.exports={_pushFocus:function(){this.setState({previousFocus:document.activeElement}),this._focus()},_popFocus:function(){this.state.previousFocus&&(this.state.previousFocus.focus(),this._clearTrap())},_focus:function(){var e=this.getDOMNode();e&&e.focus()},_trapFocus:function(){this._focusTimer=setTimeout(this._focus,10)},_clearTrap:function(){clearTimeout(this._focusTimer)},componentDidMount:function(){var e=this.getDOMNode();e&&(e.addEventListener("focusin",this._clearTrap),e.addEventListener("focusout",this._trapFocus)),this._pushFocus()},componentWillUnmount:function(){var e=this.getDOMNode();this._popFocus(),e&&(e.removeEventListener("focusin",this._clearTrap),e.removeEventListener("focusout",this._trapFocus))}}},function(t,o,s){t.exports=e}])}); | ||
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("react"));else if("function"==typeof define&&define.amd)define(["react"],t);else{var o=t("object"==typeof exports?require("react"):e.react);for(var r in o)("object"==typeof exports?exports:e)[r]=o[r]}}(this,function(e){return function(e){function t(r){if(o[r])return o[r].exports;var n=o[r]={exports:{},id:r,loaded:!1};return e[r].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var o={};return t.m=e,t.c=o,t.p="",t(0)}([function(e,t,o){"use strict";var r=o(2),n=o(3),s=o(4),c=o(1),i=c.createClass({displayName:"FocusTrap",mixins:[s],propTypes:{active:c.PropTypes.bool,onExit:c.PropTypes.func.isRequired},getDefaultProps:function(){return{active:!1,role:"dialog"}},render:function(){var e=this.props,t=e.active,o=e.className,s=e.children,i=e.element,u=e.onExit,a=e.role;return t?c.createElement("div",{className:"focus-trap",onKeyUp:this._onKeyUp,role:a,tabIndex:"-1"},c.createElement(r,{onClick:u}),c.createElement(n,{ref:"focus",className:o,element:i},s)):null},_onKeyUp:function(e){"Escape"===e.key&&this.props.onExit()}});e.exports=i},function(t,o,r){t.exports=e},function(e,t,o){"use strict";var r=function(e,t){var o={};for(var r in e)t.indexOf(r)>=0||Object.prototype.hasOwnProperty.call(e,r)&&(o[r]=e[r]);return o},n=o(1),s=n.createClass({displayName:"Backdrop",getDefaultProps:function(){return{"aria-hidden":!0,className:"focus-trap-backdrop",element:"div"}},render:function(){var e=this.props,t=e.element,o=r(e,["element"]);return n.createElement(t,o)}});e.exports=s},function(e,t,o){"use strict";var r=function(e,t){var o={};for(var r in e)t.indexOf(r)>=0||Object.prototype.hasOwnProperty.call(e,r)&&(o[r]=e[r]);return o},n=o(1),s=n.createClass({displayName:"FocalPoint",getDefaultProps:function(){return{className:"focus-trap-inner",element:"div",tabIndex:"0"}},render:function(){var e=this.props,t=e.children,o=e.element,s=r(e,["children","element"]);return n.createElement(o,s,t)}});e.exports=s},function(e,t,o){"use strict";e.exports={_pushFocus:function(){this.setState({previousFocus:document.activeElement}),this._focus()},_popFocus:function(){this.state.previousFocus.focus(),this._clearTrap()},_focus:function(){this.refs.focus&&this.refs.focus.getDOMNode().focus()},_trapFocus:function(e){this._focusTimer=setTimeout(this._focus,10)},_clearTrap:function(){clearTimeout(this._focusTimer)},componentDidMount:function(){document.addEventListener("focus",this._onFocusLeave,!0),this._pushFocus()},componentWillUnmount:function(){document.removeEventListener("focus",this._onFocusLeave,!0),this._popFocus()},_onFocusLeave:function(e){var t=this.refs.focus.getDOMNode();t.contains(e.target)===!1&&(e.preventDefault(),this._trapFocus())}}}])}); |
{ | ||
"name": "react-focus-trap", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "", | ||
@@ -8,2 +8,4 @@ "main": "dist/focus-trap.js", | ||
"start": "webpack -wd --config webpack.example.config.js", | ||
"test": "karma start", | ||
"coveralls": "CONTINUOUS_INTEGRATION=true npm test && coveralls < coverage/report-lcov/lcov.info", | ||
"prepublish": "./scripts/production" | ||
@@ -21,5 +23,22 @@ }, | ||
"devDependencies": { | ||
"babel-core": "^5.x.x", | ||
"babel-loader": "^5.x.x", | ||
"webpack": "^1.x.x", | ||
"webpack-dev-server": "^1.x.x" | ||
"babel-runtime": "^5.1.10", | ||
"chai": "^2.2.0", | ||
"coveralls": "^2.11.2", | ||
"istanbul": "^0.3.5", | ||
"istanbul-instrumenter-loader": "^0.1.2", | ||
"karma": "^0.12.32", | ||
"karma-chrome-launcher": "^0.1.7", | ||
"karma-cli": "0.0.4", | ||
"karma-coverage": "^0.2.7", | ||
"karma-firefox-launcher": "^0.1.4", | ||
"karma-mocha": "^0.1.10", | ||
"karma-nyan-reporter": "0.0.60", | ||
"karma-sinon-chai": "^0.3.0", | ||
"karma-webpack": "^1.5.0", | ||
"mocha": "^2.2.1", | ||
"react": ">= 0.12.1", | ||
"sinon": "^1.14.1", | ||
"webpack": "^1.x.x" | ||
}, | ||
@@ -26,0 +45,0 @@ "dependencies": { |
@@ -1,3 +0,10 @@ | ||
# React Focus Trap | ||
[![NPM](https://nodei.co/npm/react-focus-trap.png?compact=true)](https://npmjs.org/package/react-focus-trap) | ||
--- | ||
[![Build Status](https://travis-ci.org/vigetlabs/react-focus-trap.png?branch=master)](https://travis-ci.org/vigetlabs/react-focus-trap) | ||
[![Coverage Status](https://coveralls.io/repos/vigetlabs/react-focus-trap/badge.svg)](https://coveralls.io/r/vigetlabs/react-focus-trap) | ||
--- | ||
A generic focus management tool for components such as dialogs and dropdowns. | ||
@@ -7,11 +14,12 @@ | ||
React Focus Trap is a container element that will manage focus for its children | ||
React Focus Trap is a container element that will manage focus for its children. | ||
```javascript | ||
let Modal = React.createClass({ | ||
render() { | ||
<FocusTrap onExit={ this._onExit }> | ||
Amazing stuff goes here | ||
</FocusTrap> | ||
return ( | ||
<FocusTrap onExit={ this._onExit } active={ this.props.active }> | ||
Amazing stuff goes here | ||
</FocusTrap> | ||
) | ||
} | ||
@@ -29,8 +37,8 @@ }) | ||
| Name | Default | Description | | ||
| ---------- | -------------------- | ----------------------------------------------------- | | ||
| active | false | Should the FocusTrap render? | | ||
| className | 'focus-trap-inner' | The class of the inner container that maintains focus | | ||
| onExit | null (but required) | Callback when escape or an outside click occurs | | ||
| element | 'div' | The tag name of the inner container | | ||
| role | 'dialog' | The aria role for the inner container | | ||
| Name | Default | Description | | ||
| ---------- | --------------------- | ----------------------------------------------------- | | ||
| active | `false` | Should the FocusTrap render? | | ||
| className | `'focus-trap-inner'` | The class of the inner container that maintains focus | | ||
| onExit | `null (but required)` | Callback when escape or an outside click occurs | | ||
| element | `'div'` | The tag name of the inner container | | ||
| role | `'dialog'` | The aria role for the inner container | |
@@ -6,2 +6,3 @@ /** | ||
* when it is unmounted | ||
* http://www.nczonline.net/blog/2013/02/12/making-an-accessible-dialog-box/ | ||
*/ | ||
@@ -20,19 +21,13 @@ | ||
_popFocus() { | ||
if (this.state.previousFocus) { | ||
this.state.previousFocus.focus() | ||
this._clearTrap() | ||
} | ||
this.state.previousFocus.focus() | ||
this._clearTrap() | ||
}, | ||
_focus() { | ||
let el = this.getDOMNode() | ||
if (el) { | ||
el.focus() | ||
if (this.refs.focus) { | ||
this.refs.focus.getDOMNode().focus() | ||
} | ||
}, | ||
// trap keyboard focus within modal | ||
// via http://www.nczonline.net/blog/2013/02/12/making-an-accessible-dialog-box/ | ||
_trapFocus() { | ||
_trapFocus(e) { | ||
this._focusTimer = setTimeout(this._focus, 10) | ||
@@ -46,9 +41,3 @@ }, | ||
componentDidMount() { | ||
let el = this.getDOMNode() | ||
if (el) { | ||
el.addEventListener('focusin', this._clearTrap) | ||
el.addEventListener('focusout', this._trapFocus) | ||
} | ||
document.addEventListener('focus', this._onFocusLeave, true) | ||
this._pushFocus() | ||
@@ -58,9 +47,12 @@ }, | ||
componentWillUnmount() { | ||
let el = this.getDOMNode() | ||
document.removeEventListener('focus', this._onFocusLeave, true) | ||
this._popFocus() | ||
}, | ||
if (el) { | ||
el.removeEventListener('focusin', this._clearTrap) | ||
el.removeEventListener('focusout', this._trapFocus) | ||
_onFocusLeave(event) { | ||
let el = this.refs.focus.getDOMNode() | ||
if (el.contains(event.target) === false) { | ||
event.preventDefault(); | ||
this._trapFocus() | ||
} | ||
@@ -67,0 +59,0 @@ } |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
162623
43
931
43
20
1