From 220a36c2e4c97c1e7a373b67ed46bb8fabc73b7a Mon Sep 17 00:00:00 2001 From: David Sevilla Martin Date: Fri, 31 Jan 2020 17:51:11 -0500 Subject: [PATCH] common: add Checkbox, Switch, FieldSet components --- js/src/common/components/Checkbox.tsx | 67 +++++++++++++++++++++++++++ js/src/common/components/FieldSet.tsx | 26 +++++++++++ js/src/common/components/Switch.tsx | 17 +++++++ 3 files changed, 110 insertions(+) create mode 100644 js/src/common/components/Checkbox.tsx create mode 100644 js/src/common/components/FieldSet.tsx create mode 100644 js/src/common/components/Switch.tsx diff --git a/js/src/common/components/Checkbox.tsx b/js/src/common/components/Checkbox.tsx new file mode 100644 index 000000000..a52d6d1bc --- /dev/null +++ b/js/src/common/components/Checkbox.tsx @@ -0,0 +1,67 @@ +import Component, { ComponentProps } from '../Component'; +import LoadingIndicator from './LoadingIndicator'; +import icon from '../helpers/icon'; + +export interface CheckboxProps extends ComponentProps { + /** + * Whether or not the checkbox is checked + */ + state: boolean; + + /** + * Whether or not the checkbox is disabled. + */ + disabled: boolean; + + /** + * A callback to run when the checkbox is checked/unchecked. + */ + onchange?: Function; +} + +/** + * The `Checkbox` component defines a checkbox input. + */ +export default class Checkbox extends Component { + /** + * Whether or not the checkbox's value is in the process of being saved. + */ + loading = false; + + view() { + const className = classNames( + 'Checkbox', + this.props.className, + this.props.state ? 'on' : 'off', + this.loading && 'loading', + this.props.disabled && 'disabled' + ); + + return ( + + ); + } + + /** + * Get the template for the checkbox's display (tick/cross icon). + */ + protected getDisplay() { + return this.loading ? LoadingIndicator.component({ size: 'tiny' }) : icon(this.props.state ? 'fas fa-check' : 'fas fa-times'); + } + + /** + * Run a callback when the state of the checkbox is changed. + */ + protected onchange(checked: boolean) { + if (this.props.onchange) this.props.onchange(checked, this); + } +} diff --git a/js/src/common/components/FieldSet.tsx b/js/src/common/components/FieldSet.tsx new file mode 100644 index 000000000..e6674db8f --- /dev/null +++ b/js/src/common/components/FieldSet.tsx @@ -0,0 +1,26 @@ +import Component, { ComponentProps } from '../Component'; +import listItems from '../helpers/listItems'; + +export interface FieldSetProps extends ComponentProps { + /** + * The title of this group of fields + */ + label: string; +} + +/** + * The `FieldSet` component defines a collection of fields, displayed in a list + * underneath a title. + * + * The children should be an array of items to show in the fieldset. + */ +export default class FieldSet extends Component { + view() { + return ( +
+ {this.props.label} +
    {listItems(this.props.children)}
+
+ ); + } +} diff --git a/js/src/common/components/Switch.tsx b/js/src/common/components/Switch.tsx new file mode 100644 index 000000000..2fd246244 --- /dev/null +++ b/js/src/common/components/Switch.tsx @@ -0,0 +1,17 @@ +import Checkbox from './Checkbox'; + +/** + * The `Switch` component is a `Checkbox`, but with a switch display instead of + * a tick/cross one. + */ +export default class Switch extends Checkbox { + static initProps(props) { + super.initProps(props); + + props.className = `${props.className || ''} Checkbox--switch`; + } + + getDisplay() { + return this.loading ? super.getDisplay() : ''; + } +}