Skip to content

Commit 4129544

Browse files
author
Akos Kitta
committed
generalized the react-select component
so tha we can reuse it all over the application. Signed-off-by: Akos Kitta <[email protected]>
1 parent a866bde commit 4129544

File tree

7 files changed

+125
-124
lines changed

7 files changed

+125
-124
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import * as React from 'react';
2+
import Select from 'react-select';
3+
import { Styles } from 'react-select/src/styles';
4+
import { Props } from 'react-select/src/components';
5+
import { ThemeConfig } from 'react-select/src/theme';
6+
7+
export class ArduinoSelect<T> extends Select<T> {
8+
9+
constructor(props: Readonly<Props<T>>) {
10+
super(props);
11+
}
12+
13+
render(): React.ReactNode {
14+
const { defaultValue, onChange, options, className } = this.props;
15+
const height = 25;
16+
const styles: Styles = {
17+
control: styles => ({
18+
...styles,
19+
width: 200,
20+
color: 'var(--theia-ui-font-color1)'
21+
}),
22+
dropdownIndicator: styles => ({
23+
...styles,
24+
padding: 0
25+
}),
26+
indicatorSeparator: () => ({
27+
display: 'none'
28+
}),
29+
indicatorsContainer: () => ({
30+
padding: '0px 5px'
31+
}),
32+
menu: styles => ({
33+
...styles,
34+
marginTop: 0
35+
})
36+
};
37+
const theme: ThemeConfig = theme => ({
38+
...theme,
39+
borderRadius: 0,
40+
spacing: {
41+
controlHeight: height,
42+
baseUnit: 2,
43+
menuGutter: 4
44+
}, colors: {
45+
...theme.colors,
46+
// `primary50`??? it's crazy but apparently, without this, we would get a light-blueish
47+
// color when selecting an option in the select by clicking and then not releasing the button.
48+
// https://react-select.com/styles#overriding-the-theme
49+
primary50: 'var(--theia-accent-color4)',
50+
}
51+
});
52+
const DropdownIndicator = () => <span className='fa fa-caret-down caret' />;
53+
return <Select
54+
options={options}
55+
defaultValue={defaultValue}
56+
onChange={onChange}
57+
components={{ DropdownIndicator }}
58+
theme={theme}
59+
styles={styles}
60+
classNamePrefix='arduino-select'
61+
className={className}
62+
isSearchable={false}
63+
/>
64+
}
65+
66+
}

arduino-ide-extension/src/browser/monitor/monitor-widget.tsx

+9-73
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import * as React from 'react';
22
import * as dateFormat from 'dateformat';
33
import { postConstruct, injectable, inject } from 'inversify';
4-
import { ThemeConfig } from 'react-select/src/theme';
54
import { OptionsType } from 'react-select/src/types';
6-
import Select from 'react-select';
7-
import { Styles } from 'react-select/src/styles';
5+
import { ArduinoSelect } from '../components/arduino-select';
86
import { ReactWidget, Message, Widget } from '@theia/core/lib/browser/widgets';
97
import { MonitorConfig } from '../../common/protocol/monitor-service';
108
import { MonitorModel } from './monitor-model';
@@ -74,11 +72,6 @@ export class MonitorWidget extends ReactWidget {
7472
this.update();
7573
}
7674

