From f7107df27883bdf92e4badf0387922d016555398 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Wed, 26 Aug 2020 00:03:56 -0400 Subject: [PATCH] more --- packages/react-dock/src/Dock.tsx | 23 ++++-- packages/redux-devtools-dock-monitor/.babelrc | 4 +- .../redux-devtools-dock-monitor/package.json | 7 ++ .../src/DockMonitor.tsx | 77 +++++++++++++++---- .../src/actions.ts | 27 ++++++- .../src/constants.ts | 2 +- .../src/parse-key.ts | 12 +++ .../src/reducers.ts | 55 +++++++++++-- .../redux-devtools/src/createDevTools.tsx | 2 +- packages/redux-devtools/src/index.ts | 3 +- 10 files changed, 169 insertions(+), 43 deletions(-) create mode 100644 packages/redux-devtools-dock-monitor/src/parse-key.ts diff --git a/packages/react-dock/src/Dock.tsx b/packages/react-dock/src/Dock.tsx index 2889032a..d06c5e8f 100644 --- a/packages/react-dock/src/Dock.tsx +++ b/packages/react-dock/src/Dock.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { Component, ReactNode } from 'react'; import PropTypes from 'prop-types'; import debounce from 'lodash.debounce'; import autoprefix from './autoprefix'; @@ -227,12 +227,14 @@ interface Props { dockStyle?: React.CSSProperties | null; dockHiddenStyle?: React.CSSProperties | null; duration: number; - children?: React.FunctionComponent<{ - position: 'left' | 'right' | 'top' | 'bottom'; - isResizing: boolean | undefined; - size: number; - isVisible: boolean | undefined; - }>; + children?: + | React.FunctionComponent<{ + position: 'left' | 'right' | 'top' | 'bottom'; + isResizing: boolean | undefined; + size: number; + isVisible: boolean | undefined; + }> + | ReactNode; } interface State { @@ -376,7 +378,12 @@ export default class Dock extends Component { />
{typeof children === 'function' - ? children({ + ? (children as React.FunctionComponent<{ + position: 'left' | 'right' | 'top' | 'bottom'; + isResizing: boolean | undefined; + size: number; + isVisible: boolean | undefined; + }>)({ position, isResizing, size, diff --git a/packages/redux-devtools-dock-monitor/.babelrc b/packages/redux-devtools-dock-monitor/.babelrc index 8cc520a8..0d42ef44 100644 --- a/packages/redux-devtools-dock-monitor/.babelrc +++ b/packages/redux-devtools-dock-monitor/.babelrc @@ -4,7 +4,5 @@ "@babel/preset-react", "@babel/preset-typescript" ], - "plugins": [ - "@babel/plugin-proposal-class-properties" - ] + "plugins": ["@babel/plugin-proposal-class-properties"] } diff --git a/packages/redux-devtools-dock-monitor/package.json b/packages/redux-devtools-dock-monitor/package.json index 27ed478f..e53a621a 100644 --- a/packages/redux-devtools-dock-monitor/package.json +++ b/packages/redux-devtools-dock-monitor/package.json @@ -45,9 +45,16 @@ "prop-types": "^15.7.2", "react-dock": "^0.2.4" }, + "devDependencies": { + "@types/react": "^16.9.46", + "react": "^16.13.1", + "redux": "^4.0.5", + "redux-devtools": "^3.6.1" + }, "peerDependencies": { "@types/react": "^16.3.18", "react": "^16.3.0", + "redux": "^3.4.0 || ^4.0.0", "redux-devtools": "^3.4.0" } } diff --git a/packages/redux-devtools-dock-monitor/src/DockMonitor.tsx b/packages/redux-devtools-dock-monitor/src/DockMonitor.tsx index 99427463..69d1ce2f 100644 --- a/packages/redux-devtools-dock-monitor/src/DockMonitor.tsx +++ b/packages/redux-devtools-dock-monitor/src/DockMonitor.tsx @@ -1,17 +1,55 @@ -import React, { cloneElement, Children, Component } from 'react'; +import React, { + cloneElement, + Children, + Component, + ReactNode, + ReactElement, +} from 'react'; import PropTypes from 'prop-types'; import Dock from 'react-dock'; +import { Action, Dispatch } from 'redux'; +import { LiftedState, Monitor } from 'redux-devtools'; import { POSITIONS } from './constants'; import { toggleVisibility, changeMonitor, changePosition, changeSize, + DockMonitorAction, } from './actions'; -import reducer from './reducers'; +import reducer, { DockMonitorState } from './reducers'; import parseKey from 'parse-key'; -export default class DockMonitor extends Component { +interface KeyObject { + name: string; + ctrl: boolean; + meta: boolean; + shift: boolean; + alt: boolean; + sequence: string; +} + +export interface DockMonitorProps> + extends LiftedState { + defaultPosition: 'left' | 'top' | 'right' | 'bottom'; + defaultIsVisible: boolean; + defaultSize: number; + toggleVisibilityKey: string; + changePositionKey: string; + changeMonitorKey?: string; + fluid: boolean; + + dispatch: Dispatch; + + children: + | Monitor> + | Monitor>[]; +} + +export default class DockMonitor< + S, + A extends Action +> extends Component> { static update = reducer; static propTypes = { @@ -39,10 +77,8 @@ export default class DockMonitor extends Component { fluid: true, }; - constructor(props) { + constructor(props: DockMonitorProps) { super(props); - this.handleKeyDown = this.handleKeyDown.bind(this); - this.handleSizeChange = this.handleSizeChange.bind(this); const childrenCount = Children.count(props.children); if (childrenCount === 0) { @@ -71,7 +107,7 @@ export default class DockMonitor extends Component { window.removeEventListener('keydown', this.handleKeyDown); } - matchesKey(key, event) { + matchesKey(key: KeyObject | undefined, event: KeyboardEvent) { if (!key) { return false; } @@ -87,17 +123,17 @@ export default class DockMonitor extends Component { ); } - handleKeyDown(e) { + handleKeyDown = (e: KeyboardEvent) => { // 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) + ((e.target! as { tagName?: string }).tagName === 'INPUT' || + (e.target! as { tagName?: string }).tagName === 'SELECT' || + (e.target! as { tagName?: string }).tagName === 'TEXTAREA' || + (e.target! as { isContentEditable?: boolean }).isContentEditable) ) { return; } @@ -120,13 +156,20 @@ export default class DockMonitor extends Component { e.preventDefault(); this.props.dispatch(changeMonitor()); } - } + }; - handleSizeChange(requestedSize) { + handleSizeChange = (requestedSize: number) => { this.props.dispatch(changeSize(requestedSize)); - } + }; - renderChild(child, index, otherProps) { + renderChild( + child: ReactElement, + index: number, + otherProps: Omit< + DockMonitorProps, + 'monitorState' | 'children' | 'fluid' + > + ) { const { monitorState } = this.props; const { childMonitorIndex, childMonitorStates } = monitorState; @@ -153,7 +196,7 @@ export default class DockMonitor extends Component { onSizeChange={this.handleSizeChange} dimMode="none" > - {Children.map(children, (child, index) => + {Children.map(children, (child, index) => this.renderChild(child, index, rest) )} diff --git a/packages/redux-devtools-dock-monitor/src/actions.ts b/packages/redux-devtools-dock-monitor/src/actions.ts index d253293c..42db490e 100644 --- a/packages/redux-devtools-dock-monitor/src/actions.ts +++ b/packages/redux-devtools-dock-monitor/src/actions.ts @@ -1,20 +1,39 @@ export const TOGGLE_VISIBILITY = '@@redux-devtools-log-monitor/TOGGLE_VISIBILITY'; -export function toggleVisibility() { +interface ToggleVisibilityAction { + type: typeof TOGGLE_VISIBILITY; +} +export function toggleVisibility(): ToggleVisibilityAction { return { type: TOGGLE_VISIBILITY }; } export const CHANGE_POSITION = '@@redux-devtools-log-monitor/CHANGE_POSITION'; -export function changePosition() { +interface ChangePositionAction { + type: typeof CHANGE_POSITION; +} +export function changePosition(): ChangePositionAction { return { type: CHANGE_POSITION }; } export const CHANGE_SIZE = '@@redux-devtools-log-monitor/CHANGE_SIZE'; -export function changeSize(size) { +interface ChangeSizeAction { + type: typeof CHANGE_SIZE; + size: number; +} +export function changeSize(size: number): ChangeSizeAction { return { type: CHANGE_SIZE, size: size }; } export const CHANGE_MONITOR = '@@redux-devtools-log-monitor/CHANGE_MONITOR'; -export function changeMonitor() { +interface ChangeMonitorAction { + type: typeof CHANGE_MONITOR; +} +export function changeMonitor(): ChangeMonitorAction { return { type: CHANGE_MONITOR }; } + +export type DockMonitorAction = + | ToggleVisibilityAction + | ChangePositionAction + | ChangeSizeAction + | ChangeMonitorAction; diff --git a/packages/redux-devtools-dock-monitor/src/constants.ts b/packages/redux-devtools-dock-monitor/src/constants.ts index e935427f..38c503d4 100644 --- a/packages/redux-devtools-dock-monitor/src/constants.ts +++ b/packages/redux-devtools-dock-monitor/src/constants.ts @@ -1 +1 @@ -export const POSITIONS = ['left', 'top', 'right', 'bottom']; +export const POSITIONS = ['left', 'top', 'right', 'bottom'] as const; diff --git a/packages/redux-devtools-dock-monitor/src/parse-key.ts b/packages/redux-devtools-dock-monitor/src/parse-key.ts new file mode 100644 index 00000000..e3cda606 --- /dev/null +++ b/packages/redux-devtools-dock-monitor/src/parse-key.ts @@ -0,0 +1,12 @@ +declare module 'parse-key' { + interface KeyObject { + name: string; + ctrl: boolean; + meta: boolean; + shift: boolean; + alt: boolean; + sequence: string; + } + + export default function parse(s: string): KeyObject; +} diff --git a/packages/redux-devtools-dock-monitor/src/reducers.ts b/packages/redux-devtools-dock-monitor/src/reducers.ts index ff28f53e..eb2e4d91 100644 --- a/packages/redux-devtools-dock-monitor/src/reducers.ts +++ b/packages/redux-devtools-dock-monitor/src/reducers.ts @@ -1,33 +1,64 @@ +import { Children } from 'react'; +import { Action } from 'redux'; import { CHANGE_MONITOR, CHANGE_POSITION, CHANGE_SIZE, + DockMonitorAction, TOGGLE_VISIBILITY, } from './actions'; import { POSITIONS } from './constants'; -import { Children } from 'react'; +import { DockMonitorProps } from './DockMonitor'; -function position(props, state = props.defaultPosition, action) { +export interface DockMonitorState { + position: 'left' | 'top' | 'right' | 'bottom'; + size: number; + isVisible: boolean; + childMonitorStates: unknown[]; + childMonitorIndex: number; +} + +function position>( + props: DockMonitorProps, + state = props.defaultPosition, + action: DockMonitorAction +) { return action.type === CHANGE_POSITION ? POSITIONS[(POSITIONS.indexOf(state) + 1) % POSITIONS.length] : state; } -function size(props, state = props.defaultSize, action) { +function size>( + props: DockMonitorProps, + state = props.defaultSize, + action: DockMonitorAction +) { return action.type === CHANGE_SIZE ? action.size : state; } -function isVisible(props, state = props.defaultIsVisible, action) { +function isVisible>( + props: DockMonitorProps, + state = props.defaultIsVisible, + action: DockMonitorAction +) { return action.type === TOGGLE_VISIBILITY ? !state : state; } -function childMonitorStates(props, state = [], action) { +function childMonitorStates>( + props: DockMonitorProps, + state: unknown[] = [], + action: DockMonitorAction +) { return Children.map(props.children, (child, index) => child.type.update(child.props, state[index], action) ); } -function childMonitorIndex(props, state = 0, action) { +function childMonitorIndex>( + props: DockMonitorProps, + state = 0, + action: DockMonitorAction +) { switch (action.type) { case CHANGE_MONITOR: return (state + 1) % Children.count(props.children); @@ -36,14 +67,22 @@ function childMonitorIndex(props, state = 0, action) { } } -export default function reducer(props, state = {}, action) { +export default function reducer>( + props: DockMonitorProps, + state: Partial = {}, + action: DockMonitorAction +): DockMonitorState { 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 with the index ${index} ` + - `(${child.type.displayName || child.type.name || child.type}) ` + + `(${ + child.type.displayName || + child.type.name || + ((child.type as unknown) as string) + }) ` + 'does not appear to be a valid Redux DevTools monitor.' ); } diff --git a/packages/redux-devtools/src/createDevTools.tsx b/packages/redux-devtools/src/createDevTools.tsx index 13f76ad5..a76fc06b 100644 --- a/packages/redux-devtools/src/createDevTools.tsx +++ b/packages/redux-devtools/src/createDevTools.tsx @@ -34,7 +34,7 @@ interface Props< store?: EnhancedStore; } -type Monitor< +export type Monitor< S, A extends Action, MonitorProps, diff --git a/packages/redux-devtools/src/index.ts b/packages/redux-devtools/src/index.ts index 83d28bcb..33ca13ff 100644 --- a/packages/redux-devtools/src/index.ts +++ b/packages/redux-devtools/src/index.ts @@ -2,6 +2,7 @@ export { default as instrument, ActionCreators, ActionTypes, + LiftedState, } from 'redux-devtools-instrument'; export { default as persistState } from './persistState'; -export { default as createDevTools } from './createDevTools'; +export { default as createDevTools, Monitor } from './createDevTools';