From 43eec232f09415f4059ff5e4951dcb6c78bd9d7c Mon Sep 17 00:00:00 2001 From: Standa Opichal Date: Thu, 4 Aug 2016 14:58:27 +0200 Subject: [PATCH] Avoid wrapping children This changes the API so that by default the FocusTrap doesn't wrap the children and therefore there must only be a single child element under HotKeys. In such a case there is no tabIndex manipulation unless used explicitly. In order to wrap the contents one needs to explicitly define the component property as follows:

This is NOT going to get wrapped with a div

This is going to get wrapped around with a div

--- README.md | 2 +- examples/master/index.js | 8 +++++--- lib/FocusTrap.js | 42 ++++++++++++++++++++++++++++++++++------ 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 879c2ac0..a06a8a5d 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ const Node = React.createClass({ }; return ( - + Node contents ); diff --git a/examples/master/index.js b/examples/master/index.js index 00e5a9ac..ff974970 100644 --- a/examples/master/index.js +++ b/examples/master/index.js @@ -1,7 +1,7 @@ import {HotKeys, HotKeyMapMixin} from 'react-hotkeys'; import React from 'react'; import ReactDOM from 'react-dom'; -import rand from 'lodash/number/random'; +import rand from 'lodash/random'; const DEFAULT_NODE_SIZE = 100; const SIZE_INCREMENT = 5; @@ -51,7 +51,9 @@ const App = React.createClass({ - {Array.apply(null, new Array(10)).map((e, i) => )} +
+ {Array.apply(null, new Array(10)).map((e, i) => )} +
); @@ -110,7 +112,7 @@ const Node = React.createClass({ // - by default we would set it to -1 so it can only be directly clicked (& tapped?) // or focused programattically return ( - + Node ); diff --git a/lib/FocusTrap.js b/lib/FocusTrap.js index c8cdd593..8631d039 100644 --- a/lib/FocusTrap.js +++ b/lib/FocusTrap.js @@ -1,5 +1,7 @@ import React from 'react'; +const DOCUMENT_FRAGMENT = 'documentFragment'; + const FocusTrap = React.createClass({ propTypes: { @@ -11,10 +13,30 @@ const FocusTrap = React.createClass({ getDefaultProps() { return { - component: 'div' + component: DOCUMENT_FRAGMENT }; }, + onFocus() { + const child = React.Children.only(this.props.children); + if (child.onFocus) { + child.onFocus(...arguments); + } + if (this.props.onFocus) { + this.props.onFocus(...arguments); + } + }, + + onBlur() { + const child = React.Children.only(this.props.children); + if (child.onBlur) { + child.onBlur(...arguments); + } + if (this.props.onBlur) { + this.props.onBlur(...arguments); + } + }, + render() { const { component: Component, @@ -22,11 +44,19 @@ const FocusTrap = React.createClass({ ...props } = this.props; - return ( - - {children} - - ); + if (Component !== DOCUMENT_FRAGMENT) { + return ( + + {children} + + ); + } + + const child = React.Children.only(children); + const onFocus = this.onFocus; + const onBlur = this.onBlur; + + return React.cloneElement(child, {...props, onFocus, onBlur}); } });