Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STCOM-1285 Migrate way from findDOMNode in stripes-react-hotkeys #44

Merged
merged 10 commits into from
Sep 25, 2024
13 changes: 10 additions & 3 deletions lib/FocusTrap.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import PropTypes from 'prop-types';
import React from 'react';
import ReactDOM from 'react-dom';
import { addFocusListener, addBlurListener } from './focusListeners';

class FocusTrap extends React.Component {
Expand All @@ -27,7 +26,13 @@ class FocusTrap extends React.Component {
};

componentDidMount() {
if (!this.willWrap) {
if (!this.willWrap && this.props.element) {
this.setupNativeListeners();
}
}

componentDidUpdate(prevProps) {
if (!prevProps.element && this.props.element) {
this.setupNativeListeners();
}
}
Expand All @@ -41,9 +46,10 @@ class FocusTrap extends React.Component {
const {
onFocus,
onBlur,
element,
} = this.props;

const elem = ReactDOM.findDOMNode(this);
const elem = element;

if (elem && !this.focusListener) {
if (!elem.getAttribute('tabindex')) {
Expand Down Expand Up @@ -73,6 +79,7 @@ class FocusTrap extends React.Component {
component: Component,
children,
noWrapper,
element,
...props
} = this.props;

Expand Down
28 changes: 20 additions & 8 deletions lib/HotKeys.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ const buildBindArray = (bindArray, wrapper, handlers, keyMap) => {
Object.keys(handlers).forEach(h => {
let sequences = getSequencesFromMap(h, keyMap);

// if no keyMap entry is present, assume the handler's key *is*
// if no keyMap entry is present, assume the handler's key *is*
// the keyCombo (a hard-coded sequence like "enter" or "ctrl + e".)
// if (!keyCombo) {
// keyCombo = h;
// }
sequences.forEach((keyCombo) => {
if ( handlers[h] && // avoid undefined handler functions

if ( handlers[h] && // avoid undefined handler functions
bindArray.findIndex((w) => w.keyCombo === keyCombo) === -1 ) { // avoid duplicate keyCombos
const wrapped = {
keyCombo,
Expand Down Expand Up @@ -118,7 +118,17 @@ class HotKeys extends React.Component {
}

componentDidMount() {
this.attachment = this.props.attach || ReactDOM.findDOMNode(this);
const { attach } = this.props;



// handle refs...
if (attach) {
this.attachment = attach?.current ? attach.current : attach;
} else {
// this will still error if no attach prop is provided...
this.attachment = ReactDOM.findDOMNode(this);
}
JohnC-80 marked this conversation as resolved.
Show resolved Hide resolved
this.keyboardjs = new Keyboard(this.attachment);
this.keyboardjs.setLocale("us", usLocale);
this.updateHotKeys(true);
Expand All @@ -128,6 +138,8 @@ class HotKeys extends React.Component {
if (contains(this.attachment, document.activeElement)) {
this.isFocused = true;
}
// if an attachment wasn't included, re-render to pick up the attachment node in FocusTrap.
if(typeof attach === 'undefined') this.forceUpdate();
}

componentDidUpdate(prevProps, prevState) {
Expand Down Expand Up @@ -215,7 +227,7 @@ class HotKeys extends React.Component {
// and watch... (we don't even watch if no key bindings were stored)
this.keyboardjs.watch(this.attachment);
}

};

childHandledSequence = (sequence = null) => {
Expand Down Expand Up @@ -263,17 +275,17 @@ class HotKeys extends React.Component {
} = this.props;

const focusTrapProps = omit(
this.props,
this.props,
'keyMap',
'handlers',
'focused',
'attach',
'HKcontext'
'HKcontext'
);

return (
<HotKeysProvider value={this.state.HKcontext}>
<FocusTrap {...focusTrapProps} onFocus={this.onFocus} onBlur={this.onBlur}>
<FocusTrap {...focusTrapProps} onFocus={this.onFocus} onBlur={this.onBlur} element={this.attachment}>
{children}
</FocusTrap>
</HotKeysProvider>
Expand Down
9 changes: 5 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ We've modified it to use a more efficient keyboard handling library (KeyboardJS)
```js
import { HotKeys } from '@folio/stripes-components/lib/HotKeys';
//..
const keys = {
const keys = {
'delete' : ['delete','backspace'],
};

Expand All @@ -35,7 +35,7 @@ Components can be wrapped to give them the necessary props/functionality to resp
import { HotKeysHOC } from '@folio/stripes-components/lib/HotKeys';

class MyComponent extends React.Component {
// typical component internals... constructor(), render(), etc.
// typical component internals... constructor(), render(), etc.
}

// wrap component with HOC...
Expand All @@ -44,7 +44,7 @@ export default HotKeysHOC(MyComponent);
You can then use the component as normal, supplying appropriate `keyMap` and `handlers` props.

```js
const keys = {
const keys = {
'delete' : ['delete','backspace'],
};

Expand All @@ -63,6 +63,7 @@ keyMap | object | Object of named hotkey sequences: e.g. { 'deletion': ['delete'
handlers | object | Object of hotkey sequence names with corresponding handler functions: e.g. { 'delete': this.doDelete }| |
noWrapper | bool | if true, HotKeys will attempt to use its child component's outer container as its basis for focus. If false, it will wrap the component in the element with the tagname provided in the `component` prop. | false |
component | any | Tagname of component that will be potentially used to wrap the child component and keep track of focus. | 'div' |
attach | DOM element | DOM node to attach the handlers to | |

## Development

Expand All @@ -72,7 +73,7 @@ You can then `yarn link` this into an existing module/workspace.

run `yarn prepublish` to rebuild exposed package files.

Run tests via
Run tests via
```
yarn test-dev
``
Loading