mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2024-11-29 04:53:54 +03:00
Component-centric API, horrors are encapsulated
This commit is contained in:
parent
34d599af77
commit
79b51a7c0f
|
@ -28,8 +28,8 @@
|
||||||
"node-libs-browser": "^0.5.2",
|
"node-libs-browser": "^0.5.2",
|
||||||
"react-dock": "^0.1.0",
|
"react-dock": "^0.1.0",
|
||||||
"react-hot-loader": "^1.3.0",
|
"react-hot-loader": "^1.3.0",
|
||||||
"redux-devtools": "^3.0.0-alpha-7",
|
"redux-devtools": "^3.0.0-alpha-8",
|
||||||
"redux-devtools-log-monitor": "^1.0.0-alpha-7",
|
"redux-devtools-log-monitor": "^1.0.0-alpha-8",
|
||||||
"webpack": "^1.9.11",
|
"webpack": "^1.9.11",
|
||||||
"webpack-dev-server": "^1.9.0"
|
"webpack-dev-server": "^1.9.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
import React from 'react';
|
||||||
import { createDevTools } from 'redux-devtools';
|
import { createDevTools } from 'redux-devtools';
|
||||||
import createLogMonitor from 'redux-devtools-log-monitor';
|
import LogMonitor from 'redux-devtools-log-monitor';
|
||||||
import createDockMonitor from '../dock/DockMonitor';
|
import DockMonitor from '../dock/DockMonitor';
|
||||||
|
|
||||||
export default createDevTools(
|
export default createDevTools(
|
||||||
createDockMonitor(
|
<DockMonitor defaultPosition='bottom'>
|
||||||
createLogMonitor()
|
<LogMonitor theme='ocean' />
|
||||||
)
|
</DockMonitor>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,24 +2,36 @@
|
||||||
// TODO: extract to a separate project.
|
// TODO: extract to a separate project.
|
||||||
//
|
//
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { cloneElement, Children, Component, PropTypes } from 'react';
|
||||||
import Dock from 'react-dock';
|
import Dock from 'react-dock';
|
||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
|
|
||||||
const POSITIONS = ['left', 'top', 'right', 'bottom'];
|
const POSITIONS = ['left', 'top', 'right', 'bottom'];
|
||||||
|
|
||||||
class DockMonitor extends Component {
|
export default class DockMonitor extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
defaultPosition: PropTypes.oneOf(POSITIONS).isRequired,
|
||||||
|
defaultIsVisible: PropTypes.bool.isRequired,
|
||||||
|
toggleVisibilityShortcut: PropTypes.string.isRequired,
|
||||||
|
changePositionShortcut: PropTypes.string.isRequired,
|
||||||
|
|
||||||
monitorState: PropTypes.shape({
|
monitorState: PropTypes.shape({
|
||||||
position: PropTypes.oneOf(POSITIONS).isRequired,
|
position: PropTypes.oneOf(POSITIONS).isRequired,
|
||||||
isVisible: PropTypes.bool.isRequired,
|
isVisible: PropTypes.bool.isRequired,
|
||||||
child: PropTypes.any
|
child: PropTypes.any
|
||||||
}).isRequired,
|
}),
|
||||||
|
|
||||||
monitorActions: PropTypes.shape({
|
monitorActions: PropTypes.shape({
|
||||||
toggleVisibility: PropTypes.func.isRequired,
|
toggleVisibility: PropTypes.func.isRequired,
|
||||||
changePosition: PropTypes.func.isRequired
|
changePosition: PropTypes.func.isRequired
|
||||||
}).isRequired
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
defaultIsVisible: true,
|
||||||
|
defaultPosition: 'right',
|
||||||
|
toggleVisibilityShortcut: 'H',
|
||||||
|
changePositionShortcut: 'Q'
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -39,11 +51,11 @@ class DockMonitor extends Component {
|
||||||
|
|
||||||
const key = event.keyCode || event.which;
|
const key = event.keyCode || event.which;
|
||||||
const char = String.fromCharCode(key);
|
const char = String.fromCharCode(key);
|
||||||
switch (char) {
|
switch (char.toUpperCase()) {
|
||||||
case 'H':
|
case this.props.toggleVisibilityShortcut.toUpperCase():
|
||||||
this.props.monitorActions.toggleVisibility();
|
this.props.monitorActions.toggleVisibility();
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case this.props.changePositionShortcut.toUpperCase():
|
||||||
this.props.monitorActions.changePosition();
|
this.props.monitorActions.changePosition();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -52,13 +64,29 @@ class DockMonitor extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { children, monitorState } = this.props;
|
const {
|
||||||
const { position, isVisible } = monitorState;
|
monitorState,
|
||||||
|
monitorActions,
|
||||||
|
historyState,
|
||||||
|
historyActions,
|
||||||
|
children
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const {
|
||||||
|
position,
|
||||||
|
isVisible
|
||||||
|
} = monitorState;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dock position={position}
|
<Dock position={position}
|
||||||
isVisible={isVisible}
|
isVisible={isVisible}
|
||||||
dimMode='none'>
|
dimMode='none'>
|
||||||
{children}
|
{cloneElement(Children.only(children), {
|
||||||
|
monitorState: monitorState.child,
|
||||||
|
monitorActions: monitorActions.child,
|
||||||
|
historyState,
|
||||||
|
historyActions
|
||||||
|
})}
|
||||||
</Dock>
|
</Dock>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -74,43 +102,32 @@ function changePosition() {
|
||||||
return { type: CHANGE_POSITION };
|
return { type: CHANGE_POSITION };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function create(child, {
|
DockMonitor.setup = function setup(props) {
|
||||||
defaultIsVisible = true,
|
function position(state = props.defaultPosition, action) {
|
||||||
defaultPosition = 'right'
|
|
||||||
} = {}) {
|
|
||||||
function position(state = defaultPosition, action) {
|
|
||||||
return (action.type === CHANGE_POSITION) ?
|
return (action.type === CHANGE_POSITION) ?
|
||||||
POSITIONS[(POSITIONS.indexOf(state) + 1) % POSITIONS.length] :
|
POSITIONS[(POSITIONS.indexOf(state) + 1) % POSITIONS.length] :
|
||||||
state;
|
state;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isVisible(state = defaultIsVisible, action) {
|
function isVisible(state = props.defaultIsVisible, action) {
|
||||||
return (action.type === TOGGLE_VISIBILITY) ?
|
return (action.type === TOGGLE_VISIBILITY) ?
|
||||||
!state :
|
!state :
|
||||||
state;
|
state;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChildMonitor = child.component;
|
const child = Children.only(props.children);
|
||||||
const CompositeMonitor = ({ monitorState, monitorActions, ...rest }) => (
|
const childSetupResult = child.type.setup(child.props);
|
||||||
<DockMonitor monitorState={monitorState}
|
|
||||||
monitorActions={monitorActions}>
|
|
||||||
<ChildMonitor {...rest}
|
|
||||||
monitorState={monitorState.child}
|
|
||||||
monitorActions={monitorActions.child} />
|
|
||||||
</DockMonitor>
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
component: CompositeMonitor,
|
|
||||||
reducer: combineReducers({
|
reducer: combineReducers({
|
||||||
position,
|
position,
|
||||||
isVisible,
|
isVisible,
|
||||||
child: child.reducer
|
child: childSetupResult.reducer
|
||||||
}),
|
}),
|
||||||
actionCreators: {
|
actionCreators: {
|
||||||
toggleVisibility,
|
toggleVisibility,
|
||||||
changePosition,
|
changePosition,
|
||||||
child: child.actionCreators
|
child: childSetupResult.actionCreators
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "redux-devtools",
|
"name": "redux-devtools",
|
||||||
"version": "3.0.0-alpha-7",
|
"version": "3.0.0-alpha-8",
|
||||||
"description": "Redux DevTools with hot reloading and time travel",
|
"description": "Redux DevTools with hot reloading and time travel",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import bindActionCreatorsDeep from './bindActionCreatorsDeep';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { ActionCreators as historyActionCreators } from './instrument';
|
|
||||||
|
|
||||||
export default function connectMonitor({
|
|
||||||
component,
|
|
||||||
reducer = () => null,
|
|
||||||
actionCreators = {}
|
|
||||||
}) {
|
|
||||||
function mapStateToProps(state) {
|
|
||||||
return {
|
|
||||||
historyState: state.historyState,
|
|
||||||
monitorState: state.monitorState
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
|
||||||
return {
|
|
||||||
historyActions: bindActionCreators(historyActionCreators, dispatch),
|
|
||||||
monitorActions: bindActionCreatorsDeep(actionCreators, dispatch)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const Monitor = connect(mapStateToProps, mapDispatchToProps)(component);
|
|
||||||
Monitor.reducer = reducer;
|
|
||||||
return Monitor;
|
|
||||||
}
|
|
|
@ -1,21 +1,49 @@
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Children, Component, PropTypes } from 'react';
|
||||||
import instrument from './instrument';
|
import { connect } from 'react-redux';
|
||||||
import connectMonitor from './connectMonitor';
|
import { bindActionCreators } from 'redux';
|
||||||
|
import bindActionCreatorsDeep from './bindActionCreatorsDeep';
|
||||||
|
import instrument, { ActionCreators as historyActionCreators } from './instrument';
|
||||||
|
|
||||||
export default function createDevTools(monitor) {
|
export default function createDevTools(children) {
|
||||||
const Monitor = connectMonitor(monitor);
|
const child = Children.only(children);
|
||||||
|
const { type: Monitor } = child;
|
||||||
|
const { reducer, actionCreators } = Monitor.setup(child.props);
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
historyState: state.historyState,
|
||||||
|
monitorState: state.monitorState
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapDispatchToProps(dispatch) {
|
||||||
|
return {
|
||||||
|
historyActions: bindActionCreators(historyActionCreators, dispatch),
|
||||||
|
monitorActions: bindActionCreatorsDeep(actionCreators, dispatch)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const ConnectedMonitor = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(Monitor);
|
||||||
|
|
||||||
return class DevTools extends Component {
|
return class DevTools extends Component {
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
store: PropTypes.object.isRequired
|
store: PropTypes.object.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
static instrument = () => instrument(Monitor.reducer);
|
static instrument = () => instrument(reducer);
|
||||||
|
|
||||||
|
constructor(props, context) {
|
||||||
|
super(props, context);
|
||||||
|
this.instrumentedStore = context.store.instrumentedStore;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Monitor {...this.props}
|
<ConnectedMonitor {...child.props}
|
||||||
store={this.context.store.instrumentedStore} />
|
store={this.instrumentedStore} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user