{-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE QuasiQuotes #-} {-# OPTIONS_GHC -Wall #-} module Web.Suavemente.Input where import Control.Arrow ((&&&)) import Control.Concurrent.STM.TVar (newTVar, readTVar) import Control.Monad.State.Class (MonadState (..), modify) import Control.Monad.Trans.Class (lift) import Data.Aeson (FromJSON (..), Value, withText) import Data.Aeson.Types (Parser) import Data.Bool (bool) import Data.Colour.SRGB (Colour, sRGB24show, sRGB24read) import Data.Text (unpack) import Text.Blaze (preEscapedString, Markup, ToMarkup (..)) import Text.InterpolatedString.Perl6 (qc, q) import Web.Suavemente.Core import Web.Suavemente.Types ------------------------------------------------------------------------------ -- | Generate a new name for an HTML element. genName :: MonadState Int m => m String genName = do s <- get modify (+1) pure $ show s ------------------------------------------------------------------------------ -- | Constructor for building 'Suave' inputs that are backed by HTML elements. mkInput :: (Value -> Parser a) -> (String -> a -> Markup) -- ^ Function to construct the HTML element. The first parameter is what should be used for the element's 'id' attribute. -> a -- ^ The input's initial value. -> Suave a mkInput p f a = Suave $ do name <- genName tvar <- lift $ newTVar a pure $ Input (f name a) (getEvents p tvar name) (readTVar tvar) ------------------------------------------------------------------------------ -- | Create an input driven by an HTML slider. slider :: (ToMarkup a, Num a, FromJSON a) => String -- ^ label -> a -- ^ min -> a -- ^ max -> a -- ^ initial value -> Suave a slider label l u = mkInput parseJSON $ \name v -> preEscapedString [qc|