Skip to content

Commit

Permalink
fix: mouse can steal selection when dropdown scrolls on input change
Browse files Browse the repository at this point in the history
  • Loading branch information
jhbertra committed Jan 28, 2022
1 parent 9d84174 commit 5e88b52
Showing 1 changed file with 25 additions and 2 deletions.
27 changes: 25 additions & 2 deletions src/NSelect.purs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ module NSelect
import Prelude

import Data.Foldable (traverse_)
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..), isJust)
import Effect.Aff as Aff
import Effect.Aff.Class (class MonadAff)
import Effect.Class (class MonadEffect)
Expand Down Expand Up @@ -69,6 +69,7 @@ data Action pa cs m
| ReceiveProps (Props pa cs m)
| OnWindowMouseDown
| OnWindowMouseUp
| OnWindowMouseMove
| OnWindowDragEnd
| OnMouseDownRoot
| OnMouseDownToggle
Expand All @@ -85,6 +86,13 @@ type InnerState pa cs m =
, clickedInside :: Boolean
, isOpen :: Boolean
, highlightedIndex :: Int
-- When we use the arrow keys, we want to prevent the mouse from stealing
-- the selection back if it is hovering over top of the dropdown. So when an
-- arrow key is pressed, we create a subscription that listens for a
-- mousemove event on the window. When this event is fired, we unsubscribe
-- and clean this value up. If this value is `Just`, we ignore the
-- `OnMouseEnterItem` action.
, mouseMoveSubscription :: Maybe H.SubscriptionId
}

initialState :: forall pa cs m. Props pa cs m -> InnerState pa cs m
Expand All @@ -93,6 +101,7 @@ initialState props =
, clickedInside: false
, isOpen: false
, highlightedIndex: 0
, mouseMoveSubscription: Nothing
}

type State =
Expand Down Expand Up @@ -261,6 +270,13 @@ handleHighlightedIndexChange
=> Int
-> DSL pa cs m Unit
handleHighlightedIndexChange index = do
waitingForMouseMove <- H.gets $ isJust <<< _.mouseMoveSubscription
when (not waitingForMouseMove) do
win <- H.liftEffect Web.window
mouseMoveSubscription <- H.subscribe $
QE.eventListener ET.mousemove (Window.toEventTarget win)
(const $ Just OnWindowMouseMove)
H.modify_ _ { mouseMoveSubscription = Just mouseMoveSubscription }
updateHighlightedIndex index
scrollIntoViewIfNeeded index

Expand Down Expand Up @@ -319,6 +335,11 @@ handleAction = case _ of
$ H.modify_
$ _ { clickedInside = false }

OnWindowMouseMove -> do
mouseMoveSubscription <- H.gets _.mouseMoveSubscription
H.modify_ _ { mouseMoveSubscription = Nothing }
traverse_ H.unsubscribe mouseMoveSubscription

OnWindowDragEnd -> do
-- Handle the case of dragging from NSelect dropdown to the outside.
state <- H.get
Expand Down Expand Up @@ -363,7 +384,9 @@ handleAction = case _ of
H.raise $ Selected index

OnMouseEnterItem index -> do
updateHighlightedIndex index
waitingForMouseMove <- H.gets $ isJust <<< _.mouseMoveSubscription
when (not waitingForMouseMove) do
updateHighlightedIndex index

OnValueInput value -> do
handleHighlightedIndexChange 0
Expand Down

0 comments on commit 5e88b52

Please sign in to comment.