Skip to content

Commit

Permalink
fix: remove all generics from NDSSelect
Browse files Browse the repository at this point in the history
react-windowed-select does not forward <Option, IsMulti extends boolean, Group extends GroupBase<Option>>
downstream to the react-select resulting in mismatches between the expected types (defaulting to unknown)
and the actual types inferred by react-select.

This caused a problem for both the onChange and the custom components.
  • Loading branch information
haideralsh committed May 9, 2024
1 parent 5b608c9 commit 45c8fbf
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 33 deletions.
37 changes: 17 additions & 20 deletions src/Select/Select.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { forwardRef, ReactNode, MutableRefObject } from "react";
import Select from "react-select/base";
import WindowedSelect, { GroupBase } from "react-windowed-select";
import WindowedSelect from "react-windowed-select";
import type { Props as SelectProps } from "react-select";
import { useTranslation } from "react-i18next";
import { useTheme } from "styled-components";
Expand All @@ -10,7 +10,6 @@ import { MaybeFieldLabel } from "../FieldLabel";
import { InlineValidation } from "../Validation";
import customStyles from "../Select/customReactSelectStyles";
import { getSubset } from "../utils/subset";
import { SelectControl } from "../AsyncSelect/AsyncSelectComponents";
import { ComponentSize, useComponentSize } from "../NDSProvider/ComponentSizeContext";
import {
SelectMultiValue,
Expand All @@ -19,37 +18,37 @@ import {
SelectInput,
SelectDropdownIndicator,
SelectMenu,
SelectControl,
} from "./SelectComponents";
import { SelectOption } from "./SelectOption";

interface WindowedSelectProps<Option, IsMulti extends boolean, Group extends GroupBase<Option>>
extends SelectProps<Option, IsMulti, Group> {
interface WindowedSelectProps extends SelectProps {
windowThreshold: number;
}

type CustomProps<Option, IsMulti extends boolean, Group extends GroupBase<Option>> = {
autocomplete?: WindowedSelectProps<Option, IsMulti, Group>["isSearchable"];
type CustomProps = {
autocomplete?: WindowedSelectProps["isSearchable"];
labelText?: string;
size?: ComponentSize;
requirementText?: string;
helpText?: ReactNode;
disabled?: WindowedSelectProps<Option, IsMulti, Group>["isDisabled"];
disabled?: WindowedSelectProps["isDisabled"];
errorMessage?: string;
errorList?: string[];
initialIsOpen?: WindowedSelectProps<Option, IsMulti, Group>["defaultMenuIsOpen"];
multiselect?: WindowedSelectProps<Option, IsMulti, Group>["isMulti"];
initialIsOpen?: WindowedSelectProps["defaultMenuIsOpen"];
multiselect?: WindowedSelectProps["isMulti"];
maxHeight?: string;
defaultValue?: WindowedSelectProps<Option, IsMulti, Group>["defaultInputValue"];
defaultValue?: WindowedSelectProps["defaultInputValue"];
};

export type NDSSelectProps<Option, IsMulti extends boolean, Group extends GroupBase<Option>> = Omit<
WindowedSelectProps<Option, IsMulti, Group>,
export type NDSSelectProps = Omit<
WindowedSelectProps,
"isSearchable" | "isDisabled" | "isMulti" | "defaultMenuIsOpen" | "defaultInputValue"
> &
CustomProps<Option, IsMulti, Group>;
CustomProps;

const NDSSelect = forwardRef(
<Option, IsMulti extends boolean, Group extends GroupBase<Option>>(
(
{
size,
autocomplete,
Expand Down Expand Up @@ -84,11 +83,8 @@ const NDSSelect = forwardRef(
"aria-label": ariaLabel,
windowThreshold = 100,
...props
}: NDSSelectProps<Option, IsMulti, Group>,
ref:
| ((instance: Select<Option, IsMulti, Group> | null) => void)
| MutableRefObject<Select<Option, IsMulti, Group> | null>
| null
}: NDSSelectProps,
ref: ((instance: Select | null) => void) | MutableRefObject<Select | null> | null
) => {
const { t } = useTranslation();
const theme = useTheme();
Expand All @@ -101,6 +97,7 @@ const NDSSelect = forwardRef(
<Field {...spaceProps}>
<MaybeFieldLabel labelText={labelText} requirementText={requirementText} helpText={helpText}>
<WindowedSelect
windowThreshold={windowThreshold}
className={className}
classNamePrefix={classNamePrefix}
noOptionsMessage={noOptionsMessage}
Expand Down Expand Up @@ -131,7 +128,7 @@ const NDSSelect = forwardRef(
menuPosition={menuPosition}
onInputChange={onInputChange}
components={{
SelectOption: (props) => (
Option: (props) => (
<SelectOption size={componentSize} {...props}>
{props.children}
</SelectOption>
Expand Down
26 changes: 17 additions & 9 deletions src/Select/SelectComponents.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import React from "react";
import { components as selectComponents } from "react-windowed-select";
import {
ClearIndicatorProps,
ContainerProps,
ControlProps,
DropdownIndicatorProps,
InputProps,
MenuProps,
MultiValueProps,
components as selectComponents,
} from "react-windowed-select";

export const SelectControl = (props) => {
// eslint-disable-next-line react/prop-types
export const SelectControl = (props: ControlProps) => {
const { isFocused } = props;
return (
<div data-testid="select-control">
Expand All @@ -15,47 +23,47 @@ export const SelectControl = (props) => {
);
};

export const SelectMultiValue = (props) => {
export const SelectMultiValue = (props: MultiValueProps) => {
return (
<div data-testid="select-multivalue">
<selectComponents.MultiValue {...props} />
</div>
);
};

export const SelectClearIndicator = (props) => {
export const SelectClearIndicator = (props: ClearIndicatorProps) => {
return (
<div data-testid="select-clear">
<selectComponents.ClearIndicator {...props} />
</div>
);
};

export const SelectDropdownIndicator = (props) => {
export const SelectDropdownIndicator = (props: DropdownIndicatorProps) => {
return (
<div data-testid="select-arrow">
<selectComponents.DropdownIndicator {...props} />
</div>
);
};

export const SelectMenu = (props) => {
export const SelectMenu = (props: MenuProps) => {
return (
<div data-testid="select-dropdown">
<selectComponents.Menu {...props} />
</div>
);
};

export const SelectContainer = (props) => {
export const SelectContainer = (props: ContainerProps) => {
return (
<div data-testid="select-container">
<selectComponents.SelectContainer {...props} />
</div>
);
};

export const SelectInput = (props) => {
export const SelectInput = (props: InputProps) => {
return (
<div data-testid="select-input">
<selectComponents.Input {...props} />
Expand Down
8 changes: 4 additions & 4 deletions src/Select/SelectOption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import { subPx } from "../utils";
import { ComponentSize, useComponentSize } from "../NDSProvider/ComponentSizeContext";
import { stylesForSize } from "./customReactSelectStyles";

type SelectOptionProps = {
type StyledOptionProps = {
isSelected: boolean;
isFocused: boolean;
size: ComponentSize;
};

export const StyledOption = styled.div<SelectOptionProps>(
export const StyledOption = styled.div<StyledOptionProps>(
typography,
({ isSelected, isFocused, theme }) => ({
"&:last-child": {
Expand Down Expand Up @@ -51,11 +51,11 @@ export const StyledOption = styled.div<SelectOptionProps>(
)
);

interface CustomOptionProps extends OptionProps {
interface SelectOptionProps extends OptionProps {
size?: ComponentSize;
}

export function SelectOption(props: CustomOptionProps) {
export function SelectOption(props: SelectOptionProps) {
const size = useComponentSize(props.size);

return (
Expand Down

0 comments on commit 45c8fbf

Please sign in to comment.