-----------------------------------------------------------------------------
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE MultilineStrings  #-}
{-# LANGUAGE RecordWildCards   #-}
-----------------------------------------------------------------------------
module Miso.UI.Form
  ( -- ** Props
    FormProps (..)
  , defaultFormProps
  , FieldProps (..)
  , defaultFieldProps
    -- ** Views
  , form_
  , field_
    -- ** Samples
  , formUsage
  , formSample
  , formCodeSample
  , formPropsApi
  ) where
-----------------------------------------------------------------------------
import           Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
-----------------------------------------------------------------------------
import           Miso.UI.Button
import           Miso.UI.Checkbox
import           Miso.UI.Input
import           Miso.UI.Label
import           Miso.UI.RadioGroup
import           Miso.UI.Switch
import           Miso.UI.Textarea
-----------------------------------------------------------------------------
-- | Props for 'form_'
data FormProps action
  = FormProps
  { forall action. FormProps action -> [MisoString]
formClasses :: [MisoString]
    -- ^ Extra classes appended to @form.form@ (e.g. @grid gap-6@)
  , forall action. FormProps action -> [Attribute action]
formAttrs :: [Attribute action]
  }
-----------------------------------------------------------------------------
-- | Smart constructor: vertical form grid
defaultFormProps :: FormProps action
defaultFormProps :: forall action. FormProps action
defaultFormProps
  = FormProps
  { formClasses :: [MisoString]
formClasses = [ MisoString
"grid", MisoString
"gap-6" ]
  , formAttrs :: [Attribute action]
formAttrs = []
  }
-----------------------------------------------------------------------------
-- | <https://basecoatui.com/components/form/ Form>, driven by 'FormProps'
form_
  :: FormProps action
  -> [View model action]
  -> View model action
form_ :: forall action model.
FormProps action -> [View model action] -> View model action
form_ FormProps {[MisoString]
[Attribute action]
formClasses :: forall action. FormProps action -> [MisoString]
formAttrs :: forall action. FormProps action -> [Attribute action]
formClasses :: [MisoString]
formAttrs :: [Attribute action]
..} [View model action]
kids =
  [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.form_
    ( [MisoString] -> Attribute action
forall action. [MisoString] -> Attribute action
P.classes_ (MisoString
"form" MisoString -> [MisoString] -> [MisoString]
forall a. a -> [a] -> [a]
: [MisoString]
formClasses)
    Attribute action -> [Attribute action] -> [Attribute action]
forall a. a -> [a] -> [a]
: [Attribute action]
formAttrs
    ) [View model action]
kids
-----------------------------------------------------------------------------
-- | Props for 'field_': label + control + description stack
data FieldProps model action
  = FieldProps
  { forall model action. FieldProps model action -> Maybe MisoString
fieldId :: Maybe MisoString
    -- ^ id of the labelled control (@for@ on the label)
  , forall model action.
FieldProps model action -> Maybe (View model action)
fieldLabel :: Maybe (View model action)
  , forall model action.
FieldProps model action -> Maybe (View model action)
fieldDescription :: Maybe (View model action)
  , forall model action. FieldProps model action -> [MisoString]
fieldClasses :: [MisoString]
  , forall model action. FieldProps model action -> [Attribute action]
fieldAttrs :: [Attribute action]
  }
-----------------------------------------------------------------------------
-- | Smart constructor
defaultFieldProps :: FieldProps model action
defaultFieldProps :: forall model action. FieldProps model action
defaultFieldProps
  = FieldProps
  { fieldId :: Maybe MisoString
fieldId = Maybe MisoString
forall a. Maybe a
Nothing
  , fieldLabel :: Maybe (View model action)
fieldLabel = Maybe (View model action)
forall a. Maybe a
Nothing
  , fieldDescription :: Maybe (View model action)
fieldDescription = Maybe (View model action)
forall a. Maybe a
Nothing
  , fieldClasses :: [MisoString]
fieldClasses = []
  , fieldAttrs :: [Attribute action]
fieldAttrs = []
  }
-----------------------------------------------------------------------------
-- | <https://basecoatui.com/components/field/ Field>: labelled control with
-- optional description. Children are the control(s).
field_
  :: FieldProps model action
  -> [View model action]
  -> View model action
field_ :: forall model action.
FieldProps model action -> [View model action] -> View model action
field_ FieldProps {[MisoString]
[Attribute action]
Maybe MisoString
Maybe (View model action)
fieldId :: forall model action. FieldProps model action -> Maybe MisoString
fieldLabel :: forall model action.
FieldProps model action -> Maybe (View model action)
fieldDescription :: forall model action.
FieldProps model action -> Maybe (View model action)
fieldClasses :: forall model action. FieldProps model action -> [MisoString]
fieldAttrs :: forall model action. FieldProps model action -> [Attribute action]
fieldId :: Maybe MisoString
fieldLabel :: Maybe (View model action)
fieldDescription :: Maybe (View model action)
fieldClasses :: [MisoString]
fieldAttrs :: [Attribute action]
..} [View model action]
kids =
  [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.div_
    ( [MisoString] -> Attribute action
forall action. [MisoString] -> Attribute action
P.classes_ (MisoString
"grid" MisoString -> [MisoString] -> [MisoString]
forall a. a -> [a] -> [a]
: MisoString
"gap-2" MisoString -> [MisoString] -> [MisoString]
forall a. a -> [a] -> [a]
: [MisoString]
fieldClasses)
    Attribute action -> [Attribute action] -> [Attribute action]
forall a. a -> [a] -> [a]
: [Attribute action]
fieldAttrs
    )
    ([View model action] -> View model action)
-> [View model action] -> View model action
forall a b. (a -> b) -> a -> b
$ [[View model action]] -> [View model action]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    [ [ LabelProps action -> [View model action] -> View model action
forall action model.
LabelProps action -> [View model action] -> View model action
label_ LabelProps action
forall action. LabelProps action
defaultLabelProps { labelFor = fieldId } [ View model action
l ] | Just View model action
l <- [Maybe (View model action)
fieldLabel] ]
    , [View model action]
kids
    , [ [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.p_ [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"text-muted-foreground text-sm" ] [ View model action
d ]
      | Just View model action
d <- [Maybe (View model action)
fieldDescription]
      ]
    ]
-----------------------------------------------------------------------------
-- | Compact usage example (source of the kitchen sink "Code" tab)
formUsage :: View model action
formUsage :: forall model action. View model action
formUsage =
  FormProps action -> [View model action] -> View model action
forall action model.
FormProps action -> [View model action] -> View model action
form_ FormProps action
forall action. FormProps action
defaultFormProps
  [ FieldProps model action -> [View model action] -> View model action
forall model action.
FieldProps model action -> [View model action] -> View model action
field_ FieldProps (ZonkAny 0) action
forall model action. FieldProps model action
defaultFieldProps
    { fieldId = Just "username"
    , fieldLabel = Just "Username"
    , fieldDescription = Just "This is your public display name."
    }
    [ InputProps action -> View model action
forall action model. InputProps action -> View model action
input_ InputProps action
forall action. InputProps action
defaultInputProps
      { inputId = Just "username"
      , inputPlaceholder = Just "dmjio"
      }
    ]
  , FieldProps model action -> [View model action] -> View model action
forall model action.
FieldProps model action -> [View model action] -> View model action
field_ FieldProps model action
forall model action. FieldProps model action
defaultFieldProps
    { fieldId = Just "bio"
    , fieldLabel = Just "Bio"
    }
    [ TextareaProps action -> View model action
forall action model. TextareaProps action -> View model action
textarea_ TextareaProps action
forall action. TextareaProps action
defaultTextareaProps
      { textareaId = Just "bio"
      , textareaRows = Just "3"
      }
    ]
  , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps (ZonkAny 1)
forall action. ButtonProps action
defaultButtonProps
    { buttonAttrs = [ P.type_ "submit" ] }
    [ View model action
"Submit" ]
  ]
-----------------------------------------------------------------------------
formSample :: View model action
formSample :: forall model action. View model action
formSample =
  FormProps action -> [View model action] -> View model action
forall action model.
FormProps action -> [View model action] -> View model action
form_ FormProps action
forall action. FormProps action
defaultFormProps { formClasses = [ "grid", "w-full", "max-w-sm", "gap-6" ] }
  [ FieldProps model action -> [View model action] -> View model action
forall model action.
FieldProps model action -> [View model action] -> View model action
field_ FieldProps (ZonkAny 2) action
forall model action. FieldProps model action
defaultFieldProps
    { fieldId = Just "demo-form-text"
    , fieldLabel = Just "Username"
    , fieldDescription = Just "This is your public display name."
    }
    [ InputProps action -> View model action
forall action model. InputProps action -> View model action
input_ InputProps action
forall action. InputProps action
defaultInputProps
      { inputId = Just "demo-form-text"
      , inputPlaceholder = Just "dmjio"
      }
    ]
  , FieldProps model action -> [View model action] -> View model action
forall model action.
FieldProps model action -> [View model action] -> View model action
field_ FieldProps (ZonkAny 3) action
forall model action. FieldProps model action
defaultFieldProps
    { fieldId = Just "demo-form-select"
    , fieldLabel = Just "Email"
    , fieldDescription = Just "You can manage email addresses in your email settings."
    }
    [ [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.select_
      [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.id_ MisoString
"demo-form-select" ]
      [ [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.option_ [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.value_ MisoString
"bob@example.com" ] [ View model action
"m@example.com" ]
      , [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.option_ [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.value_ MisoString
"alice@example.com" ] [ View model action
"m@google.com" ]
      , [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.option_ [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.value_ MisoString
"john@example.com" ] [ View model action
"m@support.com" ]
      ]
    ]
  , FieldProps model action -> [View model action] -> View model action
forall model action.
FieldProps model action -> [View model action] -> View model action
field_ FieldProps (ZonkAny 4) action
forall model action. FieldProps model action
defaultFieldProps
    { fieldId = Just "demo-form-textarea"
    , fieldLabel = Just "Bio"
    , fieldDescription = Just "You can @mention other users and organizations."
    }
    [ TextareaProps action -> View model action
forall action model. TextareaProps action -> View model action
textarea_ TextareaProps action
forall action. TextareaProps action
defaultTextareaProps
      { textareaId = Just "demo-form-textarea"
      , textareaPlaceholder = Just "I like to..."
      , textareaRows = Just "3"
      }
    ]
  , [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.div_
    [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"flex flex-col gap-3" ]
    [ LabelProps action -> [View model action] -> View model action
forall action model.
LabelProps action -> [View model action] -> View model action
label_ LabelProps action
forall action. LabelProps action
defaultLabelProps { labelFor = Just "demo-form-radio" }
      [ View model action
"Notify me about..." ]
    , RadioGroupProps action -> [View model action] -> View model action
forall action model.
RadioGroupProps action -> [View model action] -> View model action
radioGroup_ RadioGroupProps (ZonkAny 5)
forall action. RadioGroupProps action
defaultRadioGroupProps { radioGroupAttrs = [ P.id_ "demo-form-radio" ] }
      [ RadioProps action -> [View model action] -> View model action
forall action model.
RadioProps action -> [View model action] -> View model action
radio_ RadioProps action
forall action. RadioProps action
defaultRadioProps
        { radioName = "demo-form-radio"
        , radioValue = "1"
        , radioLabelClasses = [ "font-normal" ]
        }
        [ View model action
"All new messages" ]
      , RadioProps action -> [View model action] -> View model action
forall action model.
RadioProps action -> [View model action] -> View model action
radio_ RadioProps action
forall action. RadioProps action
defaultRadioProps
        { radioName = "demo-form-radio"
        , radioValue = "2"
        , radioLabelClasses = [ "font-normal" ]
        }
        [ View model action
"Direct messages and mentions" ]
      , RadioProps action -> [View model action] -> View model action
forall action model.
RadioProps action -> [View model action] -> View model action
radio_ RadioProps action
forall action. RadioProps action
defaultRadioProps
        { radioName = "demo-form-radio"
        , radioValue = "3"
        , radioLabelClasses = [ "font-normal" ]
        }
        [ View model action
"Nothing" ]
      ]
    ]
  , [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.div_
    [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"flex flex-row items-start gap-3 rounded-md border p-4 shadow-xs" ]
    [ CheckboxProps action -> View model action
forall action model. CheckboxProps action -> View model action
checkboxInput_ CheckboxProps action
forall action. CheckboxProps action
defaultCheckboxProps { checkboxId = Just "demo-form-checkbox" }
    , [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.div_
      [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"flex flex-col gap-1" ]
      [ LabelProps action -> [View model action] -> View model action
forall action model.
LabelProps action -> [View model action] -> View model action
label_ LabelProps action
forall action. LabelProps action
defaultLabelProps
        { labelFor = Just "demo-form-checkbox"
        , labelClasses = [ "leading-snug" ]
        }
        [ View model action
"Use different settings for my mobile devices" ]
      , [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.p_
        [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"text-muted-foreground text-sm leading-snug" ]
        [ View model action
"You can manage your mobile notifications in the mobile settings page." ]
      ]
    ]
  , [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.section_
    [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"grid gap-4" ]
    [ [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.h3_ [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"text-lg font-medium" ] [ View model action
"Email Notifications" ]
    , Bool -> View model action
forall {model} {action}. Bool -> View model action
marketingRow Bool
False
    , Bool -> View model action
forall {model} {action}. Bool -> View model action
marketingRow Bool
True
    ]
  , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps (ZonkAny 6)
forall action. ButtonProps action
defaultButtonProps
    { buttonAttrs = [ P.type_ "submit" ] }
    [ View model action
"Submit" ]
  ]
  where
    marketingRow :: Bool -> View model action
marketingRow Bool
disabled =
      [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.div_
      [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"gap-2 flex flex-row items-start justify-between rounded-lg border p-4 shadow-xs" ]
      [ [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.div_
        [ [MisoString] -> Attribute action
forall action. [MisoString] -> Attribute action
P.classes_ (MisoString
"flex" MisoString -> [MisoString] -> [MisoString]
forall a. a -> [a] -> [a]
: MisoString
"flex-col" MisoString -> [MisoString] -> [MisoString]
forall a. a -> [a] -> [a]
: MisoString
"gap-0.5" MisoString -> [MisoString] -> [MisoString]
forall a. a -> [a] -> [a]
: [ MisoString
"opacity-60" | Bool
disabled ]) ]
        [ LabelProps action -> [View model action] -> View model action
forall action model.
LabelProps action -> [View model action] -> View model action
label_ LabelProps action
forall action. LabelProps action
defaultLabelProps
          { labelFor = Just switchId
          , labelClasses = [ "leading-normal" ]
          }
          [ View model action
"Marketing emails" ]
        , [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.p_
          [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"text-muted-foreground text-sm" ]
          [ View model action
"Receive emails about new products, features, and more." ]
        ]
      , SwitchProps action -> View model action
forall action model. SwitchProps action -> View model action
switchInput_ SwitchProps action
forall action. SwitchProps action
defaultSwitchProps
        { switchId = Just switchId
        , switchDisabled = disabled
        }
      ]
      where
        switchId :: MisoString
switchId = if Bool
disabled then MisoString
"demo-form-switch-disabled" else MisoString
"demo-form-switch"
-----------------------------------------------------------------------------
formCodeSample :: View model action
formCodeSample :: forall model action. View model action
formCodeSample =
  View model action
"""
  -----------------------------------------------------------------------------
  module MyForm (formUsage) where
  -----------------------------------------------------------------------------
  import           Miso
  import qualified Miso.Html.Element as H
  import qualified Miso.Html.Property as P
  import           Miso.UI.Button
  import           Miso.UI.Checkbox
  import           Miso.UI.Input
  import           Miso.UI.Label
  import           Miso.UI.RadioGroup
  import           Miso.UI.Switch
  import           Miso.UI.Textarea
  import           Miso.UI.Form
  -----------------------------------------------------------------------------
  formUsage :: View model action
  formUsage =
    form_ defaultFormProps
    [ field_ defaultFieldProps
      { fieldId = Just "username"
      , fieldLabel = Just "Username"
      , fieldDescription = Just "This is your public display name."
      }
      [ input_ defaultInputProps
        { inputId = Just "username"
        , inputPlaceholder = Just "dmjio"
        }
      ]
    , field_ defaultFieldProps
      { fieldId = Just "bio"
      , fieldLabel = Just "Bio"
      }
      [ textarea_ defaultTextareaProps
        { textareaId = Just "bio"
        , textareaRows = Just "3"
        }
      ]
    , button_ defaultButtonProps
      { buttonAttrs = [ P.type_ "submit" ] }
      [ "Submit" ]
    ]
  """
-----------------------------------------------------------------------------
formPropsApi :: View model action
formPropsApi :: forall model action. View model action
formPropsApi =
  View model action
"""
  -- | Props for 'form_'
  data FormProps action
    = FormProps
    { formClasses :: [MisoString]
      -- ^ Extra classes appended to @form.form@ (e.g. @grid gap-6@)
    , formAttrs :: [Attribute action]
    }
  -----------------------------------------------------------------------------
  -- | Smart constructor: vertical form grid
  defaultFormProps :: FormProps action
  defaultFormProps
    = FormProps
    { formClasses = [ "grid", "gap-6" ]
    , formAttrs = []
    }
  -----------------------------------------------------------------------------
  -- | Props for 'field_': label + control + description stack
  data FieldProps model action
    = FieldProps
    { fieldId :: Maybe MisoString
      -- ^ id of the labelled control (@for@ on the label)
    , fieldLabel :: Maybe (View model action)
    , fieldDescription :: Maybe (View model action)
    , fieldClasses :: [MisoString]
    , fieldAttrs :: [Attribute action]
    }
  -----------------------------------------------------------------------------
  -- | Smart constructor
  defaultFieldProps :: FieldProps model action
  defaultFieldProps
    = FieldProps
    { fieldId = Nothing
    , fieldLabel = Nothing
    , fieldDescription = Nothing
    , fieldClasses = []
    , fieldAttrs = []
    }
  """
-----------------------------------------------------------------------------