{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE MultilineStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Miso.UI.Form
(
FormProps (..)
, defaultFormProps
, FieldProps (..)
, defaultFieldProps
, form_
, field_
, 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
data FormProps action
= FormProps
{ forall action. FormProps action -> [MisoString]
formClasses :: [MisoString]
, forall action. FormProps action -> [Attribute action]
formAttrs :: [Attribute action]
}
defaultFormProps :: FormProps action
defaultFormProps :: forall action. FormProps action
defaultFormProps
= FormProps
{ formClasses :: [MisoString]
formClasses = [ MisoString
"grid", MisoString
"gap-6" ]
, formAttrs :: [Attribute action]
formAttrs = []
}
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
data FieldProps model action
= FieldProps
{ forall model action. FieldProps model action -> Maybe MisoString
fieldId :: Maybe MisoString
, 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]
}
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 = []
}
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]
]
]
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 = []
}
"""