diff --git a/packages/devui/src/Button/Button.tsx b/packages/devui/src/Button/Button.tsx index bd866225..73246d72 100644 --- a/packages/devui/src/Button/Button.tsx +++ b/packages/devui/src/Button/Button.tsx @@ -1,9 +1,9 @@ import React, { Component, ReactNode } from 'react'; import PropTypes from 'prop-types'; +import { Base16Theme } from 'base16'; import createStyledComponent from '../utils/createStyledComponent'; import * as styles from './styles'; import { commonStyle, tooltipStyle } from './styles/common'; -import { Theme } from '../themes/default'; const ButtonWrapper = createStyledComponent(styles, 'button'); const TooltipWrapper = createStyledComponent(tooltipStyle); @@ -41,7 +41,7 @@ export interface ButtonProps { primary?: boolean; size?: Size; mark?: Mark | false; - theme?: Theme; + theme?: Base16Theme; } export default class Button extends Component { diff --git a/packages/devui/src/Dialog/Dialog.tsx b/packages/devui/src/Dialog/Dialog.tsx index 761fbe16..dc058b4e 100644 --- a/packages/devui/src/Dialog/Dialog.tsx +++ b/packages/devui/src/Dialog/Dialog.tsx @@ -1,10 +1,10 @@ import React, { PureComponent, Component } from 'react'; import PropTypes from 'prop-types'; +import { Base16Theme } from 'base16'; import createStyledComponent from '../utils/createStyledComponent'; import * as styles from './styles'; import Button from '../Button'; import Form from '../Form'; -import { Theme } from '../themes/default'; import { Props as FormProps } from '../Form/Form'; const DialogWrapper = createStyledComponent(styles); @@ -23,7 +23,7 @@ export interface DialogProps { e: React.MouseEvent | false ) => void; onSubmit: () => void; - theme?: Theme; + theme?: Base16Theme; } type Rest

