diff --git a/packages/devui/.babelrc b/packages/devui/.babelrc index 645cc56e..912790c1 100755 --- a/packages/devui/.babelrc +++ b/packages/devui/.babelrc @@ -1,4 +1,11 @@ { - "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" + ], + "sourceType": "unambiguous" } diff --git a/packages/devui/.eslintignore b/packages/devui/.eslintignore new file mode 100644 index 00000000..b1e0862f --- /dev/null +++ b/packages/devui/.eslintignore @@ -0,0 +1,2 @@ +lib +demo diff --git a/packages/devui/.eslintrc.js b/packages/devui/.eslintrc.js new file mode 100644 index 00000000..72e1f8dd --- /dev/null +++ b/packages/devui/.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/devui/.prettierignore b/packages/devui/.prettierignore new file mode 100644 index 00000000..b1e0862f --- /dev/null +++ b/packages/devui/.prettierignore @@ -0,0 +1,2 @@ +lib +demo diff --git a/packages/devui/.storybook/config.js b/packages/devui/.storybook/config.js index eefdbad6..4c8be1fa 100755 --- a/packages/devui/.storybook/config.js +++ b/packages/devui/.storybook/config.js @@ -1,9 +1,9 @@ -import { configure, setAddon, addDecorator } from '@storybook/react'; +import { configure, addDecorator } from '@storybook/react'; import { withOptions } from '@storybook/addon-options'; import { withInfo } from '@storybook/addon-info'; import { withKnobs } from '@storybook/addon-knobs'; import { withTheme } from './themeAddon/theme'; -import '../src/presets.js'; +import '../src/presets'; addDecorator( withOptions({ @@ -21,7 +21,7 @@ addDecorator(withTheme); addDecorator(withKnobs); addDecorator(withInfo); -const req = require.context('../src/', true, /stories\/index\.js$/); +const req = require.context('../src/', true, /stories\/index\.tsx$/); function loadStories() { req.keys().forEach(filename => req(filename)); diff --git a/packages/devui/.storybook/themeAddon/Panel.js b/packages/devui/.storybook/themeAddon/Panel.js index 7e0ee5f4..44b1e5ba 100644 --- a/packages/devui/.storybook/themeAddon/Panel.js +++ b/packages/devui/.storybook/themeAddon/Panel.js @@ -2,7 +2,7 @@ import React from 'react'; import Form from '@storybook/addon-knobs/dist/components/PropForm'; import styled from 'styled-components'; import { EVENT_ID_DATA, DEFAULT_THEME_STATE } from './constant'; -import { listSchemes, listThemes } from '../../src/utils/theme'; +import { listSchemes, listThemes } from '../../lib/utils/theme'; const FormWrapper = styled.div` width: 100%; diff --git a/packages/devui/.storybook/webpack.config.js b/packages/devui/.storybook/webpack.config.js old mode 100755 new mode 100644 index 9fc16d31..3b3be188 --- a/packages/devui/.storybook/webpack.config.js +++ b/packages/devui/.storybook/webpack.config.js @@ -1,8 +1,12 @@ const path = require('path'); +const TSDocgenPlugin = require('react-docgen-typescript-webpack-plugin'); -module.exports = (baseConfig, env, defaultConfig) => { - // Add custom webpack config here like: - // defaultConfig.module.rules.push - - return defaultConfig; +module.exports = (baseConfig, env, config) => { + config.module.rules.push({ + test: /\.(ts|tsx)$/, + loader: require.resolve('babel-loader') + }); + config.plugins.push(new TSDocgenPlugin()); // optional + config.resolve.extensions.push('.ts', '.tsx'); + return config; }; diff --git a/packages/devui/package.json b/packages/devui/package.json index 7de9ccb9..a591b3fe 100755 --- a/packages/devui/package.json +++ b/packages/devui/package.json @@ -12,13 +12,22 @@ }, "author": "Mihail Diordiev (https://github.com/zalmoxisus)", "license": "MIT", + "main": "lib/index.js", + "types": "lib/index.d.ts", "scripts": { + "type-check": "tsc --noEmit", + "type-check:watch": "npm run type-check -- --watch", "start": "npm run storybook", - "build": "rimraf ./lib && babel ./src --out-dir ./lib --ignore tests,stories", + "clean": "rimraf lib", + "build": "npm run build:types && npm run build:js", + "build:types": "tsc --emitDeclarationOnly", + "build:js": "babel src --out-dir lib --ignore tests,stories --extensions \".ts,.tsx\" --source-maps inline", + "lint": "eslint . --ext .js,.jsx,.ts,.tsx", + "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix", "lint:css": "stylelint './src/**/styles/*.js'", "test:update": "npm run jest -- -u", "test": "jest --no-cache", - "storybook": "start-storybook -p 9001 -c .storybook -s ./fonts", + "storybook": "npm run build && start-storybook -p 9001 -c .storybook -s ./fonts", "publish-storybook": "bash .scripts/publish_storybook.sh", "prepare": "npm run build", "prepublishOnly": "npm run test && npm run build" @@ -36,11 +45,22 @@ "@babel/plugin-transform-runtime": "^7.2.0", "@babel/preset-env": "^7.3.1", "@babel/preset-react": "^7.0.0", - "@storybook/addon-actions": "^4.1.4", - "@storybook/addon-info": "^4.1.4", - "@storybook/addon-knobs": "^4.1.4", - "@storybook/addon-options": "^4.1.4", - "@storybook/react": "4.0.9", + "@storybook/addon-actions": "^4.1.18", + "@storybook/addon-info": "^4.1.18", + "@storybook/addon-knobs": "^4.1.18", + "@storybook/addon-options": "^4.1.18", + "@storybook/react": "^4.1.18", + "@types/codemirror": "^0.0.95", + "@types/color": "^2.0.1", + "@types/json-schema": "^7.0.4", + "@types/react-icons": "^2.2.7", + "@types/react-jsonschema-form": "^1.7.3", + "@types/react-select": "^1.3.4", + "@types/storybook__addon-actions": "^3.4.3", + "@types/storybook__addon-knobs": "^4.0.5", + "@types/storybook__react": "^4.0.2", + "babel-loader": "^8.1.0", + "csstype": "^2.6.10", "enzyme": "^3.1.0", "enzyme-adapter-react-16": "^1.0.2", "enzyme-to-json": "^3.1.4", @@ -48,18 +68,20 @@ "jest": "^24.1.0", "jsdom": "^11.3.0", "react": "^16.0.0", - "react-addons-test-utils": "^15.6.2", + "react-docgen-typescript-webpack-plugin": "^1.1.0", "react-dom": "^16.0.0", "react-test-renderer": "^16.0.0", "rimraf": "^2.6.2", "stylelint": "^7.6.0", "stylelint-config-standard": "^15.0.0", - "stylelint-processor-styled-components": "^0.0.4" + "stylelint-processor-styled-components": "^0.0.4", + "typescript": "^3.8.3" }, "peerDependencies": { "react": "^0.14.9 || ^15.3.0" }, "dependencies": { + "@types/prop-types": "^15.6.0", "base16": "^1.0.0", "codemirror": "^5.21.0", "color": "^2.0.0", @@ -73,6 +95,5 @@ }, "jest": { "setupTestFrameworkScriptFile": "/tests/setup.js" - }, - "main": "lib/index.js" + } } diff --git a/packages/devui/src/Button/Button.js b/packages/devui/src/Button/Button.js deleted file mode 100644 index a5211eaa..00000000 --- a/packages/devui/src/Button/Button.js +++ /dev/null @@ -1,92 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import createStyledComponent from '../utils/createStyledComponent'; -import * as styles from './styles'; -import { commonStyle, tooltipStyle } from './styles/common'; - -const ButtonWrapper = createStyledComponent(styles, 'button'); -const TooltipWrapper = createStyledComponent(tooltipStyle); -const CommonWrapper = createStyledComponent(commonStyle); - -export default class Button extends Component { - shouldComponentUpdate(nextProps) { - return ( - nextProps.children !== this.props.children || - nextProps.disabled !== this.props.disabled || - nextProps.mark !== this.props.mark || - nextProps.size !== this.props.size || - nextProps.primary !== this.props.primary || - nextProps.tooltipPosition !== this.props.tooltipPosition || - nextProps.title !== this.props.title - ); - } - - onMouseUp = e => { - e.target.blur(); - }; - - render() { - const button = ( - - {this.props.children} - - ); - - const Wrapper = this.props.title ? TooltipWrapper : CommonWrapper; - return ( - - {button} - - ); - } -} - -Button.propTypes = { - children: PropTypes.any.isRequired, - title: PropTypes.string, - tooltipPosition: PropTypes.oneOf([ - 'top', - 'bottom', - 'left', - 'right', - 'bottom-left', - 'bottom-right', - 'top-left', - 'top-right' - ]), - onClick: PropTypes.func, - type: PropTypes.string, - disabled: PropTypes.bool, - primary: PropTypes.bool, - size: PropTypes.oneOf(['big', 'normal', 'small']), - mark: PropTypes.oneOf([ - false, - 'base08', - 'base09', - 'base0A', - 'base0B', - 'base0C', - 'base0D', - 'base0E', - 'base0F' - ]), - theme: PropTypes.object -}; - -Button.defaultProps = { - tooltipPosition: 'top' -}; diff --git a/packages/devui/src/Button/Button.tsx b/packages/devui/src/Button/Button.tsx new file mode 100644 index 00000000..15b188bd --- /dev/null +++ b/packages/devui/src/Button/Button.tsx @@ -0,0 +1,128 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +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); +const CommonWrapper = createStyledComponent(commonStyle); + +export type TooltipPosition = + | 'top' + | 'bottom' + | 'left' + | 'right' + | 'bottom-left' + | 'bottom-right' + | 'top-left' + | 'top-right'; + +export type Size = 'big' | 'normal' | 'small'; + +export type Mark = + | 'base08' + | 'base09' + | 'base0A' + | 'base0B' + | 'base0C' + | 'base0D' + | 'base0E' + | 'base0F'; + +interface Props { + children: unknown; + title?: string; + tooltipPosition: TooltipPosition; + onClick?: React.MouseEventHandler; + type?: 'button' | 'reset' | 'submit'; + disabled?: boolean; + primary?: boolean; + size?: Size; + mark?: Mark | false; + theme?: Theme; +} + +export default class Button extends Component { + shouldComponentUpdate(nextProps: Props) { + return ( + nextProps.children !== this.props.children || + nextProps.disabled !== this.props.disabled || + nextProps.mark !== this.props.mark || + nextProps.size !== this.props.size || + nextProps.primary !== this.props.primary || + nextProps.tooltipPosition !== this.props.tooltipPosition || + nextProps.title !== this.props.title + ); + } + + onMouseUp: React.MouseEventHandler = e => { + e.currentTarget.blur(); + }; + + render() { + const button = ( + + {this.props.children} + + ); + + const Wrapper = this.props.title ? TooltipWrapper : CommonWrapper; + return ( + + {button} + + ); + } + + static propTypes = { + children: PropTypes.any.isRequired, + title: PropTypes.string, + tooltipPosition: PropTypes.oneOf([ + 'top', + 'bottom', + 'left', + 'right', + 'bottom-left', + 'bottom-right', + 'top-left', + 'top-right' + ]), + onClick: PropTypes.func, + type: PropTypes.string, + disabled: PropTypes.bool, + primary: PropTypes.bool, + size: PropTypes.oneOf(['big', 'normal', 'small']), + mark: PropTypes.oneOf([ + false, + 'base08', + 'base09', + 'base0A', + 'base0B', + 'base0C', + 'base0D', + 'base0E', + 'base0F' + ]), + theme: PropTypes.object + }; + + static defaultProps = { + tooltipPosition: 'top' + }; +} diff --git a/packages/devui/src/Button/index.js b/packages/devui/src/Button/index.ts similarity index 100% rename from packages/devui/src/Button/index.js rename to packages/devui/src/Button/index.ts diff --git a/packages/devui/src/Button/stories/index.js b/packages/devui/src/Button/stories/index.tsx old mode 100755 new mode 100644 similarity index 61% rename from packages/devui/src/Button/stories/index.js rename to packages/devui/src/Button/stories/index.tsx index 29a89650..b6831a4d --- a/packages/devui/src/Button/stories/index.js +++ b/packages/devui/src/Button/stories/index.tsx @@ -5,6 +5,7 @@ import { action } from '@storybook/addon-actions'; import { withKnobs, text, boolean, select } from '@storybook/addon-knobs'; import MdFiberManualRecord from 'react-icons/lib/md/fiber-manual-record'; import Button from '../'; +import { Mark, Size, TooltipPosition } from '../Button'; export const Container = styled.div` display: flex; @@ -20,18 +21,22 @@ storiesOf('Button', module)