|
1 | 1 | import React from 'react'; |
2 | 2 | import Tooltip from '../../components/Tooltip'; |
3 | 3 |
|
4 | | -import PreferenceSwitch from './PreferenceSwitch'; |
5 | | -import PreferenceDropdown, { NameMapper } from './PreferenceDropdown'; |
6 | | -import PreferenceNumber from './PreferenceNumber'; |
7 | | -import PreferenceText from './PreferenceText'; |
8 | | -import PreferenceKeybinding from './PreferenceKeybinding'; |
| 4 | +import PreferenceSwitch, { Props as SwitchProps } from './PreferenceSwitch'; |
| 5 | +import PreferenceDropdown, { |
| 6 | + Props as DropdownProps, |
| 7 | +} from './PreferenceDropdown'; |
| 8 | +import PreferenceNumber, { Props as NumberProps } from './PreferenceNumber'; |
| 9 | +import PreferenceText, { Props as TextProps } from './PreferenceText'; |
| 10 | +import PreferenceKeybinding, { |
| 11 | + Props as KeybindingProps, |
| 12 | +} from './PreferenceKeybinding'; |
9 | 13 | import { Container } from './elements'; |
10 | 14 |
|
11 | | -export type Props = { |
| 15 | +type PreferenceType = |
| 16 | + | 'boolean' |
| 17 | + | 'string' |
| 18 | + | 'dropdown' |
| 19 | + | 'keybinding' |
| 20 | + | 'number'; |
| 21 | + |
| 22 | +type PreferenceProps<TString extends PreferenceType> = { |
| 23 | + type: TString; |
12 | 24 | title: string; |
13 | 25 | style?: React.CSSProperties; |
14 | 26 | className?: string; |
15 | 27 | tooltip?: string; |
16 | | -} & ( |
17 | | - | BooleanPreference |
18 | | - | StringPreference |
19 | | - | DropdownPreference |
20 | | - | KeybindingPreference |
21 | | - | NumberPreference); |
22 | | - |
23 | | -type SetValueT<T> = (value: T) => void; |
24 | | - |
25 | | -export type BooleanPreference = { |
26 | | - type: 'boolean'; |
27 | | - value: boolean; |
28 | | - defaultValue?: boolean; |
29 | | - setValue: SetValueT<boolean>; |
30 | | -}; |
31 | | - |
32 | | -export type StringPreference = { |
33 | | - type: 'string'; |
34 | | - value: string; |
35 | | - defaultValue?: string; |
36 | | - setValue: SetValueT<string>; |
37 | | -}; |
38 | | - |
39 | | -export type DropdownPreference = { |
40 | | - type: 'dropdown'; |
41 | | - options: string[]; |
42 | | - value: string; |
43 | | - defaultValue?: string; |
44 | | - setValue: SetValueT<string>; |
45 | | - mapName?: NameMapper; |
46 | 28 | }; |
47 | 29 |
|
48 | | -export type KeybindingPreference = { |
49 | | - type: 'keybinding'; |
50 | | - value: string[][]; |
51 | | - defaultValue?: string[][]; |
52 | | - setValue: SetValueT<string[][]>; |
53 | | -}; |
54 | | - |
55 | | -export type NumberPreference = { |
56 | | - type: 'number'; |
57 | | - value: number; |
58 | | - defaultValue?: number; |
59 | | - setValue: SetValueT<number>; |
60 | | -}; |
| 30 | +export type BooleanPreference = PreferenceProps<'boolean'> & SwitchProps; |
61 | 31 |
|
62 | | -export default class Preference extends React.Component<Props> { |
63 | | - getOptionComponent = () => { |
64 | | - const { props } = this; |
65 | | - if (props.type === 'boolean') { |
66 | | - return ( |
67 | | - <PreferenceSwitch |
68 | | - {...props} |
69 | | - setValue={props.setValue} |
70 | | - value={props.value} |
71 | | - /> |
72 | | - ); |
73 | | - } |
| 32 | +export type StringPreference = PreferenceProps<'string'> & TextProps; |
74 | 33 |
|
75 | | - if (props.type === 'string') { |
76 | | - return ( |
77 | | - <PreferenceText |
78 | | - {...props} |
79 | | - setValue={props.setValue} |
80 | | - value={props.value} |
81 | | - /> |
82 | | - ); |
83 | | - } |
| 34 | +export type DropdownPreference = PreferenceProps<'dropdown'> & DropdownProps; |
84 | 35 |
|
85 | | - if (props.type === 'dropdown') { |
86 | | - return ( |
87 | | - <PreferenceDropdown |
88 | | - {...props} |
89 | | - options={props.options} |
90 | | - setValue={props.setValue} |
91 | | - value={props.value} |
92 | | - /> |
93 | | - ); |
94 | | - } |
| 36 | +export type KeybindingPreference = PreferenceProps<'keybinding'> & |
| 37 | + KeybindingProps; |
95 | 38 |
|
96 | | - if (props.type === 'keybinding') { |
97 | | - return ( |
98 | | - <PreferenceKeybinding |
99 | | - {...props} |
100 | | - setValue={props.setValue} |
101 | | - value={props.value} |
102 | | - /> |
103 | | - ); |
104 | | - } |
| 39 | +export type NumberPreference = PreferenceProps<'number'> & NumberProps; |
105 | 40 |
|
106 | | - return ( |
107 | | - <PreferenceNumber |
108 | | - {...props} |
109 | | - setValue={props.setValue} |
110 | | - value={props.value} |
111 | | - /> |
112 | | - ); |
113 | | - }; |
114 | | - |
115 | | - render() { |
116 | | - const { title, style, className, tooltip } = this.props; |
| 41 | +export type Props = |
| 42 | + | BooleanPreference |
| 43 | + | StringPreference |
| 44 | + | DropdownPreference |
| 45 | + | KeybindingPreference |
| 46 | + | NumberPreference; |
| 47 | + |
| 48 | +const Preference = (props: Props) => { |
| 49 | + const { title, style, className, tooltip, ...contentProps } = props; |
| 50 | + |
| 51 | + let content: React.ReactNode; |
| 52 | + switch ( |
| 53 | + contentProps.type // need 'type' as discriminant of union type |
| 54 | + ) { |
| 55 | + case 'boolean': |
| 56 | + content = <PreferenceSwitch {...contentProps} />; |
| 57 | + break; |
| 58 | + case 'string': |
| 59 | + content = <PreferenceText {...contentProps} />; |
| 60 | + break; |
| 61 | + case 'dropdown': |
| 62 | + content = <PreferenceDropdown {...contentProps} />; |
| 63 | + break; |
| 64 | + case 'keybinding': |
| 65 | + content = <PreferenceKeybinding {...contentProps} />; |
| 66 | + break; |
| 67 | + default: |
| 68 | + content = <PreferenceNumber {...contentProps} />; |
| 69 | + } |
117 | 70 |
|
118 | | - const Title = tooltip ? ( |
119 | | - <Tooltip placement="right" content={tooltip}> |
120 | | - {title} |
121 | | - </Tooltip> |
122 | | - ) : ( |
123 | | - <span>{title}</span> |
124 | | - ); |
| 71 | + const Title = tooltip ? ( |
| 72 | + <Tooltip placement="right" content={tooltip}> |
| 73 | + {title} |
| 74 | + </Tooltip> |
| 75 | + ) : ( |
| 76 | + <span>{title}</span> |
| 77 | + ); |
| 78 | + |
| 79 | + return ( |
| 80 | + <Container style={style} className={className}> |
| 81 | + {Title} |
| 82 | + <div>{content}</div> |
| 83 | + </Container> |
| 84 | + ); |
| 85 | +}; |
125 | 86 |
|
126 | | - return ( |
127 | | - <Container style={style} className={className}> |
128 | | - {Title} |
129 | | - <div>{this.getOptionComponent()}</div> |
130 | | - </Container> |
131 | | - ); |
132 | | - } |
133 | | -} |
| 87 | +export default Preference; |
0 commit comments