2020-06-10 16:13:56 +00:00
|
|
|
import * as React from "react";
|
|
|
|
import {ReactElement} from "react";
|
2020-11-07 12:16:07 +00:00
|
|
|
import {AST_Export} from "terser";
|
2020-06-10 16:13:56 +00:00
|
|
|
|
|
|
|
const cssStyle = require("./InputField.scss");
|
|
|
|
|
|
|
|
export interface BoxedInputFieldProperties {
|
|
|
|
prefix?: string;
|
2020-08-10 22:25:20 +00:00
|
|
|
suffix?: string;
|
|
|
|
|
2020-06-10 16:13:56 +00:00
|
|
|
placeholder?: string;
|
|
|
|
|
|
|
|
disabled?: boolean;
|
|
|
|
editable?: boolean;
|
|
|
|
|
2020-07-20 17:08:13 +00:00
|
|
|
value?: string;
|
2020-06-10 16:13:56 +00:00
|
|
|
defaultValue?: string;
|
|
|
|
|
|
|
|
rightIcon?: () => ReactElement;
|
|
|
|
leftIcon?: () => ReactElement;
|
|
|
|
inputBox?: () => ReactElement; /* if set the onChange and onInput will not work anymore! */
|
|
|
|
|
|
|
|
isInvalid?: boolean;
|
|
|
|
|
|
|
|
className?: string;
|
|
|
|
|
|
|
|
size?: "normal" | "large" | "small";
|
|
|
|
|
2020-12-18 18:18:01 +00:00
|
|
|
onFocus?: (event: React.FocusEvent | React.MouseEvent) => void;
|
2020-06-10 16:13:56 +00:00
|
|
|
onBlur?: () => void;
|
|
|
|
|
|
|
|
onChange?: (newValue: string) => void;
|
|
|
|
onInput?: (newValue: string) => void;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface BoxedInputFieldState {
|
|
|
|
disabled?: boolean;
|
|
|
|
defaultValue?: string;
|
|
|
|
isInvalid?: boolean;
|
|
|
|
value?: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
export class BoxedInputField extends React.Component<BoxedInputFieldProperties, BoxedInputFieldState> {
|
|
|
|
private refInput = React.createRef<HTMLInputElement>();
|
|
|
|
private inputEdited = false;
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
this.state = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
draggable={false}
|
|
|
|
className={
|
2020-06-15 14:56:05 +00:00
|
|
|
cssStyle.containerBoxed + " " +
|
2020-07-20 17:08:13 +00:00
|
|
|
cssStyle["size-" + (this.props.size || "normal")] + " " +
|
2020-06-10 16:13:56 +00:00
|
|
|
(this.state.disabled || this.props.disabled ? cssStyle.disabled : "") + " " +
|
|
|
|
(this.state.isInvalid || this.props.isInvalid ? cssStyle.isInvalid : "") + " " +
|
2020-07-20 17:08:13 +00:00
|
|
|
(typeof this.props.editable !== "boolean" || this.props.editable ? cssStyle.editable : "") + " " +
|
2020-06-10 16:13:56 +00:00
|
|
|
(this.props.leftIcon ? "" : cssStyle.noLeftIcon) + " " +
|
|
|
|
(this.props.rightIcon ? "" : cssStyle.noRightIcon) + " " +
|
|
|
|
this.props.className
|
|
|
|
}
|
|
|
|
|
|
|
|
onFocus={this.props.onFocus}
|
|
|
|
onBlur={() => this.onInputBlur()}
|
|
|
|
>
|
|
|
|
{this.props.leftIcon ? this.props.leftIcon() : ""}
|
|
|
|
{this.props.prefix ? <a key={"prefix"} className={cssStyle.prefix}>{this.props.prefix}</a> : undefined}
|
|
|
|
{this.props.inputBox ?
|
|
|
|
<span key={"custom-input"} className={cssStyle.inputBox + " " + (this.props.editable ? cssStyle.editable : "")} onClick={this.props.onFocus}>{this.props.inputBox()}</span> :
|
|
|
|
<input key={"input"}
|
|
|
|
ref={this.refInput}
|
2020-07-20 17:08:13 +00:00
|
|
|
value={this.props.value || this.state.value}
|
2020-06-10 16:13:56 +00:00
|
|
|
defaultValue={this.state.defaultValue || this.props.defaultValue}
|
|
|
|
placeholder={this.props.placeholder}
|
2020-07-20 17:08:13 +00:00
|
|
|
readOnly={typeof this.props.editable === "boolean" ? !this.props.editable : false}
|
2020-06-10 16:13:56 +00:00
|
|
|
disabled={this.state.disabled || this.props.disabled}
|
|
|
|
onInput={this.props.onInput && (event => this.props.onInput(event.currentTarget.value))}
|
|
|
|
onKeyDown={e => this.onKeyDown(e)}
|
|
|
|
/>}
|
2020-08-10 22:25:20 +00:00
|
|
|
{this.props.suffix ? <a key={"suffix"} className={cssStyle.suffix}>{this.props.suffix}</a> : undefined}
|
2020-06-10 16:13:56 +00:00
|
|
|
{this.props.rightIcon ? this.props.rightIcon() : ""}
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
2020-06-15 14:56:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface FlatInputFieldProperties {
|
|
|
|
defaultValue?: string;
|
2020-09-17 21:06:02 +00:00
|
|
|
value?: string;
|
|
|
|
|
2020-06-15 14:56:05 +00:00
|
|
|
placeholder?: string;
|
|
|
|
|
|
|
|
className?: string;
|
|
|
|
|
|
|
|
label?: string | React.ReactElement;
|
|
|
|
labelType?: "static" | "floating";
|
|
|
|
labelClassName?: string;
|
|
|
|
labelFloatingClassName?: string;
|
|
|
|
|
|
|
|
help?: string | React.ReactElement;
|
|
|
|
helpClassName?: string;
|
|
|
|
|
|
|
|
invalidClassName?: string;
|
|
|
|
|
|
|
|
disabled?: boolean;
|
|
|
|
editable?: boolean;
|
|
|
|
|
|
|
|
onFocus?: () => void;
|
|
|
|
onBlur?: () => void;
|
|
|
|
|
|
|
|
onChange?: (newValue?: string) => void;
|
|
|
|
onInput?: (newValue?: string) => 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<FlatInputFieldProperties, FlatInputFieldState> {
|
|
|
|
private refInput = React.createRef<HTMLInputElement>();
|
|
|
|
|
|
|
|
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;
|
2020-09-17 21:06:02 +00:00
|
|
|
|
2020-06-15 14:56:05 +00:00
|
|
|
return (
|
|
|
|
<div className={cssStyle.containerFlat + " " + (this.state.isInvalid ? cssStyle.isInvalid : "") + " " + (this.state.filled ? cssStyle.isFilled : "") + " " + (this.props.className || "")}>
|
|
|
|
{this.props.label ?
|
|
|
|
<label className={
|
|
|
|
cssStyle["type-" + (this.props.labelType || "static")] + " " +
|
|
|
|
(this.props.labelClassName || "") + " " +
|
|
|
|
(this.props.labelFloatingClassName && this.state.filled ? this.props.labelFloatingClassName : "")}>{this.props.label}</label> : undefined}
|
|
|
|
<input
|
|
|
|
defaultValue={this.props.defaultValue}
|
2020-09-17 21:06:02 +00:00
|
|
|
value={this.props.value}
|
|
|
|
|
2020-06-15 14:56:05 +00:00
|
|
|
type={"text"}
|
|
|
|
ref={this.refInput}
|
|
|
|
readOnly={readOnly}
|
|
|
|
disabled={disabled}
|
|
|
|
placeholder={placeholder}
|
|
|
|
|
|
|
|
onFocus={this.props.onFocus}
|
|
|
|
onBlur={this.props.onBlur}
|
|
|
|
onChange={() => this.onChange()}
|
|
|
|
onInput={e => this.props.onInput && this.props.onInput(e.currentTarget.value)}
|
|
|
|
onKeyPress={e => this.props.finishOnEnter && e.key === "Enter" && this.refInput.current?.blur()}
|
|
|
|
/>
|
|
|
|
{this.state.invalidMessage ? <small className={cssStyle.invalidFeedback + " " + (this.props.invalidClassName || "")}>{this.state.invalidMessage}</small> : undefined}
|
|
|
|
{this.props.help ? <small className={cssStyle.help + " " + (this.props.helpClassName || "")}>{this.props.help}</small> : undefined}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2020-06-15 15:02:28 +00:00
|
|
|
this.setState({ filled: !!value });
|
2020-06-15 14:56:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inputElement() : HTMLInputElement | undefined {
|
|
|
|
return this.refInput.current;
|
|
|
|
}
|
|
|
|
|
|
|
|
focus() {
|
|
|
|
this.refInput.current?.focus();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-07 12:16:07 +00:00
|
|
|
export interface SelectProperties {
|
|
|
|
type?: "flat" | "boxed";
|
|
|
|
|
2020-06-15 14:56:05 +00:00
|
|
|
defaultValue?: string;
|
|
|
|
value?: string;
|
|
|
|
|
|
|
|
className?: string;
|
|
|
|
|
|
|
|
label?: string | React.ReactElement;
|
|
|
|
labelClassName?: string;
|
|
|
|
|
|
|
|
help?: string | React.ReactElement;
|
|
|
|
helpClassName?: string;
|
|
|
|
|
|
|
|
invalidClassName?: string;
|
|
|
|
|
|
|
|
disabled?: boolean;
|
|
|
|
editable?: boolean;
|
|
|
|
|
|
|
|
onFocus?: () => void;
|
|
|
|
onBlur?: () => void;
|
|
|
|
|
|
|
|
onChange?: (event?: React.ChangeEvent<HTMLSelectElement>) => void;
|
|
|
|
}
|
|
|
|
|
2020-11-07 12:16:07 +00:00
|
|
|
export interface SelectFieldState {
|
2020-06-15 14:56:05 +00:00
|
|
|
disabled?: boolean;
|
|
|
|
|
|
|
|
isInvalid: boolean;
|
|
|
|
invalidMessage: string | React.ReactElement;
|
|
|
|
}
|
|
|
|
|
2020-11-07 12:16:07 +00:00
|
|
|
export class Select extends React.Component<SelectProperties, SelectFieldState> {
|
2020-06-15 14:56:05 +00:00
|
|
|
private refSelect = React.createRef<HTMLSelectElement>();
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
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 (
|
2020-11-07 12:16:07 +00:00
|
|
|
<div className={(this.props.type === "boxed" ? cssStyle.containerBoxed : cssStyle.containerFlat) + " " + (this.state.isInvalid ? cssStyle.isInvalid : "") + " " + (this.props.className || "") + " " + cssStyle.noLeftIcon + " " + cssStyle.noRightIcon}>
|
2020-06-15 14:56:05 +00:00
|
|
|
{this.props.label ?
|
|
|
|
<label className={cssStyle["type-static"] + " " + (this.props.labelClassName || "")}>{this.props.label}</label> : undefined}
|
|
|
|
<select
|
|
|
|
ref={this.refSelect}
|
|
|
|
|
|
|
|
value={this.props.value}
|
|
|
|
defaultValue={this.props.defaultValue}
|
|
|
|
disabled={disabled}
|
|
|
|
|
|
|
|
onFocus={this.props.onFocus}
|
|
|
|
onBlur={this.props.onBlur}
|
|
|
|
onChange={e => this.props.onChange && this.props.onChange(e)}
|
|
|
|
>
|
|
|
|
{this.props.children}
|
|
|
|
</select>
|
|
|
|
{this.state.invalidMessage ? <small className={cssStyle.invalidFeedback + " " + (this.props.invalidClassName || "")}>{this.state.invalidMessage}</small> : undefined}
|
|
|
|
{this.props.help ? <small className={cssStyle.help + " " + (this.props.helpClassName || "")}>{this.props.help}</small> : undefined}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
selectElement() : HTMLSelectElement | undefined {
|
|
|
|
return this.refSelect.current;
|
|
|
|
}
|
|
|
|
|
|
|
|
focus() {
|
|
|
|
this.refSelect.current?.focus();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|