77-
onBeforeAttach(msg: Message): void {
78-
super.onBeforeAttach(msg);
79-
this.clearConsole();
80-
}
81-
8275
protected onAfterAttach(msg: Message): void {
8376
super.onAfterAttach(msg);
8477
this.monitorConnection.autoConnect = true;
@@ -131,8 +124,8 @@ export class MonitorWidget extends ReactWidget {
131124
<SerialMonitorSendField onSend={this.onSend} />
132125
</div>
133126
<div className='config'>
134-
{this.renderSelectField('arduino-serial-monitor-line-endings', lineEndings, lineEnding, this.onChangeLineEnding)}
135-
{this.renderSelectField('arduino-serial-monitor-baud-rates', baudRates, baudRate, this.onChangeBaudRate)}
127+
<ArduinoSelect className='serial-monitor-select' options={lineEndings} defaultValue={lineEnding} onChange={this.onChangeLineEnding} />
128+
<ArduinoSelect className='serial-monitor-select' options={baudRates} defaultValue={baudRate} onChange={this.onChangeBaudRate} />
136129
</div>
137130
</div>
138131
<div id='serial-monitor-output-container'>
@@ -155,67 +148,8 @@ export class MonitorWidget extends ReactWidget {
155148
this.model.baudRate = option.value;
156149
}
157150

158-
protected renderSelectField<T>(
159-
id: string,
160-
options: OptionsType<SelectOption<T>>,
161-
defaultValue: SelectOption<T>,
162-
onChange: (option: SelectOption<T>) => void): React.ReactNode {
163-
164-
const height = 25;
165-
const styles: Styles = {
166-
control: (styles, state) => ({
167-
...styles,
168-
width: 200,
169-
color: 'var(--theia-ui-font-color1)'
170-
}),
171-
dropdownIndicator: styles => ({
172-
...styles,
173-
padding: 0
174-
}),
175-
indicatorSeparator: () => ({
176-
display: 'none'
177-
}),
178-
indicatorsContainer: () => ({
179-
padding: '0px 5px'
180-
}),
181-
menu: styles => ({
182-
...styles,
183-
marginTop: 0
184-
})
185-
};
186-
const theme: ThemeConfig = theme => ({
187-
...theme,
188-
borderRadius: 0,
189-
spacing: {
190-
controlHeight: height,
191-
baseUnit: 2,
192-
menuGutter: 4
193-
}, colors: {
194-
...theme.colors,
195-
// `primary50`??? it's crazy but apparently, without this, we would get a light-blueish
196-
// color when selecting an option in the select by clicking and then not releasing the button.
197-
// https://react-select.com/styles#overriding-the-theme
198-
primary50: 'var(--theia-accent-color4)',
199-
}
200-
});
201-
const DropdownIndicator = () => <span className='fa fa-caret-down caret' />;
202-
return <Select
203-
options={options}
204-
defaultValue={defaultValue}
205-
onChange={onChange}
206-
components={{ DropdownIndicator }}
207-
theme={theme}
208-
styles={styles}
209-
maxMenuHeight={this.widgetHeight - 40}
210-
classNamePrefix='sms'
211-
className='serial-monitor-select'
212-
id={id}
213-
isSearchable={false}
214-
/>
215-
}
216151
}
217152

218-
219153
export namespace SerialMonitorSendField {
220154
export interface Props {
221155
readonly onSend: (text: string) => void
@@ -248,14 +182,12 @@ export class SerialMonitorSendField extends React.Component<SerialMonitorSendFie
248182
<input
249183
tabIndex={-1}
250184
ref={ref => this.inputField = ref}
251-
type='text' id='serial-monitor-send'
185+
id='serial-monitor-send'
186+
type='text'
252187
autoComplete='off'
253188
value={this.state.value}
254189
onChange={this.handleChange} />
255190
<button className='button' onClick={this.handleSubmit}>Send</button>
256-
{/* <input className='btn' type='submit' value='Submit' />
257-
<form onSubmit={this.handleSubmit}>
258-
</form> */}
259191
</React.Fragment>
260192
}
261193

@@ -268,6 +200,7 @@ export class SerialMonitorSendField extends React.Component<SerialMonitorSendFie
268200
this.setState({ value: '' });
269201
event.preventDefault();
270202
}
203+
271204
}
272205

