diff --git a/.gitignore b/.gitignore index 2145901aa5..c2b0e26a6e 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,9 @@ Resources/Public/Styles/**/*.map Resources/Public/Styles/Font* lerna-debug.log npm-debug.log + +# +# editors / IDEs +# +.vscode/ +.idea/ diff --git a/package.json b/package.json index 55e1da97cb..b8f0670424 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,9 @@ "ts-loader": "^3", "tslib": "^1.9.3", "tslint": "^5.11.0", + "tslint-config-prettier": "^1.15.0", + "tslint-immutable": "^4.7.0", + "tslint-react": "^3.6.0", "typescript": "^3.0.1", "watch": "^1.0.2", "webpack": "^3.8.1", diff --git a/packages/react-ui-components/.storybook/webpack.config.js b/packages/react-ui-components/.storybook/webpack.config.js index 8b8eae2b02..3594a237d1 100644 --- a/packages/react-ui-components/.storybook/webpack.config.js +++ b/packages/react-ui-components/.storybook/webpack.config.js @@ -14,6 +14,13 @@ module.exports = (storybookBaseConfig, configType) => { // module: { rules: [ + { + test: /\.tsx?$/, + exclude: /(node_modules)/, + use: [{ + loader: 'ts-loader' + }] + }, { test: /\.js$/, exclude: /(node_modules)/, @@ -58,6 +65,10 @@ module.exports = (storybookBaseConfig, configType) => { }] } ] - } + }, + + resolve: { + extensions: ['.ts', '.tsx', '.js'] + }, }); }; diff --git a/packages/react-ui-components/package.json b/packages/react-ui-components/package.json index 7ea86e6329..290c755e5c 100644 --- a/packages/react-ui-components/package.json +++ b/packages/react-ui-components/package.json @@ -12,7 +12,7 @@ "babel": "babel ./src --out-dir ./lib", "css": "cpx './src/**/*.css' ./lib && cpx './src/**/*.woff' ./lib && cpx './src/**/*.woff2' ./lib", "clean": "rimraf ./lib ./dist", - "lint": "eslint src && stylelint 'src/**/*.css'", + "lint": "eslint src && stylelint 'src/**/*.css' && tslint -t codeFrame -p ../tsconfig.json -c ../../tslint.json", "jest": "NODE_ENV=test jest", "jest:updateSnapshots": "NODE_ENV=test jest -u", "start": "cross-env STORY=true start-storybook -p 9001" diff --git a/packages/react-ui-components/src/Badge/badge.js b/packages/react-ui-components/src/Badge/badge.js deleted file mode 100644 index 4dcd38d429..0000000000 --- a/packages/react-ui-components/src/Badge/badge.js +++ /dev/null @@ -1,44 +0,0 @@ -import React, {PureComponent} from 'react'; -import PropTypes from 'prop-types'; -import mergeClassNames from 'classnames'; - -class Badge extends PureComponent { - static propTypes = { - /** - * An optional `className` to attach to the wrapper. - */ - className: PropTypes.string, - - /** - * Badge's label. - */ - label: PropTypes.string, - - /** - * An optional css theme to be injected. - */ - theme: PropTypes.shape({ - badge: PropTypes.string - }).isRequired - }; - - render() { - const { - className, - theme, - label, - ...rest - } = this.props; - const finalClassName = mergeClassNames({ - [theme.badge]: true, - [className]: className && className.length - }); - const attributes = {}; - - return ( -
{label}
- ); - } -} - -export default Badge; diff --git a/packages/react-ui-components/src/Badge/badge.spec.js b/packages/react-ui-components/src/Badge/badge.spec.js index 255bd0c952..ae6476346f 100644 --- a/packages/react-ui-components/src/Badge/badge.spec.js +++ b/packages/react-ui-components/src/Badge/badge.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import Badge from './badge.js'; +import Badge from './badge'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/Badge/badge.tsx b/packages/react-ui-components/src/Badge/badge.tsx new file mode 100644 index 0000000000..7626178316 --- /dev/null +++ b/packages/react-ui-components/src/Badge/badge.tsx @@ -0,0 +1,41 @@ +import mergeClassNames from 'classnames'; +import React, {PureComponent} from 'react'; + +interface BadgeTheme { + readonly badge: string; +} + +interface BadgeProps { + /** + * An optional `className` to attach to the wrapper. + */ + readonly className?: string; + + /** + * Badge's label. + */ + readonly label: string; + + /** + * An optional css theme to be injected. + */ + readonly theme?: BadgeTheme; +} + +class Badge extends PureComponent { + public render(): JSX.Element { + const { + className, + theme, + label, + ...rest + } = this.props; + const finalClassName = mergeClassNames(theme!.badge, className); + + return ( +
{label}
+ ); + } +} + +export default Badge; diff --git a/packages/react-ui-components/src/Badge/index.js b/packages/react-ui-components/src/Badge/index.js index e951da1f8c..a0140d4de2 100644 --- a/packages/react-ui-components/src/Badge/index.js +++ b/packages/react-ui-components/src/Badge/index.js @@ -1,6 +1,6 @@ import {themr} from '@friendsofreactjs/react-css-themr'; -import identifiers from './../identifiers'; +import identifiers from '../identifiers'; import style from './style.css'; -import Badge from './badge.js'; +import Badge from './badge'; export default themr(identifiers.badge, style)(Badge); diff --git a/packages/react-ui-components/src/Badge/index.spec.js b/packages/react-ui-components/src/Badge/index.spec.js index 804013406c..db68e568fe 100644 --- a/packages/react-ui-components/src/Badge/index.spec.js +++ b/packages/react-ui-components/src/Badge/index.spec.js @@ -1,4 +1,4 @@ -import Badge from './index.js'; +import Badge from '.'; describe(' (entry point)', () => { it('should export a Component.', () => { diff --git a/packages/react-ui-components/src/Badge/index.story.js b/packages/react-ui-components/src/Badge/index.story.js index 4a7ec719fb..f7b1eb984b 100644 --- a/packages/react-ui-components/src/Badge/index.story.js +++ b/packages/react-ui-components/src/Badge/index.story.js @@ -1,8 +1,8 @@ import React from 'react'; import {storiesOf} from '@storybook/react'; import {withKnobs, text} from '@storybook/addon-knobs'; -import {StoryWrapper} from './../_lib/storyUtils.js'; -import Badge from './index.js'; +import {StoryWrapper} from './../_lib/storyUtils'; +import Badge from '.'; storiesOf('Badge', module) .addDecorator(withKnobs) diff --git a/packages/react-ui-components/src/Bar/bar.js b/packages/react-ui-components/src/Bar/bar.js deleted file mode 100644 index 914b76cab3..0000000000 --- a/packages/react-ui-components/src/Bar/bar.js +++ /dev/null @@ -1,49 +0,0 @@ -import React, {PureComponent} from 'react'; -import PropTypes from 'prop-types'; -import mergeClassNames from 'classnames'; - -class Bar extends PureComponent { - static propTypes = { - /** - * This prop controls the vertical positioning of the Bar. - */ - position: PropTypes.oneOf(['top', 'bottom']).isRequired, - - /** - * An optional css theme to be injected. - */ - theme: PropTypes.shape({ - 'bar': PropTypes.string, - 'bar--top': PropTypes.string, - 'bar--bottom': PropTypes.string - }).isRequired, - - /** - * An optional `className` to attach to the wrapper. - */ - className: PropTypes.string, - - /** - * The contents to be rendered within the `Bar`. - */ - children: PropTypes.any.isRequired - }; - - render() { - const {position, className, theme, children, ...rest} = this.props; - const finalClassName = mergeClassNames({ - [className]: className && className.length, - [theme.bar]: true, - [theme['bar--top']]: position === 'top', - [theme['bar--bottom']]: position === 'bottom' - }); - - return ( -
- {children} -
- ); - } -} - -export default Bar; diff --git a/packages/react-ui-components/src/Bar/bar.spec.js b/packages/react-ui-components/src/Bar/bar.spec.js index 2a414699f5..1616d8deb3 100644 --- a/packages/react-ui-components/src/Bar/bar.spec.js +++ b/packages/react-ui-components/src/Bar/bar.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import Bar from './bar.js'; +import Bar from './bar'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/Bar/bar.tsx b/packages/react-ui-components/src/Bar/bar.tsx new file mode 100644 index 0000000000..eb7b724506 --- /dev/null +++ b/packages/react-ui-components/src/Bar/bar.tsx @@ -0,0 +1,59 @@ +import mergeClassNames from 'classnames'; +import React, {PureComponent} from 'react'; + +type BarPosition = 'top' | 'bottom'; + +interface BarTheme { + readonly 'bar': string; + readonly 'bar--top': string; + readonly 'bar--bottom': string; +} + +interface BarProps { + /** + * This prop controls the vertical positioning of the Bar. + */ + readonly position: BarPosition; + + /** + * An optional css theme to be injected. + */ + readonly theme?: BarTheme; + + /** + * An optional `className` to attach to the wrapper. + */ + readonly className?: string; + + /** + * The contents to be rendered within the `Bar`. + */ + readonly children: React.ReactNode; +} + +class Bar extends PureComponent { + public render(): JSX.Element { + const {position, className, theme, children, ...rest} = this.props; + const finalClassName = mergeClassNames( + className, + theme!.bar, + { + [theme!['bar--top']]: position === 'top', + [theme!['bar--bottom']]: position === 'bottom' + } + ); + + // TODO: + // The prop 'rest' is empty here. I suppose it contains all the attributes that are not part of the Badge Api/Interface. + // Consider enxtending Bagde with React.HTMLAttributes like we did in the Button component. + // It also enables autocomplete for the whole div Api. + // Consider this for the other components. + return ( +
+ {children} +
+ ); + } +} + +export default Bar; diff --git a/packages/react-ui-components/src/Bar/index.js b/packages/react-ui-components/src/Bar/index.js index 7c06b5e395..7e1ded97f1 100644 --- a/packages/react-ui-components/src/Bar/index.js +++ b/packages/react-ui-components/src/Bar/index.js @@ -1,6 +1,6 @@ import {themr} from '@friendsofreactjs/react-css-themr'; -import identifiers from './../identifiers'; +import identifiers from '../identifiers'; import style from './style.css'; -import Bar from './bar.js'; +import Bar from './bar'; export default themr(identifiers.bar, style)(Bar); diff --git a/packages/react-ui-components/src/Bar/index.spec.js b/packages/react-ui-components/src/Bar/index.spec.js index 8cba3a8651..71b044a505 100644 --- a/packages/react-ui-components/src/Bar/index.spec.js +++ b/packages/react-ui-components/src/Bar/index.spec.js @@ -1,4 +1,4 @@ -import Bar from './index.js'; +import Bar from '.'; describe(' (entry point)', () => { it('should export a Component.', () => { diff --git a/packages/react-ui-components/src/Bar/index.story.js b/packages/react-ui-components/src/Bar/index.story.js index 512a9aab51..ad1dde7528 100644 --- a/packages/react-ui-components/src/Bar/index.story.js +++ b/packages/react-ui-components/src/Bar/index.story.js @@ -1,8 +1,8 @@ import React from 'react'; import {storiesOf} from '@storybook/react'; import {withKnobs, select} from '@storybook/addon-knobs'; -import {StoryWrapper} from './../_lib/storyUtils.js'; -import Bar from './index.js'; +import {StoryWrapper} from './../_lib/storyUtils'; +import Bar from '.'; storiesOf('Bar', module) .addDecorator(withKnobs) diff --git a/packages/react-ui-components/src/Button/__snapshots__/button.spec.js.snap b/packages/react-ui-components/src/Button/__snapshots__/button.spec.js.snap index 08ceb85b4f..07bd72b830 100644 --- a/packages/react-ui-components/src/Button/__snapshots__/button.spec.js.snap +++ b/packages/react-ui-components/src/Button/__snapshots__/button.spec.js.snap @@ -3,6 +3,7 @@ exports[` - ); - } -} - -export default Button; diff --git a/packages/react-ui-components/src/Button/button.spec.js b/packages/react-ui-components/src/Button/button.spec.js index 2d79b1a18b..9ef769798c 100644 --- a/packages/react-ui-components/src/Button/button.spec.js +++ b/packages/react-ui-components/src/Button/button.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import Button from './button.js'; +import Button from './button'; describe(' + ); + } +} + +export default Button; diff --git a/packages/react-ui-components/src/Button/index.js b/packages/react-ui-components/src/Button/index.js index 34dcf12a1a..f5cf48e6be 100644 --- a/packages/react-ui-components/src/Button/index.js +++ b/packages/react-ui-components/src/Button/index.js @@ -1,6 +1,6 @@ import {themr} from '@friendsofreactjs/react-css-themr'; -import identifiers from './../identifiers'; +import identifiers from '../identifiers'; import style from './style.css'; -import Button from './button.js'; +import Button from './button'; export default themr(identifiers.button, style)(Button); diff --git a/packages/react-ui-components/src/Button/index.spec.js b/packages/react-ui-components/src/Button/index.spec.js index b06e92562d..6c8a3b0dca 100644 --- a/packages/react-ui-components/src/Button/index.spec.js +++ b/packages/react-ui-components/src/Button/index.spec.js @@ -1,4 +1,4 @@ -import Button from './index.js'; +import Button from '.'; describe(' @@ -86,7 +86,7 @@ storiesOf('Button', module) isActive={boolean('Active', false)} isDisabled={boolean('Disabled', false)} size={select('Size', validSizes, 'regular')} - > + > {text('Label', 'Button Clean')} @@ -149,7 +149,7 @@ storiesOf('Button', module) isActive={boolean('Active', false)} isDisabled={boolean('Disabled', false)} size={select('Size', validSizes, 'regular')} - > + > {text('Label', 'Button Clean')} @@ -212,7 +212,7 @@ storiesOf('Button', module) isActive={boolean('Active', false)} isDisabled={boolean('Disabled', false)} size={select('Size', validSizes, 'regular')} - > + > {text('Label', 'Button Clean')} diff --git a/packages/react-ui-components/src/ButtonGroup/buttonGroup.js b/packages/react-ui-components/src/ButtonGroup/buttonGroup.js index ed29474d17..003dbe7f17 100644 --- a/packages/react-ui-components/src/ButtonGroup/buttonGroup.js +++ b/packages/react-ui-components/src/ButtonGroup/buttonGroup.js @@ -1,7 +1,7 @@ import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import mergeClassNames from 'classnames'; -import ButtonGroupItem from './buttonGroupItem.js'; +import ButtonGroupItem from './buttonGroupItem'; class ButtonGroup extends PureComponent { static propTypes = { diff --git a/packages/react-ui-components/src/ButtonGroup/buttonGroup.spec.js b/packages/react-ui-components/src/ButtonGroup/buttonGroup.spec.js index cb1c500c12..8f69ae79b5 100644 --- a/packages/react-ui-components/src/ButtonGroup/buttonGroup.spec.js +++ b/packages/react-ui-components/src/ButtonGroup/buttonGroup.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import ButtonGroup from './buttonGroup.js'; +import ButtonGroup from './buttonGroup'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/ButtonGroup/buttonGroupItem.spec.js b/packages/react-ui-components/src/ButtonGroup/buttonGroupItem.spec.js index 87c307884b..0500b12ef2 100644 --- a/packages/react-ui-components/src/ButtonGroup/buttonGroupItem.spec.js +++ b/packages/react-ui-components/src/ButtonGroup/buttonGroupItem.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import ButtonGroupItem from './buttonGroupItem.js'; +import ButtonGroupItem from './buttonGroupItem'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/ButtonGroup/index.js b/packages/react-ui-components/src/ButtonGroup/index.js index e5909798fe..af7f13d704 100644 --- a/packages/react-ui-components/src/ButtonGroup/index.js +++ b/packages/react-ui-components/src/ButtonGroup/index.js @@ -1,6 +1,6 @@ import {themr} from '@friendsofreactjs/react-css-themr'; -import identifiers from './../identifiers'; +import identifiers from '../identifiers'; import style from './style.css'; -import ButtonGroup from './buttonGroup.js'; +import ButtonGroup from './buttonGroup'; export default themr(identifiers.buttonGroup, style)(ButtonGroup); diff --git a/packages/react-ui-components/src/ButtonGroup/index.spec.js b/packages/react-ui-components/src/ButtonGroup/index.spec.js index 34272574f1..0390b14e87 100644 --- a/packages/react-ui-components/src/ButtonGroup/index.spec.js +++ b/packages/react-ui-components/src/ButtonGroup/index.spec.js @@ -1,4 +1,4 @@ -import ButtonGroup from './index.js'; +import ButtonGroup from '.'; describe(' (entry point)', () => { it('should export a Component.', () => { diff --git a/packages/react-ui-components/src/ButtonGroup/index.story.js b/packages/react-ui-components/src/ButtonGroup/index.story.js index efb81f39d1..e1b12ffe97 100644 --- a/packages/react-ui-components/src/ButtonGroup/index.story.js +++ b/packages/react-ui-components/src/ButtonGroup/index.story.js @@ -1,9 +1,9 @@ import React from 'react'; import {storiesOf, action} from '@storybook/react'; import {withKnobs} from '@storybook/addon-knobs'; -import {StoryWrapper} from './../_lib/storyUtils.js'; -import ButtonGroup from './index.js'; -import IconButton from './../IconButton/index.js'; +import {StoryWrapper} from './../_lib/storyUtils'; +import ButtonGroup from '.'; +import IconButton from './../IconButton'; storiesOf('ButtonGroup', module) .addDecorator(withKnobs) @@ -18,20 +18,20 @@ storiesOf('ButtonGroup', module) style="lighter" icon="level-up-alt" title="One, active" - /> + /> + /> + /> ), diff --git a/packages/react-ui-components/src/CheckBox/checkBox.js b/packages/react-ui-components/src/CheckBox/checkBox.js deleted file mode 100644 index 607731e5ba..0000000000 --- a/packages/react-ui-components/src/CheckBox/checkBox.js +++ /dev/null @@ -1,81 +0,0 @@ -import React, {PureComponent} from 'react'; -import PropTypes from 'prop-types'; -import mergeClassNames from 'classnames'; - -class CheckBox extends PureComponent { - static propTypes = { - /** - * This prop controls the visual active state of the CheckBox. - */ - isChecked: PropTypes.bool.isRequired, - - /** - * This prop controls if the CheckBox is disabled or not. - */ - isDisabled: PropTypes.bool, - - /** - * An optional `className` to attach to the wrapper. - */ - className: PropTypes.string, - - /** - * An optional change handler which gets called once the user clicks on the CheckBox. - */ - onChange: PropTypes.func, - - /** - * An optional css theme to be injected. - */ - theme: PropTypes.shape({ - checkbox: PropTypes.string, - checkbox__input: PropTypes.string, // eslint-disable-line - checkbox__inputMirror: PropTypes.string, // eslint-disable-line - 'checkbox__inputMirror--active': PropTypes.string - }).isRequired - }; - - handleChange = () => { - const {onChange, isChecked} = this.props; - - if (onChange) { - onChange(!isChecked); - } - } - - render() { - const { - isChecked, - isDisabled, - className, - theme, - ...rest - } = this.props; - const finalClassName = mergeClassNames({ - [className]: className && className.length, - [theme.checkbox]: true, - [theme.checkbox__disabled]: isDisabled - }); - const mirrorClassNames = mergeClassNames({ - [theme.checkbox__inputMirror]: true, - [theme['checkbox__inputMirror--active']]: isChecked - }); - - return ( -
- -
-
- ); - } -} - -export default CheckBox; diff --git a/packages/react-ui-components/src/CheckBox/checkBox.spec.js b/packages/react-ui-components/src/CheckBox/checkBox.spec.js index 1bf4952f82..5d61833569 100644 --- a/packages/react-ui-components/src/CheckBox/checkBox.spec.js +++ b/packages/react-ui-components/src/CheckBox/checkBox.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import CheckBox from './checkBox.js'; +import CheckBox from './checkBox'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/CheckBox/checkBox.tsx b/packages/react-ui-components/src/CheckBox/checkBox.tsx new file mode 100644 index 0000000000..5efde12d0d --- /dev/null +++ b/packages/react-ui-components/src/CheckBox/checkBox.tsx @@ -0,0 +1,87 @@ +import mergeClassNames from 'classnames'; +import React, {PureComponent} from 'react'; + +interface CheckBoxTheme { + readonly checkbox: string; + readonly checkbox__disabled: string; + readonly checkbox__input: string; // eslint-disable-line + readonly checkbox__inputMirror: string; // eslint-disable-line + readonly 'checkbox__inputMirror--active': string; +} + +interface CheckBoxProps { + /** + * This prop controls the visual active state of the CheckBox. + */ + readonly isChecked: boolean; + + /** + * This prop controls if the CheckBox is disabled or not. + */ + readonly isDisabled?: boolean; + + /** + * An optional `className` to attach to the wrapper. + */ + readonly className?: string; + + /** + * An optional change handler which gets called once the user clicks on the CheckBox. + */ + readonly onChange?: (isChecked: boolean) => void; + + /** + * An optional css theme to be injected. + */ + readonly theme: CheckBoxTheme; +} + +class CheckBox extends PureComponent { + public render(): JSX.Element { + const { + isChecked, + isDisabled, + className, + theme, + ...rest + } = this.props; + const finalClassName = mergeClassNames( + className, + theme.checkbox, + { + [theme.checkbox__disabled]: isDisabled, + } + ); + const mirrorClassNames = mergeClassNames( + theme.checkbox__inputMirror, + { + [theme['checkbox__inputMirror--active']]: isChecked, + } + ); + + return ( +
+ +
+
+ ); + } + + private readonly handleChange = () => { + const {onChange, isChecked} = this.props; + + if (onChange) { + onChange(!isChecked); + } + } +} + +export default CheckBox; diff --git a/packages/react-ui-components/src/CheckBox/index.js b/packages/react-ui-components/src/CheckBox/index.js index b75e1289ed..dfa3133b33 100644 --- a/packages/react-ui-components/src/CheckBox/index.js +++ b/packages/react-ui-components/src/CheckBox/index.js @@ -1,6 +1,6 @@ import {themr} from '@friendsofreactjs/react-css-themr'; -import identifiers from './../identifiers'; +import identifiers from '../identifiers'; import style from './style.css'; -import CheckBox from './checkBox.js'; +import CheckBox from './checkBox'; export default themr(identifiers.checkBox, style)(CheckBox); diff --git a/packages/react-ui-components/src/CheckBox/index.spec.js b/packages/react-ui-components/src/CheckBox/index.spec.js index da2402fb53..7227f9dee6 100644 --- a/packages/react-ui-components/src/CheckBox/index.spec.js +++ b/packages/react-ui-components/src/CheckBox/index.spec.js @@ -1,4 +1,4 @@ -import CheckBox from './index.js'; +import CheckBox from '.'; describe(' (entry point)', () => { it('should export a Component.', () => { diff --git a/packages/react-ui-components/src/CheckBox/index.story.js b/packages/react-ui-components/src/CheckBox/index.story.js index ab67ec46b7..440cb2cdd6 100644 --- a/packages/react-ui-components/src/CheckBox/index.story.js +++ b/packages/react-ui-components/src/CheckBox/index.story.js @@ -1,8 +1,8 @@ import React from 'react'; import {storiesOf, action} from '@storybook/react'; import {withKnobs, boolean} from '@storybook/addon-knobs'; -import {StoryWrapper} from './../_lib/storyUtils.js'; -import CheckBox from './index.js'; +import {StoryWrapper} from './../_lib/storyUtils'; +import CheckBox from '.'; storiesOf('CheckBox', module) .addDecorator(withKnobs) diff --git a/packages/react-ui-components/src/DateInput/dateInput.spec.js b/packages/react-ui-components/src/DateInput/dateInput.spec.js index 7a2909f574..38b71659ba 100644 --- a/packages/react-ui-components/src/DateInput/dateInput.spec.js +++ b/packages/react-ui-components/src/DateInput/dateInput.spec.js @@ -2,8 +2,8 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; import moment from 'moment'; -import {createStubComponent} from './../_lib/testUtils.js'; -import {DateInput} from './dateInput.js'; +import {createStubComponent} from './../_lib/testUtils'; +import {DateInput} from './dateInput'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/DateInput/index.js b/packages/react-ui-components/src/DateInput/index.js index 1e32e44031..5ba7f60aaa 100644 --- a/packages/react-ui-components/src/DateInput/index.js +++ b/packages/react-ui-components/src/DateInput/index.js @@ -1,5 +1,5 @@ import {themr} from '@friendsofreactjs/react-css-themr'; -import identifiers from './../identifiers'; +import identifiers from '../identifiers'; import style from './style.css'; import DateInput from './dateInput'; @@ -8,9 +8,9 @@ const ThemedDateInput = themr(identifiers.dateInput, style)(DateInput); // // Dependency injection // -import injectProps from './../_lib/injectProps.js'; -import Button from './../Button/index'; -import Icon from './../Icon/index'; +import injectProps from './../_lib/injectProps'; +import Button from './../Button'; +import Icon from './../Icon'; import DatePicker from 'react-datetime'; import Collapse from 'react-collapse'; diff --git a/packages/react-ui-components/src/DateInput/index.spec.js b/packages/react-ui-components/src/DateInput/index.spec.js index 0f844289f2..0255b2aca1 100644 --- a/packages/react-ui-components/src/DateInput/index.spec.js +++ b/packages/react-ui-components/src/DateInput/index.spec.js @@ -1,4 +1,4 @@ -import DateInput from './index.js'; +import DateInput from '.'; describe(' (entry point)', () => { it('should export a Component.', () => { diff --git a/packages/react-ui-components/src/DateInput/index.story.js b/packages/react-ui-components/src/DateInput/index.story.js index 447f8d1da3..055b4a23b4 100644 --- a/packages/react-ui-components/src/DateInput/index.story.js +++ b/packages/react-ui-components/src/DateInput/index.story.js @@ -1,8 +1,8 @@ import React from 'react'; import {storiesOf, action} from '@storybook/react'; import {withKnobs, text, boolean} from '@storybook/addon-knobs'; -import {StoryWrapper} from './../_lib/storyUtils.js'; -import DateInput from './index.js'; +import {StoryWrapper} from './../_lib/storyUtils'; +import DateInput from '.'; storiesOf('DateInput', module) .addDecorator(withKnobs) diff --git a/packages/react-ui-components/src/Dialog/dialog.spec.js b/packages/react-ui-components/src/Dialog/dialog.spec.js index 5ccf65771c..589d155a76 100644 --- a/packages/react-ui-components/src/Dialog/dialog.spec.js +++ b/packages/react-ui-components/src/Dialog/dialog.spec.js @@ -1,8 +1,8 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import {createStubComponent} from './../_lib/testUtils.js'; -import {DialogWithoutEscape as Dialog} from './dialog.js'; +import {createStubComponent} from './../_lib/testUtils'; +import {DialogWithoutEscape as Dialog} from './dialog'; import Portal from 'react-portal'; describe('', () => { diff --git a/packages/react-ui-components/src/Dialog/index.js b/packages/react-ui-components/src/Dialog/index.js index 44cbd9433a..0f66bdc57c 100644 --- a/packages/react-ui-components/src/Dialog/index.js +++ b/packages/react-ui-components/src/Dialog/index.js @@ -1,15 +1,15 @@ import {themr} from '@friendsofreactjs/react-css-themr'; -import identifiers from './../identifiers'; +import identifiers from '../identifiers'; import style from './style.css'; -import Dialog from './dialog.js'; +import Dialog from './dialog'; const ThemedDialog = themr(identifiers.dialog, style)(Dialog); // // Dependency injection // -import injectProps from './../_lib/injectProps.js'; -import IconButton from './../IconButton/index'; +import injectProps from './../_lib/injectProps'; +import IconButton from './../IconButton'; export default injectProps({ IconButtonComponent: IconButton diff --git a/packages/react-ui-components/src/Dialog/index.spec.js b/packages/react-ui-components/src/Dialog/index.spec.js index 97b7aabeb6..c2fad6657b 100644 --- a/packages/react-ui-components/src/Dialog/index.spec.js +++ b/packages/react-ui-components/src/Dialog/index.spec.js @@ -1,4 +1,4 @@ -import Dialog from './index.js'; +import Dialog from '.'; describe(' (entry point)', () => { it('should export a Component.', () => { diff --git a/packages/react-ui-components/src/Dialog/index.story.js b/packages/react-ui-components/src/Dialog/index.story.js index 156ef77ec4..c85338cbe0 100644 --- a/packages/react-ui-components/src/Dialog/index.story.js +++ b/packages/react-ui-components/src/Dialog/index.story.js @@ -1,9 +1,9 @@ import React from 'react'; import {storiesOf, action} from '@storybook/react'; import {withKnobs, text, boolean} from '@storybook/addon-knobs'; -import {StoryWrapper} from './../_lib/storyUtils.js'; -import Dialog from './index.js'; -import Button from './../Button/index.js'; +import {StoryWrapper} from './../_lib/storyUtils'; +import Dialog from '.'; +import Button from './../Button'; storiesOf('Dialog', module) .addDecorator(withKnobs) diff --git a/packages/react-ui-components/src/DropDown/contents.spec.js b/packages/react-ui-components/src/DropDown/contents.spec.js index 6a793709c5..9c8313c4e6 100644 --- a/packages/react-ui-components/src/DropDown/contents.spec.js +++ b/packages/react-ui-components/src/DropDown/contents.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import ShallowDropDownContents from './contents.js'; +import ShallowDropDownContents from './contents'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/DropDown/header.spec.js b/packages/react-ui-components/src/DropDown/header.spec.js index be89fe1f20..92b0f982f0 100644 --- a/packages/react-ui-components/src/DropDown/header.spec.js +++ b/packages/react-ui-components/src/DropDown/header.spec.js @@ -1,8 +1,8 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import {createStubComponent} from './../_lib/testUtils.js'; -import ShallowDropDownHeader from './header.js'; +import {createStubComponent} from './../_lib/testUtils'; +import ShallowDropDownHeader from './header'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/DropDown/index.js b/packages/react-ui-components/src/DropDown/index.js index 4454c198fc..8bb41f15b3 100644 --- a/packages/react-ui-components/src/DropDown/index.js +++ b/packages/react-ui-components/src/DropDown/index.js @@ -1,11 +1,11 @@ import {themr} from '@friendsofreactjs/react-css-themr'; -import identifiers from './../identifiers'; +import identifiers from '../identifiers'; import style from './style.css'; import ContextDropDownWrapper, { StatelessDropDownWrapper, ContextDropDownHeader, ContextDropDownContents -} from './wrapper.js'; +} from './wrapper'; const DropDown = themr(identifiers.dropDown, style)(ContextDropDownWrapper); const StatelessDropDown = themr(identifiers.dropDown, style)(StatelessDropDownWrapper); @@ -15,8 +15,8 @@ const DropDownContents = themr(identifiers.dropDownContents, style)(ContextDropD // // Dependency injection // -import injectProps from './../_lib/injectProps.js'; -import Icon from './../Icon/index'; +import injectProps from './../_lib/injectProps'; +import Icon from './../Icon'; DropDown.Header = injectProps({ IconComponent: Icon diff --git a/packages/react-ui-components/src/DropDown/index.spec.js b/packages/react-ui-components/src/DropDown/index.spec.js index afdbe32140..1d88a1dcd0 100644 --- a/packages/react-ui-components/src/DropDown/index.spec.js +++ b/packages/react-ui-components/src/DropDown/index.spec.js @@ -1,4 +1,4 @@ -import DropDown from './index.js'; +import DropDown from '.'; describe(' (entry point)', () => { it('should export a Component.', () => { diff --git a/packages/react-ui-components/src/DropDown/index.story.js b/packages/react-ui-components/src/DropDown/index.story.js index 9e5385cf79..b6c669856a 100644 --- a/packages/react-ui-components/src/DropDown/index.story.js +++ b/packages/react-ui-components/src/DropDown/index.story.js @@ -1,8 +1,8 @@ import React from 'react'; import {storiesOf} from '@storybook/react'; import {withKnobs, text, boolean, select} from '@storybook/addon-knobs'; -import {StoryWrapper} from './../_lib/storyUtils.js'; -import DropDown from './index.js'; +import {StoryWrapper} from './../_lib/storyUtils'; +import DropDown from '.'; const validStyles = ['default', 'darker']; diff --git a/packages/react-ui-components/src/DropDown/wrapper.js b/packages/react-ui-components/src/DropDown/wrapper.js index d0289de7ab..b9c4483ce2 100644 --- a/packages/react-ui-components/src/DropDown/wrapper.js +++ b/packages/react-ui-components/src/DropDown/wrapper.js @@ -3,8 +3,8 @@ import PropTypes from 'prop-types'; import omit from 'lodash.omit'; import mergeClassNames from 'classnames'; import enhanceWithClickOutside from 'react-click-outside'; -import ShallowDropDownHeader from './header.js'; -import ShallowDropDownContents from './contents.js'; +import ShallowDropDownHeader from './header'; +import ShallowDropDownContents from './contents'; const wrapperPropTypes = { /** diff --git a/packages/react-ui-components/src/DropDown/wrapper.spec.js b/packages/react-ui-components/src/DropDown/wrapper.spec.js index 1b77bcc389..8c1d1488f5 100644 --- a/packages/react-ui-components/src/DropDown/wrapper.spec.js +++ b/packages/react-ui-components/src/DropDown/wrapper.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import {DropDownWrapper} from './wrapper.js'; +import {DropDownWrapper} from './wrapper'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/Frame/frame.spec.js b/packages/react-ui-components/src/Frame/frame.spec.js index 3e9b74728e..414c2d7b17 100644 --- a/packages/react-ui-components/src/Frame/frame.spec.js +++ b/packages/react-ui-components/src/Frame/frame.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import Frame from './frame.js'; +import Frame from './frame'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/Frame/index.js b/packages/react-ui-components/src/Frame/index.js index eab1e2411d..c700ea82ed 100644 --- a/packages/react-ui-components/src/Frame/index.js +++ b/packages/react-ui-components/src/Frame/index.js @@ -1,5 +1,5 @@ import {themr} from '@friendsofreactjs/react-css-themr'; -import identifiers from './../identifiers'; -import Frame from './frame.js'; +import identifiers from '../identifiers'; +import Frame from './frame'; export default themr(identifiers.frame)(Frame); diff --git a/packages/react-ui-components/src/Frame/index.spec.js b/packages/react-ui-components/src/Frame/index.spec.js index 549fbc7e8c..068f05264e 100644 --- a/packages/react-ui-components/src/Frame/index.spec.js +++ b/packages/react-ui-components/src/Frame/index.spec.js @@ -1,4 +1,4 @@ -import Frame from './index.js'; +import Frame from '.'; describe(' (entry point)', () => { it('should export a Component.', () => { diff --git a/packages/react-ui-components/src/Headline/headline.js b/packages/react-ui-components/src/Headline/headline.js deleted file mode 100644 index 43246b7f61..0000000000 --- a/packages/react-ui-components/src/Headline/headline.js +++ /dev/null @@ -1,95 +0,0 @@ -import React, {PureComponent} from 'react'; -import PropTypes from 'prop-types'; -import mergeClassNames from 'classnames'; - -const types = [ - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6' -]; - -class Headline extends PureComponent { - static propTypes = { - /** - * The contents to be rendered. - */ - children: PropTypes.any.isRequired, - - /** - * The semantic tag type of the headline. - */ - type: PropTypes.oneOf(types).isRequired, - - /** - * Optional style identifier, this enables the possibility to diff the - * semantic value of the UI to the displayed style. - */ - style: PropTypes.oneOf(types), - - /** - * An optional `className` to attach to the wrapper. - */ - className: PropTypes.string, - - /** - * An optional css theme to be injected. - */ - theme: PropTypes.shape({ - 'heading': PropTypes.string, - 'heading--h1': PropTypes.string - }).isRequired - }; - - static defaultProps = { - type: 'h1' - }; - - render() { - const { - type, - className, - children, - theme, - ...rest - } = this.props; - const classNames = mergeClassNames({ - [theme.heading]: true, - [theme['heading--h1']]: true, - [className]: className && className.length - }); - let heading; - - switch (type) { - case 'h1': - heading =

{children}

; - break; - - case 'h2': - heading =

{children}

; - break; - - case 'h3': - heading =

{children}

; - break; - - case 'h4': - heading =

{children}

; - break; - - case 'h5': - heading =
{children}
; - break; - - default: - heading =
{children}
; - break; - } - - return heading; - } -} - -export default Headline; diff --git a/packages/react-ui-components/src/Headline/headline.spec.js b/packages/react-ui-components/src/Headline/headline.spec.js index 6d13e216b4..50c3242572 100644 --- a/packages/react-ui-components/src/Headline/headline.spec.js +++ b/packages/react-ui-components/src/Headline/headline.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import Headline from './headline.js'; +import Headline from './headline'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/Headline/headline.tsx b/packages/react-ui-components/src/Headline/headline.tsx new file mode 100644 index 0000000000..5274236740 --- /dev/null +++ b/packages/react-ui-components/src/Headline/headline.tsx @@ -0,0 +1,76 @@ +import mergeClassNames from 'classnames'; +import React, {PureComponent} from 'react'; + +import {PickDefaultProps} from '../../types'; + +type HeadlineType = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; + +interface HeadlineTheme { + readonly 'heading': string; + readonly 'heading--h1': string; +} + +interface HeadlineProps { + /** + * The contents to be rendered. + */ + readonly children: React.ReactNode; + + /** + * The semantic tag type of the headline. + */ + readonly type: HeadlineType; + + /** + * Optional style identifier, this enables the possibility to diff the + * semantic value of the UI to the displayed style. + */ + readonly style?: HeadlineType; + + /** + * An optional `className` to attach to the wrapper. + */ + readonly className?: string; + + /** + * An optional css theme to be injected. + */ + readonly theme?: HeadlineTheme; +} + +type DefaultProps = PickDefaultProps; + +class Headline extends PureComponent { + public static readonly defaultProps: DefaultProps = { + type: 'h1', + }; + + public render(): JSX.Element { + const { + type, + className, + children, + theme, + style, // TODO: Discuss what this style prop should do. + ...rest + } = this.props; + const classNames = mergeClassNames(theme!.heading, theme!['heading--h1'], className); + + switch (type) { + case 'h1': + return

{children}

; + case 'h2': + return

{children}

; + case 'h3': + return

{children}

; + case 'h4': + return

{children}

; + case 'h5': + return
{children}
; + default: + return
{children}
; + } + } +} + +export default Headline; diff --git a/packages/react-ui-components/src/Headline/index.js b/packages/react-ui-components/src/Headline/index.js index 347336d469..1eb898c58c 100644 --- a/packages/react-ui-components/src/Headline/index.js +++ b/packages/react-ui-components/src/Headline/index.js @@ -1,6 +1,6 @@ import {themr} from '@friendsofreactjs/react-css-themr'; -import identifiers from './../identifiers'; +import identifiers from '../identifiers'; import style from './style.css'; -import Headline from './headline.js'; +import Headline from './headline'; export default themr(identifiers.headline, style)(Headline); diff --git a/packages/react-ui-components/src/Headline/index.spec.js b/packages/react-ui-components/src/Headline/index.spec.js index 2d39b9a82e..17ecdb8b1c 100644 --- a/packages/react-ui-components/src/Headline/index.spec.js +++ b/packages/react-ui-components/src/Headline/index.spec.js @@ -1,4 +1,4 @@ -import Headline from './index.js'; +import Headline from '.'; describe(' (entry point)', () => { it('should export a Component.', () => { diff --git a/packages/react-ui-components/src/Headline/index.story.js b/packages/react-ui-components/src/Headline/index.story.js index 225db9f450..7e305052e3 100644 --- a/packages/react-ui-components/src/Headline/index.story.js +++ b/packages/react-ui-components/src/Headline/index.story.js @@ -1,8 +1,8 @@ import React from 'react'; import {storiesOf} from '@storybook/react'; import {withKnobs, select} from '@storybook/addon-knobs'; -import {StoryWrapper} from './../_lib/storyUtils.js'; -import Headline from './index.js'; +import {StoryWrapper} from './../_lib/storyUtils'; +import Headline from '.'; storiesOf('Headline', module) .addDecorator(withKnobs) diff --git a/packages/react-ui-components/src/Icon/icon.js b/packages/react-ui-components/src/Icon/icon.js deleted file mode 100644 index 19ed8b0493..0000000000 --- a/packages/react-ui-components/src/Icon/icon.js +++ /dev/null @@ -1,90 +0,0 @@ -import React, {PureComponent} from 'react'; -import PropTypes from 'prop-types'; -import mergeClassNames from 'classnames'; -import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; -import mapper from './mapper'; - -class Icon extends PureComponent { - static propTypes = { - - /** - * We use the react component FortAwesome provides to render icons. - * we will pass down all props to the component via {...rest} to expose it's api - * https://github.com/FortAwesome/react-fontawesome/blob/master/README.md - */ - - /** - * The ID of the icon to render. - */ - icon: PropTypes.string.isRequired, - - /** - * The (accessibility) label for this icon - */ - label: PropTypes.string, - - /** - * Controls the padding around the icon in a standardized way. - */ - padded: PropTypes.oneOf(['none', 'left', 'right']), - - /** - * An optional `className` to attach to the wrapper. - */ - className: PropTypes.string, - - /** - * Adjust the color of the icon - */ - color: PropTypes.oneOf(['default', 'warn', 'error', 'primaryBlue']), - - /** - * An optional css theme to be injected. - */ - theme: PropTypes.shape({ - icon: PropTypes.string, - 'icon--big': PropTypes.string, - 'icon--small': PropTypes.string, - 'icon--tiny': PropTypes.string, - 'icon--paddedLeft': PropTypes.string, - 'icon--paddedRight': PropTypes.string, - 'icon--spin': PropTypes.string - }).isRequired - }; - - render() { - const {padded, theme, label, icon, className, color, ...rest} = this.props; - if (!icon || typeof icon !== 'string') { - return null; - } - const iconClassName = icon; - const classNames = mergeClassNames({ - [theme.icon]: true, - [iconClassName]: true, - [className]: className && className.length, - [theme['icon--paddedLeft']]: padded === 'left', - [theme['icon--paddedRight']]: padded === 'right', - [theme['icon--color-warn']]: color === 'warn', - [theme['icon--color-error']]: color === 'error', - [theme['icon--color-primaryBlue']]: color === 'primaryBlue' - }); - - const mappedIcon = mapper(icon); - const iconArray = mappedIcon.split(' '); - let processedIcon = mappedIcon; - let prefix = 'fas'; - if (iconArray.length > 1) { - prefix = iconArray[0]; - const iconClass = iconArray[1]; - if (iconClass.startsWith('fa-')) { - processedIcon = iconClass.substr(3); - } else { - processedIcon = iconClass; - } - } - - return ; - } -} - -export default Icon; diff --git a/packages/react-ui-components/src/Icon/icon.spec.js b/packages/react-ui-components/src/Icon/icon.spec.js index 9f479e006c..d28300800a 100644 --- a/packages/react-ui-components/src/Icon/icon.spec.js +++ b/packages/react-ui-components/src/Icon/icon.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import Icon from './icon.js'; +import Icon from './icon'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/Icon/icon.tsx b/packages/react-ui-components/src/Icon/icon.tsx new file mode 100644 index 0000000000..af46b0df51 --- /dev/null +++ b/packages/react-ui-components/src/Icon/icon.tsx @@ -0,0 +1,106 @@ +import {IconName, IconPrefix, IconProp} from '@fortawesome/fontawesome-svg-core'; +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; +import mergeClassNames from 'classnames'; +import React, {PureComponent} from 'react'; + +import {PickDefaultProps} from '../../types'; +import mapper from './mapper'; + +type IconPadding = 'none' | 'left' | 'right'; +type IconColor = 'default' | 'warn' | 'error' | 'primaryBlue'; + +interface IconTheme { + readonly icon: string; + readonly 'icon--big': string; + readonly 'icon--small': string; + readonly 'icon--tiny': string; + readonly 'icon--paddedLeft': string; + readonly 'icon--paddedRight': string; + readonly 'icon--spin': string; + readonly 'icon--color-warn': string; + readonly 'icon--color-error': string; + readonly 'icon--color-primaryBlue': string; +} + +export interface IconProps { + /** + * We use the react component FortAwesome provides to render icons. + * we will pass down all props to the component via {...rest} to expose it's api + * https://github.com/FortAwesome/react-fontawesome/blob/master/README.md + */ + + /** + * The ID of the icon to render. + */ + readonly icon: string; + + /** + * The (accessibility) label for this icon + */ + readonly label?: string; + + /** + * Controls the padding around the icon in a standardized way. + */ + readonly padded?: IconPadding; + + /** + * An optional `className` to attach to the wrapper. + */ + readonly className?: string; + + /** + * Adjust the color of the icon + */ + readonly color?: IconColor; + + /** + * An optional css theme to be injected. + */ + readonly theme?: IconTheme; +} + +type DefaultProps = PickDefaultProps; + +const defaultProps: DefaultProps = { + color: 'default', + padded: 'none' +}; + +class Icon extends PureComponent { + public static readonly defaultProps = defaultProps; + + public render(): JSX.Element | null { + const {padded, theme, label, icon, className, color, ...rest} = this.props; + const iconClassName = icon; + const classNames = mergeClassNames( + theme!.icon, + iconClassName, + className, + { + [theme!['icon--paddedLeft']]: padded === 'left', + [theme!['icon--paddedRight']]: padded === 'right', + [theme!['icon--color-warn']]: color === 'warn', + [theme!['icon--color-error']]: color === 'error', + [theme!['icon--color-primaryBlue']]: color === 'primaryBlue', + } + ); + + return ; + } + + private readonly getIconProp = (icon: string): IconProp => { + const mappedIcon = mapper(icon); + const iconArray = mappedIcon.split(' '); + if (iconArray.length > 1) { + const prefix = iconArray[0]; + const processedIcon = iconArray[1].startsWith('fa-') ? iconArray[1].substr(3) : iconArray[1]; + return [prefix as IconPrefix, processedIcon as IconName]; + } else { + const prefix: IconPrefix = 'fas'; + return [prefix, mappedIcon as IconName]; + } + } +} + +export default Icon; diff --git a/packages/react-ui-components/src/Icon/index.js b/packages/react-ui-components/src/Icon/index.js index 1f87ea01ac..f61b3ac356 100644 --- a/packages/react-ui-components/src/Icon/index.js +++ b/packages/react-ui-components/src/Icon/index.js @@ -3,9 +3,9 @@ import {fab} from '@fortawesome/free-brands-svg-icons'; import {fas} from '@fortawesome/free-solid-svg-icons'; import {far} from '@fortawesome/free-regular-svg-icons'; import {themr} from '@friendsofreactjs/react-css-themr'; -import identifiers from './../identifiers'; +import identifiers from '../identifiers'; import style from './style.css'; -import Icon from './icon.js'; +import Icon from './icon'; /* eslint-disable no-unused-vars */ import faStyle from '@fortawesome/fontawesome-svg-core/styles.css'; /* eslint-enable no-unused-vars */ diff --git a/packages/react-ui-components/src/Icon/index.spec.js b/packages/react-ui-components/src/Icon/index.spec.js index 84fcc7700f..aca865c2d7 100644 --- a/packages/react-ui-components/src/Icon/index.spec.js +++ b/packages/react-ui-components/src/Icon/index.spec.js @@ -1,4 +1,4 @@ -import Icon from './index.js'; +import Icon from '.'; describe(' (entry point)', () => { it('should export a Component.', () => { diff --git a/packages/react-ui-components/src/Icon/index.story.js b/packages/react-ui-components/src/Icon/index.story.js index 85efa1194a..15652c3efa 100644 --- a/packages/react-ui-components/src/Icon/index.story.js +++ b/packages/react-ui-components/src/Icon/index.story.js @@ -1,8 +1,8 @@ import React from 'react'; import {storiesOf} from '@storybook/react'; import {withKnobs, boolean, text, select} from '@storybook/addon-knobs'; -import {StoryWrapper} from './../_lib/storyUtils.js'; -import Icon from './index.js'; +import {StoryWrapper} from './../_lib/storyUtils'; +import Icon from '.'; storiesOf('Icon', module) .addDecorator(withKnobs) diff --git a/packages/react-ui-components/src/Icon/mapper.js b/packages/react-ui-components/src/Icon/mapper.js deleted file mode 100644 index 5902ddc496..0000000000 --- a/packages/react-ui-components/src/Icon/mapper.js +++ /dev/null @@ -1,711 +0,0 @@ -/** - * Simple mapper from Neos Icon names to Fontawesome 5 icon classes. - */ -const mapper = icon => { - const map = { - 'address-book-o': 'far fa-address-book', - 'address-card-o': 'far fa-address-card', - 'area-chart': 'fas fa-chart-area', - 'arrow-circle-o-down': 'far fa-arrow-alt-circle-down', - 'arrow-circle-o-left': 'far fa-arrow-alt-circle-left', - 'arrow-circle-o-right': 'far fa-arrow-alt-circle-right', - 'arrow-circle-o-up': 'far fa-arrow-alt-circle-up', - 'arrows-alt': 'fas fa-expand-arrows-alt', - 'arrows-h': 'fas fa-arrows-alt-h', - 'arrows-v': 'fas fa-arrows-alt-v', - 'arrows': 'fas fa-arrows-alt', - 'asl-interpreting': 'fas fa-american-sign-language-interpreting', - 'automobile': 'fas fa-car', - 'bank': 'fas fa-university', - 'bar-chart-o': 'far fa-chart-bar', - 'bar-chart': 'far fa-chart-bar', - 'bathtub': 'fas fa-bath', - 'battery-0': 'fas fa-battery-empty', - 'battery-1': 'fas fa-battery-quarter', - 'battery-2': 'fas fa-battery-half', - 'battery-3': 'fas fa-battery-three-quarters', - 'battery-4': 'fas fa-battery-full', - 'battery': 'fas fa-battery-full', - 'bell-o': 'far fa-bell', - 'bell-slash-o': 'far fa-bell-slash', - 'bitbucket-square': 'fab fa-bitbucket', - 'bitcoin': 'fab fa-btc', - 'bookmark-o': 'far fa-bookmark', - 'building-o': 'far fa-building', - 'cab': 'fas fa-taxi', - 'calendar-check-o': 'far fa-calendar-check', - 'calendar-minus-o': 'far fa-calendar-minus', - 'calendar-empty': 'far fa-calendar', - 'calendar-o': 'far fa-calendar', - 'calendar-plus-o': 'far fa-calendar-plus', - 'calendar-times-o': 'far fa-calendar-times', - 'calendar': 'fas fa-calendar-alt', - 'caret-square-o-down': 'far fa-caret-square-down', - 'caret-square-o-left': 'far fa-caret-square-left', - 'caret-square-o-right': 'far fa-caret-square-right', - 'caret-square-o-up': 'far fa-caret-square-up', - 'cc': 'far fa-closed-captioning', - 'chain-broken': 'fas fa-unlink', - 'chain': 'fas fa-link', - 'check-circle-o': 'far fa-check-circle', - 'check-square-o': 'far fa-check-square', - 'circle-o-notch': 'fas fa-circle-notch', - 'circle-o': 'far fa-circle', - 'circle-thin': 'far fa-circle', - 'clock-o': 'far fa-clock', - 'close': 'fas fa-times', - 'cloud-download': 'fas fa-cloud-download-alt', - 'cloud-upload': 'fas fa-cloud-upload-alt', - 'cny': 'fas fa-yen-sign', - 'code-fork': 'fas fa-code-branch', - 'comment-o': 'far fa-comment', - 'commenting-o': 'far fa-comment-alt', - 'commenting': 'fas fa-comment-alt', - 'comments-o': 'far fa-comments', - 'credit-card-alt': 'fas fa-credit-card', - 'cutlery': 'fas fa-utensils', - 'dashboard': 'fas fa-tachometer-alt', - 'deafness': 'fas fa-deaf', - 'dedent': 'fas fa-outdent', - 'diamond': 'far fa-gem', - 'dollar': 'fas fa-dollar-sign', - 'dot-circle-o': 'far fa-dot-circle', - 'drivers-license-o': 'far fa-id-card', - 'drivers-license': 'fas fa-id-card', - 'eercast': 'fab fa-sellcast', - 'envelope-alt': 'far fa-envelope', - 'envelope-o': 'far fa-envelope', - 'envelope-open-o': 'far fa-envelope-open', - 'eur': 'fas fa-euro-sign', - 'euro': 'fas fa-euro-sign', - 'exchange': 'fas fa-exchange-alt', - 'external-link-square': 'fas fa-external-link-square-alt', - 'external-link': 'fas fa-external-link-alt', - 'eyedropper': 'fas fa-eye-dropper', - 'fa': 'fab fa-font-awesome', - 'facebook-f': 'fab fa-facebook-f', - 'facebook-official': 'fab fa-facebook', - 'facebook': 'fab fa-facebook-f', - 'feed': 'fas fa-rss', - 'file-archive-o': 'far fa-file-archive', - 'file-audio-o': 'far fa-file-audio', - 'file-code-o': 'far fa-file-code', - 'file-excel-o': 'far fa-file-excel', - 'file-image-o': 'far fa-file-image', - 'file-movie-o': 'far fa-file-video', - 'file-o': 'far fa-file', - 'file-pdf-o': 'far fa-file-pdf', - 'file-photo-o': 'far fa-file-image', - 'file-picture-o': 'far fa-file-image', - 'file-powerpoint-o': 'far fa-file-powerpoint', - 'file-sound-o': 'far fa-file-audio', - 'file-text-o': 'far fa-file-alt', - 'file-text': 'fas fa-file-alt', - 'file-video-o': 'far fa-file-video', - 'file-word-o': 'far fa-file-word', - 'file-zip-o': 'far fa-file-archive', - 'files-o': 'far fa-copy', - 'flag-alt': 'far fa-flag', - 'flag-o': 'far fa-flag', - 'flash': 'fas fa-bolt', - 'floppy-o': 'far fa-save', - 'folder-o': 'far fa-folder', - 'folder-open-alt': 'far fa-folder-open', - 'folder-open-o': 'far fa-folder-open', - 'frown-o': 'far fa-frown', - 'futbol-o': 'far fa-futbol', - 'gbp': 'fas fa-pound-sign', - 'ge': 'fab fa-empire', - 'gear': 'fas fa-cog', - 'gears': 'fas fa-cogs', - 'gittip': 'fab fa-gratipay', - 'glass': 'fas fa-glass-martini', - 'google-plus-circle': 'fab fa-google-plus', - 'google-plus-official': 'fab fa-google-plus', - 'google-plus': 'fab fa-google-plus-g', - 'group': 'fas fa-users', - 'hand-grab-o': 'far fa-hand-rock', - 'hand-lizard-o': 'far fa-hand-lizard', - 'hand-o-down': 'far fa-hand-point-down', - 'hand-o-left': 'far fa-hand-point-left', - 'hand-o-right': 'far fa-hand-point-right', - 'hand-o-up': 'far fa-hand-point-up', - 'hand-paper-o': 'far fa-hand-paper', - 'hand-peace-o': 'far fa-hand-peace', - 'hand-pointer-o': 'far fa-hand-pointer', - 'hand-rock-o': 'far fa-hand-rock', - 'hand-scissors-o': 'far fa-hand-scissors', - 'hand-spock-o': 'far fa-hand-spock', - 'hand-stop-o': 'far fa-hand-paper', - 'handshake-o': 'far fa-handshake', - 'hard-of-hearing': 'fas fa-deaf', - 'hdd-o': 'far fa-hdd', - 'header': 'fas fa-heading', - 'heart-o': 'far fa-heart', - 'hospital-o': 'far fa-hospital', - 'hotel': 'fas fa-bed', - 'hourglass-1': 'fas fa-hourglass-start', - 'hourglass-2': 'fas fa-hourglass-half', - 'hourglass-3': 'fas fa-hourglass-end', - 'hourglass-o': 'far fa-hourglass', - 'id-card-o': 'far fa-id-card', - 'ils': 'fas fa-shekel-sign', - 'image': 'far fa-image', - 'inr': 'fas fa-rupee-sign', - 'institution': 'fas fa-university', - 'intersex': 'fas fa-transgender', - 'jpy': 'fas fa-yen-sign', - 'keyboard-o': 'far fa-keyboard', - 'krw': 'fas fa-won-sign', - 'legal': 'fas fa-gavel', - 'lemon-o': 'far fa-lemon', - 'level-down': 'fas fa-level-down-alt', - 'level-up': 'fas fa-level-up-alt', - 'life-bouy': 'far fa-life-ring', - 'life-buoy': 'far fa-life-ring', - 'life-saver': 'far fa-life-ring', - 'lightbulb-o': 'far fa-lightbulb', - 'line-chart': 'fas fa-chart-line', - 'linkedin-square': 'fab fa-linkedin', - 'linkedin': 'fab fa-linkedin-in', - 'long-arrow-down': 'fas fa-long-arrow-alt-down', - 'long-arrow-left': 'fas fa-long-arrow-alt-left', - 'long-arrow-right': 'fas fa-long-arrow-alt-right', - 'long-arrow-up': 'fas fa-long-arrow-alt-up', - 'mail-forward': 'fas fa-share', - 'mail-reply-all': 'fas fa-reply-all', - 'mail-reply': 'fas fa-reply', - 'map-marker': 'fas fa-map-marker-alt', - 'map-o': 'far fa-map', - 'meanpath': 'fab fa-font-awesome', - 'meh-o': 'far fa-meh', - 'minus-square-o': 'far fa-minus-square', - 'mobile-phone': 'fas fa-mobile-alt', - 'mobile': 'fas fa-mobile-alt', - 'money': 'far fa-money-bill-alt', - 'moon-o': 'far fa-moon', - 'mortar-board': 'fas fa-graduation-cap', - 'navicon': 'fas fa-bars', - 'newspaper-o': 'far fa-newspaper', - 'paper-plane-o': 'far fa-paper-plane', - 'paste': 'far fa-clipboard', - 'pause-circle-o': 'far fa-pause-circle', - 'pencil-square-o': 'far fa-edit', - 'pencil-square': 'fas fa-pen-square', - 'pencil': 'fas fa-pencil-alt', - 'photo': 'far fa-image', - 'picture-o': 'far fa-image', - 'pie-chart': 'fas fa-chart-pie', - 'play-circle-o': 'far fa-play-circle', - 'plus-square-o': 'far fa-plus-square', - 'question-circle-o': 'far fa-question-circle', - 'ra': 'fab fa-rebel', - 'refresh': 'fas fa-sync', - 'remove': 'fas fa-times', - 'remove-sign': 'fas fa-ban', - 'reorder': 'fas fa-bars', - 'repeat': 'fas fa-redo', - 'resistance': 'fab fa-rebel', - 'rmb': 'fas fa-yen-sign', - 'rotate-left': 'fas fa-undo', - 'rotate-right': 'fas fa-redo', - 'rouble': 'fas fa-ruble-sign', - 'rub': 'fas fa-ruble-sign', - 'ruble': 'fas fa-ruble-sign', - 'rupee': 'fas fa-rupee-sign', - 's15': 'fas fa-bath', - 'scissors': 'fas fa-cut', - 'send-o': 'far fa-paper-plane', - 'send': 'fas fa-paper-plane', - 'share-square-o': 'far fa-share-square', - 'shekel': 'fas fa-shekel-sign', - 'sheqel': 'fas fa-shekel-sign', - 'shield': 'fas fa-shield-alt', - 'sign-in': 'fas fa-sign-in-alt', - 'sign-out': 'fas fa-sign-out-alt', - 'signing': 'fas fa-sign-language', - 'sliders': 'fas fa-sliders-h', - 'smile-o': 'far fa-smile', - 'snowflake-o': 'far fa-snowflake', - 'soccer-ball-o': 'far fa-futbol', - 'sort-alpha-asc': 'fas fa-sort-alpha-down', - 'sort-alpha-desc': 'fas fa-sort-alpha-up', - 'sort-amount-asc': 'fas fa-sort-amount-down', - 'sort-amount-desc': 'fas fa-sort-amount-up', - 'sort-asc': 'fas fa-sort-up', - 'sort-desc': 'fas fa-sort-down', - 'sort-numeric-asc': 'fas fa-sort-numeric-down', - 'sort-numeric-desc': 'fas fa-sort-numeric-up', - 'spoon': 'fas fa-utensil-spoon', - 'square-o': 'far fa-square', - 'star-half-empty': 'far fa-star-half', - 'star-half-full': 'far fa-star-half', - 'star-half-o': 'far fa-star-half', - 'star-o': 'far fa-star', - 'sticky-note-o': 'far fa-sticky-note', - 'stop-circle-o': 'far fa-stop-circle', - 'sun-o': 'far fa-sun', - 'support': 'far fa-life-ring', - 'tablet': 'fas fa-tablet-alt', - 'tachometer': 'fas fa-tachometer-alt', - 'television': 'fas fa-tv', - 'thermometer-0': 'fas fa-thermometer-empty', - 'thermometer-1': 'fas fa-thermometer-quarter', - 'thermometer-2': 'fas fa-thermometer-half', - 'thermometer-3': 'fas fa-thermometer-three-quarters', - 'thermometer-4': 'fas fa-thermometer-full', - 'thermometer': 'fas fa-thermometer-full', - 'thumb-tack': 'fas fa-thumbtack', - 'thumbs-o-down': 'far fa-thumbs-down', - 'thumbs-o-up': 'far fa-thumbs-up', - 'ticket': 'fas fa-ticket-alt', - 'times-circle-o': 'far fa-times-circle', - 'times-rectangle-o': 'far fa-window-close', - 'times-rectangle': 'fas fa-window-close', - 'toggle-down': 'far fa-caret-square-down', - 'toggle-left': 'far fa-caret-square-left', - 'toggle-right': 'far fa-caret-square-right', - 'toggle-up': 'far fa-caret-square-up', - 'trash-o': 'far fa-trash-alt', - 'trash': 'fas fa-trash-alt', - 'try': 'fas fa-lira-sign', - 'turkish-lira': 'fas fa-lira-sign', - 'unsorted': 'fas fa-sort', - 'upload-alt': 'fas fa-upload', - 'usd': 'fas fa-dollar-sign', - 'user-circle-o': 'far fa-user-circle', - 'user-o': 'far fa-user', - 'vcard-o': 'far fa-address-card', - 'vcard': 'fas fa-address-card', - 'video-camera': 'fas fa-video', - 'vimeo': 'fab fa-vimeo-v', - 'volume-control-phone': 'fas fa-phone-volume', - 'warning': 'fas fa-exclamation-triangle', - 'wechat': 'fab fa-weixin', - 'wheelchair-alt': 'fab fa-accessible-icon', - 'window-close-o': 'far fa-window-close', - 'won': 'fas fa-won-sign', - 'y-combinator-square': 'fab fa-hacker-news', - 'yc-square': 'fab fa-hacker-news', - 'yc': 'fab fa-y-combinator', - 'yen': 'fas fa-yen-sign', - 'youtube-play': 'fab fa-youtube', - 'youtube-square': 'fab fa-youtube', - 'picture': 'far fa-image', - 'copy': 'far fa-copy' - }; - - // all Icons from: - // https://github.com/FortAwesome/Font-Awesome/blob/master/svg-with-js/js/fa-brands.js#L118 - const brands = [ - '500px', - 'accessible-icon', - 'accusoft', - 'adn', - 'adversal', - 'affiliatetheme', - 'algolia', - 'amazon', - 'amazon-pay', - 'amilia', - 'android', - 'angellist', - 'angrycreative', - 'angular', - 'app-store', - 'app-store-ios', - 'apper', - 'apple', - 'apple-pay', - 'asymmetrik', - 'audible', - 'autoprefixer', - 'avianex', - 'aviato', - 'aws', - 'bandcamp', - 'behance', - 'behance-square', - 'bimobject', - 'bitbucket', - 'bitcoin', - 'bity', - 'black-tie', - 'blackberry', - 'blogger', - 'blogger-b', - 'bluetooth', - 'bluetooth-b', - 'btc', - 'buromobelexperte', - 'buysellads', - 'cc-amazon-pay', - 'cc-amex', - 'cc-apple-pay', - 'cc-diners-club', - 'cc-discover', - 'cc-jcb', - 'cc-mastercard', - 'cc-paypal', - 'cc-stripe', - 'cc-visa', - 'centercode', - 'chrome', - 'cloudscale', - 'cloudsmith', - 'cloudversify', - 'codepen', - 'codiepie', - 'connectdevelop', - 'contao', - 'cpanel', - 'creative-commons', - 'creative-commons-by', - 'creative-commons-nc', - 'creative-commons-nc-eu', - 'creative-commons-nc-jp', - 'creative-commons-nd', - 'creative-commons-pd', - 'creative-commons-pd-alt', - 'creative-commons-remix', - 'creative-commons-sa', - 'creative-commons-sampling', - 'creative-commons-sampling-plus', - 'creative-commons-share', - 'css3', - 'css3-alt', - 'cuttlefish', - 'd-and-d', - 'dashcube', - 'delicious', - 'deploydog', - 'deskpro', - 'deviantart', - 'digg', - 'digital-ocean', - 'discord', - 'discourse', - 'dochub', - 'docker', - 'draft2digital', - 'dribbble', - 'dribbble-square', - 'dropbox', - 'drupal', - 'dyalog', - 'earlybirds', - 'ebay', - 'edge', - 'elementor', - 'ello', - 'ember', - 'empire', - 'envira', - 'erlang', - 'ethereum', - 'etsy', - 'expeditedssl', - 'facebook', - 'facebook-f', - 'facebook-messenger', - 'facebook-square', - 'firefox', - 'first-order', - 'first-order-alt', - 'firstdraft', - 'flickr', - 'flipboard', - 'fly', - 'font-awesome', - 'font-awesome-alt', - 'font-awesome-flag', - 'font-awesome-logo-full', - 'fonticons', - 'fonticons-fi', - 'fort-awesome', - 'fort-awesome-alt', - 'forumbee', - 'foursquare', - 'free-code-camp', - 'freebsd', - 'fulcrum', - 'galactic-republic', - 'galactic-senate', - 'get-pocket', - 'gg', - 'gg-circle', - 'git', - 'git-square', - 'github', - 'github-alt', - 'github-square', - 'gitkraken', - 'gitlab', - 'gitter', - 'glide', - 'glide-g', - 'gofore', - 'goodreads', - 'goodreads-g', - 'google', - 'google-drive', - 'google-play', - 'google-plus', - 'google-plus-g', - 'google-plus-square', - 'google-wallet', - 'gratipay', - 'grav', - 'gripfire', - 'grunt', - 'gulp', - 'hacker-news', - 'hacker-news-square', - 'hackerrank', - 'hips', - 'hire-a-helper', - 'hooli', - 'hornbill', - 'hotjar', - 'houzz', - 'html5', - 'hubspot', - 'imdb', - 'instagram', - 'internet-explorer', - 'ioxhost', - 'itunes', - 'itunes-note', - 'java', - 'jedi-order', - 'jenkins', - 'joget', - 'joomla', - 'js', - 'js-square', - 'jsfiddle', - 'kaggle', - 'keybase', - 'keycdn', - 'kickstarter', - 'kickstarter-k', - 'korvue', - 'laravel', - 'lastfm', - 'lastfm-square', - 'leanpub', - 'less', - 'line', - 'linkedin', - 'linkedin-in', - 'linode', - 'linux', - 'lyft', - 'magento', - 'mailchimp', - 'mandalorian', - 'markdown', - 'mastodon', - 'maxcdn', - 'medapps', - 'medium', - 'medium-m', - 'medrt', - 'meetup', - 'megaport', - 'microsoft', - 'mix', - 'mixcloud', - 'mizuni', - 'modx', - 'monero', - 'napster', - 'neos', - 'nimblr', - 'nintendo-switch', - 'node', - 'node-js', - 'npm', - 'ns8', - 'nutritionix', - 'odnoklassniki', - 'odnoklassniki-square', - 'old-republic', - 'opencart', - 'openid', - 'opera', - 'optin-monster', - 'osi', - 'page4', - 'pagelines', - 'palfed', - 'patreon', - 'paypal', - 'periscope', - 'phabricator', - 'phoenix-framework', - 'phoenix-squadron', - 'php', - 'pied-piper', - 'pied-piper-alt', - 'pied-piper-hat', - 'pied-piper-pp', - 'pinterest', - 'pinterest-p', - 'pinterest-square', - 'playstation', - 'product-hunt', - 'pushed', - 'python', - 'qq', - 'quinscape', - 'quora', - 'r-project', - 'ravelry', - 'react', - 'readme', - 'rebel', - 'red-river', - 'reddit', - 'reddit-alien', - 'reddit-square', - 'rendact', - 'renren', - 'replyd', - 'researchgate', - 'resolving', - 'rev', - 'rocketchat', - 'rockrms', - 'safari', - 'sass', - 'schlix', - 'scribd', - 'searchengin', - 'sellcast', - 'sellsy', - 'servicestack', - 'shirtsinbulk', - 'shopware', - 'simplybuilt', - 'sistrix', - 'sith', - 'skyatlas', - 'skype', - 'slack', - 'slack-hash', - 'slideshare', - 'snapchat', - 'snapchat-ghost', - 'snapchat-square', - 'soundcloud', - 'speakap', - 'spotify', - 'squarespace', - 'stack-exchange', - 'stack-overflow', - 'staylinked', - 'steam', - 'steam-square', - 'steam-symbol', - 'sticker-mule', - 'strava', - 'stripe', - 'stripe-s', - 'studiovinari', - 'stumbleupon', - 'stumbleupon-circle', - 'superpowers', - 'supple', - 'teamspeak', - 'telegram', - 'telegram-plane', - 'tencent-weibo', - 'themeco', - 'themeisle', - 'trade-federation', - 'trello', - 'tripadvisor', - 'tumblr', - 'tumblr-square', - 'twitch', - 'twitter', - 'twitter-square', - 'typo3', - 'uber', - 'uikit', - 'uniregistry', - 'untappd', - 'usb', - 'ussunnah', - 'vaadin', - 'viacoin', - 'viadeo', - 'viadeo-square', - 'viber', - 'vimeo', - 'vimeo-square', - 'vimeo-v', - 'vine', - 'vk', - 'vnv', - 'vuejs', - 'weebly', - 'weibo', - 'weixin', - 'whatsapp', - 'whatsapp-square', - 'whmcs', - 'wikipedia-w', - 'windows', - 'wix', - 'wolf-pack-battalion', - 'wordpress', - 'wordpress-simple', - 'wpbeginner', - 'wpexplorer', - 'wpforms', - 'xbox', - 'xing', - 'xing-square', - 'y-combinator', - 'yahoo', - 'yandex', - 'yandex-international', - 'yelp', - 'yoast', - 'youtube', - 'youtube-square', - 'zhihu' - ]; - - /** - * Neos <= 3.3 prefixed icons with this, we need to strip those - * otherwise the mapping would'nt work for brand icons - */ - if (icon.startsWith('fas fa-')) { - icon = icon.substr(7).split(' ')[0]; - } - - if (icon.startsWith('icon-')) { - icon = icon.substr(5).split(' ')[0]; - } - - icon = icon.trim(); - - if (map[icon]) { - return map[icon]; - } - - if (brands.includes(icon)) { - return 'fab fa-' + icon; - } - - if (!icon.includes(' ')) { - return 'fas fa-' + icon; - } - - return icon; -}; - -export default mapper; diff --git a/packages/react-ui-components/src/Icon/mapper.ts b/packages/react-ui-components/src/Icon/mapper.ts new file mode 100644 index 0000000000..b9d9a83ca2 --- /dev/null +++ b/packages/react-ui-components/src/Icon/mapper.ts @@ -0,0 +1,717 @@ +/** + * Simple mapper from Neos Icon names to Fontawesome 5 icon classes. + */ +// TODO: create type for this, so we can have autocompletion +// alternatively just use IconName or even better IconLookup (has IconPrefix & IconName) of FontAwesome typings +const map: {readonly [key: string]: string} = { + 'address-book-o': 'far fa-address-book', + 'address-card-o': 'far fa-address-card', + 'area-chart': 'fas fa-chart-area', + 'arrow-circle-o-down': 'far fa-arrow-alt-circle-down', + 'arrow-circle-o-left': 'far fa-arrow-alt-circle-left', + 'arrow-circle-o-right': 'far fa-arrow-alt-circle-right', + 'arrow-circle-o-up': 'far fa-arrow-alt-circle-up', + 'arrows': 'fas fa-arrows-alt', + 'arrows-alt': 'fas fa-expand-arrows-alt', + 'arrows-h': 'fas fa-arrows-alt-h', + 'arrows-v': 'fas fa-arrows-alt-v', + 'asl-interpreting': 'fas fa-american-sign-language-interpreting', + 'automobile': 'fas fa-car', + 'bank': 'fas fa-university', + 'bar-chart': 'far fa-chart-bar', + 'bar-chart-o': 'far fa-chart-bar', + 'bathtub': 'fas fa-bath', + 'battery': 'fas fa-battery-full', + 'battery-0': 'fas fa-battery-empty', + 'battery-1': 'fas fa-battery-quarter', + 'battery-2': 'fas fa-battery-half', + 'battery-3': 'fas fa-battery-three-quarters', + 'battery-4': 'fas fa-battery-full', + 'bell-o': 'far fa-bell', + 'bell-slash-o': 'far fa-bell-slash', + 'bitbucket-square': 'fab fa-bitbucket', + 'bitcoin': 'fab fa-btc', + 'bookmark-o': 'far fa-bookmark', + 'building-o': 'far fa-building', + 'cab': 'fas fa-taxi', + 'calendar': 'fas fa-calendar-alt', + 'calendar-check-o': 'far fa-calendar-check', + 'calendar-empty': 'far fa-calendar', + 'calendar-minus-o': 'far fa-calendar-minus', + 'calendar-o': 'far fa-calendar', + 'calendar-plus-o': 'far fa-calendar-plus', + 'calendar-times-o': 'far fa-calendar-times', + 'caret-square-o-down': 'far fa-caret-square-down', + 'caret-square-o-left': 'far fa-caret-square-left', + 'caret-square-o-right': 'far fa-caret-square-right', + 'caret-square-o-up': 'far fa-caret-square-up', + 'cc': 'far fa-closed-captioning', + 'chain': 'fas fa-link', + 'chain-broken': 'fas fa-unlink', + 'check-circle-o': 'far fa-check-circle', + 'check-square-o': 'far fa-check-square', + 'circle-o': 'far fa-circle', + 'circle-o-notch': 'fas fa-circle-notch', + 'circle-thin': 'far fa-circle', + 'clock-o': 'far fa-clock', + 'close': 'fas fa-times', + 'cloud-download': 'fas fa-cloud-download-alt', + 'cloud-upload': 'fas fa-cloud-upload-alt', + 'cny': 'fas fa-yen-sign', + 'code-fork': 'fas fa-code-branch', + 'comment-o': 'far fa-comment', + 'commenting': 'fas fa-comment-alt', + 'commenting-o': 'far fa-comment-alt', + 'comments-o': 'far fa-comments', + 'copy': 'far fa-copy', + 'credit-card-alt': 'fas fa-credit-card', + 'cutlery': 'fas fa-utensils', + 'dashboard': 'fas fa-tachometer-alt', + 'deafness': 'fas fa-deaf', + 'dedent': 'fas fa-outdent', + 'diamond': 'far fa-gem', + 'dollar': 'fas fa-dollar-sign', + 'dot-circle-o': 'far fa-dot-circle', + 'drivers-license': 'fas fa-id-card', + 'drivers-license-o': 'far fa-id-card', + 'eercast': 'fab fa-sellcast', + 'envelope-alt': 'far fa-envelope', + 'envelope-o': 'far fa-envelope', + 'envelope-open-o': 'far fa-envelope-open', + 'eur': 'fas fa-euro-sign', + 'euro': 'fas fa-euro-sign', + 'exchange': 'fas fa-exchange-alt', + 'external-link': 'fas fa-external-link-alt', + 'external-link-square': 'fas fa-external-link-square-alt', + 'eyedropper': 'fas fa-eye-dropper', + 'fa': 'fab fa-font-awesome', + 'facebook': 'fab fa-facebook-f', + 'facebook-f': 'fab fa-facebook-f', + 'facebook-official': 'fab fa-facebook', + 'feed': 'fas fa-rss', + 'file-archive-o': 'far fa-file-archive', + 'file-audio-o': 'far fa-file-audio', + 'file-code-o': 'far fa-file-code', + 'file-excel-o': 'far fa-file-excel', + 'file-image-o': 'far fa-file-image', + 'file-movie-o': 'far fa-file-video', + 'file-o': 'far fa-file', + 'file-pdf-o': 'far fa-file-pdf', + 'file-photo-o': 'far fa-file-image', + 'file-picture-o': 'far fa-file-image', + 'file-powerpoint-o': 'far fa-file-powerpoint', + 'file-sound-o': 'far fa-file-audio', + 'file-text': 'fas fa-file-alt', + 'file-text-o': 'far fa-file-alt', + 'file-video-o': 'far fa-file-video', + 'file-word-o': 'far fa-file-word', + 'file-zip-o': 'far fa-file-archive', + 'files-o': 'far fa-copy', + 'flag-alt': 'far fa-flag', + 'flag-o': 'far fa-flag', + 'flash': 'fas fa-bolt', + 'floppy-o': 'far fa-save', + 'folder-o': 'far fa-folder', + 'folder-open-alt': 'far fa-folder-open', + 'folder-open-o': 'far fa-folder-open', + 'frown-o': 'far fa-frown', + 'futbol-o': 'far fa-futbol', + 'gbp': 'fas fa-pound-sign', + 'ge': 'fab fa-empire', + 'gear': 'fas fa-cog', + 'gears': 'fas fa-cogs', + 'gittip': 'fab fa-gratipay', + 'glass': 'fas fa-glass-martini', + 'google-plus': 'fab fa-google-plus-g', + 'google-plus-circle': 'fab fa-google-plus', + 'google-plus-official': 'fab fa-google-plus', + 'group': 'fas fa-users', + 'hand-grab-o': 'far fa-hand-rock', + 'hand-lizard-o': 'far fa-hand-lizard', + 'hand-o-down': 'far fa-hand-point-down', + 'hand-o-left': 'far fa-hand-point-left', + 'hand-o-right': 'far fa-hand-point-right', + 'hand-o-up': 'far fa-hand-point-up', + 'hand-paper-o': 'far fa-hand-paper', + 'hand-peace-o': 'far fa-hand-peace', + 'hand-pointer-o': 'far fa-hand-pointer', + 'hand-rock-o': 'far fa-hand-rock', + 'hand-scissors-o': 'far fa-hand-scissors', + 'hand-spock-o': 'far fa-hand-spock', + 'hand-stop-o': 'far fa-hand-paper', + 'handshake-o': 'far fa-handshake', + 'hard-of-hearing': 'fas fa-deaf', + 'hdd-o': 'far fa-hdd', + 'header': 'fas fa-heading', + 'heart-o': 'far fa-heart', + 'hospital-o': 'far fa-hospital', + 'hotel': 'fas fa-bed', + 'hourglass-1': 'fas fa-hourglass-start', + 'hourglass-2': 'fas fa-hourglass-half', + 'hourglass-3': 'fas fa-hourglass-end', + 'hourglass-o': 'far fa-hourglass', + 'id-card-o': 'far fa-id-card', + 'ils': 'fas fa-shekel-sign', + 'image': 'far fa-image', + 'inr': 'fas fa-rupee-sign', + 'institution': 'fas fa-university', + 'intersex': 'fas fa-transgender', + 'jpy': 'fas fa-yen-sign', + 'keyboard-o': 'far fa-keyboard', + 'krw': 'fas fa-won-sign', + 'legal': 'fas fa-gavel', + 'lemon-o': 'far fa-lemon', + 'level-down': 'fas fa-level-down-alt', + 'level-up': 'fas fa-level-up-alt', + 'life-bouy': 'far fa-life-ring', + 'life-buoy': 'far fa-life-ring', + 'life-saver': 'far fa-life-ring', + 'lightbulb-o': 'far fa-lightbulb', + 'line-chart': 'fas fa-chart-line', + 'linkedin': 'fab fa-linkedin-in', + 'linkedin-square': 'fab fa-linkedin', + 'long-arrow-down': 'fas fa-long-arrow-alt-down', + 'long-arrow-left': 'fas fa-long-arrow-alt-left', + 'long-arrow-right': 'fas fa-long-arrow-alt-right', + 'long-arrow-up': 'fas fa-long-arrow-alt-up', + 'mail-forward': 'fas fa-share', + 'mail-reply': 'fas fa-reply', + 'mail-reply-all': 'fas fa-reply-all', + 'map-marker': 'fas fa-map-marker-alt', + 'map-o': 'far fa-map', + 'meanpath': 'fab fa-font-awesome', + 'meh-o': 'far fa-meh', + 'minus-square-o': 'far fa-minus-square', + 'mobile': 'fas fa-mobile-alt', + 'mobile-phone': 'fas fa-mobile-alt', + 'money': 'far fa-money-bill-alt', + 'moon-o': 'far fa-moon', + 'mortar-board': 'fas fa-graduation-cap', + 'navicon': 'fas fa-bars', + 'newspaper-o': 'far fa-newspaper', + 'paper-plane-o': 'far fa-paper-plane', + 'paste': 'far fa-clipboard', + 'pause-circle-o': 'far fa-pause-circle', + 'pencil': 'fas fa-pencil-alt', + 'pencil-square': 'fas fa-pen-square', + 'pencil-square-o': 'far fa-edit', + 'photo': 'far fa-image', + 'picture': 'far fa-image', + 'picture-o': 'far fa-image', + 'pie-chart': 'fas fa-chart-pie', + 'play-circle-o': 'far fa-play-circle', + 'plus-square-o': 'far fa-plus-square', + 'question-circle-o': 'far fa-question-circle', + 'ra': 'fab fa-rebel', + 'refresh': 'fas fa-sync', + 'remove': 'fas fa-times', + 'remove-sign': 'fas fa-ban', + 'reorder': 'fas fa-bars', + 'repeat': 'fas fa-redo', + 'resistance': 'fab fa-rebel', + 'rmb': 'fas fa-yen-sign', + 'rotate-left': 'fas fa-undo', + 'rotate-right': 'fas fa-redo', + 'rouble': 'fas fa-ruble-sign', + 'rub': 'fas fa-ruble-sign', + 'ruble': 'fas fa-ruble-sign', + 'rupee': 'fas fa-rupee-sign', + 's15': 'fas fa-bath', + 'scissors': 'fas fa-cut', + 'send': 'fas fa-paper-plane', + 'send-o': 'far fa-paper-plane', + 'share-square-o': 'far fa-share-square', + 'shekel': 'fas fa-shekel-sign', + 'sheqel': 'fas fa-shekel-sign', + 'shield': 'fas fa-shield-alt', + 'sign-in': 'fas fa-sign-in-alt', + 'sign-out': 'fas fa-sign-out-alt', + 'signing': 'fas fa-sign-language', + 'sliders': 'fas fa-sliders-h', + 'smile-o': 'far fa-smile', + 'snowflake-o': 'far fa-snowflake', + 'soccer-ball-o': 'far fa-futbol', + 'sort-alpha-asc': 'fas fa-sort-alpha-down', + 'sort-alpha-desc': 'fas fa-sort-alpha-up', + 'sort-amount-asc': 'fas fa-sort-amount-down', + 'sort-amount-desc': 'fas fa-sort-amount-up', + 'sort-asc': 'fas fa-sort-up', + 'sort-desc': 'fas fa-sort-down', + 'sort-numeric-asc': 'fas fa-sort-numeric-down', + 'sort-numeric-desc': 'fas fa-sort-numeric-up', + 'spoon': 'fas fa-utensil-spoon', + 'square-o': 'far fa-square', + 'star-half-empty': 'far fa-star-half', + 'star-half-full': 'far fa-star-half', + 'star-half-o': 'far fa-star-half', + 'star-o': 'far fa-star', + 'sticky-note-o': 'far fa-sticky-note', + 'stop-circle-o': 'far fa-stop-circle', + 'sun-o': 'far fa-sun', + 'support': 'far fa-life-ring', + 'tablet': 'fas fa-tablet-alt', + 'tachometer': 'fas fa-tachometer-alt', + 'television': 'fas fa-tv', + 'thermometer': 'fas fa-thermometer-full', + 'thermometer-0': 'fas fa-thermometer-empty', + 'thermometer-1': 'fas fa-thermometer-quarter', + 'thermometer-2': 'fas fa-thermometer-half', + 'thermometer-3': 'fas fa-thermometer-three-quarters', + 'thermometer-4': 'fas fa-thermometer-full', + 'thumb-tack': 'fas fa-thumbtack', + 'thumbs-o-down': 'far fa-thumbs-down', + 'thumbs-o-up': 'far fa-thumbs-up', + 'ticket': 'fas fa-ticket-alt', + 'times-circle-o': 'far fa-times-circle', + 'times-rectangle': 'fas fa-window-close', + 'times-rectangle-o': 'far fa-window-close', + 'toggle-down': 'far fa-caret-square-down', + 'toggle-left': 'far fa-caret-square-left', + 'toggle-right': 'far fa-caret-square-right', + 'toggle-up': 'far fa-caret-square-up', + 'trash': 'fas fa-trash-alt', + 'trash-o': 'far fa-trash-alt', + 'try': 'fas fa-lira-sign', + 'turkish-lira': 'fas fa-lira-sign', + 'unsorted': 'fas fa-sort', + 'upload-alt': 'fas fa-upload', + 'usd': 'fas fa-dollar-sign', + 'user-circle-o': 'far fa-user-circle', + 'user-o': 'far fa-user', + 'vcard': 'fas fa-address-card', + 'vcard-o': 'far fa-address-card', + 'video-camera': 'fas fa-video', + 'vimeo': 'fab fa-vimeo-v', + 'volume-control-phone': 'fas fa-phone-volume', + 'warning': 'fas fa-exclamation-triangle', + 'wechat': 'fab fa-weixin', + 'wheelchair-alt': 'fab fa-accessible-icon', + 'window-close-o': 'far fa-window-close', + 'won': 'fas fa-won-sign', + 'y-combinator-square': 'fab fa-hacker-news', + 'yc': 'fab fa-y-combinator', + 'yc-square': 'fab fa-hacker-news', + 'yen': 'fas fa-yen-sign', + 'youtube-play': 'fab fa-youtube', + 'youtube-square': 'fab fa-youtube', +}; + +// all Icons from: +// https://github.com/FortAwesome/Font-Awesome/blob/master/svg-with-js/js/fa-brands.js#L118 +const brands: ReadonlyArray = [ + '500px', + 'accessible-icon', + 'accusoft', + 'adn', + 'adversal', + 'affiliatetheme', + 'algolia', + 'amazon', + 'amazon-pay', + 'amilia', + 'android', + 'angellist', + 'angrycreative', + 'angular', + 'app-store', + 'app-store-ios', + 'apper', + 'apple', + 'apple-pay', + 'asymmetrik', + 'audible', + 'autoprefixer', + 'avianex', + 'aviato', + 'aws', + 'bandcamp', + 'behance', + 'behance-square', + 'bimobject', + 'bitbucket', + 'bitcoin', + 'bity', + 'black-tie', + 'blackberry', + 'blogger', + 'blogger-b', + 'bluetooth', + 'bluetooth-b', + 'btc', + 'buromobelexperte', + 'buysellads', + 'cc-amazon-pay', + 'cc-amex', + 'cc-apple-pay', + 'cc-diners-club', + 'cc-discover', + 'cc-jcb', + 'cc-mastercard', + 'cc-paypal', + 'cc-stripe', + 'cc-visa', + 'centercode', + 'chrome', + 'cloudscale', + 'cloudsmith', + 'cloudversify', + 'codepen', + 'codiepie', + 'connectdevelop', + 'contao', + 'cpanel', + 'creative-commons', + 'creative-commons-by', + 'creative-commons-nc', + 'creative-commons-nc-eu', + 'creative-commons-nc-jp', + 'creative-commons-nd', + 'creative-commons-pd', + 'creative-commons-pd-alt', + 'creative-commons-remix', + 'creative-commons-sa', + 'creative-commons-sampling', + 'creative-commons-sampling-plus', + 'creative-commons-share', + 'css3', + 'css3-alt', + 'cuttlefish', + 'd-and-d', + 'dashcube', + 'delicious', + 'deploydog', + 'deskpro', + 'deviantart', + 'digg', + 'digital-ocean', + 'discord', + 'discourse', + 'dochub', + 'docker', + 'draft2digital', + 'dribbble', + 'dribbble-square', + 'dropbox', + 'drupal', + 'dyalog', + 'earlybirds', + 'ebay', + 'edge', + 'elementor', + 'ello', + 'ember', + 'empire', + 'envira', + 'erlang', + 'ethereum', + 'etsy', + 'expeditedssl', + 'facebook', + 'facebook-f', + 'facebook-messenger', + 'facebook-square', + 'firefox', + 'first-order', + 'first-order-alt', + 'firstdraft', + 'flickr', + 'flipboard', + 'fly', + 'font-awesome', + 'font-awesome-alt', + 'font-awesome-flag', + 'font-awesome-logo-full', + 'fonticons', + 'fonticons-fi', + 'fort-awesome', + 'fort-awesome-alt', + 'forumbee', + 'foursquare', + 'free-code-camp', + 'freebsd', + 'fulcrum', + 'galactic-republic', + 'galactic-senate', + 'get-pocket', + 'gg', + 'gg-circle', + 'git', + 'git-square', + 'github', + 'github-alt', + 'github-square', + 'gitkraken', + 'gitlab', + 'gitter', + 'glide', + 'glide-g', + 'gofore', + 'goodreads', + 'goodreads-g', + 'google', + 'google-drive', + 'google-play', + 'google-plus', + 'google-plus-g', + 'google-plus-square', + 'google-wallet', + 'gratipay', + 'grav', + 'gripfire', + 'grunt', + 'gulp', + 'hacker-news', + 'hacker-news-square', + 'hackerrank', + 'hips', + 'hire-a-helper', + 'hooli', + 'hornbill', + 'hotjar', + 'houzz', + 'html5', + 'hubspot', + 'imdb', + 'instagram', + 'internet-explorer', + 'ioxhost', + 'itunes', + 'itunes-note', + 'java', + 'jedi-order', + 'jenkins', + 'joget', + 'joomla', + 'js', + 'js-square', + 'jsfiddle', + 'kaggle', + 'keybase', + 'keycdn', + 'kickstarter', + 'kickstarter-k', + 'korvue', + 'laravel', + 'lastfm', + 'lastfm-square', + 'leanpub', + 'less', + 'line', + 'linkedin', + 'linkedin-in', + 'linode', + 'linux', + 'lyft', + 'magento', + 'mailchimp', + 'mandalorian', + 'markdown', + 'mastodon', + 'maxcdn', + 'medapps', + 'medium', + 'medium-m', + 'medrt', + 'meetup', + 'megaport', + 'microsoft', + 'mix', + 'mixcloud', + 'mizuni', + 'modx', + 'monero', + 'napster', + 'neos', + 'nimblr', + 'nintendo-switch', + 'node', + 'node-js', + 'npm', + 'ns8', + 'nutritionix', + 'odnoklassniki', + 'odnoklassniki-square', + 'old-republic', + 'opencart', + 'openid', + 'opera', + 'optin-monster', + 'osi', + 'page4', + 'pagelines', + 'palfed', + 'patreon', + 'paypal', + 'periscope', + 'phabricator', + 'phoenix-framework', + 'phoenix-squadron', + 'php', + 'pied-piper', + 'pied-piper-alt', + 'pied-piper-hat', + 'pied-piper-pp', + 'pinterest', + 'pinterest-p', + 'pinterest-square', + 'playstation', + 'product-hunt', + 'pushed', + 'python', + 'qq', + 'quinscape', + 'quora', + 'r-project', + 'ravelry', + 'react', + 'readme', + 'rebel', + 'red-river', + 'reddit', + 'reddit-alien', + 'reddit-square', + 'rendact', + 'renren', + 'replyd', + 'researchgate', + 'resolving', + 'rev', + 'rocketchat', + 'rockrms', + 'safari', + 'sass', + 'schlix', + 'scribd', + 'searchengin', + 'sellcast', + 'sellsy', + 'servicestack', + 'shirtsinbulk', + 'shopware', + 'simplybuilt', + 'sistrix', + 'sith', + 'skyatlas', + 'skype', + 'slack', + 'slack-hash', + 'slideshare', + 'snapchat', + 'snapchat-ghost', + 'snapchat-square', + 'soundcloud', + 'speakap', + 'spotify', + 'squarespace', + 'stack-exchange', + 'stack-overflow', + 'staylinked', + 'steam', + 'steam-square', + 'steam-symbol', + 'sticker-mule', + 'strava', + 'stripe', + 'stripe-s', + 'studiovinari', + 'stumbleupon', + 'stumbleupon-circle', + 'superpowers', + 'supple', + 'teamspeak', + 'telegram', + 'telegram-plane', + 'tencent-weibo', + 'themeco', + 'themeisle', + 'trade-federation', + 'trello', + 'tripadvisor', + 'tumblr', + 'tumblr-square', + 'twitch', + 'twitter', + 'twitter-square', + 'typo3', + 'uber', + 'uikit', + 'uniregistry', + 'untappd', + 'usb', + 'ussunnah', + 'vaadin', + 'viacoin', + 'viadeo', + 'viadeo-square', + 'viber', + 'vimeo', + 'vimeo-square', + 'vimeo-v', + 'vine', + 'vk', + 'vnv', + 'vuejs', + 'weebly', + 'weibo', + 'weixin', + 'whatsapp', + 'whatsapp-square', + 'whmcs', + 'wikipedia-w', + 'windows', + 'wix', + 'wolf-pack-battalion', + 'wordpress', + 'wordpress-simple', + 'wpbeginner', + 'wpexplorer', + 'wpforms', + 'xbox', + 'xing', + 'xing-square', + 'y-combinator', + 'yahoo', + 'yandex', + 'yandex-international', + 'yelp', + 'yoast', + 'youtube', + 'youtube-square', + 'zhihu' +]; + +const mapper = (icon: string): string => { + /** + * Neos <= 3.3 prefixed icons with this, we need to strip those + * otherwise the mapping would'nt work for brand icons + */ + const iconName = trimPrefixes(icon).trim(); + + if (map[iconName]) { + return map[iconName]; + } + + if (brands.includes(iconName)) { + return 'fab fa-' + iconName; + } + + if (!iconName.includes(' ')) { + return 'fas fa-' + iconName; + } + + return iconName; +}; + +function trimPrefixes(icon: string): string { + if (icon.startsWith('fas fa-')) { + return icon.substr(7).split(' ')[0]; + } + + if (icon.startsWith('icon-')) { + return icon.substr(5).split(' ')[0]; + } + + return icon; +} + +export default mapper; diff --git a/packages/react-ui-components/src/IconButton/iconButton.js b/packages/react-ui-components/src/IconButton/iconButton.js deleted file mode 100644 index 5570de760c..0000000000 --- a/packages/react-ui-components/src/IconButton/iconButton.js +++ /dev/null @@ -1,73 +0,0 @@ -import React, {PureComponent} from 'react'; -import PropTypes from 'prop-types'; -import mergeClassNames from 'classnames'; - -class IconButton extends PureComponent { - static propTypes = { - /** - * The icon key which gets passed to the Icon Component. - */ - icon: PropTypes.string.isRequired, - - /** - * An optional `className` to attach to the wrapper. - */ - className: PropTypes.string, - - /** - * Defines the size of the icon button. - */ - size: PropTypes.oneOf(['small', 'regular']), - - /** - * An optional css theme to be injected. - */ - theme: PropTypes.shape({/* eslint-disable quote-props */ - 'iconButton': PropTypes.string - }).isRequired, /* eslint-enable quote-props */ - - /** - * Static component dependencies which are injected from the outside (index.js) - */ - IconComponent: PropTypes.any.isRequired, - ButtonComponent: PropTypes.any.isRequired, - - /** - * Optional disabled flag - */ - disabled: PropTypes.bool - }; - - static defaultProps = { - size: 'regular', - style: 'transparent', - hoverStyle: 'brand' - }; - - render() { - const { - IconComponent, - ButtonComponent, - className, - theme, - icon, - size, - disabled, - ...rest - } = this.props; - const finalClassName = mergeClassNames({ - [className]: className && className.length, - [theme.iconButton]: true, - [theme[`size-${size}`]]: true, - [theme['iconButton--disabled']]: disabled - }); - - return ( - - - - ); - } -} - -export default IconButton; diff --git a/packages/react-ui-components/src/IconButton/iconButton.spec.js b/packages/react-ui-components/src/IconButton/iconButton.spec.js index ef387ba7d0..a0f8022551 100644 --- a/packages/react-ui-components/src/IconButton/iconButton.spec.js +++ b/packages/react-ui-components/src/IconButton/iconButton.spec.js @@ -1,8 +1,8 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import {createStubComponent} from './../_lib/testUtils.js'; -import IconButton from './iconButton.js'; +import {createStubComponent} from './../_lib/testUtils'; +import IconButton from './iconButton'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/IconButton/iconButton.tsx b/packages/react-ui-components/src/IconButton/iconButton.tsx new file mode 100644 index 0000000000..5de3257dec --- /dev/null +++ b/packages/react-ui-components/src/IconButton/iconButton.tsx @@ -0,0 +1,92 @@ +import {IconName} from '@fortawesome/fontawesome-svg-core'; +import mergeClassNames from 'classnames'; +import React, {PureComponent} from 'react'; + +import {PickDefaultProps} from '../../types'; +import {ButtonHoverStyle, ButtonProps, ButtonSize, ButtonStyle} from '../Button/button'; +import {IconProps} from '../Icon/icon'; + +interface IconButtonTheme { + readonly 'iconButton': string; + readonly 'iconButton--disabled': string; +} + +interface IconButtonProps { + /** + * The icon key which gets passed to the Icon Component. + */ + readonly icon: string | IconName; + + /** + * An optional `className` to attach to the wrapper. + */ + readonly className?: string; + + /** + * Defines the size of the icon button. + */ + readonly size: ButtonSize; + + /** + * An optional css theme to be injected. + */ + readonly theme?: IconButtonTheme; + + // TODO: This feels strange. Can we use the actual class here? + /** + * Static component dependencies which are injected from the outside (index.js) + */ + readonly IconComponent: React.ComponentClass; + readonly ButtonComponent: React.ComponentClass; + + /** + * Optional disabled flag + */ + readonly disabled?: boolean; + + readonly style: ButtonStyle; + + readonly hoverStyle: ButtonHoverStyle; +} + +type DefaultProps = PickDefaultProps; + +const defaultProps: DefaultProps = { + hoverStyle: 'brand', + size: 'regular', + style: 'transparent', +}; + +class IconButton extends PureComponent { + public static readonly defaultProps = defaultProps; + + public render(): JSX.Element { + const { + IconComponent, + ButtonComponent, + className, + theme, + icon, + size, + disabled, + ...rest + } = this.props; + const finalClassName = mergeClassNames( + className, + theme!.iconButton, + // @ts-ignore implizit any because IconButtonTheme has no index signature + theme![`size-${size}`], + { + [theme!['iconButton--disabled']]: disabled + } + ); + + return ( + + + + ); + } +} + +export default IconButton; diff --git a/packages/react-ui-components/src/IconButton/index.js b/packages/react-ui-components/src/IconButton/index.js index 17359ef38e..eab76b3854 100644 --- a/packages/react-ui-components/src/IconButton/index.js +++ b/packages/react-ui-components/src/IconButton/index.js @@ -1,16 +1,16 @@ import {themr} from '@friendsofreactjs/react-css-themr'; -import identifiers from './../identifiers'; +import identifiers from '../identifiers'; import style from './style.css'; -import IconButton from './iconButton.js'; +import IconButton from './iconButton'; const ThemedIconButton = themr(identifiers.iconButton, style)(IconButton); // // Dependency injection // -import injectProps from './../_lib/injectProps.js'; -import Icon from './../Icon/index'; -import Button from './../Button/index'; +import injectProps from './../_lib/injectProps'; +import Icon from './../Icon'; +import Button from './../Button'; export default injectProps({ IconComponent: Icon, diff --git a/packages/react-ui-components/src/IconButton/index.spec.js b/packages/react-ui-components/src/IconButton/index.spec.js index 6ef3385c5d..d9b68ecc26 100644 --- a/packages/react-ui-components/src/IconButton/index.spec.js +++ b/packages/react-ui-components/src/IconButton/index.spec.js @@ -1,4 +1,4 @@ -import IconButton from './index.js'; +import IconButton from '.'; describe(' (entry point)', () => { it('should export a Component.', () => { diff --git a/packages/react-ui-components/src/IconButton/index.story.js b/packages/react-ui-components/src/IconButton/index.story.js index 1f24467501..990a2dc26f 100644 --- a/packages/react-ui-components/src/IconButton/index.story.js +++ b/packages/react-ui-components/src/IconButton/index.story.js @@ -1,8 +1,8 @@ import React from 'react'; import {storiesOf, action} from '@storybook/react'; import {withKnobs, text, select} from '@storybook/addon-knobs'; -import {StoryWrapper} from './../_lib/storyUtils.js'; -import IconButton from './index.js'; +import {StoryWrapper} from './../_lib/storyUtils'; +import IconButton from '.'; const validStyleKeys = ['clean', 'brand', 'lighter', 'transparent']; const validHoverStyleKeys = ['clean', 'brand', 'darken']; diff --git a/packages/react-ui-components/src/IconButtonDropDown/__snapshots__/iconButtonDropDown.spec.js.snap b/packages/react-ui-components/src/IconButtonDropDown/__snapshots__/iconButtonDropDown.spec.js.snap index 57379d7134..4687c33d89 100644 --- a/packages/react-ui-components/src/IconButtonDropDown/__snapshots__/iconButtonDropDown.spec.js.snap +++ b/packages/react-ui-components/src/IconButtonDropDown/__snapshots__/iconButtonDropDown.spec.js.snap @@ -14,6 +14,7 @@ exports[` should render correctly. 1`] = ` onFocus={[Function]} onMouseDown={[Function]} onMouseEnter={[Function]} + size="regular" style="clean" > should render correctly. 1`] = `
should render correctly. 1`] = `
{ - const {onClick, id} = this.props; - onClick(id); - }; - - render() { - const {children, ...rest} = this.props; - - return ( - - {children} - - ); - } -} - -export default DropDownItem; diff --git a/packages/react-ui-components/src/IconButtonDropDown/dropDownItem.spec.js b/packages/react-ui-components/src/IconButtonDropDown/dropDownItem.spec.js index 6e9148063c..94514fe66b 100644 --- a/packages/react-ui-components/src/IconButtonDropDown/dropDownItem.spec.js +++ b/packages/react-ui-components/src/IconButtonDropDown/dropDownItem.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import {shallow} from 'enzyme'; import toJson from 'enzyme-to-json'; -import DropDownItem from './dropDownItem.js'; +import DropDownItem from './dropDownItem'; describe('', () => { let props; diff --git a/packages/react-ui-components/src/IconButtonDropDown/dropDownItem.tsx b/packages/react-ui-components/src/IconButtonDropDown/dropDownItem.tsx new file mode 100644 index 0000000000..959a6428b6 --- /dev/null +++ b/packages/react-ui-components/src/IconButtonDropDown/dropDownItem.tsx @@ -0,0 +1,44 @@ +import React, {PureComponent} from 'react'; + +type DropDownItemId = string; + +interface DropDownItemProps { + /** + * The handler to call when clicking on the item of the DropDown. + */ + readonly onClick: (id: DropDownItemId) => void; + + /** + * The ID to reference the clicked item in the `onClick` handker. + */ + readonly id: DropDownItemId; + + /** + * The children to render within the anchor. + */ + readonly children: React.ReactNode; + + readonly className: string; +} + +class DropDownItem extends PureComponent { + public render(): JSX.Element { + const {children, ...rest} = this.props; + + return ( + + {children} + + ); + } + + private readonly handleClick = () => { + this.props.onClick(this.props.id); + } +} + +export default DropDownItem; diff --git a/packages/react-ui-components/src/IconButtonDropDown/iconButtonDropDown.js b/packages/react-ui-components/src/IconButtonDropDown/iconButtonDropDown.js deleted file mode 100644 index 5956b4ccd2..0000000000 --- a/packages/react-ui-components/src/IconButtonDropDown/iconButtonDropDown.js +++ /dev/null @@ -1,190 +0,0 @@ -import React, {PureComponent} from 'react'; -import PropTypes from 'prop-types'; -import mergeClassNames from 'classnames'; -import DropDownItem from './dropDownItem.js'; - -export default class IconButtonDropDown extends PureComponent { - state = { - isOpen: false - }; - - _mouseHoldTimeout = null; - - _mouseHoverTimeout = null; - - static propTypes = { - /** - * The key of the Icon which is always displayed. - */ - icon: PropTypes.string.isRequired, - - /** - * Children to be rendered inside the DropDown. - */ - children: PropTypes.any.isRequired, - - /** - * You can pass an modeIcon which displays the current selected item in a leaner way. - * Modify this prop via listening to the `onItemSelect` propType. - */ - modeIcon: PropTypes.string.isRequired, - - /** - * Will be called once the user clicks on the wrapper if - * it is NOT opened right meow. - */ - onClick: PropTypes.func.isRequired, - - /** - * Will be called once the user selects an item. - * You should specify an `dropDownId` prop on each child, - * which will then be propagated to this handler as the first - * and only argument. - */ - onItemSelect: PropTypes.func.isRequired, - - /** - * An optional css theme to be injected. - */ - theme: PropTypes.shape({ - 'wrapper': PropTypes.string, - 'wrapper__btn': PropTypes.string, - 'wrapper__btnModeIcon': PropTypes.string, - 'wrapper__dropDown': PropTypes.string, - 'wrapper__dropDown--isOpen': PropTypes.string, - 'wrapper__dropDownItem': PropTypes.string - }).isRequired, - - /** - * Static component dependencies which are injected from the outside (index.js) - */ - IconComponent: PropTypes.any.isRequired, - ButtonComponent: PropTypes.any.isRequired, - - /** - * An optional `className` to attach to the wrapper. - */ - className: PropTypes.string, - - /** - * Controls the whole components disabled state. - */ - isDisabled: PropTypes.bool, - - /** - * Props which are propagated to the