Merge pull request #45 from JordanMartinez/exposeInput
Expose `input` type in Select components and combine `spec` and `input` into `Select.component`
This commit is contained in:
commit
467b35fa5d
7 changed files with 151 additions and 154 deletions
examples
src
|
@ -2,7 +2,6 @@ module Components.Dropdown where
|
|||
|
||||
import Prelude
|
||||
|
||||
import Data.Const (Const)
|
||||
import Effect.Aff (Aff)
|
||||
import Data.Array ((!!), mapWithIndex, length)
|
||||
import Data.Maybe (Maybe(..), fromMaybe)
|
||||
|
@ -18,7 +17,7 @@ type Slot =
|
|||
|
||||
type State =
|
||||
( items :: Array String
|
||||
, selection :: Maybe String
|
||||
, selection :: Maybe String
|
||||
, buttonLabel :: String
|
||||
)
|
||||
|
||||
|
@ -32,21 +31,25 @@ type Input =
|
|||
, buttonLabel :: String
|
||||
}
|
||||
|
||||
input :: Input -> S.Input State
|
||||
input { items, buttonLabel } =
|
||||
{ inputType: S.Toggle
|
||||
, search: Nothing
|
||||
, debounceTime: Nothing
|
||||
, getItemCount: length <<< _.items
|
||||
, items
|
||||
, buttonLabel
|
||||
, selection: Nothing
|
||||
component :: H.Component HH.HTML S.Query' Input Message Aff
|
||||
component = S.component input $ S.defaultSpec
|
||||
{ render = render
|
||||
, handleEvent = handleEvent
|
||||
}
|
||||
|
||||
spec :: S.Spec State (Const Void) Void () Message Aff
|
||||
spec = S.defaultSpec { render = render, handleMessage = handleMessage }
|
||||
where
|
||||
handleMessage = case _ of
|
||||
input :: Input -> S.Input State
|
||||
input { items, buttonLabel } =
|
||||
{ inputType: S.Toggle
|
||||
, search: Nothing
|
||||
, debounceTime: Nothing
|
||||
, getItemCount: length <<< _.items
|
||||
, items
|
||||
, buttonLabel
|
||||
, selection: Nothing
|
||||
}
|
||||
|
||||
handleEvent :: S.Event -> H.HalogenM (S.State State) S.Action' () Message Aff Unit
|
||||
handleEvent = case _ of
|
||||
S.Selected ix -> do
|
||||
st <- H.get
|
||||
let selection = st.items !! ix
|
||||
|
@ -54,8 +57,9 @@ spec = S.defaultSpec { render = render, handleMessage = handleMessage }
|
|||
H.raise $ SelectionChanged st.selection selection
|
||||
_ -> pure unit
|
||||
|
||||
render st =
|
||||
HH.div
|
||||
render :: S.State State -> H.ComponentHTML S.Action' () Aff
|
||||
render st =
|
||||
HH.div
|
||||
[ class_ "Dropdown" ]
|
||||
[ renderToggle, renderContainer ]
|
||||
where
|
||||
|
@ -70,13 +74,12 @@ spec = S.defaultSpec { render = render, handleMessage = handleMessage }
|
|||
( renderItem `mapWithIndex` st.items )
|
||||
where
|
||||
renderItem index item =
|
||||
HH.div
|
||||
( SS.setItemProps index
|
||||
[ classes_
|
||||
HH.div
|
||||
( SS.setItemProps index
|
||||
[ classes_
|
||||
[ "Dropdown__item"
|
||||
, "Dropdown__item--highlighted" # guard (st.highlightedIndex == Just index)
|
||||
]
|
||||
]
|
||||
)
|
||||
)
|
||||
[ HH.text item ]
|
||||
|
||||
|
|
|
@ -24,11 +24,11 @@ import Internal.RemoteData as RD
|
|||
import Select as S
|
||||
import Select.Setters as SS
|
||||
|
||||
type Slot =
|
||||
type Slot =
|
||||
S.Slot Query ChildSlots Message
|
||||
|
||||
type State =
|
||||
( selections :: Array Location
|
||||
( selections :: Array Location
|
||||
, available :: RD.RemoteData String (Array Location)
|
||||
)
|
||||
|
||||
|
@ -39,43 +39,43 @@ data Action
|
|||
data Query a
|
||||
= GetSelections (Array Location -> a)
|
||||
|
||||
data Message
|
||||
= ItemRemoved Location
|
||||
data Message
|
||||
= ItemRemoved Location
|
||||
| SelectionsChanged (Array Location)
|
||||
|
||||
type ChildSlots =
|
||||
type ChildSlots =
|
||||
( dropdown :: D.Slot Unit )
|
||||
|
||||
-- this typeahead will be opaque; users can just use this pre-built
|
||||
-- input instead of the usual select one.
|
||||
input :: S.Input State
|
||||
input =
|
||||
{ inputType: S.Text
|
||||
, debounceTime: Just (Milliseconds 300.0)
|
||||
, search: Nothing
|
||||
, getItemCount: maybe 0 length <<< RD.toMaybe <<< _.available
|
||||
, selections: []
|
||||
, available: RD.NotAsked
|
||||
}
|
||||
|
||||
spec :: S.Spec State Query Action ChildSlots Message Aff
|
||||
spec = S.defaultSpec
|
||||
component :: H.Component HH.HTML (S.Query Query ChildSlots) Unit Message Aff
|
||||
component = S.component (const input) $ S.defaultSpec
|
||||
{ render = render
|
||||
, handleAction = handleAction
|
||||
, handleQuery = handleQuery
|
||||
, handleMessage = handleMessage
|
||||
, handleEvent = handleEvent
|
||||
}
|
||||
where
|
||||
handleMessage
|
||||
:: S.Message
|
||||
-- this typeahead will be opaque; users can just use this pre-built
|
||||
-- input instead of the usual select one.
|
||||
input :: S.Input State
|
||||
input =
|
||||
{ inputType: S.Text
|
||||
, debounceTime: Just (Milliseconds 300.0)
|
||||
, search: Nothing
|
||||
, getItemCount: maybe 0 length <<< RD.toMaybe <<< _.available
|
||||
, selections: []
|
||||
, available: RD.NotAsked
|
||||
}
|
||||
|
||||
handleEvent
|
||||
:: S.Event
|
||||
-> H.HalogenM (S.State State) (S.Action Action) ChildSlots Message Aff Unit
|
||||
handleMessage = case _ of
|
||||
handleEvent = case _ of
|
||||
S.Selected ix -> do
|
||||
st <- H.get
|
||||
for_ st.available \arr ->
|
||||
for_ (arr !! ix) \item -> do
|
||||
let newSelections = item : st.selections
|
||||
H.modify_ _
|
||||
H.modify_ _
|
||||
{ selections = item : st.selections
|
||||
, available = RD.Success (filter (_ /= item) arr)
|
||||
, search = ""
|
||||
|
@ -83,7 +83,7 @@ spec = S.defaultSpec
|
|||
H.raise $ SelectionsChanged newSelections
|
||||
S.Searched str -> do
|
||||
st <- H.get
|
||||
-- we'll use an external api to search locations
|
||||
-- we'll use an external api to search locations
|
||||
H.modify_ _ { available = RD.Loading }
|
||||
items <- H.liftAff $ searchLocations str
|
||||
H.modify_ _ { available = items <#> \xs -> difference xs st.selections }
|
||||
|
@ -92,13 +92,13 @@ spec = S.defaultSpec
|
|||
-- You can remove all type signatures except for this one; we need to tell the
|
||||
-- compiler about the `a` type variable. The minimal necessary signature is below.
|
||||
handleQuery :: forall a. Query a -> H.HalogenM _ _ _ _ _ (Maybe a)
|
||||
handleQuery = case _ of
|
||||
handleQuery = case _ of
|
||||
GetSelections reply -> do
|
||||
st <- H.get
|
||||
pure $ Just $ reply st.selections
|
||||
|
||||
handleAction
|
||||
:: Action
|
||||
handleAction
|
||||
:: Action
|
||||
-> H.HalogenM (S.State State) (S.Action Action) ChildSlots Message Aff Unit
|
||||
handleAction = case _ of
|
||||
Remove item -> do
|
||||
|
@ -109,23 +109,23 @@ spec = S.defaultSpec
|
|||
HandleDropdown msg -> case msg of
|
||||
D.SelectionChanged oldSelection newSelection -> do
|
||||
st <- H.get
|
||||
let
|
||||
let
|
||||
mkLocation str = { name: "User Added: " <> str, population: "1" }
|
||||
newSelections = case oldSelection, newSelection of
|
||||
Nothing, Nothing ->
|
||||
Nothing, Nothing ->
|
||||
Nothing
|
||||
Nothing, Just str ->
|
||||
Nothing, Just str ->
|
||||
Just (mkLocation str : st.selections)
|
||||
Just str, Nothing ->
|
||||
Just str, Nothing ->
|
||||
Just (filter (_ /= mkLocation str) st.selections)
|
||||
Just old, Just new ->
|
||||
Just old, Just new ->
|
||||
Just (mkLocation new : (filter (_ /= mkLocation old) st.selections))
|
||||
for_ newSelections \selections ->
|
||||
for_ newSelections \selections ->
|
||||
H.modify_ _ { selections = selections }
|
||||
|
||||
render :: S.State State -> H.ComponentHTML (S.Action Action) ChildSlots Aff
|
||||
render st =
|
||||
HH.div
|
||||
render st =
|
||||
HH.div
|
||||
[ class_ "Typeahead" ]
|
||||
[ renderSelections, renderInput, renderDropdown, renderContainer ]
|
||||
where
|
||||
|
@ -139,7 +139,7 @@ spec = S.defaultSpec
|
|||
renderSelectedItem item =
|
||||
HH.div
|
||||
[ class_ "Typeahead__item--selected Location" ]
|
||||
[ HH.span
|
||||
[ HH.span
|
||||
[ class_ "Location__name" ]
|
||||
[ HH.text item.name ]
|
||||
, closeButton item
|
||||
|
@ -147,32 +147,32 @@ spec = S.defaultSpec
|
|||
|
||||
closeButton item =
|
||||
HH.span
|
||||
[ class_ "Location__closeButton"
|
||||
[ class_ "Location__closeButton"
|
||||
, HE.onClick \_ -> Just $ S.Action $ Remove item
|
||||
]
|
||||
[ HH.text "×" ]
|
||||
|
||||
renderInput = HH.input $ SS.setInputProps
|
||||
[ classes_
|
||||
[ classes_
|
||||
[ "Typeahead__input"
|
||||
, "Typeahead__input--selections" # guard hasSelections
|
||||
, "Typeahead__input--active" # guard (st.visibility == S.On)
|
||||
]
|
||||
, HP.placeholder "Type to search..."
|
||||
, HP.placeholder "Type to search..."
|
||||
]
|
||||
|
||||
renderDropdown = whenElem (st.visibility == S.On) \_ ->
|
||||
HH.slot _dropdown unit (S.component D.spec) (D.input dropdownInput) handler
|
||||
HH.slot _dropdown unit D.component dropdownInput handler
|
||||
where
|
||||
_dropdown = SProxy :: SProxy "dropdown"
|
||||
handler msg = Just $ S.Action $ HandleDropdown msg
|
||||
dropdownInput = { items: [ "Earth", "Mars" ], buttonLabel: "Human Planets" }
|
||||
|
||||
renderContainer = whenElem (st.visibility == S.On) \_ ->
|
||||
HH.div
|
||||
(SS.setContainerProps
|
||||
[ classes_
|
||||
[ "Typeahead__container"
|
||||
HH.div
|
||||
(SS.setContainerProps
|
||||
[ classes_
|
||||
[ "Typeahead__container"
|
||||
, "Typeahead__container--hasItems" # guard hasItems
|
||||
]
|
||||
]
|
||||
|
@ -186,14 +186,14 @@ spec = S.defaultSpec
|
|||
RD.NotAsked -> renderMsg "No search performed..."
|
||||
RD.Loading -> renderMsg "Loading..."
|
||||
RD.Failure e -> renderMsg e
|
||||
RD.Success available
|
||||
RD.Success available
|
||||
| hasItems -> renderItem `mapWithIndex` available
|
||||
| otherwise -> renderMsg "No results found"
|
||||
|
||||
renderItem index { name, population } =
|
||||
HH.div
|
||||
(SS.setItemProps index [ classes_ [ base, highlight, "Location" ] ])
|
||||
[ HH.span
|
||||
HH.div
|
||||
(SS.setItemProps index [ classes_ [ base, highlight, "Location" ] ])
|
||||
[ HH.span
|
||||
[ class_ "Location__name" ]
|
||||
[ HH.text name ]
|
||||
, HH.span
|
||||
|
@ -214,7 +214,6 @@ type Location =
|
|||
|
||||
searchLocations :: String -> Aff (RD.RemoteData String (Array Location))
|
||||
searchLocations search = do
|
||||
res <- AX.get AR.json ("https://swapi.co/api/planets/?search=" <> search)
|
||||
res <- AX.get AR.json ("https://swapi.co/api/planets/?search=" <> search)
|
||||
let body = lmap AR.printResponseFormatError res.body
|
||||
pure $ RD.fromEither $ traverse decodeJson =<< (_ .: "results") =<< decodeJson =<< body
|
||||
|
||||
|
|
|
@ -13,4 +13,3 @@ classes_ = HP.classes <<< map HH.ClassName
|
|||
|
||||
whenElem :: forall p i. Boolean -> (Unit -> HH.HTML i p) -> HH.HTML i p
|
||||
whenElem cond render = if cond then render unit else HH.text ""
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
-- | Copied over from
|
||||
-- | Copied over from
|
||||
-- | https://github.com/krisajenkins/purescript-remotedata
|
||||
-- |
|
||||
-- | due to dependency conflicts
|
||||
|
@ -42,4 +42,3 @@ fromMaybe (Just value) = Success value
|
|||
fromEither :: forall e a. Either e a -> RemoteData e a
|
||||
fromEither (Left err) = Failure err
|
||||
fromEither (Right value) = Success value
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ import Halogen.Aff as HA
|
|||
import Halogen.HTML as HH
|
||||
import Halogen.VDom.Driver (runUI)
|
||||
import Internal.Proxy (ProxyS, proxy)
|
||||
import Select as Select
|
||||
import Web.DOM.Element (getAttribute)
|
||||
import Web.DOM.NodeList (toArray)
|
||||
import Web.DOM.ParentNode (QuerySelector(..), querySelectorAll)
|
||||
|
@ -48,7 +47,7 @@ type Components
|
|||
routes :: Components
|
||||
routes = M.fromFoldable
|
||||
[ Tuple "typeahead" $ proxy typeahead
|
||||
, Tuple "dropdown" $ proxy dropdown
|
||||
, Tuple "dropdown" $ proxy dropdown
|
||||
]
|
||||
|
||||
app :: H.Component HH.HTML (Const Void) String Void Aff
|
||||
|
@ -74,9 +73,9 @@ selectElements
|
|||
:: { query :: QuerySelector, attr :: String }
|
||||
-> Aff (Array { element :: HTMLElement, attr :: String })
|
||||
selectElements { query, attr } = do
|
||||
nodeArray <- liftEffect do
|
||||
nodeArray <- liftEffect do
|
||||
toArray =<< querySelectorAll query <<< toParentNode =<< document =<< window
|
||||
let
|
||||
let
|
||||
elems = fromMaybe [] <<< sequence $ fromNode <$> nodeArray
|
||||
attrs <- liftEffect $ traverse (getAttribute attr <<< toElement) elems
|
||||
pure $ zipWith ({ element: _, attr: _ }) elems (fromMaybe "" <$> attrs)
|
||||
|
@ -88,7 +87,7 @@ dropdown :: forall t0 t1 t2. H.Component HH.HTML t0 t1 t2 Aff
|
|||
dropdown = H.mkComponent
|
||||
{ initialState: const unit
|
||||
, render: \_ ->
|
||||
HH.slot label unit (Select.component Dropdown.spec) (Dropdown.input input) \_ -> Nothing
|
||||
HH.slot label unit Dropdown.component input \_ -> Nothing
|
||||
, eval: H.mkEval H.defaultEval
|
||||
}
|
||||
where
|
||||
|
@ -99,9 +98,8 @@ typeahead :: forall t0 t1 t2. H.Component HH.HTML t0 t1 t2 Aff
|
|||
typeahead = H.mkComponent
|
||||
{ initialState: const unit
|
||||
, render: \_ ->
|
||||
HH.slot label unit (Select.component Typeahead.spec) Typeahead.input \_ -> Nothing
|
||||
HH.slot label unit Typeahead.component unit \_ -> Nothing
|
||||
, eval: H.mkEval H.defaultEval
|
||||
}
|
||||
where
|
||||
label = SProxy :: SProxy "typeahead"
|
||||
|
||||
|
|
134
src/Select.purs
134
src/Select.purs
|
@ -30,7 +30,7 @@ import Web.HTML.HTMLElement as HTMLElement
|
|||
import Web.UIEvent.KeyboardEvent as KE
|
||||
import Web.UIEvent.MouseEvent as ME
|
||||
|
||||
data Action act
|
||||
data Action action
|
||||
= Search String
|
||||
| Highlight Target
|
||||
| Select Target (Maybe ME.MouseEvent)
|
||||
|
@ -39,24 +39,24 @@ data Action act
|
|||
| Key KE.KeyboardEvent
|
||||
| PreventClick ME.MouseEvent
|
||||
| SetVisibility Visibility
|
||||
| Initialize (Maybe (Action act))
|
||||
| Action act
|
||||
| Initialize (Maybe action)
|
||||
| Action action
|
||||
|
||||
type Action' = Action Void
|
||||
|
||||
-----
|
||||
-- QUERIES
|
||||
|
||||
data Query query ps a
|
||||
= Send (ChildQueryBox ps (Maybe a))
|
||||
data Query query slots a
|
||||
= Send (ChildQueryBox slots (Maybe a))
|
||||
| Query (query a)
|
||||
|
||||
type Query' = Query (Const Void) ()
|
||||
|
||||
-----
|
||||
-- Message
|
||||
-- Event
|
||||
|
||||
data Message
|
||||
data Event
|
||||
= Searched String
|
||||
| Selected Int
|
||||
| VisibilityChanged Visibility
|
||||
|
@ -65,7 +65,7 @@ data Message
|
|||
-- HELPER TYPES
|
||||
|
||||
-- | The component slot type for easy use in a parent component
|
||||
type Slot query ps msg = H.Slot (Query query ps) msg
|
||||
type Slot query slots msg = H.Slot (Query query slots) msg
|
||||
|
||||
-- | The component slot type when there is no extension
|
||||
type Slot' = Slot (Const Void) () Void
|
||||
|
@ -115,80 +115,83 @@ type Input st =
|
|||
| st
|
||||
}
|
||||
|
||||
type Spec st query act ps msg m =
|
||||
{ -- usual Halogen component spec
|
||||
render
|
||||
:: State st
|
||||
-> H.ComponentHTML (Action act) ps m
|
||||
|
||||
type Spec st query action slots input msg m =
|
||||
{ -- usual Halogen component spec
|
||||
render
|
||||
:: State st
|
||||
-> H.ComponentHTML (Action action) slots m
|
||||
|
||||
-- handle additional actions provided to the component
|
||||
, handleAction
|
||||
:: act
|
||||
-> H.HalogenM (State st) (Action act) ps msg m Unit
|
||||
, handleAction
|
||||
:: action
|
||||
-> H.HalogenM (State st) (Action action) slots msg m Unit
|
||||
|
||||
-- handle additional queries provided to the component
|
||||
, handleQuery
|
||||
, handleQuery
|
||||
:: forall a
|
||||
. query a
|
||||
-> H.HalogenM (State st) (Action act) ps msg m (Maybe a)
|
||||
. query a
|
||||
-> H.HalogenM (State st) (Action action) slots msg m (Maybe a)
|
||||
|
||||
-- handle messages emitted by the component; provide H.raise to simply
|
||||
-- raise the Select messages to the parent.
|
||||
, handleMessage
|
||||
:: Message
|
||||
-> H.HalogenM (State st) (Action act) ps msg m Unit
|
||||
, handleEvent
|
||||
:: Event
|
||||
-> H.HalogenM (State st) (Action action) slots msg m Unit
|
||||
|
||||
-- optionally handle input on parent re-renders
|
||||
, receive
|
||||
:: Input st
|
||||
-> Maybe (Action act)
|
||||
, receive
|
||||
:: input
|
||||
-> Maybe action
|
||||
|
||||
-- perform some action when the component initializes.
|
||||
, initialize
|
||||
:: Maybe (Action act)
|
||||
, initialize
|
||||
:: Maybe action
|
||||
|
||||
-- optionally perform some action on initialization. disabled by default.
|
||||
, finalize
|
||||
:: Maybe (Action act)
|
||||
:: Maybe action
|
||||
}
|
||||
|
||||
type Spec' st m = Spec st (Const Void) Void () Void m
|
||||
type Spec' st input m = Spec st (Const Void) Void () input Void m
|
||||
|
||||
defaultSpec :: forall st query act ps msg m. Spec st query act ps msg m
|
||||
defaultSpec =
|
||||
defaultSpec
|
||||
:: forall st query action slots input msg m
|
||||
. Spec st query action slots input msg m
|
||||
defaultSpec =
|
||||
{ render: const (HH.text mempty)
|
||||
, handleAction: const (pure unit)
|
||||
, handleQuery: const (pure Nothing)
|
||||
, handleMessage: const (pure unit)
|
||||
, handleEvent: const (pure unit)
|
||||
, receive: const Nothing
|
||||
, initialize: Nothing
|
||||
, finalize: Nothing
|
||||
}
|
||||
|
||||
|
||||
component
|
||||
:: forall st query act ps msg m
|
||||
:: forall st query action slots input msg m
|
||||
. MonadAff m
|
||||
=> Row.Lacks "debounceRef" st
|
||||
=> Row.Lacks "visibility" st
|
||||
=> Row.Lacks "highlightedIndex" st
|
||||
=> Spec st query act ps msg m
|
||||
-> H.Component HH.HTML (Query query ps) (Input st) msg m
|
||||
component spec = H.mkComponent
|
||||
{ initialState
|
||||
=> (input -> Input st)
|
||||
-> Spec st query action slots input msg m
|
||||
-> H.Component HH.HTML (Query query slots) input msg m
|
||||
component mkInput spec = H.mkComponent
|
||||
{ initialState: initialState <<< mkInput
|
||||
, render: spec.render
|
||||
, eval: H.mkEval $ H.defaultEval
|
||||
{ handleQuery = handleQuery spec.handleQuery
|
||||
, handleAction = handleAction spec.handleAction spec.handleMessage
|
||||
, initialize = Just (Initialize spec.initialize)
|
||||
, receive = spec.receive
|
||||
, finalize = spec.finalize
|
||||
, eval: H.mkEval
|
||||
{ handleQuery: handleQuery spec.handleQuery
|
||||
, handleAction: handleAction spec.handleAction spec.handleEvent
|
||||
, initialize: Just (Initialize spec.initialize)
|
||||
, receive: map Action <<< spec.receive
|
||||
, finalize: map Action spec.finalize
|
||||
}
|
||||
}
|
||||
where
|
||||
initialState :: Input st -> State st
|
||||
initialState = Builder.build pipeline
|
||||
where
|
||||
pipeline =
|
||||
pipeline =
|
||||
Builder.modify (SProxy :: _ "search") (fromMaybe "")
|
||||
>>> Builder.modify (SProxy :: _ "debounceTime") (fromMaybe mempty)
|
||||
>>> Builder.insert (SProxy :: _ "debounceRef") Nothing
|
||||
|
@ -196,11 +199,11 @@ component spec = H.mkComponent
|
|||
>>> Builder.insert (SProxy :: _ "highlightedIndex") Nothing
|
||||
|
||||
handleQuery
|
||||
:: forall st query act ps msg m a
|
||||
:: forall st query action slots msg m a
|
||||
. MonadAff m
|
||||
=> (query a -> H.HalogenM (State st) (Action act) ps msg m (Maybe a))
|
||||
-> Query query ps a
|
||||
-> H.HalogenM (State st) (Action act) ps msg m (Maybe a)
|
||||
=> (query a -> H.HalogenM (State st) (Action action) slots msg m (Maybe a))
|
||||
-> Query query slots a
|
||||
-> H.HalogenM (State st) (Action action) slots msg m (Maybe a)
|
||||
handleQuery handleQuery' = case _ of
|
||||
Send box ->
|
||||
H.HalogenM $ liftF $ H.ChildQuery box
|
||||
|
@ -209,21 +212,21 @@ handleQuery handleQuery' = case _ of
|
|||
handleQuery' query
|
||||
|
||||
handleAction
|
||||
:: forall st act ps msg m
|
||||
:: forall st action slots msg m
|
||||
. MonadAff m
|
||||
=> Row.Lacks "debounceRef" st
|
||||
=> Row.Lacks "visibility" st
|
||||
=> Row.Lacks "highlightedIndex" st
|
||||
=> (act -> H.HalogenM (State st) (Action act) ps msg m Unit)
|
||||
-> (Message -> H.HalogenM (State st) (Action act) ps msg m Unit)
|
||||
-> Action act
|
||||
-> H.HalogenM (State st) (Action act) ps msg m Unit
|
||||
handleAction handleAction' handleMessage = case _ of
|
||||
=> (action -> H.HalogenM (State st) (Action action) slots msg m Unit)
|
||||
-> (Event -> H.HalogenM (State st) (Action action) slots msg m Unit)
|
||||
-> Action action
|
||||
-> H.HalogenM (State st) (Action action) slots msg m Unit
|
||||
handleAction handleAction' handleEvent = case _ of
|
||||
Initialize mbAction -> do
|
||||
ref <- H.liftEffect $ Ref.new Nothing
|
||||
H.modify_ _ { debounceRef = Just ref }
|
||||
for_ mbAction handle
|
||||
|
||||
for_ mbAction handleAction'
|
||||
|
||||
Search str -> do
|
||||
st <- H.get
|
||||
ref <- H.liftEffect $ map join $ traverse Ref.read st.debounceRef
|
||||
|
@ -244,7 +247,7 @@ handleAction handleAction' handleMessage = case _ of
|
|||
void $ H.liftEffect $ traverse_ (Ref.write Nothing) st.debounceRef
|
||||
H.modify_ _ { highlightedIndex = Just 0 }
|
||||
newState <- H.get
|
||||
handleMessage $ Searched newState.search
|
||||
handleEvent $ Searched newState.search
|
||||
|
||||
void $ H.liftEffect $ traverse_ (Ref.write $ Just { var, fiber }) st.debounceRef
|
||||
|
||||
|
@ -269,9 +272,9 @@ handleAction handleAction' handleMessage = case _ of
|
|||
for_ mbEv (H.liftEffect <<< preventDefault <<< ME.toEvent)
|
||||
st <- H.get
|
||||
when (st.visibility == On) case target of
|
||||
Index ix -> handleMessage $ Selected ix
|
||||
Next -> handleMessage $ Selected $ getTargetIndex st target
|
||||
Prev -> handleMessage $ Selected $ getTargetIndex st target
|
||||
Index ix -> handleEvent $ Selected ix
|
||||
Next -> handleEvent $ Selected $ getTargetIndex st target
|
||||
Prev -> handleEvent $ Selected $ getTargetIndex st target
|
||||
|
||||
ToggleClick ev -> do
|
||||
H.liftEffect $ preventDefault $ ME.toEvent ev
|
||||
|
@ -316,13 +319,13 @@ handleAction handleAction' handleMessage = case _ of
|
|||
st <- H.get
|
||||
when (st.visibility /= v) do
|
||||
H.modify_ _ { visibility = v, highlightedIndex = Just 0 }
|
||||
handleMessage $ VisibilityChanged v
|
||||
handleEvent $ VisibilityChanged v
|
||||
|
||||
Action act -> handleAction' act
|
||||
|
||||
where
|
||||
-- eta-expansion is necessary to avoid infinite recursion
|
||||
handle act = handleAction handleAction' handleMessage act
|
||||
handle act = handleAction handleAction' handleEvent act
|
||||
|
||||
getTargetIndex st = case _ of
|
||||
Index i -> i
|
||||
|
@ -341,6 +344,3 @@ handleAction handleAction' handleMessage = case _ of
|
|||
|
||||
lastIndex :: State st -> Int
|
||||
lastIndex = (_ - 1) <<< st.getItemCount <<< userState
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -100,15 +100,15 @@ type ItemProps props =
|
|||
-- | with `mapWithIndex`:
|
||||
-- |
|
||||
-- | ```purescript
|
||||
-- | renderItem index itemHTML =
|
||||
-- | renderItem index itemHTML =
|
||||
-- | HH.li (setItemProps index [ props ]) [ itemHTML ]
|
||||
-- |
|
||||
-- | render = renderItem `mapWithIndex` itemsArray
|
||||
-- | ```
|
||||
setItemProps
|
||||
:: forall props act
|
||||
. Int
|
||||
-> Array (HP.IProp (ItemProps props) (Action act))
|
||||
. Int
|
||||
-> Array (HP.IProp (ItemProps props) (Action act))
|
||||
-> Array (HP.IProp (ItemProps props) (Action act))
|
||||
setItemProps index = append
|
||||
[ HE.onMouseDown \ev -> Just (Select (Index index) (Just ev))
|
||||
|
@ -125,4 +125,3 @@ setContainerProps
|
|||
-> Array (HP.IProp (onMouseDown :: ME.MouseEvent | props) (Action act))
|
||||
setContainerProps = append
|
||||
[ HE.onMouseDown $ Just <<< PreventClick ]
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue