zepio/app/components/input.js

109 lines
2.5 KiB
JavaScript
Raw Normal View History

2018-12-06 07:42:30 -08:00
// @flow
/* eslint-disable max-len */
2019-01-24 06:56:49 -08:00
import React, { type Element } from 'react';
2018-12-06 07:42:30 -08:00
import styled from 'styled-components';
2019-01-24 06:56:49 -08:00
import theme from '../theme';
type Props = {
inputType?: 'input' | 'textarea',
value: string,
onChange?: string => void,
onFocus?: (SyntheticFocusEvent<HTMLInputElement>) => void,
rows?: number,
disabled?: boolean,
type?: string,
step?: number,
name?: string,
renderRight?: () => Element<*> | null,
bgColor?: string,
};
type DefaultStylesProps = PropsWithTheme<{
bgColor: ?string,
withRightElement: boolean,
}>;
// $FlowFixMe
const getDefaultStyles: ($PropertyType<Props, 'inputType'>) => Element<*> = t => styled[t]`
border-radius: ${(props: DefaultStylesProps) => props.theme.boxBorderRadius};
border: none;
background-color: ${(props: DefaultStylesProps) => props.bgColor || props.theme.colors.inputBackground};
color: ${(props: DefaultStylesProps) => props.theme.colors.text};
padding: 15px;
padding-right: ${(props: DefaultStylesProps) => (props.withRightElement ? '85px' : '15px')};
2018-12-06 07:42:30 -08:00
width: 100%;
outline: none;
font-family: ${(props: DefaultStylesProps) => props.theme.fontFamily};
2018-12-06 07:42:30 -08:00
::placeholder {
opacity: 0.5;
}
2018-12-06 07:42:30 -08:00
`;
2019-01-24 06:56:49 -08:00
const Wrapper = styled.div`
position: relative;
`;
const RightElement = styled.div`
position: absolute;
top: 15px;
right: 15px;
`;
const Input = getDefaultStyles('input');
const Textarea = getDefaultStyles('textarea');
2018-12-06 07:42:30 -08:00
2019-01-12 09:55:53 -08:00
export const InputComponent = ({
inputType,
2019-01-24 06:56:49 -08:00
bgColor,
2019-01-12 09:55:53 -08:00
onChange = () => {},
2019-01-24 06:56:49 -08:00
renderRight = () => null,
2019-01-12 09:55:53 -08:00
...props
}: Props) => {
2019-01-24 06:56:49 -08:00
const rightElement = renderRight();
const inputTypes = {
2018-12-15 07:10:39 -08:00
input: () => (
2019-01-24 06:56:49 -08:00
<Input
onChange={evt => onChange(evt.target.value)}
withRightElement={Boolean(rightElement)}
bgColor={bgColor}
data-testid='Input'
2019-01-24 06:56:49 -08:00
{...props}
/>
2018-12-15 07:10:39 -08:00
),
textarea: () => (
<Textarea
onChange={evt => onChange(evt.target.value)}
bgColor={bgColor}
data-testid='Textarea'
{...props}
/>
2018-12-15 07:10:39 -08:00
),
};
if (!Object.keys(inputTypes).find(key => key === inputType)) {
2018-12-07 05:45:20 -08:00
throw new Error(`Invalid input type: ${String(inputType)}`);
2018-12-06 07:42:30 -08:00
}
2019-01-24 06:56:49 -08:00
return (
<Wrapper>
{inputTypes[inputType || 'input']()}
{rightElement && <RightElement>{rightElement}</RightElement>}
</Wrapper>
);
2018-12-06 07:42:30 -08:00
};
InputComponent.defaultProps = {
inputType: 'input',
rows: 4,
disabled: false,
type: 'text',
name: '',
2019-01-24 06:56:49 -08:00
renderRight: () => null,
onChange: () => {},
onFocus: () => {},
step: 1,
bgColor: theme.colors.inputBackground,
2018-12-06 07:42:30 -08:00
};