import * as React from "react"; import {ReactElement} from "react"; import {joinClassList} from "tc-shared/ui/react-elements/Helper"; const cssStyle = require("./InputField.scss"); export const ControlledBoxedInputField = (props: { prefix?: string; suffix?: string; placeholder?: string; disabled?: boolean; editable?: boolean; value?: string; rightIcon?: () => ReactElement; leftIcon?: () => ReactElement; inputBox?: () => ReactElement; /* if set the onChange and onInput will not work anymore! */ isInvalid?: boolean; className?: string; maxLength?: number, size?: "normal" | "large" | "small"; type?: "text" | "password" | "number"; onChange: (newValue?: string) => void, onEnter?: () => void, onFocus?: () => void, onBlur?: () => void, finishOnEnter?: boolean, refInput?: React.RefObject }) => { return (
{props.leftIcon ? props.leftIcon() : ""} {props.prefix ? {props.prefix} : undefined} {props.inputBox ? {props.inputBox()} : props.onChange(event.currentTarget.value)} onKeyPress={event => { if(event.key === "Enter") { if(props.finishOnEnter) { event.currentTarget.blur(); } if(props.onEnter) { props.onEnter(); } } }} /> } {props.suffix ? {props.suffix} : undefined} {props.rightIcon ? props.rightIcon() : ""}
); } export interface BoxedInputFieldProperties { prefix?: string; suffix?: string; placeholder?: string; disabled?: boolean; editable?: boolean; value?: string; defaultValue?: string; rightIcon?: () => ReactElement; leftIcon?: () => ReactElement; inputBox?: () => ReactElement; /* if set the onChange and onInput will not work anymore! */ isInvalid?: boolean; className?: string; maxLength?: number, size?: "normal" | "large" | "small"; type?: "text" | "password" | "number"; onFocus?: (event: React.FocusEvent | React.MouseEvent) => void; onBlur?: () => void; onChange?: (newValue: string) => void; onInput?: (newValue: string) => void; finishOnEnter?: boolean, } export interface BoxedInputFieldState { disabled?: boolean; defaultValue?: string; isInvalid?: boolean; value?: string; } export class BoxedInputField extends React.Component { private refInput = React.createRef(); private inputEdited = false; constructor(props) { super(props); this.state = {}; } render() { return (
this.onInputBlur()} > {this.props.leftIcon ? this.props.leftIcon() : ""} {this.props.prefix ? {this.props.prefix} : undefined} {this.props.inputBox ? {this.props.inputBox()} : this.props.onInput(event.currentTarget.value))} onKeyDown={e => this.onKeyDown(e)} maxLength={this.props.maxLength} /> } {this.props.suffix ? {this.props.suffix} : undefined} {this.props.rightIcon ? this.props.rightIcon() : ""}
) } focusInput() { this.refInput.current?.focus(); } private onKeyDown(event: React.KeyboardEvent) { this.inputEdited = true; if(event.key === "Enter") this.refInput.current?.blur(); } private onInputBlur() { if(this.props.onChange && this.inputEdited) { this.inputEdited = false; this.props.onChange(this.refInput.current.value); } if(this.props.onBlur) this.props.onBlur(); } } export const ControlledFlatInputField = (props: { type?: "text" | "password" | "number", value: string, placeholder?: string, className?: string, label?: React.ReactNode, labelType?: "static" | "floating", labelClassName?: string, labelFloatingClassName?: string, help?: React.ReactNode, helpClassName?: string, invalid?: React.ReactNode, invalidClassName?: string, disabled?: boolean, editable?: boolean, onFocus?: () => void, onBlur?: () => void, onChange?: (newValue?: string) => void, onInput?: (newValue?: string) => void, onEnter?: () => void, finishOnEnter?: boolean, }) => { const filled = props.value.length > 0; return (
{props.label ? ( ) : undefined} props.onChange && props.onChange(event.currentTarget.value)} onInput={event => props.onInput && props.onInput(event.currentTarget.value)} onKeyPress={event => { if(event.key === "Enter") { if(props.finishOnEnter) { event.currentTarget.blur(); } if(props.onEnter) { props.onEnter(); } } }} /> {props.invalid ? ( {props.invalid} ) : undefined} {props.help ? ( {props.help} ) : undefined}
); } export interface FlatInputFieldProperties { defaultValue?: string; value?: string; placeholder?: string; className?: string; label?: string | React.ReactElement; labelType?: "static" | "floating"; labelClassName?: string; labelFloatingClassName?: string; type?: "text" | "password" | "number"; help?: string | React.ReactElement; helpClassName?: string; invalidClassName?: string; disabled?: boolean; editable?: boolean; onFocus?: () => void; onBlur?: () => void; onChange?: (newValue?: string) => void; onInput?: (newValue?: string) => void; onEnter?: () => void; finishOnEnter?: boolean; } export interface FlatInputFieldState { filled: boolean; placeholder?: string; disabled?: boolean; editable?: boolean; isInvalid: boolean; invalidMessage: string | React.ReactElement; } export class FlatInputField extends React.Component { private readonly refInput = React.createRef(); constructor(props) { super(props); this.state = { isInvalid: false, filled: !!this.props.defaultValue, invalidMessage: "" } } render() { const disabled = typeof this.state.disabled === "boolean" ? this.state.disabled : typeof this.props.disabled === "boolean" ? this.props.disabled : false; const readOnly = typeof this.state.editable === "boolean" ? !this.state.editable : typeof this.props.editable === "boolean" ? !this.props.editable : false; const placeholder = typeof this.state.placeholder === "string" ? this.state.placeholder : typeof this.props.placeholder === "string" ? this.props.placeholder : undefined; const filled = this.state.filled || this.props.value?.length > 0; return (
{this.props.label ? : undefined} this.onChange()} onInput={e => this.props.onInput && this.props.onInput(e.currentTarget.value)} onKeyPress={e => { if(e.key === "Enter") { if(this.props.finishOnEnter) { this.refInput.current?.blur(); } if(this.props.onEnter) { this.props.onEnter(); } } }} /> {this.state.invalidMessage ? {this.state.invalidMessage} : undefined} {this.props.help ? {this.props.help} : undefined}
); } private onChange() { const value = this.refInput.current?.value; this.setState({ filled: !!value}); this.props.onChange && this.props.onChange(value); } value() { return this.refInput.current?.value; } setValue(value: string | undefined) { this.refInput.current.value = typeof value === "undefined" ? "" : value; this.setState({ filled: !!value }); } inputElement() : HTMLInputElement | undefined { return this.refInput.current; } focus() { this.refInput.current?.focus(); } } export const ControlledSelect = (props: { type?: "flat" | "boxed", className?: string, value: string, placeHolder?: string, label?: React.ReactNode, labelClassName?: string, help?: React.ReactNode, helpClassName?: string, invalid?: React.ReactNode, invalidClassName?: string, disabled?: boolean, onFocus?: () => void, onBlur?: () => void, onChange?: (event?: React.ChangeEvent) => void, children: React.ReactElement | React.ReactElement[] }) => { const disabled = typeof props.disabled === "boolean" ? props.disabled : false; return (
{!props.label ? undefined : } {props.invalid ? {props.invalid} : undefined} {props.help ? {props.help} : undefined}
); } export interface SelectProperties { type?: "flat" | "boxed"; refSelect?: React.RefObject, defaultValue?: string; value?: string; className?: string; label?: string | React.ReactElement; labelClassName?: string; help?: string | React.ReactElement; helpClassName?: string; invalidClassName?: string; disabled?: boolean; editable?: boolean; title?: string, onFocus?: () => void; onBlur?: () => void; onChange?: (event?: React.ChangeEvent) => void; } export interface SelectFieldState { disabled?: boolean; isInvalid: boolean; invalidMessage: string | React.ReactElement; } export class Select extends React.Component { private refSelect; constructor(props) { super(props); this.refSelect = this.props.refSelect || React.createRef(); this.state = { isInvalid: false, invalidMessage: "" } } render() { const disabled = typeof this.state.disabled === "boolean" ? this.state.disabled : typeof this.props.disabled === "boolean" ? this.props.disabled : false; return (
{this.props.label ? : undefined} {this.state.invalidMessage ? {this.state.invalidMessage} : undefined} {this.props.help ? {this.props.help} : undefined}
); } selectElement() : HTMLSelectElement | undefined { return this.refSelect.current; } focus() { this.refSelect.current?.focus(); } }