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/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 ++ 7 files changed, 455 insertions(+) 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 (limited to 'packages/ui/src') 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>; -- cgit v1.2.3-70-g09d2