in Dataset/JS/ReactSelect/index.tsx [773:905]
value: valueTernary(isMulti, selectValue, selectValue[0] || null),
options: selectValue,
action: 'initial-input-focus',
};
hasKeptFocus = !prevWasFocused;
}
// If the 'initial-input-focus' action has been set already
// then reset the ariaSelection to null
if (ariaSelection?.action === 'initial-input-focus') {
newAriaSelection = null;
}
return {
...newMenuOptionsState,
...newInputIsHiddenState,
prevProps: props,
ariaSelection: newAriaSelection,
prevWasFocused: hasKeptFocus,
};
}
componentDidMount() {
this.startListeningComposition();
this.startListeningToTouch();
if (this.props.closeMenuOnScroll && document && document.addEventListener) {
// Listen to all scroll events, and filter them out inside of 'onScroll'
document.addEventListener('scroll', this.onScroll, true);
}
if (this.props.autoFocus) {
this.focusInput();
}
// Scroll focusedOption into view if menuIsOpen is set on mount (e.g. defaultMenuIsOpen)
if (
this.props.menuIsOpen &&
this.state.focusedOption &&
this.menuListRef &&
this.focusedOptionRef
) {
scrollIntoView(this.menuListRef, this.focusedOptionRef);
}
}
componentDidUpdate(prevProps: Props<Option, IsMulti, Group>) {
const { isDisabled, menuIsOpen } = this.props;
const { isFocused } = this.state;
if (
// ensure focus is restored correctly when the control becomes enabled
(isFocused && !isDisabled && prevProps.isDisabled) ||
// ensure focus is on the Input when the menu opens
(isFocused && menuIsOpen && !prevProps.menuIsOpen)
) {
this.focusInput();
}
if (isFocused && isDisabled && !prevProps.isDisabled) {
// ensure select state gets blurred in case Select is programmatically disabled while focused
// eslint-disable-next-line react/no-did-update-set-state
this.setState({ isFocused: false }, this.onMenuClose);
} else if (
!isFocused &&
!isDisabled &&
prevProps.isDisabled &&
this.inputRef === document.activeElement
) {
// ensure select state gets focused in case Select is programatically re-enabled while focused (Firefox)
// eslint-disable-next-line react/no-did-update-set-state
this.setState({ isFocused: true });
}
// scroll the focused option into view if necessary
if (
this.menuListRef &&
this.focusedOptionRef &&
this.scrollToFocusedOptionOnUpdate
) {
scrollIntoView(this.menuListRef, this.focusedOptionRef);
this.scrollToFocusedOptionOnUpdate = false;
}
}
componentWillUnmount() {
this.stopListeningComposition();
this.stopListeningToTouch();
document.removeEventListener('scroll', this.onScroll, true);
}
// ==============================
// Consumer Handlers
// ==============================
onMenuOpen() {
this.props.onMenuOpen();
}
onMenuClose() {
this.onInputChange('', {
action: 'menu-close',
prevInputValue: this.props.inputValue,
});
this.props.onMenuClose();
}
onInputChange(newValue: string, actionMeta: InputActionMeta) {
this.props.onInputChange(newValue, actionMeta);
}
// ==============================
// Methods
// ==============================
focusInput() {
if (!this.inputRef) return;
this.inputRef.focus();
}
blurInput() {
if (!this.inputRef) return;
this.inputRef.blur();
}
// aliased for consumers
focus = this.focusInput;
blur = this.blurInput;
openMenu(focusOption: 'first' | 'last') {
const { selectValue, isFocused } = this.state;
const focusableOptions = this.buildFocusableOptions();
let openAtIndex = focusOption === 'first' ? 0 : focusableOptions.length - 1;
if (!this.props.isMulti) {
const selectedIndex = focusableOptions.indexOf(selectValue[0]);
if (selectedIndex > -1) {