From ac3e76209c88f48acefc0508a7fb5b6d199dfe6e Mon Sep 17 00:00:00 2001 From: Noah Overcash Date: Thu, 21 Dec 2023 14:33:21 -0500 Subject: [PATCH 1/2] refine inputs typings --- README.md | 6 ++-- components/lib/Checkbox/Checkbox.d.ts | 12 +++----- components/lib/Datepicker/Datepicker.d.ts | 12 ++------ .../lib/MultiSelection/MultiSelection.d.ts | 30 +++++++------------ components/lib/RadioButton/RadioButton.d.ts | 8 ++--- components/lib/Select/Select.d.ts | 8 ++--- components/lib/TextField/TextField.d.ts | 10 +++---- 7 files changed, 30 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 6c97d0f..29d9684 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,11 @@ This is a set of TypeScript typings for the [Stripes](https://github.com/folio-o `react-final-form` support is currently experimental. Stripes has form fields which can optionally be controlled via react-final-form or left uncontrolled. However, in RFF, [FieldRenderProps](https://github.com/final-form/react-final-form/blob/09ccc607b3e8843addd7cbde7a84a82866587000/typescript/index.d.ts#L43-L50) are defined problematically: -- `input` and `meta` are **required**, whereas Stripes should have them be optional, meaning we cannot require them; +- `input` and `meta` are **required**, whereas Stripes should have them be optional (for non-RFF use), meaning we cannot require them; - the `` definition requires the `component` to require `input` and `meta`, meaning we cannot leave them optional; and - the props also allow any other prop to be passed through and overwrites their types as `any`, erasing any specific component typings. -With this current situation, there's not too much we can do to make everyone happy. Therefore, this aspect of the typings is experimental and may change in the future. +With this current situation, there's not too much we can do to make everyone happy. Therefore, **this aspect of the typings is experimental and may change in the future**. Currently, the recommended way to use Stripes components in react-final-form without sacrificing typings is via the render prop or as a child: @@ -30,7 +30,6 @@ import { TextField } from '@folio/stripes/components'; name="foo" render={({ input, meta }) => ( {({ input, meta }) => ( { +export interface CheckboxProps extends AriaAttributes, InputHTMLAttributes { /** If the field should automatically focus on mount */ autoFocus?: boolean; /** If the checkbox is checked */ @@ -34,9 +32,7 @@ export interface CheckboxProps /** Add a class to the inner input */ innerClass?: string; /** Reference to the inner input */ - inputRef?: - | RefObject - | ((node: HTMLInputElement | null) => void); + inputRef?: RefObject | ((node: HTMLInputElement | null) => void); /** The checkbox's label */ label?: string; /** Add a class to the label */ @@ -61,8 +57,8 @@ export interface CheckboxProps warning?: string | ReactNode; // TODO: reference react-final-form FieldRenderProps - input: any; - meta: any; + input?: any; + meta?: any; } /** diff --git a/components/lib/Datepicker/Datepicker.d.ts b/components/lib/Datepicker/Datepicker.d.ts index 2804443..69f0664 100644 --- a/components/lib/Datepicker/Datepicker.d.ts +++ b/components/lib/Datepicker/Datepicker.d.ts @@ -1,12 +1,6 @@ import { Moment } from 'moment'; import Popper from 'popper.js'; -import { - AriaAttributes, - Component, - FocusEventHandler, - ReactNode, - RefObject, -} from 'react'; +import { AriaAttributes, Component, FocusEventHandler, ReactNode, RefObject } from 'react'; import { Merge } from 'type-fest'; import { TextFieldProps } from '../TextField'; @@ -72,8 +66,8 @@ export interface DatepickerProps extends AriaAttributes { outputFormatter?: (date: Moment) => string; // TODO: reference react-final-form FieldRenderProps - input: any; - meta: any; + input?: any; + meta?: any; } /** diff --git a/components/lib/MultiSelection/MultiSelection.d.ts b/components/lib/MultiSelection/MultiSelection.d.ts index 5131314..cc7da21 100644 --- a/components/lib/MultiSelection/MultiSelection.d.ts +++ b/components/lib/MultiSelection/MultiSelection.d.ts @@ -13,9 +13,7 @@ export interface MultiSelectionDefaultOptionType { * Props each action may accept * @see https://github.com/folio-org/stripes-components/tree/master/lib/MultiSelection#actions */ -export interface MultiSelectionActionItemProps< - OptionType = MultiSelectionDefaultOptionType -> { +export interface MultiSelectionActionItemProps { /** The search term */ filterValue: string; /** If this search was an exact match */ @@ -24,9 +22,7 @@ export interface MultiSelectionActionItemProps< renderedItems: ReadonlyArray; } -export interface MultiSelectionProps< - OptionType = MultiSelectionDefaultOptionType -> { +export interface MultiSelectionProps { /** * Custom actions, such as a "New" row * @see https://github.com/folio-org/stripes-components/tree/master/lib/MultiSelection#actions @@ -59,13 +55,10 @@ export interface MultiSelectionProps< /** A custom filter function, either directly gives results or does something async */ filter?: ( filterText: string | undefined, - list: OptionType[] + list: OptionType[], ) => { renderedItems: OptionType[]; exactMatch?: boolean } | Promise; /** A custom formatter to render each option */ - formatter?: (props: { - option: OptionType; - searchTerm: string | undefined; - }) => ReactNode; + formatter?: (props: { option: OptionType; searchTerm: string | undefined }) => ReactNode; /** Adds a custom ID to the control */ id?: string; /** If true, adds valid styles to the field */ @@ -95,16 +88,13 @@ export interface MultiSelectionProps< /** The selected objects */ value?: OptionType[]; /** Same as {@link formatter}, `formatter` should probably be used instead. */ - valueFormatter?: ( - option: OptionType, - searchTerm: string | undefined - ) => ReactNode; + valueFormatter?: (option: OptionType, searchTerm: string | undefined) => ReactNode; /** Inline feedback for the user indicating a validation warning */ warning?: ReactNode; // TODO: reference react-final-form FieldRenderProps - input: any; - meta: any; + input?: any; + meta?: any; } /** @@ -127,6 +117,6 @@ export interface MultiSelectionProps< * dataOptions={optionList} * /> */ -export default class MultiSelection< - OptionType = MultiSelectionDefaultOptionType -> extends Component> {} +export default class MultiSelection extends Component< + MultiSelectionProps +> {} diff --git a/components/lib/RadioButton/RadioButton.d.ts b/components/lib/RadioButton/RadioButton.d.ts index 73cae24..c87eb79 100644 --- a/components/lib/RadioButton/RadioButton.d.ts +++ b/components/lib/RadioButton/RadioButton.d.ts @@ -7,9 +7,7 @@ import { InputHTMLAttributes, } from 'react'; -export interface RadioButtonProps - extends AriaAttributes, - InputHTMLAttributes { +export interface RadioButtonProps extends AriaAttributes, InputHTMLAttributes { /** If the field should automatically focus on mount */ autoFocus?: boolean; /** If the radio button is centered */ @@ -54,8 +52,8 @@ export interface RadioButtonProps warning?: string; // TODO: reference react-final-form FieldRenderProps - input: any; - meta: any; + input?: any; + meta?: any; } /** diff --git a/components/lib/Select/Select.d.ts b/components/lib/Select/Select.d.ts index 55e2ac9..42b64a9 100644 --- a/components/lib/Select/Select.d.ts +++ b/components/lib/Select/Select.d.ts @@ -60,8 +60,8 @@ export interface SelectBaseProps { warning?: ReactNode; // TODO: reference react-final-form FieldRenderProps - input: any; - meta: any; + input?: any; + meta?: any; } export type SelectProps = RequireExactlyOne< @@ -91,6 +91,4 @@ export type SelectProps = RequireExactlyOne< * ]} * /> */ -export default class Select extends Component< - SelectProps -> {} +export default class Select extends Component> {} diff --git a/components/lib/TextField/TextField.d.ts b/components/lib/TextField/TextField.d.ts index 7ae678a..2a08480 100644 --- a/components/lib/TextField/TextField.d.ts +++ b/components/lib/TextField/TextField.d.ts @@ -91,8 +91,8 @@ export interface TextFieldProps warning?: ReactNode; // TODO: reference react-final-form FieldRenderProps - input: any; - meta: any; + input?: any; + meta?: any; } /** @@ -112,6 +112,6 @@ export interface TextFieldProps * onChange={this.handleChange} * /> */ -export default class TextField< - Type extends string | number = string -> extends Component> {} +export default class TextField extends Component< + TextFieldProps +> {} From d339008c490ac31a4e3d70953977254c581036a7 Mon Sep 17 00:00:00 2001 From: Noah Overcash Date: Thu, 21 Dec 2023 14:36:39 -0500 Subject: [PATCH 2/2] oops, this one too --- README.md | 2 +- components/lib/Timepicker/Timepicker.d.ts | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 29d9684..7c80ede 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ With this current situation, there's not too much we can do to make everyone hap Currently, the recommended way to use Stripes components in react-final-form without sacrificing typings is via the render prop or as a child: -```tsx +```jsx import { Field } from 'react-final-form'; import { TextField } from '@folio/stripes/components'; diff --git a/components/lib/Timepicker/Timepicker.d.ts b/components/lib/Timepicker/Timepicker.d.ts index 0de94c8..9c619c6 100644 --- a/components/lib/Timepicker/Timepicker.d.ts +++ b/components/lib/Timepicker/Timepicker.d.ts @@ -1,11 +1,8 @@ import Popper from 'popper.js'; import { AriaAttributes, ComponentType, ReactNode, RefObject } from 'react'; -import { FieldRenderProps } from 'react-final-form'; import { IntlShape } from 'react-intl'; -export interface TimepickerProps - extends AriaAttributes, - FieldRenderProps { +export interface TimepickerProps extends AriaAttributes { /** If the field should auto-focus on mount */ autoFocus?: boolean; /** Disables the input field */ @@ -36,7 +33,7 @@ export interface TimepickerProps value: string | undefined, timezone: string, timeFormat: string, - intl: IntlShape + intl: IntlShape, ) => string; /** Where the overlay should be placed in relation to the field */ placement?: Popper.Placement; @@ -54,6 +51,10 @@ export interface TimepickerProps usePortal?: boolean; /** The field's value */ value?: string; + + // TODO: reference react-final-form FieldRenderProps + input?: any; + meta?: any; } /**