@workday/canvas-kit-preview-react 9.0.0-alpha.364-next.3 → 9.0.0-alpha.382-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commonjs/color-picker/lib/ColorPicker.js +24 -47
- package/dist/commonjs/color-picker/lib/parts/ColorReset.js +32 -23
- package/dist/commonjs/color-picker/lib/parts/SwatchBook.js +26 -39
- package/dist/commonjs/form-field/lib/FormField.js +10 -33
- package/dist/commonjs/form-field/lib/FormFieldHint.js +8 -31
- package/dist/commonjs/form-field/lib/FormFieldInput.js +6 -17
- package/dist/commonjs/form-field/lib/FormFieldLabel.js +8 -31
- package/dist/commonjs/form-field/lib/hooks/useFormFieldHint.js +4 -5
- package/dist/commonjs/form-field/lib/hooks/useFormFieldInput.js +5 -6
- package/dist/commonjs/form-field/lib/hooks/useFormFieldLabel.js +4 -5
- package/dist/commonjs/form-field/lib/hooks/useFormFieldModel.js +8 -16
- package/dist/commonjs/form-field/lib/hooks/useFormFieldOrientation.js +3 -3
- package/dist/commonjs/menu/lib/Menu.js +96 -129
- package/dist/commonjs/menu/lib/MenuItem.js +94 -109
- package/dist/commonjs/pill/lib/Pill.js +55 -60
- package/dist/commonjs/pill/lib/PillAvatar.js +6 -17
- package/dist/commonjs/pill/lib/PillCount.js +7 -30
- package/dist/commonjs/pill/lib/PillIcon.js +8 -31
- package/dist/commonjs/pill/lib/PillIconButton.js +13 -36
- package/dist/commonjs/pill/lib/PillLabel.js +10 -33
- package/dist/commonjs/pill/lib/usePillModel.js +8 -16
- package/dist/commonjs/segmented-control/lib/SegmentedControl.js +6 -7
- package/dist/commonjs/segmented-control/lib/SegmentedControlItem.js +24 -49
- package/dist/commonjs/segmented-control/lib/SegmentedControlList.js +13 -38
- package/dist/commonjs/segmented-control/lib/hooks/useSegmentedControlItem.js +8 -10
- package/dist/commonjs/segmented-control/lib/hooks/useSegmentedControlModel.js +31 -31
- package/dist/commonjs/select/lib/Select.js +147 -189
- package/dist/commonjs/select/lib/SelectBase.js +106 -101
- package/dist/commonjs/select/lib/SelectMenu.js +53 -84
- package/dist/commonjs/select/lib/SelectOption.js +33 -47
- package/dist/commonjs/select/lib/scrolling.js +6 -7
- package/dist/commonjs/select/lib/utils.js +4 -4
- package/dist/commonjs/side-panel/lib/SidePanel.js +36 -51
- package/dist/commonjs/side-panel/lib/SidePanelToggleButton.js +17 -40
- package/dist/commonjs/side-panel/lib/hooks.js +20 -20
- package/dist/commonjs/status-indicator/lib/StatusIndicator.js +10 -34
- package/dist/commonjs/status-indicator/lib/StatusIndicatorIcon.js +9 -21
- package/dist/commonjs/status-indicator/lib/StatusIndicatorLabel.js +5 -28
- package/dist/commonjs/status-indicator/lib/hooks/useStatusIndicatorModel.js +6 -15
- package/dist/commonjs/text-area/lib/TextArea.js +8 -31
- package/dist/commonjs/text-area/lib/TextAreaField.d.ts.map +1 -1
- package/dist/commonjs/text-area/lib/TextAreaField.js +12 -36
- package/dist/commonjs/text-input/lib/TextInput.js +8 -31
- package/dist/commonjs/text-input/lib/TextInputField.d.ts.map +1 -1
- package/dist/commonjs/text-input/lib/TextInputField.js +12 -24
- package/dist/commonjs/text-input/lib/hooks/useTextInputField.js +3 -3
- package/dist/commonjs/text-input/lib/hooks/useTextInputModel.js +1 -1
- package/dist/es6/color-picker/lib/ColorPicker.js +15 -38
- package/dist/es6/color-picker/lib/parts/ColorReset.js +27 -18
- package/dist/es6/color-picker/lib/parts/SwatchBook.js +21 -34
- package/dist/es6/form-field/lib/FormField.js +4 -27
- package/dist/es6/form-field/lib/FormFieldHint.js +4 -27
- package/dist/es6/form-field/lib/FormFieldInput.js +3 -14
- package/dist/es6/form-field/lib/FormFieldLabel.js +4 -27
- package/dist/es6/form-field/lib/hooks/useFormFieldHint.js +2 -3
- package/dist/es6/form-field/lib/hooks/useFormFieldInput.js +3 -4
- package/dist/es6/form-field/lib/hooks/useFormFieldLabel.js +2 -3
- package/dist/es6/form-field/lib/hooks/useFormFieldModel.js +8 -16
- package/dist/es6/form-field/lib/hooks/useFormFieldOrientation.js +2 -2
- package/dist/es6/menu/lib/Menu.js +91 -125
- package/dist/es6/menu/lib/MenuItem.js +90 -106
- package/dist/es6/pill/lib/Pill.js +45 -50
- package/dist/es6/pill/lib/PillAvatar.js +3 -14
- package/dist/es6/pill/lib/PillCount.js +4 -27
- package/dist/es6/pill/lib/PillIcon.js +3 -26
- package/dist/es6/pill/lib/PillIconButton.js +7 -30
- package/dist/es6/pill/lib/PillLabel.js +5 -28
- package/dist/es6/pill/lib/usePillModel.js +8 -16
- package/dist/es6/segmented-control/lib/SegmentedControl.js +2 -3
- package/dist/es6/segmented-control/lib/SegmentedControlItem.js +17 -42
- package/dist/es6/segmented-control/lib/SegmentedControlList.js +9 -34
- package/dist/es6/segmented-control/lib/hooks/useSegmentedControlItem.js +5 -7
- package/dist/es6/segmented-control/lib/hooks/useSegmentedControlModel.js +29 -29
- package/dist/es6/select/lib/Select.js +144 -186
- package/dist/es6/select/lib/SelectBase.js +99 -94
- package/dist/es6/select/lib/SelectMenu.js +49 -80
- package/dist/es6/select/lib/SelectOption.js +30 -44
- package/dist/es6/select/lib/scrolling.js +6 -7
- package/dist/es6/select/lib/utils.js +4 -4
- package/dist/es6/side-panel/lib/SidePanel.js +31 -46
- package/dist/es6/side-panel/lib/SidePanelToggleButton.js +10 -33
- package/dist/es6/side-panel/lib/hooks.js +19 -19
- package/dist/es6/status-indicator/lib/StatusIndicator.js +5 -29
- package/dist/es6/status-indicator/lib/StatusIndicatorIcon.js +6 -18
- package/dist/es6/status-indicator/lib/StatusIndicatorLabel.js +3 -26
- package/dist/es6/status-indicator/lib/hooks/useStatusIndicatorModel.js +6 -15
- package/dist/es6/text-area/lib/TextArea.js +4 -27
- package/dist/es6/text-area/lib/TextAreaField.d.ts.map +1 -1
- package/dist/es6/text-area/lib/TextAreaField.js +9 -33
- package/dist/es6/text-input/lib/TextInput.js +4 -27
- package/dist/es6/text-input/lib/TextInputField.d.ts.map +1 -1
- package/dist/es6/text-input/lib/TextInputField.js +9 -21
- package/dist/es6/text-input/lib/hooks/useTextInputField.js +1 -1
- package/dist/es6/text-input/lib/hooks/useTextInputModel.js +1 -1
- package/package.json +3 -4
- package/text-area/lib/TextAreaField.tsx +6 -2
- package/text-input/lib/TextInputField.tsx +6 -2
|
@@ -1,30 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __extends = (this && this.__extends) || (function () {
|
|
3
|
-
var extendStatics = function (d, b) {
|
|
4
|
-
extendStatics = Object.setPrototypeOf ||
|
|
5
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
-
return extendStatics(d, b);
|
|
8
|
-
};
|
|
9
|
-
return function (d, b) {
|
|
10
|
-
if (typeof b !== "function" && b !== null)
|
|
11
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
-
extendStatics(d, b);
|
|
13
|
-
function __() { this.constructor = d; }
|
|
14
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
-
};
|
|
16
|
-
})();
|
|
17
|
-
var __assign = (this && this.__assign) || function () {
|
|
18
|
-
__assign = Object.assign || function(t) {
|
|
19
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
20
|
-
s = arguments[i];
|
|
21
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
22
|
-
t[p] = s[p];
|
|
23
|
-
}
|
|
24
|
-
return t;
|
|
25
|
-
};
|
|
26
|
-
return __assign.apply(this, arguments);
|
|
27
|
-
};
|
|
28
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
29
3
|
if (k2 === undefined) k2 = k;
|
|
30
4
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
@@ -44,42 +18,30 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
44
18
|
__setModuleDefault(result, mod);
|
|
45
19
|
return result;
|
|
46
20
|
};
|
|
47
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
48
|
-
var t = {};
|
|
49
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
50
|
-
t[p] = s[p];
|
|
51
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
52
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
53
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
54
|
-
t[p[i]] = s[p[i]];
|
|
55
|
-
}
|
|
56
|
-
return t;
|
|
57
|
-
};
|
|
58
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
59
22
|
exports.Select = void 0;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
_this.state = {
|
|
23
|
+
const React = __importStar(require("react"));
|
|
24
|
+
const common_1 = require("@workday/canvas-kit-react/common");
|
|
25
|
+
const SelectMenu_1 = require("./SelectMenu");
|
|
26
|
+
const SelectBase_1 = require("./SelectBase");
|
|
27
|
+
const utils_1 = require("./utils");
|
|
28
|
+
class SelectContainer extends React.Component {
|
|
29
|
+
constructor(props) {
|
|
30
|
+
super(props);
|
|
31
|
+
this.state = {
|
|
70
32
|
focusedOptionIndex: 0,
|
|
71
33
|
menuVisibility: 'closed',
|
|
72
34
|
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
35
|
+
this.localButtonRef = React.createRef();
|
|
36
|
+
this.inputRef = React.createRef();
|
|
37
|
+
this.menuRef = React.createRef();
|
|
76
38
|
// For type-ahead functionality
|
|
77
|
-
|
|
78
|
-
|
|
39
|
+
this.keysSoFar = '';
|
|
40
|
+
this.clearKeysSoFarTimeout = 500;
|
|
79
41
|
// Cached values
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
42
|
+
this.normalizedOptions = [];
|
|
43
|
+
this.areOptionsDefined = () => {
|
|
44
|
+
const { options } = this.props;
|
|
83
45
|
if (!options || options.length === 0) {
|
|
84
46
|
return false;
|
|
85
47
|
}
|
|
@@ -88,15 +50,15 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
88
50
|
// Store normalized options since the options prop can take on multiple
|
|
89
51
|
// forms: an array of strings or an array of objects (sometimes with
|
|
90
52
|
// arbitrary keys)
|
|
91
|
-
|
|
92
|
-
|
|
53
|
+
this.setNormalizedOptions = () => {
|
|
54
|
+
const { options } = this.props;
|
|
93
55
|
// Abort if options weren't defined
|
|
94
|
-
if (!
|
|
56
|
+
if (!this.areOptionsDefined()) {
|
|
95
57
|
return;
|
|
96
58
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
59
|
+
this.normalizedOptions = options.map(option => {
|
|
60
|
+
let data = {};
|
|
61
|
+
let disabled, id, label, value;
|
|
100
62
|
if (typeof option === 'string') {
|
|
101
63
|
disabled = false;
|
|
102
64
|
id = common_1.generateUniqueId();
|
|
@@ -111,21 +73,19 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
111
73
|
label = option.label || option.value;
|
|
112
74
|
}
|
|
113
75
|
return {
|
|
114
|
-
data
|
|
115
|
-
disabled
|
|
116
|
-
id
|
|
117
|
-
label
|
|
118
|
-
value
|
|
76
|
+
data,
|
|
77
|
+
disabled,
|
|
78
|
+
id,
|
|
79
|
+
label,
|
|
80
|
+
value,
|
|
119
81
|
};
|
|
120
82
|
});
|
|
121
83
|
};
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
for (var i = startIndex; i < endIndex; i++) {
|
|
126
|
-
var label = _this.normalizedOptions[i].label.toLowerCase();
|
|
84
|
+
this.getIndexByStartString = (startIndex, startString, endIndex = this.normalizedOptions.length, ignoreDisabled = true) => {
|
|
85
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
86
|
+
const label = this.normalizedOptions[i].label.toLowerCase();
|
|
127
87
|
if (label.indexOf(startString.toLowerCase()) === 0) {
|
|
128
|
-
if (!ignoreDisabled || (ignoreDisabled && !
|
|
88
|
+
if (!ignoreDisabled || (ignoreDisabled && !this.normalizedOptions[i].disabled)) {
|
|
129
89
|
return i;
|
|
130
90
|
}
|
|
131
91
|
}
|
|
@@ -141,64 +101,64 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
141
101
|
// Up/Down key means "focus the first enabled option above/below the currently
|
|
142
102
|
// focused option", or pressing the Home/End key means "focus the first/last
|
|
143
103
|
// enabled option on the menu."
|
|
144
|
-
|
|
104
|
+
this.focusNextEnabledOption = (startIndex, direction) => {
|
|
145
105
|
// Ensure direction is non-zero
|
|
146
106
|
if (direction === 0) {
|
|
147
107
|
return;
|
|
148
108
|
}
|
|
149
|
-
|
|
150
|
-
|
|
109
|
+
const numOptions = this.normalizedOptions.length;
|
|
110
|
+
let currentIndex = startIndex;
|
|
151
111
|
// Check if currentIndex refers to an enabled option. If not, keep moving
|
|
152
112
|
// the index in the prescribed direction until we find an enabled option.
|
|
153
113
|
while (currentIndex >= 0 &&
|
|
154
114
|
currentIndex < numOptions &&
|
|
155
|
-
|
|
115
|
+
this.normalizedOptions[currentIndex].disabled) {
|
|
156
116
|
currentIndex += direction;
|
|
157
117
|
}
|
|
158
118
|
// Update the focused index only if currentIndex is inbounds and
|
|
159
119
|
// refers to an enabled option
|
|
160
120
|
if (currentIndex >= 0 &&
|
|
161
121
|
currentIndex < numOptions &&
|
|
162
|
-
!
|
|
163
|
-
|
|
122
|
+
!this.normalizedOptions[currentIndex].disabled) {
|
|
123
|
+
this.setState({ focusedOptionIndex: currentIndex });
|
|
164
124
|
}
|
|
165
125
|
};
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
focusedOptionIndex: utils_1.getCorrectedIndexByValue(
|
|
126
|
+
this.updateStateFromValue = () => {
|
|
127
|
+
this.setState({
|
|
128
|
+
focusedOptionIndex: utils_1.getCorrectedIndexByValue(this.normalizedOptions, this.props.value),
|
|
169
129
|
});
|
|
170
130
|
};
|
|
171
|
-
|
|
172
|
-
if (
|
|
173
|
-
|
|
131
|
+
this.focusButton = () => {
|
|
132
|
+
if (this.localButtonRef.current) {
|
|
133
|
+
this.localButtonRef.current.focus();
|
|
174
134
|
}
|
|
175
135
|
};
|
|
176
|
-
|
|
177
|
-
if (
|
|
178
|
-
clearTimeout(
|
|
136
|
+
this.setMenuAnimationTimeout = (callback) => {
|
|
137
|
+
if (this.menuAnimationTimer) {
|
|
138
|
+
clearTimeout(this.menuAnimationTimer);
|
|
179
139
|
}
|
|
180
|
-
|
|
140
|
+
this.menuAnimationTimer = setTimeout(callback, SelectMenu_1.menuAnimationDuration);
|
|
181
141
|
};
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
142
|
+
this.openMenu = () => {
|
|
143
|
+
this.setState({ menuVisibility: 'opening' });
|
|
144
|
+
this.setMenuAnimationTimeout(() => {
|
|
145
|
+
this.setState({ menuVisibility: 'opened' });
|
|
186
146
|
});
|
|
187
147
|
};
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
148
|
+
this.closeMenu = () => {
|
|
149
|
+
this.setState({ menuVisibility: 'closing' });
|
|
150
|
+
this.setMenuAnimationTimeout(() => {
|
|
151
|
+
this.setState({
|
|
192
152
|
// Reset the focused option to the currently selected option in case
|
|
193
153
|
// the user focused a different option but chose not to select it. The
|
|
194
154
|
// next time the menu opens, focus should begin on the selected option.
|
|
195
|
-
focusedOptionIndex: utils_1.getCorrectedIndexByValue(
|
|
155
|
+
focusedOptionIndex: utils_1.getCorrectedIndexByValue(this.normalizedOptions, this.props.value),
|
|
196
156
|
menuVisibility: 'closed',
|
|
197
157
|
});
|
|
198
158
|
});
|
|
199
159
|
};
|
|
200
|
-
|
|
201
|
-
|
|
160
|
+
this.toggleMenu = (open) => {
|
|
161
|
+
const { menuVisibility } = this.state;
|
|
202
162
|
if (open) {
|
|
203
163
|
switch (menuVisibility) {
|
|
204
164
|
// We're opening a menu which is currently closed: set the menu state
|
|
@@ -206,14 +166,14 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
206
166
|
// from 0 opacity in the open state to the targeted 1.0 opacity in
|
|
207
167
|
// the opening state.
|
|
208
168
|
case 'closed':
|
|
209
|
-
|
|
169
|
+
this.setState({ menuVisibility: 'open' }, this.openMenu);
|
|
210
170
|
break;
|
|
211
171
|
// We're opening a menu which is in the process of closing. Since the
|
|
212
172
|
// menu isn't closed, there's no need to set the open state: kick off
|
|
213
173
|
// openMenu immediately.
|
|
214
174
|
case 'close':
|
|
215
175
|
case 'closing':
|
|
216
|
-
|
|
176
|
+
this.openMenu();
|
|
217
177
|
break;
|
|
218
178
|
// Otherwise, we're opening a menu is already opened or in the process of
|
|
219
179
|
// opening; no need to do anything further.
|
|
@@ -226,14 +186,14 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
226
186
|
// We're closing a menu which is currently opened: set the menu state to
|
|
227
187
|
// close before kicking off closeMenu.
|
|
228
188
|
case 'opened':
|
|
229
|
-
|
|
189
|
+
this.setState({ menuVisibility: 'close' }, this.closeMenu);
|
|
230
190
|
break;
|
|
231
191
|
// We're closing a menu which is in the process of opening. Since the
|
|
232
192
|
// menu isn't opened, there's no need to set the close state: kick off
|
|
233
193
|
// closeMenu immediately.
|
|
234
194
|
case 'open':
|
|
235
195
|
case 'opening':
|
|
236
|
-
|
|
196
|
+
this.closeMenu();
|
|
237
197
|
break;
|
|
238
198
|
// Otherwise, we're closing a menu which is already closed or in the process
|
|
239
199
|
// of closing; no need to do anything further.
|
|
@@ -246,28 +206,28 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
246
206
|
// In order for Select to be usable as a controlled component, we
|
|
247
207
|
// need to programmatically change the value of the SelectInput
|
|
248
208
|
// in such a way that triggers its change event
|
|
249
|
-
|
|
250
|
-
if (
|
|
251
|
-
|
|
209
|
+
this.fireChangeEvent = (value) => {
|
|
210
|
+
if (this.inputRef && this.inputRef.current) {
|
|
211
|
+
const nativeInputValue = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this.inputRef.current), 'value');
|
|
252
212
|
if (nativeInputValue && nativeInputValue.set) {
|
|
253
|
-
nativeInputValue.set.call(
|
|
213
|
+
nativeInputValue.set.call(this.inputRef.current, value);
|
|
254
214
|
}
|
|
255
|
-
|
|
215
|
+
let event;
|
|
256
216
|
if (typeof Event === 'function') {
|
|
257
217
|
// Modern browsers
|
|
258
|
-
|
|
218
|
+
event = new Event('change', { bubbles: true });
|
|
259
219
|
}
|
|
260
220
|
else {
|
|
261
221
|
// IE 11
|
|
262
|
-
|
|
263
|
-
|
|
222
|
+
event = document.createEvent('Event');
|
|
223
|
+
event.initEvent('change', true, true);
|
|
264
224
|
}
|
|
265
|
-
|
|
225
|
+
this.inputRef.current.dispatchEvent(event);
|
|
266
226
|
}
|
|
267
227
|
};
|
|
268
|
-
|
|
228
|
+
this.handleKeyboardTypeAhead = (key, numOptions) => {
|
|
269
229
|
// Abort immediately if the menu is the process of closing
|
|
270
|
-
if (
|
|
230
|
+
if (this.state.menuVisibility === 'closing') {
|
|
271
231
|
return;
|
|
272
232
|
}
|
|
273
233
|
// Set the starting point of the search to one of two locations
|
|
@@ -284,45 +244,45 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
284
244
|
// "San Francisco" as you type "san " (because "san " still matches
|
|
285
245
|
// "San Francisco") and then advances focus to "San Jose" after you
|
|
286
246
|
// type the "j" at the end.
|
|
287
|
-
|
|
288
|
-
?
|
|
289
|
-
:
|
|
247
|
+
let start = this.keysSoFar.length === 0
|
|
248
|
+
? this.state.focusedOptionIndex + 1
|
|
249
|
+
: this.state.focusedOptionIndex;
|
|
290
250
|
// If the starting point is beyond the list of options, reset it
|
|
291
251
|
// to the beginning of the list
|
|
292
252
|
start = start === numOptions ? 0 : start;
|
|
293
|
-
|
|
294
|
-
|
|
253
|
+
this.keysSoFar += key;
|
|
254
|
+
this.startClearKeysSoFarTimer();
|
|
295
255
|
// First, look for a match from start to end
|
|
296
|
-
|
|
297
|
-
matchIndex =
|
|
256
|
+
let matchIndex;
|
|
257
|
+
matchIndex = this.getIndexByStartString(start, this.keysSoFar);
|
|
298
258
|
// If a match isn't found between start and end, wrap the search
|
|
299
259
|
// around and search again from the beginning (0) to start
|
|
300
260
|
if (matchIndex === -1) {
|
|
301
|
-
matchIndex =
|
|
261
|
+
matchIndex = this.getIndexByStartString(0, this.keysSoFar, start);
|
|
302
262
|
}
|
|
303
263
|
// A match was found...
|
|
304
264
|
if (matchIndex > -1) {
|
|
305
|
-
if (
|
|
265
|
+
if (this.state.menuVisibility === 'closed') {
|
|
306
266
|
// If the menu is closed, fire the change event
|
|
307
|
-
|
|
267
|
+
this.fireChangeEvent(this.normalizedOptions[matchIndex].value);
|
|
308
268
|
}
|
|
309
269
|
else {
|
|
310
270
|
// Otherwise the menu is visible (or at least partially visible);
|
|
311
271
|
// focus the matched option
|
|
312
|
-
|
|
272
|
+
this.setState({ focusedOptionIndex: matchIndex });
|
|
313
273
|
}
|
|
314
274
|
}
|
|
315
275
|
};
|
|
316
|
-
|
|
317
|
-
if (
|
|
318
|
-
clearTimeout(
|
|
276
|
+
this.startClearKeysSoFarTimer = () => {
|
|
277
|
+
if (this.clearKeysSoFarTimer) {
|
|
278
|
+
clearTimeout(this.clearKeysSoFarTimer);
|
|
319
279
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
},
|
|
280
|
+
this.clearKeysSoFarTimer = setTimeout(() => {
|
|
281
|
+
this.keysSoFar = '';
|
|
282
|
+
}, this.clearKeysSoFarTimeout);
|
|
323
283
|
};
|
|
324
|
-
|
|
325
|
-
|
|
284
|
+
this.handleClick = (event) => {
|
|
285
|
+
const { menuVisibility } = this.state;
|
|
326
286
|
switch (menuVisibility) {
|
|
327
287
|
// If we click the button while the menu is in the process of closing,
|
|
328
288
|
// we want to toggle the menu back on. However, we also need to focus
|
|
@@ -330,48 +290,48 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
330
290
|
// callback (because the menu already exists).
|
|
331
291
|
case 'close':
|
|
332
292
|
case 'closing':
|
|
333
|
-
if (
|
|
334
|
-
|
|
293
|
+
if (this.menuRef.current) {
|
|
294
|
+
this.menuRef.current.focus();
|
|
335
295
|
}
|
|
336
|
-
|
|
296
|
+
this.toggleMenu(true);
|
|
337
297
|
break;
|
|
338
298
|
case 'closed':
|
|
339
|
-
|
|
299
|
+
this.toggleMenu(true);
|
|
340
300
|
break;
|
|
341
301
|
// Otherwise, the menu is opened or in the process of opening; toggle
|
|
342
302
|
// the menu off.
|
|
343
303
|
default:
|
|
344
|
-
|
|
304
|
+
this.toggleMenu(false);
|
|
345
305
|
break;
|
|
346
306
|
}
|
|
347
307
|
};
|
|
348
|
-
|
|
308
|
+
this.handleOptionSelection = (index) => {
|
|
349
309
|
// Abort if a disabled option was clicked (we ignore these clicks)
|
|
350
|
-
if (
|
|
310
|
+
if (this.normalizedOptions[index].disabled) {
|
|
351
311
|
return;
|
|
352
312
|
}
|
|
353
313
|
// Toggle menu off, shift focus back to the button, and fire change event
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
314
|
+
this.toggleMenu(false);
|
|
315
|
+
this.focusButton();
|
|
316
|
+
this.fireChangeEvent(this.normalizedOptions[index].value);
|
|
357
317
|
};
|
|
358
|
-
|
|
318
|
+
this.handleMenuCloseOnKeyPress = () => {
|
|
359
319
|
// Toggle menu off and shift focus back to the button
|
|
360
|
-
|
|
361
|
-
|
|
320
|
+
this.handleClose();
|
|
321
|
+
this.focusButton();
|
|
362
322
|
};
|
|
363
|
-
|
|
364
|
-
|
|
323
|
+
this.handleClose = () => {
|
|
324
|
+
this.toggleMenu(false);
|
|
365
325
|
};
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
326
|
+
this.handleKeyDown = (event) => {
|
|
327
|
+
const { options } = this.props;
|
|
328
|
+
const numOptions = options.length;
|
|
329
|
+
const { focusedOptionIndex, menuVisibility } = this.state;
|
|
330
|
+
let isShortcut = false;
|
|
371
331
|
// Check for type-ahead first
|
|
372
332
|
if (event.key.length === 1 && event.key.match(/\S/)) {
|
|
373
333
|
isShortcut = true;
|
|
374
|
-
|
|
334
|
+
this.handleKeyboardTypeAhead(event.key, numOptions);
|
|
375
335
|
}
|
|
376
336
|
else {
|
|
377
337
|
switch (event.key) {
|
|
@@ -381,25 +341,25 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
381
341
|
case 'Down': // IE/Edge specific value
|
|
382
342
|
isShortcut = true;
|
|
383
343
|
if (menuVisibility === 'closed' || menuVisibility === 'closing') {
|
|
384
|
-
|
|
344
|
+
this.toggleMenu(true);
|
|
385
345
|
}
|
|
386
346
|
else {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
347
|
+
const direction = event.key === 'ArrowUp' || event.key === 'Up' ? -1 : 1;
|
|
348
|
+
const startIndex = focusedOptionIndex + direction;
|
|
349
|
+
this.focusNextEnabledOption(startIndex, direction);
|
|
390
350
|
}
|
|
391
351
|
break;
|
|
392
352
|
case 'Home':
|
|
393
353
|
case 'End':
|
|
394
354
|
isShortcut = true;
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
355
|
+
const direction = event.key === 'Home' ? 1 : -1;
|
|
356
|
+
const startIndex = event.key === 'Home' ? 0 : numOptions - 1;
|
|
357
|
+
this.focusNextEnabledOption(startIndex, direction);
|
|
398
358
|
break;
|
|
399
359
|
case 'Tab':
|
|
400
360
|
if (menuVisibility !== 'closed') {
|
|
401
361
|
isShortcut = true;
|
|
402
|
-
|
|
362
|
+
this.handleMenuCloseOnKeyPress();
|
|
403
363
|
}
|
|
404
364
|
break;
|
|
405
365
|
case 'Spacebar':
|
|
@@ -407,14 +367,14 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
407
367
|
isShortcut = true;
|
|
408
368
|
// If the user is in the middle of typing a string, treat
|
|
409
369
|
// space key as type-ahead rather than option selection
|
|
410
|
-
if (
|
|
411
|
-
|
|
370
|
+
if (this.keysSoFar !== '') {
|
|
371
|
+
this.handleKeyboardTypeAhead(' ', numOptions);
|
|
412
372
|
}
|
|
413
373
|
else if (menuVisibility === 'closed' || menuVisibility === 'closing') {
|
|
414
|
-
|
|
374
|
+
this.toggleMenu(true);
|
|
415
375
|
}
|
|
416
376
|
else {
|
|
417
|
-
|
|
377
|
+
this.handleOptionSelection(focusedOptionIndex);
|
|
418
378
|
}
|
|
419
379
|
break;
|
|
420
380
|
case 'Enter':
|
|
@@ -424,7 +384,7 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
424
384
|
isShortcut = false;
|
|
425
385
|
}
|
|
426
386
|
else {
|
|
427
|
-
|
|
387
|
+
this.handleOptionSelection(focusedOptionIndex);
|
|
428
388
|
}
|
|
429
389
|
break;
|
|
430
390
|
default:
|
|
@@ -445,7 +405,7 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
445
405
|
event.preventDefault();
|
|
446
406
|
}
|
|
447
407
|
};
|
|
448
|
-
|
|
408
|
+
this.setNormalizedOptions();
|
|
449
409
|
// We need a local ref (RefObject) to the Select component's underlying
|
|
450
410
|
// button to manage focus within the component and to serve as its Popper
|
|
451
411
|
// Menu's anchorElement. If the buttonRef prop (to be forwarded to the
|
|
@@ -464,14 +424,13 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
464
424
|
// or call buttonRef with the underlying button element if it was a
|
|
465
425
|
// callback ref.
|
|
466
426
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
467
|
-
|
|
468
|
-
return _this;
|
|
427
|
+
this.forwardedButtonRef = common_1.useForkRef(props.buttonRef, this.localButtonRef);
|
|
469
428
|
}
|
|
470
|
-
|
|
429
|
+
componentDidMount() {
|
|
471
430
|
this.updateStateFromValue();
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
|
|
431
|
+
}
|
|
432
|
+
componentDidUpdate(prevProps) {
|
|
433
|
+
const { options, value } = this.props;
|
|
475
434
|
if (options !== prevProps.options) {
|
|
476
435
|
this.setNormalizedOptions();
|
|
477
436
|
this.updateStateFromValue();
|
|
@@ -479,8 +438,8 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
479
438
|
if (value !== prevProps.value) {
|
|
480
439
|
this.updateStateFromValue();
|
|
481
440
|
}
|
|
482
|
-
}
|
|
483
|
-
|
|
441
|
+
}
|
|
442
|
+
componentWillUnmount() {
|
|
484
443
|
// Clear timers
|
|
485
444
|
if (this.menuAnimationTimer) {
|
|
486
445
|
clearTimeout(this.menuAnimationTimer);
|
|
@@ -488,14 +447,14 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
488
447
|
if (this.clearKeysSoFarTimer) {
|
|
489
448
|
clearTimeout(this.clearKeysSoFarTimer);
|
|
490
449
|
}
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
|
|
450
|
+
}
|
|
451
|
+
render() {
|
|
452
|
+
const { value,
|
|
494
453
|
// Strip props we don't want to pass down from elemProps
|
|
495
|
-
buttonRef
|
|
496
|
-
|
|
454
|
+
buttonRef, options, onKeyDown, ...elemProps } = this.props;
|
|
455
|
+
const { focusedOptionIndex, menuVisibility } = this.state;
|
|
497
456
|
// Don't pass in event handlers if options weren't defined
|
|
498
|
-
|
|
457
|
+
const eventHandlers = this.areOptionsDefined()
|
|
499
458
|
? {
|
|
500
459
|
onClick: this.handleClick,
|
|
501
460
|
onKeyDown: this.handleKeyDown,
|
|
@@ -503,17 +462,16 @@ var SelectContainer = /** @class */ (function (_super) {
|
|
|
503
462
|
onOptionSelection: this.handleOptionSelection,
|
|
504
463
|
}
|
|
505
464
|
: {};
|
|
506
|
-
return (React.createElement(SelectBase_1.SelectBase,
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
}(React.Component));
|
|
465
|
+
return (React.createElement(SelectBase_1.SelectBase, Object.assign({ forwardedButtonRef: this.forwardedButtonRef, localButtonRef: this.localButtonRef, focusedOptionIndex: focusedOptionIndex, inputRef: this.inputRef, menuRef: this.menuRef, menuVisibility: menuVisibility, options: this.normalizedOptions, value: value }, eventHandlers, elemProps)));
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
SelectContainer.ErrorType = common_1.ErrorType;
|
|
511
469
|
exports.Select = common_1.createComponent('button')({
|
|
512
470
|
displayName: 'Select',
|
|
513
|
-
Component:
|
|
471
|
+
Component: (props, ref, Element) => (
|
|
514
472
|
// Select is still a class component, so we render a renamed version of it
|
|
515
473
|
// (SelectContainer) and pass it ref and Element
|
|
516
|
-
React.createElement(SelectContainer,
|
|
474
|
+
React.createElement(SelectContainer, Object.assign({ as: Element, buttonRef: ref }, props))),
|
|
517
475
|
subComponents: {
|
|
518
476
|
ErrorType: common_1.ErrorType,
|
|
519
477
|
},
|