= Omit< diff --git a/packages/devui/src/Editor/Editor.tsx b/packages/devui/src/Editor/Editor.tsx index 36624c4c..ab8a53cf 100644 --- a/packages/devui/src/Editor/Editor.tsx +++ b/packages/devui/src/Editor/Editor.tsx @@ -2,6 +2,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import styled from 'styled-components'; import CodeMirror from 'codemirror'; +import { Base16Theme } from 'base16'; import { defaultStyle, themedStyle } from './styles'; import { Theme } from '../themes/default'; @@ -19,7 +20,7 @@ export interface EditorProps { lineNumbers: boolean; lineWrapping: boolean; readOnly: boolean; - theme?: Theme; + theme?: Base16Theme; foldGutter: boolean; autofocus: boolean; onChange: (value: string, change: CodeMirror.EditorChangeLinkedList) => void; diff --git a/packages/devui/src/Form/Form.tsx b/packages/devui/src/Form/Form.tsx index a4228d04..4e8f651f 100644 --- a/packages/devui/src/Form/Form.tsx +++ b/packages/devui/src/Form/Form.tsx @@ -1,11 +1,11 @@ import React, { PureComponent, Component } from 'react'; import PropTypes from 'prop-types'; import JSONSchemaForm, { FormProps } from 'react-jsonschema-form'; +import { Base16Theme } from 'base16'; import createStyledComponent from '../utils/createStyledComponent'; import styles from './styles'; import Button from '../Button'; import customWidgets from './widgets'; -import { Theme } from '../themes/default'; const FormContainer = createStyledComponent(styles, JSONSchemaForm); @@ -14,7 +14,7 @@ export interface Props extends FormProps { submitText?: string; primaryButton?: boolean; noSubmit?: boolean; - theme?: Theme; + theme?: Base16Theme; } /** diff --git a/packages/devui/src/Notification/Notification.tsx b/packages/devui/src/Notification/Notification.tsx index c17e3111..4e57923f 100644 --- a/packages/devui/src/Notification/Notification.tsx +++ b/packages/devui/src/Notification/Notification.tsx @@ -4,9 +4,9 @@ import { MdClose } from 'react-icons/md'; import { MdWarning } from 'react-icons/md'; import { MdError } from 'react-icons/md'; import { MdCheckCircle } from 'react-icons/md'; +import { Base16Theme } from 'base16'; import createStyledComponent from '../utils/createStyledComponent'; import styles from './styles'; -import { Theme } from '../themes/default'; const NotificationWrapper = createStyledComponent(styles); @@ -16,7 +16,7 @@ export interface NotificationProps { children?: React.ReactNode; type: Type; onClose?: React.MouseEventHandler; - theme?: Theme; + theme?: Base16Theme; } export default class Notification extends Component { diff --git a/packages/devui/src/SegmentedControl/SegmentedControl.tsx b/packages/devui/src/SegmentedControl/SegmentedControl.tsx index 726eac3b..075e327d 100644 --- a/packages/devui/src/SegmentedControl/SegmentedControl.tsx +++ b/packages/devui/src/SegmentedControl/SegmentedControl.tsx @@ -1,8 +1,8 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import { Base16Theme } from 'base16'; import createStyledComponent from '../utils/createStyledComponent'; import styles from './styles'; -import { Theme } from '../themes/default'; const SegmentedWrapper = createStyledComponent(styles); @@ -11,7 +11,7 @@ export interface SegmentedControlProps { selected?: string; onClick: (value: string) => void; disabled?: boolean; - theme?: Theme; + theme?: Base16Theme; } export default class SegmentedControl extends Component { diff --git a/packages/devui/src/Slider/Slider.tsx b/packages/devui/src/Slider/Slider.tsx index 8ba8e309..9029b3ab 100644 --- a/packages/devui/src/Slider/Slider.tsx +++ b/packages/devui/src/Slider/Slider.tsx @@ -1,9 +1,9 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import { Base16Theme } from 'base16'; import createStyledComponent from '../utils/createStyledComponent'; import * as styles from './styles'; import { containerStyle } from './styles/common'; -import { Theme } from '../themes/default'; const SliderWrapper = createStyledComponent(styles); const ContainerWithValue = createStyledComponent(containerStyle); @@ -17,7 +17,7 @@ export interface SliderProps { withValue?: boolean; disabled?: boolean; onChange: (value: number) => void; - theme?: Theme; + theme?: Base16Theme; } export default class Slider extends Component { diff --git a/packages/devui/src/Toolbar/styles/Toolbar.ts b/packages/devui/src/Toolbar/styles/Toolbar.ts index 84ab798a..a70b13ad 100644 --- a/packages/devui/src/Toolbar/styles/Toolbar.ts +++ b/packages/devui/src/Toolbar/styles/Toolbar.ts @@ -1,5 +1,6 @@ import styled, { ThemedStyledInterface } from 'styled-components'; -import { Theme } from '../../themes/default'; +import { Base16Theme } from 'base16'; +import * as CSS from 'csstype'; export type BorderPosition = 'top' | 'bottom'; @@ -10,7 +11,9 @@ export interface Props { noBorder?: boolean; } -const Toolbar = (styled as ThemedStyledInterface).div` +const Toolbar = (styled as ThemedStyledInterface< + Base16Theme & { fontFamily?: CSS.Property.FontFamily } +>).div` display: flex; flex-shrink: 0; box-sizing: border-box; diff --git a/packages/devui/src/utils/createStyledComponent.ts b/packages/devui/src/utils/createStyledComponent.ts index 1cf51d12..fc77eac9 100644 --- a/packages/devui/src/utils/createStyledComponent.ts +++ b/packages/devui/src/utils/createStyledComponent.ts @@ -59,7 +59,10 @@ export default function createStyledComponent< C extends keyof JSX.IntrinsicElements | React.ComponentType, // eslint-disable-next-line @typescript-eslint/ban-types O extends object = {} ->(styles: Styles, component?: C): StyledComponent { +>( + styles: Styles, + component?: C +): StyledComponent { return (styled as ThemedStyledInterface)((component || 'div') as C)` ${(props: ThemedStyledProps & O, Theme>) => isThemeFromProvider(props.theme) @@ -72,7 +75,7 @@ export default function createStyledComponent< ...props, theme: getDefaultTheme(props.theme), })} - `; + ` as StyledComponent; } // TODO: memoize it? diff --git a/packages/redux-devtools-log-monitor/package.json b/packages/redux-devtools-log-monitor/package.json index da31d099..bb95f078 100644 --- a/packages/redux-devtools-log-monitor/package.json +++ b/packages/redux-devtools-log-monitor/package.json @@ -57,7 +57,7 @@ "peerDependencies": { "@types/react": "^16.9.46", "react": "^16.3.0", - "redux": "^4.0.5", + "redux": "^3.4.0 || ^4.0.0", "redux-devtools": "^3.4.0" } } diff --git a/packages/redux-devtools-slider-monitor/.babelrc b/packages/redux-devtools-slider-monitor/.babelrc index e60d3036..0d42ef44 100644 --- a/packages/redux-devtools-slider-monitor/.babelrc +++ b/packages/redux-devtools-slider-monitor/.babelrc @@ -1,4 +1,8 @@ { - "presets": ["@babel/preset-env", "@babel/preset-react"], + "presets": [ + "@babel/preset-env", + "@babel/preset-react", + "@babel/preset-typescript" + ], "plugins": ["@babel/plugin-proposal-class-properties"] } diff --git a/packages/redux-devtools-slider-monitor/.eslintignore b/packages/redux-devtools-slider-monitor/.eslintignore new file mode 100644 index 00000000..be897dba --- /dev/null +++ b/packages/redux-devtools-slider-monitor/.eslintignore @@ -0,0 +1,2 @@ +examples +lib diff --git a/packages/redux-devtools-slider-monitor/.eslintrc.js b/packages/redux-devtools-slider-monitor/.eslintrc.js new file mode 100644 index 00000000..e98ddf18 --- /dev/null +++ b/packages/redux-devtools-slider-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-slider-monitor/examples/todomvc/package.json b/packages/redux-devtools-slider-monitor/examples/todomvc/package.json index ceba0ccc..c238684b 100644 --- a/packages/redux-devtools-slider-monitor/examples/todomvc/package.json +++ b/packages/redux-devtools-slider-monitor/examples/todomvc/package.json @@ -13,19 +13,17 @@ "url": "https://github.com/calesce/redux-slider-monitor.git" }, "license": "MIT", - "devDependencies": { - "@babel/core": "^7.11.0", - "@babel/plugin-proposal-class-properties": "^7.10.4", - "@babel/preset-env": "^7.11.0", - "@babel/preset-react": "^7.10.4", - "babel-loader": "^8.1.0", - "raw-loader": "^4.0.1", - "webpack": "^4.44.1", - "webpack-dev-server": "^3.11.0" - }, "dependencies": { + "classnames": "^2.2.6", "react-hot-loader": "^4.12.21", + "react": "^16.13.1", + "react-dom": "^16.13.1", "react-redux": "^7.2.1", - "redux-devtools-slider-monitor": "^2.0.0-5" + "redux": "^4.0.5", + "redux-devtools": "^3.7.0", + "redux-devtools-dock-monitor": "^1.2.0", + "redux-devtools-log-monitor": "^2.1.0", + "redux-devtools-slider-monitor": "^2.0.0-5", + "todomvc-app-css": "^2.3.0" } } diff --git a/packages/redux-devtools-slider-monitor/package.json b/packages/redux-devtools-slider-monitor/package.json index a6126d39..e316e60e 100644 --- a/packages/redux-devtools-slider-monitor/package.json +++ b/packages/redux-devtools-slider-monitor/package.json @@ -2,47 +2,51 @@ "name": "redux-devtools-slider-monitor", "version": "2.0.0-5", "description": "A custom monitor for replaying Redux actions that works similarly to a video player", - "main": "lib/SliderMonitor.js", - "scripts": { - "clean": "rimraf lib", - "build": "babel src --out-dir lib", - "prepare": "npm run build", - "prepublishOnly": "npm run clean && npm run build" - }, - "repository": { - "url": "https://github.com/reduxjs/redux-devtools" - }, - "author": "Cale Newman (http://github.com/calesce)", - "license": "MIT", + "homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-slider-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/preset-env": "^7.11.0", - "@babel/preset-react": "^7.10.4", - "classnames": "^2.2.6", - "react": "^16.13.1", - "react-dom": "^16.13.1", - "redux": "^4.0.5", - "redux-devtools": "^3.7.0", - "redux-devtools-dock-monitor": "^1.2.0", - "redux-devtools-log-monitor": "^2.1.0", - "rimraf": "^3.0.2", - "style-loader": "^1.2.1", - "todomvc-app-css": "^2.3.0" + "license": "MIT", + "author": "Cale Newman (http://github.com/calesce)", + "files": [ + "lib", + "src" + ], + "main": "lib/SliderMonitor.js", + "types": "lib/SliderMonitor.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/reduxjs/redux-devtools.git" }, - "peerDependencies": { - "react": "^0.14.0 || ^15.0.0 || ^16.0.0-0", - "react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0-0", - "redux-devtools": "^3.0.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", + "prepublishOnly": "npm run clean && npm run build" }, "dependencies": { + "@types/prop-types": "^15.7.3", + "@types/redux-devtools-themes": "^1.0.0", "devui": "^1.0.0-6", "prop-types": "^15.7.2", "redux-devtools-themes": "^1.0.0" + }, + "devDependencies": { + "@types/react": "^16.9.46", + "react": "^16.13.1", + "redux": "^4.0.5", + "redux-devtools": "^3.7.0" + }, + "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-slider-monitor/src/SliderButton.js b/packages/redux-devtools-slider-monitor/src/SliderButton.tsx similarity index 91% rename from packages/redux-devtools-slider-monitor/src/SliderButton.js rename to packages/redux-devtools-slider-monitor/src/SliderButton.tsx index 9c29406a..3e8402ab 100644 --- a/packages/redux-devtools-slider-monitor/src/SliderButton.js +++ b/packages/redux-devtools-slider-monitor/src/SliderButton.tsx @@ -1,8 +1,16 @@ import React, { Component, PureComponent } from 'react'; import PropTypes from 'prop-types'; +import { Base16Theme } from 'redux-devtools-themes'; import Button from 'devui/lib/Button'; -export default class SliderButton extends (PureComponent || Component) { +interface Props { + theme: Base16Theme; + type: string; + onClick: () => void; + disabled?: boolean; +} + +export default class SliderButton extends (PureComponent || Component) { static propTypes = { theme: PropTypes.object, type: PropTypes.string, @@ -61,7 +69,7 @@ export default class SliderButton extends (PureComponent || Component) { ); - renderStepButton = (direction) => { + renderStepButton = (direction: 'left' | 'right') => { const isLeft = direction === 'left'; const d = isLeft ? 'M15.41 16.09l-4.58-4.59 4.58-4.59-1.41-1.41-6 6 6 6z' diff --git a/packages/redux-devtools-slider-monitor/src/SliderMonitor.js b/packages/redux-devtools-slider-monitor/src/SliderMonitor.tsx similarity index 77% rename from packages/redux-devtools-slider-monitor/src/SliderMonitor.js rename to packages/redux-devtools-slider-monitor/src/SliderMonitor.tsx index 12efdfdd..05df27e3 100644 --- a/packages/redux-devtools-slider-monitor/src/SliderMonitor.js +++ b/packages/redux-devtools-slider-monitor/src/SliderMonitor.tsx @@ -1,7 +1,9 @@ import React, { Component, PureComponent } from 'react'; import PropTypes from 'prop-types'; +import { Action, Dispatch } from 'redux'; import * as themes from 'redux-devtools-themes'; -import { ActionCreators } from 'redux-devtools'; +import { Base16Theme } from 'redux-devtools-themes'; +import { ActionCreators, LiftedAction, LiftedState } from 'redux-devtools'; import { Toolbar, Divider } from 'devui/lib/Toolbar'; import Slider from 'devui/lib/Slider'; import Button from 'devui/lib/Button'; @@ -10,9 +12,44 @@ import SegmentedControl from 'devui/lib/SegmentedControl'; import reducer from './reducers'; import SliderButton from './SliderButton'; +// eslint-disable-next-line @typescript-eslint/unbound-method const { reset, jumpToState } = ActionCreators; -export default class SliderMonitor extends (PureComponent || Component) { +interface ExternalProps> { + // eslint-disable-next-line @typescript-eslint/ban-types + dispatch: Dispatch>; + preserveScrollTop: boolean; + select: (state: S) => unknown; + theme: keyof typeof themes | Base16Theme; + keyboardEnabled: boolean; + hideResetButton?: boolean; +} + +interface DefaultProps { + select: (state: unknown) => unknown; + theme: keyof typeof themes; + preserveScrollTop: boolean; + keyboardEnabled: boolean; +} + +interface SliderMonitorProps> // eslint-disable-next-line @typescript-eslint/ban-types + extends LiftedState { + // eslint-disable-next-line @typescript-eslint/ban-types + dispatch: Dispatch>; + preserveScrollTop: boolean; + select: (state: S) => unknown; + theme: keyof typeof themes | Base16Theme; + keyboardEnabled: boolean; + hideResetButton?: boolean; +} + +interface State { + timer: number | undefined; + replaySpeed: string; +} + +class SliderMonitor> extends (PureComponent || + Component), State> { static update = reducer; static propTypes = { @@ -25,7 +62,7 @@ export default class SliderMonitor extends (PureComponent || Component) { initialScrollTop: PropTypes.number, }), preserveScrollTop: PropTypes.bool, - stagedActions: PropTypes.array, + // stagedActions: PropTypes.array, select: PropTypes.func.isRequired, hideResetButton: PropTypes.bool, theme: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), @@ -33,13 +70,13 @@ export default class SliderMonitor extends (PureComponent || Component) { }; static defaultProps = { - select: (state) => state, + select: (state: unknown) => state, theme: 'nicinabox', preserveScrollTop: true, keyboardEnabled: true, }; - state = { + state: State = { timer: undefined, replaySpeed: '1x', }; @@ -56,7 +93,7 @@ export default class SliderMonitor extends (PureComponent || Component) { } } - setUpTheme = () => { + setUpTheme = (): Base16Theme => { let theme; if (typeof this.props.theme === 'string') { if (typeof themes[this.props.theme] !== 'undefined') { @@ -76,7 +113,7 @@ export default class SliderMonitor extends (PureComponent || Component) { this.props.dispatch(reset()); }; - handleKeyPress = (event) => { + handleKeyPress = (event: KeyboardEvent) => { if (!this.props.keyboardEnabled) { return null; } @@ -105,7 +142,7 @@ export default class SliderMonitor extends (PureComponent || Component) { return null; }; - handleSliderChange = (value) => { + handleSliderChange = (value: number) => { if (this.state.timer) { this.pauseReplay(); } @@ -134,7 +171,7 @@ export default class SliderMonitor extends (PureComponent || Component) { } let counter = stateIndex; - const timer = setInterval(() => { + const timer = window.setInterval(() => { if (counter + 1 <= computedStates.length - 1) { dispatch(jumpToState(counter + 1)); } @@ -165,7 +202,7 @@ export default class SliderMonitor extends (PureComponent || Component) { } }; - loop = (index) => { + loop = (index: number) => { let currentTimestamp = Date.now(); let timestampDiff = this.getLatestTimestampDiff(index); @@ -204,16 +241,16 @@ export default class SliderMonitor extends (PureComponent || Component) { } }; - getLatestTimestampDiff = (index) => + getLatestTimestampDiff = (index: number) => this.getTimestampOfStateIndex(index + 1) - this.getTimestampOfStateIndex(index); - getTimestampOfStateIndex = (stateIndex) => { + getTimestampOfStateIndex = (stateIndex: number) => { const id = this.props.stagedActionIds[stateIndex]; return this.props.actionsById[id].timestamp; }; - pauseReplay = (cb) => { + pauseReplay = (cb?: () => void) => { if (this.state.timer) { cancelAnimationFrame(this.state.timer); clearInterval(this.state.timer); @@ -246,7 +283,7 @@ export default class SliderMonitor extends (PureComponent || Component) { } }; - changeReplaySpeed = (replaySpeed) => { + changeReplaySpeed = (replaySpeed: string) => { this.setState({ replaySpeed }); if (this.state.timer) { @@ -276,7 +313,7 @@ export default class SliderMonitor extends (PureComponent || Component) { let actionType = actionsById[actionId].action.type; if (actionType === undefined) actionType = ''; else if (actionType === null) actionType = ''; - else actionType = actionType.toString() || ''; + else actionType = (actionType as string).toString() || ''; const onPlayClick = replaySpeed === 'Live' ? this.startRealtimeReplay : this.startReplay; @@ -295,7 +332,7 @@ export default class SliderMonitor extends (PureComponent || Component) { {playPause} > +> & { + update( + monitorProps: ExternalProps>, + // eslint-disable-next-line @typescript-eslint/ban-types + state: {} | undefined, + action: Action + // eslint-disable-next-line @typescript-eslint/ban-types + ): {}; + defaultProps: DefaultProps; +}; diff --git a/packages/redux-devtools-slider-monitor/src/reducers.js b/packages/redux-devtools-slider-monitor/src/reducers.ts similarity index 100% rename from packages/redux-devtools-slider-monitor/src/reducers.js rename to packages/redux-devtools-slider-monitor/src/reducers.ts diff --git a/packages/redux-devtools-slider-monitor/tsconfig.json b/packages/redux-devtools-slider-monitor/tsconfig.json new file mode 100644 index 00000000..7b7d1492 --- /dev/null +++ b/packages/redux-devtools-slider-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 640fd87b..812dc26b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -63,7 +63,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@>=7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.11.0", "@babel/core@^7.11.1", "@babel/core@^7.7.5": +"@babel/core@>=7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.11.1", "@babel/core@^7.7.5": version "7.11.1" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.1.tgz#2c55b604e73a40dc21b0e52650b11c65cf276643" integrity sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ==