Skip to content

Commit

Permalink
fix(Autocomplete): enhance logic for when to blur
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Nov 12, 2023
1 parent fff72da commit d71bb49
Show file tree
Hide file tree
Showing 2 changed files with 471 additions and 182 deletions.
136 changes: 74 additions & 62 deletions packages/dnb-eufemia/src/components/autocomplete/Autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,6 @@ class AutocompleteInstance extends React.PureComponent {
clearTimeout(this._ariaLiveUpdateTimeout)
clearTimeout(this._focusTimeout)
clearTimeout(this._blurTimeout)
clearTimeout(this._toggleVisibleTimeout)
}

setVisible = (args = null, onStateComplete = null) => {
Expand Down Expand Up @@ -564,6 +563,8 @@ class AutocompleteInstance extends React.PureComponent {
const data = this.runFilter(value, options)
const count = this.countData(data)

const { keep_value, keep_value_and_selection } = this.props

if (value && value.length > 0) {
// show the "no_options" message
if (count === 0) {
Expand All @@ -583,15 +584,12 @@ class AutocompleteInstance extends React.PureComponent {
}
}
} else {
if (
!isTrue(this.props.keep_value) &&
!isTrue(this.props.keep_value_and_selection)
) {
if (!isTrue(keep_value) && !isTrue(keep_value_and_selection)) {
// this will not remove selected_item
this.totalReset()
}

if (isTrue(this.props.keep_value)) {
if (isTrue(keep_value)) {
this.resetSelectedItem()
}

Expand Down Expand Up @@ -893,15 +891,38 @@ class AutocompleteInstance extends React.PureComponent {
}
}

onReserveActivityHandler = (event) => {
// Prevent to happen the on_blur event during drawer-list activity
this.__preventFiringBlurEvent =
onReserveActivityHandler = (event = null) => {
this.__preventFiringBlurEvent = Boolean(
event.key === 'enter' ||
event.key === 'space' ||
(event.target && getPreviousSibling('dnb-drawer-list', event.target))
(event?.currentTarget
? getPreviousSibling('dnb-drawer-list', event.currentTarget) ||
getPreviousSibling(
'dnb-input__submit-button__button',
event.currentTarget
)
: false)
)

if (this.__preventFiringBlurEvent) {
setTimeout(
() => {
this.__preventFiringBlurEvent = false
},
isTrue(this.props.no_animation) ? 1 : DrawerList.blurDelay
)
}
}

onBlurHandler = (event) => {
if (
this.__preventFiringBlurEvent ||
this.context.drawerList.hasFocusOnElement ||
this.state.hasBlur
) {
this.__preventFiringBlurEvent = null
return false
}

const {
open_on_focus,
keep_value,
Expand All @@ -910,60 +931,54 @@ class AutocompleteInstance extends React.PureComponent {
no_animation,
} = this.props

if (
!this.state.hasBlur &&
!this.__preventFiringBlurEvent &&
!this.context.drawerList.hasFocusOnElement
) {
dispatchCustomElementEvent(this, 'on_blur', {
event,
...this.getEventObjects('on_blur'),
})
dispatchCustomElementEvent(this, 'on_blur', {
event,
...this.getEventObjects('on_blur'),
})

this.setState({
hasBlur: true,
hasFocus: false,
})

if (!isTrue(keep_value) && !isTrue(keep_value_and_selection)) {
this.setState({
hasBlur: true,
hasFocus: false,
typedInputValue: null,
_listenForPropChanges: false,
})
}

if (!isTrue(keep_value_and_selection)) {
this.setState({
typedInputValue: null,
_listenForPropChanges: false,
})
}
if (!isTrue(prevent_selection)) {
const existingValue = this.state.inputValue

if (!isTrue(prevent_selection)) {
const existingValue = this.state.inputValue
if (!isTrue(keep_value) && !isTrue(keep_value_and_selection)) {
this.clearInputValue()
}

const resetAfterClose = () => {
if (
!isTrue(keep_value) ||
!existingValue ||
this.hasSelectedItem()
) {
this.resetActiveItem()
}
this.resetFilter()
}

if (isTrue(no_animation)) {
resetAfterClose()
} else {
clearTimeout(this._blurTimeout)
this._blurTimeout = setTimeout(
resetAfterClose,
DrawerList.blurDelay
) // only to let the animation pass, before we make the effect. Else this would be a visible change
const resetAfterClose = () => {
if (
!isTrue(keep_value) ||
!existingValue ||
this.hasSelectedItem()
) {
this.resetActiveItem()
}
this.resetFilter()
}

if (isTrue(open_on_focus)) {
this.setHidden()
if (isTrue(no_animation)) {
resetAfterClose()
} else {
clearTimeout(this._blurTimeout)
this._blurTimeout = setTimeout(
resetAfterClose,
DrawerList.blurDelay
) // only to let the animation pass, before we make the effect. Else this would be a visible change
}
} else if (this.__preventFiringBlurEvent) {
this.__preventFiringBlurEvent = null
return false
}

if (isTrue(open_on_focus)) {
this.setHidden()
}
}

Expand Down Expand Up @@ -1029,8 +1044,7 @@ class AutocompleteInstance extends React.PureComponent {
(!this.hasValidData() || !this.hasSelectedItem()) &&
!this.hasActiveItem()
) {
clearTimeout(this._toggleVisibleTimeout)
this._toggleVisibleTimeout = setTimeout(this.toggleVisible, 1) // to make sure we first handle the DrawerList key enter, before we update the state with a toggle/visible. Else the submit is not set properly
this.toggleVisible()
} else {
this.setVisible()
}
Expand Down Expand Up @@ -1541,12 +1555,9 @@ class AutocompleteInstance extends React.PureComponent {
} catch (e) {
// do nothing
}
clearTimeout(this._focusTimeout)
this._focusTimeout = setTimeout(() => {
this.setState({
hasFocus: false,
})
}, 1) // we have to wait in order to make sure the focus situation is cleared up
this.setState({
hasFocus: false,
})
}
)
}
Expand Down Expand Up @@ -1895,6 +1906,7 @@ class AutocompleteInstance extends React.PureComponent {
status: !opened && status ? status_state : null,
onKeyDown: this.onTriggerKeyDownHandler,
onSubmit: this.toggleVisible,
onMouseDown: this.onReserveActivityHandler,
'aria-haspopup': 'listbox',
'aria-expanded': isExpanded,
'aria-label': !hidden ? submit_button_title : undefined,
Expand Down
Loading

0 comments on commit d71bb49

Please sign in to comment.