-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathExpandableEl.hs
66 lines (58 loc) · 2.16 KB
/
ExpandableEl.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecursiveDo #-}
{-# OPTIONS_GHC -Wall #-}
{-# OPTIONS_GHC -Wno-missing-signatures #-}
{-# OPTIONS_GHC -Wno-unused-top-binds #-}
{-# OPTIONS_GHC -Wno-name-shadowing #-}
{-# OPTIONS_GHC -Wno-unused-do-bind #-}
module ExpandableEl where
import Control.Monad.Fix (MonadFix)
import Data.Function ((&))
import Reflex.Dom (DomBuilder, Event, EventName (Click), MonadHold,
PostBuild, accum, domEvent, el', elAttr, switchDyn,
text, widgetHold, (=:))
data ElState = ElCollapsed | ElExpanded deriving (Eq, Show)
swapEl current
| ElCollapsed == current = ElExpanded
| otherwise = ElCollapsed
-- | Creates expandable widget using the `content` function
--
-- The `content` function transforms `ElState` to a corresponding widget.
-- The monadic value of the widget is an `Event` that triggers state change.
expandable :: (DomBuilder t m, MonadHold t m, MonadFix m, PostBuild t m)
=> (ElState -> m (Event t ())) -> m ()
expandable content = do
rec
clickEvDyn <- widgetHold (content ElCollapsed) (fmap content stateEv)
stateEv <- accum (&) ElCollapsed (swapEl <$ switchDyn clickEvDyn)
return ()
expandableContent tagName collapsed expanded content = do
rec
(containerEl, _) <- el' tagName $
expandable $ \case
ElCollapsed -> do
collapsed
text " ("
elAttr "a" ("class" =: "link") $ text "expand"
text ")"
return $ domEvent Click containerEl
ElExpanded -> do
(spanEl, _) <- el' "span" $ do
expanded
text " ("
elAttr "a" ("class" =: "link") $ text "collapse"
text ")"
content
return $ domEvent Click spanEl
return ()
expandableContentLi collapsed expanded content
= expandableContent "li" collapsed expanded content
expandableLi :: (DomBuilder t m, MonadHold t m, MonadFix m, PostBuild t m)
=> (ElState -> m ()) -> m ()
expandableLi content = do
rec
(liEl, _) <- el' "li" $
expandable (\state -> content state >> return (() <$ ev))
let ev = domEvent Click liEl
return ()