{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} module Shpadoinkle.Widgets.Form.Input where import Data.Coerce (Coercible, coerce) import Data.Text (Text, pack) import Data.Text.Read (double) import Shpadoinkle (Html, Prop) import Shpadoinkle.Html as Html (input, onInput, type', value) import Shpadoinkle.Widgets.Types.Core (Hygiene (Dirty)) import Shpadoinkle.Widgets.Types.Form as Form (Input (Input, _value)) import Shpadoinkle.Widgets.Types.Search (Search (Search)) type Config m a = [(Text, Prop m (Input a))] mkInput :: Text -> (Text -> a) -> (a -> Text) -> Config m a -> Input a -> Html m (Input a) mkInput t to from attrs inp = Html.input ( Html.value (from $ Form._value inp) : Html.onInput (\x _ -> Input Dirty $ to x) : Html.type' t : attrs ) [] fractional :: Fractional n => Show n => Config m n -> Input n -> Html m (Input n) fractional cfg inp = mkInput "number" to (pack . show) cfg inp where to t = case double t of Right (d,"") -> realToFrac d _ -> _value inp integral :: Integral n => Show n => Config m n -> Input n -> Html m (Input n) integral cfg inp = mkInput "number" to (pack . show) cfg inp where to t = case double t of Right (d,"") -> round d _ -> _value inp search :: Config m Search -> Input Search -> Html m (Input Search) search = mkInput "search" coerce coerce text :: forall m t. Coercible Text t => Config m t -> Input t -> Html m (Input t) text = mkInput "text" coerce coerce