redux-devtools/packages/redux-devtools-dock-monitor/src/DockMonitor.js
Nathan Bierema ebdf32661e
Add redux-devtools-dock-monitor package (#561)
* Stash

* Cleanup

* Fix

* Add export default from plugin

* Remove empty test
2020-08-06 16:25:12 -04:00

163 lines
4.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { cloneElement, Children, Component } from 'react';
import PropTypes from 'prop-types';
import Dock from 'react-dock';
import { POSITIONS } from './constants';
import {
toggleVisibility,
changeMonitor,
changePosition,
changeSize
} from './actions';
import reducer from './reducers';
import parseKey from 'parse-key';
export default class DockMonitor extends Component {
static update = reducer;
static propTypes = {
defaultPosition: PropTypes.oneOf(POSITIONS),
defaultIsVisible: PropTypes.bool.isRequired,
defaultSize: PropTypes.number.isRequired,
toggleVisibilityKey: PropTypes.string.isRequired,
changePositionKey: PropTypes.string.isRequired,
changeMonitorKey: PropTypes.string,
fluid: PropTypes.bool,
dispatch: PropTypes.func,
monitorState: PropTypes.shape({
position: PropTypes.oneOf(POSITIONS).isRequired,
size: PropTypes.number.isRequired,
isVisible: PropTypes.bool.isRequired,
childMonitorState: PropTypes.any
})
};
static defaultProps = {
defaultIsVisible: true,
defaultPosition: 'right',
defaultSize: 0.3,
fluid: true
};
constructor(props) {
super(props);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleSizeChange = this.handleSizeChange.bind(this);
const childrenCount = Children.count(props.children);
if (childrenCount === 0) {
// eslint-disable-next-line no-console
console.error(
'<DockMonitor> requires at least one monitor inside. ' +
'Why dont you try <LogMonitor>? You can get it at ' +
'https://github.com/gaearon/redux-devtools-log-monitor.'
);
} else if (childrenCount > 1 && !props.changeMonitorKey) {
// eslint-disable-next-line no-console
console.error(
'You specified multiple monitors inside <DockMonitor> ' +
'but did not provide `changeMonitorKey` prop to change them. ' +
'Try specifying <DockMonitor changeMonitorKey="ctrl-m" /> ' +
'and then press Ctrl-M.'
);
}
}
componentDidMount() {
window.addEventListener('keydown', this.handleKeyDown);
}
componentWillUnmount() {
window.removeEventListener('keydown', this.handleKeyDown);
}
matchesKey(key, event) {
if (!key) {
return false;
}
const charCode = event.keyCode || event.which;
const char = String.fromCharCode(charCode);
return (
key.name.toUpperCase() === char.toUpperCase() &&
key.alt === event.altKey &&
key.ctrl === event.ctrlKey &&
key.meta === event.metaKey &&
key.shift === event.shiftKey
);
}
handleKeyDown(e) {
// Ignore regular keys when focused on a field
// and no modifiers are active.
if (
!e.ctrlKey &&
!e.metaKey &&
!e.altKey &&
(e.target.tagName === 'INPUT' ||
e.target.tagName === 'SELECT' ||
e.target.tagName === 'TEXTAREA' ||
e.target.isContentEditable)
) {
return;
}
const visibilityKey = parseKey(this.props.toggleVisibilityKey);
const positionKey = parseKey(this.props.changePositionKey);
let monitorKey;
if (this.props.changeMonitorKey) {
monitorKey = parseKey(this.props.changeMonitorKey);
}
if (this.matchesKey(visibilityKey, e)) {
e.preventDefault();
this.props.dispatch(toggleVisibility());
} else if (this.matchesKey(positionKey, e)) {
e.preventDefault();
this.props.dispatch(changePosition());
} else if (this.matchesKey(monitorKey, e)) {
e.preventDefault();
this.props.dispatch(changeMonitor());
}
}
handleSizeChange(requestedSize) {
this.props.dispatch(changeSize(requestedSize));
}
renderChild(child, index, otherProps) {
const { monitorState } = this.props;
const { childMonitorIndex, childMonitorStates } = monitorState;
if (index !== childMonitorIndex) {
return null;
}
return cloneElement(child, {
monitorState: childMonitorStates[index],
...otherProps
});
}
render() {
const { monitorState, children, fluid, ...rest } = this.props;
const { position, isVisible, size } = monitorState;
return (
<Dock
position={position}
isVisible={isVisible}
size={size}
fluid={fluid}
onSizeChange={this.handleSizeChange}
dimMode="none"
>
{Children.map(children, (child, index) =>
this.renderChild(child, index, rest)
)}
</Dock>
);
}
}