Skip to content

Commit 3c8729a

Browse files
WesSouzaarturbien
authored andcommitted
feat(select): convert to TypeScript and export types
1 parent 0f3c9ff commit 3c8729a

File tree

9 files changed

+686
-571
lines changed

9 files changed

+686
-571
lines changed

src/Select/Select.js

Lines changed: 0 additions & 518 deletions
This file was deleted.

src/Select/Select.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ name: Select
33
menu: Components
44
---
55

6-
import Select from './Select'
7-
import Window from '../Window/Window'
8-
import WindowContent from '../WindowContent/WindowContent'
6+
import { Select } from './Select';
7+
import Window from '../Window/Window';
8+
import WindowContent from '../WindowContent/WindowContent';
99
import { Cutout } from '../Cutout/Cutout';
1010

1111
# Select

src/Select/Select.spec.js renamed to src/Select/Select.spec.tsx

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
// Bsased on https://github.com/mui-org/material-ui
2-
import React from 'react';
2+
33
import { fireEvent } from '@testing-library/react';
4+
import React from 'react';
45
import { renderWithTheme } from '../../test/utils';
5-
import Select from './Select';
6+
import { Select } from './Select';
7+
import { SelectOption, SelectRef } from './Select.types';
68

7-
const options = [
9+
const options: SelectOption[] = [
810
{ label: 'ten', value: 10 },
911
{ label: 'twenty', value: 20 },
1012
{ label: 'thirty', value: 30 }
@@ -15,7 +17,9 @@ describe('<Select />', () => {
1517
const { container } = renderWithTheme(
1618
<Select value={10} options={options} />
1719
);
18-
expect(container.querySelector('input').value).toBe('10');
20+
21+
const input = container.querySelector('input') as HTMLInputElement;
22+
expect(input.value).toBe('10');
1923
});
2024

2125
it('renders dropdown button with icon', () => {
@@ -85,14 +89,17 @@ describe('<Select />', () => {
8589
expect(o[1]).toHaveAttribute('data-value', '20');
8690
});
8791
[' ', 'ArrowUp', 'ArrowDown', 'Enter'].forEach(key => {
88-
it(`should open menu when pressed ${key} key on select`, () => {
92+
it(`should open menu when pressed ${
93+
key === ' ' ? 'Space' : key
94+
} key on select`, () => {
8995
const { getByRole } = renderWithTheme(
9096
<Select value='' options={[{ label: 'none', value: '' }]} />
9197
);
9298
getByRole('button').focus();
93-
fireEvent.keyDown(document.activeElement, { key });
99+
const focusedButton = document.activeElement as HTMLButtonElement;
100+
fireEvent.keyDown(focusedButton, { key });
94101
expect(getByRole('listbox', { hidden: false })).toBeInTheDocument();
95-
fireEvent.keyUp(document.activeElement, { key });
102+
fireEvent.keyUp(focusedButton, { key });
96103
expect(getByRole('listbox', { hidden: false })).toBeInTheDocument();
97104
});
98105
});
@@ -135,9 +142,9 @@ describe('<Select />', () => {
135142
<Select value={10} open options={options} menuMaxHeight={220} />
136143
);
137144

138-
const listbox = getByRole('listbox');
145+
const listbox = getByRole('listbox') as HTMLElement;
139146
expect(
140-
listbox.getAttribute('style').includes('max-height: 220px')
147+
listbox.getAttribute('style')?.includes('max-height: 220px')
141148
).toBeTruthy();
142149
});
143150
});
@@ -182,7 +189,10 @@ describe('<Select />', () => {
182189
<Select
183190
open
184191
value={obj1}
185-
options={[{ value: obj1 }, { value: obj2 }]}
192+
options={[
193+
{ label: '1', value: obj1 },
194+
{ label: '2', value: obj2 }
195+
]}
186196
/>
187197
);
188198
const o = getAllByRole('option');
@@ -324,9 +334,10 @@ describe('<Select />', () => {
324334
<Select readOnly value='10' options={options} />
325335
);
326336
getByRole('button').focus();
327-
fireEvent.keyDown(document.activeElement, { key: 'ArrowDown' });
337+
const focusedButton = document.activeElement as HTMLElement;
338+
fireEvent.keyDown(focusedButton, { key: 'ArrowDown' });
328339
expect(queryByRole('listbox')).not.toBeInTheDocument();
329-
fireEvent.keyUp(document.activeElement, { key: 'ArrowDown' });
340+
fireEvent.keyUp(focusedButton, { key: 'ArrowDown' });
330341
expect(queryByRole('listbox')).not.toBeInTheDocument();
331342
});
332343
});
@@ -346,7 +357,8 @@ describe('<Select />', () => {
346357

347358
describe('prop: renderValue', () => {
348359
it('should use the prop to render the value', () => {
349-
const formatDisplay = x => `0b${x.value.toString(2)}`;
360+
const formatDisplay = (x: SelectOption) =>
361+
`0b${Number(x.value).toString(2)}`;
350362
const { getByRole } = renderWithTheme(
351363
<Select
352364
formatDisplay={formatDisplay}
@@ -381,15 +393,15 @@ describe('<Select />', () => {
381393

382394
describe('prop: inputRef', () => {
383395
it('should be able to return the input node via a ref object', () => {
384-
const ref = React.createRef();
396+
const ref = React.createRef<SelectRef>();
385397
renderWithTheme(<Select inputRef={ref} value='' />);
386-
expect(ref.current.node).toHaveProperty('tagName', 'INPUT');
398+
expect(ref.current?.node).toHaveProperty('tagName', 'INPUT');
387399
});
388400

389401
it('should be able focus the trigger imperatively', () => {
390-
const ref = React.createRef();
402+
const ref = React.createRef<SelectRef>();
391403
const { getByRole } = renderWithTheme(<Select inputRef={ref} value='' />);
392-
ref.current.focus();
404+
ref.current?.focus();
393405
expect(getByRole('button')).toHaveFocus();
394406
});
395407
});

src/Select/Select.stories.js renamed to src/Select/Select.stories.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
/* eslint-disable no-console */
2-
import React from 'react';
3-
import styled from 'styled-components';
42

5-
import { Select, Window, WindowContent, Cutout, Fieldset } from 'react95';
3+
import { ComponentMeta } from '@storybook/react';
4+
import { Cutout, Fieldset, Select, Window, WindowContent } from 'react95';
5+
import styled from 'styled-components';
6+
import { SelectChangeEvent, SelectOption } from './Select.types';
67

78
const options = [
89
{ value: 1, label: '⚡ Pikachu' },
@@ -37,13 +38,14 @@ const Wrapper = styled.div`
3738
}
3839
`;
3940

40-
const onChange = (evt, nextSelection) => console.log(evt, nextSelection);
41+
const onChange = (event: SelectChangeEvent, option: SelectOption) =>
42+
console.log(event, option);
4143

4244
export default {
4345
title: 'Select',
4446
component: Select,
4547
decorators: [story => <Wrapper>{story()}</Wrapper>]
46-
};
48+
} as ComponentMeta<typeof Select>;
4749

4850
export function Default() {
4951
return (
@@ -154,7 +156,9 @@ Flat.story = {
154156
export function CustomDisplayFormatting() {
155157
return (
156158
<Select
157-
formatDisplay={opt => `${opt.label.toUpperCase()} 👍 👍`}
159+
formatDisplay={(opt: SelectOption<number>) =>
160+
`${opt.label.toUpperCase()} 👍 👍`
161+
}
158162
onChange={onChange}
159163
options={options}
160164
width={220}

src/Select/Select.styles.js renamed to src/Select/Select.styles.tsx

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
import styled, { css } from 'styled-components';
2-
import { StyledButton as Button } from '../Button/Button';
32

3+
import { StyledButton as Button } from '../Button/Button';
44
import {
5-
shadow as commonShadow,
65
createDisabledTextStyles,
76
createFlatBoxStyles,
8-
createScrollbars
7+
createScrollbars,
8+
shadow as commonShadow
99
} from '../common';
1010
import { blockSizes } from '../common/system';
1111
import { StyledCutout } from '../Cutout/Cutout';
12+
import { CommonThemeProps } from '../types';
13+
14+
import { SelectVariants } from './Select.types';
15+
16+
type CommonSelectStyleProps = {
17+
$disabled?: boolean;
18+
native?: boolean;
19+
variant?: SelectVariants;
20+
} & CommonThemeProps;
1221

1322
const sharedInputContentStyles = css`
1423
box-sizing: border-box;
@@ -48,29 +57,29 @@ export const StyledSelectContent = styled.div`
4857
border: 2px dotted ${({ theme }) => theme.focusSecondary};
4958
}
5059
`;
51-
const sharedWrapperStyles = css`
60+
const sharedWrapperStyles = css<CommonSelectStyleProps>`
5261
height: ${blockSizes.md};
5362
display: inline-block;
54-
color: ${({ theme, isDisabled }) =>
55-
isDisabled ? createDisabledTextStyles() : theme.canvasText};
63+
color: ${({ $disabled = false, theme }) =>
64+
$disabled ? createDisabledTextStyles() : theme.canvasText};
5665
font-size: 1rem;
57-
cursor: ${({ isDisabled }) => (isDisabled ? 'default' : 'pointer')};
66+
cursor: ${({ $disabled }) => ($disabled ? 'default' : 'pointer')};
5867
`;
5968

60-
export const StyledSelectWrapper = styled(StyledCutout)`
69+
export const StyledSelectWrapper = styled(StyledCutout)<CommonSelectStyleProps>`
6170
${sharedWrapperStyles}
62-
background: ${({ theme, isDisabled }) =>
63-
isDisabled ? theme.material : theme.canvas};
71+
background: ${({ $disabled = false, theme }) =>
72+
$disabled ? theme.material : theme.canvas};
6473
&:focus {
6574
outline: 0;
6675
}
6776
`;
6877

69-
export const StyledFlatSelectWrapper = styled.div`
78+
export const StyledFlatSelectWrapper = styled.div<CommonSelectStyleProps>`
7079
${createFlatBoxStyles()}
7180
${sharedWrapperStyles}
72-
background: ${({ theme, isDisabled }) =>
73-
isDisabled ? theme.flatLight : theme.canvas};
81+
background: ${({ $disabled = false, theme }) =>
82+
$disabled ? theme.flatLight : theme.canvas};
7483
`;
7584

7685
export const StyledNativeSelect = styled.select`
@@ -96,11 +105,11 @@ export const StyledNativeSelect = styled.select`
96105
}
97106
`;
98107

99-
export const StyledDropdownButton = styled(Button)`
108+
export const StyledDropdownButton = styled(Button)<CommonSelectStyleProps>`
100109
width: 30px;
101110
padding: 0;
102111
flex-shrink: 0;
103-
${({ variant }) =>
112+
${({ variant = 'default' }) =>
104113
variant === 'flat'
105114
? css`
106115
height: 100%;
@@ -116,7 +125,7 @@ export const StyledDropdownButton = styled(Button)`
116125
inset -1px -1px 0 1px ${({ theme }) => theme.borderDark};
117126
}
118127
`}
119-
${({ native, variant }) =>
128+
${({ native = false, variant = 'default' }) =>
120129
native &&
121130
(variant === 'flat'
122131
? `
@@ -130,11 +139,11 @@ export const StyledDropdownButton = styled(Button)`
130139
right: 2px;
131140
height: calc(100% - 4px);
132141
`)}
133-
pointer-events: ${({ isDisabled, native }) =>
134-
isDisabled || native ? 'none' : 'auto'}
142+
pointer-events: ${({ $disabled = false, native = false }) =>
143+
$disabled || native ? 'none' : 'auto'}
135144
`;
136145

137-
export const StyledDropdownIcon = styled.span`
146+
export const StyledDropdownIcon = styled.span<CommonSelectStyleProps>`
138147
position: absolute;
139148
left: 50%;
140149
top: 50%;
@@ -145,10 +154,10 @@ export const StyledDropdownIcon = styled.span`
145154
border-right: 6px solid transparent;
146155
display: inline-block;
147156
border-top: 6px solid
148-
${({ theme, isDisabled }) =>
149-
isDisabled ? theme.materialTextDisabled : theme.materialText};
150-
${({ theme, isDisabled }) =>
151-
isDisabled &&
157+
${({ $disabled = false, theme }) =>
158+
$disabled ? theme.materialTextDisabled : theme.materialText};
159+
${({ $disabled = false, theme }) =>
160+
$disabled &&
152161
`
153162
filter: drop-shadow(1px 1px 0px ${theme.materialTextDisabledShadow});
154163
border-top-color: ${theme.materialTextDisabled};
@@ -158,7 +167,7 @@ export const StyledDropdownIcon = styled.span`
158167
}
159168
`;
160169

161-
export const StyledDropdownMenu = styled.ul`
170+
export const StyledDropdownMenu = styled.ul<CommonSelectStyleProps>`
162171
box-sizing: border-box;
163172
164173
font-size: 1rem;
@@ -172,7 +181,7 @@ export const StyledDropdownMenu = styled.ul`
172181
z-index: 1;
173182
cursor: pointer;
174183
box-shadow: ${commonShadow};
175-
${({ variant }) =>
184+
${({ variant = 'default' }) =>
176185
variant === 'flat'
177186
? css`
178187
bottom: 2px;
@@ -184,7 +193,7 @@ export const StyledDropdownMenu = styled.ul`
184193
width: calc(100% - 2px);
185194
border: 2px solid ${({ theme }) => theme.borderDarkest};
186195
`}
187-
${({ variant }) => createScrollbars(variant)}
196+
${({ variant = 'default' }) => createScrollbars(variant)}
188197
`;
189198

190199
export const StyledDropdownMenuItem = styled.li`

0 commit comments

Comments
 (0)