UNPKG

44.7 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.isInteractive = isInteractive;
7exports.default = void 0;
8
9var React = _interopRequireWildcard(require("react"));
10
11var _overrides = require("../helpers/overrides.js");
12
13var _deleteAlt = _interopRequireDefault(require("../icon/delete-alt.js"));
14
15var _triangleDown = _interopRequireDefault(require("../icon/triangle-down.js"));
16
17var _search = _interopRequireDefault(require("../icon/search.js"));
18
19var _index = require("../locale/index.js");
20
21var _index2 = require("../popover/index.js");
22
23var _index3 = require("../spinner/index.js");
24
25var _getBuiId = _interopRequireDefault(require("../utils/get-bui-id.js"));
26
27var _autosizeInput = _interopRequireDefault(require("./autosize-input.js"));
28
29var _constants = require("./constants.js");
30
31var _defaultProps = _interopRequireDefault(require("./default-props.js"));
32
33var _dropdown = _interopRequireDefault(require("./dropdown.js"));
34
35var _styledComponents = require("./styled-components.js");
36
37var _index4 = require("./utils/index.js");
38
39function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
40
41function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
42
43function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
44
45function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
46
47function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
48
49function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
50
51function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
52
53function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
54
55function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
56
57function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
58
59function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
60
61function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
62
63function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
64
65function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
66
67function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
68
69function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
70
71function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
72
73function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
74
75function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
76
77function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
78
79function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
80
81function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
82
83function Noop() {
84 return null;
85}
86
87var isClick = function isClick(event) {
88 return event.type === 'click';
89};
90
91var isLeftClick = function isLeftClick(event) {
92 return event.button !== null && event.button !== undefined && event.button === 0;
93};
94
95var containsNode = function containsNode(parent, child) {
96 if (typeof document !== 'undefined') {
97 // eslint-disable-next-line flowtype/no-weak-types
98 return child && parent && parent.contains(child);
99 }
100};
101
102function isInteractive(rootTarget, rootElement) {
103 if (rootTarget instanceof Element) {
104 var target = rootTarget;
105
106 while (target && target !== rootElement) {
107 var role = target.getAttribute('role');
108
109 if (role === 'button' || role === 'link') {
110 return true;
111 }
112
113 if (target.tagName) target = target.parentElement;
114 }
115 }
116
117 return false;
118} // eslint-disable-next-line flowtype/no-weak-types
119
120
121var Select =
122/*#__PURE__*/
123function (_React$Component) {
124 _inherits(Select, _React$Component);
125
126 // anchor is a ref that refers to the outermost element rendered when the dropdown menu is not
127 // open. This is required so that we can check if clicks are on/off the anchor element.
128 // dropdown is a ref that refers to the popover element. This is required so that we can check if
129 // clicks are on/off the dropdown element.
130 // dragging is a flag to track whether a mobile device is currently scrolling versus clicking.
131 // focusAfterClear is a flag to indicate that the dropdowm menu should open after a selected
132 // option has been cleared.
133 // openAfterFocus is a flag to indicate that the dropdown menu should open when the component is
134 // focused. Developers have the option to disable initial clicks opening the dropdown menu. If not
135 // disabled, clicks will set this flag to true. Upon focusing, look to this to see if the menu should
136 // be opened, or only focus.
137 // When an item is selected, it also triggers handleClickOutside and since the selected item is
138 // already out of the menu (DOM), it will not recognize it as a subnode and triggers handleBlur
139 // that sets isOpen to false. That's a faulty logic causing visible problems when
140 // closeOnSelect is false. This flag helps to detect that selection was just made.
141 // the select components can accept an array of options or an object where properties are optgroups
142 // and values are arrays of options. this class property is constructed and updated in a normalized
143 // shape where optgroup titles are stored on the option in the __optgroup field.
144 // id generated for the listbox. used by screenreaders to associate the input with the menu it controls
145 function Select(props) {
146 var _this;
147
148 _classCallCheck(this, Select);
149
150 _this = _possibleConstructorReturn(this, _getPrototypeOf(Select).call(this, props));
151
152 _defineProperty(_assertThisInitialized(_this), "anchor", React.createRef());
153
154 _defineProperty(_assertThisInitialized(_this), "dropdown", React.createRef());
155
156 _defineProperty(_assertThisInitialized(_this), "input", void 0);
157
158 _defineProperty(_assertThisInitialized(_this), "dragging", void 0);
159
160 _defineProperty(_assertThisInitialized(_this), "focusAfterClear", void 0);
161
162 _defineProperty(_assertThisInitialized(_this), "openAfterFocus", void 0);
163
164 _defineProperty(_assertThisInitialized(_this), "justSelected", void 0);
165
166 _defineProperty(_assertThisInitialized(_this), "options", []);
167
168 _defineProperty(_assertThisInitialized(_this), "listboxId", (0, _getBuiId.default)());
169
170 _defineProperty(_assertThisInitialized(_this), "state", {
171 activeDescendant: null,
172 inputValue: '',
173 isFocused: false,
174 isOpen: _this.props.startOpen,
175 isPseudoFocused: false
176 });
177
178 _defineProperty(_assertThisInitialized(_this), "isMounted", false);
179
180 _defineProperty(_assertThisInitialized(_this), "handleTouchOutside", function (event) {
181 if (containsNode(_this.dropdown.current, event.target)) return;
182
183 if (!containsNode(_this.anchor.current, event.target)) {
184 _this.closeMenu();
185 }
186 });
187
188 _defineProperty(_assertThisInitialized(_this), "handleTouchMove", function () {
189 return _this.dragging = true;
190 });
191
192 _defineProperty(_assertThisInitialized(_this), "handleTouchStart", function () {
193 return _this.dragging = false;
194 });
195
196 _defineProperty(_assertThisInitialized(_this), "handleTouchEnd", function (event) {
197 if (_this.dragging) return;
198
199 _this.handleClick(event);
200 });
201
202 _defineProperty(_assertThisInitialized(_this), "handleTouchEndClearValue", function (event) {
203 if (_this.dragging) return;
204
205 _this.clearValue(event);
206 });
207
208 _defineProperty(_assertThisInitialized(_this), "handleClick", function (event) {
209 if (_this.props.disabled || !isClick(event) && !isLeftClick(event)) {
210 return;
211 } // Case comes up when text has been typed into the input field. If no text provided,
212 // the 'input' element will have essentially 0 width therefore will not be clickable.
213 // When click outside does not reset input, text provided will stay rendered after clicks away
214 // from the select component. Upon subsequent clicks on the provided text, open the dropdown
215 // menu, in addition to text edit operations.
216
217
218 if (event.target === _this.input) {
219 // CHASE: not sure why this condition is here. I cannot replicate a situation where clicks
220 // on provided text break into here.
221 if (!_this.state.isFocused) {
222 _this.openAfterFocus = _this.props.openOnClick;
223
224 _this.focus();
225
226 return;
227 }
228
229 if (!_this.state.isOpen) {
230 _this.setState({
231 isOpen: true,
232 isPseudoFocused: false
233 });
234
235 return;
236 }
237 } // Ensures that interactive elements within the Select component do not trigger the outer click
238 // handler. For example, after an option is selected clicks on the 'clear' icon call here. We
239 // should ignore those events. This comes after case where click is on input element, so that
240 // those are handled on their own.
241
242
243 if (_this.input && isInteractive(event.target, _this.input)) {
244 return;
245 } // For the simple case where clicking on the Select does not allow for providing
246 // text input to filter the dropdown options.
247
248
249 if (!_this.props.searchable) {
250 _this.focus();
251
252 _this.setState(function (prev) {
253 return {
254 isOpen: !prev.isOpen
255 };
256 });
257
258 return;
259 } // Cases below only apply to searchable Select component.
260
261
262 if (_this.state.isFocused) {
263 // iOS ignores programmatic calls to input.focus() that were not triggered by a click event.
264 // This component can get into a state where isFocused is true, but the DOM node is not
265 // focused. Call focus here again to ensure.
266 _this.focus(); // Case comes up when click outside does not reset input - once text has been provided to
267 // the input, and the user closes the dropdown menu the provided text is maintained. After
268 // this, if the user focuses back into the select component then clicks on the component,
269 // the provided text highlights rather than position's the cursor at the end of the input.
270
271
272 if (_this.input) _this.input.value = '';
273
274 _this.setState(function (prev) {
275 return {
276 isOpen: !_this.focusAfterClear && !prev.isOpen,
277 isPseudoFocused: false
278 };
279 });
280
281 _this.focusAfterClear = false;
282 } else {
283 _this.openAfterFocus = _this.props.openOnClick;
284
285 _this.focus();
286 }
287 });
288
289 _defineProperty(_assertThisInitialized(_this), "handleInputFocus", function (event) {
290 if (_this.props.disabled) return;
291 if (_this.props.onFocus) _this.props.onFocus(event);
292 var toOpen = _this.state.isOpen || _this.openAfterFocus; // if focus happens after clear values, don't open dropdown yet.
293
294 toOpen = !_this.focusAfterClear && toOpen;
295
296 _this.setState({
297 isFocused: true,
298 isOpen: !!toOpen
299 });
300
301 _this.focusAfterClear = false;
302 _this.openAfterFocus = false;
303 });
304
305 _defineProperty(_assertThisInitialized(_this), "handleBlur", function (event) {
306 if (event.relatedTarget) {
307 if (containsNode(_this.anchor.current, event.relatedTarget) || containsNode(_this.dropdown.current, event.relatedTarget)) {
308 return;
309 }
310 } else {
311 if (containsNode(_this.anchor.current, event.target)) {
312 return;
313 }
314 }
315
316 if (_this.props.onBlur) {
317 _this.props.onBlur(event);
318 }
319
320 if (_this.isMounted) {
321 _this.setState({
322 isFocused: false,
323 isOpen: false,
324 isPseudoFocused: false,
325 inputValue: _this.props.onBlurResetsInput ? '' : _this.state.inputValue
326 });
327 }
328
329 if (typeof document !== 'undefined') {
330 document.removeEventListener('click', _this.handleClickOutside);
331 }
332 });
333
334 _defineProperty(_assertThisInitialized(_this), "handleClickOutside", function (event) {
335 if (_this.justSelected) {
336 _this.justSelected = false;
337 return;
338 }
339
340 if (containsNode(_this.dropdown.current, event.target)) return;
341 var isFocused = _this.state.isFocused || _this.state.isPseudoFocused;
342
343 if (isFocused && !containsNode(_this.anchor.current, event.target)) {
344 _this.handleBlur(event);
345 }
346 });
347
348 _defineProperty(_assertThisInitialized(_this), "handleInputChange", function (event) {
349 var newInputValue = event.target.value;
350
351 _this.setState({
352 inputValue: newInputValue,
353 isOpen: true,
354 isPseudoFocused: false
355 });
356
357 if (_this.props.onInputChange) {
358 _this.props.onInputChange(event);
359 }
360 });
361
362 _defineProperty(_assertThisInitialized(_this), "handleKeyDown", function (event) {
363 if (_this.props.disabled) return;
364
365 switch (event.keyCode) {
366 case 8:
367 // backspace
368 if (!_this.state.inputValue && _this.props.backspaceRemoves) {
369 event.preventDefault();
370
371 _this.backspaceValue();
372 }
373
374 break;
375
376 case 9:
377 // tab
378 _this.setState(function (prevState) {
379 return {
380 isPseudoFocused: false,
381 isFocused: false,
382 isOpen: false,
383 inputValue: !_this.props.onCloseResetsInput || !_this.props.onBlurResetsInput ? prevState.inputValue : ''
384 };
385 });
386
387 break;
388
389 case 27:
390 // escape
391 if (!_this.state.isOpen && _this.props.clearable && _this.props.escapeClearsValue) {
392 _this.clearValue(event);
393
394 _this.setState({
395 isFocused: false,
396 isPseudoFocused: false
397 });
398 }
399
400 break;
401
402 case 32:
403 // space
404 if (_this.props.searchable) {
405 break;
406 }
407
408 event.preventDefault();
409
410 if (!_this.state.isOpen) {
411 _this.setState({
412 isOpen: true
413 });
414 }
415
416 break;
417
418 case 38:
419 // up
420 event.preventDefault();
421
422 if (!_this.state.isOpen) {
423 _this.setState({
424 isOpen: true
425 });
426 }
427
428 break;
429
430 case 40:
431 // down
432 event.preventDefault();
433
434 if (!_this.state.isOpen) {
435 _this.setState({
436 isOpen: true
437 });
438 }
439
440 break;
441
442 case 33:
443 // page up
444 event.preventDefault();
445
446 if (!_this.state.isOpen) {
447 _this.setState({
448 isOpen: true
449 });
450 }
451
452 break;
453
454 case 34:
455 // page down
456 event.preventDefault();
457
458 if (!_this.state.isOpen) {
459 _this.setState({
460 isOpen: true
461 });
462 }
463
464 break;
465
466 case 35:
467 // end key
468 if (event.shiftKey) {
469 break;
470 }
471
472 event.preventDefault();
473
474 if (!_this.state.isOpen) {
475 _this.setState({
476 isOpen: true
477 });
478 }
479
480 break;
481
482 case 36:
483 // home key
484 if (event.shiftKey) {
485 break;
486 }
487
488 event.preventDefault();
489
490 if (!_this.state.isOpen) {
491 _this.setState({
492 isOpen: true
493 });
494 }
495
496 break;
497
498 case 46:
499 // delete
500 if (!_this.state.inputValue && _this.props.deleteRemoves) {
501 event.preventDefault();
502
503 _this.popValue();
504 }
505
506 break;
507 }
508 });
509
510 _defineProperty(_assertThisInitialized(_this), "getOptionLabel", function (locale, _ref) {
511 var option = _ref.option;
512 return option.isCreatable ? "".concat(locale.select.create, " \u201C").concat(option[_this.props.labelKey], "\u201D") : option[_this.props.labelKey];
513 });
514
515 _defineProperty(_assertThisInitialized(_this), "getValueLabel", function (_ref2) {
516 var option = _ref2.option;
517 return option[_this.props.labelKey];
518 });
519
520 _defineProperty(_assertThisInitialized(_this), "handleActiveDescendantChange", function (id) {
521 if (id) {
522 _this.setState({
523 activeDescendant: id
524 });
525 } else {
526 _this.setState({
527 activeDescendant: null
528 });
529 }
530 });
531
532 _defineProperty(_assertThisInitialized(_this), "handleInputRef", function (input) {
533 _this.input = input;
534
535 if (_this.props.controlRef) {
536 if (typeof _this.props.controlRef === 'function') {
537 _this.props.controlRef(input);
538 } else {
539 _this.props.controlRef.current = input;
540 }
541 }
542 });
543
544 _defineProperty(_assertThisInitialized(_this), "selectValue", function (_ref3) {
545 var item = _ref3.item;
546
547 if (item.disabled) {
548 return;
549 }
550
551 _this.justSelected = true; // NOTE: we add/set the value in a callback to make sure the
552 // input value is empty to avoid styling issues in Chrome
553
554 var updatedValue = _this.props.onSelectResetsInput ? '' : _this.state.inputValue;
555
556 if (_this.props.multi) {
557 _this.setState({
558 inputValue: updatedValue,
559 isOpen: !_this.props.closeOnSelect
560 }, function () {
561 var valueArray = _this.props.value;
562
563 if (valueArray.some(function (i) {
564 return i[_this.props.valueKey] === item[_this.props.valueKey];
565 })) {
566 _this.removeValue(item);
567 } else {
568 _this.addValue(item);
569 }
570 });
571 } else {
572 _this.focus();
573
574 _this.setState({
575 inputValue: updatedValue,
576 isOpen: !_this.props.closeOnSelect,
577 isFocused: true,
578 isPseudoFocused: false
579 }, function () {
580 _this.setValue([item], item, _constants.STATE_CHANGE_TYPE.select);
581 });
582 }
583 });
584
585 _defineProperty(_assertThisInitialized(_this), "addValue", function (item) {
586 var valueArray = _toConsumableArray(_this.props.value);
587
588 _this.setValue(valueArray.concat(item), item, _constants.STATE_CHANGE_TYPE.select);
589 });
590
591 _defineProperty(_assertThisInitialized(_this), "backspaceValue", function () {
592 var item = _this.popValue();
593
594 if (!item) {
595 return;
596 }
597
598 var valueLength = _this.props.value.length;
599 var renderLabel = _this.props.getValueLabel || _this.getValueLabel;
600 var labelForInput = renderLabel({
601 option: item,
602 index: valueLength - 1
603 }); // label might not be a string, it might be a Node of another kind.
604
605 if (!_this.props.backspaceClearsInputValue && typeof labelForInput === 'string') {
606 var remainingInput = labelForInput.slice(0, -1);
607
608 _this.setState({
609 inputValue: remainingInput,
610 isOpen: true
611 });
612 }
613 });
614
615 _defineProperty(_assertThisInitialized(_this), "popValue", function () {
616 var valueArray = _toConsumableArray(_this.props.value);
617
618 var valueLength = valueArray.length;
619 if (!valueLength) return;
620 if (valueArray[valueLength - 1].clearableValue === false) return;
621 var item = valueArray.pop();
622
623 _this.setValue(valueArray, item, _constants.STATE_CHANGE_TYPE.remove);
624
625 return item;
626 });
627
628 _defineProperty(_assertThisInitialized(_this), "removeValue", function (item) {
629 var valueArray = _toConsumableArray(_this.props.value);
630
631 _this.setValue(valueArray.filter(function (i) {
632 return i[_this.props.valueKey] !== item[_this.props.valueKey];
633 }), item, _constants.STATE_CHANGE_TYPE.remove);
634
635 _this.focus();
636 });
637
638 _defineProperty(_assertThisInitialized(_this), "clearValue", function (event) {
639 if (isClick(event) && !isLeftClick(event)) return;
640
641 if (_this.props.value) {
642 var resetValue = _this.props.value.filter(function (item) {
643 return item.clearableValue === false;
644 });
645
646 _this.setValue(resetValue, null, _constants.STATE_CHANGE_TYPE.clear);
647 }
648
649 _this.setState({
650 inputValue: '',
651 isOpen: false
652 });
653
654 _this.focus();
655
656 _this.focusAfterClear = true;
657 });
658
659 _defineProperty(_assertThisInitialized(_this), "shouldShowPlaceholder", function () {
660 return !(_this.state.inputValue || _this.props.value && _this.props.value.length);
661 });
662
663 _defineProperty(_assertThisInitialized(_this), "shouldShowValue", function () {
664 return !_this.state.inputValue;
665 });
666
667 _this.options = (0, _index4.normalizeOptions)(props.options);
668 return _this;
669 }
670
671 _createClass(Select, [{
672 key: "componentDidMount",
673 value: function componentDidMount() {
674 if (this.props.autoFocus) {
675 this.focus();
676 }
677
678 this.isMounted = true;
679 }
680 }, {
681 key: "componentDidUpdate",
682 value: function componentDidUpdate(prevProps, prevState) {
683 if (typeof document !== 'undefined') {
684 if (prevState.isOpen !== this.state.isOpen) {
685 if (this.state.isOpen) {
686 this.props.onOpen && this.props.onOpen();
687 document.addEventListener('touchstart', this.handleTouchOutside);
688 } else {
689 this.props.onClose && this.props.onClose();
690 document.removeEventListener('touchstart', this.handleTouchOutside);
691 }
692 }
693
694 if (!prevState.isFocused && this.state.isFocused) {
695 document.addEventListener('click', this.handleClickOutside);
696 }
697 }
698 }
699 }, {
700 key: "componentWillUnmount",
701 value: function componentWillUnmount() {
702 if (typeof document !== 'undefined') {
703 document.removeEventListener('touchstart', this.handleTouchOutside);
704 }
705
706 this.isMounted = false;
707 }
708 }, {
709 key: "focus",
710 value: function focus() {
711 if (!this.input) return;
712 this.input.focus();
713 } // Handle touch outside on mobile to dismiss menu, ensures that the
714 // touch target is not within the anchor DOM node.
715
716 }, {
717 key: "closeMenu",
718 value: function closeMenu() {
719 if (this.props.onCloseResetsInput) {
720 this.setState({
721 inputValue: '',
722 isOpen: false,
723 isPseudoFocused: this.state.isFocused && !this.props.multi
724 });
725 } else {
726 this.setState({
727 isOpen: false,
728 isPseudoFocused: this.state.isFocused && !this.props.multi
729 });
730 }
731 }
732 }, {
733 key: "getValueArray",
734
735 /**
736 * Extends the value into an array from the given options
737 */
738 value: function getValueArray(value) {
739 var _this2 = this;
740
741 if (!Array.isArray(value)) {
742 if (value === null || value === undefined) return [];
743 value = [value];
744 }
745
746 return value.map(function (value) {
747 return (0, _index4.expandValue)(value, _this2.props);
748 });
749 }
750 }, {
751 key: "setValue",
752 value: function setValue(value, option, type) {
753 if (this.props.onChange) {
754 this.props.onChange({
755 value: value,
756 option: option,
757 type: type
758 });
759 }
760 }
761 }, {
762 key: "renderLoading",
763 value: function renderLoading() {
764 if (!this.props.isLoading) return;
765 var sharedProps = this.getSharedProps();
766 var _this$props$overrides = this.props.overrides,
767 overrides = _this$props$overrides === void 0 ? {} : _this$props$overrides;
768
769 var _getOverrides = (0, _overrides.getOverrides)(overrides.LoadingIndicator, _index3.Spinner),
770 _getOverrides2 = _slicedToArray(_getOverrides, 2),
771 LoadingIndicator = _getOverrides2[0],
772 loadingIndicatorProps = _getOverrides2[1];
773
774 return React.createElement(LoadingIndicator, _extends({
775 size: 16,
776 overrides: {
777 Svg: {
778 style: _styledComponents.getLoadingIconStyles
779 }
780 },
781 $silenceV11DeprecationWarning: true
782 }, sharedProps, loadingIndicatorProps));
783 }
784 }, {
785 key: "renderValue",
786 value: function renderValue(valueArray, isOpen, locale) {
787 var _this3 = this;
788
789 var _this$props$overrides2 = this.props.overrides,
790 overrides = _this$props$overrides2 === void 0 ? {} : _this$props$overrides2;
791 var sharedProps = this.getSharedProps();
792 var renderLabel = this.props.getValueLabel || this.getValueLabel;
793 var Value = this.props.valueComponent || Noop;
794
795 if (!valueArray.length) {
796 return null;
797 }
798
799 if (this.props.multi) {
800 return valueArray.map(function (value, i) {
801 var disabled = sharedProps.$disabled || value.clearableValue === false;
802 return React.createElement(Value, _extends({
803 value: value,
804 key: "value-".concat(i, "-").concat(value[_this3.props.valueKey]),
805 removeValue: function removeValue() {
806 return _this3.removeValue(value);
807 },
808 disabled: disabled,
809 overrides: {
810 Tag: overrides.Tag,
811 MultiValue: overrides.MultiValue
812 }
813 }, sharedProps, {
814 $disabled: disabled
815 }), renderLabel({
816 option: value,
817 index: i
818 }));
819 });
820 } else if (this.shouldShowValue()) {
821 return React.createElement(Value, _extends({
822 value: valueArray[0][this.props.valueKey],
823 disabled: this.props.disabled,
824 overrides: {
825 SingleValue: overrides.SingleValue
826 }
827 }, sharedProps), renderLabel({
828 option: valueArray[0]
829 }));
830 }
831 }
832 }, {
833 key: "renderInput",
834 value: function renderInput() {
835 var _this4 = this;
836
837 var _this$props$overrides3 = this.props.overrides,
838 overrides = _this$props$overrides3 === void 0 ? {} : _this$props$overrides3;
839
840 var _getOverrides3 = (0, _overrides.getOverrides)(overrides.InputContainer, _styledComponents.StyledInputContainer),
841 _getOverrides4 = _slicedToArray(_getOverrides3, 2),
842 InputContainer = _getOverrides4[0],
843 inputContainerProps = _getOverrides4[1];
844
845 var sharedProps = this.getSharedProps();
846 var isOpen = this.state.isOpen;
847 var selected = this.getValueArray(this.props.value).map(function (v) {
848 return v[_this4.props.labelKey];
849 }).join(', ');
850 var selectedLabel = selected.length ? "Selected ".concat(selected, ". ") : '';
851 var label = "".concat(selectedLabel).concat(this.props['aria-label'] || '');
852
853 if (!this.props.searchable) {
854 return React.createElement(InputContainer, _extends({
855 "aria-activedescendant": this.state.activeDescendant,
856 "aria-expanded": isOpen,
857 "aria-disabled": this.props.disabled,
858 "aria-label": label,
859 "aria-labelledby": this.props['aria-labelledby'],
860 "aria-owns": this.state.isOpen ? this.listboxId : null,
861 "aria-required": this.props.required || null,
862 onFocus: this.handleInputFocus,
863 ref: this.handleInputRef,
864 tabIndex: 0
865 }, sharedProps, inputContainerProps));
866 }
867
868 return React.createElement(InputContainer, _extends({}, sharedProps, inputContainerProps), React.createElement(_autosizeInput.default, _extends({
869 "aria-activedescendant": this.state.activeDescendant,
870 "aria-autocomplete": "list",
871 "aria-controls": this.state.isOpen ? this.listboxId : null,
872 "aria-describedby": this.props['aria-describedby'],
873 "aria-errormessage": this.props['aria-errormessage'],
874 "aria-disabled": this.props.disabled || null,
875 "aria-expanded": isOpen,
876 "aria-haspopup": "listbox",
877 "aria-label": label,
878 "aria-labelledby": this.props['aria-labelledby'],
879 "aria-required": this.props.required || null,
880 disabled: this.props.disabled || null,
881 id: this.props.id || null,
882 inputRef: this.handleInputRef,
883 onChange: this.handleInputChange,
884 onFocus: this.handleInputFocus,
885 overrides: {
886 Input: overrides.Input
887 },
888 required: this.props.required && !this.props.value.length || null,
889 role: "combobox",
890 value: this.state.inputValue,
891 tabIndex: 0
892 }, sharedProps)));
893 }
894 }, {
895 key: "renderClear",
896 value: function renderClear() {
897 var isValueEntered = Boolean(this.props.value && this.props.value.length || this.state.inputValue);
898
899 if (!this.props.clearable || this.props.disabled || this.props.isLoading || !isValueEntered) {
900 return;
901 }
902
903 var sharedProps = this.getSharedProps();
904 var _this$props$overrides4 = this.props.overrides,
905 overrides = _this$props$overrides4 === void 0 ? {} : _this$props$overrides4;
906
907 var _getOverrides5 = (0, _overrides.getOverrides)(overrides.ClearIcon, _deleteAlt.default),
908 _getOverrides6 = _slicedToArray(_getOverrides5, 2),
909 ClearIcon = _getOverrides6[0],
910 clearIconProps = _getOverrides6[1];
911
912 var ariaLabel = this.props.multi ? 'Clear all' : 'Clear value';
913 return React.createElement(ClearIcon, _extends({
914 size: 16,
915 title: ariaLabel,
916 "aria-label": ariaLabel,
917 onClick: this.clearValue,
918 onTouchEnd: this.handleTouchEndClearValue,
919 onTouchMove: this.handleTouchMove,
920 onTouchStart: this.handleTouchStart,
921 role: "button",
922 overrides: {
923 Svg: {
924 component: _styledComponents.StyledClearIcon,
925 props: overrides.ClearIcon && overrides.ClearIcon.props ? overrides.ClearIcon.props : {},
926 style: overrides.ClearIcon && overrides.ClearIcon.style ? overrides.ClearIcon.style : {}
927 }
928 }
929 }, sharedProps, clearIconProps));
930 }
931 }, {
932 key: "renderArrow",
933 value: function renderArrow() {
934 if (this.props.type !== _constants.TYPE.select) {
935 return null;
936 }
937
938 var _this$props$overrides5 = this.props.overrides,
939 overrides = _this$props$overrides5 === void 0 ? {} : _this$props$overrides5;
940
941 var _getOverrides7 = (0, _overrides.getOverrides)(overrides.SelectArrow, _triangleDown.default),
942 _getOverrides8 = _slicedToArray(_getOverrides7, 2),
943 SelectArrow = _getOverrides8[0],
944 selectArrowProps = _getOverrides8[1];
945
946 var sharedProps = this.getSharedProps();
947 return React.createElement(SelectArrow, _extends({
948 size: 16,
949 title: 'open',
950 overrides: {
951 Svg: {
952 component: _styledComponents.StyledSelectArrow,
953 props: overrides.SelectArrow && overrides.SelectArrow.props ? overrides.SelectArrow.props : {},
954 style: overrides.SelectArrow && overrides.SelectArrow.style ? overrides.SelectArrow.style : {}
955 }
956 }
957 }, sharedProps, selectArrowProps));
958 }
959 }, {
960 key: "renderSearch",
961 value: function renderSearch() {
962 if (this.props.type !== _constants.TYPE.search) {
963 return null;
964 }
965
966 var _this$props$overrides6 = this.props.overrides,
967 overrides = _this$props$overrides6 === void 0 ? {} : _this$props$overrides6;
968
969 var _getOverrides9 = (0, _overrides.getOverrides)(overrides.SearchIconContainer, _styledComponents.StyledSearchIconContainer),
970 _getOverrides10 = _slicedToArray(_getOverrides9, 2),
971 SearchIconContainer = _getOverrides10[0],
972 searchIconContainerProps = _getOverrides10[1];
973
974 var _getOverrides11 = (0, _overrides.getOverrides)(overrides.SearchIcon, _search.default),
975 _getOverrides12 = _slicedToArray(_getOverrides11, 2),
976 SearchIcon = _getOverrides12[0],
977 searchIconProps = _getOverrides12[1];
978
979 var sharedProps = this.getSharedProps();
980 return (// TODO(v11): remove searchIconProps from SearchIconContainer
981 React.createElement(SearchIconContainer, _extends({}, sharedProps, searchIconProps, searchIconContainerProps), React.createElement(SearchIcon, _extends({
982 size: 16,
983 title: 'search'
984 }, searchIconProps)))
985 );
986 }
987 }, {
988 key: "filterOptions",
989 value: function filterOptions(excludeOptions) {
990 var _this5 = this;
991
992 var filterValue = this.state.inputValue; // apply filter function
993
994 if (this.props.filterOptions) {
995 this.options = this.props.filterOptions(this.options, filterValue, excludeOptions, {
996 valueKey: this.props.valueKey,
997 labelKey: this.props.labelKey
998 });
999 } // can user create a new option + there's no exact match already
1000
1001
1002 if (filterValue && this.props.creatable && this.options.concat(this.props.value).every(function (opt) {
1003 return opt[_this5.props.labelKey].toLowerCase() !== filterValue.toLowerCase().trim();
1004 })) {
1005 var _this$options$push;
1006
1007 // $FlowFixMe - this.options is typed as a read-only array
1008 this.options.push((_this$options$push = {
1009 id: filterValue
1010 }, _defineProperty(_this$options$push, this.props.labelKey, filterValue), _defineProperty(_this$options$push, this.props.valueKey, filterValue), _defineProperty(_this$options$push, "isCreatable", true), _this$options$push));
1011 }
1012
1013 return this.options;
1014 }
1015 }, {
1016 key: "getSharedProps",
1017 value: function getSharedProps() {
1018 var _this$props = this.props,
1019 clearable = _this$props.clearable,
1020 creatable = _this$props.creatable,
1021 disabled = _this$props.disabled,
1022 error = _this$props.error,
1023 positive = _this$props.positive,
1024 isLoading = _this$props.isLoading,
1025 multi = _this$props.multi,
1026 required = _this$props.required,
1027 size = _this$props.size,
1028 searchable = _this$props.searchable,
1029 type = _this$props.type,
1030 value = _this$props.value;
1031 var _this$state = this.state,
1032 isOpen = _this$state.isOpen,
1033 isFocused = _this$state.isFocused,
1034 isPseudoFocused = _this$state.isPseudoFocused;
1035 return {
1036 $clearable: clearable,
1037 $creatable: creatable,
1038 $disabled: disabled,
1039 $error: error,
1040 $positive: positive,
1041 $isFocused: isFocused,
1042 $isLoading: isLoading,
1043 $isOpen: isOpen,
1044 $isPseudoFocused: isPseudoFocused,
1045 $multi: multi,
1046 $required: required,
1047 $searchable: searchable,
1048 $size: size,
1049 $type: type,
1050 $isEmpty: !this.getValueArray(value).length
1051 };
1052 }
1053 }, {
1054 key: "render",
1055 value: function render() {
1056 var _this6 = this;
1057
1058 this.options = (0, _index4.normalizeOptions)(this.props.options);
1059 var _this$props2 = this.props,
1060 _this$props2$override = _this$props2.overrides,
1061 overrides = _this$props2$override === void 0 ? {} : _this$props2$override,
1062 type = _this$props2.type,
1063 multi = _this$props2.multi,
1064 noResultsMsg = _this$props2.noResultsMsg,
1065 value = _this$props2.value,
1066 filterOutSelected = _this$props2.filterOutSelected;
1067
1068 if (process.env.NODE_ENV !== "production") {
1069 // value may be nullish, only warn if value is defined
1070 if (value && !Array.isArray(value)) {
1071 console.warn('The Select component expects an array as the value prop. For more information, please visit the docs at https://baseweb.design/components/select/');
1072 }
1073 }
1074
1075 var _getOverrides13 = (0, _overrides.getOverrides)(overrides.Root, _styledComponents.StyledRoot),
1076 _getOverrides14 = _slicedToArray(_getOverrides13, 2),
1077 Root = _getOverrides14[0],
1078 rootProps = _getOverrides14[1];
1079
1080 var _getOverrides15 = (0, _overrides.getOverrides)(overrides.ControlContainer, _styledComponents.StyledControlContainer),
1081 _getOverrides16 = _slicedToArray(_getOverrides15, 2),
1082 ControlContainer = _getOverrides16[0],
1083 controlContainerProps = _getOverrides16[1];
1084
1085 var _getOverrides17 = (0, _overrides.getOverrides)(overrides.ValueContainer, _styledComponents.StyledValueContainer),
1086 _getOverrides18 = _slicedToArray(_getOverrides17, 2),
1087 ValueContainer = _getOverrides18[0],
1088 valueContainerProps = _getOverrides18[1];
1089
1090 var _getOverrides19 = (0, _overrides.getOverrides)(overrides.IconsContainer, _styledComponents.StyledIconsContainer),
1091 _getOverrides20 = _slicedToArray(_getOverrides19, 2),
1092 IconsContainer = _getOverrides20[0],
1093 iconsContainerProps = _getOverrides20[1];
1094
1095 var _getOverrides21 = (0, _overrides.getOverrides)(overrides.Popover, _index2.Popover),
1096 _getOverrides22 = _slicedToArray(_getOverrides21, 2),
1097 PopoverOverride = _getOverrides22[0],
1098 popoverProps = _getOverrides22[1];
1099
1100 var _getOverrides23 = (0, _overrides.getOverrides)(overrides.Placeholder, _styledComponents.StyledPlaceholder),
1101 _getOverrides24 = _slicedToArray(_getOverrides23, 2),
1102 Placeholder = _getOverrides24[0],
1103 placeholderProps = _getOverrides24[1];
1104
1105 var sharedProps = this.getSharedProps();
1106 var valueArray = this.getValueArray(value);
1107 var options = this.filterOptions(multi && filterOutSelected ? valueArray : null);
1108 var isOpen = this.state.isOpen;
1109 sharedProps.$isOpen = isOpen;
1110
1111 if (process.env.NODE_ENV !== "production") {
1112 if (this.props.error && this.props.positive) {
1113 // eslint-disable-next-line no-console
1114 console.warn("[Select] `error` and `positive` are both set to `true`. `error` will take precedence but this may not be what you want.");
1115 }
1116 }
1117
1118 return React.createElement(_index.LocaleContext.Consumer, null, function (locale) {
1119 return React.createElement(PopoverOverride // Popover does not provide ability to forward refs through, and if we were to simply
1120 // apply the ref to the Root component below it would be overwritten before the popover
1121 // renders it. Using this strategy, we will get a ref to the popover, then reuse its
1122 // anchorRef so we can check if clicks are on the select component or not.
1123 // eslint-disable-next-line flowtype/no-weak-types
1124 , _extends({
1125 ref: function ref(_ref4) {
1126 if (!_ref4) return;
1127 _this6.anchor = _ref4.anchorRef;
1128 },
1129 focusLock: false,
1130 mountNode: _this6.props.mountNode,
1131 onEsc: function onEsc() {
1132 return _this6.closeMenu();
1133 },
1134 isOpen: isOpen,
1135 popoverMargin: 0,
1136 content: function content() {
1137 var dropdownProps = {
1138 error: _this6.props.error,
1139 positive: _this6.props.positive,
1140 getOptionLabel: _this6.props.getOptionLabel || _this6.getOptionLabel.bind(_this6, locale),
1141 id: _this6.listboxId,
1142 isLoading: _this6.props.isLoading,
1143 labelKey: _this6.props.labelKey,
1144 maxDropdownHeight: _this6.props.maxDropdownHeight,
1145 multi: multi,
1146 noResultsMsg: noResultsMsg,
1147 onActiveDescendantChange: _this6.handleActiveDescendantChange,
1148 onItemSelect: _this6.selectValue,
1149 options: options,
1150 overrides: overrides,
1151 required: _this6.props.required,
1152 searchable: _this6.props.searchable,
1153 size: _this6.props.size,
1154 type: type,
1155 value: valueArray,
1156 valueKey: _this6.props.valueKey,
1157 width: _this6.anchor.current ? _this6.anchor.current.clientWidth : null,
1158 keyboardControlNode: _this6.anchor
1159 };
1160 return React.createElement(_dropdown.default, _extends({
1161 innerRef: _this6.dropdown
1162 }, dropdownProps));
1163 },
1164 placement: _index2.PLACEMENT.bottom
1165 }, popoverProps), React.createElement(Root, _extends({
1166 onBlur: _this6.handleBlur,
1167 "data-baseweb": "select"
1168 }, sharedProps, rootProps), React.createElement(ControlContainer, _extends({
1169 onKeyDown: _this6.handleKeyDown,
1170 onClick: _this6.handleClick,
1171 onTouchEnd: _this6.handleTouchEnd,
1172 onTouchMove: _this6.handleTouchMove,
1173 onTouchStart: _this6.handleTouchStart
1174 }, sharedProps, controlContainerProps), type === _constants.TYPE.search ? _this6.renderSearch() : null, React.createElement(ValueContainer, _extends({}, sharedProps, valueContainerProps), _this6.renderValue(valueArray, isOpen, locale), _this6.renderInput(), _this6.shouldShowPlaceholder() ? React.createElement(Placeholder, _extends({}, sharedProps, placeholderProps), typeof _this6.props.placeholder !== 'undefined' ? _this6.props.placeholder : locale.select.placeholder) : null), React.createElement(IconsContainer, _extends({}, sharedProps, iconsContainerProps), _this6.renderLoading(), _this6.renderClear(), type === _constants.TYPE.select ? _this6.renderArrow() : null))));
1175 });
1176 }
1177 }]);
1178
1179 return Select;
1180}(React.Component);
1181
1182_defineProperty(Select, "defaultProps", _defaultProps.default);
1183
1184var _default = Select;
1185exports.default = _default;
\No newline at end of file