Skip to content

Commit

Permalink
Typecasting forwardRef inside Select (#1774)
Browse files Browse the repository at this point in the history
  • Loading branch information
siddhantrawal authored Jan 11, 2024
1 parent 0ccd7b7 commit 70428a9
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/lovely-pears-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@itwin/itwinui-react': patch
---

Fixed `Select` and `LabeledSelect` to correctly handle generic types.
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,16 @@ it('should handle required attribute', () => {

expect(container.querySelector('.iui-input-label.iui-required')).toBeTruthy();
});

it('should allow passing ref to LabeledSelect', () => {
const selectRef = React.createRef<HTMLElement>();
render(
<LabeledSelect
options={[{ value: 1, label: 'Option 1' }]}
ref={selectRef}
data-select
/>,
);

expect(selectRef?.current).toHaveAttribute('data-select');
});
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ export const LabeledSelect = React.forwardRef(
</InputGrid>
);
},
);
) as <T>(
props: LabeledSelectProps<T> & { ref?: React.ForwardedRef<HTMLElement> },
) => JSX.Element;

export default LabeledSelect;
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/**
* This test file tests some LabeledSelect type related cases that have not been tested in other files
* (e.g. react-workshop, unit tests, etc.)
*/

import React, { useRef } from 'react';
import LabeledSelect from './LabeledSelect.js';

() => {
const ref = useRef(null);
return (
<>
<LabeledSelect
options={[
{ value: 1, label: 'Option 1' },
{ value: 2, label: 'Option 2' },
{ value: 3, label: 'Option 3' },
]}
onChange={(value) => {
const returnValue: number = value;
return returnValue;
}}
ref={ref}
/>
</>
);
};

() => {
return (
<>
<LabeledSelect<number>
options={[
{ value: 1, label: 'Option 1' },
{ value: 2, label: 'Option 2' },
{ value: 3, label: 'Option 3' },
]}
onChange={(value) => {
const returnValue: number = value;
return returnValue;
}}
/>
</>
);
};

() => {
return (
<>
<LabeledSelect<string>
label='Select Label'
options={[
{ value: '1', label: 'Item #1' },
{ value: '2', label: 'Item #2' },
{ value: '3', label: 'Item #3' },
]}
onChange={(value) => {
const returnValue: string = value;
return returnValue;
}}
/>
</>
);
};

() => {
return (
<>
<LabeledSelect<string>
label='Select Label'
options={[
// There should be error: TS 2322
// @ts-expect-error (TS 2322): Type 'number' is not assignable to type 'string'.
{ value: 1, label: 'Item #1' },
]}
onChange={(value) => {
const returnValue: string = value;
return returnValue;
}}
/>
</>
);
};
13 changes: 13 additions & 0 deletions packages/itwinui-react/src/core/Select/Select.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -598,3 +598,16 @@ it.each([true, false] as const)(
expect(selectButton).toHaveTextContent('B');
},
);

it('should allow passing ref to Select', () => {
const selectRef = React.createRef<HTMLElement>();
render(
<Select
options={[{ value: 1, label: 'Option 1' }]}
ref={selectRef}
data-select
/>,
);

expect(selectRef?.current).toHaveAttribute('data-select');
});
4 changes: 3 additions & 1 deletion packages/itwinui-react/src/core/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,9 @@ export const Select = React.forwardRef(
</>
);
},
);
) as <T>(
props: SelectProps<T> & { ref?: React.ForwardedRef<HTMLElement> },
) => JSX.Element;

type SingleSelectButtonProps<T> = {
selectedItem?: SelectOption<T>;
Expand Down
86 changes: 86 additions & 0 deletions packages/itwinui-react/src/core/Select/Select.types-test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/**
* This test file tests some Select type related cases that have not been tested in other files
* (e.g. react-workshop, unit tests, etc.)
*/

import React, { useRef } from 'react';
import Select from './Select.js';

() => {
const ref = useRef(null);
return (
<>
<Select
options={[
{ value: 1, label: 'Option 1' },
{ value: 2, label: 'Option 2' },
{ value: 3, label: 'Option 3' },
]}
onChange={(value) => {
const returnValue: number = value;
return returnValue;
}}
ref={ref}
/>
</>
);
};

() => {
return (
<>
<Select<number>
options={[
{ value: 1, label: 'Option 1' },
{ value: 2, label: 'Option 2' },
{ value: 3, label: 'Option 3' },
]}
onChange={(value) => {
const returnValue: number = value;
return returnValue;
}}
/>
</>
);
};

() => {
return (
<>
<Select<string>
options={[
{ value: '1', label: 'Option 1' },
{ value: '2', label: 'Option 2' },
{ value: '3', label: 'Option 3' },
]}
onChange={(value) => {
const returnValue: string = value;
return returnValue;
}}
/>
</>
);
};

() => {
return (
<>
<Select<string>
label='Select Label'
options={[
// There should be error: TS 2322
// @ts-expect-error (TS 2322): Type 'number' is not assignable to type 'string'.
{ value: 1, label: 'Item #1' },
]}
onChange={(value) => {
const returnValue: string = value;
return returnValue;
}}
/>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/**
* This test file to test some Table type related cases that have not been tested in other files
* This test file tests some Table type related cases that have not been tested in other files
* (e.g. react-workshop, unit tests, etc.)
*/

Expand Down
7 changes: 6 additions & 1 deletion packages/itwinui-react/tsconfig.test.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
{
"extends": "./tsconfig.json",
// TODO: Test all the files, and not just the Table files or just the build files.
"include": ["src/core/Table/**/*", "src/react-table/*"]
"include": [
"src/core/Table/**/*",
"src/react-table/*",
"src/core/Select/**/*",
"src/core/LabeledSelect/**/*"
]
}

0 comments on commit 70428a9

Please sign in to comment.