From fa671378c7282cda1ed6f46340a53622e3bc96dc Mon Sep 17 00:00:00 2001 From: Jacob Fletcher Date: Mon, 29 Nov 2021 13:33:38 -0500 Subject: [PATCH] feat: abstracts select component --- .../components/fields/Select/Field/index.tsx | 32 ++++--- .../components/fields/Text/Field/index.tsx | 2 +- demo/collections/CustomComponents/index.ts | 2 +- .../components/elements/ReactSelect/types.ts | 10 ++- .../forms/field-types/Select/Input.tsx | 87 +++++++++++++++++++ .../forms/field-types/Select/index.tsx | 67 ++++---------- .../forms/field-types/Select/types.ts | 5 -- .../forms/field-types/Text/index.tsx | 2 - src/admin/components/forms/useField/index.tsx | 7 +- src/fields/config/types.ts | 5 +- 10 files changed, 136 insertions(+), 83 deletions(-) create mode 100644 src/admin/components/forms/field-types/Select/Input.tsx diff --git a/demo/collections/CustomComponents/components/fields/Select/Field/index.tsx b/demo/collections/CustomComponents/components/fields/Select/Field/index.tsx index e3c35481ef5..ef957b1c271 100644 --- a/demo/collections/CustomComponents/components/fields/Select/Field/index.tsx +++ b/demo/collections/CustomComponents/components/fields/Select/Field/index.tsx @@ -1,5 +1,5 @@ -import React, { useCallback, useState } from 'react'; -import SelectInput from '../../../../../../../src/admin/components/forms/field-types/Select'; +import React, { useCallback } from 'react'; +import SelectInput from '../../../../../../../src/admin/components/forms/field-types/Select/Input'; import { Props as SelectFieldType } from '../../../../../../../src/admin/components/forms/field-types/Select/types'; import useField from '../../../../../../../src/admin/components/forms/useField'; @@ -8,38 +8,43 @@ const Select: React.FC = (props) => { path, name, label, - options + options, } = props; const { + showError, value, - setValue + setValue, } = useField({ - path + path, }); - const onChange = useCallback((incomingValue) => { + const onChange = useCallback((incomingOption) => { + const { value: incomingValue } = incomingOption; + const sendToCRM = async () => { try { const req = await fetch('https://fake-crm.com', { method: 'post', body: JSON.stringify({ - someKey: incomingValue - }) + someKey: incomingValue, + }), }); const res = await req.json(); if (res.ok) { - console.log('Successfully synced to CRM.') + console.log('Successfully synced to CRM.'); // eslint-disable-line no-console } } catch (e) { console.error(e); } - } + }; sendToCRM(); - setValue(incomingValue) - }, []) + setValue(incomingValue); + }, [ + setValue, + ]); return ( = (props) => { options={options} value={value as string} onChange={onChange} + showError={showError} /> - ) + ); }; export default Select; diff --git a/demo/collections/CustomComponents/components/fields/Text/Field/index.tsx b/demo/collections/CustomComponents/components/fields/Text/Field/index.tsx index 371e8c4876f..d72f4714059 100644 --- a/demo/collections/CustomComponents/components/fields/Text/Field/index.tsx +++ b/demo/collections/CustomComponents/components/fields/Text/Field/index.tsx @@ -30,7 +30,7 @@ const Text: React.FC = (props) => { return ( | GroupedOptionsType; + 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 | GroupedOptionsType + options: Options isMulti?: boolean, isDisabled?: boolean onInputChange?: (val: string) => void diff --git a/src/admin/components/forms/field-types/Select/Input.tsx b/src/admin/components/forms/field-types/Select/Input.tsx new file mode 100644 index 00000000000..4ebddb54202 --- /dev/null +++ b/src/admin/components/forms/field-types/Select/Input.tsx @@ -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 & { + 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 = (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 ( +
+ +
+ ); +}; + +export default SelectInput; diff --git a/src/admin/components/forms/field-types/Select/index.tsx b/src/admin/components/forms/field-types/Select/index.tsx index 9f6e676f77b..ad151e30e06 100644 --- a/src/admin/components/forms/field-types/Select/index.tsx +++ b/src/admin/components/forms/field-types/Select/index.tsx @@ -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) => { condition, } = {}, value: valueFromProps, - onChange: onChangeFromProps + onChange: onChangeFromProps, } = props; const path = pathFromProps || name; @@ -87,15 +80,8 @@ const Select: React.FC = (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) => { } return ( -
- -
+ ); }; diff --git a/src/admin/components/forms/field-types/Select/types.ts b/src/admin/components/forms/field-types/Select/types.ts index 3da18f9d5ca..38b35a15177 100644 --- a/src/admin/components/forms/field-types/Select/types.ts +++ b/src/admin/components/forms/field-types/Select/types.ts @@ -1,10 +1,5 @@ import { SelectField } from '../../../../../fields/config/types'; -export type Option = { - label: string - value: any -} - export type Props = Omit & { path?: string } diff --git a/src/admin/components/forms/field-types/Text/index.tsx b/src/admin/components/forms/field-types/Text/index.tsx index f1705d35f81..7b2b3d18c99 100644 --- a/src/admin/components/forms/field-types/Text/index.tsx +++ b/src/admin/components/forms/field-types/Text/index.tsx @@ -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) => { const { path: pathFromProps, diff --git a/src/admin/components/forms/useField/index.tsx b/src/admin/components/forms/useField/index.tsx index 5cee2de4a2f..d87b7c5547c 100644 --- a/src/admin/components/forms/useField/index.tsx +++ b/src/admin/components/forms/useField/index.tsx @@ -77,7 +77,7 @@ const useField = (options: Options): FieldType => { ignoreWhileFlattening, initialValue, stringify, - condition + condition, ]); // Method to return from `useField`, used to @@ -91,12 +91,11 @@ const useField = (options: Options): FieldType => { setModified(true); } } - setInternalValue(val); }, [ setModified, modified, - ignoreWhileFlattening + ignoreWhileFlattening, ]); useEffect(() => { @@ -116,7 +115,7 @@ const useField = (options: Options): FieldType => { }, [ valueToSend, sendField, - field + field, ]); return { diff --git a/src/fields/config/types.ts b/src/fields/config/types.ts index a8fb9caeba7..d7f6e976679 100644 --- a/src/fields/config/types.ts +++ b/src/fields/config/types.ts @@ -48,13 +48,10 @@ export type Labels = { export type Validate = (value?: T, options?: any) => string | true | Promise; -export type OptionObject = { +export type Option = { label: string value: string } - -export type Option = OptionObject | string - export interface FieldBase { name: string; label?: string | false;