Files
remark42/web/app/components/button/button.tsx
T

108 lines
2.1 KiB
TypeScript

/** @jsx h */
import { Component, h, RenderableProps } from 'preact';
import b from 'bem-react-helper';
import noop from '@app/utils/noop';
import { Theme } from '@app/common/types';
interface Props {
type?: string;
kind?: string;
theme: Theme;
mix?: string;
onClick?: (e: MouseEvent) => void;
onFocus?: (e: FocusEvent) => void;
onBlur?: (e: FocusEvent) => void;
}
interface State {
isClicked: boolean;
isFocused: boolean;
}
export class Button extends Component<JSX.HTMLAttributes & Props, State> {
constructor(props: Props) {
super(props);
this.state = {
isClicked: false,
isFocused: false,
};
this.onMouseDown = this.onMouseDown.bind(this);
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
}
onMouseDown() {
this.setState({
isClicked: true,
});
}
onClick(e: MouseEvent) {
this.props.onClick!(e);
}
onBlur(e: FocusEvent) {
this.setState({
isClicked: false,
isFocused: false,
});
this.props.onBlur!(e);
}
onFocus(e: FocusEvent) {
this.setState({
isFocused: true,
});
this.props.onFocus!(e);
}
render(props: RenderableProps<JSX.HTMLAttributes & Props>, state: State) {
const { children, className } = props;
const { isClicked, isFocused } = state;
let rclassName = b(
'button',
{ mix: props.mix },
{ theme: props.theme, type: props.type, kind: props.kind, clicked: isClicked, focused: isFocused }
);
if (className) {
rclassName +=
' ' +
b(
className,
{},
{ theme: props.theme, type: props.type, kind: props.kind, clicked: isClicked, focused: isFocused }
);
}
const localProps = { ...props };
delete localProps.children;
delete localProps.mix;
return (
<button
{...localProps}
className={rclassName}
onMouseDown={this.onMouseDown}
onBlur={this.onBlur}
onFocus={this.onFocus}
>
{children}
</button>
);
}
}
Button.defaultProps = {
type: 'button',
onClick: noop,
onBlur: noop,
onFocus: noop,
};