Skip to content

Commit 1c907d9

Browse files
committed
Remove IsMulti type parameter from SelectField
1 parent b27d081 commit 1c907d9

File tree

4 files changed

+48
-64
lines changed

4 files changed

+48
-64
lines changed

packages/bento-design-system/src/SelectField/SelectField.tsx

+23-28
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,26 @@ export type SelectOption<A> = Omit<
2222
value: A;
2323
};
2424

25-
type Props<A, IsMulti extends boolean> = (IsMulti extends false
26-
? FieldProps<A | undefined>
27-
: FieldProps<A[]>) & {
25+
type MultiProps<A> = {
26+
isMulti: true;
27+
multiValueMessage?: (numberOfSelectedOptions: number) => LocalizedString;
28+
showMultiSelectBulkActions?: boolean;
29+
selectAllButtonLabel?: LocalizedString;
30+
clearAllButtonLabel?: LocalizedString;
31+
} & FieldProps<A[]>;
32+
33+
type SingleProps<A> = {
34+
isMulti?: false;
35+
} & FieldProps<A | undefined>;
36+
37+
type Props<A> = {
2838
menuSize?: ListSize;
2939
placeholder: LocalizedString;
3040
options: Array<SelectOption<A>>;
31-
isMulti?: IsMulti;
3241
noOptionsMessage?: LocalizedString;
3342
isReadOnly?: boolean;
3443
searchable?: boolean;
35-
} & (IsMulti extends true
36-
? {
37-
multiValueMessage?: (numberOfSelectedOptions: number) => LocalizedString;
38-
showMultiSelectBulkActions?: boolean;
39-
selectAllButtonLabel?: LocalizedString;
40-
clearAllButtonLabel?: LocalizedString;
41-
}
42-
: {});
44+
} & (SingleProps<A> | MultiProps<A>);
4345

