import * as React from 'react'; import { ComponentClass, MouseEvent, PureComponent, ReactNode } from 'react'; import getPassThrough, { PassTroughFunction } from '../../utils/getPassThrough'; import { Component } from '../../types'; export interface ButtonNodeProps { flat: boolean; innerRef(instance: HTMLElement): void; onMouseLeave(event: MouseEvent): void; onMouseUp(event: MouseEvent): void; primary: boolean; type: string | null; } export interface ButtonProps { accent: boolean; children: ReactNode; flat: boolean; floating: boolean; href: string; innerRef(instance: HTMLElement): void; label: string; mini: boolean; neutral: boolean; onMouseLeave(event: MouseEvent): void; onMouseUp(event: MouseEvent): void; primary: boolean; raised: boolean; toggle: boolean; type: string; } export interface ButtonFactoryArgs { ButtonNode: Component; LinkNode: Component; passthrough: PassTroughFunction; } export default function buttonFactory({ ButtonNode, LinkNode, passthrough, }: ButtonFactoryArgs): ComponentClass { const passProps = getPassThrough(passthrough); return class Button extends PureComponent { public static defaultProps = { accent: false, flat: false, floating: false, mini: false, neutral: true, primary: false, raised: false, type: 'button', }; private rootNode: HTMLElement | null = null; private handleMouseUp = event => { if (this.rootNode) { this.rootNode.blur(); } if (this.props.onMouseUp) { this.props.onMouseUp(event); } }; private handleMouseLeave = event => { if (this.rootNode) { this.rootNode.blur(); } if (this.props.onMouseLeave) { this.props.onMouseLeave(event); } }; private handleInnerRef = node => { const { innerRef } = this.props; this.rootNode = node; if (innerRef) { innerRef(node); } }; public render() { const nodeTag = this.props.href ? 'LinkNode' : 'ButtonNode'; const ButtonElement = this.props.href ? LinkNode : ButtonNode; const { children, primary, flat, label, type, ...others } = this.props; const isPrimary = primary || (!others.accent && !others.neutral); const isNoneOther = !others.raised && !others.floating && !others.toggle; const isFlat = flat || isNoneOther; return ( {children} {label} ); } }; }