reflex-dom-contrib 0.3 → 0.4
raw patch · 3 files changed
+94/−32 lines, 3 filesdep ~bifunctorsdep ~ghcjs-domdep ~time
Dependency ranges changed: bifunctors, ghcjs-dom, time, transformers
Files
- reflex-dom-contrib.cabal +5/−5
- src/Reflex/Dom/Contrib/Widgets/Common.hs +41/−0
- src/Reflex/Dom/Contrib/Widgets/Modal.hs +48/−27
reflex-dom-contrib.cabal view
@@ -1,5 +1,5 @@ name: reflex-dom-contrib-version: 0.3+version: 0.4 synopsis: A playground for experimenting with infrastructure and common code for reflex applications description: This library is intended to be a public playground for developing infrastructure, higher level APIs, and widget@@ -46,11 +46,11 @@ build-depends: aeson >= 0.8 && < 0.11, base >= 4.6 && < 4.9,- bifunctors >= 4.0 && < 5.1,+ bifunctors >= 4.0 && < 5.2, bytestring >= 0.10 && < 0.11, containers >= 0.5 && < 0.6, data-default >= 0.5 && < 0.6,- ghcjs-dom >= 0.1 && < 0.2,+ ghcjs-dom >= 0.1 && < 0.3, http-types >= 0.8 && < 0.10, lens >= 4.9 && < 4.14, mtl >= 2.0 && < 2.3,@@ -61,8 +61,8 @@ safe >= 0.3 && < 0.4, string-conv >= 0.1 && < 0.2, text >= 1.2 && < 1.3,- time >= 1.5 && < 1.6,- transformers >= 0.4 && < 0.5+ time >= 1.5 && < 1.7,+ transformers >= 0.4 && < 0.6 if impl(ghcjs) build-depends:
src/Reflex/Dom/Contrib/Widgets/Common.hs view
@@ -410,6 +410,47 @@ ------------------------------------------------------------------------------+-- | Returns a unit event that fires when the widget loses focus or enter is+-- pressed. This function does not tagDyn the widget's value like+-- blurOrEnter.+blurOrEnterEvent :: Reflex t => HtmlWidget t a -> Event t ()+blurOrEnterEvent w = leftmost+ [ () <$ (ffilter (==13) $ _hwidget_keypress w)+ , () <$ (ffilter not $ updated $ _hwidget_hasFocus w)+ ]+++------------------------------------------------------------------------------+-- | Allows you to restrict when a widget fires and only allow valid values to+-- appear. If an invalid value is entered, it will revert to the last known+-- good value when the restrict event fires.+enforcingWidget+ :: MonadWidget t m+ => (HtmlWidget t (Maybe a) -> Event t ())+ -> GWidget t m (Maybe a)+ -> GWidget t m a+enforcingWidget restrictEvent wFunc cfg = do+ rec+ let iv = Just $ _widgetConfig_initialValue cfg+ newSetValue = leftmost [ Just <$> _widgetConfig_setValue cfg+ , Just <$> resetEvent+ ]+ w <- wFunc $ WidgetConfig newSetValue iv+ (_widgetConfig_attributes cfg)+ let eMay = tag (current $ value w) $ restrictEvent w+ e = fmapMaybe id eMay+ v <- holdDyn (_widgetConfig_initialValue cfg) e+ let resetEvent = tag (current v) $ ffilter isNothing eMay+ return $ HtmlWidget { _hwidget_value = v+ , _hwidget_change = e+ , _hwidget_keypress = _hwidget_keypress w+ , _hwidget_keydown = _hwidget_keydown w+ , _hwidget_keyup = _hwidget_keyup w+ , _hwidget_hasFocus = _hwidget_hasFocus w+ }+++------------------------------------------------------------------------------ -- | Allows you to restrict when a widget fires. For instance, -- @restrictWidget blurOrEnter@ restricts a widget so it only fires on blur -- or when enter is pressed.
src/Reflex/Dom/Contrib/Widgets/Modal.hs view
@@ -15,6 +15,7 @@ module Reflex.Dom.Contrib.Widgets.Modal where ------------------------------------------------------------------------------+import Data.Bifunctor import Data.Either import Data.Map (Map) import Data.Monoid@@ -26,60 +27,80 @@ --------------------------------------------------------------------------------- | When the hiding strategy is RemoveFromDOM, the widget adds and removes--- the modal markup from the DOM when the modal is opened and closed. For--- @DisplayNone@ and @VisibilityInvisible@ the modal markup is always kept in--- the DOM and visibility is controlled by setting the style to @display:none@--- or @visibility:invisible@ respectively. @DisplayNone@ causes the elements--- to be completely taken out of the document flow. This means that widgets--- in the modal will only be able to get things like height when the modal is--- visible. Using @VisibilityInvisible@ gets around this limitation.+-- | The hiding strategies DisplayNone and VisibilityInvisible control+-- visibility by setting the style to @display:none@ or @visibility:invisible@+-- respectively. @DisplayNone@ causes the elements to remain in the DOM but+-- be taken out of the document flow. This means that widgets in the modal+-- will only be able to get things like height when the modal is visible.+-- Using @VisibilityInvisible@ makes height information available even when+-- modal is not visible. data HidingStrategy = DisplayNone | VisibilityInvisible- | RemoveFromDOM deriving (Eq,Show,Ord,Enum,Bounded) data ModalConfig = ModalConfig- { modalHidingStrategy :: HidingStrategy- , modalAttributes :: Map String String+ { modalAttributes :: Map String String -- ^ Attributes to put on the modal's outermost div } -------------------------------------------------------------------------------modal+-- | Implements a modal that stays in the DOM but is hidden with either+-- visibility:hidden or display:none when not displayed.+hidingModal :: MonadWidget t m- => ModalConfig+ => HidingStrategy+ -> ModalConfig -> Event t Bool -- ^ Event to open and/or close the model- -> m (Event t a, Event t ())+ -> m (a, Event t ()) -- ^ Widget rendering the body of the modal. Returns an event with a -- success value and an event triggering the close of the modal.- -> m (Event t a)-modal cfg showm body = do+ -> m a+hidingModal strategy cfg showm body = do rec let visE = leftmost [showm, False <$ closem]- (resE, closem) <- case modalHidingStrategy cfg of- RemoveFromDOM -> do- res <- widgetHoldHelper removeFromDOMWrapper False visE- a <- extractEvent fst res- b <- extractEvent snd res- return (a,b)- _ -> go =<< holdDyn False visE+ (resE, closem) <- go =<< holdDyn False visE return resE where- removeFromDOMWrapper False = return (never, never)- removeFromDOMWrapper True = go $ constDyn True go vis = do attrs <- mapDyn (\b -> modalAttributes cfg <> visibility b) vis elDynAttr "div" attrs body visibility True = "style" =: "display:block;" visibility False =- case modalHidingStrategy cfg of+ case strategy of VisibilityInvisible -> "style" =: "visibility:hidden; display:block;" DisplayNone -> "style" =: "display:none;"- RemoveFromDOM -> mempty+++------------------------------------------------------------------------------+-- | Implements a modal that is removed from the DOM when not displayed. This+-- involves a widgetHold and therefore this widget uses a different signature+-- than hidingModal that makes the value inside the event available to the+-- function constructing the modal.+removingModal+ :: MonadWidget t m+ => ModalConfig+ -> Event t a+ -- ^ Event to open the model+ -> (a -> m (b, Event t ()))+ -- ^ Widget rendering the body of the modal. Returns an event with a+ -- success value and an event triggering the close of the modal.+ -> m (Dynamic t (Maybe b))+removingModal cfg showm body = do+ rec let visE = leftmost [Just <$> showm, Nothing <$ closem]+ (resE, closem) <- do+ res <- widgetHoldHelper removeFromDOMWrapper Nothing visE+ a <- mapDyn fst res+ b <- extractEvent snd res+ return (a,b)+ return resE+ where+ removeFromDOMWrapper Nothing = return (Nothing, never)+ removeFromDOMWrapper (Just a) =+ elAttr "div" (modalAttributes cfg) $+ first Just <$> body a ------------------------------------------------------------------------------