bulmex 1.0.0 → 2.0.0
raw patch · 13 files changed
+547/−372 lines, 13 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Reflex.Bulmex.Load: writeReadDom :: (FromJSON a, ToJSON a, DomBuilder t m, Prerender js t m) => Text -> a -> m (Dynamic t a)
- Reflex.Bulmex.PreventDefault: elDynAttrModConf :: (DomBuilder t m, PostBuild t m) => (ElementConfig EventResult t (DomBuilderSpace m) -> ElementConfig EventResult t (DomBuilderSpace m)) -> Text -> Dynamic t (Map Text Text) -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
- Reflex.Bulmex.PreventDefault: elDynAttrPrevDef :: forall a en m t. (DomBuilder t m, PostBuild t m) => EventName en -> Text -> Dynamic t (Map Text Text) -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
- Reflex.Bulmex.Tag: Down :: ToolDirection
- Reflex.Bulmex.Tag: Lft :: ToolDirection
- Reflex.Bulmex.Tag: Rght :: ToolDirection
- Reflex.Bulmex.Tag: Top :: ToolDirection
- Reflex.Bulmex.Tag: ahref :: (DomBuilder t m, PostBuild t m) => Text -> m a -> m a
- Reflex.Bulmex.Tag: ahref' :: (DomBuilder t m, PostBuild t m) => AttrMap -> Text -> m a -> m a
- Reflex.Bulmex.Tag: ahrefDyn :: (DomBuilder t m, PostBuild t m) => Dynamic t AttrMap -> Dynamic t Text -> m a -> m a
- Reflex.Bulmex.Tag: box :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: buttons :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: column :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: columnClass :: DomBuilder t m => Text -> m a -> m a
- Reflex.Bulmex.Tag: columns :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: columnsClass :: DomBuilder t m => Text -> m a -> m a
- Reflex.Bulmex.Tag: container :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: containerClass :: DomBuilder t m => Text -> m a -> m a
- Reflex.Bulmex.Tag: content :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: control :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: controlClass :: DomBuilder t m => Text -> m a -> m a
- Reflex.Bulmex.Tag: controlDyn :: (PostBuild t m, DomBuilder t m) => Dynamic t AttrMap -> m a -> m a
- Reflex.Bulmex.Tag: data ToolDirection
- Reflex.Bulmex.Tag: defaultEl :: (arg -> arg -> arg) -> (arg -> m a -> m a) -> arg -> arg -> m a -> m a
- Reflex.Bulmex.Tag: direction :: ToolDirection -> Text
- Reflex.Bulmex.Tag: dynAttrEl :: Reflex t => (Dynamic t AttrMap -> m a -> m a) -> AttrMap -> Dynamic t AttrMap -> m a -> m a
- Reflex.Bulmex.Tag: evtText :: (DomBuilder t m, PostBuild t m, MonadHold t m) => Event t Text -> m ()
- Reflex.Bulmex.Tag: field :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: fieldClass :: DomBuilder t m => Text -> m a -> m a
- Reflex.Bulmex.Tag: fieldGrouped :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: flask :: (PostBuild t m, DomBuilder t m) => m ()
- Reflex.Bulmex.Tag: hero :: DomBuilder t m => Text -> m a -> m a
- Reflex.Bulmex.Tag: hideDiv :: (PostBuild t m, DomBuilder t m) => Dynamic t AttrMap -> Dynamic t Bool -> m a -> m a
- Reflex.Bulmex.Tag: hideDiv_ :: (PostBuild t m, DomBuilder t m) => Dynamic t Bool -> m a -> m a
- Reflex.Bulmex.Tag: hideEmptyDiv :: (Eq (f b), Alternative f, PostBuild t m, DomBuilder t m) => Dynamic t (f b) -> m a -> m a
- Reflex.Bulmex.Tag: hideEmptyDyn :: (Eq (f b), Alternative f, PostBuild t m, DomBuilder t m) => Dynamic t AttrMap -> Dynamic t (f b) -> m a -> m a
- Reflex.Bulmex.Tag: icon :: (PostBuild t m, DomBuilder t m) => Text -> m ()
- Reflex.Bulmex.Tag: iconClass :: (PostBuild t m, DomBuilder t m) => Text -> Text -> m ()
- Reflex.Bulmex.Tag: iconDyn :: (PostBuild t m, DomBuilder t m) => Dynamic t AttrMap -> Dynamic t AttrMap -> m ()
- Reflex.Bulmex.Tag: image :: DomBuilder t m => Text -> m ()
- Reflex.Bulmex.Tag: imageClass :: DomBuilder t m => Text -> Text -> m ()
- Reflex.Bulmex.Tag: labelClass :: DomBuilder t m => Text -> m a -> m a
- Reflex.Bulmex.Tag: labelEl :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: labeled' :: DomBuilder t m => m () -> m a -> m a
- Reflex.Bulmex.Tag: loadSpinner :: (DomBuilder t m) => m ()
- Reflex.Bulmex.Tag: partialDiv :: DomBuilder t m => Text -> Text -> m a -> m a
- Reflex.Bulmex.Tag: sect :: (DomBuilder t m) => m a -> m a
- Reflex.Bulmex.Tag: section :: (PostBuild t m, DomBuilder t m) => m a -> m a
- Reflex.Bulmex.Tag: sectionDyn :: (PostBuild t m, DomBuilder t m) => Dynamic t AttrMap -> m a -> m a
- Reflex.Bulmex.Tag: subtitle :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: subtitleClass :: DomBuilder t m => Text -> m a -> m a
- Reflex.Bulmex.Tag: switchDiv :: (PostBuild t m, DomBuilder t m) => Dynamic t Bool -> m () -> m a -> m a
- Reflex.Bulmex.Tag: textSpace :: DomBuilder t m => m ()
- Reflex.Bulmex.Tag: tile :: DomBuilder t m => Text -> m a -> m a
- Reflex.Bulmex.Tag: tileAncestor :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: tileChild :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: tileChildClass :: DomBuilder t m => Text -> m a -> m a
- Reflex.Bulmex.Tag: tileParent :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: tileParentClass :: DomBuilder t m => Text -> m a -> m a
- Reflex.Bulmex.Tag: tipToAttr :: ToolDirection -> Text -> AttrMap
- Reflex.Bulmex.Tag: title :: DomBuilder t m => m a -> m a
- Reflex.Bulmex.Tag: titleClazz :: DomBuilder t m => Text -> m a -> m a
- Reflex.Bulmex.Tag: tooltipText :: (PostBuild t m, DomBuilder t m) => Dynamic t Text -> m a -> m a
- Reflex.Bulmex.Tag: tooltipText' :: (PostBuild t m, DomBuilder t m) => ToolDirection -> Dynamic t Text -> m a -> m a
- Reflex.Bulmex.Tag: txtEl :: (Text -> m a -> m a) -> Text -> Text -> m a -> m a
+ Reflex.Bulmex.Event: evtText :: (DomBuilder t m, PostBuild t m, MonadHold t m) => Event t Text -> m ()
+ Reflex.Bulmex.Html: writeReadDom :: (FromJSON a, ToJSON a, DomBuilder t m, Prerender js t m) => Text -> a -> m (Dynamic t a)
+ Reflex.Bulmex.Tag.Abstract: defaultEl :: (arg -> arg -> arg) -> (arg -> m a -> m a) -> arg -> arg -> m a -> m a
+ Reflex.Bulmex.Tag.Abstract: dynAttrEl :: Reflex t => (Dynamic t AttrMap -> m a -> m a) -> AttrMap -> Dynamic t AttrMap -> m a -> m a
+ Reflex.Bulmex.Tag.Abstract: partialDiv :: DomBuilder t m => Text -> Text -> m a -> m a
+ Reflex.Bulmex.Tag.Abstract: txtEl :: (Text -> m a -> m a) -> Text -> Text -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: box :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: buttons :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: column :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: columnClass :: DomBuilder t m => Text -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: columns :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: columnsClass :: DomBuilder t m => Text -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: container :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: containerClass :: DomBuilder t m => Text -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: content :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: control :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: controlClass :: DomBuilder t m => Text -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: controlDyn :: (PostBuild t m, DomBuilder t m) => Dynamic t AttrMap -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: field :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: fieldClass :: DomBuilder t m => Text -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: fieldGrouped :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: hero :: DomBuilder t m => Text -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: labelClass :: DomBuilder t m => Text -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: labelEl :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: labeled' :: DomBuilder t m => m () -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: sect :: (DomBuilder t m) => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: section :: (PostBuild t m, DomBuilder t m) => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: sectionDyn :: (PostBuild t m, DomBuilder t m) => Dynamic t AttrMap -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: subtitle :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: subtitleClass :: DomBuilder t m => Text -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: tile :: DomBuilder t m => Text -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: tileAncestor :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: tileChild :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: tileChildClass :: DomBuilder t m => Text -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: tileParent :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: tileParentClass :: DomBuilder t m => Text -> m a -> m a
+ Reflex.Bulmex.Tag.Bulma: title :: DomBuilder t m => m a -> m a
+ Reflex.Bulmex.Tag.Bulma: titleClazz :: DomBuilder t m => Text -> m a -> m a
+ Reflex.Bulmex.Tag.Hide: hideDiv :: (PostBuild t m, DomBuilder t m) => Dynamic t AttrMap -> Dynamic t Bool -> m a -> m a
+ Reflex.Bulmex.Tag.Hide: hideDiv_ :: (PostBuild t m, DomBuilder t m) => Dynamic t Bool -> m a -> m a
+ Reflex.Bulmex.Tag.Hide: hideEmptyDiv :: (Eq (f b), Alternative f, PostBuild t m, DomBuilder t m) => Dynamic t (f b) -> m a -> m a
+ Reflex.Bulmex.Tag.Hide: hideEmptyDyn :: (Eq (f b), Alternative f, PostBuild t m, DomBuilder t m) => Dynamic t AttrMap -> Dynamic t (f b) -> m a -> m a
+ Reflex.Bulmex.Tag.Hide: switchDiv :: (PostBuild t m, DomBuilder t m) => Dynamic t Bool -> m () -> m a -> m a
+ Reflex.Bulmex.Tag.Icon: flask :: (PostBuild t m, DomBuilder t m) => m ()
+ Reflex.Bulmex.Tag.Icon: icon :: (PostBuild t m, DomBuilder t m) => Text -> m ()
+ Reflex.Bulmex.Tag.Icon: iconClass :: (PostBuild t m, DomBuilder t m) => Text -> Text -> m ()
+ Reflex.Bulmex.Tag.Icon: iconDyn :: (PostBuild t m, DomBuilder t m) => Dynamic t AttrMap -> Dynamic t AttrMap -> m ()
+ Reflex.Bulmex.Tag.Odd: ahref :: (DomBuilder t m, PostBuild t m) => Text -> m a -> m a
+ Reflex.Bulmex.Tag.Odd: ahref' :: (DomBuilder t m, PostBuild t m) => AttrMap -> Text -> m a -> m a
+ Reflex.Bulmex.Tag.Odd: ahrefDyn :: (DomBuilder t m, PostBuild t m) => Dynamic t AttrMap -> Dynamic t Text -> m a -> m a
+ Reflex.Bulmex.Tag.Odd: elDynAttrModConf :: (DomBuilder t m, PostBuild t m) => (ElementConfig EventResult t (DomBuilderSpace m) -> ElementConfig EventResult t (DomBuilderSpace m)) -> Text -> Dynamic t (Map Text Text) -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
+ Reflex.Bulmex.Tag.Odd: elDynAttrPrevDef :: forall a en m t. (DomBuilder t m, PostBuild t m) => EventName en -> Text -> Dynamic t (Map Text Text) -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
+ Reflex.Bulmex.Tag.Odd: image :: DomBuilder t m => Text -> m ()
+ Reflex.Bulmex.Tag.Odd: imageClass :: DomBuilder t m => Text -> Text -> m ()
+ Reflex.Bulmex.Tag.Odd: textSpace :: DomBuilder t m => m ()
+ Reflex.Bulmex.Tag.Tooltip: Down :: ToolDirection
+ Reflex.Bulmex.Tag.Tooltip: Lft :: ToolDirection
+ Reflex.Bulmex.Tag.Tooltip: Rght :: ToolDirection
+ Reflex.Bulmex.Tag.Tooltip: Top :: ToolDirection
+ Reflex.Bulmex.Tag.Tooltip: data ToolDirection
+ Reflex.Bulmex.Tag.Tooltip: tipToAttr :: ToolDirection -> Text -> AttrMap
+ Reflex.Bulmex.Tag.Tooltip: tooltipText :: (PostBuild t m, DomBuilder t m) => Dynamic t Text -> m a -> m a
+ Reflex.Bulmex.Tag.Tooltip: tooltipText' :: (PostBuild t m, DomBuilder t m) => ToolDirection -> Dynamic t Text -> m a -> m a
Files
- README.md +15/−1
- bulmex.cabal +9/−5
- src/Reflex/Bulmex/Event.hs +7/−2
- src/Reflex/Bulmex/Html.hs +54/−8
- src/Reflex/Bulmex/Load.hs +0/−43
- src/Reflex/Bulmex/PreventDefault.hs +0/−48
- src/Reflex/Bulmex/Tag.hs +9/−265
- src/Reflex/Bulmex/Tag/Abstract.hs +40/−0
- src/Reflex/Bulmex/Tag/Bulma.hs +165/−0
- src/Reflex/Bulmex/Tag/Hide.hs +52/−0
- src/Reflex/Bulmex/Tag/Icon.hs +46/−0
- src/Reflex/Bulmex/Tag/Odd.hs +100/−0
- src/Reflex/Bulmex/Tag/Tooltip.hs +50/−0
README.md view
@@ -1,1 +1,15 @@-# awesome-project-name+# Bulmex, reflex infused with bulma++With a bunch of helper functions such as making server side +rendering easier.+See related [blogpost](https://jappieklooster.nl/reflex-server-side-html-rendering.html).++Reflex: ++- core: https://hackage.haskell.org/package/reflex+- DOM: https://hackage.haskell.org/package/reflex-dom-core++CSS:++- Bulma: https://bulma.io/+- Baloon: https://kazzkiq.github.io/balloon.css/
bulmex.cabal view
@@ -2,12 +2,12 @@ -- -- see: https://github.com/sol/hpack ----- hash: 2b99255d36d075b833dc8c72472ac37a01a82e94c211ebc8955bb3075e4f5d12+-- hash: ff65f5447cccce6ee9bed9f2913c5cfb43a800f93be78f0fc411b1c89f46ab8b name: bulmex-version: 1.0.0+version: 2.0.0 synopsis: Reflex infused with bulma (css)-description: Please see the README on GitHub at <https://github.com/githubuser/awesome-project-name#readme>+description: Reflex infused with bulma, With a bunch of helper functions for making server side rendering easier. See related [blogpost](https://jappieklooster.nl/reflex-server-side-html-rendering.html). category: Web homepage: https://github.com/jappeace/bulmex#readme bug-reports: https://github.com/jappeace/bulmex/issues@@ -32,10 +32,14 @@ Reflex.Bulmex.Event Reflex.Bulmex.Html Reflex.Bulmex.Input.Polymorphic- Reflex.Bulmex.Load- Reflex.Bulmex.PreventDefault Reflex.Bulmex.Space Reflex.Bulmex.Tag+ Reflex.Bulmex.Tag.Abstract+ Reflex.Bulmex.Tag.Bulma+ Reflex.Bulmex.Tag.Hide+ Reflex.Bulmex.Tag.Icon+ Reflex.Bulmex.Tag.Odd+ Reflex.Bulmex.Tag.Tooltip other-modules: Paths_bulmex hs-source-dirs:
src/Reflex/Bulmex/Event.hs view
@@ -1,5 +1,6 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-} -- | Helper functions for dealing with events module Reflex.Bulmex.Event where@@ -7,6 +8,7 @@ import Control.Applicative (empty) import Control.Monad (void) import Control.Monad.IO.Class (MonadIO)+import qualified Data.Text as Text import Data.Time.Clock (NominalDiffTime) import Data.Witherable import Reflex@@ -83,3 +85,6 @@ delayed <- delay time event holdEvent defVal (leftmost [pure <$> event, empty <$ delayed]) $ maybe (pure defVal) monadFunc++evtText :: (Dom.DomBuilder t m, PostBuild t m, MonadHold t m) => Event t Text.Text -> m ()+evtText evt = Dom.dynText =<< holdDyn "" evt
src/Reflex/Bulmex/Html.hs view
@@ -7,7 +7,8 @@ -- | A root for an app, -- usefull for server side html rendering.--- has a neat api for the head tag, use this if that api your needs.+-- has a neat api for the head tag, use this if that api suits your needs.+-- For more info see blogpost: https://jappieklooster.nl/reflex-server-side-html-rendering.html module Reflex.Bulmex.Html ( htmlWidget -- * Head tag stuff@@ -21,20 +22,43 @@ -- * Defaults , defScript , defSettings+ -- * Load+ , writeReadDom ) where import Control.Lens-import Control.Monad (void)-import Data.Foldable (traverse_)-import qualified Data.Map.Strict as Map-import qualified Data.Text as Text-import GHC.Generics (Generic)+import Control.Monad (void)+import Control.Monad (join)+import Data.Aeson+import Data.Aeson.Text+import qualified Data.ByteString.Lazy as LBS+import Data.Foldable (traverse_)+import qualified Data.Map.Strict as Map+import Data.Maybe+import qualified Data.Text as Text+import Data.Text.Encoding+import qualified Data.Text.Lazy as LText+import GHC.Generics (Generic)+import JSDOM+import JSDOM.Generated.Element+import JSDOM.Generated.NonElementParentNode import Network.URI-import qualified Reflex.Dom.Builder.Class as Dom-import qualified Reflex.Dom.Widget as Dom+import Reflex+import qualified Reflex.Dom.Builder.Class as Dom+import qualified Reflex.Dom.Prerender as Dom+import qualified Reflex.Dom.Widget as Dom -- | Adds the core html tags. -- we already know most of the head.+--+-- > <html>+-- > <head>+-- > 'HeadSettings' <!-- provided settings --!>+-- > </head>+-- > <body>+-- > 'm a' <!-- provided monad --!>+-- > </body>+-- > </html> htmlWidget :: (Dom.DomBuilder t m) => HeadSettings -> m a -> m a htmlWidget settings content = Dom.el "html" $ do@@ -108,3 +132,25 @@ (Map.fromList -- bulmo [("rel", "stylesheet"), ("href", href)]) Dom.blank) $ settings ^.. head_css . traversed . to (Text.pack . show)++-- | Insert an encodable in the document body,+-- in case of the server side rendering we encode it as script tag with jsonval,+-- in case of ghcjsdom we read the value from that script tag+-- first arg is the idname to connect the two up (has to be uniq for a doc)+writeReadDom :: (FromJSON a, ToJSON a, Dom.DomBuilder t m, Dom.Prerender js t m) =>+ Text.Text -> a -> m (Dynamic t a)+writeReadDom comelid serverState =+ Dom.prerender (do+ Dom.elAttr "script" (Map.fromList [+ ("type", "application/json"),+ ("id", comelid)+ ]) $+ Dom.text $ LText.toStrict $ encodeToLazyText serverState+ pure serverState+ ) $ do+ mayDoc <- currentDocument+ mayEl' <- sequence $ (getElementById <$> mayDoc) <*> pure comelid+ mayInner <- sequence $ getInnerHTML <$> join mayEl'+ let result = (join $ decode . LBS.fromStrict . encodeUtf8 <$> mayInner)+ pure $ fromMaybe serverState -- TODO don't fail silently+ result
− src/Reflex/Bulmex/Load.hs
@@ -1,43 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}---- | Load functions-module Reflex.Bulmex.Load where--import Control.Monad (join)-import Data.Aeson-import Data.Aeson.Text-import qualified Data.ByteString.Lazy as LBS-import qualified Data.Map as Map-import Data.Maybe-import qualified Data.Text as Text-import Data.Text.Encoding-import qualified Data.Text.Lazy as LText-import JSDOM-import JSDOM.Generated.Element-import JSDOM.Generated.NonElementParentNode-import Reflex-import qualified Reflex.Dom.Builder.Class as Dom-import qualified Reflex.Dom.Prerender as Dom-import qualified Reflex.Dom.Widget.Basic as Dom---- | Insert an encodable in the document body,--- in case of the server side rendering we encode it as script tag with jsonval,--- in case of ghcjsdom we read the value from that script tag--- first arg is the idname to connect the two up (has to be uniq for a doc)-writeReadDom :: (FromJSON a, ToJSON a, Dom.DomBuilder t m, Dom.Prerender js t m) =>- Text.Text -> a -> m (Dynamic t a)-writeReadDom comelid serverState =- Dom.prerender (do- Dom.elAttr "script" (Map.fromList [- ("type", "application/json"),- ("id", comelid)- ]) $- Dom.text $ LText.toStrict $ encodeToLazyText serverState- pure serverState- ) $ do- mayDoc <- currentDocument- mayEl' <- sequence $ (getElementById <$> mayDoc) <*> pure comelid- mayInner <- sequence $ getInnerHTML <$> join mayEl'- let result = (join $ decode . LBS.fromStrict . encodeUtf8 <$> mayInner)- pure $ fromMaybe serverState -- TODO don't fail silently- result
− src/Reflex/Bulmex/PreventDefault.hs
@@ -1,48 +0,0 @@-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}---- | ripped from https://gist.github.com/3noch/134b1ee7fa48c347be9d164c3fac4ef7-module Reflex.Bulmex.PreventDefault where--import Control.Lens ((%~), (.~))-import Data.Map (Map)-import Data.Proxy (Proxy (..))-import Data.Text (Text)-import Reflex.Dom.Core---- | Like 'elDynAttr'' but configures "prevent default" on the given event.-elDynAttrPrevDef ::- forall a en m t. (DomBuilder t m, PostBuild t m)- => EventName en -- ^ Event on the element to configure with 'preventDefault'- -> Text -- ^ Element tag- -> Dynamic t (Map Text Text) -- ^ Element attributes- -> m a -- ^ Child of element- -> m (Element EventResult (DomBuilderSpace m) t, a) -- An element and the result of the child-elDynAttrPrevDef ev =- elDynAttrModConf- (\elCfg ->- elCfg &- elementConfig_eventSpec %~- addEventSpecFlags- (Proxy :: Proxy (DomBuilderSpace m))- ev- (const preventDefault))---- | Like 'elDynAttr'' but allows you to modify the element configuration.------ Special thanks to @luigy: https://gist.github.com/luigy/b49ce04de8462e594c9c2b5b455ae5a5#file-foo-hs-elDynAttrModConf ::- (DomBuilder t m, PostBuild t m)- => (ElementConfig EventResult t (DomBuilderSpace m) -> ElementConfig EventResult t (DomBuilderSpace m))- -> Text- -> Dynamic t (Map Text Text)- -> m a- -> m (Element EventResult (DomBuilderSpace m) t, a)-elDynAttrModConf f elementTag attrs child = do- modifyAttrs <- dynamicAttributesToModifyAttributes attrs- let cfg =- def & modifyAttributes .~ fmapCheap mapKeysToAttributeName modifyAttrs- result <- element elementTag (f cfg) child- postBuild <- getPostBuild- notReadyUntil postBuild- pure result
src/Reflex/Bulmex/Tag.hs view
@@ -1,266 +1,10 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes #-}---- | bulma divs-module Reflex.Bulmex.Tag where--import Control.Applicative-import Data.Bool-import qualified Data.Map.Strict as Map-import qualified Data.Text as Text-import Reflex-import Reflex.Bulmex.Attr-import Reflex.Bulmex.Space-import qualified Reflex.Dom.Builder.Class as Dom-import qualified Reflex.Dom.Widget as Dom-import qualified Reflex.Tags as T--container :: Dom.DomBuilder t m => m a -> m a-container = containerClass mempty--containerClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a-containerClass = partialDiv "container"--partialDiv :: Dom.DomBuilder t m => Text.Text -> Text.Text -> m a -> m a-partialDiv = txtEl T.divClass--txtEl :: (Text.Text -> m a -> m a) -> Text.Text -> Text.Text -> m a -> m a-txtEl = defaultEl spaceJoin---- | allows us to set a default value for tags by defining a join function--- not a monoid because often it does it wrong, text needs a space--- for example in case of classes, and the default map monoid is broken-defaultEl :: (arg -> arg -> arg) -> (arg -> m a -> m a) -> arg -> arg -> m a -> m a-defaultEl monoidF elF a b = elF $ monoidF a b--buttons :: Dom.DomBuilder t m => m a -> m a-buttons = T.divClass "buttons"---- | kindoff hard to set an image tag in reflex-image :: Dom.DomBuilder t m => Text.Text -> m()-image url = T.imgAttr (Map.singleton "src" url) Dom.blank---- | first class second src-imageClass :: Dom.DomBuilder t m => Text.Text -> Text.Text -> m()-imageClass clazz url = T.imgAttr (Map.fromList [("src",url), ("class", clazz)]) Dom.blank---- | bulma hero sturcture--- | <section class="hero">--- | <div class="hero-body">--- | <div class="container">-hero :: Dom.DomBuilder t m => Text.Text -> m a -> m a-hero styles =- txtEl T.sectionClass "hero" styles . T.divClass "hero-body" . container--content :: Dom.DomBuilder t m => m a -> m a-content = T.divClass "content"--sect :: (Dom.DomBuilder t m) => m a -> m a-sect = T.divClass "section"--section :: (PostBuild t m, Dom.DomBuilder t m) => m a -> m a-section = sectionDyn $ constDyn mempty--sectionDyn ::- (PostBuild t m, Dom.DomBuilder t m) => Dynamic t AttrMap -> m a -> m a-sectionDyn =- dynAttrEl (\a b -> T.divDynAttr a $ container b) $ classAttr "section"--columns :: Dom.DomBuilder t m => m a -> m a-columns = columnsClass mempty--column :: Dom.DomBuilder t m => m a -> m a-column = columnClass mempty--columnsClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a-columnsClass = partialDiv "columns"--columnClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a-columnClass = partialDiv "column"--control :: Dom.DomBuilder t m => m a -> m a-control = controlClass mempty--controlClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a-controlClass = partialDiv "control"--controlDyn ::- (PostBuild t m, Dom.DomBuilder t m) => Dynamic t AttrMap -> m a -> m a-controlDyn = dynAttrEl T.divDynAttr $ classAttr "control"--tile :: Dom.DomBuilder t m => Text.Text -> m a -> m a-tile = partialDiv "tile"--tileChild :: Dom.DomBuilder t m => m a -> m a-tileChild = tileChildClass mempty--tileChildClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a-tileChildClass = txtEl tile "is-child"--tileParentClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a-tileParentClass = txtEl tile "is-parent"--tileParent :: Dom.DomBuilder t m => m a -> m a-tileParent = tileParentClass mempty--tileAncestor :: Dom.DomBuilder t m => m a -> m a-tileAncestor = tile "is-ancestor"--dynAttrEl ::- Reflex t- => (Dynamic t AttrMap -> m a -> m a)- -> AttrMap- -> Dynamic t AttrMap- -> m a- -> m a-dynAttrEl f = defaultEl ((<*>) . (<$>) attrUnion) f . constDyn--field :: Dom.DomBuilder t m => m a -> m a-field = fieldClass mempty--fieldClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a-fieldClass = partialDiv "field"--fieldGrouped :: Dom.DomBuilder t m => m a -> m a-fieldGrouped = fieldClass "is-grouped"--title :: Dom.DomBuilder t m => m a -> m a-title = titleClazz "is-1"--titleClazz :: Dom.DomBuilder t m => Text.Text -> m a -> m a-titleClazz = txtEl T.h1Class "title"--subtitle :: Dom.DomBuilder t m => m a -> m a-subtitle = subtitleClass "is-3"--subtitleClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a-subtitleClass = txtEl T.h2Class "subtitle"--box :: Dom.DomBuilder t m => m a -> m a-box = T.divClass "box"--evtText :: (Dom.DomBuilder t m, PostBuild t m, MonadHold t m) => Event t Text.Text -> m ()-evtText evt = Dom.dynText =<< holdDyn "" evt---labeled' :: Dom.DomBuilder t m => m () -> m a -> m a-labeled' labelM inputM = do- labelEl labelM- control inputM---- | named labelEl cause didn't want to fix name clashes-labelEl :: Dom.DomBuilder t m => m a -> m a-labelEl = labelClass mempty--labelClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a-labelClass = txtEl T.labelClass "label"--data ToolDirection- = Top -- top is graphic bugged- | Lft- | Rght- | Down---- | balloon css, for example: https://cdnjs.cloudflare.com/ajax/libs/balloon-css/0.5.0/balloon.min.css-tooltipText ::- (PostBuild t m, Dom.DomBuilder t m) => Dynamic t Text.Text -> m a -> m a-tooltipText = tooltipText' Rght--tooltipText' ::- (PostBuild t m, Dom.DomBuilder t m)- => ToolDirection- -> Dynamic t Text.Text- -> m a- -> m a-tooltipText' dir tipDyn monad = T.spanDynAttr (tipToAttr dir <$> tipDyn) $ monad--tipToAttr :: ToolDirection -> Text.Text -> AttrMap-tipToAttr dir "" = tipToAttr dir "-"-tipToAttr dir tip =- Map.fromList [("data-balloon", tip), ("data-balloon-pos", direction dir)]--direction :: ToolDirection -> Text.Text-direction Top = "top"-direction Lft = "left"-direction Rght = "right"-direction Down = "down"--icon :: (PostBuild t m, Dom.DomBuilder t m) => Text.Text -> m ()-icon = iconClass ""---- | second is name-iconClass ::- (PostBuild t m, Dom.DomBuilder t m) => Text.Text -> Text.Text -> m ()-iconClass wrapClass =- iconDyn (constDyn (classAttr wrapClass)) . constDyn . classAttr--iconDyn ::- (PostBuild t m, Dom.DomBuilder t m)- => Dynamic t AttrMap- -> Dynamic t AttrMap- -> m ()-iconDyn wrapClass mdiClass = do- textSpace- T.spanDynAttr (attrUnion (classAttr "icon") <$> wrapClass) $- T.iDynAttr (Map.unionWith (<>) (classAttr "mdi mdi-") <$> mdiClass) $- Dom.blank- textSpace---- | sometimes you just need 2 pieces of text to seperate with a space-textSpace :: Dom.DomBuilder t m => m ()-textSpace = Dom.text space--flask :: (PostBuild t m, Dom.DomBuilder t m) => m ()-flask = icon "flask"---- | a html tag that accepts any text into it's href value-ahref :: (Dom.DomBuilder t m, PostBuild t m) => Text.Text -> m a -> m a-ahref = ahref' mempty--ahref' :: (Dom.DomBuilder t m, PostBuild t m) => AttrMap -> Text.Text -> m a -> m a-ahref' uno = ahrefDyn (constDyn uno) . constDyn--ahrefDyn :: (Dom.DomBuilder t m, PostBuild t m) => Dynamic t AttrMap -> Dynamic t Text.Text -> m a -> m a-ahrefDyn uno txt = T.aDynAttr $ (attrUnion <$> uno) <*> (Map.singleton "href" <$> txt)--switchDiv ::- (PostBuild t m, Dom.DomBuilder t m)- => Dynamic t Bool- -> m ()- -> m a- -> m a-switchDiv attrDyn true false = do- hideDiv_ (not <$> attrDyn) true- hideDiv_ attrDyn false---- | when dynamic is true ishidden will be added, else the attrmap is used-hideDiv ::- (PostBuild t m, Dom.DomBuilder t m)- => Dynamic t AttrMap- -> Dynamic t Bool- -> m a- -> m a-hideDiv attrDyn hide =- T.divDynAttr $ bool <$> attrDyn <*> constDyn isHidden <*> hide--hideDiv_ :: (PostBuild t m, Dom.DomBuilder t m) => Dynamic t Bool -> m a -> m a-hideDiv_ = hideDiv $ constDyn Map.empty--loadSpinner :: (Dom.DomBuilder t m) => m ()-loadSpinner = imageClass "loadSpinner" "spinner.svg"--hideEmptyDiv ::- (Eq (f b), Alternative f, PostBuild t m, Dom.DomBuilder t m)- => Dynamic t (f b)- -> m a- -> m a-hideEmptyDiv = hideEmptyDyn $ constDyn Map.empty+module Reflex.Bulmex.Tag+ ( module X+ ) where -hideEmptyDyn ::- (Eq (f b), Alternative f, PostBuild t m, Dom.DomBuilder t m)- => Dynamic t AttrMap- -> Dynamic t (f b)- -> m a- -> m a-hideEmptyDyn dyn = hideDiv dyn . fmap ((==) empty)+import Reflex.Bulmex.Tag.Abstract as X+import Reflex.Bulmex.Tag.Bulma as X+import Reflex.Bulmex.Tag.Hide as X+import Reflex.Bulmex.Tag.Icon as X+import Reflex.Bulmex.Tag.Odd as X+import Reflex.Bulmex.Tag.Tooltip as X
+ src/Reflex/Bulmex/Tag/Abstract.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}++-- | Abstract tags, most tags have very similiar overload mechanisms+-- this provides an abstraction over that+module Reflex.Bulmex.Tag.Abstract(+ defaultEl+ , txtEl+ , dynAttrEl+ , partialDiv+ ) where++import qualified Data.Text as Text+import Reflex+import Reflex.Bulmex.Attr+import Reflex.Bulmex.Space+import qualified Reflex.Dom.Builder.Class as Dom+import qualified Reflex.Tags as T++partialDiv :: Dom.DomBuilder t m => Text.Text -> Text.Text -> m a -> m a+partialDiv = txtEl T.divClass++txtEl :: (Text.Text -> m a -> m a) -> Text.Text -> Text.Text -> m a -> m a+txtEl = defaultEl spaceJoin++-- | allows us to set a default value for tags by defining a join function+-- not a monoid because often it does it wrong, text needs a space+-- for example in case of classes, and the default map monoid is broken+defaultEl :: (arg -> arg -> arg) -> (arg -> m a -> m a) -> arg -> arg -> m a -> m a+defaultEl monoidF elF a b = elF $ monoidF a b++dynAttrEl ::+ Reflex t+ => (Dynamic t AttrMap -> m a -> m a)+ -> AttrMap+ -> Dynamic t AttrMap+ -> m a+ -> m a+dynAttrEl f = defaultEl ((<*>) . (<$>) attrUnion) f . constDyn
+ src/Reflex/Bulmex/Tag/Bulma.hs view
@@ -0,0 +1,165 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}++-- | Bulma styled tags: https://bulma.io/+module Reflex.Bulmex.Tag.Bulma+ (+ -- * Layout+ container+ , containerClass+ , hero+ , content+ , sect+ , section+ , sectionDyn+ , columns+ , column+ , columnsClass+ , columnClass+ -- * Tiles+ , tile+ , tileChild+ , tileChildClass+ , tileParentClass+ , tileParent+ , tileAncestor+ -- * Form+ , control+ , controlClass+ , controlDyn+ , buttons+ , field+ , fieldClass+ , fieldGrouped+ , labeled'+ , labelEl+ , labelClass+ -- * Title+ , title+ , titleClazz+ , subtitle+ , subtitleClass+ -- * Box+ , box+ ) where++import qualified Data.Text as Text+import Reflex+import Reflex.Bulmex.Attr+import Reflex.Bulmex.Tag.Abstract+import qualified Reflex.Dom.Builder.Class as Dom+import qualified Reflex.Tags as T++-- | Container: https://bulma.io/documentation/layout/container/+container :: Dom.DomBuilder t m => m a -> m a+container = containerClass mempty++containerClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a+containerClass = partialDiv "container"++buttons :: Dom.DomBuilder t m => m a -> m a+buttons = T.divClass "buttons"++-- | bulma hero sturcture https://bulma.io/documentation/layout/hero/+--+-- > <section class="hero">+-- > <div class="hero-body">+-- > <div class="container">++hero :: Dom.DomBuilder t m => Text.Text -> m a -> m a+hero styles =+ txtEl T.sectionClass "hero" styles . T.divClass "hero-body" . container++content :: Dom.DomBuilder t m => m a -> m a+content = T.divClass "content"++sect :: (Dom.DomBuilder t m) => m a -> m a+sect = T.divClass "section"++-- | https://bulma.io/documentation/layout/section/+section :: (PostBuild t m, Dom.DomBuilder t m) => m a -> m a+section = sectionDyn $ constDyn mempty++sectionDyn ::+ (PostBuild t m, Dom.DomBuilder t m) => Dynamic t AttrMap -> m a -> m a+sectionDyn =+ dynAttrEl (\a b -> T.divDynAttr a $ container b) $ classAttr "section"++-- | https://bulma.io/documentation/columns/+columns :: Dom.DomBuilder t m => m a -> m a+columns = columnsClass mempty++column :: Dom.DomBuilder t m => m a -> m a+column = columnClass mempty++columnsClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a+columnsClass = partialDiv "columns"++columnClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a+columnClass = partialDiv "column"++control :: Dom.DomBuilder t m => m a -> m a+control = controlClass mempty++controlClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a+controlClass = partialDiv "control"++controlDyn ::+ (PostBuild t m, Dom.DomBuilder t m) => Dynamic t AttrMap -> m a -> m a+controlDyn = dynAttrEl T.divDynAttr $ classAttr "control"++-- | https://bulma.io/documentation/layout/tiles/+tile :: Dom.DomBuilder t m => Text.Text -> m a -> m a+tile = partialDiv "tile"++tileChild :: Dom.DomBuilder t m => m a -> m a+tileChild = tileChildClass mempty++tileChildClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a+tileChildClass = txtEl tile "is-child"++tileParentClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a+tileParentClass = txtEl tile "is-parent"++tileParent :: Dom.DomBuilder t m => m a -> m a+tileParent = tileParentClass mempty++tileAncestor :: Dom.DomBuilder t m => m a -> m a+tileAncestor = tile "is-ancestor"++field :: Dom.DomBuilder t m => m a -> m a+field = fieldClass mempty++fieldClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a+fieldClass = partialDiv "field"++fieldGrouped :: Dom.DomBuilder t m => m a -> m a+fieldGrouped = fieldClass "is-grouped"++title :: Dom.DomBuilder t m => m a -> m a+title = titleClazz "is-1"++titleClazz :: Dom.DomBuilder t m => Text.Text -> m a -> m a+titleClazz = txtEl T.h1Class "title"++subtitle :: Dom.DomBuilder t m => m a -> m a+subtitle = subtitleClass "is-3"++subtitleClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a+subtitleClass = txtEl T.h2Class "subtitle"++box :: Dom.DomBuilder t m => m a -> m a+box = T.divClass "box"++labeled' :: Dom.DomBuilder t m => m () -> m a -> m a+labeled' labelM inputM = do+ labelEl labelM+ control inputM++-- | named labelEl cause didn't want to fix name clashes+labelEl :: Dom.DomBuilder t m => m a -> m a+labelEl = labelClass mempty++labelClass :: Dom.DomBuilder t m => Text.Text -> m a -> m a+labelClass = txtEl T.labelClass "label"
+ src/Reflex/Bulmex/Tag/Hide.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}++-- | A div that can hide with bulma is-hidden class+module Reflex.Bulmex.Tag.Hide where++import Control.Applicative+import Data.Bool+import qualified Data.Map.Strict as Map+import Reflex+import Reflex.Bulmex.Attr+import qualified Reflex.Dom.Builder.Class as Dom+import qualified Reflex.Tags as T++switchDiv ::+ (PostBuild t m, Dom.DomBuilder t m)+ => Dynamic t Bool+ -> m ()+ -> m a+ -> m a+switchDiv attrDyn true false = do+ hideDiv_ (not <$> attrDyn) true+ hideDiv_ attrDyn false++-- | when dynamic is true ishidden will be added, else the attrmap is used+hideDiv ::+ (PostBuild t m, Dom.DomBuilder t m)+ => Dynamic t AttrMap+ -> Dynamic t Bool+ -> m a+ -> m a+hideDiv attrDyn hide =+ T.divDynAttr $ bool <$> attrDyn <*> constDyn isHidden <*> hide++hideDiv_ :: (PostBuild t m, Dom.DomBuilder t m) => Dynamic t Bool -> m a -> m a+hideDiv_ = hideDiv $ constDyn Map.empty++hideEmptyDiv ::+ (Eq (f b), Alternative f, PostBuild t m, Dom.DomBuilder t m)+ => Dynamic t (f b)+ -> m a+ -> m a+hideEmptyDiv = hideEmptyDyn $ constDyn Map.empty++hideEmptyDyn ::+ (Eq (f b), Alternative f, PostBuild t m, Dom.DomBuilder t m)+ => Dynamic t AttrMap+ -> Dynamic t (f b)+ -> m a+ -> m a+hideEmptyDyn dyn = hideDiv dyn . fmap ((==) empty)
+ src/Reflex/Bulmex/Tag/Icon.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}++-- | Icons with material design+module Reflex.Bulmex.Tag.Icon+ (-- * Icon+ icon+ , iconClass+ , iconDyn+ ,-- * Flask+ flask+ ) where++import qualified Data.Map.Strict as Map+import qualified Data.Text as Text+import Reflex+import Reflex.Bulmex.Attr+import Reflex.Bulmex.Tag.Odd+import qualified Reflex.Dom.Builder.Class as Dom+import qualified Reflex.Dom.Widget as Dom+import qualified Reflex.Tags as T++icon :: (PostBuild t m, Dom.DomBuilder t m) => Text.Text -> m ()+icon = iconClass ""++-- | second is name+iconClass ::+ (PostBuild t m, Dom.DomBuilder t m) => Text.Text -> Text.Text -> m ()+iconClass wrapClass =+ iconDyn (constDyn (classAttr wrapClass)) . constDyn . classAttr++iconDyn ::+ (PostBuild t m, Dom.DomBuilder t m)+ => Dynamic t AttrMap+ -> Dynamic t AttrMap+ -> m ()+iconDyn wrapClass mdiClass = do+ textSpace+ T.spanDynAttr (attrUnion (classAttr "icon") <$> wrapClass) $+ T.iDynAttr (Map.unionWith (<>) (classAttr "mdi mdi-") <$> mdiClass) $+ Dom.blank+ textSpace++flask :: (PostBuild t m, Dom.DomBuilder t m) => m ()+flask = icon "flask"
+ src/Reflex/Bulmex/Tag/Odd.hs view
@@ -0,0 +1,100 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+++-- | Odd tag helpers, these have uncommen html attributes+-- They don't fit in the 'normal' pattern of Abstract+module Reflex.Bulmex.Tag.Odd+ (+ -- * Image+ image+ , imageClass+ -- * Link+ , ahref+ , ahref'+ , ahrefDyn+ -- * Space+ , textSpace+ -- * Prevent browser default+ , elDynAttrPrevDef+ , elDynAttrModConf+ ) where++import Control.Lens ((%~), (.~))+import Data.Map (Map)+import qualified Data.Map.Strict as Map+import Data.Proxy (Proxy (..))+import Data.Text (Text)+import qualified Data.Text as Text+import Reflex+import Reflex.Bulmex.Attr+import Reflex.Bulmex.Space+import qualified Reflex.Dom.Builder.Class as Dom+import Reflex.Dom.Core+import qualified Reflex.Dom.Widget as Dom+import qualified Reflex.Tags as T+++-- | kindoff hard to set an image tag in reflex+image :: Dom.DomBuilder t m => Text.Text -> m()+image url = T.imgAttr (Map.singleton "src" url) Dom.blank++-- | first class second src+imageClass :: Dom.DomBuilder t m => Text.Text -> Text.Text -> m()+imageClass clazz url = T.imgAttr (Map.fromList [("src",url), ("class", clazz)]) Dom.blank++-- | sometimes you just need 2 pieces of text to seperate with a space+textSpace :: Dom.DomBuilder t m => m ()+textSpace = Dom.text space++-- | a html tag that accepts any text into it's href value+ahref :: (Dom.DomBuilder t m, PostBuild t m) => Text.Text -> m a -> m a+ahref = ahref' mempty++ahref' :: (Dom.DomBuilder t m, PostBuild t m) => AttrMap -> Text.Text -> m a -> m a+ahref' uno = ahrefDyn (constDyn uno) . constDyn++ahrefDyn :: (Dom.DomBuilder t m, PostBuild t m) => Dynamic t AttrMap -> Dynamic t Text.Text -> m a -> m a+ahrefDyn uno txt = T.aDynAttr $ (attrUnion <$> uno) <*> (Map.singleton "href" <$> txt)++-- | From https://gist.github.com/3noch/134b1ee7fa48c347be9d164c3fac4ef7+-- Like 'elDynAttr'' but configures "prevent default" on the given event.+-- Blocks for example a context menu from poping up on right mouse click.+-- This should be used with caution, as it may be unexpected for end user.+elDynAttrPrevDef ::+ forall a en m t. (DomBuilder t m, PostBuild t m)+ => EventName en -- ^ Event on the element to configure with 'preventDefault'+ -> Text -- ^ Element tag+ -> Dynamic t (Map Text Text) -- ^ Element attributes+ -> m a -- ^ Child of element+ -> m (Element EventResult (DomBuilderSpace m) t, a) -- An element and the result of the child+elDynAttrPrevDef ev =+ elDynAttrModConf+ (\elCfg ->+ elCfg &+ elementConfig_eventSpec %~+ addEventSpecFlags+ (Proxy :: Proxy (DomBuilderSpace m))+ ev+ (const preventDefault))++-- | Like 'elDynAttr'' but allows you to modify the element configuration.+--+-- Special thanks to @luigy: https://gist.github.com/luigy/b49ce04de8462e594c9c2b5b455ae5a5#file-foo-hs+elDynAttrModConf ::+ (DomBuilder t m, PostBuild t m)+ => (ElementConfig EventResult t (DomBuilderSpace m) -> ElementConfig EventResult t (DomBuilderSpace m))+ -> Text+ -> Dynamic t (Map Text Text)+ -> m a+ -> m (Element EventResult (DomBuilderSpace m) t, a)+elDynAttrModConf f elementTag attrs child = do+ modifyAttrs <- dynamicAttributesToModifyAttributes attrs+ let cfg =+ def & modifyAttributes .~ fmapCheap mapKeysToAttributeName modifyAttrs+ result <- element elementTag (f cfg) child+ postBuild <- getPostBuild+ notReadyUntil postBuild+ pure result
+ src/Reflex/Bulmex/Tag/Tooltip.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}++-- | Tooltips with balloon css+module Reflex.Bulmex.Tag.Tooltip(+ tooltipText,+ tooltipText',+ ToolDirection(..),+ tipToAttr+ ) where++import qualified Data.Map.Strict as Map+import qualified Data.Text as Text+import Reflex+import Reflex.Bulmex.Attr+import qualified Reflex.Dom.Builder.Class as Dom+import qualified Reflex.Tags as T++data ToolDirection+ = Top -- top is graphic bugged+ | Lft+ | Rght+ | Down++-- | balloon css, for example: https://cdnjs.cloudflare.com/ajax/libs/balloon-css/0.5.0/balloon.min.css+-- uses a span underneath+tooltipText ::+ (PostBuild t m, Dom.DomBuilder t m) => Dynamic t Text.Text -> m a -> m a+tooltipText = tooltipText' Rght++-- | Allows setting of initial direction+tooltipText' ::+ (PostBuild t m, Dom.DomBuilder t m)+ => ToolDirection+ -> Dynamic t Text.Text+ -> m a+ -> m a+tooltipText' dir tipDyn monad = T.spanDynAttr (tipToAttr dir <$> tipDyn) $ monad++tipToAttr :: ToolDirection -> Text.Text -> AttrMap+tipToAttr dir "" = tipToAttr dir "-"+tipToAttr dir tip =+ Map.fromList [("data-balloon", tip), ("data-balloon-pos", direction dir)]++direction :: ToolDirection -> Text.Text+direction Top = "top"+direction Lft = "left"+direction Rght = "right"+direction Down = "down"