Skip to content

Instantly share code, notes, and snippets.

@calderaro
Last active June 1, 2020 00:35
Show Gist options
  • Save calderaro/1c4b60582adf05f7807de5a6af41cf07 to your computer and use it in GitHub Desktop.
Save calderaro/1c4b60582adf05f7807de5a6af41cf07 to your computer and use it in GitHub Desktop.
React Inputs
import React from "react";
import DatePicker from "react-datepicker";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faQuestionCircle } from "@fortawesome/free-regular-svg-icons";
import "react-datepicker/dist/react-datepicker.css";
import styles from "./styles.module.css";
interface Props<Key> {
id: Key;
value?: Date | null;
label?: string;
placeholder?: string;
password?: boolean;
onChange?: (value: Date | null, key: Key) => void;
onHelp?: () => void;
minDate?: Date | null;
showTime?: boolean;
}
class InputDate<Key extends string> extends React.Component<Props<Key>> {
render() {
const {
id,
value,
label,
onChange,
onHelp,
minDate,
showTime,
} = this.props;
const change = (e: Date | null) => {
if (onChange) {
onChange(e, id);
}
};
return (
<div className={styles.inputContainer}>
<div className={styles.labelContainer}>
{label ? (
<label className={styles.inputLabel} htmlFor={id}>
{label}
</label>
) : null}
{onHelp ? (
<button
onClick={onHelp}
className={styles.helpButton}
type="button"
>
<FontAwesomeIcon icon={faQuestionCircle} />
</button>
) : null}
</div>
<DatePicker
showTimeSelect={showTime ? showTime : false}
timeFormat="HH:mm"
minDate={minDate}
className={styles.input}
selected={value}
timeIntervals={60}
onChange={change}
/>
</div>
);
}
}
export default InputDate;
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faEdit } from "@fortawesome/free-solid-svg-icons";
import style from "./styles.module.css";
interface Props<Key> {
value?: File | string | null;
id: Key;
onChange?: (value: File, key: Key) => void;
label?: string;
parser?: (string: string) => string;
}
interface State {
img: string | null;
}
export default class Image<Key extends string> extends React.Component<
Props<Key>,
State
> {
private input = React.createRef<HTMLInputElement>();
constructor(props: Props<Key>) {
super(props);
this.state = {
img: "",
};
}
componentDidMount() {
const { value, parser } = this.props;
if (!value) {
return this.setState({ img: "" });
}
if (value instanceof File) {
this.readFile(value);
}
if (typeof value === "string") {
this.setState({ img: parser ? parser(value) : value });
}
}
componentDidUpdate(prevProps: Props<Key>) {
const { value, parser } = this.props;
if (!value) {
return;
}
if (value instanceof File && value !== prevProps.value) {
this.readFile(value);
}
if (typeof value === "string" && value !== prevProps.value) {
this.setState({ img: parser ? parser(value) : value });
}
}
readFile = (file: File) => {
const reader = new FileReader();
reader.onload = (e) => {
const data = e.target?.result;
if (data && typeof data === "string") {
this.setState({ img: data });
}
};
reader.readAsDataURL(file);
};
openFileSelector = (e: React.MouseEvent) => {
e.stopPropagation();
this.input.current?.click();
};
change = (event: React.ChangeEvent<HTMLInputElement>) => {
const { id, onChange } = this.props;
const value = event.target.files?.[0];
if (value) {
onChange?.(value, id);
}
};
render() {
const { id, label } = this.props;
return (
<div className={style.inputContainerStyle}>
<label htmlFor={id} className={style.inputLabelStyle}>
{label}
</label>
<div className={style.imageContainer}>
{this.state.img ? (
<img className={style.image} src={this.state.img} alt="" />
) : null}
<button
type="button"
className={style.changeButton}
onClick={this.openFileSelector}
>
<FontAwesomeIcon icon={faEdit} />
</button>
</div>
<input
type="file"
style={{ display: "none" }}
id={id}
onChange={this.change}
ref={this.input}
/>
</div>
);
}
}
import React from "react";
import styles from "./styles.module.css";
export interface Change<T> {
id: string;
value: T;
}
interface SelectOption<T> {
label: string;
value: T;
}
interface Props<T> {
id: string;
value?: T;
label?: string;
placeholder?: string;
password?: boolean;
options: SelectOption<T>[];
onChange?: (change: Change<T>) => void;
className?: string;
}
export default class InputSelect<T> extends React.Component<Props<T>> {
render() {
const { id, value, label, onChange, options, placeholder, className } = this.props;
const valueIndex = options.findIndex((item) => item.value === value);
return (
<div className={styles.inputContainer + " " + className}>
{label ? (
<label className={styles.inputLabel} htmlFor={id}>
{label}
</label>
) : null}
<select<T>
id={id}
className={styles.input}
value={valueIndex}
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
if (onChange) {
onChange({ id, value: options[parseInt(e.target.value)].value });
}
}}
placeholder={placeholder}
>
{options.map((option, index) => (
<option value={index} key={option.label + index}>
{option.label}
</option>
))}
</select>
</div>
);
}
}
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faQuestionCircle } from "@fortawesome/free-regular-svg-icons";
import styles from "./styles.module.css";
interface Props<key> {
id: key;
value: string | number | string[] | undefined;
label?: string;
placeholder?: string;
password?: boolean;
onChange?: (value: string, key: key) => void;
onHelp?: () => void;
disabled?: boolean;
readOnly?: boolean;
onClick?: (event: React.MouseEvent<HTMLInputElement, MouseEvent>) => void;
onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
containerClassname?: string;
inputClassname?: string;
}
class InputText<key extends string> extends React.Component<Props<key>> {
render() {
const {
id,
value,
label,
onChange,
placeholder,
password,
onHelp,
disabled,
readOnly,
containerClassname,
inputClassname,
onFocus,
onBlur,
onClick,
} = this.props;
const change = (e: React.ChangeEvent<HTMLInputElement>) => {
if (onChange) {
onChange(e.target.value, id);
}
};
return (
<div className={styles.inputContainer + " " + (containerClassname || "")}>
<div className={styles.labelContainer}>
{label ? (
<label className={styles.inputLabel} htmlFor={id}>
{label}
</label>
) : null}
{onHelp ? (
<button
onClick={onHelp}
className={styles.helpButton}
type="button"
>
<FontAwesomeIcon icon={faQuestionCircle} />
</button>
) : null}
</div>
<input
id={id}
className={styles.input + " " + (inputClassname || "")}
value={value}
type={password ? "password" : "text"}
onChange={change}
placeholder={placeholder}
disabled={disabled}
readOnly={readOnly}
onFocus={(e) => onFocus?.(e)}
onBlur={(e) => onBlur?.(e)}
onClick={onClick}
autoComplete="off"
/>
</div>
);
}
}
export default InputText;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment