From 2faa16319b59ece946757af7630ca4ab1264f1f5 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Thu, 27 Aug 2020 09:19:37 -0400 Subject: [PATCH] feat(redux-devtools-log-monitor): convert to TypeScript (#613) * Stash * And that * finish * fix up dependencies --- packages/redux-devtools-log-monitor/.babelrc | 11 +-- .../redux-devtools-log-monitor/.eslintignore | 1 + .../redux-devtools-log-monitor/.eslintrc.js | 13 ++++ .../redux-devtools-log-monitor/package.json | 69 ++++++++++-------- .../src/{LogMonitor.js => LogMonitor.tsx} | 69 +++++++++++------- ...gMonitorButton.js => LogMonitorButton.tsx} | 58 +++++++-------- ...orButtonBar.js => LogMonitorButtonBar.tsx} | 50 +++++++------ ...LogMonitorEntry.js => LogMonitorEntry.tsx} | 72 +++++++++++++------ ...tryAction.js => LogMonitorEntryAction.tsx} | 32 ++++++--- ...orEntryList.js => LogMonitorEntryList.tsx} | 30 ++++++-- .../redux-devtools-log-monitor/src/actions.js | 11 --- .../redux-devtools-log-monitor/src/actions.ts | 25 +++++++ .../src/{brighten.js => brighten.ts} | 4 +- .../redux-devtools-log-monitor/src/index.js | 1 - .../redux-devtools-log-monitor/src/index.ts | 2 + .../src/reducers.js | 24 ------- .../src/reducers.ts | 47 ++++++++++++ .../redux-devtools-log-monitor/tsconfig.json | 7 ++ yarn.lock | 9 ++- 19 files changed, 345 insertions(+), 190 deletions(-) create mode 100644 packages/redux-devtools-log-monitor/.eslintignore create mode 100644 packages/redux-devtools-log-monitor/.eslintrc.js rename packages/redux-devtools-log-monitor/src/{LogMonitor.js => LogMonitor.tsx} (78%) rename packages/redux-devtools-log-monitor/src/{LogMonitorButton.js => LogMonitorButton.tsx} (64%) rename packages/redux-devtools-log-monitor/src/{LogMonitorButtonBar.js => LogMonitorButtonBar.tsx} (62%) rename packages/redux-devtools-log-monitor/src/{LogMonitorEntry.js => LogMonitorEntry.tsx} (70%) rename packages/redux-devtools-log-monitor/src/{LogMonitorEntryAction.js => LogMonitorEntryAction.tsx} (63%) rename packages/redux-devtools-log-monitor/src/{LogMonitorEntryList.js => LogMonitorEntryList.tsx} (70%) delete mode 100644 packages/redux-devtools-log-monitor/src/actions.js create mode 100644 packages/redux-devtools-log-monitor/src/actions.ts rename packages/redux-devtools-log-monitor/src/{brighten.js => brighten.ts} (79%) delete mode 100644 packages/redux-devtools-log-monitor/src/index.js create mode 100644 packages/redux-devtools-log-monitor/src/index.ts delete mode 100644 packages/redux-devtools-log-monitor/src/reducers.js create mode 100644 packages/redux-devtools-log-monitor/src/reducers.ts create mode 100644 packages/redux-devtools-log-monitor/tsconfig.json diff --git a/packages/redux-devtools-log-monitor/.babelrc b/packages/redux-devtools-log-monitor/.babelrc index 2d8ea82b..0d42ef44 100644 --- a/packages/redux-devtools-log-monitor/.babelrc +++ b/packages/redux-devtools-log-monitor/.babelrc @@ -1,7 +1,8 @@ { - "presets": ["@babel/preset-env", "@babel/preset-react"], - "plugins": [ - "@babel/plugin-proposal-class-properties", - "@babel/plugin-proposal-export-default-from" - ] + "presets": [ + "@babel/preset-env", + "@babel/preset-react", + "@babel/preset-typescript" + ], + "plugins": ["@babel/plugin-proposal-class-properties"] } diff --git a/packages/redux-devtools-log-monitor/.eslintignore b/packages/redux-devtools-log-monitor/.eslintignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/redux-devtools-log-monitor/.eslintignore @@ -0,0 +1 @@ +lib diff --git a/packages/redux-devtools-log-monitor/.eslintrc.js b/packages/redux-devtools-log-monitor/.eslintrc.js new file mode 100644 index 00000000..e98ddf18 --- /dev/null +++ b/packages/redux-devtools-log-monitor/.eslintrc.js @@ -0,0 +1,13 @@ +module.exports = { + extends: '../../.eslintrc', + overrides: [ + { + files: ['*.ts', '*.tsx'], + extends: '../../eslintrc.ts.react.base.json', + parserOptions: { + tsconfigRootDir: __dirname, + project: ['./tsconfig.json'], + }, + }, + ], +}; diff --git a/packages/redux-devtools-log-monitor/package.json b/packages/redux-devtools-log-monitor/package.json index 43bfb4b3..a4799c6c 100644 --- a/packages/redux-devtools-log-monitor/package.json +++ b/packages/redux-devtools-log-monitor/package.json @@ -2,21 +2,6 @@ "name": "redux-devtools-log-monitor", "version": "2.0.1", "description": "The default tree view monitor for Redux DevTools", - "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" - }, "keywords": [ "redux", "devtools", @@ -26,31 +11,53 @@ "time travel", "live edit" ], - "author": "Dan Abramov (http://github.com/gaearon)", - "license": "MIT", + "homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-log-monitor", "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.1", - "@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": "^3.0.2" + "license": "MIT", + "author": "Dan Abramov (http://github.com/gaearon)", + "files": [ + "lib", + "src" + ], + "main": "lib/index.js", + "types": "lib/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/reduxjs/redux-devtools" }, - "peerDependencies": { - "react": "^16.3.0", - "redux-devtools": "^3.4.0" + "scripts": { + "build": "npm run build:types && npm run build:js", + "build:types": "tsc --emitDeclarationOnly", + "build:js": "babel src --out-dir lib --extensions \".ts,.tsx\" --source-maps inline", + "clean": "rimraf lib", + "lint": "eslint . --ext .ts,.tsx", + "lint:fix": "eslint . --ext .ts,.tsx --fix", + "type-check": "tsc --noEmit", + "type-check:watch": "npm run type-check -- --watch", + "preversion": "npm run type-check && npm run lint && npm run test", + "prepublishOnly": "npm run clean && npm run build" }, "dependencies": { + "@types/lodash.debounce": "^4.0.6", + "@types/prop-types": "^15.7.3", + "@types/redux-devtools-themes": "^1.0.0", "lodash.debounce": "^4.0.8", "prop-types": "^15.7.2", "react-json-tree": "^0.12.1", - "react-pure-render": "^1.0.2", "redux-devtools-themes": "^1.0.0" + }, + "devDependencies": { + "@types/react": "^16.9.46", + "react": "^16.13.1", + "redux": "^4.0.5", + "redux-devtools": "^3.6.1" + }, + "peerDependencies": { + "@types/react": "^16.9.46", + "react": "^16.3.0", + "redux": "^4.0.5", + "redux-devtools": "^3.4.0" } } diff --git a/packages/redux-devtools-log-monitor/src/LogMonitor.js b/packages/redux-devtools-log-monitor/src/LogMonitor.tsx similarity index 78% rename from packages/redux-devtools-log-monitor/src/LogMonitor.js rename to packages/redux-devtools-log-monitor/src/LogMonitor.tsx index 4c0867d7..132cfe36 100644 --- a/packages/redux-devtools-log-monitor/src/LogMonitor.js +++ b/packages/redux-devtools-log-monitor/src/LogMonitor.tsx @@ -1,17 +1,26 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; -import shouldPureComponentUpdate from 'react-pure-render/function'; +import { Action, Dispatch } from 'redux'; import * as themes from 'redux-devtools-themes'; -import { ActionCreators } from 'redux-devtools'; -import { updateScrollTop, startConsecutiveToggle } from './actions'; -import reducer from './reducers'; +import { Base16Theme } from 'redux-devtools-themes'; +import { ActionCreators, LiftedAction, LiftedState } from 'redux-devtools'; +import { + updateScrollTop, + startConsecutiveToggle, + LogMonitorAction, +} from './actions'; +import reducer, { LogMonitorState } from './reducers'; import LogMonitorButtonBar from './LogMonitorButtonBar'; import LogMonitorEntryList from './LogMonitorEntryList'; import debounce from 'lodash.debounce'; +// eslint-disable-next-line @typescript-eslint/unbound-method const { toggleAction, setActionsActive } = ActionCreators; -const styles = { +const styles: { + container: React.CSSProperties; + elements: React.CSSProperties; +} = { container: { fontFamily: 'monaco, Consolas, Lucida Console, monospace', position: 'relative', @@ -32,7 +41,23 @@ const styles = { }, }; -export default class LogMonitor extends Component { +export interface LogMonitorProps> + extends LiftedState { + dispatch: Dispatch>; + + preserveScrollTop: boolean; + select: (state: S) => unknown; + theme: keyof typeof themes | Base16Theme; + expandActionRoot: boolean; + expandStateRoot: boolean; + markStateDiff: boolean; + hideMainButtons?: boolean; +} + +export default class LogMonitor< + S, + A extends Action +> extends PureComponent> { static update = reducer; static propTypes = { @@ -56,7 +81,7 @@ export default class LogMonitor extends Component { }; static defaultProps = { - select: (state) => state, + select: (state: unknown) => state, theme: 'nicinabox', preserveScrollTop: true, expandActionRoot: true, @@ -64,22 +89,14 @@ export default class LogMonitor extends Component { markStateDiff: false, }; - shouldComponentUpdate = shouldPureComponentUpdate; + scrollDown?: boolean; + node?: HTMLDivElement | null; updateScrollTop = debounce(() => { const node = this.node; this.props.dispatch(updateScrollTop(node ? node.scrollTop : 0)); }, 500); - constructor(props) { - super(props); - this.handleToggleAction = this.handleToggleAction.bind(this); - this.handleToggleConsecutiveAction = this.handleToggleConsecutiveAction.bind( - this - ); - this.getRef = this.getRef.bind(this); - } - scroll() { const node = this.node; if (!node) { @@ -114,7 +131,7 @@ export default class LogMonitor extends Component { } } - UNSAFE_componentWillReceiveProps(nextProps) { + UNSAFE_componentWillReceiveProps(nextProps: LogMonitorProps) { const node = this.node; if (!node) { this.scrollDown = true; @@ -134,11 +151,11 @@ export default class LogMonitor extends Component { this.scroll(); } - handleToggleAction(id) { + handleToggleAction = (id: number) => { this.props.dispatch(toggleAction(id)); - } + }; - handleToggleConsecutiveAction(id) { + handleToggleConsecutiveAction = (id: number) => { const { monitorState, actionsById } = this.props; const { consecutiveToggleStartId } = monitorState; if (consecutiveToggleStartId && actionsById[consecutiveToggleStartId]) { @@ -151,10 +168,10 @@ export default class LogMonitor extends Component { } else if (id > 0) { this.props.dispatch(startConsecutiveToggle(id)); } - } + }; getTheme() { - let { theme } = this.props; + const { theme } = this.props; if (typeof theme !== 'string') { return theme; } @@ -170,9 +187,9 @@ export default class LogMonitor extends Component { return themes.nicinabox; } - getRef(node) { + getRef: React.RefCallback = (node) => { this.node = node; - } + }; render() { const theme = this.getTheme(); diff --git a/packages/redux-devtools-log-monitor/src/LogMonitorButton.js b/packages/redux-devtools-log-monitor/src/LogMonitorButton.tsx similarity index 64% rename from packages/redux-devtools-log-monitor/src/LogMonitorButton.js rename to packages/redux-devtools-log-monitor/src/LogMonitorButton.tsx index 23e9587c..50afcc85 100644 --- a/packages/redux-devtools-log-monitor/src/LogMonitorButton.js +++ b/packages/redux-devtools-log-monitor/src/LogMonitorButton.tsx @@ -1,8 +1,8 @@ -import React from 'react'; +import React, { CSSProperties } from 'react'; +import { Base16Theme } from 'redux-devtools-themes'; import brighten from './brighten'; -import shouldPureComponentUpdate from 'react-pure-render/function'; -const styles = { +const styles: { base: CSSProperties } = { base: { cursor: 'pointer', fontWeight: 'bold', @@ -20,48 +20,50 @@ const styles = { }, }; -export default class LogMonitorButton extends React.Component { - shouldComponentUpdate = shouldPureComponentUpdate; +interface State { + hovered: boolean; + active: boolean; +} - constructor(props) { - super(props); +interface Props { + theme: Base16Theme; + onClick: () => void; + enabled: boolean; +} - this.handleMouseEnter = this.handleMouseEnter.bind(this); - this.handleMouseLeave = this.handleMouseLeave.bind(this); - this.handleMouseDown = this.handleMouseDown.bind(this); - this.handleMouseUp = this.handleMouseUp.bind(this); - this.onClick = this.onClick.bind(this); +export default class LogMonitorButton extends React.PureComponent< + Props, + State +> { + state: State = { + hovered: false, + active: false, + }; - this.state = { - hovered: false, - active: false, - }; - } - - handleMouseEnter() { + handleMouseEnter = () => { this.setState({ hovered: true }); - } + }; - handleMouseLeave() { + handleMouseLeave = () => { this.setState({ hovered: false }); - } + }; - handleMouseDown() { + handleMouseDown = () => { this.setState({ active: true }); - } + }; - handleMouseUp() { + handleMouseUp = () => { this.setState({ active: false }); - } + }; - onClick() { + onClick = () => { if (!this.props.enabled) { return; } if (this.props.onClick) { this.props.onClick(); } - } + }; render() { let style = { diff --git a/packages/redux-devtools-log-monitor/src/LogMonitorButtonBar.js b/packages/redux-devtools-log-monitor/src/LogMonitorButtonBar.tsx similarity index 62% rename from packages/redux-devtools-log-monitor/src/LogMonitorButtonBar.js rename to packages/redux-devtools-log-monitor/src/LogMonitorButtonBar.tsx index 27b5b34f..abb2ec7a 100644 --- a/packages/redux-devtools-log-monitor/src/LogMonitorButtonBar.js +++ b/packages/redux-devtools-log-monitor/src/LogMonitorButtonBar.tsx @@ -1,12 +1,16 @@ -import React, { Component } from 'react'; +import React, { CSSProperties, PureComponent } from 'react'; import PropTypes from 'prop-types'; -import shouldPureComponentUpdate from 'react-pure-render/function'; -import { ActionCreators } from 'redux-devtools'; +import { ActionCreators, LiftedAction } from 'redux-devtools'; +import { Base16Theme } from 'redux-devtools-themes'; +import { Action, Dispatch } from 'redux'; import LogMonitorButton from './LogMonitorButton'; +import { LogMonitorAction } from './actions'; +import { LogMonitorState } from './reducers'; +// eslint-disable-next-line @typescript-eslint/unbound-method const { reset, rollback, commit, sweep } = ActionCreators; -const style = { +const style: CSSProperties = { textAlign: 'center', borderBottomWidth: 1, borderBottomStyle: 'solid', @@ -16,37 +20,37 @@ const style = { flexDirection: 'row', }; -export default class LogMonitorButtonBar extends Component { +interface Props> { + theme: Base16Theme; + dispatch: Dispatch>; + hasStates: boolean; + hasSkippedActions: boolean; +} + +export default class LogMonitorButtonBar< + S, + A extends Action +> extends PureComponent> { static propTypes = { dispatch: PropTypes.func, theme: PropTypes.object, }; - shouldComponentUpdate = shouldPureComponentUpdate; - - constructor(props) { - super(props); - this.handleReset = this.handleReset.bind(this); - this.handleRollback = this.handleRollback.bind(this); - this.handleSweep = this.handleSweep.bind(this); - this.handleCommit = this.handleCommit.bind(this); - } - - handleRollback() { + handleRollback = () => { this.props.dispatch(rollback()); - } + }; - handleSweep() { + handleSweep = () => { this.props.dispatch(sweep()); - } + }; - handleCommit() { + handleCommit = () => { this.props.dispatch(commit()); - } + }; - handleReset() { + handleReset = () => { this.props.dispatch(reset()); - } + }; render() { const { theme, hasStates, hasSkippedActions } = this.props; diff --git a/packages/redux-devtools-log-monitor/src/LogMonitorEntry.js b/packages/redux-devtools-log-monitor/src/LogMonitorEntry.tsx similarity index 70% rename from packages/redux-devtools-log-monitor/src/LogMonitorEntry.js rename to packages/redux-devtools-log-monitor/src/LogMonitorEntry.tsx index 6f4aea78..3cf48af4 100644 --- a/packages/redux-devtools-log-monitor/src/LogMonitorEntry.js +++ b/packages/redux-devtools-log-monitor/src/LogMonitorEntry.tsx @@ -1,10 +1,11 @@ -import React, { Component } from 'react'; +import React, { CSSProperties, MouseEventHandler, PureComponent } from 'react'; import PropTypes from 'prop-types'; -import JSONTree from 'react-json-tree'; +import JSONTree, { StylingValue } from 'react-json-tree'; +import { Base16Theme } from 'redux-devtools-themes'; +import { Action } from 'redux'; import LogMonitorEntryAction from './LogMonitorEntryAction'; -import shouldPureComponentUpdate from 'react-pure-render/function'; -const styles = { +const styles: { entry: CSSProperties; root: CSSProperties } = { entry: { display: 'block', WebkitUserSelect: 'none', @@ -15,15 +16,40 @@ const styles = { }, }; -const getDeepItem = (data, path) => +const getDeepItem = (data: any, path: (string | number)[]) => path.reduce((obj, key) => obj && obj[key], data); -const dataIsEqual = (data, previousData, keyPath) => { +const dataIsEqual = ( + data: any, + previousData: unknown, + keyPath: (string | number)[] +) => { const path = [...keyPath].reverse().slice(1); return getDeepItem(data, path) === getDeepItem(previousData, path); }; -export default class LogMonitorEntry extends Component { +interface Props> { + theme: Base16Theme; + select: (state: any) => unknown; + action: A; + actionId: number; + state: S; + previousState: S | undefined; + collapsed: boolean; + inFuture: boolean; + selected: boolean; + error: string | undefined; + expandActionRoot: boolean; + expandStateRoot: boolean; + markStateDiff: boolean; + onActionClick: (id: number) => void; + onActionShiftClick: (id: number) => void; +} + +export default class LogMonitorEntry< + S, + A extends Action +> extends PureComponent> { static propTypes = { state: PropTypes.object.isRequired, action: PropTypes.object.isRequired, @@ -37,17 +63,10 @@ export default class LogMonitorEntry extends Component { selected: PropTypes.bool, expandActionRoot: PropTypes.bool, expandStateRoot: PropTypes.bool, + previousState: PropTypes.object, }; - shouldComponentUpdate = shouldPureComponentUpdate; - - constructor(props) { - super(props); - this.handleActionClick = this.handleActionClick.bind(this); - this.shouldExpandNode = this.shouldExpandNode.bind(this); - } - - printState(state, error) { + printState(state: S, error: string | undefined) { let errorText = error; if (!errorText) { try { @@ -59,7 +78,11 @@ export default class LogMonitorEntry extends Component { typeof this.props.previousState !== 'undefined' ? this.props.select(this.props.previousState) : undefined; - const getValueStyle = ({ style }, nodeType, keyPath) => ({ + const getValueStyle: StylingValue = ( + { style }, + nodeType, + keyPath + ) => ({ style: { ...style, backgroundColor: dataIsEqual(data, previousData, keyPath) @@ -67,7 +90,7 @@ export default class LogMonitorEntry extends Component { : this.props.theme.base01, }, }); - const getNestedNodeStyle = ({ style }, keyPath) => ({ + const getNestedNodeStyle: StylingValue = ({ style }, keyPath) => ({ style: { ...style, ...(keyPath.length > 1 ? {} : styles.root), @@ -75,7 +98,6 @@ export default class LogMonitorEntry extends Component { }); theme = { extend: this.props.theme, - tree: styles.tree, value: getValueStyle, nestedNode: getNestedNodeStyle, }; @@ -112,7 +134,7 @@ export default class LogMonitorEntry extends Component { ); } - handleActionClick(e) { + handleActionClick: MouseEventHandler = (e) => { const { actionId, onActionClick, onActionShiftClick } = this.props; if (actionId > 0) { if (e.shiftKey) { @@ -121,11 +143,15 @@ export default class LogMonitorEntry extends Component { onActionClick(actionId); } } - } + }; - shouldExpandNode(keyName, data, level) { + shouldExpandNode = ( + keyPath: (string | number)[], + data: any, + level: number + ) => { return this.props.expandStateRoot && level === 0; - } + }; render() { const { diff --git a/packages/redux-devtools-log-monitor/src/LogMonitorEntryAction.js b/packages/redux-devtools-log-monitor/src/LogMonitorEntryAction.tsx similarity index 63% rename from packages/redux-devtools-log-monitor/src/LogMonitorEntryAction.js rename to packages/redux-devtools-log-monitor/src/LogMonitorEntryAction.tsx index 87a89e4c..8a20ecc9 100644 --- a/packages/redux-devtools-log-monitor/src/LogMonitorEntryAction.js +++ b/packages/redux-devtools-log-monitor/src/LogMonitorEntryAction.tsx @@ -1,5 +1,7 @@ -import React, { Component } from 'react'; +import React, { Component, CSSProperties, MouseEventHandler } from 'react'; import JSONTree from 'react-json-tree'; +import { Base16Theme } from 'redux-devtools-themes'; +import { Action } from 'redux'; const styles = { actionBar: { @@ -14,13 +16,19 @@ const styles = { }, }; -export default class LogMonitorAction extends Component { - constructor(props) { - super(props); - this.shouldExpandNode = this.shouldExpandNode.bind(this); - } +interface Props> { + theme: Base16Theme; + collapsed: boolean; + action: A; + expandActionRoot: boolean; + onClick: MouseEventHandler; + style: CSSProperties; +} - renderPayload(payload) { +export default class LogMonitorAction< + A extends Action +> extends Component> { + renderPayload(payload: Record) { return (
{ return this.props.expandActionRoot && level === 0; - } + }; render() { const { type, ...payload } = this.props.action; @@ -58,7 +70,7 @@ export default class LogMonitorAction extends Component { }} >
- {type !== null && type.toString()} + {type !== null && (type as string).toString()}
{!this.props.collapsed ? this.renderPayload(payload) : ''}
diff --git a/packages/redux-devtools-log-monitor/src/LogMonitorEntryList.js b/packages/redux-devtools-log-monitor/src/LogMonitorEntryList.tsx similarity index 70% rename from packages/redux-devtools-log-monitor/src/LogMonitorEntryList.js rename to packages/redux-devtools-log-monitor/src/LogMonitorEntryList.tsx index 7acaa370..ce3c074a 100644 --- a/packages/redux-devtools-log-monitor/src/LogMonitorEntryList.js +++ b/packages/redux-devtools-log-monitor/src/LogMonitorEntryList.tsx @@ -1,9 +1,31 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; +import { Action } from 'redux'; +import { PerformAction } from 'redux-devtools'; +import { Base16Theme } from 'redux-devtools-themes'; import LogMonitorEntry from './LogMonitorEntry'; -import shouldPureComponentUpdate from 'react-pure-render/function'; -export default class LogMonitorEntryList extends Component { +interface Props> { + actionsById: { [actionId: number]: PerformAction
}; + computedStates: { state: S; error?: string }[]; + stagedActionIds: number[]; + skippedActionIds: number[]; + currentStateIndex: number; + consecutiveToggleStartId: number | null | undefined; + + select: (state: S) => unknown; + onActionClick: (id: number) => void; + theme: Base16Theme; + expandActionRoot: boolean; + expandStateRoot: boolean; + markStateDiff: boolean; + onActionShiftClick: (id: number) => void; +} + +export default class LogMonitorEntryList< + S, + A extends Action +> extends PureComponent> { static propTypes = { actionsById: PropTypes.object, computedStates: PropTypes.array, @@ -19,8 +41,6 @@ export default class LogMonitorEntryList extends Component { expandStateRoot: PropTypes.bool, }; - shouldComponentUpdate = shouldPureComponentUpdate; - render() { const elements = []; const { diff --git a/packages/redux-devtools-log-monitor/src/actions.js b/packages/redux-devtools-log-monitor/src/actions.js deleted file mode 100644 index 0b1dd617..00000000 --- a/packages/redux-devtools-log-monitor/src/actions.js +++ /dev/null @@ -1,11 +0,0 @@ -export const UPDATE_SCROLL_TOP = - '@@redux-devtools-log-monitor/UPDATE_SCROLL_TOP'; -export function updateScrollTop(scrollTop) { - return { type: UPDATE_SCROLL_TOP, scrollTop }; -} - -export const START_CONSECUTIVE_TOGGLE = - '@@redux-devtools-log-monitor/START_CONSECUTIVE_TOGGLE'; -export function startConsecutiveToggle(id) { - return { type: START_CONSECUTIVE_TOGGLE, id }; -} diff --git a/packages/redux-devtools-log-monitor/src/actions.ts b/packages/redux-devtools-log-monitor/src/actions.ts new file mode 100644 index 00000000..8661dc7e --- /dev/null +++ b/packages/redux-devtools-log-monitor/src/actions.ts @@ -0,0 +1,25 @@ +export const UPDATE_SCROLL_TOP = + '@@redux-devtools-log-monitor/UPDATE_SCROLL_TOP'; +interface UpdateScrollTopAction { + type: typeof UPDATE_SCROLL_TOP; + scrollTop: number; +} +export function updateScrollTop(scrollTop: number): UpdateScrollTopAction { + return { type: UPDATE_SCROLL_TOP, scrollTop }; +} + +export const START_CONSECUTIVE_TOGGLE = + '@@redux-devtools-log-monitor/START_CONSECUTIVE_TOGGLE'; +interface StartConsecutiveToggleAction { + type: typeof START_CONSECUTIVE_TOGGLE; + id: number | null; +} +export function startConsecutiveToggle( + id: number | null +): StartConsecutiveToggleAction { + return { type: START_CONSECUTIVE_TOGGLE, id }; +} + +export type LogMonitorAction = + | UpdateScrollTopAction + | StartConsecutiveToggleAction; diff --git a/packages/redux-devtools-log-monitor/src/brighten.js b/packages/redux-devtools-log-monitor/src/brighten.ts similarity index 79% rename from packages/redux-devtools-log-monitor/src/brighten.js rename to packages/redux-devtools-log-monitor/src/brighten.ts index 257e2aa0..14167804 100644 --- a/packages/redux-devtools-log-monitor/src/brighten.js +++ b/packages/redux-devtools-log-monitor/src/brighten.ts @@ -1,9 +1,9 @@ -export default function (hexColor, lightness) { +export default function (hexColor: string, lightness: number) { let hex = String(hexColor).replace(/[^0-9a-f]/gi, ''); if (hex.length < 6) { hex = hex.replace(/(.)/g, '$1$1'); } - let lum = lightness || 0; + const lum = lightness || 0; let rgb = '#'; let c; diff --git a/packages/redux-devtools-log-monitor/src/index.js b/packages/redux-devtools-log-monitor/src/index.js deleted file mode 100644 index 0a3a289b..00000000 --- a/packages/redux-devtools-log-monitor/src/index.js +++ /dev/null @@ -1 +0,0 @@ -export default from './LogMonitor'; diff --git a/packages/redux-devtools-log-monitor/src/index.ts b/packages/redux-devtools-log-monitor/src/index.ts new file mode 100644 index 00000000..174328d5 --- /dev/null +++ b/packages/redux-devtools-log-monitor/src/index.ts @@ -0,0 +1,2 @@ +import LogMonitor from './LogMonitor'; +export default LogMonitor; diff --git a/packages/redux-devtools-log-monitor/src/reducers.js b/packages/redux-devtools-log-monitor/src/reducers.js deleted file mode 100644 index 1312a9b9..00000000 --- a/packages/redux-devtools-log-monitor/src/reducers.js +++ /dev/null @@ -1,24 +0,0 @@ -import { UPDATE_SCROLL_TOP, START_CONSECUTIVE_TOGGLE } from './actions'; - -function initialScrollTop(props, state = 0, action) { - if (!props.preserveScrollTop) { - return 0; - } - - return action.type === UPDATE_SCROLL_TOP ? action.scrollTop : state; -} - -function startConsecutiveToggle(props, state, action) { - return action.type === START_CONSECUTIVE_TOGGLE ? action.id : state; -} - -export default function reducer(props, state = {}, action) { - return { - initialScrollTop: initialScrollTop(props, state.initialScrollTop, action), - consecutiveToggleStartId: startConsecutiveToggle( - props, - state.consecutiveToggleStartId, - action - ), - }; -} diff --git a/packages/redux-devtools-log-monitor/src/reducers.ts b/packages/redux-devtools-log-monitor/src/reducers.ts new file mode 100644 index 00000000..8d75a139 --- /dev/null +++ b/packages/redux-devtools-log-monitor/src/reducers.ts @@ -0,0 +1,47 @@ +import { Action } from 'redux'; +import { + UPDATE_SCROLL_TOP, + START_CONSECUTIVE_TOGGLE, + LogMonitorAction, +} from './actions'; +import { LogMonitorProps } from './LogMonitor'; + +function initialScrollTop>( + props: LogMonitorProps, + state = 0, + action: LogMonitorAction +) { + if (!props.preserveScrollTop) { + return 0; + } + + return action.type === UPDATE_SCROLL_TOP ? action.scrollTop : state; +} + +function startConsecutiveToggle>( + props: LogMonitorProps, + state: number | null | undefined, + action: LogMonitorAction +) { + return action.type === START_CONSECUTIVE_TOGGLE ? action.id : state; +} + +export interface LogMonitorState { + initialScrollTop: number; + consecutiveToggleStartId: number | null | undefined; +} + +export default function reducer>( + props: LogMonitorProps, + state: Partial = {}, + action: LogMonitorAction +): LogMonitorState { + return { + initialScrollTop: initialScrollTop(props, state.initialScrollTop, action), + consecutiveToggleStartId: startConsecutiveToggle( + props, + state.consecutiveToggleStartId, + action + ), + }; +} diff --git a/packages/redux-devtools-log-monitor/tsconfig.json b/packages/redux-devtools-log-monitor/tsconfig.json new file mode 100644 index 00000000..7b7d1492 --- /dev/null +++ b/packages/redux-devtools-log-monitor/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.react.base.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["src"] +} diff --git a/yarn.lock b/yarn.lock index 6e6c0774..180b96b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3045,7 +3045,7 @@ dependencies: "@babel/types" "^7.3.0" -"@types/base16@^1.0.2": +"@types/base16@*", "@types/base16@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@types/base16/-/base16-1.0.2.tgz#eb3a07db52309bfefb9ba010dfdb3c0784971f65" integrity sha512-oYO/U4VD1DavwrKuCSQWdLG+5K22SLPem2OQaHmFcQuwHoVeGC+JGVRji2MUqZUAIQZHEonOeVfAX09hYiLsdg== @@ -3340,6 +3340,13 @@ "@types/prop-types" "*" csstype "^3.0.2" +"@types/redux-devtools-themes@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/redux-devtools-themes/-/redux-devtools-themes-1.0.0.tgz#4d22d3e8be499fc7eec220e020b0640d4bfb17bd" + integrity sha512-ul3x0MYM5Nzj57Fh9wINyHFne8vZL04RC4nWAUWLYcL105vHoa/oJyopuKOrQmqVmhqmDiL4c9FfLbUmIB7TWQ== + dependencies: + "@types/base16" "*" + "@types/serve-static@*": version "1.13.5" resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.5.tgz#3d25d941a18415d3ab092def846e135a08bbcf53"