import React, { useState } from 'react';
import ImmutablePureComponent from 'react-immutable-pure-component';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { v4 as uuidv4 } from 'uuid';
import { SketchPicker } from 'react-color';
import Overlay from 'react-overlays/lib/Overlay';
import { isMobile } from '../../is_mobile';
import detectPassiveEvents from 'detect-passive-events';
const FormPropTypes = {
label: PropTypes.oneOfType([
PropTypes.string,
PropTypes.object,
PropTypes.node,
]),
};
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
export const InputContainer = (props) => {
const containerClass = classNames('input', {
'with_label': props.label,
'required': props.required,
'boolean': props.type === 'checkbox',
}, props.extraClass);
return (
{props.children}
{props.hint && {props.hint}}
);
};
InputContainer.propTypes = {
label: FormPropTypes.label,
hint: PropTypes.node,
required: PropTypes.bool,
type: PropTypes.string,
children: PropTypes.node,
extraClass: PropTypes.string,
};
export const LabelInputContainer = ({ label, children, ...props }) => {
const [id] = useState(uuidv4());
const childrenWithProps = React.Children.map(children, child => (
React.cloneElement(child, { id: id, key: id })
));
return (
{childrenWithProps}
);
};
LabelInputContainer.propTypes = {
label: FormPropTypes.label.isRequired,
children: PropTypes.node,
};
export const LabelInput = ({ label, dispatch, ...props }) => (
);
LabelInput.propTypes = {
label: FormPropTypes.label.isRequired,
dispatch: PropTypes.func,
};
export const LabelTextarea = ({ label, dispatch, ...props }) => (
);
LabelTextarea.propTypes = {
label: FormPropTypes.label.isRequired,
dispatch: PropTypes.func,
};
export class SimpleInput extends ImmutablePureComponent {
static propTypes = {
label: FormPropTypes.label,
hint: PropTypes.node,
}
render() {
const { hint, ...props } = this.props;
const Input = this.props.label ? LabelInput : 'input';
return (
);
}
}
export class SimpleTextarea extends ImmutablePureComponent {
static propTypes = {
label: FormPropTypes.label,
hint: PropTypes.node,
}
render() {
const { hint, ...props } = this.props;
const Input = this.props.label ? LabelTextarea : 'textarea';
return (
);
}
}
export class SimpleForm extends ImmutablePureComponent {
static propTypes = {
children: PropTypes.node,
};
static defaultProps = {
acceptCharset: 'UTF-8',
onSubmit: e => {},
};
onSubmit = e => {
this.props.onSubmit(e);
e.preventDefault();
}
render() {
const { children, onSubmit, ...props } = this.props;
return (
);
}
}
export const FieldsGroup = ({ children }) => (
{children}
);
FieldsGroup.propTypes = {
children: PropTypes.node,
};
export const Checkbox = props => (
);
export class RadioGroup extends ImmutablePureComponent {
static propTypes = {
label: FormPropTypes.label,
children: PropTypes.node,
}
render() {
const { label, children, onChange } = this.props;
const childrenWithProps = React.Children.map(children, child =>
React.cloneElement(child, { onChange })
);
return (
);
}
}
export class ColorPicker extends React.PureComponent {
static propTypes = {
style: PropTypes.object,
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
onClose: PropTypes.func,
}
handleDocumentClick = e => {
if (this.node && !this.node.contains(e.target)) {
this.props.onClose();
}
}
componentDidMount() {
document.addEventListener('click', this.handleDocumentClick, false);
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleDocumentClick, false);
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
}
setRef = c => {
this.node = c;
}
render() {
const { style, value, onChange } = this.props;
let margin_left_picker = isMobile(window.innerWidth) ? '20px' : '12px';
return (
);
}
}
export class ColorWithPicker extends ImmutablePureComponent {
static propTypes = {
buttonId: PropTypes.string.isRequired,
label: FormPropTypes.label,
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
}
onToggle = (e) => {
if (!e.key || e.key === 'Enter') {
if (this.state.active) {
this.onHidePicker();
} else {
this.onShowPicker(e);
}
}
}
state = {
active: false,
placement: null,
}
onHidePicker = () => {
this.setState({ active: false });
}
onShowPicker = ({ target }) => {
this.setState({ active: true });
this.setState({ placement: isMobile(window.innerWidth) ? 'bottom' : 'right' });
}
render() {
const { buttonId, label, value, onChange } = this.props;
const { active, placement } = this.state;
return (
);
}
}
export class RadioItem extends ImmutablePureComponent {
static propTypes = {
label: FormPropTypes.label,
hint: PropTypes.node,
value: PropTypes.string.isRequired,
checked: PropTypes.bool.isRequired,
onChange: PropTypes.func,
dispatch: PropTypes.func,
}
static defaultProps = {
checked: false,
}
state = {
id: uuidv4(),
}
render() {
const { label, hint, dispatch, ...props } = this.props;
const { id } = this.state;
return (
);
}
}
export class SelectDropdown extends ImmutablePureComponent {
static propTypes = {
label: FormPropTypes.label,
items: PropTypes.object.isRequired,
}
render() {
const { label, items, ...props } = this.props;
const optionElems = Object.keys(items).map(item => (
));
const selectElem = ;
return label ? (
{selectElem}
) : selectElem;
}
}
export const TextInput = props => (
);
export const FileChooser = props => (
);
FileChooser.defaultProps = {
accept: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
};
export const FileChooserLogo = props => (
);
FileChooserLogo.defaultProps = {
accept: ['image/svg', 'image/png'],
};