4446
declare module "react-select/dist/declarations/src/Select" {
4547
export interface Props<Option, IsMulti extends boolean, Group extends GroupBase<Option>> {
@@ -53,7 +55,7 @@ declare module "react-select/dist/declarations/src/Select" {
5355
}
5456
}
5557

56-
export function SelectField<A, IsMulti extends boolean = false>(props: Props<A, IsMulti>) {
58+
export function SelectField<A>(props: Props<A>) {
5759
const dropdownConfig = useBentoConfig().dropdown;
5860

5961
const {
@@ -127,12 +129,10 @@ export function SelectField<A, IsMulti extends boolean = false>(props: Props<A,
127129
onChange={(o) => {
128130
if (isMulti) {
129131
const multiValue = o as MultiValueT<SelectOption<A>>;
130-
(onChange as Props<A, true>["onChange"])(multiValue.map((a) => a.value));
132+
onChange(multiValue.map((a) => a.value));
131133
} else {
132134
const singleValue = o as SingleValueT<SelectOption<A>>;
133-
(onChange as Props<A, false>["onChange"])(
134-
singleValue == null ? undefined : singleValue.value
135-
);
135+
onChange(singleValue == null ? undefined : singleValue.value);
136136
}
137137
}}
138138
onBlur={onBlur}
@@ -159,35 +159,30 @@ export function SelectField<A, IsMulti extends boolean = false>(props: Props<A,
159159
MultiValue,
160160
}}
161161
openMenuOnFocus
162-
styles={selectComponents.styles<SelectOption<A>, IsMulti>()}
162+
styles={selectComponents.styles<SelectOption<A>>()}
163163
validationState={validationState}
164164
isMulti={isMulti}
165165
isClearable={false}
166166
noOptionsMessage={() => noOptionsMessage ?? defaultMessages.SelectField.noOptionsMessage}
167167
multiValueMessage={
168168
isMulti
169-
? (props as unknown as Props<A, true>).multiValueMessage ??
170-
defaultMessages.SelectField.multiOptionsSelected
169+
? props.multiValueMessage ?? defaultMessages.SelectField.multiOptionsSelected
171170
: undefined
172171
}
173172
closeMenuOnSelect={!isMulti}
174173
hideSelectedOptions={false}
175174
menuSize={menuSize}
176175
menuIsOpen={isReadOnly ? false : undefined}
177176
isSearchable={isReadOnly ? false : searchable ?? true}
178-
showMultiSelectBulkActions={
179-
isMulti ? (props as unknown as Props<A, true>).showMultiSelectBulkActions : false
180-
}
177+
showMultiSelectBulkActions={isMulti ? props.showMultiSelectBulkActions : false}
181178
clearAllButtonLabel={
182179
isMulti
183-
? (props as unknown as Props<A, true>).clearAllButtonLabel ??
184-
defaultMessages.SelectField.clearAllButtonLabel
180+
? props.clearAllButtonLabel ?? defaultMessages.SelectField.clearAllButtonLabel
185181
: undefined
186182
}
187183
selectAllButtonLabel={
188184
isMulti
189-
? (props as unknown as Props<A, true>).selectAllButtonLabel ??
190-
defaultMessages.SelectField.selectAllButtonLabel
185+
? props.selectAllButtonLabel ?? defaultMessages.SelectField.selectAllButtonLabel
191186
: undefined
192187
}
193188
/>
@@ -199,7 +194,7 @@ export function SelectField<A, IsMulti extends boolean = false>(props: Props<A,
199194
// NOTE(gabro): we override MultiValue instead of ValueContainer (which would be more natural)
200195
// because overriding ValueContainer breaks the logic for closing the menu when clicking away.
201196
// See: https://github.com/JedWatson/react-select/issues/2239#issuecomment-861848975
202-
function MultiValue<A, IsMulti extends boolean>(props: MultiValueProps<A, IsMulti>) {
197+
function MultiValue<A>(props: MultiValueProps<A>) {
203198
const inputConfig = useBentoConfig().input;
204199
const numberOfSelectedOptions = props.getValue().length;
205200

packages/bento-design-system/src/SelectField/components.tsx

+23-34
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ import { ListItem } from "../List/ListItem";
3838
import { useBentoConfig } from "../BentoConfigContext";
3939
import { useSprinkles } from "../SprinklesContext";
4040

41-
export function Control<A, IsMulti extends boolean>({
41+
export function Control<A>({
4242
selectProps: { validationState: validation, isDisabled, isReadOnly = false },
4343
innerProps,
4444
innerRef,
4545
menuIsOpen,
4646
children,
47-
}: ControlProps<A, IsMulti>) {
47+
}: ControlProps<A>) {
4848
const inputConfig = useBentoConfig().input;
4949

5050
return (
@@ -64,7 +64,7 @@ export function Control<A, IsMulti extends boolean>({
6464
);
6565
}
6666

67-
export function ValueContainer<A, IsMulti extends boolean>(props: ValueContainerProps<A, IsMulti>) {
67+
export function ValueContainer<A>(props: ValueContainerProps<A>) {
6868
const sprinkles = useSprinkles();
6969
return (
7070
<defaultComponents.ValueContainer
@@ -76,11 +76,7 @@ export function ValueContainer<A, IsMulti extends boolean>(props: ValueContainer
7676
);
7777
}
7878

79-
export function SingleValue<A, IsMulti extends boolean>({
80-
children,
81-
isDisabled,
82-
data,
83-
}: SingleValueProps<A, IsMulti>) {
79+
export function SingleValue<A>({ children, isDisabled, data }: SingleValueProps<A>) {
8480
const inputConfig = useBentoConfig().input;
8581

8682
return (
@@ -101,10 +97,7 @@ export function SingleValue<A, IsMulti extends boolean>({
10197
);
10298
}
10399

104-
export function Placeholder<A, IsMulti extends boolean>({
105-
children,
106-
isDisabled,
107-
}: PlaceholderProps<A, IsMulti>) {
100+
export function Placeholder<A>({ children, isDisabled }: PlaceholderProps<A>) {
108101
const inputConfig = useBentoConfig().input;
109102

110103
return (
@@ -116,10 +109,10 @@ export function Placeholder<A, IsMulti extends boolean>({
116109
);
117110
}
118111

119-
export function DropdownIndicator<A, IsMulti extends boolean>({
112+
export function DropdownIndicator<A>({
120113
isDisabled,
121114
selectProps: { isReadOnly },
122-
}: DropdownIndicatorProps<A, IsMulti>) {
115+
}: DropdownIndicatorProps<A>) {
123116
if (isReadOnly) return null;
124117
return (
125118
<Box paddingLeft={16}>
@@ -128,7 +121,7 @@ export function DropdownIndicator<A, IsMulti extends boolean>({
128121
);
129122
}
130123

131-
export function Input<A, IsMulti extends boolean>(props: InputProps<A, IsMulti>) {
124+
export function Input<A>(props: InputProps<A>) {
132125
const inputConfig = useBentoConfig().input;
133126

134127
return (
@@ -143,7 +136,7 @@ export function Input<A, IsMulti extends boolean>(props: InputProps<A, IsMulti>)
143136
);
144137
}
145138

146-
export function Menu<A, IsMulti extends boolean>(props: MenuProps<A, IsMulti>) {
139+
export function Menu<A>(props: MenuProps<A>) {
147140
const dropdownConfig = useBentoConfig().dropdown;
148141
const sprinkles = useSprinkles();
149142

@@ -177,9 +170,7 @@ export function Menu<A, IsMulti extends boolean>(props: MenuProps<A, IsMulti>) {
177170
);
178171
}
179172

180-
export function MenuList<A extends { disabled?: boolean }, IsMulti extends boolean>(
181-
props: MenuListProps<A, IsMulti>
182-
) {
173+
export function MenuList<A extends { disabled?: boolean }>(props: MenuListProps<A>) {
183174
const dropdownConfig = useBentoConfig().dropdown;
184175

185176
return (
@@ -220,9 +211,7 @@ export function MenuList<A extends { disabled?: boolean }, IsMulti extends boole
220211
);
221212
}
222213

223-
export function Option<B, A extends SelectOption<B>, IsMulti extends boolean>(
224-
props: OptionProps<A, IsMulti>
225-
) {
214+
export function Option<B, A extends SelectOption<B>>(props: OptionProps<A>) {
226215
return (
227216
<defaultComponents.Option {...props}>
228217
<ListItem
@@ -243,13 +232,11 @@ export function Option<B, A extends SelectOption<B>, IsMulti extends boolean>(
243232
);
244233
}
245234

246-
export function MenuPortal<A, IsMulti extends boolean>(
247-
props: MenuPortalProps<A, IsMulti, GroupBase<A>>
248-
) {
235+
export function MenuPortal<A>(props: MenuPortalProps<A, boolean, GroupBase<A>>) {
249236
return <defaultComponents.MenuPortal {...props} />;
250237
}
251238

252-
export function NoOptionsMessage<A, IsMulti extends boolean>(props: NoticeProps<A, IsMulti>) {
239+
export function NoOptionsMessage<A>(props: NoticeProps<A>) {
253240
return (
254241
<Inset space={16}>
255242
<Inline space={0} align="center" alignY="center">
@@ -263,11 +250,13 @@ export function NoOptionsMessage<A, IsMulti extends boolean>(props: NoticeProps<
263250

264251
export const IndicatorSeparator = null;
265252

266-
export const styles = <A, IsMulti extends boolean>(): StylesConfig<A, IsMulti> => ({
267-
menuPortal: ({ zIndex, ...provided }) => provided,
268-
valueContainer: ({ padding, ...provided }) => provided,
269-
input: ({ margin, paddingBottom, paddingTop, color, ...provided }) => provided,
270-
menu: () => ({}),
271-
menuList: ({ paddingTop, paddingBottom, ...provided }) => provided,
272-
option: () => ({}),
273-
});
253+
export function styles<A>(): StylesConfig<A> {
254+
return {
255+
menuPortal: ({ zIndex, ...provided }) => provided,
256+
valueContainer: ({ padding, ...provided }) => provided,
257+
input: ({ margin, paddingBottom, paddingTop, color, ...provided }) => provided,
258+
menu: () => ({}),
259+
menuList: ({ paddingTop, paddingBottom, ...provided }) => provided,
260+
option: () => ({}),
261+
};
262+
}

packages/storybook/stories/Components/Form.stories.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const ExampleNumberField = (
6060

6161
const ExampleSelectField = <A extends {}>(
6262
props: Omit<
63-
SelectFieldProps<A, false>,
63+
SelectFieldProps<A> & { isMulti?: false },
6464
"placeholder" | "value" | "onChange" | "name" | "onBlur" | "multiValueMessage"
6565
>
6666
) => {

packages/website/src/snippets/Form/fields.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export const ExampleNumberField = (
5050

5151
export const ExampleSelectField = <A extends {}>(
5252
props: Omit<
53-
SelectFieldProps<A, false>,
53+
SelectFieldProps<A> & { isMulti?: false },
5454
"placeholder" | "value" | "onChange" | "name" | "onBlur" | "menuSize"
5555
>
5656
) => {

0 commit comments

Comments
 (0)