From 9a5b313ea12bdb9dc3e3873ca3a2639bd7483e46 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Mon, 28 Jan 2019 11:35:25 +0100 Subject: Update packages --- packages/ui/.gitignore | 2 + packages/ui/package-lock.json | 207 +++++++++++++++++++++++++++++++++++++ packages/ui/package.json | 41 ++++++++ packages/ui/src/badge/index.tsx | 75 ++++++++++++++ packages/ui/src/headline/index.tsx | 71 +++++++++++++ packages/ui/src/icon/index.tsx | 55 ++++++++++ packages/ui/src/index.ts | 5 + packages/ui/src/infobox/index.tsx | 194 ++++++++++++++++++++++++++++++++++ packages/ui/src/loader/index.tsx | 45 ++++++++ packages/ui/src/typings/generic.ts | 10 ++ packages/ui/tsconfig.json | 12 +++ packages/ui/tslint.json | 3 + packages/ui/webpack.config.js | 19 ++++ 13 files changed, 739 insertions(+) create mode 100644 packages/ui/.gitignore create mode 100644 packages/ui/package-lock.json create mode 100644 packages/ui/package.json create mode 100644 packages/ui/src/badge/index.tsx create mode 100644 packages/ui/src/headline/index.tsx create mode 100644 packages/ui/src/icon/index.tsx create mode 100644 packages/ui/src/index.ts create mode 100644 packages/ui/src/infobox/index.tsx create mode 100644 packages/ui/src/loader/index.tsx create mode 100644 packages/ui/src/typings/generic.ts create mode 100644 packages/ui/tsconfig.json create mode 100644 packages/ui/tslint.json create mode 100644 packages/ui/webpack.config.js (limited to 'packages/ui') diff --git a/packages/ui/.gitignore b/packages/ui/.gitignore new file mode 100644 index 000000000..d01826a6b --- /dev/null +++ b/packages/ui/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +lib diff --git a/packages/ui/package-lock.json b/packages/ui/package-lock.json new file mode 100644 index 000000000..8fa68a29b --- /dev/null +++ b/packages/ui/package-lock.json @@ -0,0 +1,207 @@ +{ + "name": "@meetfranz/ui", + "version": "0.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@mdi/js": { + "version": "3.3.92", + "resolved": "https://registry.npmjs.org/@mdi/js/-/js-3.3.92.tgz", + "integrity": "sha512-l+12IwTycHlijWMiRWBAssm0RSgkQiwMthIy/EcBAdSqtnsHnFjHq+aI2MBZ8/AYX0QBxNUv4+EN0SXZgNkWDg==" + }, + "@mdi/react": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mdi/react/-/react-1.1.0.tgz", + "integrity": "sha512-c0+avMYEZ6i7Pg1ULLFs+p7k8bDPiie9rrgGYs8VWQhw2tUUYz7r0lIPVzD3bzMghWfyhfkArj88K5Of0WTMNw==" + }, + "@meetfranz/theme": { + "version": "file:../theme", + "requires": { + "color": "^3.1.0" + }, + "dependencies": { + "color": { + "version": "3.1.0", + "bundled": true, + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "color-convert": { + "version": "1.9.3", + "bundled": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "color-string": { + "version": "1.5.3", + "bundled": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "is-arrayish": { + "version": "0.3.2", + "bundled": true + }, + "simple-swizzle": { + "version": "0.2.2", + "bundled": true, + "requires": { + "is-arrayish": "^0.3.1" + } + } + } + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + }, + "create-react-class": { + "version": "15.6.3", + "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz", + "integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==", + "requires": { + "fbjs": "^0.8.9", + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "fbjs": { + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", + "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "requires": { + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "react-loader": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/react-loader/-/react-loader-2.4.5.tgz", + "integrity": "sha1-zT5VHGzQc4wcDxPwc2VPk4KL5ak=", + "requires": { + "create-react-class": "^15.5.2", + "prop-types": "^15.5.8", + "spin.js": "2.x" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "spin.js": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/spin.js/-/spin.js-2.3.2.tgz", + "integrity": "sha1-bKpW1SBnNFD9XPvGlx5tB3LDeho=" + }, + "ua-parser-js": { + "version": "0.7.19", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.19.tgz", + "integrity": "sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ==" + }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" + } + } +} diff --git a/packages/ui/package.json b/packages/ui/package.json new file mode 100644 index 000000000..cd7252850 --- /dev/null +++ b/packages/ui/package.json @@ -0,0 +1,41 @@ +{ + "name": "@meetfranz/ui", + "version": "0.0.0", + "description": "React UI components for Franz", + "main": "lib/index.js", + "scripts": { + "dev": "NODE_ENV=development ../../node_modules/.bin/webpack -w", + "prepare": "../../node_modules/.bin/webpack" + }, + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/meetfranz/franz.git" + }, + "keywords": [ + "Franz", + "Forms", + "React", + "UI" + ], + "author": "Stefan Malzner ", + "license": "Apache-2.0", + "dependencies": { + "@mdi/js": "^3.3.92", + "@mdi/react": "^1.1.0", + "@meetfranz/theme": "file:../theme", + "react-loader": "^2.4.5" + }, + "peerDependencies": { + "classnames": "^2.2.6", + "lodash": "^4.17.11", + "mobx": "^5.8.0", + "mobx-react": "^5.4.3", + "react": "^16.7.0", + "react-dom": "16.7.0", + "react-jss": "^8.6.1" + }, + "gitHead": "e31248830eb63c8bff3d9add3baa4ca8916b74e1" +} diff --git a/packages/ui/src/badge/index.tsx b/packages/ui/src/badge/index.tsx new file mode 100644 index 000000000..241e778e7 --- /dev/null +++ b/packages/ui/src/badge/index.tsx @@ -0,0 +1,75 @@ +import { Theme } from '@meetfranz/theme'; +import classnames from 'classnames'; +import React, { Component } from 'react'; +import injectStyle from 'react-jss'; + +import { IWithStyle } from '../typings/generic'; + +interface IProps extends IWithStyle { + type: string; + className?: string; + children: React.ReactNode; +} + +const badgeStyles = (theme: Theme) => { + const styles = {}; + Object.keys(theme.styleTypes).map((style) => { + Object.assign(styles, { + [style]: { + background: theme.styleTypes[style].accent, + color: theme.styleTypes[style].contrast, + border: theme.styleTypes[style].border, + }, + }); + }); + + return styles; +}; + +const styles = (theme: Theme) => ({ + badge: { + display: 'inline-block', + padding: [3, 8, 4], + fontSize: theme.badgeFontSize, + borderRadius: theme.badgeBorderRadius, + margin: [0, 4], + + '&:first-child': { + marginLeft: 0, + }, + + '&:last-child': { + marginRight: 0, + }, + }, + ...badgeStyles(theme), +}); + +class BadgeComponent extends Component { + public static defaultProps = { + type: 'primary', + }; + + render() { + const { + classes, + children, + type, + className, + } = this.props; + + return ( +
+ {children} +
+ ); + } +} + +export const Badge = injectStyle(styles)(BadgeComponent); diff --git a/packages/ui/src/headline/index.tsx b/packages/ui/src/headline/index.tsx new file mode 100644 index 000000000..3458a40ad --- /dev/null +++ b/packages/ui/src/headline/index.tsx @@ -0,0 +1,71 @@ +import { Theme } from '@meetfranz/theme'; +import classnames from 'classnames'; +import React, { Component } from 'react'; +import injectStyle from 'react-jss'; + +import { uiFontSize } from '@meetfranz/theme/lib/themes/default'; +import { IWithStyle, Omit } from '../typings/generic'; + +interface IProps extends IWithStyle { + level?: number; + className?: string; + children: string | React.ReactNode; + id?: string; +} + +const styles = (theme: Theme) => ({ + headline: { + fontWeight: 'lighter', + color: theme.colorText, + marginTop: 0, + marginBottom: 10, + textAlign: 'left', + }, + h1: { + fontSize: 30, + marginTop: 0, + }, + h2: { + fontSize: 20, + }, + h3: { + fontSize: 18, + }, + h4: { + fontSize: theme.uiFontSize, + }, +}); + +class HeadlineComponent extends Component { + render() { + const { + classes, + level, + className, + children, + id, + } = this.props; + + return React.createElement( + `h${level}`, + { + id, + className: classnames({ + [classes.headline]: true, + [classes[level ? `h${level}` : 'h1']]: true, + [`${className}`]: className, + }), + }, + children, + ); + } +} + +const Headline = injectStyle(styles)(HeadlineComponent); + +const createH = (level: number) => (props: Omit) => {props.children}; + +export const H1 = createH(1); +export const H2 = createH(2); +export const H3 = createH(3); +export const H4 = createH(4); diff --git a/packages/ui/src/icon/index.tsx b/packages/ui/src/icon/index.tsx new file mode 100644 index 000000000..e30d3396d --- /dev/null +++ b/packages/ui/src/icon/index.tsx @@ -0,0 +1,55 @@ +import * as mdiIcons from '@mdi/js'; +import MdiIcon from '@mdi/react'; +import { Theme } from '@meetfranz/theme'; +import classnames from 'classnames'; +import React, { Component } from 'react'; +import injectStyle from 'react-jss'; + +import { IWithStyle } from '../typings/generic'; + +interface IProps extends IWithStyle { + icon: keyof typeof mdiIcons; + size?: number; + className?: string; +} + +const styles = (theme: Theme) => ({ + icon: { + fill: theme.colorText, + }, +}); + +class IconComponent extends Component { + public static defaultProps = { + size: 1, + }; + + render() { + const { + classes, + icon: iconName, + size, + className, + } = this.props; + + let icon = ''; + if (iconName && mdiIcons[iconName]) { + icon = mdiIcons[iconName]; + } else if (iconName && !mdiIcons[iconName]) { + console.warn(`Icon '${iconName}' was not found`); + } + + return ( + + ); + } +} + +export const Icon = injectStyle(styles)(IconComponent); diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts new file mode 100644 index 000000000..1eeec5144 --- /dev/null +++ b/packages/ui/src/index.ts @@ -0,0 +1,5 @@ +export { Icon } from './icon'; +export { Infobox } from './infobox'; +export * from './headline'; +export { Loader } from './loader'; +export { Badge } from './badge'; diff --git a/packages/ui/src/infobox/index.tsx b/packages/ui/src/infobox/index.tsx new file mode 100644 index 000000000..bf985ea9c --- /dev/null +++ b/packages/ui/src/infobox/index.tsx @@ -0,0 +1,194 @@ +import { Theme } from '@meetfranz/theme'; +import classnames from 'classnames'; +import { observer } from 'mobx-react'; +import React, { Component } from 'react'; +import injectStyle from 'react-jss'; +// import Loader from 'react-loader'; + +import { Icon } from '../'; +import { IWithStyle } from '../typings/generic'; + +interface IProps extends IWithStyle { + icon?: string; + type?: string; + dismissable?: boolean; + onDismiss?: () => void; + ctaOnClick?: () => void; + ctaLabel?: string; + ctaLoading?: boolean; + children: React.ReactNode; +} + +interface IState { + isDismissing: boolean; + dismissed: boolean; +} + +const buttonStyles = (theme: Theme) => { + const styles = {}; + Object.keys(theme.styleTypes).map((style) => { + Object.assign(styles, { + [style]: { + background: theme.styleTypes[style].accent, + color: theme.styleTypes[style].contrast, + border: theme.styleTypes[style].border, + + '& svg': { + fill: theme.styleTypes[style].contrast, + }, + }, + }); + }); + + return styles; +}; + +const styles = (theme: Theme) => ({ + wrapper: { + position: 'relative', + overflow: 'hidden', + }, + infobox: { + alignItems: 'center', + borderRadius: theme.borderRadiusSmall, + display: 'flex', + height: 'auto', + marginBottom: 30, + padding: '15px 20px', + top: 0, + transition: 'all 0.5s', + opacity: 1, + }, + dismissing: { + // position: 'absolute', + marginTop: -100, + opacity: 0, + }, + content: { + flex: 1, + }, + icon: { + marginRight: 10, + }, + close: { + color: (props: IProps) => theme.styleTypes[props.type ? props.type : 'primary'].contrast, + marginRight: -5, + border: 0, + background: 'none', + }, + cta: { + borderColor: (props: IProps) => theme.styleTypes[props.type ? props.type : 'primary'].contrast, + borderRadius: theme.borderRadiusSmall, + borderStyle: 'solid', + borderWidth: 1, + background: 'none', + color: (props: IProps) => theme.styleTypes[props.type ? props.type : 'primary'].contrast, + marginLeft: 15, + padding: [4, 10], + fontSize: theme.uiFontSize, + transition: 'opacity 0.3s', + + '&:hover': { + opacity: 0.6, + }, + }, + ...buttonStyles(theme), +}); + +@observer +class InfoboxComponent extends Component { + public static defaultProps = { + type: 'primary', + dismissable: false, + ctaOnClick: () => {}, + onDismiss: () => {}, + ctaLabel: '', + ctaLoading: false, + }; + + state = { + isDismissing: false, + dismissed: false, + }; + + dismiss() { + const { + onDismiss, + } = this.props; + + this.setState({ + isDismissing: true, + }); + + if (onDismiss) { + onDismiss(); + } + + setTimeout(() => { + this.setState({ + dismissed: true, + }); + }, 3000); + } + + render() { + const { + classes, + children, + icon, + type, + ctaLabel, + ctaLoading, + ctaOnClick, + dismissable, + } = this.props; + + const { + isDismissing, + dismissed, + } = this.state; + + if (dismissed) { + return null; + } + + return ( +
+
+ {icon && ( + + )} +
+ {children} +
+ {ctaLabel && ( + + )} + {dismissable && ( + + )} +
+
+ ); + } +} + +export const Infobox = injectStyle(styles)(InfoboxComponent); diff --git a/packages/ui/src/loader/index.tsx b/packages/ui/src/loader/index.tsx new file mode 100644 index 000000000..799caf195 --- /dev/null +++ b/packages/ui/src/loader/index.tsx @@ -0,0 +1,45 @@ +import { Theme } from '@meetfranz/theme'; +import classnames from 'classnames'; +import React, { Component } from 'react'; +import injectStyle from 'react-jss'; +import ReactLoader from 'react-loader'; + +import { IWithStyle } from '../typings/generic'; + +interface IProps extends IWithStyle { + className?: string; +} + +const styles = (theme: Theme) => ({ + container: { + position: 'relative', + height: 60, + }, +}); + +class LoaderComponent extends Component { + render() { + const { + classes, + className, + theme, + } = this.props; + + return ( +
+ +
+ ); + } +} + +export const Loader = injectStyle(styles)(LoaderComponent); diff --git a/packages/ui/src/typings/generic.ts b/packages/ui/src/typings/generic.ts new file mode 100644 index 000000000..d5f953b9f --- /dev/null +++ b/packages/ui/src/typings/generic.ts @@ -0,0 +1,10 @@ +import { Theme } from '@meetfranz/theme/lib'; +import { Classes } from 'jss'; + +export interface IWithStyle { + classes: Classes; + theme: Theme; +} + +export type Merge = Omit> & N; +export type Omit = Pick>; diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json new file mode 100644 index 000000000..8b9507eac --- /dev/null +++ b/packages/ui/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.settings.json", + "compilerOptions": { + "outDir": "lib", + "rootDir": "src" + }, + "references": [ + { + "path": "../theme" + } + ] +} diff --git a/packages/ui/tslint.json b/packages/ui/tslint.json new file mode 100644 index 000000000..0946f2096 --- /dev/null +++ b/packages/ui/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": "../../tslint.json" +} diff --git a/packages/ui/webpack.config.js b/packages/ui/webpack.config.js new file mode 100644 index 000000000..cc3370359 --- /dev/null +++ b/packages/ui/webpack.config.js @@ -0,0 +1,19 @@ +const path = require('path'); +const baseConfig = require('../../webpack.config.base')(__dirname); + +module.exports = Object.assign({}, baseConfig, { + output: { + filename: 'index.js', + path: path.join(__dirname, 'lib'), + libraryTarget: 'commonjs2', + }, + externals: { + react: 'react', + reactDom: 'react-dom', + classnames: 'classnames', + lodash: 'lodash', + mobx: 'mobx', + mobxReact: 'mobx-react', + reactJss: 'react-jss', + }, +}); -- cgit v1.2.3-70-g09d2