diff --git a/src/components/inputs/Area.stories.jsx b/src/components/inputs/Area.stories.jsx new file mode 100644 index 0000000..2f0e2da --- /dev/null +++ b/src/components/inputs/Area.stories.jsx @@ -0,0 +1,26 @@ +import * as React from "react" +import * as ReactDOM from "react-dom" +import * as Decorators from "../../utils/Decorators" +import { Area } from "./Area" + + +export default { + component: Area, + title: "Inputs/Area", + decorators: [Decorators.Bluelib], + argTypes: { + customColor: { + control: {type: "color"}, + }, + }, +} + + +export const Default = props => ( + +) +Default.args = { + placeholder: "Enter multiline text here\n\nThis component can be resized", + disabled: false, + required: false, +} diff --git a/src/components/inputs/Area.tsx b/src/components/inputs/Area.tsx new file mode 100644 index 0000000..c04ce33 --- /dev/null +++ b/src/components/inputs/Area.tsx @@ -0,0 +1,41 @@ +import * as React from "react" +import * as ReactDOM from "react-dom" +import * as Types from "../../types" +import {BaseElement} from "../BaseElement" +import mergeClassNames from "classnames" + + +interface AreaProps { + placeholder: string, + required?: boolean, + disabled?: boolean, + + onChange: (contents: string) => boolean, + value?: string, + + [props: string]: any, +} + + +export function Area({onChange, ...props}: AreaProps): JSX.Element { + props.bluelibClassNames = mergeClassNames(props.bluelibClassNames, "input", "input-area") + + const onChangeWrapper = React.useCallback( + + (event: React.ChangeEvent): boolean => { + const contents = event.target.value + + if(onChange) { + return onChange(contents) + } + + return false + }, + + [onChange] + ) + + return ( + + ) +} diff --git a/src/components/inputs/Field.stories.jsx b/src/components/inputs/Field.stories.jsx index 693a1e0..94ba8a8 100644 --- a/src/components/inputs/Field.stories.jsx +++ b/src/components/inputs/Field.stories.jsx @@ -12,9 +12,6 @@ export default { customColor: { control: {type: "color"}, }, - disabled: { - control: {type: "boolean"}, - }, }, } diff --git a/src/components/inputs/Field.tsx b/src/components/inputs/Field.tsx index cf44796..c27b452 100644 --- a/src/components/inputs/Field.tsx +++ b/src/components/inputs/Field.tsx @@ -10,28 +10,32 @@ interface FieldProps { required?: boolean, disabled?: boolean, - onChange?: (event: React.FormEvent) => boolean, - onInput?: (event: React.FormEvent) => boolean, - onInvalid?: (event: React.FormEvent) => boolean, - onReset?: (event: React.FormEvent) => boolean, - onSubmit?: (event: React.FormEvent) => boolean, + onChange: (contents: string) => boolean, + value?: string, [props: string]: any, } -export function Field({onChange, onInput, onInvalid, ...props}: FieldProps): JSX.Element { - +export function Field({onChange, value, ...props}: FieldProps): JSX.Element { props.bluelibClassNames = mergeClassNames(props.bluelibClassNames, "input", "input-field") - // Propagate change events only if the element is enabled - if(!props.disabled) { - props.onChange = onChange - props.onInput = onInput - props.onInvalid = onInvalid - } + const onChangeWrapper = React.useCallback( + + (event: React.ChangeEvent): boolean => { + const contents = event.target.value + + if(onChange) { + return onChange(contents) + } + + return false + }, + + [onChange] + ) return ( - + ) } diff --git a/src/components/inputs/Multiselect.stories.jsx b/src/components/inputs/Multiselect.stories.jsx new file mode 100644 index 0000000..78b60cd --- /dev/null +++ b/src/components/inputs/Multiselect.stories.jsx @@ -0,0 +1,49 @@ +import * as React from "react" +import * as ReactDOM from "react-dom" +import * as Decorators from "../../utils/Decorators" +import { Option } from "./Option" +import { OptionGroup } from "./OptionGroup" +import { Multiselect } from "./Multiselect" + + +export default { + component: Multiselect, + title: "Inputs/Multiselect", + decorators: [Decorators.Bluelib], + argTypes: { + customColor: { + control: {type: "color"}, + }, + }, +} + + +export const Default = props => ( + + +) +Default.args = { + disabled: false, +} + + +export const WithGroups = props => ( + + + + + + +) +WithGroups.args = { + disabled: false, +} \ No newline at end of file diff --git a/src/components/inputs/Multiselect.tsx b/src/components/inputs/Multiselect.tsx new file mode 100644 index 0000000..a820d8f --- /dev/null +++ b/src/components/inputs/Multiselect.tsx @@ -0,0 +1,24 @@ +import * as React from "react" +import * as ReactDOM from "react-dom" +import * as Types from "../../types" +import {BaseElement} from "../BaseElement" +import mergeClassNames from "classnames" + + +interface MultiselectProps { + disabled?: boolean, + + onChange?: (event: React.FormEvent) => boolean, + + [props: string]: any, +} + + +export function Multiselect({...props}: MultiselectProps): JSX.Element { + + props.bluelibClassNames = mergeClassNames(props.bluelibClassNames, "input", "input-multiselect") + + return ( + + ) +} diff --git a/src/components/inputs/Option.tsx b/src/components/inputs/Option.tsx new file mode 100644 index 0000000..413a1cf --- /dev/null +++ b/src/components/inputs/Option.tsx @@ -0,0 +1,23 @@ +import * as React from "react" +import * as ReactDOM from "react-dom" +import * as Types from "../../types" +import {BaseElement} from "../BaseElement" +import mergeClassNames from "classnames" + + +interface OptionProps { + label: string, + + [props: string]: any, +} + + +export function Option({label, ...props}: OptionProps): JSX.Element { + props.bluelibClassNames = mergeClassNames(props.bluelibClassNames, "input-option") + + return ( + + {label} + + ) +} diff --git a/src/components/inputs/OptionGroup.tsx b/src/components/inputs/OptionGroup.tsx new file mode 100644 index 0000000..9ec12a4 --- /dev/null +++ b/src/components/inputs/OptionGroup.tsx @@ -0,0 +1,22 @@ +import * as React from "react" +import * as ReactDOM from "react-dom" +import * as Types from "../../types" +import {BaseElement} from "../BaseElement" +import mergeClassNames from "classnames" + + +interface OptionGroupProps { + label: string, + + [props: string]: any, +} + + +export function OptionGroup({...props}: OptionGroupProps): JSX.Element { + + props.bluelibClassNames = mergeClassNames(props.bluelibClassNames, "input-optgroup") + + return ( + + ) +} diff --git a/src/components/inputs/Select.stories.jsx b/src/components/inputs/Select.stories.jsx new file mode 100644 index 0000000..b9f3298 --- /dev/null +++ b/src/components/inputs/Select.stories.jsx @@ -0,0 +1,50 @@ +import * as React from "react" +import * as ReactDOM from "react-dom" +import * as Decorators from "../../utils/Decorators" +import { Select } from "./Select" +import { Option } from "./Option" +import { OptionGroup } from "./OptionGroup" + + +export default { + component: Select, + title: "Inputs/Select", + decorators: [Decorators.Bluelib], + argTypes: { + customColor: { + control: {type: "color"}, + }, + }, +} + + +export const Default = props => ( + +) +Default.args = { + disabled: false, +} + + +export const WithGroups = props => ( + +) +WithGroups.args = { + disabled: false, +} \ No newline at end of file diff --git a/src/components/inputs/Select.tsx b/src/components/inputs/Select.tsx new file mode 100644 index 0000000..e6873c0 --- /dev/null +++ b/src/components/inputs/Select.tsx @@ -0,0 +1,43 @@ +import * as React from "react" +import * as ReactDOM from "react-dom" +import * as Types from "../../types" +import {BaseElement} from "../BaseElement" +import mergeClassNames from "classnames" + + +interface SelectProps { + disabled?: boolean, + + onChange?: (contents: string) => boolean, + value?: string, + + children: React.ReactNode, + + [props: string]: any, +} + + +export function Select({onChange, children, ...props}: SelectProps): JSX.Element { + props.bluelibClassNames = mergeClassNames(props.bluelibClassNames, "input", "input-select") + + const onChangeWrapper = React.useCallback( + + (event: React.ChangeEvent): boolean => { + const contents = event.target.value + + if(onChange) { + return onChange(contents) + } + + return false + }, + + [onChange] + ) + + return ( + + // TODO + + ) +}