feat: abstracts select component

This commit is contained in:
Jacob Fletcher
2021-11-29 13:33:38 -05:00
parent 615e3695f2
commit fa671378c7
10 changed files with 136 additions and 83 deletions

View File

@@ -1,18 +1,20 @@
import { OptionsType, GroupedOptionsType } from 'react-select';
export type Options = OptionsType<Value> | GroupedOptionsType<Value>;
export type Value = {
label: string
value: any
options?: Value[]
value: string
options?: Options
}
export type Props = {
className?: string
value?: Value | Value[],
onChange?: (value: any) => void,
onChange?: (value: Value) => void,
disabled?: boolean,
showError?: boolean,
options: OptionsType<Value> | GroupedOptionsType<Value>
options: Options
isMulti?: boolean,
isDisabled?: boolean
onInputChange?: (val: string) => void

View File

@@ -0,0 +1,87 @@
import React from 'react';
import Label from '../../Label';
import Error from '../../Error';
import FieldDescription from '../../FieldDescription';
import { SelectField } from '../../../../../fields/config/types';
import { Description } from '../../FieldDescription/types';
import ReactSelect from '../../../elements/ReactSelect';
import { Value as ReactSelectValue, Options as ReactSelectOptions } from '../../../elements/ReactSelect/types';
// import { FieldType } from '../../useField/types';
import './index.scss';
export type SelectInputProps = Omit<SelectField, 'type' | 'value'> & {
showError: boolean
errorMessage?: string
readOnly?: boolean
path?: string
required?: boolean
value?: string
description?: Description
onChange?: (value: ReactSelectValue) => void
style?: React.CSSProperties
width?: string
hasMany?: boolean
options?: ReactSelectOptions
}
const SelectInput: React.FC<SelectInputProps> = (props) => {
const {
showError,
errorMessage,
readOnly,
path,
label,
required,
value,
onChange,
description,
style,
width,
options,
hasMany,
} = props;
const classes = [
'field-type',
'select',
showError && 'error',
readOnly && 'read-only',
].filter(Boolean).join(' ');
const selectedOption = options.find((option) => option.value === value);
return (
<div
className={classes}
style={{
...style,
width,
}}
>
<Error
showError={showError}
message={errorMessage}
/>
<Label
htmlFor={path}
label={label}
required={required}
/>
<ReactSelect
onChange={onChange}
value={selectedOption}
showError={showError}
isDisabled={readOnly}
options={options}
isMulti={hasMany}
/>
<FieldDescription
value={value}
description={description}
/>
</div>
);
};
export default SelectInput;

View File

@@ -1,17 +1,10 @@
import React, { useCallback, useState, useEffect } from 'react';
import React, { useCallback, useState } from 'react';
import withCondition from '../../withCondition';
import ReactSelect from '../../../elements/ReactSelect';
import useField from '../../useField';
import Label from '../../Label';
import Error from '../../Error';
import FieldDescription from '../../FieldDescription';
import { select } from '../../../../../fields/validations';
import { Option } from '../../../../../fields/config/types';
import { Props, Option as ReactSelectOption } from './types';
import './index.scss';
const baseClass = 'select';
import { Props, ReactSelectOption } from './types';
import SelectInput from './Input';
const formatOptions = (options: Option[]): ReactSelectOption[] => options.map((option) => {
if (typeof option === 'object' && option.value) {
@@ -41,7 +34,7 @@ const Select: React.FC<Props> = (props) => {
condition,
} = {},
value: valueFromProps,
onChange: onChangeFromProps
onChange: onChangeFromProps,
} = props;
const path = pathFromProps || name;
@@ -87,15 +80,8 @@ const Select: React.FC<Props> = (props) => {
readOnly,
hasMany,
onChangeFromProps,
setValue
])
const classes = [
'field-type',
baseClass,
showError && 'error',
readOnly && `${baseClass}--read-only`,
].filter(Boolean).join(' ');
setValue,
]);
let valueToRender;
@@ -108,35 +94,18 @@ const Select: React.FC<Props> = (props) => {
}
return (
<div
className={classes}
style={{
...style,
width,
}}
>
<Error
showError={showError}
message={errorMessage}
/>
<Label
htmlFor={path}
label={label}
required={required}
/>
<ReactSelect
onChange={onChange}
value={valueToRender}
showError={showError}
isDisabled={readOnly}
options={options}
isMulti={hasMany}
/>
<FieldDescription
value={value}
description={description}
/>
</div>
<SelectInput
onChange={onChange}
value={valueToRender}
name={name}
options={options}
label={label}
showError={showError}
errorMessage={errorMessage}
description={description}
style={style}
width={width}
/>
);
};

View File

@@ -1,10 +1,5 @@
import { SelectField } from '../../../../../fields/config/types';
export type Option = {
label: string
value: any
}
export type Props = Omit<SelectField, 'type'> & {
path?: string
}

View File

@@ -5,8 +5,6 @@ import { text } from '../../../../../fields/validations';
import { Props } from './types';
import TextInput from './Input';
import './index.scss';
const Text: React.FC<Props> = (props) => {
const {
path: pathFromProps,

View File

@@ -77,7 +77,7 @@ const useField = <T extends unknown>(options: Options): FieldType<T> => {
ignoreWhileFlattening,
initialValue,
stringify,
condition
condition,
]);
// Method to return from `useField`, used to
@@ -91,12 +91,11 @@ const useField = <T extends unknown>(options: Options): FieldType<T> => {
setModified(true);
}
}
setInternalValue(val);
}, [
setModified,
modified,
ignoreWhileFlattening
ignoreWhileFlattening,
]);
useEffect(() => {
@@ -116,7 +115,7 @@ const useField = <T extends unknown>(options: Options): FieldType<T> => {
}, [
valueToSend,
sendField,
field
field,
]);
return {

View File

@@ -48,13 +48,10 @@ export type Labels = {
export type Validate<T = any> = (value?: T, options?: any) => string | true | Promise<string | true>;
export type OptionObject = {
export type Option = {
label: string
value: string
}
export type Option = OptionObject | string
export interface FieldBase {
name: string;
label?: string | false;