@khanacademy/wonder-blocks-dropdown 2.3.20 → 2.4.3
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/es/index.js +1681 -2466
- package/dist/index.js +2676 -3342
- package/package.json +17 -16
- package/src/components/__tests__/dropdown-core.test.js +3 -1
- package/src/components/dropdown-core.js +29 -16
- package/src/components/single-select.stories.js +68 -0
- package/src/__tests__/index.test.js +0 -23
package/dist/es/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import _extends from '@babel/runtime/helpers/extends';
|
|
2
|
+
import { Component, createElement, Fragment, cloneElement, Children, createRef } from 'react';
|
|
2
3
|
import { StyleSheet, css } from 'aphrodite';
|
|
3
4
|
import { Link } from 'react-router-dom';
|
|
4
5
|
import { any } from 'prop-types';
|
|
@@ -6,312 +7,18 @@ import Color, { mix, fade, SemanticColor } from '@khanacademy/wonder-blocks-colo
|
|
|
6
7
|
import Spacing from '@khanacademy/wonder-blocks-spacing';
|
|
7
8
|
import { LabelMedium, styles as styles$a, LabelLarge } from '@khanacademy/wonder-blocks-typography';
|
|
8
9
|
import { getClickableBehavior, isClientSideUrl, ClickableBehavior } from '@khanacademy/wonder-blocks-clickable';
|
|
9
|
-
import { addStyle, View
|
|
10
|
+
import { addStyle, View } from '@khanacademy/wonder-blocks-core';
|
|
11
|
+
import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/objectWithoutPropertiesLoose';
|
|
10
12
|
import Icon, { icons } from '@khanacademy/wonder-blocks-icon';
|
|
11
13
|
import ReactDOM from 'react-dom';
|
|
12
14
|
import { Popper } from 'react-popper';
|
|
13
15
|
import { VariableSizeList } from 'react-window';
|
|
14
16
|
import { maybeGetPortalMountedModalHostElement } from '@khanacademy/wonder-blocks-modal';
|
|
15
17
|
import { withActionScheduler } from '@khanacademy/wonder-blocks-timing';
|
|
16
|
-
import PopperJS from 'popper.js';
|
|
17
18
|
import IconButton from '@khanacademy/wonder-blocks-icon-button';
|
|
18
19
|
import { Strut } from '@khanacademy/wonder-blocks-layout';
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
if (!(instance instanceof Constructor)) {
|
|
22
|
-
throw new TypeError("Cannot call a class as a function");
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function _defineProperties(target, props) {
|
|
27
|
-
for (var i = 0; i < props.length; i++) {
|
|
28
|
-
var descriptor = props[i];
|
|
29
|
-
descriptor.enumerable = descriptor.enumerable || false;
|
|
30
|
-
descriptor.configurable = true;
|
|
31
|
-
if ("value" in descriptor) descriptor.writable = true;
|
|
32
|
-
Object.defineProperty(target, descriptor.key, descriptor);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function _createClass(Constructor, protoProps, staticProps) {
|
|
37
|
-
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
38
|
-
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
39
|
-
return Constructor;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function _defineProperty(obj, key, value) {
|
|
43
|
-
if (key in obj) {
|
|
44
|
-
Object.defineProperty(obj, key, {
|
|
45
|
-
value: value,
|
|
46
|
-
enumerable: true,
|
|
47
|
-
configurable: true,
|
|
48
|
-
writable: true
|
|
49
|
-
});
|
|
50
|
-
} else {
|
|
51
|
-
obj[key] = value;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return obj;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function _extends() {
|
|
58
|
-
_extends = Object.assign || function (target) {
|
|
59
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
60
|
-
var source = arguments[i];
|
|
61
|
-
|
|
62
|
-
for (var key in source) {
|
|
63
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
64
|
-
target[key] = source[key];
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return target;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
return _extends.apply(this, arguments);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function ownKeys(object, enumerableOnly) {
|
|
76
|
-
var keys = Object.keys(object);
|
|
77
|
-
|
|
78
|
-
if (Object.getOwnPropertySymbols) {
|
|
79
|
-
var symbols = Object.getOwnPropertySymbols(object);
|
|
80
|
-
if (enumerableOnly) symbols = symbols.filter(function (sym) {
|
|
81
|
-
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
82
|
-
});
|
|
83
|
-
keys.push.apply(keys, symbols);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return keys;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function _objectSpread2(target) {
|
|
90
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
91
|
-
var source = arguments[i] != null ? arguments[i] : {};
|
|
92
|
-
|
|
93
|
-
if (i % 2) {
|
|
94
|
-
ownKeys(Object(source), true).forEach(function (key) {
|
|
95
|
-
_defineProperty(target, key, source[key]);
|
|
96
|
-
});
|
|
97
|
-
} else if (Object.getOwnPropertyDescriptors) {
|
|
98
|
-
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
99
|
-
} else {
|
|
100
|
-
ownKeys(Object(source)).forEach(function (key) {
|
|
101
|
-
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return target;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function _inherits(subClass, superClass) {
|
|
110
|
-
if (typeof superClass !== "function" && superClass !== null) {
|
|
111
|
-
throw new TypeError("Super expression must either be null or a function");
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
115
|
-
constructor: {
|
|
116
|
-
value: subClass,
|
|
117
|
-
writable: true,
|
|
118
|
-
configurable: true
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
if (superClass) _setPrototypeOf(subClass, superClass);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function _getPrototypeOf(o) {
|
|
125
|
-
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
|
|
126
|
-
return o.__proto__ || Object.getPrototypeOf(o);
|
|
127
|
-
};
|
|
128
|
-
return _getPrototypeOf(o);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function _setPrototypeOf(o, p) {
|
|
132
|
-
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
|
|
133
|
-
o.__proto__ = p;
|
|
134
|
-
return o;
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
return _setPrototypeOf(o, p);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function _isNativeReflectConstruct() {
|
|
141
|
-
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
|
142
|
-
if (Reflect.construct.sham) return false;
|
|
143
|
-
if (typeof Proxy === "function") return true;
|
|
144
|
-
|
|
145
|
-
try {
|
|
146
|
-
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
|
|
147
|
-
return true;
|
|
148
|
-
} catch (e) {
|
|
149
|
-
return false;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
154
|
-
if (source == null) return {};
|
|
155
|
-
var target = {};
|
|
156
|
-
var sourceKeys = Object.keys(source);
|
|
157
|
-
var key, i;
|
|
158
|
-
|
|
159
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
|
160
|
-
key = sourceKeys[i];
|
|
161
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
162
|
-
target[key] = source[key];
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return target;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function _objectWithoutProperties(source, excluded) {
|
|
169
|
-
if (source == null) return {};
|
|
170
|
-
|
|
171
|
-
var target = _objectWithoutPropertiesLoose(source, excluded);
|
|
172
|
-
|
|
173
|
-
var key, i;
|
|
174
|
-
|
|
175
|
-
if (Object.getOwnPropertySymbols) {
|
|
176
|
-
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
177
|
-
|
|
178
|
-
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
|
179
|
-
key = sourceSymbolKeys[i];
|
|
180
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
181
|
-
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
182
|
-
target[key] = source[key];
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return target;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function _assertThisInitialized(self) {
|
|
190
|
-
if (self === void 0) {
|
|
191
|
-
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return self;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
function _possibleConstructorReturn(self, call) {
|
|
198
|
-
if (call && (typeof call === "object" || typeof call === "function")) {
|
|
199
|
-
return call;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return _assertThisInitialized(self);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function _createSuper(Derived) {
|
|
206
|
-
var hasNativeReflectConstruct = _isNativeReflectConstruct();
|
|
207
|
-
|
|
208
|
-
return function _createSuperInternal() {
|
|
209
|
-
var Super = _getPrototypeOf(Derived),
|
|
210
|
-
result;
|
|
211
|
-
|
|
212
|
-
if (hasNativeReflectConstruct) {
|
|
213
|
-
var NewTarget = _getPrototypeOf(this).constructor;
|
|
214
|
-
|
|
215
|
-
result = Reflect.construct(Super, arguments, NewTarget);
|
|
216
|
-
} else {
|
|
217
|
-
result = Super.apply(this, arguments);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return _possibleConstructorReturn(this, result);
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
function _toConsumableArray(arr) {
|
|
225
|
-
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function _arrayWithoutHoles(arr) {
|
|
229
|
-
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function _iterableToArray(iter) {
|
|
233
|
-
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
function _unsupportedIterableToArray(o, minLen) {
|
|
237
|
-
if (!o) return;
|
|
238
|
-
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
|
239
|
-
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
240
|
-
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
241
|
-
if (n === "Map" || n === "Set") return Array.from(o);
|
|
242
|
-
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
function _arrayLikeToArray(arr, len) {
|
|
246
|
-
if (len == null || len > arr.length) len = arr.length;
|
|
247
|
-
|
|
248
|
-
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
|
249
|
-
|
|
250
|
-
return arr2;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function _nonIterableSpread() {
|
|
254
|
-
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
function _createForOfIteratorHelper(o, allowArrayLike) {
|
|
258
|
-
var it;
|
|
259
|
-
|
|
260
|
-
if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
|
|
261
|
-
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
|
|
262
|
-
if (it) o = it;
|
|
263
|
-
var i = 0;
|
|
264
|
-
|
|
265
|
-
var F = function () {};
|
|
266
|
-
|
|
267
|
-
return {
|
|
268
|
-
s: F,
|
|
269
|
-
n: function () {
|
|
270
|
-
if (i >= o.length) return {
|
|
271
|
-
done: true
|
|
272
|
-
};
|
|
273
|
-
return {
|
|
274
|
-
done: false,
|
|
275
|
-
value: o[i++]
|
|
276
|
-
};
|
|
277
|
-
},
|
|
278
|
-
e: function (e) {
|
|
279
|
-
throw e;
|
|
280
|
-
},
|
|
281
|
-
f: F
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
var normalCompletion = true,
|
|
289
|
-
didErr = false,
|
|
290
|
-
err;
|
|
291
|
-
return {
|
|
292
|
-
s: function () {
|
|
293
|
-
it = o[Symbol.iterator]();
|
|
294
|
-
},
|
|
295
|
-
n: function () {
|
|
296
|
-
var step = it.next();
|
|
297
|
-
normalCompletion = step.done;
|
|
298
|
-
return step;
|
|
299
|
-
},
|
|
300
|
-
e: function (e) {
|
|
301
|
-
didErr = true;
|
|
302
|
-
err = e;
|
|
303
|
-
},
|
|
304
|
-
f: function () {
|
|
305
|
-
try {
|
|
306
|
-
if (!normalCompletion && it.return != null) it.return();
|
|
307
|
-
} finally {
|
|
308
|
-
if (didErr) throw err;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
var keyCodes = {
|
|
21
|
+
const keyCodes = {
|
|
315
22
|
tab: 9,
|
|
316
23
|
enter: 13,
|
|
317
24
|
escape: 27,
|
|
@@ -319,142 +26,127 @@ var keyCodes = {
|
|
|
319
26
|
up: 38,
|
|
320
27
|
down: 40
|
|
321
28
|
};
|
|
322
|
-
|
|
29
|
+
const selectDropdownStyle = {
|
|
323
30
|
marginTop: Spacing.xSmall_8,
|
|
324
31
|
marginBottom: Spacing.xSmall_8
|
|
325
32
|
}; // Filterable dropdown has minimum dimensions requested from Design.
|
|
326
33
|
// Note that these can be overridden by the provided style if needed.
|
|
327
34
|
|
|
328
|
-
|
|
35
|
+
const filterableDropdownStyle = {
|
|
329
36
|
minHeight: 100,
|
|
330
37
|
maxHeight: 384
|
|
331
38
|
};
|
|
332
|
-
|
|
39
|
+
const searchInputStyle = {
|
|
333
40
|
margin: Spacing.xSmall_8,
|
|
334
41
|
marginTop: Spacing.xxxSmall_4
|
|
335
42
|
}; // The default item height
|
|
336
43
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
44
|
+
const DROPDOWN_ITEM_HEIGHT = 40;
|
|
45
|
+
const SEPARATOR_ITEM_HEIGHT = 9;
|
|
46
|
+
const SEARCH_ITEM_HEIGHT = DROPDOWN_ITEM_HEIGHT + searchInputStyle.margin + searchInputStyle.marginTop; // The default labels that will be used by different components
|
|
340
47
|
|
|
341
|
-
|
|
48
|
+
const defaultLabels = {
|
|
342
49
|
clearSearch: "Clear search",
|
|
343
50
|
filter: "Filter",
|
|
344
51
|
noResults: "No results",
|
|
345
52
|
selectNoneLabel: "Select none",
|
|
346
|
-
selectAllLabel:
|
|
347
|
-
return "Select all (".concat(numOptions, ")");
|
|
348
|
-
},
|
|
53
|
+
selectAllLabel: numOptions => `Select all (${numOptions})`,
|
|
349
54
|
noneSelected: "0 items",
|
|
350
|
-
someSelected:
|
|
351
|
-
return "".concat(numSelectedValues, " items");
|
|
352
|
-
},
|
|
55
|
+
someSelected: numSelectedValues => `${numSelectedValues} items`,
|
|
353
56
|
allSelected: "All items"
|
|
354
57
|
};
|
|
355
58
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
59
|
+
const {
|
|
60
|
+
blue,
|
|
61
|
+
white,
|
|
62
|
+
offBlack,
|
|
63
|
+
offBlack32
|
|
64
|
+
} = Color;
|
|
65
|
+
const StyledAnchor = addStyle("a");
|
|
66
|
+
const StyledButton = addStyle("button");
|
|
67
|
+
const StyledLink = addStyle(Link);
|
|
363
68
|
/**
|
|
364
69
|
* The action item trigger actions, such as navigating to a different page or
|
|
365
70
|
* opening a modal. Supply the href and/or onClick props. Used as a child of
|
|
366
71
|
* ActionMenu.
|
|
367
72
|
*/
|
|
368
73
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
function ActionItem() {
|
|
375
|
-
_classCallCheck(this, ActionItem);
|
|
376
|
-
|
|
377
|
-
return _super.apply(this, arguments);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
_createClass(ActionItem, [{
|
|
381
|
-
key: "render",
|
|
382
|
-
value: function render() {
|
|
383
|
-
var _this$props = this.props,
|
|
384
|
-
skipClientNav = _this$props.skipClientNav,
|
|
385
|
-
disabled = _this$props.disabled,
|
|
386
|
-
href = _this$props.href,
|
|
387
|
-
target = _this$props.target,
|
|
388
|
-
indent = _this$props.indent,
|
|
389
|
-
label = _this$props.label,
|
|
390
|
-
onClick = _this$props.onClick,
|
|
391
|
-
role = _this$props.role,
|
|
392
|
-
style = _this$props.style,
|
|
393
|
-
testId = _this$props.testId;
|
|
394
|
-
var router = this.context.router;
|
|
395
|
-
var ClickableBehavior = getClickableBehavior(href, skipClientNav, router);
|
|
396
|
-
return /*#__PURE__*/createElement(ClickableBehavior, {
|
|
397
|
-
disabled: disabled,
|
|
398
|
-
onClick: onClick,
|
|
399
|
-
href: href,
|
|
400
|
-
role: role,
|
|
401
|
-
target: target
|
|
402
|
-
}, function (state, childrenProps) {
|
|
403
|
-
var pressed = state.pressed,
|
|
404
|
-
hovered = state.hovered,
|
|
405
|
-
focused = state.focused;
|
|
406
|
-
var defaultStyle = [styles.shared, disabled && styles.disabled, !disabled && (pressed ? styles.active : (hovered || focused) && styles.focus), // pass optional styles from react-window (if applies)
|
|
407
|
-
style];
|
|
408
|
-
|
|
409
|
-
var props = _objectSpread2({
|
|
410
|
-
"data-test-id": testId,
|
|
411
|
-
disabled: disabled,
|
|
412
|
-
role: role,
|
|
413
|
-
style: [defaultStyle]
|
|
414
|
-
}, childrenProps);
|
|
415
|
-
|
|
416
|
-
var children = /*#__PURE__*/createElement(Fragment, null, /*#__PURE__*/createElement(LabelMedium, {
|
|
417
|
-
style: [indent && styles.indent, styles.label]
|
|
418
|
-
}, label));
|
|
419
|
-
|
|
420
|
-
if (href && !disabled) {
|
|
421
|
-
return router && !skipClientNav && isClientSideUrl(href) ? /*#__PURE__*/createElement(StyledLink, _extends({}, props, {
|
|
422
|
-
to: href
|
|
423
|
-
}), children) : /*#__PURE__*/createElement(StyledAnchor, _extends({}, props, {
|
|
424
|
-
href: href,
|
|
425
|
-
target: target
|
|
426
|
-
}), children);
|
|
427
|
-
} else {
|
|
428
|
-
return /*#__PURE__*/createElement(StyledButton, _extends({
|
|
429
|
-
type: "button"
|
|
430
|
-
}, props, {
|
|
431
|
-
disabled: disabled
|
|
432
|
-
}), children);
|
|
433
|
-
}
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
|
-
}], [{
|
|
437
|
-
key: "isClassOf",
|
|
438
|
-
value: function isClassOf(instance) {
|
|
439
|
-
return instance && instance.type && instance.type.__IS_ACTION_ITEM__;
|
|
440
|
-
}
|
|
441
|
-
}]);
|
|
74
|
+
class ActionItem extends Component {
|
|
75
|
+
static isClassOf(instance) {
|
|
76
|
+
return instance && instance.type && instance.type.__IS_ACTION_ITEM__;
|
|
77
|
+
}
|
|
442
78
|
|
|
443
|
-
|
|
444
|
-
|
|
79
|
+
render() {
|
|
80
|
+
const {
|
|
81
|
+
skipClientNav,
|
|
82
|
+
disabled,
|
|
83
|
+
href,
|
|
84
|
+
target,
|
|
85
|
+
indent,
|
|
86
|
+
label,
|
|
87
|
+
onClick,
|
|
88
|
+
role,
|
|
89
|
+
style,
|
|
90
|
+
testId
|
|
91
|
+
} = this.props;
|
|
92
|
+
const {
|
|
93
|
+
router
|
|
94
|
+
} = this.context;
|
|
95
|
+
const ClickableBehavior = getClickableBehavior(href, skipClientNav, router);
|
|
96
|
+
return /*#__PURE__*/createElement(ClickableBehavior, {
|
|
97
|
+
disabled: disabled,
|
|
98
|
+
onClick: onClick,
|
|
99
|
+
href: href,
|
|
100
|
+
role: role,
|
|
101
|
+
target: target
|
|
102
|
+
}, (state, childrenProps) => {
|
|
103
|
+
const {
|
|
104
|
+
pressed,
|
|
105
|
+
hovered,
|
|
106
|
+
focused
|
|
107
|
+
} = state;
|
|
108
|
+
const defaultStyle = [styles.shared, disabled && styles.disabled, !disabled && (pressed ? styles.active : (hovered || focused) && styles.focus), // pass optional styles from react-window (if applies)
|
|
109
|
+
style];
|
|
110
|
+
|
|
111
|
+
const props = _extends({
|
|
112
|
+
"data-test-id": testId,
|
|
113
|
+
disabled,
|
|
114
|
+
role,
|
|
115
|
+
style: [defaultStyle]
|
|
116
|
+
}, childrenProps);
|
|
117
|
+
|
|
118
|
+
const children = /*#__PURE__*/createElement(Fragment, null, /*#__PURE__*/createElement(LabelMedium, {
|
|
119
|
+
style: [indent && styles.indent, styles.label]
|
|
120
|
+
}, label));
|
|
121
|
+
|
|
122
|
+
if (href && !disabled) {
|
|
123
|
+
return router && !skipClientNav && isClientSideUrl(href) ? /*#__PURE__*/createElement(StyledLink, _extends({}, props, {
|
|
124
|
+
to: href
|
|
125
|
+
}), children) : /*#__PURE__*/createElement(StyledAnchor, _extends({}, props, {
|
|
126
|
+
href: href,
|
|
127
|
+
target: target
|
|
128
|
+
}), children);
|
|
129
|
+
} else {
|
|
130
|
+
return /*#__PURE__*/createElement(StyledButton, _extends({
|
|
131
|
+
type: "button"
|
|
132
|
+
}, props, {
|
|
133
|
+
disabled: disabled
|
|
134
|
+
}), children);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
445
138
|
|
|
446
|
-
|
|
139
|
+
}
|
|
140
|
+
ActionItem.contextTypes = {
|
|
447
141
|
router: any
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
_defineProperty(ActionItem, "defaultProps", {
|
|
142
|
+
};
|
|
143
|
+
ActionItem.defaultProps = {
|
|
451
144
|
disabled: false,
|
|
452
145
|
indent: false,
|
|
453
146
|
role: "menuitem"
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
var styles = StyleSheet.create({
|
|
147
|
+
};
|
|
148
|
+
ActionItem.__IS_ACTION_ITEM__ = true;
|
|
149
|
+
const styles = StyleSheet.create({
|
|
458
150
|
shared: {
|
|
459
151
|
background: white,
|
|
460
152
|
color: offBlack,
|
|
@@ -496,9 +188,11 @@ var styles = StyleSheet.create({
|
|
|
496
188
|
}
|
|
497
189
|
});
|
|
498
190
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
191
|
+
const {
|
|
192
|
+
offBlack: offBlack$1,
|
|
193
|
+
offBlack32: offBlack32$1,
|
|
194
|
+
white: white$1
|
|
195
|
+
} = Color;
|
|
502
196
|
/**
|
|
503
197
|
* Props describing the state of the OptionItem, shared by the checkbox
|
|
504
198
|
* component,
|
|
@@ -508,11 +202,13 @@ var offBlack$1 = Color.offBlack,
|
|
|
508
202
|
* The check component used by OptionItem.
|
|
509
203
|
*/
|
|
510
204
|
function Check(props) {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
205
|
+
const {
|
|
206
|
+
disabled,
|
|
207
|
+
selected,
|
|
208
|
+
pressed,
|
|
209
|
+
hovered,
|
|
210
|
+
focused
|
|
211
|
+
} = props;
|
|
516
212
|
return /*#__PURE__*/createElement(Icon, {
|
|
517
213
|
icon: icons.check,
|
|
518
214
|
size: "small",
|
|
@@ -520,7 +216,7 @@ function Check(props) {
|
|
|
520
216
|
style: [styles$1.bounds, !selected && styles$1.hide]
|
|
521
217
|
});
|
|
522
218
|
}
|
|
523
|
-
|
|
219
|
+
const styles$1 = StyleSheet.create({
|
|
524
220
|
bounds: {
|
|
525
221
|
// Semantically, this are the constants for a small-sized icon
|
|
526
222
|
minHeight: 16,
|
|
@@ -535,15 +231,17 @@ var styles$1 = StyleSheet.create({
|
|
|
535
231
|
// Please don't copy it automatically and check with designers before using.
|
|
536
232
|
// If the intended icon is a check without a checkbox, you should be using
|
|
537
233
|
// icons.check from the Wonder Blocks Icon package.
|
|
538
|
-
|
|
234
|
+
const checkboxCheck = {
|
|
539
235
|
small: "M11.263 4.324a1 1 0 1 1 1.474 1.352l-5.5 6a1 1 0 0 1-1.505-.036l-2.5-3a1 1 0 1 1 1.536-1.28L6.536 9.48l4.727-5.157z"
|
|
540
236
|
};
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
237
|
+
const {
|
|
238
|
+
blue: blue$1,
|
|
239
|
+
white: white$2,
|
|
240
|
+
offBlack16,
|
|
241
|
+
offBlack32: offBlack32$2,
|
|
242
|
+
offBlack50,
|
|
243
|
+
offWhite
|
|
244
|
+
} = Color;
|
|
547
245
|
/**
|
|
548
246
|
* Props describing the state of the OptionItem, shared by the check
|
|
549
247
|
* component,
|
|
@@ -553,15 +251,17 @@ var blue$1 = Color.blue,
|
|
|
553
251
|
* The checkbox component used by OptionItem.
|
|
554
252
|
*/
|
|
555
253
|
function Checkbox(props) {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
254
|
+
const {
|
|
255
|
+
disabled,
|
|
256
|
+
selected,
|
|
257
|
+
pressed,
|
|
258
|
+
hovered,
|
|
259
|
+
focused
|
|
260
|
+
} = props;
|
|
261
|
+
const activeBlue = mix(offBlack32$2, blue$1);
|
|
262
|
+
const clickInteraction = pressed || hovered || focused;
|
|
263
|
+
const bgColor = disabled ? offWhite : selected && !clickInteraction ? blue$1 : white$2;
|
|
264
|
+
const checkColor = disabled ? offBlack32$2 : clickInteraction ? pressed ? activeBlue : blue$1 : white$2;
|
|
565
265
|
return /*#__PURE__*/createElement(View, {
|
|
566
266
|
style: [styles$2.checkbox, (clickInteraction || selected && !disabled) && styles$2.noBorder, disabled && styles$2.disabledCheckbox, {
|
|
567
267
|
backgroundColor: bgColor
|
|
@@ -573,7 +273,7 @@ function Checkbox(props) {
|
|
|
573
273
|
style: [disabled && selected && styles$2.disabledCheckFormatting]
|
|
574
274
|
}));
|
|
575
275
|
}
|
|
576
|
-
|
|
276
|
+
const styles$2 = StyleSheet.create({
|
|
577
277
|
checkbox: {
|
|
578
278
|
// Semantically, this are the constants for a small-sized icon
|
|
579
279
|
minHeight: 16,
|
|
@@ -599,124 +299,104 @@ var styles$2 = StyleSheet.create({
|
|
|
599
299
|
}
|
|
600
300
|
});
|
|
601
301
|
|
|
302
|
+
const _excluded = ["disabled", "label", "role", "selected", "testId", "style", "value", "onClick", "onToggle", "variant"];
|
|
303
|
+
|
|
602
304
|
/**
|
|
603
305
|
* For option items that can be selected in a dropdown, selection denoted either
|
|
604
306
|
* with a check ✔️ or a checkbox ☑️. Use as children in SingleSelect or
|
|
605
307
|
* MultiSelect.
|
|
606
308
|
*/
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
618
|
-
args[_key] = arguments[_key];
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
_this = _super.call.apply(_super, [this].concat(args));
|
|
622
|
-
|
|
623
|
-
_defineProperty(_assertThisInitialized(_this), "handleClick", function () {
|
|
624
|
-
var _this$props = _this.props,
|
|
625
|
-
onClick = _this$props.onClick,
|
|
626
|
-
onToggle = _this$props.onToggle,
|
|
627
|
-
value = _this$props.value;
|
|
309
|
+
class OptionItem extends Component {
|
|
310
|
+
constructor(...args) {
|
|
311
|
+
super(...args);
|
|
312
|
+
|
|
313
|
+
this.handleClick = () => {
|
|
314
|
+
const {
|
|
315
|
+
onClick,
|
|
316
|
+
onToggle,
|
|
317
|
+
value
|
|
318
|
+
} = this.props;
|
|
628
319
|
onToggle(value);
|
|
629
320
|
|
|
630
321
|
if (onClick) {
|
|
631
322
|
onClick();
|
|
632
323
|
}
|
|
633
|
-
}
|
|
324
|
+
};
|
|
325
|
+
}
|
|
634
326
|
|
|
635
|
-
|
|
327
|
+
static isClassOf(instance) {
|
|
328
|
+
return instance && instance.type && instance.type.__IS_OPTION_ITEM__;
|
|
636
329
|
}
|
|
637
330
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
} else {
|
|
644
|
-
return Checkbox;
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
}, {
|
|
648
|
-
key: "render",
|
|
649
|
-
value: function render() {
|
|
650
|
-
var _this$props2 = this.props,
|
|
651
|
-
disabled = _this$props2.disabled,
|
|
652
|
-
label = _this$props2.label,
|
|
653
|
-
role = _this$props2.role,
|
|
654
|
-
selected = _this$props2.selected,
|
|
655
|
-
testId = _this$props2.testId,
|
|
656
|
-
style = _this$props2.style,
|
|
657
|
-
value = _this$props2.value,
|
|
658
|
-
onClick = _this$props2.onClick,
|
|
659
|
-
onToggle = _this$props2.onToggle,
|
|
660
|
-
variant = _this$props2.variant,
|
|
661
|
-
sharedProps = _objectWithoutProperties(_this$props2, ["disabled", "label", "role", "selected", "testId", "style", "value", "onClick", "onToggle", "variant"]);
|
|
662
|
-
|
|
663
|
-
var ClickableBehavior = getClickableBehavior();
|
|
664
|
-
var CheckComponent = this.getCheckComponent();
|
|
665
|
-
return /*#__PURE__*/createElement(ClickableBehavior, {
|
|
666
|
-
disabled: disabled,
|
|
667
|
-
onClick: this.handleClick,
|
|
668
|
-
role: role
|
|
669
|
-
}, function (state, childrenProps) {
|
|
670
|
-
var pressed = state.pressed,
|
|
671
|
-
hovered = state.hovered,
|
|
672
|
-
focused = state.focused;
|
|
673
|
-
var defaultStyle = [styles$3.itemContainer, pressed ? styles$3.active : (hovered || focused) && styles$3.focus, disabled && styles$3.disabled, // pass optional styles from react-window (if applies)
|
|
674
|
-
style];
|
|
675
|
-
return /*#__PURE__*/createElement(View, _extends({}, sharedProps, {
|
|
676
|
-
testId: testId,
|
|
677
|
-
style: defaultStyle,
|
|
678
|
-
"aria-selected": selected ? "true" : "false",
|
|
679
|
-
role: role
|
|
680
|
-
}, childrenProps), /*#__PURE__*/createElement(CheckComponent, {
|
|
681
|
-
disabled: disabled,
|
|
682
|
-
selected: selected,
|
|
683
|
-
pressed: pressed,
|
|
684
|
-
hovered: hovered,
|
|
685
|
-
focused: focused
|
|
686
|
-
}), /*#__PURE__*/createElement(LabelMedium, {
|
|
687
|
-
style: styles$3.label
|
|
688
|
-
}, label));
|
|
689
|
-
});
|
|
690
|
-
}
|
|
691
|
-
}], [{
|
|
692
|
-
key: "isClassOf",
|
|
693
|
-
value: function isClassOf(instance) {
|
|
694
|
-
return instance && instance.type && instance.type.__IS_OPTION_ITEM__;
|
|
331
|
+
getCheckComponent() {
|
|
332
|
+
if (this.props.variant === "check") {
|
|
333
|
+
return Check;
|
|
334
|
+
} else {
|
|
335
|
+
return Checkbox;
|
|
695
336
|
}
|
|
696
|
-
}
|
|
337
|
+
}
|
|
697
338
|
|
|
698
|
-
|
|
699
|
-
|
|
339
|
+
render() {
|
|
340
|
+
const _this$props = this.props,
|
|
341
|
+
{
|
|
342
|
+
disabled,
|
|
343
|
+
label,
|
|
344
|
+
role,
|
|
345
|
+
selected,
|
|
346
|
+
testId,
|
|
347
|
+
style
|
|
348
|
+
} = _this$props,
|
|
349
|
+
sharedProps = _objectWithoutPropertiesLoose(_this$props, _excluded);
|
|
350
|
+
|
|
351
|
+
const ClickableBehavior = getClickableBehavior();
|
|
352
|
+
const CheckComponent = this.getCheckComponent();
|
|
353
|
+
return /*#__PURE__*/createElement(ClickableBehavior, {
|
|
354
|
+
disabled: disabled,
|
|
355
|
+
onClick: this.handleClick,
|
|
356
|
+
role: role
|
|
357
|
+
}, (state, childrenProps) => {
|
|
358
|
+
const {
|
|
359
|
+
pressed,
|
|
360
|
+
hovered,
|
|
361
|
+
focused
|
|
362
|
+
} = state;
|
|
363
|
+
const defaultStyle = [styles$3.itemContainer, pressed ? styles$3.active : (hovered || focused) && styles$3.focus, disabled && styles$3.disabled, // pass optional styles from react-window (if applies)
|
|
364
|
+
style];
|
|
365
|
+
return /*#__PURE__*/createElement(View, _extends({}, sharedProps, {
|
|
366
|
+
testId: testId,
|
|
367
|
+
style: defaultStyle,
|
|
368
|
+
"aria-selected": selected ? "true" : "false",
|
|
369
|
+
role: role
|
|
370
|
+
}, childrenProps), /*#__PURE__*/createElement(CheckComponent, {
|
|
371
|
+
disabled: disabled,
|
|
372
|
+
selected: selected,
|
|
373
|
+
pressed: pressed,
|
|
374
|
+
hovered: hovered,
|
|
375
|
+
focused: focused
|
|
376
|
+
}), /*#__PURE__*/createElement(LabelMedium, {
|
|
377
|
+
style: styles$3.label
|
|
378
|
+
}, label));
|
|
379
|
+
});
|
|
380
|
+
}
|
|
700
381
|
|
|
701
|
-
|
|
382
|
+
}
|
|
383
|
+
OptionItem.contextTypes = {
|
|
702
384
|
router: any
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
_defineProperty(OptionItem, "defaultProps", {
|
|
385
|
+
};
|
|
386
|
+
OptionItem.defaultProps = {
|
|
706
387
|
disabled: false,
|
|
707
|
-
onToggle:
|
|
708
|
-
return void 0;
|
|
709
|
-
},
|
|
388
|
+
onToggle: () => void 0,
|
|
710
389
|
role: "option",
|
|
711
390
|
selected: false
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
391
|
+
};
|
|
392
|
+
OptionItem.__IS_OPTION_ITEM__ = true;
|
|
393
|
+
const {
|
|
394
|
+
blue: blue$2,
|
|
395
|
+
white: white$3,
|
|
396
|
+
offBlack: offBlack$2,
|
|
397
|
+
offBlack32: offBlack32$3
|
|
398
|
+
} = Color;
|
|
399
|
+
const styles$3 = StyleSheet.create({
|
|
720
400
|
itemContainer: {
|
|
721
401
|
flexDirection: "row",
|
|
722
402
|
backgroundColor: white$3,
|
|
@@ -756,46 +436,32 @@ var styles$3 = StyleSheet.create({
|
|
|
756
436
|
}
|
|
757
437
|
});
|
|
758
438
|
|
|
439
|
+
// Separator item in a dropdown, used to denote a semantic break.
|
|
440
|
+
|
|
759
441
|
/**
|
|
760
442
|
* A separator used in a dropdown menu.
|
|
761
443
|
*/
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
var _super = _createSuper(SeparatorItem);
|
|
766
|
-
|
|
767
|
-
function SeparatorItem() {
|
|
768
|
-
_classCallCheck(this, SeparatorItem);
|
|
769
|
-
|
|
770
|
-
return _super.apply(this, arguments);
|
|
444
|
+
class SeparatorItem extends Component {
|
|
445
|
+
static isClassOf(instance) {
|
|
446
|
+
return instance && instance.type && instance.type.__IS_SEPARATOR_ITEM__;
|
|
771
447
|
}
|
|
772
448
|
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
);
|
|
784
|
-
}
|
|
785
|
-
}], [{
|
|
786
|
-
key: "isClassOf",
|
|
787
|
-
value: function isClassOf(instance) {
|
|
788
|
-
return instance && instance.type && instance.type.__IS_SEPARATOR_ITEM__;
|
|
789
|
-
}
|
|
790
|
-
}]);
|
|
791
|
-
|
|
792
|
-
return SeparatorItem;
|
|
793
|
-
}(Component);
|
|
449
|
+
render() {
|
|
450
|
+
return (
|
|
451
|
+
/*#__PURE__*/
|
|
452
|
+
// pass optional styles from react-window (if applies)
|
|
453
|
+
createElement(View, {
|
|
454
|
+
style: [styles$4.separator, this.props.style],
|
|
455
|
+
"aria-hidden": "true"
|
|
456
|
+
})
|
|
457
|
+
);
|
|
458
|
+
}
|
|
794
459
|
|
|
795
|
-
|
|
796
|
-
|
|
460
|
+
}
|
|
461
|
+
SeparatorItem.__IS_SEPARATOR_ITEM__ = true;
|
|
462
|
+
const styles$4 = StyleSheet.create({
|
|
797
463
|
separator: {
|
|
798
|
-
boxShadow:
|
|
464
|
+
boxShadow: `0 -1px ${Color.offBlack16}`,
|
|
799
465
|
height: 1,
|
|
800
466
|
minHeight: 1,
|
|
801
467
|
marginTop: Spacing.xxxSmall_4,
|
|
@@ -803,314 +469,52 @@ var styles$4 = StyleSheet.create({
|
|
|
803
469
|
}
|
|
804
470
|
});
|
|
805
471
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
var _super = _createSuper(DropdownOpener);
|
|
810
|
-
|
|
811
|
-
function DropdownOpener() {
|
|
812
|
-
var _this;
|
|
472
|
+
class DropdownOpener extends Component {
|
|
473
|
+
constructor(...args) {
|
|
474
|
+
super(...args);
|
|
813
475
|
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
817
|
-
args[_key] = arguments[_key];
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
_this = _super.call.apply(_super, [this].concat(args));
|
|
821
|
-
|
|
822
|
-
_defineProperty(_assertThisInitialized(_this), "getTestIdFromProps", function (childrenProps) {
|
|
476
|
+
this.getTestIdFromProps = childrenProps => {
|
|
823
477
|
return childrenProps.testId || childrenProps["data-test-id"];
|
|
824
|
-
});
|
|
825
|
-
|
|
826
|
-
return _this;
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
_createClass(DropdownOpener, [{
|
|
830
|
-
key: "renderAnchorChildren",
|
|
831
|
-
value: function renderAnchorChildren(eventState, clickableChildrenProps) {
|
|
832
|
-
var _this$props = this.props,
|
|
833
|
-
disabled = _this$props.disabled,
|
|
834
|
-
testId = _this$props.testId,
|
|
835
|
-
text = _this$props.text;
|
|
836
|
-
var renderedChildren = this.props.children(_objectSpread2(_objectSpread2({}, eventState), {}, {
|
|
837
|
-
text: text
|
|
838
|
-
}));
|
|
839
|
-
var childrenProps = renderedChildren.props;
|
|
840
|
-
var childrenTestId = this.getTestIdFromProps(childrenProps);
|
|
841
|
-
return cloneElement(renderedChildren, _objectSpread2(_objectSpread2({}, clickableChildrenProps), {}, {
|
|
842
|
-
disabled: disabled,
|
|
843
|
-
onClick: childrenProps.onClick ? function (e) {
|
|
844
|
-
// This is done to avoid overriding a
|
|
845
|
-
// custom onClick handler inside the
|
|
846
|
-
// children node
|
|
847
|
-
childrenProps.onClick(e);
|
|
848
|
-
clickableChildrenProps.onClick(e);
|
|
849
|
-
} : clickableChildrenProps.onClick,
|
|
850
|
-
// try to get the testId from the child element
|
|
851
|
-
// If it's not set, try to fallback to the parent's testId
|
|
852
|
-
"data-test-id": childrenTestId || testId
|
|
853
|
-
}));
|
|
854
|
-
}
|
|
855
|
-
}, {
|
|
856
|
-
key: "render",
|
|
857
|
-
value: function render() {
|
|
858
|
-
var _this2 = this;
|
|
859
|
-
|
|
860
|
-
return /*#__PURE__*/createElement(ClickableBehavior, {
|
|
861
|
-
onClick: this.props.onClick,
|
|
862
|
-
disabled: this.props.disabled
|
|
863
|
-
}, function (eventState, handlers) {
|
|
864
|
-
return _this2.renderAnchorChildren(eventState, handlers);
|
|
865
|
-
});
|
|
866
|
-
}
|
|
867
|
-
}]);
|
|
868
|
-
|
|
869
|
-
return DropdownOpener;
|
|
870
|
-
}(Component);
|
|
871
|
-
|
|
872
|
-
_defineProperty(DropdownOpener, "defaultProps", {
|
|
873
|
-
disabled: false
|
|
874
|
-
});
|
|
875
|
-
|
|
876
|
-
var EmptySizes = Object.freeze({
|
|
877
|
-
top: 0,
|
|
878
|
-
left: 0,
|
|
879
|
-
bottom: 0,
|
|
880
|
-
right: 0
|
|
881
|
-
});
|
|
882
|
-
/**
|
|
883
|
-
* Get the margin, padding, and border edges for a given element.
|
|
884
|
-
*/
|
|
885
|
-
|
|
886
|
-
function getEdges(element, withoutEdges) {
|
|
887
|
-
if (!withoutEdges && element instanceof Element) {
|
|
888
|
-
var style = element.currentStyle || window.getComputedStyle(element);
|
|
889
|
-
return {
|
|
890
|
-
margin: {
|
|
891
|
-
left: parseFloat(style.marginLeft),
|
|
892
|
-
top: parseFloat(style.marginTop),
|
|
893
|
-
right: parseFloat(style.marginRight),
|
|
894
|
-
bottom: parseFloat(style.marginBottom)
|
|
895
|
-
},
|
|
896
|
-
padding: {
|
|
897
|
-
left: parseFloat(style.paddingLeft),
|
|
898
|
-
top: parseFloat(style.paddingTop),
|
|
899
|
-
right: parseFloat(style.paddingRight),
|
|
900
|
-
bottom: parseFloat(style.paddingBottom)
|
|
901
|
-
},
|
|
902
|
-
border: {
|
|
903
|
-
left: parseFloat(style.borderLeftWidth),
|
|
904
|
-
top: parseFloat(style.borderTopWidth),
|
|
905
|
-
right: parseFloat(style.borderRightWidth),
|
|
906
|
-
bottom: parseFloat(style.borderBottomWidth)
|
|
907
|
-
}
|
|
908
478
|
};
|
|
909
479
|
}
|
|
910
480
|
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
var end = function end(rect) {
|
|
936
|
-
return axis === "horizontal" ? rect.right : rect.bottom;
|
|
937
|
-
};
|
|
938
|
-
|
|
939
|
-
if (end(intersectingRect) <= start(boundsRect)) {
|
|
940
|
-
return "before";
|
|
941
|
-
} else if (start(intersectingRect) >= end(boundsRect)) {
|
|
942
|
-
return "after";
|
|
481
|
+
renderAnchorChildren(eventState, clickableChildrenProps) {
|
|
482
|
+
const {
|
|
483
|
+
disabled,
|
|
484
|
+
testId,
|
|
485
|
+
text
|
|
486
|
+
} = this.props;
|
|
487
|
+
const renderedChildren = this.props.children(_extends({}, eventState, {
|
|
488
|
+
text
|
|
489
|
+
}));
|
|
490
|
+
const childrenProps = renderedChildren.props;
|
|
491
|
+
const childrenTestId = this.getTestIdFromProps(childrenProps);
|
|
492
|
+
return /*#__PURE__*/cloneElement(renderedChildren, _extends({}, clickableChildrenProps, {
|
|
493
|
+
disabled,
|
|
494
|
+
onClick: childrenProps.onClick ? e => {
|
|
495
|
+
// This is done to avoid overriding a
|
|
496
|
+
// custom onClick handler inside the
|
|
497
|
+
// children node
|
|
498
|
+
childrenProps.onClick(e);
|
|
499
|
+
clickableChildrenProps.onClick(e);
|
|
500
|
+
} : clickableChildrenProps.onClick,
|
|
501
|
+
// try to get the testId from the child element
|
|
502
|
+
// If it's not set, try to fallback to the parent's testId
|
|
503
|
+
"data-test-id": childrenTestId || testId
|
|
504
|
+
}));
|
|
943
505
|
}
|
|
944
506
|
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
* The intersection should be interpreted as whether the first rectangle is
|
|
952
|
-
* within the second.
|
|
953
|
-
*/
|
|
954
|
-
|
|
955
|
-
function getIntersection(intersectingRect, boundsRect) {
|
|
956
|
-
var horizontal = getAxisIntersection(intersectingRect, boundsRect, "horizontal");
|
|
957
|
-
var vertical = getAxisIntersection(intersectingRect, boundsRect, "vertical");
|
|
958
|
-
return {
|
|
959
|
-
horizontal: horizontal,
|
|
960
|
-
vertical: vertical
|
|
961
|
-
};
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
/**
|
|
965
|
-
* Determine if an element is obscured by other elements.
|
|
966
|
-
*
|
|
967
|
-
* This uses document.elementFromPoint to see if the given element is being
|
|
968
|
-
* overdrawn by another element. Note that this won't work if the given element
|
|
969
|
-
* has `pointer-events: none`.
|
|
970
|
-
*/
|
|
971
|
-
|
|
972
|
-
function isObscured(anchorElement, popperElement) {
|
|
973
|
-
// TODO(somewhatabstract): We should be smarter in this algorithm and
|
|
974
|
-
// actually look at the intersection of the elements doing the obscuring
|
|
975
|
-
// just as we already do with our scroll parent intersections. That way we
|
|
976
|
-
// can not only check that the entire element is obscured, but think about
|
|
977
|
-
// partial obscurement so we can move the tooltip bubble when it's anchor
|
|
978
|
-
// point is not visible.
|
|
979
|
-
// Before we assume we're visible let's check to see if something else
|
|
980
|
-
// is obscuring us. Here we check a variety of points of the element
|
|
981
|
-
// like topleft, bottomright, and center to see if they are covered by
|
|
982
|
-
// something, and if so, assume we're not visible.
|
|
983
|
-
// There are ways that this can still not work, such as different
|
|
984
|
-
// elements only covering those points and the remainder being visible,
|
|
985
|
-
// or if some covering element has none for pointer-events style, but
|
|
986
|
-
// those edge cases shouldn't bother the main usages for this method.
|
|
987
|
-
// NOTE: If the anchor element has `pointer-events: none`, we're always
|
|
988
|
-
// going to end up hiding, so, you know, probably don't do that.
|
|
989
|
-
// We're not explicitly checking for that CSS since it's a corner-case and
|
|
990
|
-
// would impact perf of the regular cases if we were always checking it.
|
|
991
|
-
// TODO(somewhatabstract, WB-300): Need to cater to the case where the
|
|
992
|
-
// viewport is zoomed such that both corners are off screen but the rest
|
|
993
|
-
// isn't. In this case some browsers don't return the element from
|
|
994
|
-
// `elementFromPoint` then doesn't return the element.
|
|
995
|
-
// Also, consider how we might mitigate the pointer-events issue and make
|
|
996
|
-
// this call more robust.
|
|
997
|
-
var bounds = getBounds(anchorElement); // This method does the main work, taking some coordinates and determining
|
|
998
|
-
// if our element is visible at that point or not.
|
|
999
|
-
|
|
1000
|
-
var isVisible = function isVisible(x, y) {
|
|
1001
|
-
var elAtPoint = document.elementFromPoint(x, y);
|
|
1002
|
-
|
|
1003
|
-
if (elAtPoint != null && (elAtPoint === popperElement || popperElement.contains(elAtPoint))) {
|
|
1004
|
-
// Oh no, we're being obscured by our own popper.
|
|
1005
|
-
// We need to look behind it. Shenanigans time.
|
|
1006
|
-
var pointerEventsStyle = elAtPoint.style.pointerEvents; // Remove pointer events so that we can look through it.
|
|
1007
|
-
|
|
1008
|
-
elAtPoint.style.pointerEvents = "none";
|
|
1009
|
-
|
|
1010
|
-
try {
|
|
1011
|
-
var visible = isVisible(x, y);
|
|
1012
|
-
return visible;
|
|
1013
|
-
} finally {
|
|
1014
|
-
// Make sure we put things back the way we found them. :)
|
|
1015
|
-
elAtPoint.style.pointerEvents = pointerEventsStyle;
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
if (anchorElement instanceof Element) {
|
|
1020
|
-
// If we are working with an element, then we can do some decendency checks
|
|
1021
|
-
// to ensure we're not just hitting a child. We're ok with saying that
|
|
1022
|
-
// we're visible if we hit a parent because we check them for visibility
|
|
1023
|
-
// elsewhere.
|
|
1024
|
-
return elAtPoint != null && (anchorElement.contains(elAtPoint) || elAtPoint.contains(anchorElement));
|
|
1025
|
-
} // If element is a reference object, all we have to work with is
|
|
1026
|
-
// intersection for checking obscurity. Since this doesn't cover
|
|
1027
|
-
// parent/child relationships in the DOM, it's not really effective
|
|
1028
|
-
// on its own and is possibly about as good as just returning `true`.
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
var intersection = elAtPoint && getIntersection(bounds, getBounds(elAtPoint, true));
|
|
1032
|
-
return (intersection === null || intersection === void 0 ? void 0 : intersection.horizontal) !== "within" || (intersection === null || intersection === void 0 ? void 0 : intersection.vertical) !== "within";
|
|
1033
|
-
}; // NOTE: We are using functions here so that we only do as much work
|
|
1034
|
-
// as we need to, short-circuiting as soon as we have a definitive
|
|
1035
|
-
// answer.
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
var isTopLeftVisible = function isTopLeftVisible() {
|
|
1039
|
-
return isVisible(bounds.left, bounds.top);
|
|
1040
|
-
};
|
|
1041
|
-
|
|
1042
|
-
var isBottomRightVisible = function isBottomRightVisible() {
|
|
1043
|
-
return isVisible(bounds.right, bounds.bottom);
|
|
1044
|
-
};
|
|
1045
|
-
|
|
1046
|
-
var isCenterVisible = function isCenterVisible() {
|
|
1047
|
-
return isVisible(bounds.left + (bounds.right - bounds.left) / 2, bounds.top + (bounds.bottom - bounds.top) / 2);
|
|
1048
|
-
};
|
|
1049
|
-
|
|
1050
|
-
return !isTopLeftVisible() && !isBottomRightVisible() && !isCenterVisible();
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
var _PopperJS$Defaults$mo, _PopperJS$Defaults$mo2;
|
|
1054
|
-
/**
|
|
1055
|
-
* The function that implements the modifier.
|
|
1056
|
-
*/
|
|
1057
|
-
|
|
1058
|
-
function visibilityModifierFn(data) {
|
|
1059
|
-
var anchorElement = data.instance.reference; // First, we see how the element intersects with its scroll parents.
|
|
1060
|
-
// If it doesn't, then we should hide it.
|
|
1061
|
-
// Otherwise, we check to see if anything else obscures the component (like
|
|
1062
|
-
// a fixed or absolute positioned element).
|
|
1063
|
-
|
|
1064
|
-
var _getElementIntersecti = getElementIntersection(anchorElement),
|
|
1065
|
-
horizontal = _getElementIntersecti.horizontal,
|
|
1066
|
-
vertical = _getElementIntersecti.vertical;
|
|
1067
|
-
|
|
1068
|
-
var hide = horizontal !== "within" || vertical !== "within" || isObscured(anchorElement, data.instance.popper); // If we're hidden, we mimic what the built-in hide method does,
|
|
1069
|
-
// and set the hide flag and the OOB attribute with appropriate
|
|
1070
|
-
// short-circuiting.
|
|
1071
|
-
// https://github.com/FezVrasta/popper.js/blob/08c5d6010346bf9df06e9f81a54fa6c2c51e3639/packages/popper/src/modifiers/hide.js#L29-L42
|
|
1072
|
-
|
|
1073
|
-
if (hide) {
|
|
1074
|
-
if (data.hide) {
|
|
1075
|
-
return data;
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
data.hide = true;
|
|
1079
|
-
data.attributes["x-out-of-boundaries"] = "";
|
|
1080
|
-
} else {
|
|
1081
|
-
// Avoid unnecessary DOM access if visibility hasn't changed
|
|
1082
|
-
if (!data.hide) {
|
|
1083
|
-
return data;
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
data.hide = false;
|
|
1087
|
-
data.attributes["x-out-of-boundaries"] = false;
|
|
1088
|
-
} // Always have to return the data object to ensure the modifier chain
|
|
1089
|
-
// in popper.js is unbroken.
|
|
1090
|
-
|
|
507
|
+
render() {
|
|
508
|
+
return /*#__PURE__*/createElement(ClickableBehavior, {
|
|
509
|
+
onClick: this.props.onClick,
|
|
510
|
+
disabled: this.props.disabled
|
|
511
|
+
}, (eventState, handlers) => this.renderAnchorChildren(eventState, handlers));
|
|
512
|
+
}
|
|
1091
513
|
|
|
1092
|
-
return data;
|
|
1093
514
|
}
|
|
1094
|
-
/**
|
|
1095
|
-
* Default configuration that sets things up how usually want them.
|
|
1096
|
-
* Usage:
|
|
1097
|
-
* ```js
|
|
1098
|
-
* import visibilityModifier from "visibility-modifier.js";
|
|
1099
|
-
* const modifiers = [
|
|
1100
|
-
* wbvisibility: visibilityModifier,
|
|
1101
|
-
* ];
|
|
1102
|
-
* ```
|
|
1103
|
-
*
|
|
1104
|
-
* Where `wbvisibility` is a unique name to give the modifier entry,
|
|
1105
|
-
* and `modifiers` is the popper.js or react-popper modifiers array.
|
|
1106
|
-
*/
|
|
1107
|
-
|
|
1108
515
|
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
// We want this to run after the "hide" modifier, by default.
|
|
1112
|
-
order: (((_PopperJS$Defaults$mo = PopperJS.Defaults.modifiers) === null || _PopperJS$Defaults$mo === void 0 ? void 0 : (_PopperJS$Defaults$mo2 = _PopperJS$Defaults$mo.hide) === null || _PopperJS$Defaults$mo2 === void 0 ? void 0 : _PopperJS$Defaults$mo2.order) || 0) + 1,
|
|
1113
|
-
fn: visibilityModifierFn
|
|
516
|
+
DropdownOpener.defaultProps = {
|
|
517
|
+
disabled: false
|
|
1114
518
|
};
|
|
1115
519
|
|
|
1116
520
|
/**
|
|
@@ -1118,191 +522,163 @@ var visibilityModifierDefaultConfig = {
|
|
|
1118
522
|
* (ActionItem, OptionItem, SeparatorItem) with custom styles to let
|
|
1119
523
|
* react-window make its own calculations.
|
|
1120
524
|
*/
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
ref = item.ref;
|
|
1153
|
-
return cloneElement(component, _objectSpread2(_objectSpread2({
|
|
1154
|
-
style: style
|
|
1155
|
-
}, populatedProps), {}, {
|
|
1156
|
-
key: index,
|
|
1157
|
-
onClick: onClick,
|
|
1158
|
-
ref: item.focusable && ref,
|
|
1159
|
-
role: role
|
|
1160
|
-
}));
|
|
1161
|
-
}
|
|
1162
|
-
}
|
|
1163
|
-
}]);
|
|
1164
|
-
|
|
1165
|
-
return DropdownVirtualizedItem;
|
|
1166
|
-
}(Component);
|
|
1167
|
-
|
|
1168
|
-
var SearchTextInput = /*#__PURE__*/function (_React$Component) {
|
|
1169
|
-
_inherits(SearchTextInput, _React$Component);
|
|
1170
|
-
|
|
1171
|
-
var _super = _createSuper(SearchTextInput);
|
|
1172
|
-
|
|
1173
|
-
function SearchTextInput() {
|
|
1174
|
-
var _this;
|
|
1175
|
-
|
|
1176
|
-
_classCallCheck(this, SearchTextInput);
|
|
1177
|
-
|
|
1178
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
1179
|
-
args[_key] = arguments[_key];
|
|
525
|
+
class DropdownVirtualizedItem extends Component {
|
|
526
|
+
render() {
|
|
527
|
+
const {
|
|
528
|
+
data,
|
|
529
|
+
index,
|
|
530
|
+
style
|
|
531
|
+
} = this.props;
|
|
532
|
+
const item = data[index];
|
|
533
|
+
|
|
534
|
+
if (SeparatorItem.isClassOf(item.component)) {
|
|
535
|
+
// add react-window style to the separator to preserve the correct
|
|
536
|
+
// position
|
|
537
|
+
return /*#__PURE__*/cloneElement(item.component, {
|
|
538
|
+
style
|
|
539
|
+
});
|
|
540
|
+
} else {
|
|
541
|
+
const {
|
|
542
|
+
component,
|
|
543
|
+
populatedProps,
|
|
544
|
+
onClick,
|
|
545
|
+
role,
|
|
546
|
+
ref
|
|
547
|
+
} = item;
|
|
548
|
+
return /*#__PURE__*/cloneElement(component, _extends({
|
|
549
|
+
style
|
|
550
|
+
}, populatedProps, {
|
|
551
|
+
key: index,
|
|
552
|
+
onClick,
|
|
553
|
+
ref: item.focusable && ref,
|
|
554
|
+
role
|
|
555
|
+
}));
|
|
1180
556
|
}
|
|
557
|
+
}
|
|
1181
558
|
|
|
1182
|
-
|
|
559
|
+
}
|
|
1183
560
|
|
|
1184
|
-
|
|
561
|
+
class SearchTextInput extends Component {
|
|
562
|
+
constructor(...args) {
|
|
563
|
+
super(...args);
|
|
564
|
+
this.state = {
|
|
1185
565
|
focused: false,
|
|
1186
|
-
labels:
|
|
566
|
+
labels: _extends({
|
|
1187
567
|
clearSearch: defaultLabels.clearSearch,
|
|
1188
568
|
filter: defaultLabels.filter
|
|
1189
|
-
},
|
|
1190
|
-
}
|
|
569
|
+
}, this.props.labels)
|
|
570
|
+
};
|
|
1191
571
|
|
|
1192
|
-
|
|
572
|
+
this.handleChange = e => {
|
|
1193
573
|
e.preventDefault();
|
|
574
|
+
this.props.onChange(e.target.value);
|
|
575
|
+
};
|
|
1194
576
|
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
onClick = _this$props.onClick,
|
|
1201
|
-
onChange = _this$props.onChange; // Empty the search text and focus the SearchTextInput
|
|
577
|
+
this.handleDismiss = () => {
|
|
578
|
+
const {
|
|
579
|
+
onClick,
|
|
580
|
+
onChange
|
|
581
|
+
} = this.props; // Empty the search text and focus the SearchTextInput
|
|
1202
582
|
|
|
1203
583
|
onChange("");
|
|
1204
584
|
|
|
1205
585
|
if (onClick) {
|
|
1206
586
|
onClick();
|
|
1207
587
|
}
|
|
1208
|
-
}
|
|
588
|
+
};
|
|
1209
589
|
|
|
1210
|
-
|
|
1211
|
-
|
|
590
|
+
this.handleBlur = e => {
|
|
591
|
+
this.setState({
|
|
1212
592
|
focused: false
|
|
1213
593
|
});
|
|
1214
|
-
}
|
|
594
|
+
};
|
|
1215
595
|
|
|
1216
|
-
|
|
1217
|
-
|
|
596
|
+
this.handleFocus = e => {
|
|
597
|
+
this.setState({
|
|
1218
598
|
focused: true
|
|
1219
599
|
});
|
|
1220
|
-
}
|
|
600
|
+
};
|
|
601
|
+
}
|
|
1221
602
|
|
|
1222
|
-
|
|
603
|
+
static isClassOf(instance) {
|
|
604
|
+
return instance && instance.type && instance.type.__IS_SEARCH_TEXT_INPUT__;
|
|
1223
605
|
}
|
|
1224
606
|
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
labels: _objectSpread2(_objectSpread2({}, this.state.labels), this.props.labels)
|
|
1232
|
-
});
|
|
1233
|
-
}
|
|
607
|
+
componentDidUpdate(prevProps) {
|
|
608
|
+
if (this.props.labels !== prevProps.labels) {
|
|
609
|
+
// eslint-disable-next-line react/no-did-update-set-state
|
|
610
|
+
this.setState({
|
|
611
|
+
labels: _extends({}, this.state.labels, this.props.labels)
|
|
612
|
+
});
|
|
1234
613
|
}
|
|
1235
|
-
}
|
|
1236
|
-
key: "maybeRenderDismissIconButton",
|
|
1237
|
-
value: function maybeRenderDismissIconButton() {
|
|
1238
|
-
var searchText = this.props.searchText;
|
|
1239
|
-
var clearSearch = this.state.labels.clearSearch;
|
|
1240
|
-
|
|
1241
|
-
if (searchText.length > 0) {
|
|
1242
|
-
return /*#__PURE__*/createElement(IconButton, {
|
|
1243
|
-
icon: icons.dismiss,
|
|
1244
|
-
kind: "tertiary",
|
|
1245
|
-
onClick: this.handleDismiss,
|
|
1246
|
-
style: styles$5.dismissIcon,
|
|
1247
|
-
"aria-label": clearSearch
|
|
1248
|
-
});
|
|
1249
|
-
}
|
|
614
|
+
}
|
|
1250
615
|
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
}
|
|
1267
|
-
icon: icons.search,
|
|
1268
|
-
size: "medium",
|
|
1269
|
-
color: Color.offBlack64,
|
|
1270
|
-
style: styles$5.searchIcon,
|
|
1271
|
-
"aria-hidden": "true"
|
|
1272
|
-
}), /*#__PURE__*/createElement("input", {
|
|
1273
|
-
type: "text",
|
|
1274
|
-
onChange: this.handleChange,
|
|
1275
|
-
onFocus: this.handleFocus,
|
|
1276
|
-
onBlur: this.handleBlur,
|
|
1277
|
-
ref: itemRef,
|
|
1278
|
-
placeholder: filter,
|
|
1279
|
-
value: searchText,
|
|
1280
|
-
className: css(styles$5.inputStyleReset, styles$a.LabelMedium),
|
|
1281
|
-
"data-test-id": testId
|
|
1282
|
-
}), this.maybeRenderDismissIconButton());
|
|
1283
|
-
}
|
|
1284
|
-
}], [{
|
|
1285
|
-
key: "isClassOf",
|
|
1286
|
-
value: function isClassOf(instance) {
|
|
1287
|
-
return instance && instance.type && instance.type.__IS_SEARCH_TEXT_INPUT__;
|
|
616
|
+
maybeRenderDismissIconButton() {
|
|
617
|
+
const {
|
|
618
|
+
searchText
|
|
619
|
+
} = this.props;
|
|
620
|
+
const {
|
|
621
|
+
clearSearch
|
|
622
|
+
} = this.state.labels;
|
|
623
|
+
|
|
624
|
+
if (searchText.length > 0) {
|
|
625
|
+
return /*#__PURE__*/createElement(IconButton, {
|
|
626
|
+
icon: icons.dismiss,
|
|
627
|
+
kind: "tertiary",
|
|
628
|
+
onClick: this.handleDismiss,
|
|
629
|
+
style: styles$5.dismissIcon,
|
|
630
|
+
"aria-label": clearSearch
|
|
631
|
+
});
|
|
1288
632
|
}
|
|
1289
|
-
}]);
|
|
1290
633
|
|
|
1291
|
-
|
|
1292
|
-
}
|
|
634
|
+
return null;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
render() {
|
|
638
|
+
const {
|
|
639
|
+
onClick,
|
|
640
|
+
itemRef,
|
|
641
|
+
searchText,
|
|
642
|
+
style,
|
|
643
|
+
testId
|
|
644
|
+
} = this.props;
|
|
645
|
+
const {
|
|
646
|
+
filter
|
|
647
|
+
} = this.state.labels;
|
|
648
|
+
return /*#__PURE__*/createElement(View, {
|
|
649
|
+
onClick: onClick,
|
|
650
|
+
style: [styles$5.inputContainer, this.state.focused && styles$5.focused, style]
|
|
651
|
+
}, /*#__PURE__*/createElement(Icon, {
|
|
652
|
+
icon: icons.search,
|
|
653
|
+
size: "medium",
|
|
654
|
+
color: Color.offBlack64,
|
|
655
|
+
style: styles$5.searchIcon,
|
|
656
|
+
"aria-hidden": "true"
|
|
657
|
+
}), /*#__PURE__*/createElement("input", {
|
|
658
|
+
type: "text",
|
|
659
|
+
onChange: this.handleChange,
|
|
660
|
+
onFocus: this.handleFocus,
|
|
661
|
+
onBlur: this.handleBlur,
|
|
662
|
+
ref: itemRef,
|
|
663
|
+
placeholder: filter,
|
|
664
|
+
value: searchText,
|
|
665
|
+
className: css(styles$5.inputStyleReset, styles$a.LabelMedium),
|
|
666
|
+
"data-test-id": testId
|
|
667
|
+
}), this.maybeRenderDismissIconButton());
|
|
668
|
+
}
|
|
1293
669
|
|
|
1294
|
-
|
|
670
|
+
}
|
|
671
|
+
SearchTextInput.defaultProps = {
|
|
1295
672
|
labels: {
|
|
1296
673
|
clearSearch: defaultLabels.clearSearch,
|
|
1297
674
|
filter: defaultLabels.filter
|
|
1298
675
|
}
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
var styles$5 = StyleSheet.create({
|
|
676
|
+
};
|
|
677
|
+
SearchTextInput.__IS_SEARCH_TEXT_INPUT__ = true;
|
|
678
|
+
const styles$5 = StyleSheet.create({
|
|
1303
679
|
inputContainer: {
|
|
1304
680
|
flexDirection: "row",
|
|
1305
|
-
border:
|
|
681
|
+
border: `1px solid ${Color.offBlack16}`,
|
|
1306
682
|
borderRadius: Spacing.xxxSmall_4,
|
|
1307
683
|
alignItems: "center",
|
|
1308
684
|
// The height of the text input is 40 in design spec and we need to
|
|
@@ -1313,7 +689,7 @@ var styles$5 = StyleSheet.create({
|
|
|
1313
689
|
minHeight: DROPDOWN_ITEM_HEIGHT
|
|
1314
690
|
},
|
|
1315
691
|
focused: {
|
|
1316
|
-
border:
|
|
692
|
+
border: `1px solid ${Color.blue}`
|
|
1317
693
|
},
|
|
1318
694
|
searchIcon: {
|
|
1319
695
|
marginLeft: Spacing.xSmall_8,
|
|
@@ -1345,36 +721,23 @@ var styles$5 = StyleSheet.create({
|
|
|
1345
721
|
* number of items that can fit into the visible porition of the
|
|
1346
722
|
* dropdowns list box.
|
|
1347
723
|
*/
|
|
1348
|
-
|
|
724
|
+
const MAX_VISIBLE_ITEMS = 9;
|
|
1349
725
|
/**
|
|
1350
726
|
* A react-window's List wrapper that instantiates the virtualized list and
|
|
1351
727
|
* dynamically calculates the item height depending on the type
|
|
1352
728
|
*/
|
|
1353
729
|
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
_classCallCheck(this, DropdownCoreVirtualized);
|
|
1363
|
-
|
|
1364
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
1365
|
-
args[_key] = arguments[_key];
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
_this = _super.call.apply(_super, [this].concat(args));
|
|
1369
|
-
|
|
1370
|
-
_defineProperty(_assertThisInitialized(_this), "state", {
|
|
1371
|
-
height: _this.getHeight(),
|
|
1372
|
-
width: _this.props.width
|
|
1373
|
-
});
|
|
730
|
+
class DropdownCoreVirtualized extends Component {
|
|
731
|
+
constructor(...args) {
|
|
732
|
+
super(...args);
|
|
733
|
+
this.state = {
|
|
734
|
+
height: this.getHeight(),
|
|
735
|
+
width: this.props.width
|
|
736
|
+
};
|
|
1374
737
|
|
|
1375
|
-
|
|
738
|
+
this.getItemSize = index => {
|
|
1376
739
|
// get the current item in the list
|
|
1377
|
-
|
|
740
|
+
const item = this.props.data[index];
|
|
1378
741
|
|
|
1379
742
|
if (SeparatorItem.isClassOf(item.component)) {
|
|
1380
743
|
// this is the separator's height (1px) + vertical margin (8px)
|
|
@@ -1386,284 +749,253 @@ var DropdownCoreVirtualized = /*#__PURE__*/function (_React$Component) {
|
|
|
1386
749
|
// default dropdown item height
|
|
1387
750
|
return DROPDOWN_ITEM_HEIGHT;
|
|
1388
751
|
}
|
|
1389
|
-
}
|
|
752
|
+
};
|
|
753
|
+
}
|
|
1390
754
|
|
|
1391
|
-
|
|
755
|
+
componentDidMount() {
|
|
756
|
+
const {
|
|
757
|
+
schedule
|
|
758
|
+
} = this.props; // Wait for styles to be applied. This way, we can get a more precise
|
|
759
|
+
// value of the container dimensions.
|
|
760
|
+
|
|
761
|
+
schedule.animationFrame(() => {
|
|
762
|
+
this.setWidth();
|
|
763
|
+
});
|
|
1392
764
|
}
|
|
1393
765
|
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
766
|
+
componentDidUpdate(prevProps) {
|
|
767
|
+
const {
|
|
768
|
+
data,
|
|
769
|
+
listRef
|
|
770
|
+
} = this.props; // if the items size has changed, then recalculate each item position
|
|
1398
771
|
|
|
1399
|
-
|
|
1400
|
-
|
|
772
|
+
if (prevProps.data.length !== data.length) {
|
|
773
|
+
this.setHeight();
|
|
1401
774
|
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
}, {
|
|
1407
|
-
key: "componentDidUpdate",
|
|
1408
|
-
value: function componentDidUpdate(prevProps) {
|
|
1409
|
-
var _this$props = this.props,
|
|
1410
|
-
data = _this$props.data,
|
|
1411
|
-
listRef = _this$props.listRef; // if the items size has changed, then recalculate each item position
|
|
1412
|
-
|
|
1413
|
-
if (prevProps.data.length !== data.length) {
|
|
1414
|
-
this.setHeight();
|
|
1415
|
-
|
|
1416
|
-
if (listRef && listRef.current) {
|
|
1417
|
-
// the ref can't associate this instance method
|
|
1418
|
-
// $FlowIgnore
|
|
1419
|
-
listRef.current.resetAfterIndex(1);
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
/**
|
|
1424
|
-
* Update container width
|
|
1425
|
-
*/
|
|
1426
|
-
|
|
1427
|
-
}, {
|
|
1428
|
-
key: "setWidth",
|
|
1429
|
-
value: function setWidth() {
|
|
1430
|
-
var rootNode = ReactDOM.findDOMNode(this);
|
|
1431
|
-
var parentNode = rootNode === null || rootNode === void 0 ? void 0 : rootNode.parentElement; // after the non-virtualized items are rendered, we get the container
|
|
1432
|
-
// width to pass it to react-window's List
|
|
1433
|
-
|
|
1434
|
-
if (parentNode) {
|
|
1435
|
-
var width = parentNode.getBoundingClientRect().width;
|
|
1436
|
-
this.setState({
|
|
1437
|
-
width: width
|
|
1438
|
-
});
|
|
775
|
+
if (listRef && listRef.current) {
|
|
776
|
+
// the ref can't associate this instance method
|
|
777
|
+
// $FlowIgnore
|
|
778
|
+
listRef.current.resetAfterIndex(1);
|
|
1439
779
|
}
|
|
1440
780
|
}
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Update container width
|
|
784
|
+
*/
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
setWidth() {
|
|
788
|
+
const rootNode = ReactDOM.findDOMNode(this);
|
|
789
|
+
const parentNode = rootNode == null ? void 0 : rootNode.parentElement; // after the non-virtualized items are rendered, we get the container
|
|
790
|
+
// width to pass it to react-window's List
|
|
791
|
+
|
|
792
|
+
if (parentNode) {
|
|
793
|
+
const width = parentNode.getBoundingClientRect().width;
|
|
1450
794
|
this.setState({
|
|
1451
|
-
|
|
795
|
+
width
|
|
1452
796
|
});
|
|
1453
797
|
}
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
}, {
|
|
1460
|
-
key: "getHeight",
|
|
1461
|
-
value: function getHeight() {
|
|
1462
|
-
// calculate using the first 10 items on the array as we want to display
|
|
1463
|
-
// this number of elements in the visible area
|
|
1464
|
-
return this.props.data.slice(0, MAX_VISIBLE_ITEMS).reduce(function (sum, item) {
|
|
1465
|
-
if (SeparatorItem.isClassOf(item.component)) {
|
|
1466
|
-
return sum + SEPARATOR_ITEM_HEIGHT;
|
|
1467
|
-
} else if (SearchTextInput.isClassOf(item.component)) {
|
|
1468
|
-
// search text input height
|
|
1469
|
-
return sum + SEARCH_ITEM_HEIGHT;
|
|
1470
|
-
} else {
|
|
1471
|
-
return sum + DROPDOWN_ITEM_HEIGHT;
|
|
1472
|
-
}
|
|
1473
|
-
}, 0);
|
|
1474
|
-
}
|
|
1475
|
-
/**
|
|
1476
|
-
* Calculates item height
|
|
1477
|
-
*/
|
|
1478
|
-
|
|
1479
|
-
}, {
|
|
1480
|
-
key: "renderInitialItems",
|
|
1481
|
-
|
|
1482
|
-
/**
|
|
1483
|
-
* render non virtualized items to calculate the container max-width that
|
|
1484
|
-
* will be used by DropdownCoreVirtualized
|
|
1485
|
-
*/
|
|
1486
|
-
value: function renderInitialItems() {
|
|
1487
|
-
var data = this.props.data;
|
|
1488
|
-
var allComponents = data.map(function (e) {
|
|
1489
|
-
return e.component;
|
|
1490
|
-
}); // 1. get the children opaque data structure to sort each item by its
|
|
1491
|
-
// label length
|
|
1492
|
-
|
|
1493
|
-
var longestItems = Children.toArray(allComponents).filter(Boolean).sort(function (a, b) {
|
|
1494
|
-
// 2. only sort elements that contain a `label` prop
|
|
1495
|
-
if (b.props.label && a.props.label) {
|
|
1496
|
-
return b.props.label.length - a.props.label.length;
|
|
1497
|
-
}
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Update container height
|
|
801
|
+
*/
|
|
1498
802
|
|
|
1499
|
-
return -1;
|
|
1500
|
-
}) // 3. only render the possible visible items to minimize layout
|
|
1501
|
-
// jumps
|
|
1502
|
-
.slice(0, MAX_VISIBLE_ITEMS); // Append longest items to calculate the container width.
|
|
1503
|
-
// We need to hide these sorted elements to avoid any FOUC.
|
|
1504
803
|
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
//
|
|
1526
|
-
|
|
1527
|
-
// or strings.
|
|
1528
|
-
// $FlowFixMe
|
|
1529
|
-
, {
|
|
1530
|
-
height: height,
|
|
1531
|
-
itemCount: data.length,
|
|
1532
|
-
itemSize: this.getItemSize,
|
|
1533
|
-
itemData: data,
|
|
1534
|
-
style: {
|
|
1535
|
-
overflowX: "hidden"
|
|
1536
|
-
} // react-window doesn't accept maybe numbers. It wants numbers
|
|
1537
|
-
// or strings.
|
|
1538
|
-
// $FlowFixMe
|
|
1539
|
-
,
|
|
1540
|
-
width: width,
|
|
1541
|
-
overscanCount: 5,
|
|
1542
|
-
ref: listRef
|
|
1543
|
-
}, DropdownVirtualizedItem)
|
|
1544
|
-
);
|
|
1545
|
-
}
|
|
1546
|
-
}, {
|
|
1547
|
-
key: "render",
|
|
1548
|
-
value: function render() {
|
|
1549
|
-
if (this.state.width === undefined) {
|
|
1550
|
-
// if we don't pass a fixed value, then we need to render
|
|
1551
|
-
// non-virtualized items to calculate width
|
|
1552
|
-
return this.renderInitialItems();
|
|
804
|
+
setHeight() {
|
|
805
|
+
// calculate dropdown's height depending on the type of items
|
|
806
|
+
const height = this.getHeight();
|
|
807
|
+
this.setState({
|
|
808
|
+
height
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* The list height that is automatically calculated depending on the
|
|
813
|
+
* component's type of each item (e.g. Separator, Option, Search, etc)
|
|
814
|
+
*/
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
getHeight() {
|
|
818
|
+
// calculate using the first 10 items on the array as we want to display
|
|
819
|
+
// this number of elements in the visible area
|
|
820
|
+
return this.props.data.slice(0, MAX_VISIBLE_ITEMS).reduce((sum, item) => {
|
|
821
|
+
if (SeparatorItem.isClassOf(item.component)) {
|
|
822
|
+
return sum + SEPARATOR_ITEM_HEIGHT;
|
|
823
|
+
} else if (SearchTextInput.isClassOf(item.component)) {
|
|
824
|
+
// search text input height
|
|
825
|
+
return sum + SEARCH_ITEM_HEIGHT;
|
|
1553
826
|
} else {
|
|
1554
|
-
|
|
1555
|
-
|
|
827
|
+
return sum + DROPDOWN_ITEM_HEIGHT;
|
|
828
|
+
}
|
|
829
|
+
}, 0);
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* Calculates item height
|
|
833
|
+
*/
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
/**
|
|
837
|
+
* render non virtualized items to calculate the container max-width that
|
|
838
|
+
* will be used by DropdownCoreVirtualized
|
|
839
|
+
*/
|
|
840
|
+
renderInitialItems() {
|
|
841
|
+
const {
|
|
842
|
+
data
|
|
843
|
+
} = this.props;
|
|
844
|
+
const allComponents = data.map(e => e.component); // 1. get the children opaque data structure to sort each item by its
|
|
845
|
+
// label length
|
|
846
|
+
|
|
847
|
+
const longestItems = Children.toArray(allComponents).filter(Boolean).sort((a, b) => {
|
|
848
|
+
// 2. only sort elements that contain a `label` prop
|
|
849
|
+
if (b.props.label && a.props.label) {
|
|
850
|
+
return b.props.label.length - a.props.label.length;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
return -1;
|
|
854
|
+
}) // 3. only render the possible visible items to minimize layout
|
|
855
|
+
// jumps
|
|
856
|
+
.slice(0, MAX_VISIBLE_ITEMS); // Append longest items to calculate the container width.
|
|
857
|
+
// We need to hide these sorted elements to avoid any FOUC.
|
|
858
|
+
|
|
859
|
+
return longestItems.map(item => /*#__PURE__*/cloneElement(item, {
|
|
860
|
+
style: {
|
|
861
|
+
visibility: "hidden"
|
|
1556
862
|
}
|
|
863
|
+
}));
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
renderVirtualizedList() {
|
|
867
|
+
const {
|
|
868
|
+
data,
|
|
869
|
+
listRef
|
|
870
|
+
} = this.props;
|
|
871
|
+
const {
|
|
872
|
+
height,
|
|
873
|
+
width
|
|
874
|
+
} = this.state;
|
|
875
|
+
return (
|
|
876
|
+
/*#__PURE__*/
|
|
877
|
+
// react-window has some issues for typing lists when passing refs
|
|
878
|
+
// $FlowIgnore
|
|
879
|
+
createElement(VariableSizeList // react-window doesn't accept maybe numbers. It wants numbers
|
|
880
|
+
// or strings.
|
|
881
|
+
// $FlowFixMe
|
|
882
|
+
, {
|
|
883
|
+
height: height,
|
|
884
|
+
itemCount: data.length,
|
|
885
|
+
itemSize: this.getItemSize,
|
|
886
|
+
itemData: data,
|
|
887
|
+
style: {
|
|
888
|
+
overflowX: "hidden"
|
|
889
|
+
} // react-window doesn't accept maybe numbers. It wants numbers
|
|
890
|
+
// or strings.
|
|
891
|
+
// $FlowFixMe
|
|
892
|
+
,
|
|
893
|
+
width: width,
|
|
894
|
+
overscanCount: 5,
|
|
895
|
+
ref: listRef
|
|
896
|
+
}, DropdownVirtualizedItem)
|
|
897
|
+
);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
render() {
|
|
901
|
+
if (this.state.width === undefined) {
|
|
902
|
+
// if we don't pass a fixed value, then we need to render
|
|
903
|
+
// non-virtualized items to calculate width
|
|
904
|
+
return this.renderInitialItems();
|
|
905
|
+
} else {
|
|
906
|
+
// width has been provided, then render the virtualized list
|
|
907
|
+
return this.renderVirtualizedList();
|
|
1557
908
|
}
|
|
1558
|
-
}
|
|
909
|
+
}
|
|
1559
910
|
|
|
1560
|
-
|
|
1561
|
-
}(Component);
|
|
911
|
+
}
|
|
1562
912
|
|
|
1563
913
|
var DropdownCoreVirtualized$1 = withActionScheduler(DropdownCoreVirtualized);
|
|
1564
914
|
|
|
915
|
+
const _excluded$1 = ["pointerEvents"];
|
|
916
|
+
|
|
1565
917
|
/**
|
|
1566
918
|
* A core dropdown component that takes an opener and children to display as
|
|
1567
919
|
* part of the dropdown menu. Renders the dropdown as a portal to avoid clipping
|
|
1568
920
|
* in overflow: auto containers.
|
|
1569
921
|
*/
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
if (prevItems.length !== currentItems.length) {
|
|
922
|
+
class DropdownCore extends Component {
|
|
923
|
+
// Keeps track of the index of the focused item, out of a list of focusable items
|
|
924
|
+
// Keeps track of the index of the focused item in the context of all the
|
|
925
|
+
// items contained by this menu, whether focusable or not, used for figuring
|
|
926
|
+
// out focus correctly when the items have changed in terms of whether
|
|
927
|
+
// they're focusable or not
|
|
928
|
+
// Whether any items have been selected since the menu was opened
|
|
929
|
+
// Keeps a reference of the virtualized list instance
|
|
930
|
+
// Figure out if the same items are focusable. If an item has been added or
|
|
931
|
+
// removed, this method will return false.
|
|
932
|
+
static sameItemsFocusable(prevItems, currentItems) {
|
|
933
|
+
if (prevItems.length !== currentItems.length) {
|
|
934
|
+
return false;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
for (let i = 0; i < prevItems.length; i++) {
|
|
938
|
+
if (prevItems[i].focusable !== currentItems[i].focusable) {
|
|
1588
939
|
return false;
|
|
1589
940
|
}
|
|
941
|
+
}
|
|
1590
942
|
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
return false;
|
|
1594
|
-
}
|
|
1595
|
-
}
|
|
943
|
+
return true;
|
|
944
|
+
}
|
|
1596
945
|
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
itemRefs.push({
|
|
1612
|
-
ref: ref,
|
|
1613
|
-
originalIndex: i
|
|
1614
|
-
});
|
|
1615
|
-
}
|
|
946
|
+
// This is here to avoid calling React.createRef on each rerender. Instead,
|
|
947
|
+
// we create the itemRefs only if it's the first time or if the set of items
|
|
948
|
+
// that are focusable has changed.
|
|
949
|
+
static getDerivedStateFromProps(props, state) {
|
|
950
|
+
if (state.itemRefs.length === 0 && props.open || !DropdownCore.sameItemsFocusable(state.prevItems, props.items)) {
|
|
951
|
+
const itemRefs = [];
|
|
952
|
+
|
|
953
|
+
for (let i = 0; i < props.items.length; i++) {
|
|
954
|
+
if (props.items[i].focusable) {
|
|
955
|
+
const ref = /*#__PURE__*/createRef();
|
|
956
|
+
itemRefs.push({
|
|
957
|
+
ref,
|
|
958
|
+
originalIndex: i
|
|
959
|
+
});
|
|
1616
960
|
}
|
|
1617
|
-
|
|
1618
|
-
return {
|
|
1619
|
-
itemRefs: itemRefs,
|
|
1620
|
-
prevItems: props.items,
|
|
1621
|
-
sameItemsFocusable: false
|
|
1622
|
-
};
|
|
1623
|
-
} else {
|
|
1624
|
-
return {
|
|
1625
|
-
prevItems: props.items,
|
|
1626
|
-
sameItemsFocusable: true
|
|
1627
|
-
};
|
|
1628
961
|
}
|
|
1629
|
-
}
|
|
1630
|
-
}]);
|
|
1631
|
-
|
|
1632
|
-
function DropdownCore(props) {
|
|
1633
|
-
var _this;
|
|
1634
962
|
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
963
|
+
return {
|
|
964
|
+
itemRefs,
|
|
965
|
+
prevItems: props.items,
|
|
966
|
+
sameItemsFocusable: false
|
|
967
|
+
};
|
|
968
|
+
} else {
|
|
969
|
+
return {
|
|
970
|
+
prevItems: props.items,
|
|
971
|
+
sameItemsFocusable: true
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
}
|
|
1646
975
|
|
|
1647
|
-
|
|
976
|
+
constructor(props) {
|
|
977
|
+
super(props); // Apply our initial focus index
|
|
1648
978
|
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
979
|
+
this.handleInteract = event => {
|
|
980
|
+
const {
|
|
981
|
+
open,
|
|
982
|
+
onOpenChanged
|
|
983
|
+
} = this.props;
|
|
984
|
+
const target = event.target;
|
|
985
|
+
const thisElement = ReactDOM.findDOMNode(this);
|
|
1655
986
|
|
|
1656
|
-
if (open && thisElement && !thisElement.contains(target) &&
|
|
987
|
+
if (open && thisElement && !thisElement.contains(target) && this.popperElement && !this.popperElement.contains(target)) {
|
|
1657
988
|
onOpenChanged(false);
|
|
1658
989
|
}
|
|
1659
|
-
}
|
|
990
|
+
};
|
|
1660
991
|
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
992
|
+
this.handleKeyDown = event => {
|
|
993
|
+
const {
|
|
994
|
+
onOpenChanged,
|
|
995
|
+
open,
|
|
996
|
+
searchText
|
|
997
|
+
} = this.props;
|
|
998
|
+
const keyCode = event.which || event.keyCode; // If menu isn't open and user presses down, open the menu
|
|
1667
999
|
|
|
1668
1000
|
if (!open) {
|
|
1669
1001
|
if (keyCode === keyCodes.down) {
|
|
@@ -1682,19 +1014,18 @@ var DropdownCore = /*#__PURE__*/function (_React$Component) {
|
|
|
1682
1014
|
// searchText is entered at least one character, dismiss button
|
|
1683
1015
|
// is displayed. When user presses tab, we should move focus
|
|
1684
1016
|
// to the dismiss button.
|
|
1685
|
-
if (
|
|
1017
|
+
if (this.hasSearchBox() && this.focusedIndex === 0 && searchText) {
|
|
1686
1018
|
return;
|
|
1687
1019
|
}
|
|
1688
1020
|
|
|
1689
|
-
|
|
1690
|
-
|
|
1021
|
+
this.restoreTabOrder();
|
|
1691
1022
|
onOpenChanged(false);
|
|
1692
1023
|
return;
|
|
1693
1024
|
|
|
1694
1025
|
case keyCodes.space:
|
|
1695
1026
|
// When we display SearchTextInput and the focus is on it,
|
|
1696
1027
|
// we should let the user type space.
|
|
1697
|
-
if (
|
|
1028
|
+
if (this.hasSearchBox() && this.focusedIndex === 0) {
|
|
1698
1029
|
return;
|
|
1699
1030
|
} // Prevent space from scrolling down the page
|
|
1700
1031
|
|
|
@@ -1704,31 +1035,28 @@ var DropdownCore = /*#__PURE__*/function (_React$Component) {
|
|
|
1704
1035
|
|
|
1705
1036
|
case keyCodes.up:
|
|
1706
1037
|
event.preventDefault();
|
|
1707
|
-
|
|
1708
|
-
_this.focusPreviousItem();
|
|
1709
|
-
|
|
1038
|
+
this.focusPreviousItem();
|
|
1710
1039
|
return;
|
|
1711
1040
|
|
|
1712
1041
|
case keyCodes.down:
|
|
1713
1042
|
event.preventDefault();
|
|
1714
|
-
|
|
1715
|
-
_this.focusNextItem();
|
|
1716
|
-
|
|
1043
|
+
this.focusNextItem();
|
|
1717
1044
|
return;
|
|
1718
1045
|
}
|
|
1719
|
-
}
|
|
1046
|
+
};
|
|
1720
1047
|
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1048
|
+
this.handleKeyUp = event => {
|
|
1049
|
+
const {
|
|
1050
|
+
onOpenChanged,
|
|
1051
|
+
open
|
|
1052
|
+
} = this.props;
|
|
1053
|
+
const keyCode = event.which || event.keyCode;
|
|
1726
1054
|
|
|
1727
1055
|
switch (keyCode) {
|
|
1728
1056
|
case keyCodes.space:
|
|
1729
1057
|
// When we display SearchTextInput and the focus is on it,
|
|
1730
1058
|
// we should let the user type space.
|
|
1731
|
-
if (
|
|
1059
|
+
if (this.hasSearchBox() && this.focusedIndex === 0) {
|
|
1732
1060
|
return;
|
|
1733
1061
|
} // Prevent space from scrolling down the page
|
|
1734
1062
|
|
|
@@ -1741,25 +1069,23 @@ var DropdownCore = /*#__PURE__*/function (_React$Component) {
|
|
|
1741
1069
|
// listening for an escape press
|
|
1742
1070
|
if (open) {
|
|
1743
1071
|
event.stopPropagation();
|
|
1744
|
-
|
|
1745
|
-
_this.restoreTabOrder();
|
|
1746
|
-
|
|
1072
|
+
this.restoreTabOrder();
|
|
1747
1073
|
onOpenChanged(false);
|
|
1748
1074
|
}
|
|
1749
1075
|
|
|
1750
1076
|
return;
|
|
1751
1077
|
}
|
|
1752
|
-
}
|
|
1078
|
+
};
|
|
1753
1079
|
|
|
1754
|
-
|
|
1080
|
+
this.handleClickFocus = index => {
|
|
1755
1081
|
// Turn itemsClicked on so pressing up or down would focus the
|
|
1756
1082
|
// appropriate item in handleKeyDown
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
}
|
|
1083
|
+
this.itemsClicked = true;
|
|
1084
|
+
this.focusedIndex = index;
|
|
1085
|
+
this.focusedOriginalIndex = this.state.itemRefs[this.focusedIndex].originalIndex;
|
|
1086
|
+
};
|
|
1761
1087
|
|
|
1762
|
-
|
|
1088
|
+
this.handleDropdownMouseUp = event => {
|
|
1763
1089
|
// $FlowIgnore[method-unbinding]
|
|
1764
1090
|
if (event.nativeEvent.stopImmediatePropagation) {
|
|
1765
1091
|
event.nativeEvent.stopImmediatePropagation();
|
|
@@ -1767,412 +1093,395 @@ var DropdownCore = /*#__PURE__*/function (_React$Component) {
|
|
|
1767
1093
|
// Workaround for jsdom
|
|
1768
1094
|
event.stopPropagation();
|
|
1769
1095
|
}
|
|
1770
|
-
}
|
|
1771
|
-
|
|
1772
|
-
_this.resetFocusedIndex();
|
|
1096
|
+
};
|
|
1773
1097
|
|
|
1774
|
-
|
|
1775
|
-
|
|
1098
|
+
this.resetFocusedIndex();
|
|
1099
|
+
this.state = {
|
|
1100
|
+
prevItems: this.props.items,
|
|
1776
1101
|
itemRefs: [],
|
|
1777
1102
|
sameItemsFocusable: false,
|
|
1778
|
-
labels:
|
|
1103
|
+
labels: _extends({
|
|
1779
1104
|
noResults: defaultLabels.noResults
|
|
1780
1105
|
}, props.labels)
|
|
1781
1106
|
};
|
|
1782
|
-
|
|
1783
|
-
|
|
1107
|
+
this.listRef = /*#__PURE__*/createRef();
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
componentDidMount() {
|
|
1111
|
+
this.updateEventListeners();
|
|
1112
|
+
this.initialFocusItem();
|
|
1784
1113
|
}
|
|
1785
1114
|
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1115
|
+
componentDidUpdate(prevProps) {
|
|
1116
|
+
const {
|
|
1117
|
+
open
|
|
1118
|
+
} = this.props;
|
|
1119
|
+
|
|
1120
|
+
if (prevProps.open !== open) {
|
|
1789
1121
|
this.updateEventListeners();
|
|
1790
1122
|
this.initialFocusItem();
|
|
1791
|
-
}
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
// last item that was focused before this change
|
|
1821
|
-
var newFocusableIndex = itemRefs.findIndex(function (ref) {
|
|
1822
|
-
return ref.originalIndex === _this2.focusedOriginalIndex;
|
|
1823
|
-
});
|
|
1824
|
-
|
|
1825
|
-
if (newFocusableIndex === -1) {
|
|
1826
|
-
// Can't find the originally focused item, return focus to
|
|
1827
|
-
// the first item that IS focusable
|
|
1828
|
-
this.focusedIndex = 0; // Reset the knowlege that things had been clicked
|
|
1829
|
-
|
|
1830
|
-
this.itemsClicked = false;
|
|
1831
|
-
this.scheduleToFocusCurrentItem();
|
|
1832
|
-
} else {
|
|
1833
|
-
this.focusedIndex = newFocusableIndex;
|
|
1834
|
-
}
|
|
1835
|
-
}
|
|
1836
|
-
|
|
1837
|
-
if (this.props.labels !== prevProps.labels) {
|
|
1838
|
-
// eslint-disable-next-line react/no-did-update-set-state
|
|
1839
|
-
this.setState({
|
|
1840
|
-
labels: _objectSpread2(_objectSpread2({}, this.state.labels), this.props.labels)
|
|
1841
|
-
});
|
|
1842
|
-
}
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
}, {
|
|
1846
|
-
key: "componentWillUnmount",
|
|
1847
|
-
value: function componentWillUnmount() {
|
|
1848
|
-
this.removeEventListeners();
|
|
1849
|
-
}
|
|
1850
|
-
}, {
|
|
1851
|
-
key: "hasSearchBox",
|
|
1852
|
-
value: function hasSearchBox() {
|
|
1853
|
-
return !!this.props.onSearchTextChanged && typeof this.props.searchText === "string";
|
|
1854
|
-
} // Resets our initial focus index to what was passed in
|
|
1855
|
-
// via the props
|
|
1856
|
-
|
|
1857
|
-
}, {
|
|
1858
|
-
key: "resetFocusedIndex",
|
|
1859
|
-
value: function resetFocusedIndex() {
|
|
1860
|
-
var initialFocusedIndex = this.props.initialFocusedIndex; // If we are given an initial focus index, select it. Otherwise
|
|
1861
|
-
// default to the first item
|
|
1862
|
-
|
|
1863
|
-
if (initialFocusedIndex) {
|
|
1864
|
-
// If we have a search box visible, then our focus
|
|
1865
|
-
// index is going to be offset by 1, since the orginal
|
|
1866
|
-
// index doesn't account for the search box's
|
|
1867
|
-
// existence.
|
|
1868
|
-
if (this.hasSearchBox()) {
|
|
1869
|
-
this.focusedIndex = initialFocusedIndex + 1;
|
|
1123
|
+
} // If the menu changed, but from open to open, figure out if we need
|
|
1124
|
+
// to recalculate the focus somehow.
|
|
1125
|
+
else if (open) {
|
|
1126
|
+
const {
|
|
1127
|
+
itemRefs,
|
|
1128
|
+
sameItemsFocusable
|
|
1129
|
+
} = this.state; // Check if the same items are focused by comparing the items at
|
|
1130
|
+
// each index and seeing if the {focusable} property is the same.
|
|
1131
|
+
// Very rarely do the set of focusable items change if the menu
|
|
1132
|
+
// hasn't been re-opened. This is for cases like a {Select all}
|
|
1133
|
+
// option that becomes disabled iff all the options are selected.
|
|
1134
|
+
|
|
1135
|
+
if (sameItemsFocusable) {
|
|
1136
|
+
return;
|
|
1137
|
+
} else {
|
|
1138
|
+
// If the set of items that was focusabled changed, it's very
|
|
1139
|
+
// likely that the previously focused item no longer has the
|
|
1140
|
+
// same index relative to the list of focusable items. Instead,
|
|
1141
|
+
// use the focusedOriginalIndex to find the new index of the
|
|
1142
|
+
// last item that was focused before this change
|
|
1143
|
+
const newFocusableIndex = itemRefs.findIndex(ref => ref.originalIndex === this.focusedOriginalIndex);
|
|
1144
|
+
|
|
1145
|
+
if (newFocusableIndex === -1) {
|
|
1146
|
+
// Can't find the originally focused item, return focus to
|
|
1147
|
+
// the first item that IS focusable
|
|
1148
|
+
this.focusedIndex = 0; // Reset the knowlege that things had been clicked
|
|
1149
|
+
|
|
1150
|
+
this.itemsClicked = false;
|
|
1151
|
+
this.scheduleToFocusCurrentItem();
|
|
1870
1152
|
} else {
|
|
1871
|
-
this.focusedIndex =
|
|
1153
|
+
this.focusedIndex = newFocusableIndex;
|
|
1872
1154
|
}
|
|
1873
|
-
} else {
|
|
1874
|
-
this.focusedIndex = 0;
|
|
1875
1155
|
}
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
var open = this.props.open;
|
|
1883
|
-
|
|
1884
|
-
if (open) {
|
|
1885
|
-
this.resetFocusedIndex();
|
|
1886
|
-
this.scheduleToFocusCurrentItem();
|
|
1887
|
-
} else if (!open) {
|
|
1888
|
-
this.itemsClicked = false;
|
|
1156
|
+
|
|
1157
|
+
if (this.props.labels !== prevProps.labels) {
|
|
1158
|
+
// eslint-disable-next-line react/no-did-update-set-state
|
|
1159
|
+
this.setState({
|
|
1160
|
+
labels: _extends({}, this.state.labels, this.props.labels)
|
|
1161
|
+
});
|
|
1889
1162
|
}
|
|
1890
1163
|
}
|
|
1891
|
-
}
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
componentWillUnmount() {
|
|
1167
|
+
this.removeEventListeners();
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
hasSearchBox() {
|
|
1171
|
+
return !!this.props.onSearchTextChanged && typeof this.props.searchText === "string";
|
|
1172
|
+
} // Resets our initial focus index to what was passed in
|
|
1173
|
+
// via the props
|
|
1174
|
+
|
|
1175
|
+
|
|
1176
|
+
resetFocusedIndex() {
|
|
1177
|
+
const {
|
|
1178
|
+
initialFocusedIndex
|
|
1179
|
+
} = this.props; // If we are given an initial focus index, select it. Otherwise
|
|
1180
|
+
// default to the first item
|
|
1181
|
+
|
|
1182
|
+
if (initialFocusedIndex) {
|
|
1183
|
+
// If we have a search box visible, then our focus
|
|
1184
|
+
// index is going to be offset by 1, since the orginal
|
|
1185
|
+
// index doesn't account for the search box's
|
|
1186
|
+
// existence.
|
|
1187
|
+
if (this.hasSearchBox()) {
|
|
1188
|
+
this.focusedIndex = initialFocusedIndex + 1;
|
|
1896
1189
|
} else {
|
|
1897
|
-
this.
|
|
1190
|
+
this.focusedIndex = initialFocusedIndex;
|
|
1898
1191
|
}
|
|
1192
|
+
} else {
|
|
1193
|
+
this.focusedIndex = 0;
|
|
1899
1194
|
}
|
|
1900
|
-
}
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1195
|
+
} // Figure out focus states for the dropdown after it has changed from open
|
|
1196
|
+
// to closed or vice versa
|
|
1197
|
+
|
|
1198
|
+
|
|
1199
|
+
initialFocusItem() {
|
|
1200
|
+
const {
|
|
1201
|
+
open
|
|
1202
|
+
} = this.props;
|
|
1203
|
+
|
|
1204
|
+
if (open) {
|
|
1205
|
+
this.resetFocusedIndex();
|
|
1206
|
+
this.scheduleToFocusCurrentItem();
|
|
1207
|
+
} else if (!open) {
|
|
1208
|
+
this.itemsClicked = false;
|
|
1911
1209
|
}
|
|
1912
|
-
}
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
this.
|
|
1919
|
-
return _this3.focusCurrentItem();
|
|
1920
|
-
});
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
updateEventListeners() {
|
|
1213
|
+
if (this.props.open) {
|
|
1214
|
+
this.addEventListeners();
|
|
1215
|
+
} else {
|
|
1216
|
+
this.removeEventListeners();
|
|
1921
1217
|
}
|
|
1922
|
-
}
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
// force react-window to scroll to ensure the focused item is visible
|
|
1929
|
-
if (this.listRef.current) {
|
|
1930
|
-
// Our focused index does not include disabled items, but the
|
|
1931
|
-
// react-window index system does include the disabled items
|
|
1932
|
-
// in the count. So we need to use "originalIndex", which
|
|
1933
|
-
// does account for disabled items.
|
|
1934
|
-
this.listRef.current.scrollToItem(fousedItemRef.originalIndex);
|
|
1935
|
-
}
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
addEventListeners() {
|
|
1221
|
+
document.addEventListener("mouseup", this.handleInteract);
|
|
1222
|
+
document.addEventListener("touchend", this.handleInteract);
|
|
1223
|
+
}
|
|
1936
1224
|
|
|
1937
|
-
|
|
1225
|
+
removeEventListeners() {
|
|
1226
|
+
document.removeEventListener("mouseup", this.handleInteract);
|
|
1227
|
+
document.removeEventListener("touchend", this.handleInteract);
|
|
1228
|
+
}
|
|
1938
1229
|
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1230
|
+
scheduleToFocusCurrentItem() {
|
|
1231
|
+
// wait for windowed items to be recalculated
|
|
1232
|
+
this.props.schedule.animationFrame(() => this.focusCurrentItem());
|
|
1233
|
+
}
|
|
1942
1234
|
|
|
1943
|
-
|
|
1944
|
-
|
|
1235
|
+
focusCurrentItem() {
|
|
1236
|
+
const fousedItemRef = this.state.itemRefs[this.focusedIndex];
|
|
1237
|
+
|
|
1238
|
+
if (fousedItemRef) {
|
|
1239
|
+
// force react-window to scroll to ensure the focused item is visible
|
|
1240
|
+
if (this.listRef.current) {
|
|
1241
|
+
// Our focused index does not include disabled items, but the
|
|
1242
|
+
// react-window index system does include the disabled items
|
|
1243
|
+
// in the count. So we need to use "originalIndex", which
|
|
1244
|
+
// does account for disabled items.
|
|
1245
|
+
this.listRef.current.scrollToItem(fousedItemRef.originalIndex);
|
|
1945
1246
|
}
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
this.
|
|
1247
|
+
|
|
1248
|
+
const node = ReactDOM.findDOMNode(fousedItemRef.ref.current);
|
|
1249
|
+
|
|
1250
|
+
if (node) {
|
|
1251
|
+
node.focus(); // Keep track of the original index of the newly focused item.
|
|
1252
|
+
// To be used if the set of focusable items in the menu changes
|
|
1253
|
+
|
|
1254
|
+
this.focusedOriginalIndex = fousedItemRef.originalIndex;
|
|
1954
1255
|
}
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1955
1258
|
|
|
1956
|
-
|
|
1259
|
+
focusPreviousItem() {
|
|
1260
|
+
if (this.focusedIndex === 0) {
|
|
1261
|
+
this.focusedIndex = this.state.itemRefs.length - 1;
|
|
1262
|
+
} else {
|
|
1263
|
+
this.focusedIndex -= 1;
|
|
1957
1264
|
}
|
|
1958
|
-
}, {
|
|
1959
|
-
key: "focusNextItem",
|
|
1960
|
-
value: function focusNextItem() {
|
|
1961
|
-
if (this.focusedIndex === this.state.itemRefs.length - 1) {
|
|
1962
|
-
this.focusedIndex = 0;
|
|
1963
|
-
} else {
|
|
1964
|
-
this.focusedIndex += 1;
|
|
1965
|
-
}
|
|
1966
1265
|
|
|
1967
|
-
|
|
1266
|
+
this.scheduleToFocusCurrentItem();
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
focusNextItem() {
|
|
1270
|
+
if (this.focusedIndex === this.state.itemRefs.length - 1) {
|
|
1271
|
+
this.focusedIndex = 0;
|
|
1272
|
+
} else {
|
|
1273
|
+
this.focusedIndex += 1;
|
|
1968
1274
|
}
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1275
|
+
|
|
1276
|
+
this.scheduleToFocusCurrentItem();
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
restoreTabOrder() {
|
|
1280
|
+
// NOTE: Because the dropdown is portalled out of its natural
|
|
1281
|
+
// position in the DOM, we need to manually return focus to the
|
|
1282
|
+
// opener element before we let the natural propagation of tab
|
|
1283
|
+
// shift the focus to the next element in the tab order.
|
|
1284
|
+
if (this.props.openerElement) {
|
|
1285
|
+
this.props.openerElement.focus();
|
|
1979
1286
|
}
|
|
1980
|
-
}
|
|
1981
|
-
key: "getItemRole",
|
|
1982
|
-
value: function getItemRole() {
|
|
1983
|
-
var role = this.props.role;
|
|
1287
|
+
}
|
|
1984
1288
|
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1289
|
+
getItemRole() {
|
|
1290
|
+
const {
|
|
1291
|
+
role
|
|
1292
|
+
} = this.props;
|
|
1988
1293
|
|
|
1989
|
-
|
|
1990
|
-
|
|
1294
|
+
switch (role) {
|
|
1295
|
+
case "listbox":
|
|
1296
|
+
return "option";
|
|
1991
1297
|
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1298
|
+
case "menu":
|
|
1299
|
+
return "menuitem";
|
|
1300
|
+
|
|
1301
|
+
default:
|
|
1302
|
+
throw new Error(`Expected "listbox" or "menu" for role, but receieved "${role}" instead.`);
|
|
1995
1303
|
}
|
|
1996
|
-
}
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
var includeSearchCount = showSearchTextInput ? 1 : 0; // Verify if there are items to be rendered or not
|
|
2006
|
-
|
|
2007
|
-
var numResults = items.length - includeSearchCount;
|
|
2008
|
-
|
|
2009
|
-
if (numResults === 0) {
|
|
2010
|
-
return /*#__PURE__*/createElement(LabelMedium, {
|
|
2011
|
-
style: styles$6.noResult,
|
|
2012
|
-
testId: "dropdown-core-no-results"
|
|
2013
|
-
}, noResults);
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
maybeRenderNoResults() {
|
|
1307
|
+
const {
|
|
1308
|
+
items,
|
|
1309
|
+
onSearchTextChanged,
|
|
1310
|
+
searchText,
|
|
1311
|
+
labels: {
|
|
1312
|
+
noResults
|
|
2014
1313
|
}
|
|
1314
|
+
} = this.props;
|
|
1315
|
+
const showSearchTextInput = !!onSearchTextChanged && typeof searchText === "string";
|
|
1316
|
+
const includeSearchCount = showSearchTextInput ? 1 : 0; // Verify if there are items to be rendered or not
|
|
2015
1317
|
|
|
2016
|
-
|
|
1318
|
+
const numResults = items.length - includeSearchCount;
|
|
1319
|
+
|
|
1320
|
+
if (numResults === 0) {
|
|
1321
|
+
return /*#__PURE__*/createElement(LabelMedium, {
|
|
1322
|
+
style: styles$6.noResult,
|
|
1323
|
+
testId: "dropdown-core-no-results"
|
|
1324
|
+
}, noResults);
|
|
2017
1325
|
}
|
|
2018
|
-
/**
|
|
2019
|
-
* Process the items and wrap them into an array that react-window can
|
|
2020
|
-
* interpret
|
|
2021
|
-
*/
|
|
2022
|
-
|
|
2023
|
-
}, {
|
|
2024
|
-
key: "parseItemsList",
|
|
2025
|
-
value: function parseItemsList() {
|
|
2026
|
-
var _this4 = this;
|
|
2027
|
-
|
|
2028
|
-
var focusCounter = 0;
|
|
2029
|
-
var itemRole = this.getItemRole();
|
|
2030
|
-
return this.props.items.map(function (item, index) {
|
|
2031
|
-
if (!SeparatorItem.isClassOf(item.component) && item.focusable) {
|
|
2032
|
-
focusCounter += 1;
|
|
2033
|
-
}
|
|
2034
1326
|
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
_this4.handleClickFocus(0);
|
|
2042
|
-
|
|
2043
|
-
_this4.focusCurrentItem();
|
|
2044
|
-
},
|
|
2045
|
-
populatedProps: {
|
|
2046
|
-
style: searchInputStyle,
|
|
2047
|
-
// pass the current ref down to the input element
|
|
2048
|
-
itemRef: _this4.state.itemRefs[focusIndex] ? _this4.state.itemRefs[focusIndex].ref : null
|
|
2049
|
-
}
|
|
2050
|
-
});
|
|
2051
|
-
}
|
|
1327
|
+
return null;
|
|
1328
|
+
}
|
|
1329
|
+
/**
|
|
1330
|
+
* Process the items and wrap them into an array that react-window can
|
|
1331
|
+
* interpret
|
|
1332
|
+
*/
|
|
2052
1333
|
|
|
2053
|
-
return _objectSpread2(_objectSpread2({}, item), {}, {
|
|
2054
|
-
role: itemRole,
|
|
2055
|
-
ref: item.focusable ? _this4.state.itemRefs[focusIndex] ? _this4.state.itemRefs[focusIndex].ref : null : null,
|
|
2056
|
-
onClick: function onClick() {
|
|
2057
|
-
_this4.handleClickFocus(focusIndex);
|
|
2058
1334
|
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
1335
|
+
parseItemsList() {
|
|
1336
|
+
let focusCounter = 0;
|
|
1337
|
+
const itemRole = this.getItemRole();
|
|
1338
|
+
return this.props.items.map((item, index) => {
|
|
1339
|
+
if (!SeparatorItem.isClassOf(item.component) && item.focusable) {
|
|
1340
|
+
focusCounter += 1;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
const focusIndex = focusCounter - 1;
|
|
2062
1344
|
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
1345
|
+
if (SearchTextInput.isClassOf(item.component)) {
|
|
1346
|
+
return _extends({}, item, {
|
|
1347
|
+
// override to avoid losing focus when pressing a key
|
|
1348
|
+
onClick: () => {
|
|
1349
|
+
this.handleClickFocus(0);
|
|
1350
|
+
this.focusCurrentItem();
|
|
1351
|
+
},
|
|
1352
|
+
populatedProps: {
|
|
1353
|
+
style: searchInputStyle,
|
|
1354
|
+
// pass the current ref down to the input element
|
|
1355
|
+
itemRef: this.state.itemRefs[focusIndex] ? this.state.itemRefs[focusIndex].ref : null
|
|
2066
1356
|
}
|
|
2067
1357
|
});
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
return _extends({}, item, {
|
|
1361
|
+
role: itemRole,
|
|
1362
|
+
ref: item.focusable ? this.state.itemRefs[focusIndex] ? this.state.itemRefs[focusIndex].ref : null : null,
|
|
1363
|
+
onClick: () => {
|
|
1364
|
+
this.handleClickFocus(focusIndex);
|
|
1365
|
+
|
|
1366
|
+
if (item.component.props.onClick) {
|
|
1367
|
+
item.component.props.onClick();
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
if (item.populatedProps.onClick) {
|
|
1371
|
+
item.populatedProps.onClick();
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
2068
1374
|
});
|
|
2069
|
-
}
|
|
2070
|
-
}
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
},
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
}
|
|
2096
|
-
}
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
_this5.popperElement = node;
|
|
2115
|
-
}
|
|
2116
|
-
},
|
|
2117
|
-
referenceElement: this.props.openerElement,
|
|
2118
|
-
placement: alignment === "left" ? "bottom-start" : "bottom-end",
|
|
2119
|
-
modifiers: {
|
|
2120
|
-
wbVisibility: visibilityModifierDefaultConfig,
|
|
2121
|
-
preventOverflow: {
|
|
2122
|
-
boundariesElement: "viewport",
|
|
2123
|
-
escapeWithReference: true
|
|
2124
|
-
}
|
|
1375
|
+
});
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
renderItems(isReferenceHidden) {
|
|
1379
|
+
const {
|
|
1380
|
+
dropdownStyle,
|
|
1381
|
+
light,
|
|
1382
|
+
openerElement
|
|
1383
|
+
} = this.props; // The dropdown width is at least the width of the opener.
|
|
1384
|
+
// It's only used if the element exists in the DOM
|
|
1385
|
+
|
|
1386
|
+
const openerStyle = openerElement && window.getComputedStyle(openerElement);
|
|
1387
|
+
const minDropdownWidth = openerStyle ? openerStyle.getPropertyValue("width") : 0; // preprocess items data to pass it to the renderer
|
|
1388
|
+
|
|
1389
|
+
const itemsList = this.parseItemsList();
|
|
1390
|
+
return /*#__PURE__*/createElement(View // Stop propagation to prevent the mouseup listener on the
|
|
1391
|
+
// document from closing the menu.
|
|
1392
|
+
, {
|
|
1393
|
+
onMouseUp: this.handleDropdownMouseUp,
|
|
1394
|
+
role: this.props.role,
|
|
1395
|
+
style: [styles$6.dropdown, light && styles$6.light, isReferenceHidden && styles$6.hidden, {
|
|
1396
|
+
minWidth: minDropdownWidth
|
|
1397
|
+
}, dropdownStyle]
|
|
1398
|
+
}, /*#__PURE__*/createElement(DropdownCoreVirtualized$1, {
|
|
1399
|
+
data: itemsList,
|
|
1400
|
+
listRef: this.listRef
|
|
1401
|
+
}), this.maybeRenderNoResults());
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
renderDropdown() {
|
|
1405
|
+
const {
|
|
1406
|
+
alignment,
|
|
1407
|
+
openerElement
|
|
1408
|
+
} = this.props; // If we are in a modal, we find where we should be portalling the menu
|
|
1409
|
+
// by using the helper function from the modal package on the opener
|
|
1410
|
+
// element.
|
|
1411
|
+
// If we are not in a modal, we use body as the location to portal to.
|
|
1412
|
+
|
|
1413
|
+
const modalHost = maybeGetPortalMountedModalHostElement(openerElement) || document.querySelector("body");
|
|
1414
|
+
|
|
1415
|
+
if (modalHost) {
|
|
1416
|
+
return /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/createElement(Popper, {
|
|
1417
|
+
innerRef: node => {
|
|
1418
|
+
if (node) {
|
|
1419
|
+
this.popperElement = node;
|
|
2125
1420
|
}
|
|
2126
|
-
},
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
}
|
|
2142
|
-
}
|
|
2143
|
-
}
|
|
1421
|
+
},
|
|
1422
|
+
referenceElement: this.props.openerElement,
|
|
1423
|
+
strategy: "fixed",
|
|
1424
|
+
placement: alignment === "left" ? "bottom-start" : "bottom-end",
|
|
1425
|
+
modifiers: [{
|
|
1426
|
+
name: "preventOverflow",
|
|
1427
|
+
options: {
|
|
1428
|
+
rootBoundary: "viewport",
|
|
1429
|
+
// Allows to overlap the popper in case there's
|
|
1430
|
+
// no more vertical room in the viewport.
|
|
1431
|
+
altAxis: true,
|
|
1432
|
+
// Also needed to make sure the Popper will be
|
|
1433
|
+
// displayed correctly in different contexts
|
|
1434
|
+
// (e.g inside a Modal)
|
|
1435
|
+
tether: false
|
|
1436
|
+
}
|
|
1437
|
+
}]
|
|
1438
|
+
}, ({
|
|
1439
|
+
placement,
|
|
1440
|
+
ref,
|
|
1441
|
+
style,
|
|
1442
|
+
hasPopperEscaped,
|
|
1443
|
+
isReferenceHidden
|
|
1444
|
+
}) => {
|
|
1445
|
+
// For some reason react-popper includes `pointerEvents: "none"`
|
|
1446
|
+
// in the `style` it passes to us, but only when running the tests.
|
|
1447
|
+
const restStyle = _objectWithoutPropertiesLoose(style, _excluded$1);
|
|
1448
|
+
|
|
1449
|
+
return /*#__PURE__*/createElement("div", {
|
|
1450
|
+
ref: ref,
|
|
1451
|
+
style: restStyle,
|
|
1452
|
+
"data-placement": placement
|
|
1453
|
+
}, this.renderItems(hasPopperEscaped || isReferenceHidden));
|
|
1454
|
+
}), modalHost);
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
return null;
|
|
1458
|
+
}
|
|
2144
1459
|
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
className: className
|
|
2160
|
-
}, opener, open && this.renderDropdown());
|
|
2161
|
-
}
|
|
2162
|
-
}]);
|
|
1460
|
+
render() {
|
|
1461
|
+
const {
|
|
1462
|
+
open,
|
|
1463
|
+
opener,
|
|
1464
|
+
style,
|
|
1465
|
+
className
|
|
1466
|
+
} = this.props;
|
|
1467
|
+
return /*#__PURE__*/createElement(View, {
|
|
1468
|
+
onKeyDown: this.handleKeyDown,
|
|
1469
|
+
onKeyUp: this.handleKeyUp,
|
|
1470
|
+
style: [styles$6.menuWrapper, style],
|
|
1471
|
+
className: className
|
|
1472
|
+
}, opener, open && this.renderDropdown());
|
|
1473
|
+
}
|
|
2163
1474
|
|
|
2164
|
-
|
|
2165
|
-
}(Component);
|
|
1475
|
+
}
|
|
2166
1476
|
|
|
2167
|
-
|
|
1477
|
+
DropdownCore.defaultProps = {
|
|
2168
1478
|
alignment: "left",
|
|
2169
1479
|
labels: {
|
|
2170
1480
|
noResults: defaultLabels.noResults
|
|
2171
1481
|
},
|
|
2172
1482
|
light: false
|
|
2173
|
-
}
|
|
2174
|
-
|
|
2175
|
-
var styles$6 = StyleSheet.create({
|
|
1483
|
+
};
|
|
1484
|
+
const styles$6 = StyleSheet.create({
|
|
2176
1485
|
menuWrapper: {
|
|
2177
1486
|
width: "fit-content"
|
|
2178
1487
|
},
|
|
@@ -2181,8 +1490,8 @@ var styles$6 = StyleSheet.create({
|
|
|
2181
1490
|
borderRadius: 4,
|
|
2182
1491
|
paddingTop: Spacing.xxxSmall_4,
|
|
2183
1492
|
paddingBottom: Spacing.xxxSmall_4,
|
|
2184
|
-
border:
|
|
2185
|
-
boxShadow:
|
|
1493
|
+
border: `solid 1px ${Color.offBlack16}`,
|
|
1494
|
+
boxShadow: `0px 8px 8px 0px ${fade(Color.offBlack, 0.1)}`,
|
|
2186
1495
|
overflowY: "auto"
|
|
2187
1496
|
},
|
|
2188
1497
|
light: {
|
|
@@ -2190,6 +1499,7 @@ var styles$6 = StyleSheet.create({
|
|
|
2190
1499
|
border: "none"
|
|
2191
1500
|
},
|
|
2192
1501
|
hidden: {
|
|
1502
|
+
pointerEvents: "none",
|
|
2193
1503
|
visibility: "hidden"
|
|
2194
1504
|
},
|
|
2195
1505
|
noResult: {
|
|
@@ -2200,7 +1510,8 @@ var styles$6 = StyleSheet.create({
|
|
|
2200
1510
|
});
|
|
2201
1511
|
var DropdownCore$1 = withActionScheduler(DropdownCore);
|
|
2202
1512
|
|
|
2203
|
-
|
|
1513
|
+
const _excluded$2 = ["children", "disabled", "focused", "hovered", "pressed", "waiting", "testId", "opened", "aria-label"];
|
|
1514
|
+
const StyledButton$1 = addStyle("button");
|
|
2204
1515
|
/**
|
|
2205
1516
|
* Although this component shares a lot with ButtonCore there are a couple
|
|
2206
1517
|
* of differences:
|
|
@@ -2208,69 +1519,55 @@ var StyledButton$1 = addStyle("button");
|
|
|
2208
1519
|
* - the down caret icon is smaller that the one that would be used by ButtonCore
|
|
2209
1520
|
*/
|
|
2210
1521
|
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
"data-test-id": testId
|
|
2255
|
-
}), /*#__PURE__*/createElement(View, {
|
|
2256
|
-
style: !disabled && (hovered || focused) && buttonStyles.focus
|
|
2257
|
-
}, label), /*#__PURE__*/createElement(Strut, {
|
|
2258
|
-
size: Spacing.xxxSmall_4
|
|
2259
|
-
}), /*#__PURE__*/createElement(Icon, {
|
|
2260
|
-
size: "small",
|
|
2261
|
-
color: "currentColor",
|
|
2262
|
-
icon: icons.caretDown
|
|
2263
|
-
}));
|
|
2264
|
-
}
|
|
2265
|
-
}]);
|
|
2266
|
-
|
|
2267
|
-
return ActionMenuOpenerCore;
|
|
2268
|
-
}(Component);
|
|
1522
|
+
class ActionMenuOpenerCore extends Component {
|
|
1523
|
+
render() {
|
|
1524
|
+
const _this$props = this.props,
|
|
1525
|
+
{
|
|
1526
|
+
children,
|
|
1527
|
+
disabled: disabledProp,
|
|
1528
|
+
focused,
|
|
1529
|
+
hovered,
|
|
1530
|
+
pressed,
|
|
1531
|
+
testId,
|
|
1532
|
+
opened,
|
|
1533
|
+
"aria-label": ariaLabel
|
|
1534
|
+
} = _this$props,
|
|
1535
|
+
restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$2);
|
|
1536
|
+
|
|
1537
|
+
const buttonColor = SemanticColor.controlDefault;
|
|
1538
|
+
|
|
1539
|
+
const buttonStyles = _generateStyles(buttonColor);
|
|
1540
|
+
|
|
1541
|
+
const disabled = disabledProp;
|
|
1542
|
+
const defaultStyle = [sharedStyles.shared, disabled && sharedStyles.disabled, buttonStyles.default, disabled && buttonStyles.disabled, !disabled && pressed && buttonStyles.active];
|
|
1543
|
+
const label = /*#__PURE__*/createElement(LabelLarge, {
|
|
1544
|
+
style: sharedStyles.text
|
|
1545
|
+
}, children);
|
|
1546
|
+
return /*#__PURE__*/createElement(StyledButton$1, _extends({
|
|
1547
|
+
"aria-expanded": opened ? "true" : "false",
|
|
1548
|
+
"aria-haspopup": "menu",
|
|
1549
|
+
"aria-label": ariaLabel,
|
|
1550
|
+
disabled: disabled,
|
|
1551
|
+
style: defaultStyle,
|
|
1552
|
+
type: "button"
|
|
1553
|
+
}, restProps, {
|
|
1554
|
+
"data-test-id": testId
|
|
1555
|
+
}), /*#__PURE__*/createElement(View, {
|
|
1556
|
+
style: !disabled && (hovered || focused) && buttonStyles.focus
|
|
1557
|
+
}, label), /*#__PURE__*/createElement(Strut, {
|
|
1558
|
+
size: Spacing.xxxSmall_4
|
|
1559
|
+
}), /*#__PURE__*/createElement(Icon, {
|
|
1560
|
+
size: "small",
|
|
1561
|
+
color: "currentColor",
|
|
1562
|
+
icon: icons.caretDown
|
|
1563
|
+
}));
|
|
1564
|
+
}
|
|
2269
1565
|
|
|
2270
|
-
|
|
1566
|
+
}
|
|
1567
|
+
ActionMenuOpenerCore.contextTypes = {
|
|
2271
1568
|
router: any
|
|
2272
|
-
}
|
|
2273
|
-
|
|
1569
|
+
};
|
|
1570
|
+
const sharedStyles = StyleSheet.create({
|
|
2274
1571
|
shared: {
|
|
2275
1572
|
position: "relative",
|
|
2276
1573
|
display: "inline-flex",
|
|
@@ -2316,18 +1613,20 @@ var sharedStyles = StyleSheet.create({
|
|
|
2316
1613
|
position: "absolute"
|
|
2317
1614
|
}
|
|
2318
1615
|
});
|
|
2319
|
-
|
|
1616
|
+
const styles$7 = {};
|
|
2320
1617
|
|
|
2321
|
-
|
|
2322
|
-
|
|
1618
|
+
const _generateStyles = color => {
|
|
1619
|
+
const buttonType = color;
|
|
2323
1620
|
|
|
2324
1621
|
if (styles$7[buttonType]) {
|
|
2325
1622
|
return styles$7[buttonType];
|
|
2326
1623
|
}
|
|
2327
1624
|
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
1625
|
+
const {
|
|
1626
|
+
offBlack32
|
|
1627
|
+
} = Color;
|
|
1628
|
+
const activeColor = mix(offBlack32, color);
|
|
1629
|
+
let newStyles = {};
|
|
2331
1630
|
newStyles = {
|
|
2332
1631
|
default: {
|
|
2333
1632
|
background: "none",
|
|
@@ -2353,202 +1652,177 @@ var _generateStyles = function _generateStyles(color) {
|
|
|
2353
1652
|
cursor: "default"
|
|
2354
1653
|
}
|
|
2355
1654
|
};
|
|
2356
|
-
styles$7[buttonType] = StyleSheet.create(newStyles);
|
|
2357
|
-
return styles$7[buttonType];
|
|
2358
|
-
};
|
|
2359
|
-
|
|
2360
|
-
/**
|
|
2361
|
-
* A menu that consists of various types of items.
|
|
2362
|
-
*/
|
|
2363
|
-
var ActionMenu = /*#__PURE__*/function (_React$Component) {
|
|
2364
|
-
_inherits(ActionMenu, _React$Component);
|
|
2365
|
-
|
|
2366
|
-
var _super = _createSuper(ActionMenu);
|
|
2367
|
-
|
|
2368
|
-
function ActionMenu() {
|
|
2369
|
-
var _this;
|
|
2370
|
-
|
|
2371
|
-
_classCallCheck(this, ActionMenu);
|
|
2372
|
-
|
|
2373
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
2374
|
-
args[_key] = arguments[_key];
|
|
2375
|
-
}
|
|
2376
|
-
|
|
2377
|
-
_this = _super.call.apply(_super, [this].concat(args));
|
|
1655
|
+
styles$7[buttonType] = StyleSheet.create(newStyles);
|
|
1656
|
+
return styles$7[buttonType];
|
|
1657
|
+
};
|
|
2378
1658
|
|
|
2379
|
-
|
|
1659
|
+
const _excluded$3 = ["text"];
|
|
2380
1660
|
|
|
2381
|
-
|
|
1661
|
+
/**
|
|
1662
|
+
* A menu that consists of various types of items.
|
|
1663
|
+
*/
|
|
1664
|
+
class ActionMenu extends Component {
|
|
1665
|
+
constructor(...args) {
|
|
1666
|
+
super(...args);
|
|
1667
|
+
this.state = {
|
|
2382
1668
|
opened: false
|
|
2383
|
-
}
|
|
1669
|
+
};
|
|
2384
1670
|
|
|
2385
|
-
|
|
1671
|
+
this.handleItemSelected = () => {
|
|
2386
1672
|
// close menu
|
|
2387
|
-
|
|
1673
|
+
this.handleOpenChanged(false); // Bring focus back to the opener element.
|
|
2388
1674
|
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
_this.openerElement.focus();
|
|
1675
|
+
if (this.openerElement) {
|
|
1676
|
+
this.openerElement.focus();
|
|
2392
1677
|
}
|
|
2393
|
-
}
|
|
1678
|
+
};
|
|
2394
1679
|
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
opened
|
|
1680
|
+
this.handleOpenChanged = opened => {
|
|
1681
|
+
this.setState({
|
|
1682
|
+
opened
|
|
2398
1683
|
});
|
|
2399
1684
|
|
|
2400
|
-
if (
|
|
2401
|
-
|
|
1685
|
+
if (this.props.onToggle) {
|
|
1686
|
+
this.props.onToggle(opened);
|
|
2402
1687
|
}
|
|
2403
|
-
}
|
|
1688
|
+
};
|
|
2404
1689
|
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
1690
|
+
this.handleOptionSelected = selectedValue => {
|
|
1691
|
+
const {
|
|
1692
|
+
onChange,
|
|
1693
|
+
selectedValues
|
|
1694
|
+
} = this.props; // If either of these are not defined, return.
|
|
2409
1695
|
|
|
2410
1696
|
if (!onChange || !selectedValues) {
|
|
2411
1697
|
return;
|
|
2412
1698
|
}
|
|
2413
1699
|
|
|
2414
1700
|
if (selectedValues.includes(selectedValue)) {
|
|
2415
|
-
|
|
2416
|
-
|
|
1701
|
+
const index = selectedValues.indexOf(selectedValue);
|
|
1702
|
+
const updatedSelection = [].concat(selectedValues.slice(0, index), selectedValues.slice(index + 1));
|
|
2417
1703
|
onChange(updatedSelection);
|
|
2418
1704
|
} else {
|
|
2419
1705
|
// Item was newly selected
|
|
2420
|
-
onChange([].concat(
|
|
1706
|
+
onChange([].concat(selectedValues, [selectedValue]));
|
|
2421
1707
|
}
|
|
2422
1708
|
|
|
2423
|
-
|
|
2424
|
-
}
|
|
2425
|
-
|
|
2426
|
-
_defineProperty(_assertThisInitialized(_this), "handleOpenerRef", function (node) {
|
|
2427
|
-
_this.openerElement = ReactDOM.findDOMNode(node);
|
|
2428
|
-
});
|
|
1709
|
+
this.handleItemSelected();
|
|
1710
|
+
};
|
|
2429
1711
|
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
}
|
|
1712
|
+
this.handleOpenerRef = node => {
|
|
1713
|
+
this.openerElement = ReactDOM.findDOMNode(node);
|
|
1714
|
+
};
|
|
2433
1715
|
|
|
2434
|
-
|
|
1716
|
+
this.handleClick = e => {
|
|
1717
|
+
this.handleOpenChanged(!this.state.opened);
|
|
1718
|
+
};
|
|
2435
1719
|
}
|
|
2436
1720
|
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
1721
|
+
/**
|
|
1722
|
+
* Used to sync the `opened` state when this component acts as a controlled
|
|
1723
|
+
* component
|
|
1724
|
+
*/
|
|
1725
|
+
static getDerivedStateFromProps(props, state) {
|
|
1726
|
+
return {
|
|
1727
|
+
opened: typeof props.opened === "boolean" ? props.opened : state.opened
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
2441
1730
|
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
1731
|
+
getMenuItems() {
|
|
1732
|
+
const {
|
|
1733
|
+
children,
|
|
1734
|
+
selectedValues
|
|
1735
|
+
} = this.props;
|
|
1736
|
+
const allChildren = Children.toArray(children).filter(Boolean); // verify if there's at least one OptionItem element to indent the
|
|
1737
|
+
// possible Action items
|
|
1738
|
+
|
|
1739
|
+
const isOptionItemIncluded = allChildren.some(item => OptionItem.isClassOf(item));
|
|
1740
|
+
return allChildren.map(item => {
|
|
1741
|
+
const {
|
|
1742
|
+
value,
|
|
1743
|
+
disabled
|
|
1744
|
+
} = item.props;
|
|
1745
|
+
const itemObject = {
|
|
1746
|
+
component: item,
|
|
1747
|
+
focusable: ActionItem.isClassOf(item) || OptionItem.isClassOf(item) ? !disabled : false,
|
|
1748
|
+
populatedProps: {}
|
|
1749
|
+
};
|
|
2447
1750
|
|
|
2448
|
-
|
|
2449
|
-
return
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
1751
|
+
if (ActionItem.isClassOf(item)) {
|
|
1752
|
+
return _extends({}, itemObject, {
|
|
1753
|
+
populatedProps: {
|
|
1754
|
+
indent: isOptionItemIncluded,
|
|
1755
|
+
onClick: this.handleItemSelected
|
|
1756
|
+
}
|
|
1757
|
+
});
|
|
1758
|
+
} else if (OptionItem.isClassOf(item)) {
|
|
1759
|
+
return _extends({}, itemObject, {
|
|
1760
|
+
populatedProps: {
|
|
1761
|
+
onToggle: this.handleOptionSelected,
|
|
1762
|
+
selected: selectedValues ? selectedValues.includes(value) : false,
|
|
1763
|
+
variant: "check"
|
|
1764
|
+
}
|
|
1765
|
+
});
|
|
1766
|
+
} else {
|
|
1767
|
+
return itemObject;
|
|
1768
|
+
}
|
|
1769
|
+
});
|
|
1770
|
+
}
|
|
2460
1771
|
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
disabled = _this$props3.disabled,
|
|
2486
|
-
menuText = _this$props3.menuText,
|
|
2487
|
-
opened = _this$props3.opened,
|
|
2488
|
-
opener = _this$props3.opener,
|
|
2489
|
-
testId = _this$props3.testId;
|
|
2490
|
-
return /*#__PURE__*/createElement(DropdownOpener, {
|
|
2491
|
-
onClick: this.handleClick,
|
|
2492
|
-
disabled: numItems === 0 || disabled,
|
|
2493
|
-
text: menuText,
|
|
2494
|
-
ref: this.handleOpenerRef,
|
|
2495
|
-
testId: opener ? undefined : testId
|
|
2496
|
-
}, opener ? opener : function (openerProps) {
|
|
2497
|
-
var text = openerProps.text,
|
|
2498
|
-
eventState = _objectWithoutProperties(openerProps, ["text"]);
|
|
2499
|
-
|
|
2500
|
-
return /*#__PURE__*/createElement(ActionMenuOpenerCore, _extends({}, eventState, {
|
|
2501
|
-
disabled: disabled,
|
|
2502
|
-
opened: !!opened,
|
|
2503
|
-
testId: testId
|
|
2504
|
-
}), menuText);
|
|
2505
|
-
});
|
|
2506
|
-
}
|
|
2507
|
-
}, {
|
|
2508
|
-
key: "render",
|
|
2509
|
-
value: function render() {
|
|
2510
|
-
var _this$props4 = this.props,
|
|
2511
|
-
alignment = _this$props4.alignment,
|
|
2512
|
-
dropdownStyle = _this$props4.dropdownStyle,
|
|
2513
|
-
style = _this$props4.style,
|
|
2514
|
-
className = _this$props4.className;
|
|
2515
|
-
var items = this.getMenuItems();
|
|
2516
|
-
var dropdownOpener = this.renderOpener(items.length);
|
|
2517
|
-
return /*#__PURE__*/createElement(DropdownCore$1, {
|
|
2518
|
-
role: "menu",
|
|
2519
|
-
style: style,
|
|
2520
|
-
className: className,
|
|
2521
|
-
opener: dropdownOpener,
|
|
2522
|
-
alignment: alignment,
|
|
2523
|
-
open: this.state.opened,
|
|
2524
|
-
items: items,
|
|
2525
|
-
openerElement: this.openerElement,
|
|
2526
|
-
onOpenChanged: this.handleOpenChanged,
|
|
2527
|
-
dropdownStyle: [styles$8.menuTopSpace, dropdownStyle]
|
|
2528
|
-
});
|
|
2529
|
-
}
|
|
2530
|
-
}], [{
|
|
2531
|
-
key: "getDerivedStateFromProps",
|
|
2532
|
-
|
|
2533
|
-
/**
|
|
2534
|
-
* Used to sync the `opened` state when this component acts as a controlled
|
|
2535
|
-
* component
|
|
2536
|
-
*/
|
|
2537
|
-
value: function getDerivedStateFromProps(props, state) {
|
|
2538
|
-
return {
|
|
2539
|
-
opened: typeof props.opened === "boolean" ? props.opened : state.opened
|
|
2540
|
-
};
|
|
2541
|
-
}
|
|
2542
|
-
}]);
|
|
1772
|
+
renderOpener(numItems) {
|
|
1773
|
+
const {
|
|
1774
|
+
disabled,
|
|
1775
|
+
menuText,
|
|
1776
|
+
opened,
|
|
1777
|
+
opener,
|
|
1778
|
+
testId
|
|
1779
|
+
} = this.props;
|
|
1780
|
+
return /*#__PURE__*/createElement(DropdownOpener, {
|
|
1781
|
+
onClick: this.handleClick,
|
|
1782
|
+
disabled: numItems === 0 || disabled,
|
|
1783
|
+
text: menuText,
|
|
1784
|
+
ref: this.handleOpenerRef,
|
|
1785
|
+
testId: opener ? undefined : testId
|
|
1786
|
+
}, opener ? opener : openerProps => {
|
|
1787
|
+
const eventState = _objectWithoutPropertiesLoose(openerProps, _excluded$3);
|
|
1788
|
+
|
|
1789
|
+
return /*#__PURE__*/createElement(ActionMenuOpenerCore, _extends({}, eventState, {
|
|
1790
|
+
disabled: disabled,
|
|
1791
|
+
opened: !!opened,
|
|
1792
|
+
testId: testId
|
|
1793
|
+
}), menuText);
|
|
1794
|
+
});
|
|
1795
|
+
}
|
|
2543
1796
|
|
|
2544
|
-
|
|
2545
|
-
|
|
1797
|
+
render() {
|
|
1798
|
+
const {
|
|
1799
|
+
alignment,
|
|
1800
|
+
dropdownStyle,
|
|
1801
|
+
style,
|
|
1802
|
+
className
|
|
1803
|
+
} = this.props;
|
|
1804
|
+
const items = this.getMenuItems();
|
|
1805
|
+
const dropdownOpener = this.renderOpener(items.length);
|
|
1806
|
+
return /*#__PURE__*/createElement(DropdownCore$1, {
|
|
1807
|
+
role: "menu",
|
|
1808
|
+
style: style,
|
|
1809
|
+
className: className,
|
|
1810
|
+
opener: dropdownOpener,
|
|
1811
|
+
alignment: alignment,
|
|
1812
|
+
open: this.state.opened,
|
|
1813
|
+
items: items,
|
|
1814
|
+
openerElement: this.openerElement,
|
|
1815
|
+
onOpenChanged: this.handleOpenChanged,
|
|
1816
|
+
dropdownStyle: [styles$8.menuTopSpace, dropdownStyle]
|
|
1817
|
+
});
|
|
1818
|
+
}
|
|
2546
1819
|
|
|
2547
|
-
|
|
1820
|
+
}
|
|
1821
|
+
ActionMenu.defaultProps = {
|
|
2548
1822
|
alignment: "left",
|
|
2549
1823
|
disabled: false
|
|
2550
|
-
}
|
|
2551
|
-
|
|
1824
|
+
};
|
|
1825
|
+
const styles$8 = StyleSheet.create({
|
|
2552
1826
|
caret: {
|
|
2553
1827
|
marginLeft: 4
|
|
2554
1828
|
},
|
|
@@ -2565,106 +1839,93 @@ var styles$8 = StyleSheet.create({
|
|
|
2565
1839
|
}
|
|
2566
1840
|
});
|
|
2567
1841
|
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
1842
|
+
const _excluded$4 = ["children", "disabled", "id", "isPlaceholder", "light", "open", "testId", "onOpenChanged"];
|
|
1843
|
+
const StyledButton$2 = addStyle("button");
|
|
1844
|
+
const {
|
|
1845
|
+
blue: blue$3,
|
|
1846
|
+
white: white$4,
|
|
1847
|
+
white50,
|
|
1848
|
+
offBlack: offBlack$3,
|
|
1849
|
+
offBlack16: offBlack16$1,
|
|
1850
|
+
offBlack32: offBlack32$4,
|
|
1851
|
+
offBlack64
|
|
1852
|
+
} = Color;
|
|
2576
1853
|
|
|
2577
1854
|
/**
|
|
2578
1855
|
* An opener that opens select boxes.
|
|
2579
1856
|
*/
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
args[_key] = arguments[_key];
|
|
2592
|
-
}
|
|
2593
|
-
|
|
2594
|
-
_this = _super.call.apply(_super, [this].concat(args));
|
|
2595
|
-
|
|
2596
|
-
_defineProperty(_assertThisInitialized(_this), "handleClick", function (e) {
|
|
2597
|
-
var open = _this.props.open;
|
|
2598
|
-
|
|
2599
|
-
_this.props.onOpenChanged(!open);
|
|
2600
|
-
});
|
|
1857
|
+
class SelectOpener extends Component {
|
|
1858
|
+
constructor(...args) {
|
|
1859
|
+
super(...args);
|
|
1860
|
+
|
|
1861
|
+
this.handleClick = e => {
|
|
1862
|
+
const {
|
|
1863
|
+
open
|
|
1864
|
+
} = this.props;
|
|
1865
|
+
this.props.onOpenChanged(!open);
|
|
1866
|
+
};
|
|
1867
|
+
}
|
|
2601
1868
|
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
1869
|
+
render() {
|
|
1870
|
+
const _this$props = this.props,
|
|
1871
|
+
{
|
|
1872
|
+
children,
|
|
1873
|
+
disabled,
|
|
1874
|
+
id,
|
|
1875
|
+
isPlaceholder,
|
|
1876
|
+
light,
|
|
1877
|
+
open,
|
|
1878
|
+
testId
|
|
1879
|
+
} = _this$props,
|
|
1880
|
+
sharedProps = _objectWithoutPropertiesLoose(_this$props, _excluded$4);
|
|
1881
|
+
|
|
1882
|
+
const ClickableBehavior = getClickableBehavior(this.context.router);
|
|
1883
|
+
return /*#__PURE__*/createElement(ClickableBehavior, {
|
|
1884
|
+
disabled: disabled,
|
|
1885
|
+
onClick: this.handleClick
|
|
1886
|
+
}, (state, childrenProps) => {
|
|
1887
|
+
const stateStyles = _generateStyles$1(light, isPlaceholder);
|
|
1888
|
+
|
|
1889
|
+
const {
|
|
1890
|
+
hovered,
|
|
1891
|
+
focused,
|
|
1892
|
+
pressed
|
|
1893
|
+
} = state; // The icon colors are kind of fickle. This is just logic
|
|
1894
|
+
// based on the zeplin design.
|
|
1895
|
+
|
|
1896
|
+
const iconColor = light ? disabled || pressed ? "currentColor" : white$4 : disabled ? offBlack32$4 : offBlack64;
|
|
1897
|
+
const style = [styles$9.shared, stateStyles.default, disabled && stateStyles.disabled, !disabled && (pressed ? stateStyles.active : (hovered || focused) && stateStyles.focus)];
|
|
1898
|
+
return /*#__PURE__*/createElement(StyledButton$2, _extends({}, sharedProps, {
|
|
1899
|
+
"aria-expanded": open ? "true" : "false",
|
|
1900
|
+
"aria-haspopup": "listbox",
|
|
1901
|
+
"data-test-id": testId,
|
|
2621
1902
|
disabled: disabled,
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
"data-test-id": testId,
|
|
2637
|
-
disabled: disabled,
|
|
2638
|
-
id: id,
|
|
2639
|
-
style: style,
|
|
2640
|
-
type: "button"
|
|
2641
|
-
}, childrenProps), /*#__PURE__*/createElement(LabelMedium, {
|
|
2642
|
-
style: styles$9.text
|
|
2643
|
-
}, children), /*#__PURE__*/createElement(Icon, {
|
|
2644
|
-
icon: icons.caretDown,
|
|
2645
|
-
color: iconColor,
|
|
2646
|
-
size: "small",
|
|
2647
|
-
style: styles$9.caret,
|
|
2648
|
-
"aria-hidden": "true"
|
|
2649
|
-
}));
|
|
2650
|
-
});
|
|
2651
|
-
}
|
|
2652
|
-
}]);
|
|
2653
|
-
|
|
2654
|
-
return SelectOpener;
|
|
2655
|
-
}(Component);
|
|
1903
|
+
id: id,
|
|
1904
|
+
style: style,
|
|
1905
|
+
type: "button"
|
|
1906
|
+
}, childrenProps), /*#__PURE__*/createElement(LabelMedium, {
|
|
1907
|
+
style: styles$9.text
|
|
1908
|
+
}, children), /*#__PURE__*/createElement(Icon, {
|
|
1909
|
+
icon: icons.caretDown,
|
|
1910
|
+
color: iconColor,
|
|
1911
|
+
size: "small",
|
|
1912
|
+
style: styles$9.caret,
|
|
1913
|
+
"aria-hidden": "true"
|
|
1914
|
+
}));
|
|
1915
|
+
});
|
|
1916
|
+
}
|
|
2656
1917
|
|
|
2657
|
-
|
|
1918
|
+
}
|
|
1919
|
+
SelectOpener.contextTypes = {
|
|
2658
1920
|
router: any
|
|
2659
|
-
}
|
|
2660
|
-
|
|
2661
|
-
_defineProperty(SelectOpener, "defaultProps", {
|
|
1921
|
+
};
|
|
1922
|
+
SelectOpener.defaultProps = {
|
|
2662
1923
|
disabled: false,
|
|
2663
1924
|
light: false,
|
|
2664
1925
|
isPlaceholder: false
|
|
2665
|
-
}
|
|
2666
|
-
|
|
2667
|
-
|
|
1926
|
+
};
|
|
1927
|
+
const buttonRadius = 4;
|
|
1928
|
+
const styles$9 = StyleSheet.create({
|
|
2668
1929
|
// TODO: Dedupe with Button styles
|
|
2669
1930
|
shared: {
|
|
2670
1931
|
position: "relative",
|
|
@@ -2703,19 +1964,19 @@ var styles$9 = StyleSheet.create({
|
|
|
2703
1964
|
// changing the borderWidth to 2 messes up the button width
|
|
2704
1965
|
// and causes it to move a couple pixels. This fixes that.
|
|
2705
1966
|
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
1967
|
+
const adjustedPaddingLeft = 16 - 1;
|
|
1968
|
+
const adjustedPaddingRight = 12 - 1;
|
|
1969
|
+
const stateStyles = {};
|
|
2709
1970
|
|
|
2710
|
-
|
|
1971
|
+
const _generateStyles$1 = (light, placeholder) => {
|
|
2711
1972
|
// "hash" the parameters
|
|
2712
|
-
|
|
1973
|
+
const styleKey = `${String(light)}-${String(placeholder)}`;
|
|
2713
1974
|
|
|
2714
1975
|
if (stateStyles[styleKey]) {
|
|
2715
1976
|
return stateStyles[styleKey];
|
|
2716
1977
|
}
|
|
2717
1978
|
|
|
2718
|
-
|
|
1979
|
+
let newStyles = {};
|
|
2719
1980
|
|
|
2720
1981
|
if (light) {
|
|
2721
1982
|
newStyles = {
|
|
@@ -2779,6 +2040,8 @@ var _generateStyles$1 = function _generateStyles(light, placeholder) {
|
|
|
2779
2040
|
return stateStyles[styleKey];
|
|
2780
2041
|
};
|
|
2781
2042
|
|
|
2043
|
+
const _excluded$5 = ["children", "disabled", "id", "light", "opener", "placeholder", "selectedValue", "testId", "alignment", "dropdownStyle", "isFilterable", "onChange", "onToggle", "opened", "style", "className"];
|
|
2044
|
+
|
|
2782
2045
|
/**
|
|
2783
2046
|
* The single select allows the selection of one item. Clients are responsible
|
|
2784
2047
|
* for keeping track of the selected item in the select.
|
|
@@ -2792,66 +2055,59 @@ var _generateStyles$1 = function _generateStyles(light, placeholder) {
|
|
|
2792
2055
|
* hundreds of items without performance problems.
|
|
2793
2056
|
*
|
|
2794
2057
|
*/
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
var _super = _createSuper(SingleSelect);
|
|
2799
|
-
|
|
2800
|
-
function SingleSelect(props) {
|
|
2801
|
-
var _this;
|
|
2802
|
-
|
|
2803
|
-
_classCallCheck(this, SingleSelect);
|
|
2058
|
+
class SingleSelect extends Component {
|
|
2059
|
+
constructor(props) {
|
|
2060
|
+
super(props);
|
|
2804
2061
|
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
_defineProperty(_assertThisInitialized(_this), "selectedIndex", void 0);
|
|
2808
|
-
|
|
2809
|
-
_defineProperty(_assertThisInitialized(_this), "handleOpenChanged", function (opened) {
|
|
2810
|
-
_this.setState({
|
|
2062
|
+
this.handleOpenChanged = opened => {
|
|
2063
|
+
this.setState({
|
|
2811
2064
|
open: opened,
|
|
2812
2065
|
searchText: ""
|
|
2813
2066
|
});
|
|
2814
2067
|
|
|
2815
|
-
if (
|
|
2816
|
-
|
|
2068
|
+
if (this.props.onToggle) {
|
|
2069
|
+
this.props.onToggle(opened);
|
|
2817
2070
|
}
|
|
2818
|
-
}
|
|
2071
|
+
};
|
|
2819
2072
|
|
|
2820
|
-
|
|
2073
|
+
this.handleToggle = selectedValue => {
|
|
2821
2074
|
// Call callback if selection changed.
|
|
2822
|
-
if (selectedValue !==
|
|
2823
|
-
|
|
2075
|
+
if (selectedValue !== this.props.selectedValue) {
|
|
2076
|
+
this.props.onChange(selectedValue);
|
|
2824
2077
|
} // Bring focus back to the opener element.
|
|
2825
2078
|
|
|
2826
2079
|
|
|
2827
|
-
if (
|
|
2828
|
-
|
|
2080
|
+
if (this.state.open && this.state.openerElement) {
|
|
2081
|
+
this.state.openerElement.focus();
|
|
2829
2082
|
}
|
|
2830
2083
|
|
|
2831
|
-
|
|
2084
|
+
this.setState({
|
|
2832
2085
|
open: false // close the menu upon selection
|
|
2833
2086
|
|
|
2834
2087
|
});
|
|
2835
2088
|
|
|
2836
|
-
if (
|
|
2837
|
-
|
|
2089
|
+
if (this.props.onToggle) {
|
|
2090
|
+
this.props.onToggle(false);
|
|
2838
2091
|
}
|
|
2839
|
-
}
|
|
2092
|
+
};
|
|
2840
2093
|
|
|
2841
|
-
|
|
2094
|
+
this.mapOptionItemsToDropdownItems = children => {
|
|
2842
2095
|
// Figure out which index should receive focus when this select opens
|
|
2843
2096
|
// Needs to exclude counting items that are disabled
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
return children.map(
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2097
|
+
let indexCounter = 0;
|
|
2098
|
+
this.selectedIndex = 0;
|
|
2099
|
+
return children.map(option => {
|
|
2100
|
+
const {
|
|
2101
|
+
selectedValue
|
|
2102
|
+
} = this.props;
|
|
2103
|
+
const {
|
|
2104
|
+
disabled,
|
|
2105
|
+
value
|
|
2106
|
+
} = option.props;
|
|
2107
|
+
const selected = selectedValue === value;
|
|
2852
2108
|
|
|
2853
2109
|
if (selected) {
|
|
2854
|
-
|
|
2110
|
+
this.selectedIndex = indexCounter;
|
|
2855
2111
|
}
|
|
2856
2112
|
|
|
2857
2113
|
if (!disabled) {
|
|
@@ -2862,39 +2118,37 @@ var SingleSelect = /*#__PURE__*/function (_React$Component) {
|
|
|
2862
2118
|
component: option,
|
|
2863
2119
|
focusable: !disabled,
|
|
2864
2120
|
populatedProps: {
|
|
2865
|
-
onToggle:
|
|
2121
|
+
onToggle: this.handleToggle,
|
|
2866
2122
|
selected: selected,
|
|
2867
2123
|
variant: "check"
|
|
2868
2124
|
}
|
|
2869
2125
|
};
|
|
2870
2126
|
});
|
|
2871
|
-
}
|
|
2127
|
+
};
|
|
2872
2128
|
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
searchText
|
|
2129
|
+
this.handleSearchTextChanged = searchText => {
|
|
2130
|
+
this.setState({
|
|
2131
|
+
searchText
|
|
2876
2132
|
});
|
|
2877
|
-
}
|
|
2878
|
-
|
|
2879
|
-
_defineProperty(_assertThisInitialized(_this), "handleOpenerRef", function (node) {
|
|
2880
|
-
var openerElement = ReactDOM.findDOMNode(node);
|
|
2133
|
+
};
|
|
2881
2134
|
|
|
2882
|
-
|
|
2883
|
-
|
|
2135
|
+
this.handleOpenerRef = node => {
|
|
2136
|
+
const openerElement = ReactDOM.findDOMNode(node);
|
|
2137
|
+
this.setState({
|
|
2138
|
+
openerElement
|
|
2884
2139
|
});
|
|
2885
|
-
}
|
|
2140
|
+
};
|
|
2886
2141
|
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
}
|
|
2142
|
+
this.handleClick = e => {
|
|
2143
|
+
this.handleOpenChanged(!this.state.open);
|
|
2144
|
+
};
|
|
2890
2145
|
|
|
2891
|
-
|
|
2892
|
-
|
|
2146
|
+
this.selectedIndex = 0;
|
|
2147
|
+
this.state = {
|
|
2893
2148
|
open: false,
|
|
2894
2149
|
searchText: "",
|
|
2895
2150
|
openerElement: null
|
|
2896
2151
|
};
|
|
2897
|
-
return _this;
|
|
2898
2152
|
}
|
|
2899
2153
|
/**
|
|
2900
2154
|
* Used to sync the `opened` state when this component acts as a controlled
|
|
@@ -2902,142 +2156,132 @@ var SingleSelect = /*#__PURE__*/function (_React$Component) {
|
|
|
2902
2156
|
*/
|
|
2903
2157
|
|
|
2904
2158
|
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2159
|
+
static getDerivedStateFromProps(props, state) {
|
|
2160
|
+
return {
|
|
2161
|
+
open: typeof props.opened === "boolean" ? props.opened : state.open
|
|
2162
|
+
};
|
|
2163
|
+
}
|
|
2910
2164
|
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
}, {
|
|
2917
|
-
key: "getMenuItems",
|
|
2918
|
-
value: function getMenuItems(children) {
|
|
2919
|
-
var isFilterable = this.props.isFilterable; // If it's not filterable, no need to do any extra besides mapping the
|
|
2920
|
-
// option items to dropdown items.
|
|
2165
|
+
filterChildren(children) {
|
|
2166
|
+
const {
|
|
2167
|
+
searchText
|
|
2168
|
+
} = this.state;
|
|
2169
|
+
const lowercasedSearchText = searchText.toLowerCase(); // Filter the children with the searchText if any.
|
|
2921
2170
|
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
value: function getSearchField() {
|
|
2927
|
-
if (!this.props.isFilterable) {
|
|
2928
|
-
return null;
|
|
2929
|
-
}
|
|
2171
|
+
return children.filter(({
|
|
2172
|
+
props
|
|
2173
|
+
}) => !searchText || props.label.toLowerCase().indexOf(lowercasedSearchText) > -1);
|
|
2174
|
+
}
|
|
2930
2175
|
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
};
|
|
2944
|
-
}
|
|
2945
|
-
}, {
|
|
2946
|
-
key: "renderOpener",
|
|
2947
|
-
value: function renderOpener(numItems) {
|
|
2948
|
-
var _this$props = this.props,
|
|
2949
|
-
children = _this$props.children,
|
|
2950
|
-
disabled = _this$props.disabled,
|
|
2951
|
-
id = _this$props.id,
|
|
2952
|
-
light = _this$props.light,
|
|
2953
|
-
opener = _this$props.opener,
|
|
2954
|
-
placeholder = _this$props.placeholder,
|
|
2955
|
-
selectedValue = _this$props.selectedValue,
|
|
2956
|
-
testId = _this$props.testId,
|
|
2957
|
-
alignment = _this$props.alignment,
|
|
2958
|
-
dropdownStyle = _this$props.dropdownStyle,
|
|
2959
|
-
isFilterable = _this$props.isFilterable,
|
|
2960
|
-
onChange = _this$props.onChange,
|
|
2961
|
-
onToggle = _this$props.onToggle,
|
|
2962
|
-
opened = _this$props.opened,
|
|
2963
|
-
style = _this$props.style,
|
|
2964
|
-
className = _this$props.className,
|
|
2965
|
-
sharedProps = _objectWithoutProperties(_this$props, ["children", "disabled", "id", "light", "opener", "placeholder", "selectedValue", "testId", "alignment", "dropdownStyle", "isFilterable", "onChange", "onToggle", "opened", "style", "className"]);
|
|
2966
|
-
|
|
2967
|
-
var selectedItem = Children.toArray(children).find(function (option) {
|
|
2968
|
-
return option.props.value === selectedValue;
|
|
2969
|
-
}); // If nothing is selected, or if the selectedValue doesn't match any
|
|
2970
|
-
// item in the menu, use the placeholder.
|
|
2971
|
-
|
|
2972
|
-
var menuText = selectedItem ? selectedItem.props.label : placeholder;
|
|
2973
|
-
var dropdownOpener = opener ? /*#__PURE__*/createElement(DropdownOpener, {
|
|
2974
|
-
onClick: this.handleClick,
|
|
2975
|
-
disabled: numItems === 0 || disabled,
|
|
2976
|
-
ref: this.handleOpenerRef,
|
|
2977
|
-
text: menuText
|
|
2978
|
-
}, opener) : /*#__PURE__*/createElement(SelectOpener, _extends({}, sharedProps, {
|
|
2979
|
-
disabled: numItems === 0 || disabled,
|
|
2980
|
-
id: id,
|
|
2981
|
-
isPlaceholder: !selectedItem,
|
|
2982
|
-
light: light,
|
|
2983
|
-
onOpenChanged: this.handleOpenChanged,
|
|
2984
|
-
open: this.state.open,
|
|
2985
|
-
ref: this.handleOpenerRef,
|
|
2986
|
-
testId: testId
|
|
2987
|
-
}), menuText);
|
|
2988
|
-
return dropdownOpener;
|
|
2989
|
-
}
|
|
2990
|
-
}, {
|
|
2991
|
-
key: "render",
|
|
2992
|
-
value: function render() {
|
|
2993
|
-
var _this$props2 = this.props,
|
|
2994
|
-
alignment = _this$props2.alignment,
|
|
2995
|
-
children = _this$props2.children,
|
|
2996
|
-
dropdownStyle = _this$props2.dropdownStyle,
|
|
2997
|
-
isFilterable = _this$props2.isFilterable,
|
|
2998
|
-
light = _this$props2.light,
|
|
2999
|
-
style = _this$props2.style,
|
|
3000
|
-
className = _this$props2.className;
|
|
3001
|
-
var searchText = this.state.searchText;
|
|
3002
|
-
var allChildren = Children.toArray(children).filter(Boolean);
|
|
3003
|
-
var filteredItems = this.getMenuItems(allChildren);
|
|
3004
|
-
var opener = this.renderOpener(allChildren.length);
|
|
3005
|
-
var searchField = this.getSearchField();
|
|
3006
|
-
var items = searchField ? [searchField].concat(_toConsumableArray(filteredItems)) : filteredItems;
|
|
3007
|
-
return /*#__PURE__*/createElement(DropdownCore$1, {
|
|
3008
|
-
role: "listbox",
|
|
3009
|
-
alignment: alignment,
|
|
3010
|
-
dropdownStyle: [isFilterable && filterableDropdownStyle, selectDropdownStyle, dropdownStyle],
|
|
3011
|
-
initialFocusedIndex: this.selectedIndex,
|
|
3012
|
-
items: items,
|
|
3013
|
-
light: light,
|
|
3014
|
-
onOpenChanged: this.handleOpenChanged,
|
|
3015
|
-
open: this.state.open,
|
|
3016
|
-
opener: opener,
|
|
3017
|
-
openerElement: this.state.openerElement,
|
|
3018
|
-
style: style,
|
|
3019
|
-
className: className,
|
|
3020
|
-
onSearchTextChanged: isFilterable ? this.handleSearchTextChanged : null,
|
|
3021
|
-
searchText: isFilterable ? searchText : ""
|
|
3022
|
-
});
|
|
3023
|
-
}
|
|
3024
|
-
}], [{
|
|
3025
|
-
key: "getDerivedStateFromProps",
|
|
3026
|
-
value: function getDerivedStateFromProps(props, state) {
|
|
3027
|
-
return {
|
|
3028
|
-
open: typeof props.opened === "boolean" ? props.opened : state.open
|
|
3029
|
-
};
|
|
2176
|
+
getMenuItems(children) {
|
|
2177
|
+
const {
|
|
2178
|
+
isFilterable
|
|
2179
|
+
} = this.props; // If it's not filterable, no need to do any extra besides mapping the
|
|
2180
|
+
// option items to dropdown items.
|
|
2181
|
+
|
|
2182
|
+
return this.mapOptionItemsToDropdownItems(isFilterable ? this.filterChildren(children) : children);
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
getSearchField() {
|
|
2186
|
+
if (!this.props.isFilterable) {
|
|
2187
|
+
return null;
|
|
3030
2188
|
}
|
|
3031
|
-
}]);
|
|
3032
2189
|
|
|
3033
|
-
|
|
3034
|
-
|
|
2190
|
+
return {
|
|
2191
|
+
component: /*#__PURE__*/createElement(SearchTextInput, {
|
|
2192
|
+
key: "search-text-input",
|
|
2193
|
+
onChange: this.handleSearchTextChanged,
|
|
2194
|
+
searchText: this.state.searchText,
|
|
2195
|
+
labels: {
|
|
2196
|
+
clearSearch: defaultLabels.clearSearch,
|
|
2197
|
+
filter: defaultLabels.filter
|
|
2198
|
+
}
|
|
2199
|
+
}),
|
|
2200
|
+
focusable: true,
|
|
2201
|
+
populatedProps: {}
|
|
2202
|
+
};
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
renderOpener(numItems) {
|
|
2206
|
+
const _this$props = this.props,
|
|
2207
|
+
{
|
|
2208
|
+
children,
|
|
2209
|
+
disabled,
|
|
2210
|
+
id,
|
|
2211
|
+
light,
|
|
2212
|
+
opener,
|
|
2213
|
+
placeholder,
|
|
2214
|
+
selectedValue,
|
|
2215
|
+
testId
|
|
2216
|
+
} = _this$props,
|
|
2217
|
+
sharedProps = _objectWithoutPropertiesLoose(_this$props, _excluded$5);
|
|
2218
|
+
|
|
2219
|
+
const selectedItem = Children.toArray(children).find(option => option.props.value === selectedValue); // If nothing is selected, or if the selectedValue doesn't match any
|
|
2220
|
+
// item in the menu, use the placeholder.
|
|
2221
|
+
|
|
2222
|
+
const menuText = selectedItem ? selectedItem.props.label : placeholder;
|
|
2223
|
+
const dropdownOpener = opener ? /*#__PURE__*/createElement(DropdownOpener, {
|
|
2224
|
+
onClick: this.handleClick,
|
|
2225
|
+
disabled: numItems === 0 || disabled,
|
|
2226
|
+
ref: this.handleOpenerRef,
|
|
2227
|
+
text: menuText
|
|
2228
|
+
}, opener) : /*#__PURE__*/createElement(SelectOpener, _extends({}, sharedProps, {
|
|
2229
|
+
disabled: numItems === 0 || disabled,
|
|
2230
|
+
id: id,
|
|
2231
|
+
isPlaceholder: !selectedItem,
|
|
2232
|
+
light: light,
|
|
2233
|
+
onOpenChanged: this.handleOpenChanged,
|
|
2234
|
+
open: this.state.open,
|
|
2235
|
+
ref: this.handleOpenerRef,
|
|
2236
|
+
testId: testId
|
|
2237
|
+
}), menuText);
|
|
2238
|
+
return dropdownOpener;
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
render() {
|
|
2242
|
+
const {
|
|
2243
|
+
alignment,
|
|
2244
|
+
children,
|
|
2245
|
+
dropdownStyle,
|
|
2246
|
+
isFilterable,
|
|
2247
|
+
light,
|
|
2248
|
+
style,
|
|
2249
|
+
className
|
|
2250
|
+
} = this.props;
|
|
2251
|
+
const {
|
|
2252
|
+
searchText
|
|
2253
|
+
} = this.state;
|
|
2254
|
+
const allChildren = Children.toArray(children).filter(Boolean);
|
|
2255
|
+
const filteredItems = this.getMenuItems(allChildren);
|
|
2256
|
+
const opener = this.renderOpener(allChildren.length);
|
|
2257
|
+
const searchField = this.getSearchField();
|
|
2258
|
+
const items = searchField ? [searchField].concat(filteredItems) : filteredItems;
|
|
2259
|
+
return /*#__PURE__*/createElement(DropdownCore$1, {
|
|
2260
|
+
role: "listbox",
|
|
2261
|
+
alignment: alignment,
|
|
2262
|
+
dropdownStyle: [isFilterable && filterableDropdownStyle, selectDropdownStyle, dropdownStyle],
|
|
2263
|
+
initialFocusedIndex: this.selectedIndex,
|
|
2264
|
+
items: items,
|
|
2265
|
+
light: light,
|
|
2266
|
+
onOpenChanged: this.handleOpenChanged,
|
|
2267
|
+
open: this.state.open,
|
|
2268
|
+
opener: opener,
|
|
2269
|
+
openerElement: this.state.openerElement,
|
|
2270
|
+
style: style,
|
|
2271
|
+
className: className,
|
|
2272
|
+
onSearchTextChanged: isFilterable ? this.handleSearchTextChanged : null,
|
|
2273
|
+
searchText: isFilterable ? searchText : ""
|
|
2274
|
+
});
|
|
2275
|
+
}
|
|
3035
2276
|
|
|
3036
|
-
|
|
2277
|
+
}
|
|
2278
|
+
SingleSelect.defaultProps = {
|
|
3037
2279
|
alignment: "left",
|
|
3038
2280
|
disabled: false,
|
|
3039
2281
|
light: false
|
|
3040
|
-
}
|
|
2282
|
+
};
|
|
2283
|
+
|
|
2284
|
+
const _excluded$6 = ["disabled", "id", "light", "opener", "testId", "alignment", "dropdownStyle", "implicitAllEnabled", "isFilterable", "labels", "onChange", "onToggle", "opened", "selectedValues", "shortcuts", "style", "className"];
|
|
3041
2285
|
|
|
3042
2286
|
/**
|
|
3043
2287
|
* A dropdown that consists of multiple selection items. This select allows
|
|
@@ -3047,107 +2291,100 @@ _defineProperty(SingleSelect, "defaultProps", {
|
|
|
3047
2291
|
* The multi select stays open until closed by the user. The onChange callback
|
|
3048
2292
|
* happens every time there is a change in the selection of the items.
|
|
3049
2293
|
*/
|
|
3050
|
-
|
|
3051
|
-
|
|
2294
|
+
class MultiSelect extends Component {
|
|
2295
|
+
constructor(props) {
|
|
2296
|
+
super(props);
|
|
3052
2297
|
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
function MultiSelect(props) {
|
|
3056
|
-
var _this;
|
|
3057
|
-
|
|
3058
|
-
_classCallCheck(this, MultiSelect);
|
|
3059
|
-
|
|
3060
|
-
_this = _super.call(this, props);
|
|
3061
|
-
|
|
3062
|
-
_defineProperty(_assertThisInitialized(_this), "labels", void 0);
|
|
3063
|
-
|
|
3064
|
-
_defineProperty(_assertThisInitialized(_this), "handleOpenChanged", function (opened) {
|
|
3065
|
-
_this.setState({
|
|
2298
|
+
this.handleOpenChanged = opened => {
|
|
2299
|
+
this.setState({
|
|
3066
2300
|
open: opened,
|
|
3067
2301
|
searchText: "",
|
|
3068
|
-
lastSelectedValues:
|
|
2302
|
+
lastSelectedValues: this.props.selectedValues
|
|
3069
2303
|
});
|
|
3070
2304
|
|
|
3071
|
-
if (
|
|
3072
|
-
|
|
2305
|
+
if (this.props.onToggle) {
|
|
2306
|
+
this.props.onToggle(opened);
|
|
3073
2307
|
}
|
|
3074
|
-
}
|
|
2308
|
+
};
|
|
3075
2309
|
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
2310
|
+
this.handleToggle = selectedValue => {
|
|
2311
|
+
const {
|
|
2312
|
+
onChange,
|
|
2313
|
+
selectedValues
|
|
2314
|
+
} = this.props;
|
|
3080
2315
|
|
|
3081
2316
|
if (selectedValues.includes(selectedValue)) {
|
|
3082
|
-
|
|
3083
|
-
|
|
2317
|
+
const index = selectedValues.indexOf(selectedValue);
|
|
2318
|
+
const updatedSelection = [].concat(selectedValues.slice(0, index), selectedValues.slice(index + 1));
|
|
3084
2319
|
onChange(updatedSelection);
|
|
3085
2320
|
} else {
|
|
3086
2321
|
// Item was newly selected
|
|
3087
|
-
onChange([].concat(
|
|
2322
|
+
onChange([].concat(selectedValues, [selectedValue]));
|
|
3088
2323
|
}
|
|
3089
|
-
}
|
|
2324
|
+
};
|
|
3090
2325
|
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
});
|
|
2326
|
+
this.handleSelectAll = () => {
|
|
2327
|
+
const {
|
|
2328
|
+
children,
|
|
2329
|
+
onChange
|
|
2330
|
+
} = this.props;
|
|
2331
|
+
const selected = Children.toArray(children).filter(Boolean).map(option => option.props.value);
|
|
3098
2332
|
onChange(selected);
|
|
3099
|
-
}
|
|
2333
|
+
};
|
|
3100
2334
|
|
|
3101
|
-
|
|
3102
|
-
|
|
2335
|
+
this.handleSelectNone = () => {
|
|
2336
|
+
const {
|
|
2337
|
+
onChange
|
|
2338
|
+
} = this.props;
|
|
3103
2339
|
onChange([]);
|
|
3104
|
-
}
|
|
2340
|
+
};
|
|
3105
2341
|
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
2342
|
+
this.mapOptionItemToDropdownItem = option => {
|
|
2343
|
+
const {
|
|
2344
|
+
selectedValues
|
|
2345
|
+
} = this.props;
|
|
2346
|
+
const {
|
|
2347
|
+
disabled,
|
|
2348
|
+
value
|
|
2349
|
+
} = option.props;
|
|
3111
2350
|
return {
|
|
3112
2351
|
component: option,
|
|
3113
2352
|
focusable: !disabled,
|
|
3114
2353
|
populatedProps: {
|
|
3115
|
-
onToggle:
|
|
2354
|
+
onToggle: this.handleToggle,
|
|
3116
2355
|
selected: selectedValues.includes(value),
|
|
3117
2356
|
variant: "checkbox"
|
|
3118
2357
|
}
|
|
3119
2358
|
};
|
|
3120
|
-
}
|
|
3121
|
-
|
|
3122
|
-
_defineProperty(_assertThisInitialized(_this), "handleOpenerRef", function (node) {
|
|
3123
|
-
var openerElement = ReactDOM.findDOMNode(node);
|
|
2359
|
+
};
|
|
3124
2360
|
|
|
3125
|
-
|
|
3126
|
-
|
|
2361
|
+
this.handleOpenerRef = node => {
|
|
2362
|
+
const openerElement = ReactDOM.findDOMNode(node);
|
|
2363
|
+
this.setState({
|
|
2364
|
+
openerElement
|
|
3127
2365
|
});
|
|
3128
|
-
}
|
|
2366
|
+
};
|
|
3129
2367
|
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
searchText
|
|
2368
|
+
this.handleSearchTextChanged = searchText => {
|
|
2369
|
+
this.setState({
|
|
2370
|
+
searchText
|
|
3133
2371
|
});
|
|
3134
|
-
}
|
|
2372
|
+
};
|
|
3135
2373
|
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
}
|
|
2374
|
+
this.handleClick = e => {
|
|
2375
|
+
this.handleOpenChanged(!this.state.open);
|
|
2376
|
+
};
|
|
3139
2377
|
|
|
3140
|
-
|
|
2378
|
+
this.state = {
|
|
3141
2379
|
open: false,
|
|
3142
2380
|
searchText: "",
|
|
3143
2381
|
lastSelectedValues: [],
|
|
3144
2382
|
// merge custom labels with the default ones
|
|
3145
|
-
labels:
|
|
2383
|
+
labels: _extends({}, defaultLabels, props.labels),
|
|
3146
2384
|
openerElement: null
|
|
3147
2385
|
}; // merge custom labels with the default ones
|
|
3148
2386
|
|
|
3149
|
-
|
|
3150
|
-
return _this;
|
|
2387
|
+
this.labels = _extends({}, defaultLabels, props.labels);
|
|
3151
2388
|
}
|
|
3152
2389
|
/**
|
|
3153
2390
|
* Used to sync the `opened` state when this component acts as a controlled
|
|
@@ -3155,274 +2392,252 @@ var MultiSelect = /*#__PURE__*/function (_React$Component) {
|
|
|
3155
2392
|
*/
|
|
3156
2393
|
|
|
3157
2394
|
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
2395
|
+
static getDerivedStateFromProps(props, state) {
|
|
2396
|
+
return {
|
|
2397
|
+
open: typeof props.opened === "boolean" ? props.opened : state.open
|
|
2398
|
+
};
|
|
2399
|
+
}
|
|
2400
|
+
|
|
2401
|
+
componentDidUpdate(prevProps) {
|
|
2402
|
+
if (this.props.labels !== prevProps.labels) {
|
|
2403
|
+
// eslint-disable-next-line react/no-did-update-set-state
|
|
2404
|
+
this.setState({
|
|
2405
|
+
labels: _extends({}, this.state.labels, this.props.labels)
|
|
2406
|
+
});
|
|
3167
2407
|
}
|
|
3168
|
-
}
|
|
3169
|
-
key: "getMenuText",
|
|
3170
|
-
value: function getMenuText(children) {
|
|
3171
|
-
var _this$props3 = this.props,
|
|
3172
|
-
implicitAllEnabled = _this$props3.implicitAllEnabled,
|
|
3173
|
-
selectedValues = _this$props3.selectedValues;
|
|
3174
|
-
var _this$state$labels = this.state.labels,
|
|
3175
|
-
noneSelected = _this$state$labels.noneSelected,
|
|
3176
|
-
someSelected = _this$state$labels.someSelected,
|
|
3177
|
-
allSelected = _this$state$labels.allSelected; // When implicit all enabled, use `labels.allSelected` when no selection
|
|
3178
|
-
// otherwise, use the `labels.noneSelected` value
|
|
3179
|
-
|
|
3180
|
-
var noSelectionText = implicitAllEnabled ? allSelected : noneSelected;
|
|
3181
|
-
|
|
3182
|
-
switch (selectedValues.length) {
|
|
3183
|
-
case 0:
|
|
3184
|
-
return noSelectionText;
|
|
3185
|
-
|
|
3186
|
-
case 1:
|
|
3187
|
-
// If there is one item selected, we display its label. If for
|
|
3188
|
-
// some reason we can't find the selected item, we use the
|
|
3189
|
-
// display text for the case where nothing is selected.
|
|
3190
|
-
var selectedItem = children.find(function (option) {
|
|
3191
|
-
return option.props.value === selectedValues[0];
|
|
3192
|
-
});
|
|
3193
|
-
return selectedItem ? selectedItem.props.label : noSelectionText;
|
|
2408
|
+
}
|
|
3194
2409
|
|
|
3195
|
-
|
|
3196
|
-
|
|
2410
|
+
getMenuText(children) {
|
|
2411
|
+
const {
|
|
2412
|
+
implicitAllEnabled,
|
|
2413
|
+
selectedValues
|
|
2414
|
+
} = this.props;
|
|
2415
|
+
const {
|
|
2416
|
+
noneSelected,
|
|
2417
|
+
someSelected,
|
|
2418
|
+
allSelected
|
|
2419
|
+
} = this.state.labels; // When implicit all enabled, use `labels.allSelected` when no selection
|
|
2420
|
+
// otherwise, use the `labels.noneSelected` value
|
|
2421
|
+
|
|
2422
|
+
const noSelectionText = implicitAllEnabled ? allSelected : noneSelected;
|
|
2423
|
+
|
|
2424
|
+
switch (selectedValues.length) {
|
|
2425
|
+
case 0:
|
|
2426
|
+
return noSelectionText;
|
|
2427
|
+
|
|
2428
|
+
case 1:
|
|
2429
|
+
// If there is one item selected, we display its label. If for
|
|
2430
|
+
// some reason we can't find the selected item, we use the
|
|
2431
|
+
// display text for the case where nothing is selected.
|
|
2432
|
+
const selectedItem = children.find(option => option.props.value === selectedValues[0]);
|
|
2433
|
+
return selectedItem ? selectedItem.props.label : noSelectionText;
|
|
2434
|
+
|
|
2435
|
+
case children.length:
|
|
2436
|
+
return allSelected;
|
|
2437
|
+
|
|
2438
|
+
default:
|
|
2439
|
+
return someSelected(selectedValues.length);
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
3197
2442
|
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
2443
|
+
getSearchField() {
|
|
2444
|
+
if (!this.props.isFilterable) {
|
|
2445
|
+
return [];
|
|
3201
2446
|
}
|
|
3202
|
-
}, {
|
|
3203
|
-
key: "getSearchField",
|
|
3204
|
-
value: function getSearchField() {
|
|
3205
|
-
if (!this.props.isFilterable) {
|
|
3206
|
-
return [];
|
|
3207
|
-
}
|
|
3208
2447
|
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
2448
|
+
const {
|
|
2449
|
+
clearSearch,
|
|
2450
|
+
filter
|
|
2451
|
+
} = this.state.labels;
|
|
2452
|
+
return [{
|
|
2453
|
+
component: /*#__PURE__*/createElement(SearchTextInput, {
|
|
2454
|
+
key: "search-text-input",
|
|
2455
|
+
onChange: this.handleSearchTextChanged,
|
|
2456
|
+
searchText: this.state.searchText,
|
|
2457
|
+
labels: {
|
|
2458
|
+
clearSearch,
|
|
2459
|
+
filter
|
|
2460
|
+
}
|
|
2461
|
+
}),
|
|
2462
|
+
focusable: true,
|
|
2463
|
+
populatedProps: {}
|
|
2464
|
+
}];
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
getShortcuts(numOptions) {
|
|
2468
|
+
const {
|
|
2469
|
+
selectedValues,
|
|
2470
|
+
shortcuts
|
|
2471
|
+
} = this.props;
|
|
2472
|
+
const {
|
|
2473
|
+
selectAllLabel,
|
|
2474
|
+
selectNoneLabel
|
|
2475
|
+
} = this.state.labels; // When there's search text input to filter, shortcuts should be hidden
|
|
2476
|
+
|
|
2477
|
+
if (shortcuts && !this.state.searchText) {
|
|
2478
|
+
const selectAllDisabled = numOptions === selectedValues.length;
|
|
2479
|
+
const selectAll = {
|
|
2480
|
+
component: /*#__PURE__*/createElement(ActionItem, {
|
|
2481
|
+
disabled: selectAllDisabled,
|
|
2482
|
+
label: selectAllLabel(numOptions),
|
|
2483
|
+
indent: true,
|
|
2484
|
+
onClick: this.handleSelectAll
|
|
3221
2485
|
}),
|
|
3222
|
-
focusable:
|
|
2486
|
+
focusable: !selectAllDisabled,
|
|
3223
2487
|
populatedProps: {}
|
|
3224
|
-
}
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
populatedProps: {}
|
|
3247
|
-
};
|
|
3248
|
-
var selectNoneDisabled = selectedValues.length === 0;
|
|
3249
|
-
var selectNone = {
|
|
3250
|
-
component: /*#__PURE__*/createElement(ActionItem, {
|
|
3251
|
-
disabled: selectNoneDisabled,
|
|
3252
|
-
label: selectNoneLabel,
|
|
3253
|
-
indent: true,
|
|
3254
|
-
onClick: this.handleSelectNone
|
|
3255
|
-
}),
|
|
3256
|
-
focusable: !selectNoneDisabled,
|
|
3257
|
-
populatedProps: {}
|
|
3258
|
-
};
|
|
3259
|
-
var separator = {
|
|
3260
|
-
component: /*#__PURE__*/createElement(SeparatorItem, {
|
|
3261
|
-
key: "shortcuts-separator"
|
|
3262
|
-
}),
|
|
3263
|
-
focusable: false,
|
|
3264
|
-
populatedProps: {}
|
|
3265
|
-
};
|
|
3266
|
-
return [selectAll, selectNone, separator];
|
|
3267
|
-
} else {
|
|
3268
|
-
return [];
|
|
3269
|
-
}
|
|
2488
|
+
};
|
|
2489
|
+
const selectNoneDisabled = selectedValues.length === 0;
|
|
2490
|
+
const selectNone = {
|
|
2491
|
+
component: /*#__PURE__*/createElement(ActionItem, {
|
|
2492
|
+
disabled: selectNoneDisabled,
|
|
2493
|
+
label: selectNoneLabel,
|
|
2494
|
+
indent: true,
|
|
2495
|
+
onClick: this.handleSelectNone
|
|
2496
|
+
}),
|
|
2497
|
+
focusable: !selectNoneDisabled,
|
|
2498
|
+
populatedProps: {}
|
|
2499
|
+
};
|
|
2500
|
+
const separator = {
|
|
2501
|
+
component: /*#__PURE__*/createElement(SeparatorItem, {
|
|
2502
|
+
key: "shortcuts-separator"
|
|
2503
|
+
}),
|
|
2504
|
+
focusable: false,
|
|
2505
|
+
populatedProps: {}
|
|
2506
|
+
};
|
|
2507
|
+
return [selectAll, selectNone, separator];
|
|
2508
|
+
} else {
|
|
2509
|
+
return [];
|
|
3270
2510
|
}
|
|
3271
|
-
}
|
|
3272
|
-
key: "getMenuItems",
|
|
3273
|
-
value: function getMenuItems(children) {
|
|
3274
|
-
var isFilterable = this.props.isFilterable; // If it's not filterable, no need to do any extra besides mapping the
|
|
3275
|
-
// option items to dropdown items.
|
|
3276
|
-
|
|
3277
|
-
if (!isFilterable) {
|
|
3278
|
-
return children.map(this.mapOptionItemToDropdownItem);
|
|
3279
|
-
}
|
|
2511
|
+
}
|
|
3280
2512
|
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
2513
|
+
getMenuItems(children) {
|
|
2514
|
+
const {
|
|
2515
|
+
isFilterable
|
|
2516
|
+
} = this.props; // If it's not filterable, no need to do any extra besides mapping the
|
|
2517
|
+
// option items to dropdown items.
|
|
3285
2518
|
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
});
|
|
3290
|
-
var lastSelectedChildren = [];
|
|
3291
|
-
var restOfTheChildren = [];
|
|
2519
|
+
if (!isFilterable) {
|
|
2520
|
+
return children.map(this.mapOptionItemToDropdownItem);
|
|
2521
|
+
}
|
|
3292
2522
|
|
|
3293
|
-
|
|
3294
|
-
|
|
2523
|
+
const {
|
|
2524
|
+
searchText,
|
|
2525
|
+
lastSelectedValues
|
|
2526
|
+
} = this.state;
|
|
2527
|
+
const lowercasedSearchText = searchText.toLowerCase(); // Filter the children with the searchText if any.
|
|
3295
2528
|
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
2529
|
+
const filteredChildren = children.filter(({
|
|
2530
|
+
props
|
|
2531
|
+
}) => !searchText || props.label.toLowerCase().indexOf(lowercasedSearchText) > -1);
|
|
2532
|
+
const lastSelectedChildren = [];
|
|
2533
|
+
const restOfTheChildren = [];
|
|
3299
2534
|
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
}
|
|
3306
|
-
} catch (err) {
|
|
3307
|
-
_iterator.e(err);
|
|
3308
|
-
} finally {
|
|
3309
|
-
_iterator.f();
|
|
2535
|
+
for (const child of filteredChildren) {
|
|
2536
|
+
if (lastSelectedValues.includes(child.props.value)) {
|
|
2537
|
+
lastSelectedChildren.push(child);
|
|
2538
|
+
} else {
|
|
2539
|
+
restOfTheChildren.push(child);
|
|
3310
2540
|
}
|
|
2541
|
+
}
|
|
3311
2542
|
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
if (lastSelectedChildren.length && restOfTheChildren.length) {
|
|
3316
|
-
lastSelectedItems.push({
|
|
3317
|
-
component: /*#__PURE__*/createElement(SeparatorItem, {
|
|
3318
|
-
key: "selected-separator"
|
|
3319
|
-
}),
|
|
3320
|
-
focusable: false,
|
|
3321
|
-
populatedProps: {}
|
|
3322
|
-
});
|
|
3323
|
-
}
|
|
2543
|
+
const lastSelectedItems = lastSelectedChildren.map(this.mapOptionItemToDropdownItem); // We want to add SeparatorItem in between last selected items and the
|
|
2544
|
+
// rest of the items only when both of them exists.
|
|
3324
2545
|
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
id = _this$props5.id,
|
|
3333
|
-
light = _this$props5.light,
|
|
3334
|
-
opener = _this$props5.opener,
|
|
3335
|
-
testId = _this$props5.testId,
|
|
3336
|
-
alignment = _this$props5.alignment,
|
|
3337
|
-
dropdownStyle = _this$props5.dropdownStyle,
|
|
3338
|
-
implicitAllEnabled = _this$props5.implicitAllEnabled,
|
|
3339
|
-
isFilterable = _this$props5.isFilterable,
|
|
3340
|
-
labels = _this$props5.labels,
|
|
3341
|
-
onChange = _this$props5.onChange,
|
|
3342
|
-
onToggle = _this$props5.onToggle,
|
|
3343
|
-
opened = _this$props5.opened,
|
|
3344
|
-
selectedValues = _this$props5.selectedValues,
|
|
3345
|
-
shortcuts = _this$props5.shortcuts,
|
|
3346
|
-
style = _this$props5.style,
|
|
3347
|
-
className = _this$props5.className,
|
|
3348
|
-
sharedProps = _objectWithoutProperties(_this$props5, ["disabled", "id", "light", "opener", "testId", "alignment", "dropdownStyle", "implicitAllEnabled", "isFilterable", "labels", "onChange", "onToggle", "opened", "selectedValues", "shortcuts", "style", "className"]);
|
|
3349
|
-
|
|
3350
|
-
var noneSelected = this.state.labels.noneSelected;
|
|
3351
|
-
var menuText = this.getMenuText(allChildren);
|
|
3352
|
-
var numOptions = allChildren.length;
|
|
3353
|
-
var dropdownOpener = opener ? /*#__PURE__*/createElement(DropdownOpener, {
|
|
3354
|
-
onClick: this.handleClick,
|
|
3355
|
-
disabled: numOptions === 0 || disabled,
|
|
3356
|
-
ref: this.handleOpenerRef,
|
|
3357
|
-
text: menuText
|
|
3358
|
-
}, opener) : /*#__PURE__*/createElement(SelectOpener, _extends({}, sharedProps, {
|
|
3359
|
-
disabled: numOptions === 0 || disabled,
|
|
3360
|
-
id: id,
|
|
3361
|
-
isPlaceholder: menuText === noneSelected,
|
|
3362
|
-
light: light,
|
|
3363
|
-
onOpenChanged: this.handleOpenChanged,
|
|
3364
|
-
open: this.state.open,
|
|
3365
|
-
ref: this.handleOpenerRef,
|
|
3366
|
-
testId: testId
|
|
3367
|
-
}), menuText);
|
|
3368
|
-
return dropdownOpener;
|
|
3369
|
-
}
|
|
3370
|
-
}, {
|
|
3371
|
-
key: "render",
|
|
3372
|
-
value: function render() {
|
|
3373
|
-
var _this$props6 = this.props,
|
|
3374
|
-
alignment = _this$props6.alignment,
|
|
3375
|
-
light = _this$props6.light,
|
|
3376
|
-
style = _this$props6.style,
|
|
3377
|
-
className = _this$props6.className,
|
|
3378
|
-
dropdownStyle = _this$props6.dropdownStyle,
|
|
3379
|
-
children = _this$props6.children,
|
|
3380
|
-
isFilterable = _this$props6.isFilterable;
|
|
3381
|
-
var _this$state2 = this.state,
|
|
3382
|
-
open = _this$state2.open,
|
|
3383
|
-
searchText = _this$state2.searchText;
|
|
3384
|
-
var noResults = this.state.labels.noResults;
|
|
3385
|
-
var allChildren = Children.toArray(children).filter(Boolean);
|
|
3386
|
-
var numOptions = allChildren.length;
|
|
3387
|
-
var filteredItems = this.getMenuItems(allChildren);
|
|
3388
|
-
var opener = this.renderOpener(allChildren);
|
|
3389
|
-
return /*#__PURE__*/createElement(DropdownCore$1, {
|
|
3390
|
-
role: "listbox",
|
|
3391
|
-
alignment: alignment,
|
|
3392
|
-
dropdownStyle: [isFilterable && filterableDropdownStyle, selectDropdownStyle, dropdownStyle],
|
|
3393
|
-
items: [].concat(_toConsumableArray(this.getSearchField()), _toConsumableArray(this.getShortcuts(numOptions)), _toConsumableArray(filteredItems)),
|
|
3394
|
-
light: light,
|
|
3395
|
-
onOpenChanged: this.handleOpenChanged,
|
|
3396
|
-
open: open,
|
|
3397
|
-
opener: opener,
|
|
3398
|
-
openerElement: this.state.openerElement,
|
|
3399
|
-
style: style,
|
|
3400
|
-
className: className,
|
|
3401
|
-
onSearchTextChanged: isFilterable ? this.handleSearchTextChanged : null,
|
|
3402
|
-
searchText: isFilterable ? searchText : "",
|
|
3403
|
-
labels: {
|
|
3404
|
-
noResults: noResults
|
|
3405
|
-
}
|
|
2546
|
+
if (lastSelectedChildren.length && restOfTheChildren.length) {
|
|
2547
|
+
lastSelectedItems.push({
|
|
2548
|
+
component: /*#__PURE__*/createElement(SeparatorItem, {
|
|
2549
|
+
key: "selected-separator"
|
|
2550
|
+
}),
|
|
2551
|
+
focusable: false,
|
|
2552
|
+
populatedProps: {}
|
|
3406
2553
|
});
|
|
3407
2554
|
}
|
|
3408
|
-
}], [{
|
|
3409
|
-
key: "getDerivedStateFromProps",
|
|
3410
|
-
value: function getDerivedStateFromProps(props, state) {
|
|
3411
|
-
return {
|
|
3412
|
-
open: typeof props.opened === "boolean" ? props.opened : state.open
|
|
3413
|
-
};
|
|
3414
|
-
}
|
|
3415
|
-
}]);
|
|
3416
2555
|
|
|
3417
|
-
|
|
3418
|
-
}
|
|
2556
|
+
return [].concat(lastSelectedItems, restOfTheChildren.map(this.mapOptionItemToDropdownItem));
|
|
2557
|
+
}
|
|
2558
|
+
|
|
2559
|
+
renderOpener(allChildren) {
|
|
2560
|
+
const _this$props = this.props,
|
|
2561
|
+
{
|
|
2562
|
+
disabled,
|
|
2563
|
+
id,
|
|
2564
|
+
light,
|
|
2565
|
+
opener,
|
|
2566
|
+
testId
|
|
2567
|
+
} = _this$props,
|
|
2568
|
+
sharedProps = _objectWithoutPropertiesLoose(_this$props, _excluded$6);
|
|
2569
|
+
|
|
2570
|
+
const {
|
|
2571
|
+
noneSelected
|
|
2572
|
+
} = this.state.labels;
|
|
2573
|
+
const menuText = this.getMenuText(allChildren);
|
|
2574
|
+
const numOptions = allChildren.length;
|
|
2575
|
+
const dropdownOpener = opener ? /*#__PURE__*/createElement(DropdownOpener, {
|
|
2576
|
+
onClick: this.handleClick,
|
|
2577
|
+
disabled: numOptions === 0 || disabled,
|
|
2578
|
+
ref: this.handleOpenerRef,
|
|
2579
|
+
text: menuText
|
|
2580
|
+
}, opener) : /*#__PURE__*/createElement(SelectOpener, _extends({}, sharedProps, {
|
|
2581
|
+
disabled: numOptions === 0 || disabled,
|
|
2582
|
+
id: id,
|
|
2583
|
+
isPlaceholder: menuText === noneSelected,
|
|
2584
|
+
light: light,
|
|
2585
|
+
onOpenChanged: this.handleOpenChanged,
|
|
2586
|
+
open: this.state.open,
|
|
2587
|
+
ref: this.handleOpenerRef,
|
|
2588
|
+
testId: testId
|
|
2589
|
+
}), menuText);
|
|
2590
|
+
return dropdownOpener;
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2593
|
+
render() {
|
|
2594
|
+
const {
|
|
2595
|
+
alignment,
|
|
2596
|
+
light,
|
|
2597
|
+
style,
|
|
2598
|
+
className,
|
|
2599
|
+
dropdownStyle,
|
|
2600
|
+
children,
|
|
2601
|
+
isFilterable
|
|
2602
|
+
} = this.props;
|
|
2603
|
+
const {
|
|
2604
|
+
open,
|
|
2605
|
+
searchText
|
|
2606
|
+
} = this.state;
|
|
2607
|
+
const {
|
|
2608
|
+
noResults
|
|
2609
|
+
} = this.state.labels;
|
|
2610
|
+
const allChildren = Children.toArray(children).filter(Boolean);
|
|
2611
|
+
const numOptions = allChildren.length;
|
|
2612
|
+
const filteredItems = this.getMenuItems(allChildren);
|
|
2613
|
+
const opener = this.renderOpener(allChildren);
|
|
2614
|
+
return /*#__PURE__*/createElement(DropdownCore$1, {
|
|
2615
|
+
role: "listbox",
|
|
2616
|
+
alignment: alignment,
|
|
2617
|
+
dropdownStyle: [isFilterable && filterableDropdownStyle, selectDropdownStyle, dropdownStyle],
|
|
2618
|
+
items: [].concat(this.getSearchField(), this.getShortcuts(numOptions), filteredItems),
|
|
2619
|
+
light: light,
|
|
2620
|
+
onOpenChanged: this.handleOpenChanged,
|
|
2621
|
+
open: open,
|
|
2622
|
+
opener: opener,
|
|
2623
|
+
openerElement: this.state.openerElement,
|
|
2624
|
+
style: style,
|
|
2625
|
+
className: className,
|
|
2626
|
+
onSearchTextChanged: isFilterable ? this.handleSearchTextChanged : null,
|
|
2627
|
+
searchText: isFilterable ? searchText : "",
|
|
2628
|
+
labels: {
|
|
2629
|
+
noResults
|
|
2630
|
+
}
|
|
2631
|
+
});
|
|
2632
|
+
}
|
|
3419
2633
|
|
|
3420
|
-
|
|
2634
|
+
}
|
|
2635
|
+
MultiSelect.defaultProps = {
|
|
3421
2636
|
alignment: "left",
|
|
3422
2637
|
disabled: false,
|
|
3423
2638
|
light: false,
|
|
3424
2639
|
shortcuts: false,
|
|
3425
2640
|
selectedValues: []
|
|
3426
|
-
}
|
|
2641
|
+
};
|
|
3427
2642
|
|
|
3428
2643
|
export { ActionItem, ActionMenu, MultiSelect, OptionItem, SeparatorItem, SingleSelect };
|