diff --git a/packages/redux-devtools-log-monitor/.babelrc b/packages/redux-devtools-log-monitor/.babelrc index 645cc56e..e073a7e7 100644 --- a/packages/redux-devtools-log-monitor/.babelrc +++ b/packages/redux-devtools-log-monitor/.babelrc @@ -1,4 +1,10 @@ { - "presets": ["@babel/preset-env", "@babel/preset-react"], - "plugins": ["@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-export-default-from"] + "presets": [ + "@babel/env", + "@babel/react", + "@babel/typescript" + ], + "plugins": [ + "@babel/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..72e1f8dd --- /dev/null +++ b/packages/redux-devtools-log-monitor/.eslintrc.js @@ -0,0 +1,21 @@ +module.exports = { + extends: '../../.eslintrc', + overrides: [ + { + files: ['*.ts', '*.tsx'], + extends: '../../eslintrc.ts.react.base.json', + parserOptions: { + tsconfigRootDir: __dirname, + project: ['./tsconfig.json'] + } + }, + { + files: ['test/*.ts', 'test/*.tsx'], + extends: '../../eslintrc.ts.react.jest.base.json', + parserOptions: { + tsconfigRootDir: __dirname, + project: ['./test/tsconfig.json'] + } + } + ] +}; diff --git a/packages/redux-devtools-log-monitor/.prettierignore b/packages/redux-devtools-log-monitor/.prettierignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/redux-devtools-log-monitor/.prettierignore @@ -0,0 +1 @@ +lib diff --git a/packages/redux-devtools-log-monitor/package.json b/packages/redux-devtools-log-monitor/package.json index 25f449e6..c99c8bbc 100644 --- a/packages/redux-devtools-log-monitor/package.json +++ b/packages/redux-devtools-log-monitor/package.json @@ -3,13 +3,20 @@ "version": "1.4.0", "description": "The default tree view monitor for Redux DevTools", "main": "lib/index.js", + "types": "lib/index.d.ts", "files": [ "lib", "src" ], "scripts": { + "type-check": "tsc --noEmit", + "type-check:watch": "npm run type-check -- --watch", "clean": "rimraf lib", - "build": "babel src --out-dir lib", + "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", + "lint": "eslint . --ext .js,.jsx,.ts,.tsx", + "lint:fix": "eslint . --ext .js,.jsx,.ts,.tx --fix", "prepare": "npm run build", "prepublishOnly": "npm run test && npm run clean && npm run build" }, @@ -35,18 +42,23 @@ "devDependencies": { "@babel/cli": "^7.2.3", "@babel/core": "^7.2.2", - "@babel/plugin-proposal-export-default-from": "^7.2.0", "@babel/plugin-proposal-class-properties": "^7.3.0", "@babel/preset-env": "^7.3.1", "@babel/preset-react": "^7.0.0", + "@types/react": "^15.0.0 || ^16.0.0", "babel-loader": "^8.0.5", + "react": "^15.0.0 || ^16.0.0", + "redux-devtools": "^3.4.0", "rimraf": "^2.3.4" }, "peerDependencies": { + "@types/react": "^15.0.0 || ^16.0.0", "react": "^15.0.0 || ^16.0.0", "redux-devtools": "^3.4.0" }, "dependencies": { + "@types/lodash.debounce": "^4.0.4", + "@types/prop-types": "^15.0.0", "lodash.debounce": "^4.0.4", "prop-types": "^15.0.0", "react-json-tree": "^0.11.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 49732de1..5bdfcaaa 100644 --- a/packages/redux-devtools-log-monitor/src/LogMonitor.js +++ b/packages/redux-devtools-log-monitor/src/LogMonitor.tsx @@ -2,16 +2,25 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import shouldPureComponentUpdate from 'react-pure-render/function'; import * as themes from 'redux-devtools-themes'; -import { ActionCreators } from 'redux-devtools'; -import { updateScrollTop, startConsecutiveToggle } from './actions'; -import reducer from './reducers'; +import { ActionCreators, LiftedAction, PerformAction } from 'redux-devtools'; +import { Base16Theme } from 'base16'; +import { Action, Dispatch } from 'redux'; +import { + updateScrollTop, + startConsecutiveToggle, + LogMonitorAction +} from './actions'; +import reducer, { LogMonitorState } from './reducers'; import LogMonitorButtonBar from './LogMonitorButtonBar'; import LogMonitorEntryList from './LogMonitorEntryList'; import debounce from 'lodash.debounce'; 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,29 @@ const styles = { } }; -export default class LogMonitor extends Component { +export interface Props { + dispatch: Dispatch< + LogMonitorAction | LiftedAction + >; + computedStates: { state: S; error?: string }[]; + actionsById: { [actionId: number]: PerformAction }; + stagedActionIds: number[]; + skippedActionIds: number[]; + currentStateIndex: number; + monitorState: LogMonitorState; + + preserveScrollTop: boolean; + select: (state: S) => unknown; + theme: keyof typeof themes | Base16Theme; + expandActionRoot: boolean; + expandStateRoot: boolean; + markStateDiff: boolean; + hideMainButtons?: boolean; +} + +export default class LogMonitor extends Component< + Props +> { static update = reducer; static propTypes = { @@ -56,7 +87,7 @@ export default class LogMonitor extends Component { }; static defaultProps = { - select: state => state, + select: (state: unknown) => state, theme: 'nicinabox', preserveScrollTop: true, expandActionRoot: true, @@ -64,6 +95,9 @@ export default class LogMonitor extends Component { markStateDiff: false }; + scrollDown?: boolean; + node?: HTMLDivElement | null; + shouldComponentUpdate = shouldPureComponentUpdate; updateScrollTop = debounce(() => { @@ -71,15 +105,6 @@ export default class LogMonitor extends Component { 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 +139,7 @@ export default class LogMonitor extends Component { } } - componentWillReceiveProps(nextProps) { + componentWillReceiveProps(nextProps: Props) { const node = this.node; if (!node) { this.scrollDown = true; @@ -134,27 +159,27 @@ 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]) { const { skippedActionIds } = this.props; const start = Math.min(consecutiveToggleStartId, id); const end = Math.max(consecutiveToggleStartId, id); - const active = skippedActionIds.indexOf(consecutiveToggleStartId) > -1; + const active = skippedActionIds.includes(consecutiveToggleStartId); this.props.dispatch(setActionsActive(start, end + 1, active)); this.props.dispatch(startConsecutiveToggle(null)); } 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 +195,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 71% rename from packages/redux-devtools-log-monitor/src/LogMonitorButton.js rename to packages/redux-devtools-log-monitor/src/LogMonitorButton.tsx index f2f50a31..d59fa8c6 100644 --- a/packages/redux-devtools-log-monitor/src/LogMonitorButton.js +++ b/packages/redux-devtools-log-monitor/src/LogMonitorButton.tsx @@ -1,8 +1,9 @@ import React from 'react'; +import { Base16Theme } from 'base16'; import brighten from './brighten'; import shouldPureComponentUpdate from 'react-pure-render/function'; -const styles = { +const styles: { base: React.CSSProperties } = { base: { cursor: 'pointer', fontWeight: 'bold', @@ -20,48 +21,49 @@ const styles = { } }; -export default class LogMonitorButton extends React.Component { +interface Props { + theme: Base16Theme; + onClick: () => void; + enabled: boolean; +} + +interface State { + hovered: boolean; + active: boolean; +} + +export default class LogMonitorButton extends React.Component { shouldComponentUpdate = shouldPureComponentUpdate; - constructor(props) { - super(props); + state: State = { + hovered: false, + active: false + }; - 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); - - 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 = { @@ -80,7 +82,7 @@ export default class LogMonitorButton extends React.Component { opacity: 0.2, cursor: 'text', backgroundColor: 'transparent' - }; + } as const; } return ( { + theme: Base16Theme; + dispatch: Dispatch< + LogMonitorAction | LiftedAction + >; + hasStates: boolean; + hasSkippedActions: boolean; +} + +export default class LogMonitorButtonBar extends Component< + Props +> { static propTypes = { dispatch: PropTypes.func, theme: PropTypes.object @@ -24,29 +39,21 @@ export default class LogMonitorButtonBar extends Component { 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 68% rename from packages/redux-devtools-log-monitor/src/LogMonitorEntry.js rename to packages/redux-devtools-log-monitor/src/LogMonitorEntry.tsx index c4cac702..298dadc8 100644 --- a/packages/redux-devtools-log-monitor/src/LogMonitorEntry.js +++ b/packages/redux-devtools-log-monitor/src/LogMonitorEntry.tsx @@ -1,10 +1,13 @@ -import React, { Component } from 'react'; +import React, { Component, MouseEventHandler } from 'react'; import PropTypes from 'prop-types'; import JSONTree from 'react-json-tree'; +import { Base16Theme } from 'base16'; +import { Action } from 'redux'; import LogMonitorEntryAction from './LogMonitorEntryAction'; import shouldPureComponentUpdate from 'react-pure-render/function'; +import { Styling, StylingConfig, StylingValue } from 'react-base16-styling'; -const styles = { +const styles: { entry: React.CSSProperties; root: React.CSSProperties } = { entry: { display: 'block', WebkitUserSelect: 'none' @@ -15,15 +18,37 @@ 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 { + state: {}; + action: any; + actionId: number; + select: (state: any) => any; + inFuture: boolean; + error: string | undefined; + onActionClick: (id: number) => void; + onActionShiftClick: (id: number) => void; + collapsed: boolean; + selected: boolean; + expandActionRoot: boolean; + expandStateRoot: boolean; + theme: Base16Theme; + previousState: any | undefined; + markStateDiff: boolean; +} + +export default class LogMonitorEntry extends Component { static propTypes = { state: PropTypes.object.isRequired, action: PropTypes.object.isRequired, @@ -41,25 +66,23 @@ export default class LogMonitorEntry extends Component { shouldComponentUpdate = shouldPureComponentUpdate; - constructor(props) { - super(props); - this.handleActionClick = this.handleActionClick.bind(this); - this.shouldExpandNode = this.shouldExpandNode.bind(this); - } - - printState(state, error) { + printState(state: any, error: string | undefined) { let errorText = error; if (!errorText) { try { const data = this.props.select(state); - let theme; + let theme: StylingConfig | Base16Theme; if (this.props.markStateDiff) { const previousData = typeof this.props.previousState !== 'undefined' ? this.props.select(this.props.previousState) : undefined; - const getValueStyle = ({ style }, nodeType, keyPath) => ({ + const getValueStyle: StylingValue = ( + { style }: Styling, + nodeType: string, + keyPath: (string | number)[] + ): Styling => ({ style: { ...style, backgroundColor: dataIsEqual(data, previousData, keyPath) @@ -67,15 +90,17 @@ export default class LogMonitorEntry extends Component { : this.props.theme.base01 } }); - const getNestedNodeStyle = ({ style }, keyPath) => ({ + const getNestedNodeStyle: StylingValue = ( + { style }: Styling, + keyPath: (string | number)[] + ): Styling => ({ style: { ...style, ...(keyPath.length > 1 ? {} : styles.root) } }); theme = { - extend: this.props.theme, - tree: styles.tree, + extend: (this.props.theme as unknown) as StylingValue, value: getValueStyle, nestedNode: getNestedNodeStyle }; @@ -112,7 +137,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 +146,15 @@ export default class LogMonitorEntry extends Component { onActionClick(actionId); } } - } + }; - shouldExpandNode(keyName, data, level) { + shouldExpandNode = ( + keyName: (string | number)[], + data: unknown, + level: number + ) => { return this.props.expandStateRoot && level === 0; - } + }; render() { const { @@ -137,7 +166,7 @@ export default class LogMonitorEntry extends Component { selected, inFuture } = this.props; - const styleEntry = { + const styleEntry: React.CSSProperties = { opacity: collapsed ? 0.5 : 1, cursor: actionId > 0 ? 'pointer' : 'default' }; diff --git a/packages/redux-devtools-log-monitor/src/LogMonitorEntryAction.js b/packages/redux-devtools-log-monitor/src/LogMonitorEntryAction.tsx similarity index 61% rename from packages/redux-devtools-log-monitor/src/LogMonitorEntryAction.js rename to packages/redux-devtools-log-monitor/src/LogMonitorEntryAction.tsx index 2b4d466f..818ac8be 100644 --- a/packages/redux-devtools-log-monitor/src/LogMonitorEntryAction.js +++ b/packages/redux-devtools-log-monitor/src/LogMonitorEntryAction.tsx @@ -1,7 +1,12 @@ -import React, { Component } from 'react'; +import React, { Component, MouseEventHandler } from 'react'; import JSONTree from 'react-json-tree'; +import { Action } from 'redux'; +import { Base16Theme } from 'base16'; -const styles = { +const styles: { + actionBar: React.CSSProperties; + payload: React.CSSProperties; +} = { actionBar: { paddingTop: 8, paddingBottom: 7, @@ -14,13 +19,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: React.CSSProperties; +} - renderPayload(payload) { +export default class LogMonitorAction< + A extends Action +> extends Component> { + renderPayload(payload: {}) { return (
{ return this.props.expandActionRoot && level === 0; - } + }; render() { const { type, ...payload } = this.props.action; @@ -58,7 +73,7 @@ export default class LogMonitorAction extends Component { }} >
- {type !== null && type.toString()} + {type !== null && (type as any).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 71% rename from packages/redux-devtools-log-monitor/src/LogMonitorEntryList.js rename to packages/redux-devtools-log-monitor/src/LogMonitorEntryList.tsx index adf648af..35b305bb 100644 --- a/packages/redux-devtools-log-monitor/src/LogMonitorEntryList.js +++ b/packages/redux-devtools-log-monitor/src/LogMonitorEntryList.tsx @@ -1,9 +1,32 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import { Action } from 'redux'; +import { Base16Theme } from 'base16'; +import { PerformAction } from 'redux-devtools'; 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) => any; + onActionClick: (id: number) => void; + onActionShiftClick: (id: number) => void; + theme: Base16Theme; + expandActionRoot: boolean; + expandStateRoot: boolean; + markStateDiff: boolean; +} + +export default class LogMonitorEntryList< + S, + A extends Action +> extends Component> { static propTypes = { actionsById: PropTypes.object, computedStates: PropTypes.array, @@ -56,7 +79,7 @@ export default class LogMonitorEntryList extends Component { actionId={actionId} state={state} previousState={previousState} - collapsed={skippedActionIds.indexOf(actionId) > -1} + collapsed={skippedActionIds.includes(actionId)} inFuture={i > currentStateIndex} selected={consecutiveToggleStartId === i} error={error} 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/base16.ts b/packages/redux-devtools-log-monitor/src/base16.ts new file mode 100644 index 00000000..2434e11c --- /dev/null +++ b/packages/redux-devtools-log-monitor/src/base16.ts @@ -0,0 +1,61 @@ +declare module 'base16' { + export interface Base16Theme { + scheme?: string; + author?: string; + base00: string; + base01: string; + base02: string; + base03: string; + base04: string; + base05: string; + base06: string; + base07: string; + base08: string; + base09: string; + base0A: string; + base0B: string; + base0C: string; + base0D: string; + base0E: string; + base0F: string; + } + + export const threezerotwofour: Base16Theme; + export const apathy: Base16Theme; + export const ashes: Base16Theme; + export const atelierDune: Base16Theme; + export const atelierForest: Base16Theme; + export const atelierHeath: Base16Theme; + export const atelierLakeside: Base16Theme; + export const atelierSeaside: Base16Theme; + export const bespin: Base16Theme; + export const brewer: Base16Theme; + export const bright: Base16Theme; + export const chalk: Base16Theme; + export const codeschool: Base16Theme; + export const colors: Base16Theme; + const _default: Base16Theme; + export default _default; + export const eighties: Base16Theme; + export const embers: Base16Theme; + export const flat: Base16Theme; + export const google: Base16Theme; + export const grayscale: Base16Theme; + export const greenscreen: Base16Theme; + export const harmonic: Base16Theme; + export const hopscotch: Base16Theme; + export const isotope: Base16Theme; + export const marrakesh: Base16Theme; + export const mocha: Base16Theme; + export const monokai: Base16Theme; + export const ocean: Base16Theme; + export const paraiso: Base16Theme; + export const pop: Base16Theme; + export const railscasts: Base16Theme; + export const shapeshifter: Base16Theme; + export const solarized: Base16Theme; + export const summerfruit: Base16Theme; + export const tomorrow: Base16Theme; + export const tube: Base16Theme; + export const twilight: Base16Theme; +} 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 aa68da46..135079cb 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..a81876d2 --- /dev/null +++ b/packages/redux-devtools-log-monitor/src/index.ts @@ -0,0 +1,5 @@ +import LogMonitor from './LogMonitor'; +import './base16'; +import './react-pure-render'; +import './redux-devtools-themes'; +export default LogMonitor; diff --git a/packages/redux-devtools-log-monitor/src/react-pure-render.ts b/packages/redux-devtools-log-monitor/src/react-pure-render.ts new file mode 100644 index 00000000..794702c7 --- /dev/null +++ b/packages/redux-devtools-log-monitor/src/react-pure-render.ts @@ -0,0 +1,6 @@ +declare module 'react-pure-render/function' { + export default function shouldPureComponentUpdate( + nextProps: unknown, + nextState: unknown + ): boolean; +} 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 a18fed2d..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..1b0c1018 --- /dev/null +++ b/packages/redux-devtools-log-monitor/src/reducers.ts @@ -0,0 +1,52 @@ +import { Action } from 'redux'; +import { + UPDATE_SCROLL_TOP, + START_CONSECUTIVE_TOGGLE, + LogMonitorAction +} from './actions'; +import { Props } from './LogMonitor'; + +function initialScrollTop( + props: Props, + state: number | undefined = 0, + action: LogMonitorAction +) { + if (!props.preserveScrollTop) { + return 0; + } + + return action.type === UPDATE_SCROLL_TOP ? action.scrollTop : state; +} + +function startConsecutiveToggle( + props: Props, + state: number | undefined | null, + action: LogMonitorAction +) { + return action.type === START_CONSECUTIVE_TOGGLE ? action.id : state; +} + +interface InitialLogMonitorState { + initialScrollTop?: number; + consecutiveToggleStartId?: number | null; +} + +export interface LogMonitorState { + initialScrollTop: number; + consecutiveToggleStartId?: number | null; +} + +export default function reducer( + props: Props, + state: InitialLogMonitorState = {}, + action: LogMonitorAction +): LogMonitorState { + return { + initialScrollTop: initialScrollTop(props, state.initialScrollTop, action), + consecutiveToggleStartId: startConsecutiveToggle( + props, + state.consecutiveToggleStartId, + action + ) + }; +} diff --git a/packages/redux-devtools-log-monitor/src/redux-devtools-themes.ts b/packages/redux-devtools-log-monitor/src/redux-devtools-themes.ts new file mode 100644 index 00000000..895ce79d --- /dev/null +++ b/packages/redux-devtools-log-monitor/src/redux-devtools-themes.ts @@ -0,0 +1,5 @@ +declare module 'redux-devtools-themes' { + import { Base16Theme } from 'base16'; + export * from 'base16'; + export const nicinabox: Base16Theme; +} 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"] +}