|
@@ -1,11 +1,15 @@
|
1
|
|
-import Select from '@atlaskit/single-select';
|
|
1
|
+import AKButton from '@atlaskit/button';
|
|
2
|
+import AKDropdownMenu from '@atlaskit/dropdown-menu';
|
|
3
|
+import ExpandIcon from '@atlaskit/icon/glyph/expand';
|
2
|
4
|
import React, { Component } from 'react';
|
3
|
5
|
|
4
|
6
|
import { translate } from '../../base/i18n';
|
5
|
7
|
|
|
8
|
+const EXPAND_ICON = <ExpandIcon label = 'expand' />;
|
|
9
|
+
|
6
|
10
|
/**
|
7
|
|
- * React component for selecting a device from a select element. Wraps Select
|
8
|
|
- * with device selection specific logic.
|
|
11
|
+ * React component for selecting a device from a select element. Wraps
|
|
12
|
+ * AKDropdownMenu with device selection specific logic.
|
9
|
13
|
*
|
10
|
14
|
* @extends Component
|
11
|
15
|
*/
|
|
@@ -26,6 +30,11 @@ class DeviceSelector extends Component {
|
26
|
30
|
*/
|
27
|
31
|
hasPermission: React.PropTypes.bool,
|
28
|
32
|
|
|
33
|
+ /**
|
|
34
|
+ * CSS class for the icon to the left of the dropdown trigger.
|
|
35
|
+ */
|
|
36
|
+ icon: React.PropTypes.string,
|
|
37
|
+
|
29
|
38
|
/**
|
30
|
39
|
* If true, will render the selector disabled with a default selection.
|
31
|
40
|
*/
|
|
@@ -79,12 +88,12 @@ class DeviceSelector extends Component {
|
79
|
88
|
return this._renderNoDevices();
|
80
|
89
|
}
|
81
|
90
|
|
82
|
|
- const items = this.props.devices.map(this._createSelectItem);
|
|
91
|
+ const items = this.props.devices.map(this._createDropdownItem);
|
83
|
92
|
const defaultSelected = items.find(item =>
|
84
|
93
|
item.value === this.props.selectedDeviceId
|
85
|
94
|
);
|
86
|
95
|
|
87
|
|
- return this._createSelector({
|
|
96
|
+ return this._createDropdown({
|
88
|
97
|
defaultSelected,
|
89
|
98
|
isDisabled: this.props.isDisabled,
|
90
|
99
|
items,
|
|
@@ -93,14 +102,44 @@ class DeviceSelector extends Component {
|
93
|
102
|
}
|
94
|
103
|
|
95
|
104
|
/**
|
96
|
|
- * Creates an object in the format expected by Select for an option element.
|
|
105
|
+ * Creates an AtlasKit Button.
|
|
106
|
+ *
|
|
107
|
+ * @param {string} buttonText - The text to display within the button.
|
|
108
|
+ * @private
|
|
109
|
+ * @returns {ReactElement}
|
|
110
|
+ */
|
|
111
|
+ _createDropdownTrigger(buttonText) {
|
|
112
|
+ return (
|
|
113
|
+ <AKButton
|
|
114
|
+ className = 'device-selector-trigger'
|
|
115
|
+ iconAfter = { EXPAND_ICON }
|
|
116
|
+ iconBefore = { this._createDropdownIcon() }>
|
|
117
|
+ { buttonText }
|
|
118
|
+ </AKButton>
|
|
119
|
+ );
|
|
120
|
+ }
|
|
121
|
+
|
|
122
|
+ /**
|
|
123
|
+ * Creates a ReactComponent for displaying an icon.
|
|
124
|
+ *
|
|
125
|
+ * @private
|
|
126
|
+ * @returns {ReactElement}
|
|
127
|
+ */
|
|
128
|
+ _createDropdownIcon() {
|
|
129
|
+ return (
|
|
130
|
+ <span className = { `device-selector-icon ${this.props.icon}` } />
|
|
131
|
+ );
|
|
132
|
+ }
|
|
133
|
+
|
|
134
|
+ /**
|
|
135
|
+ * Creates an object in the format expected by AKDropdownMenu for an option.
|
97
|
136
|
*
|
98
|
137
|
* @param {MediaDeviceInfo} device - An object with a label and a deviceId.
|
99
|
138
|
* @private
|
100
|
139
|
* @returns {Object} The passed in media device description converted to a
|
101
|
|
- * format recognized as a valid Select item.
|
|
140
|
+ * format recognized as a valid AKDropdownMenu item.
|
102
|
141
|
*/
|
103
|
|
- _createSelectItem(device) {
|
|
142
|
+ _createDropdownItem(device) {
|
104
|
143
|
return {
|
105
|
144
|
content: device.label,
|
106
|
145
|
value: device.deviceId
|
|
@@ -108,44 +147,49 @@ class DeviceSelector extends Component {
|
108
|
147
|
}
|
109
|
148
|
|
110
|
149
|
/**
|
111
|
|
- * Creates a Select Component using passed in props and options.
|
|
150
|
+ * Creates a AKDropdownMenu Component using passed in props and options.
|
112
|
151
|
*
|
113
|
|
- * @param {Object} options - Additional configuration for display Select.
|
|
152
|
+ * @param {Object} options - Additional configuration for display.
|
114
|
153
|
* @param {Object} options.defaultSelected - The option that should be set
|
115
|
154
|
* as currently chosen.
|
116
|
|
- * @param {boolean} options.isDisabled - If true Select will not open on
|
117
|
|
- * click.
|
|
155
|
+ * @param {boolean} options.isDisabled - If true, AKDropdownMenu will not
|
|
156
|
+ * open on click.
|
118
|
157
|
* @param {Array} options.items - All the selectable options to display.
|
119
|
158
|
* @param {string} options.placeholder - The translation key to display when
|
120
|
159
|
* no selection has been made.
|
121
|
160
|
* @private
|
122
|
161
|
* @returns {ReactElement}
|
123
|
162
|
*/
|
124
|
|
- _createSelector(options) {
|
|
163
|
+ _createDropdown(options) {
|
|
164
|
+ const triggerText
|
|
165
|
+ = (options.defaultSelected && options.defaultSelected.content)
|
|
166
|
+ || options.placeholder;
|
|
167
|
+
|
125
|
168
|
return (
|
126
|
|
- <Select
|
127
|
|
- defaultSelected = { options.defaultSelected }
|
128
|
|
- isDisabled = { options.isDisabled }
|
129
|
|
- isFirstChild = { true }
|
|
169
|
+ <AKDropdownMenu
|
|
170
|
+ { ...(options.isDisabled && { isOpen: !options.isDisabled }) }
|
130
|
171
|
items = { [ { items: options.items || [] } ] }
|
131
|
|
- label = { this.props.t(this.props.label) }
|
132
|
172
|
noMatchesFound
|
133
|
173
|
= { this.props.t('deviceSelection.noOtherDevices') }
|
134
|
|
- onSelected = { this._onSelect }
|
135
|
|
- placeholder = { this.props.t(options.placeholder) }
|
136
|
|
- shouldFitContainer = { true } />
|
|
174
|
+ onItemActivated = { this._onSelect }>
|
|
175
|
+ { this._createDropdownTrigger(triggerText) }
|
|
176
|
+ </AKDropdownMenu>
|
137
|
177
|
);
|
138
|
178
|
}
|
139
|
179
|
|
140
|
180
|
/**
|
141
|
181
|
* Invokes the passed in callback to notify of selection changes.
|
142
|
182
|
*
|
143
|
|
- * @param {Object} selection - Event returned from Select.
|
|
183
|
+ * @param {Object} selection - Event from choosing a AKDropdownMenu option.
|
144
|
184
|
* @private
|
145
|
185
|
* @returns {void}
|
146
|
186
|
*/
|
147
|
187
|
_onSelect(selection) {
|
148
|
|
- this.props.onSelect(selection.item.value);
|
|
188
|
+ const newDeviceId = selection.item.value;
|
|
189
|
+
|
|
190
|
+ if (this.props.selectedDeviceId !== newDeviceId) {
|
|
191
|
+ this.props.onSelect(selection.item.value);
|
|
192
|
+ }
|
149
|
193
|
}
|
150
|
194
|
|
151
|
195
|
/**
|
|
@@ -156,23 +200,23 @@ class DeviceSelector extends Component {
|
156
|
200
|
* @returns {ReactElement}
|
157
|
201
|
*/
|
158
|
202
|
_renderNoDevices() {
|
159
|
|
- return this._createSelector({
|
|
203
|
+ return this._createDropdown({
|
160
|
204
|
isDisabled: true,
|
161
|
|
- placeholder: 'settings.noDevice'
|
|
205
|
+ placeholder: this.props.t('settings.noDevice')
|
162
|
206
|
});
|
163
|
207
|
}
|
164
|
208
|
|
165
|
209
|
/**
|
166
|
|
- * Creates a Select Component that is disabled and has a placeholder stating
|
167
|
|
- * there is no permission to display the devices.
|
|
210
|
+ * Creates a AKDropdownMenu Component that is disabled and has a placeholder
|
|
211
|
+ * stating there is no permission to display the devices.
|
168
|
212
|
*
|
169
|
213
|
* @private
|
170
|
214
|
* @returns {ReactElement}
|
171
|
215
|
*/
|
172
|
216
|
_renderNoPermission() {
|
173
|
|
- return this._createSelector({
|
|
217
|
+ return this._createDropdown({
|
174
|
218
|
isDisabled: true,
|
175
|
|
- placeholder: 'settings.noPermission'
|
|
219
|
+ placeholder: this.props.t('settings.noPermission')
|
176
|
220
|
});
|
177
|
221
|
}
|
178
|
222
|
}
|