mirror of
				https://github.com/reduxjs/redux-devtools.git
				synced 2025-10-30 23:47:35 +03:00 
			
		
		
		
	Add redux-devtools-dock-monitor package (#561)
* Stash * Cleanup * Fix * Add export default from plugin * Remove empty test
This commit is contained in:
		
							parent
							
								
									c924091e8c
								
							
						
					
					
						commit
						ebdf32661e
					
				|  | @ -7,7 +7,7 @@ | ||||||
|     "clean": "rimraf lib", |     "clean": "rimraf lib", | ||||||
|     "build": "babel src --out-dir lib", |     "build": "babel src --out-dir lib", | ||||||
|     "prepare": "npm run build", |     "prepare": "npm run build", | ||||||
|     "prepublishOnly": "npm run lint && npm run clean && npm run build" |     "prepublishOnly": "npm run clean && npm run build" | ||||||
|   }, |   }, | ||||||
|   "files": [ |   "files": [ | ||||||
|     "lib", |     "lib", | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								packages/redux-devtools-dock-monitor/.babelrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								packages/redux-devtools-dock-monitor/.babelrc
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | ||||||
|  | { | ||||||
|  |   "presets": ["@babel/preset-env", "@babel/preset-react"], | ||||||
|  |   "plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-export-default-from"] | ||||||
|  | } | ||||||
							
								
								
									
										63
									
								
								packages/redux-devtools-dock-monitor/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								packages/redux-devtools-dock-monitor/README.md
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | ||||||
|  | # Redux DevTools Dock Monitor | ||||||
|  | 
 | ||||||
|  | A resizable and movable dock for [Redux DevTools](https://github.com/reduxjs/redux-devtools).   | ||||||
|  | Powered by [React Dock](https://github.com/alexkuz/react-dock). | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | 
 | ||||||
|  | ### Installation | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | yarn add redux-devtools-dock-monitor | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ### Usage | ||||||
|  | 
 | ||||||
|  | Wrap any other Redux DevTools monitor in `DockMonitor` to make it dockable to different screen edges. | ||||||
|  | For example, you can use it together with [`LogMonitor`](https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-log-monitor): | ||||||
|  | 
 | ||||||
|  | ##### `containers/DevTools.js` | ||||||
|  | 
 | ||||||
|  | ```js | ||||||
|  | import React from 'react'; | ||||||
|  | import { createDevTools } from 'redux-devtools'; | ||||||
|  | import LogMonitor from 'redux-devtools-log-monitor'; | ||||||
|  | import SliderMonitor from 'redux-slider-monitor'; | ||||||
|  | import DockMonitor from 'redux-devtools-dock-monitor'; | ||||||
|  | 
 | ||||||
|  | export default createDevTools( | ||||||
|  |   <DockMonitor | ||||||
|  |     toggleVisibilityKey="ctrl-h" | ||||||
|  |     changePositionKey="ctrl-q" | ||||||
|  |     changeMonitorKey="ctrl-m" | ||||||
|  |   > | ||||||
|  |     <LogMonitor /> | ||||||
|  |     <SliderMonitor /> | ||||||
|  |   </DockMonitor> | ||||||
|  | ); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | [Read how to start using Redux DevTools.](https://github.com/reduxjs/redux-devtools) | ||||||
|  | 
 | ||||||
|  | #### Multiple Monitors | ||||||
|  | 
 | ||||||
|  | You can put more than one monitor inside `<DockMonitor>`. There will still be a single dock, but you will be able to switch between different monitors by pressing a key specified as `changeMonitorKey` prop. | ||||||
|  | 
 | ||||||
|  | ### Props | ||||||
|  | 
 | ||||||
|  | | Name                  | Description                                                                                                                                                                                                              | | ||||||
|  | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||||||
|  | | `children`            | Any valid Redux DevTools monitor. Required.                                                                                                                                                                              | | ||||||
|  | | `toggleVisibilityKey` | A key or a key combination that toggles the dock visibility. Must be recognizable by [parse-key](https://github.com/thlorenz/parse-key) (for example, `'ctrl-h'`). Required.                                             | | ||||||
|  | | `changePositionKey`   | A key or a key combination that toggles the dock position. Must be recognizable by [parse-key](https://github.com/thlorenz/parse-key) (for example, `'ctrl-w'`). Required.                                               | | ||||||
|  | | `changeMonitorKey`    | A key or a key combination that switches the currently visible monitor. Must be recognizable by [parse-key](https://github.com/thlorenz/parse-key) (for example, `'ctrl-m'`). Required if you use more than one monitor. | | ||||||
|  | | `fluid`               | When `true`, the dock size is a fraction of the window size, fixed otherwise. Optional. By default set to `true`.                                                                                                        | | ||||||
|  | | `defaultSize`         | Size of the dock. When `fluid` is `true`, a float (`0.5` means half the window size). When `fluid` is `false`, a width in pixels. Optional. By default set to `0.3` (3/10th of the window size).                         | | ||||||
|  | | `defaultPosition`     | Where the dock appears on the screen. Valid values: `'left'`, `'top'`, `'right'`, `'bottom'`. Optional. By default set to `'right'`.                                                                                     | | ||||||
|  | | `defaultIsVisible`    | Defines whether dock should be open by default. A value of `true` means that it's open when the page/app loads.                                                                                                          | | ||||||
|  | 
 | ||||||
|  | The current size and the position are persisted between sessions with `persistState()` enhancer from Redux DevTools. | ||||||
|  | 
 | ||||||
|  | ### License | ||||||
|  | 
 | ||||||
|  | MIT | ||||||
							
								
								
									
										56
									
								
								packages/redux-devtools-dock-monitor/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								packages/redux-devtools-dock-monitor/package.json
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,56 @@ | ||||||
|  | { | ||||||
|  |   "name": "redux-devtools-dock-monitor", | ||||||
|  |   "version": "1.1.3", | ||||||
|  |   "description": "A resizable and movable dock for Redux DevTools monitors", | ||||||
|  |   "main": "lib/index.js", | ||||||
|  |   "files": [ | ||||||
|  |     "lib", | ||||||
|  |     "src" | ||||||
|  |   ], | ||||||
|  |   "scripts": { | ||||||
|  |     "clean": "rimraf lib", | ||||||
|  |     "build": "babel src --out-dir lib", | ||||||
|  |     "prepare": "npm run build", | ||||||
|  |     "prepublishOnly": "npm run test && npm run clean && npm run build" | ||||||
|  |   }, | ||||||
|  |   "repository": { | ||||||
|  |     "type": "git", | ||||||
|  |     "url": "https://github.com/reduxjs/redux-devtools.git" | ||||||
|  |   }, | ||||||
|  |   "keywords": [ | ||||||
|  |     "redux", | ||||||
|  |     "devtools", | ||||||
|  |     "flux", | ||||||
|  |     "react", | ||||||
|  |     "hot reloading", | ||||||
|  |     "time travel", | ||||||
|  |     "live edit" | ||||||
|  |   ], | ||||||
|  |   "author": "Dan Abramov <dan.abramov@me.com> (http://github.com/gaearon)", | ||||||
|  |   "license": "MIT", | ||||||
|  |   "bugs": { | ||||||
|  |     "url": "https://github.com/reduxjs/redux-devtools/issues" | ||||||
|  |   }, | ||||||
|  |   "homepage": "https://github.com/reduxjs/redux-devtools", | ||||||
|  |   "devDependencies": { | ||||||
|  |     "@babel/cli": "^7.10.5", | ||||||
|  |     "@babel/core": "^7.11.0", | ||||||
|  |     "@babel/plugin-proposal-class-properties": "^7.10.4", | ||||||
|  |     "@babel/plugin-proposal-export-default-from": "^7.10.4", | ||||||
|  |     "@babel/preset-env": "^7.11.0", | ||||||
|  |     "@babel/preset-react": "^7.10.4", | ||||||
|  |     "babel-loader": "^8.1.0", | ||||||
|  |     "rimraf": "^2.7.1" | ||||||
|  |   }, | ||||||
|  |   "peerDependencies": { | ||||||
|  |     "react": "^0.14.9 || ^15.3.0 || ^16.0.0", | ||||||
|  |     "redux-devtools": "^3.4.0" | ||||||
|  |   }, | ||||||
|  |   "dependencies": { | ||||||
|  |     "babel-runtime": "^6.26.0", | ||||||
|  |     "parse-key": "^0.2.1", | ||||||
|  |     "prop-types": "^15.7.2", | ||||||
|  |     "react-dock": "^0.2.4", | ||||||
|  |     "react-pure-render": "^1.0.2" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										162
									
								
								packages/redux-devtools-dock-monitor/src/DockMonitor.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								packages/redux-devtools-dock-monitor/src/DockMonitor.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,162 @@ | ||||||
|  | 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 don’t 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> | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								packages/redux-devtools-dock-monitor/src/actions.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								packages/redux-devtools-dock-monitor/src/actions.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | ||||||
|  | export const TOGGLE_VISIBILITY = | ||||||
|  |   '@@redux-devtools-log-monitor/TOGGLE_VISIBILITY'; | ||||||
|  | export function toggleVisibility() { | ||||||
|  |   return { type: TOGGLE_VISIBILITY }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const CHANGE_POSITION = '@@redux-devtools-log-monitor/CHANGE_POSITION'; | ||||||
|  | export function changePosition() { | ||||||
|  |   return { type: CHANGE_POSITION }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const CHANGE_SIZE = '@@redux-devtools-log-monitor/CHANGE_SIZE'; | ||||||
|  | export function changeSize(size) { | ||||||
|  |   return { type: CHANGE_SIZE, size: size }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const CHANGE_MONITOR = '@@redux-devtools-log-monitor/CHANGE_MONITOR'; | ||||||
|  | export function changeMonitor() { | ||||||
|  |   return { type: CHANGE_MONITOR }; | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								packages/redux-devtools-dock-monitor/src/constants.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								packages/redux-devtools-dock-monitor/src/constants.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | export const POSITIONS = ['left', 'top', 'right', 'bottom']; | ||||||
							
								
								
									
										1
									
								
								packages/redux-devtools-dock-monitor/src/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								packages/redux-devtools-dock-monitor/src/index.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | export default from './DockMonitor'; | ||||||
							
								
								
									
										68
									
								
								packages/redux-devtools-dock-monitor/src/reducers.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								packages/redux-devtools-dock-monitor/src/reducers.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,68 @@ | ||||||
|  | import { | ||||||
|  |   CHANGE_MONITOR, | ||||||
|  |   CHANGE_POSITION, | ||||||
|  |   CHANGE_SIZE, | ||||||
|  |   TOGGLE_VISIBILITY | ||||||
|  | } from './actions'; | ||||||
|  | import { POSITIONS } from './constants'; | ||||||
|  | import { Children } from 'react'; | ||||||
|  | 
 | ||||||
|  | function position(props, state = props.defaultPosition, action) { | ||||||
|  |   return action.type === CHANGE_POSITION | ||||||
|  |     ? POSITIONS[(POSITIONS.indexOf(state) + 1) % POSITIONS.length] | ||||||
|  |     : state; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function size(props, state = props.defaultSize, action) { | ||||||
|  |   return action.type === CHANGE_SIZE ? action.size : state; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function isVisible(props, state = props.defaultIsVisible, action) { | ||||||
|  |   return action.type === TOGGLE_VISIBILITY ? !state : state; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function childMonitorStates(props, state = [], action) { | ||||||
|  |   return Children.map(props.children, (child, index) => | ||||||
|  |     child.type.update(child.props, state[index], action) | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function childMonitorIndex(props, state = 0, action) { | ||||||
|  |   switch (action.type) { | ||||||
|  |     case CHANGE_MONITOR: | ||||||
|  |       return (state + 1) % Children.count(props.children); | ||||||
|  |     default: | ||||||
|  |       return state; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export default function reducer(props, state = {}, action) { | ||||||
|  |   if (!state.childMonitorStates) { | ||||||
|  |     Children.forEach(props.children, (child, index) => { | ||||||
|  |       if (typeof child.type.update !== 'function') { | ||||||
|  |         // eslint-disable-next-line no-console
 | ||||||
|  |         console.error( | ||||||
|  |           `Child of <DockMonitor> with the index ${index} ` + | ||||||
|  |             `(${child.type.displayName || child.type.name || child.type}) ` + | ||||||
|  |             'does not appear to be a valid Redux DevTools monitor.' | ||||||
|  |         ); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return { | ||||||
|  |     position: position(props, state.position, action), | ||||||
|  |     isVisible: isVisible(props, state.isVisible, action), | ||||||
|  |     size: size(props, state.size, action), | ||||||
|  |     childMonitorIndex: childMonitorIndex( | ||||||
|  |       props, | ||||||
|  |       state.childMonitorIndex, | ||||||
|  |       action | ||||||
|  |     ), | ||||||
|  |     childMonitorStates: childMonitorStates( | ||||||
|  |       props, | ||||||
|  |       state.childMonitorStates, | ||||||
|  |       action | ||||||
|  |     ) | ||||||
|  |   }; | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user