{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} module Main where import Control.Arrow (first, second) import Control.Monad.IO.Class (liftIO) import Data.Text (Text, pack) import Shpadoinkle (Html, JSM, newTVarIO, shpadoinkle, text) import Shpadoinkle.Backend.ParDiff (ParDiffT, runParDiff) import Shpadoinkle.Html (Debounce (..), Throttle (..), button, debounce, div_, getBody, input, onClick, onInput, throttle) import Shpadoinkle.Run (runJSorWarp) type Model = (Int, Text) type App = ParDiffT Model JSM data Control m = Control (Debounce m (Model -> Model) Model) (Debounce m (Text -> Model -> Model) Model) (Throttle m (Model -> Model) Model) (Throttle m (Text -> Model -> Model) Model) view :: Control m -> Model -> Html m Model view (Control debouncer1 debouncer2 throttler1 throttler2) (count, txt) = div_ [ text ("Count: " <> pack (show count)) , div_ [ button [ onClick $ first (+ 1) ] [ text "Increment" ] ] , div_ [ button [ runThrottle throttler1 onClick $ first (+ 1) ] [ text "Increment (throttle)" ] ] , div_ [ button [ runDebounce debouncer1 onClick $ first (+ 1) ] [ text "Increment (debounce)" ] ] , div_ [ text "Debounced input", input [ runDebounce debouncer2 onInput $ second . const ] [ ] ] , div_ [ text txt ] , div_ [ text "Throttled input", input [ runThrottle throttler2 onInput $ second . const ] [ ] ] ] app :: Control App -> JSM () app control = do model <- liftIO $ newTVarIO initial shpadoinkle id runParDiff initial model (view control) getBody where initial = (0, "") main :: IO () main = do control <- Control <$> debounce 1 <*> debounce 2 <*> throttle 1 <*> throttle 2 runJSorWarp 8080 (app control)