273206
export namespace SerialMonitorOutput {
@@ -279,6 +212,9 @@ export namespace SerialMonitorOutput {
279212

280213
export class SerialMonitorOutput extends React.Component<SerialMonitorOutput.Props> {
281214

215+
/**
216+
* Do not touch it. It is used to be able to "follow" the serial monitor log.
217+
*/
282218
protected anchor: HTMLElement | null;
283219

284220
render() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
.arduino-select__control {
2+
border: var(--theia-layout-color2) var(--theia-border-width) solid !important;
3+
background: var(--theia-layout-color2) !important;
4+
}
5+
6+
.arduino-select__control:hover {
7+
border: var(--theia-layout-color2) var(--theia-border-width) solid !important;
8+
}
9+
10+
.arduino-select__control--is-focused {
11+
border-color: var(--theia-accent-color3) !important;
12+
box-shadow: none !important;
13+
}
14+
15+
.arduino-select__option--is-selected {
16+
background-color: var(--theia-accent-color3) !important;
17+
color: var(--theia-content-font-color0) !important;
18+
border-color: var(--theia-accent-color3) !important;
19+
}
20+
21+
.arduino-select__option--is-focused {
22+
background-color: var(--theia-accent-color4) !important;
23+
border-color: var(--theia-accent-color3) !important;
24+
}
25+
26+
.arduino-select__menu {
27+
background-color: var(--theia-layout-color2) !important;
28+
border: 1px solid var(--theia-accent-color3) !important;
29+
top: auto !important; /* to align the top of the menu with the bottom of the control */
30+
box-shadow: none !important;
31+
}
32+
33+
.arduino-select__control.arduino-select__control--menu-is-open {
34+
border: 1px solid !important;
35+
border-color: var(--theia-accent-color3) !important;
36+
border-bottom-color: var(--theia-layout-color2) !important; /* if the bottom border color has the same color as the background of the control, we make the border "invisible" */
37+
}
38+
39+
.arduino-select__value-container .arduino-select__single-value {
40+
color: var(--theia-ui-font-color1) !important;
41+
}
42+
43+
.arduino-select__menu-list {
44+
padding-top: 0 !important;
45+
padding-bottom: 0 !important;
46+
}

arduino-ide-extension/src/browser/style/index.css

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
@import './board-select-dialog.css';
33
@import './main.css';
44
@import './editor.css';
5-
@import './monitor.css';
5+
@import './monitor.css';
6+
@import './arduino-select.css';

arduino-ide-extension/src/browser/style/list-widget.css

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.library-tab-icon {
2-
-webkit-mask: url('library-tab-icon.svg');
3-
mask: url('library-tab-icon.svg');
2+
-webkit-mask: url('../icons/library-tab-icon.svg');
3+
mask: url('../icons/library-tab-icon.svg');
44
}
55

66
.arduino-list-widget {

arduino-ide-extension/src/browser/style/monitor.css

-48
Original file line numberDiff line numberDiff line change
@@ -78,51 +78,3 @@
7878
.p-TabBar-toolbar .item .clear-all {
7979
background: var(--theia-icon-clear) no-repeat;
8080
}
81-
82-
/* React Select Styles */
83-
.serial-monitor-select .sms__control {
84-
border: var(--theia-layout-color2) var(--theia-border-width) solid;
85-
background: var(--theia-layout-color2);
86-
}
87-
88-
.serial-monitor-select .sms__control:hover {
89-
border: var(--theia-layout-color2) var(--theia-border-width) solid !important;
90-
}
91-
92-
.serial-monitor-select .sms__control--is-focused {
93-
border-color: var(--theia-accent-color3) !important;
94-
box-shadow: none !important;
95-
}
96-
97-
.serial-monitor-select .sms__option--is-selected {
98-
background-color: var(--theia-accent-color3);
99-
color: var(--theia-content-font-color0);
100-
border-color: var(--theia-accent-color3);
101-
}
102-
103-
.serial-monitor-select .sms__option--is-focused {
104-
background-color: var(--theia-accent-color4);
105-
border-color: var(--theia-accent-color3);
106-
}
107-
108-
.serial-monitor-select .sms__menu {
109-
background-color: var(--theia-layout-color2);
110-
border: 1px solid var(--theia-accent-color3);
111-
top: auto !important; /* to align the top of the menu with the bottom of the control */
112-
box-shadow: none;
113-
}
114-
115-
.serial-monitor-select .sms__control.sms__control--menu-is-open {
116-
border: 1px solid;
117-
border-color: var(--theia-accent-color3) !important;
118-
border-bottom-color: var(--theia-layout-color2) !important; /* if the bottom border color has the same color as the background of the control, we make the border "invisible" */
119-
}
120-
121-
.serial-monitor-select .sms__value-container .sms__single-value {
122-
color: var(--theia-ui-font-color1);
123-
}
124-
125-
.sms__menu-list {
126-
padding-top: 0 !important;
127-
padding-bottom: 0 !important;
128-
}

0 commit comments

Comments
 (0)