1
Fork 0
purescript-halogen-select/examples/Components/Dropdown.purs
Thomas Honeyman 9dacac780c
Update for Halogen 5 ()
* Remove QueryF from Select in preparation for v5 changes, as there is no longer the ability to leverage a query within ComponentHTML. Add the npm-check-updates package to dev dependencies.

* switch to variants

* Complete switch to Halogen 5

* switch examples to v5

* switch to extensible state, no comonad

* now that state can be embedded, take as an argument

* cleanup

* switch to handling messages, which addresses lingering concerns with extensibility in the components

* uncomment

* cleanup

* add default.nix file containing mkdocs

* update dependencies

* fix infinite recursion (compiler bug?)

* eta-expand instead of removing helper

* remove unused css

* Add type synonyms for simple cases

* rename RunQuery to AsAction

* allow external initialization, merge state fields

* simplify examples

* Simplify a little more

* formatting

* add finalizer to default spec

* extensible actions

* update item counts on attempted highlight

* cleanup

* polish up CSS for examples to test behavior

* switch to void
2019-04-15 19:18:42 -07:00

82 lines
2.1 KiB
Text

module Components.Dropdown where
import Prelude
import Data.Const (Const)
import Effect.Aff (Aff)
import Data.Array ((!!), mapWithIndex, length)
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Monoid (guard)
import Halogen as H
import Halogen.HTML as HH
import Internal.CSS (class_, classes_, whenElem)
import Select as S
import Select.Setters as SS
type Slot =
H.Slot S.Query' Message
type State =
( items :: Array String
, selection :: Maybe String
, buttonLabel :: String
)
data Message
= SelectionChanged (Maybe String) (Maybe String)
-- it is unnecessary to export your own input type, but doing so helps if you
-- would like to set some sensible defaults behind the scenes.
type Input =
{ items :: Array String
, buttonLabel :: String
}
input :: Input -> S.Input State
input { items, buttonLabel } =
{ inputType: S.Toggle
, search: Nothing
, debounceTime: Nothing
, getItemCount: length <<< _.items
, items
, buttonLabel
, selection: Nothing
}
spec :: S.Spec State (Const Void) Void () Message Aff
spec = S.defaultSpec { render = render, handleMessage = handleMessage }
where
handleMessage = case _ of
S.Selected ix -> do
st <- H.get
let selection = st.items !! ix
H.modify_ _ { selection = selection, visibility = S.Off }
H.raise $ SelectionChanged st.selection selection
_ -> pure unit
render st =
HH.div
[ class_ "Dropdown" ]
[ renderToggle, renderContainer ]
where
renderToggle =
HH.button
( SS.setToggleProps st [ class_ "Dropdown__toggle" ] )
[ HH.text (fromMaybe st.buttonLabel st.selection) ]
renderContainer = whenElem (st.visibility == S.On) \_ ->
HH.div
( SS.setContainerProps [ class_ "Dropdown__container" ] )
( renderItem `mapWithIndex` st.items )
where
renderItem index item =
HH.div
( SS.setItemProps index
[ classes_
[ "Dropdown__item"
, "Dropdown__item--highlighted" # guard (st.highlightedIndex == Just index)
]
]
)
[ HH.text item ]