{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DisambiguateRecordFields #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedLists #-}

module Web.View.Style where

import Data.Function ((&))
import Data.Map qualified as M
import Data.Text (Text)
import Web.View.Types


-- * Styles


-- | Set to a specific width
width :: Length -> Mod
width :: Length -> Mod
width Length
n =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"w" ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
n)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"width" Length
n
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Int Name
"flex-shrink" Int
0


-- | Set to a specific height
height :: Length -> Mod
height :: Length -> Mod
height Length
n =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"h" ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
n)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"height" Length
n
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Int Name
"flex-shrink" Int
0


-- | Allow width to grow to contents but not shrink any smaller than value
minWidth :: Length -> Mod
minWidth :: Length -> Mod
minWidth Length
n =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"mw" ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
n)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"min-width" Length
n


-- | Allow height to grow to contents but not shrink any smaller than value
minHeight :: Length -> Mod
minHeight :: Length -> Mod
minHeight Length
n =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"mh" ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
n)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"min-height" Length
n


{- | Space surrounding the children of the element

To create even spacing around and between all elements:

> col (pad 10 . gap 10) $ do
>   el_ "one"
>   el_ "two"
>   el_ "three"
-}
pad :: Sides Length -> Mod
pad :: Sides Length -> Mod
pad (All Length
n) =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"pad" ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
n)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"padding" Length
n
pad (Y Length
n) =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"pady" ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
n)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"padding-top" Length
n
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"padding-bottom" Length
n
pad (X Length
n) =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"padx" ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
n)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"padding-left" Length
n
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"padding-right" Length
n
pad (XY Length
x Length
y) =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"pad" ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
x ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
y)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"padding-left" Length
x
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"padding-right" Length
x
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"padding-top" Length
y
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"padding-bottom" Length
y
pad (TRBL Length
t Length
r Length
b Length
l) =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"pad" ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
t ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
r ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
b ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
l)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"padding-top" Length
t
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"padding-right" Length
r
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"padding-bottom" Length
b
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"padding-left" Length
l


-- | The space between child elements. See 'pad'
gap :: Length -> Mod
gap :: Length -> Mod
gap Length
n = Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"gap" ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
n) Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"gap" Length
n


fontSize :: Length -> Mod
fontSize :: Length -> Mod
fontSize Length
n = Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"fs" ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
n) Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"font-size" Length
n


-- fontFamily :: Text -> Mod
-- fontFamily t = cls1 $ Class ("font" -. n) [("font-family", pxRem n)]

-- | Set container to be a row. Favor 'Web.View.Layout.row' when possible
flexRow :: Mod
flexRow :: Mod
flexRow =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls ClassName
"row"
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Text Name
"display" Name
"flex"
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Text Name
"flex-direction" Name
"row"


-- | Set container to be a column. Favor 'Web.View.Layout.col' when possible
flexCol :: Mod
flexCol :: Mod
flexCol =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls ClassName
"col"
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Text Name
"display" Name
"flex"
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Text Name
"flex-direction" Name
"column"


-- | Adds a basic drop shadow to an element
shadow :: Mod
shadow :: Mod
shadow =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls ClassName
"shadow"
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Text Name
"box-shadow" Name
"0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)"


-- | Round the corners of the element
rounded :: Length -> Mod
rounded :: Length -> Mod
rounded Length
n = Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"rnd" ClassName -> Length -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Length
n) Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Length -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-radius" Length
n


-- | Set the background color. See 'Web.View.Types.ToColor'
bg :: (ToColor c) => c -> Mod
bg :: forall c. ToColor c => c -> Mod
bg c
c =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"bg" ClassName -> Name -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. c -> Name
forall a. ToColor a => a -> Name
colorName c
c)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> HexColor -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"background-color" (c -> HexColor
forall a. ToColor a => a -> HexColor
colorValue c
c)


-- | Set the text color. See 'Web.View.Types.ToColor'
color :: (ToColor c) => c -> Mod
color :: forall c. ToColor c => c -> Mod
color c
c = Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"clr" ClassName -> Name -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. c -> Name
forall a. ToColor a => a -> Name
colorName c
c) Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> HexColor -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"color" (c -> HexColor
forall a. ToColor a => a -> HexColor
colorValue c
c)


bold :: Mod
bold :: Mod
bold = Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls ClassName
"bold" Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Text Name
"font-weight" Name
"bold"


-- | Hide an element. See 'parent' and 'media'
hide :: Mod
hide :: Mod
hide =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls ClassName
"hide"
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Text Name
"display" Name
"none"


opacity :: Float -> Mod
opacity :: Float -> Mod
opacity Float
n =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"opacity" ClassName -> Float -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Float
n)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Float -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"opacity" Float
n


{- | Set a border around the element

> el (border 1) "all sides"
> el (border (X 1)) "only left and right"
-}
border :: Sides PxRem -> Mod
border :: Sides PxRem -> Mod
border (All PxRem
p) =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"brd" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
p)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> PxRem -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-width" PxRem
p
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Text Name
"border-style" Name
"solid"
border (Y PxRem
p) =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"brdy" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
p)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> PxRem -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-top-width" PxRem
p
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> PxRem -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-bottom-width" PxRem
p
border (X PxRem
p) =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"brdx" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
p)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> PxRem -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-left-width" PxRem
p
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> PxRem -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-right-width" PxRem
p
border (XY PxRem
x PxRem
y) =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"brd" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
x ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
y)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> PxRem -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-right-width" PxRem
x
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> PxRem -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-left-width" PxRem
x
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> PxRem -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-top-width" PxRem
y
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> PxRem -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-bottom-width" PxRem
y
border (TRBL PxRem
t PxRem
r PxRem
b PxRem
l) =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"brd" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
t ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
r ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
b ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
l)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> PxRem -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-top-width" PxRem
t
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> PxRem -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-right-width" PxRem
r
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> PxRem -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-bottom-width" PxRem
b
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> PxRem -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-left-width" PxRem
l


-- | Set a border color. See 'Web.View.Types.ToColor'
borderColor :: (ToColor c) => c -> Mod
borderColor :: forall c. ToColor c => c -> Mod
borderColor c
c =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"brdc" ClassName -> Name -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. c -> Name
forall a. ToColor a => a -> Name
colorName c
c)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> HexColor -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"border-color" (c -> HexColor
forall a. ToColor a => a -> HexColor
colorValue c
c)


{- | Use a button-like cursor when hovering over the element

Button-like elements:

> btn = pointer . bg Primary . hover (bg PrimaryLight)
>
> options = row id $ do
>   el btn "Login"
>   el btn "Sign Up"
-}
pointer :: Mod
pointer :: Mod
pointer = Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls ClassName
"pointer" Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Text Name
"cursor" Name
"pointer"


-- | Cut off the contents of the element
truncate :: Mod
truncate :: Mod
truncate =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls ClassName
"truncate"
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Text Name
"white-space" Name
"nowrap"
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Text Name
"overflow" Name
"hidden"
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& forall val. ToStyleValue val => Name -> val -> Class -> Class
prop @Text Name
"text-overflow" Name
"ellipsis"


{- | Animate changes to the given property

> el (transition 100 (Height 400)) "Tall"
> el (transition 100 (Height 100)) "Small"
-}
transition :: Ms -> TransitionProperty -> Mod
transition :: Ms -> TransitionProperty -> Mod
transition Ms
ms = \case
  (Height PxRem
n) -> Name -> PxRem -> Mod
forall {val}.
(ToClassName val, ToStyleValue val) =>
Name -> val -> Mod
trans Name
"height" PxRem
n
  (Width PxRem
n) -> Name -> PxRem -> Mod
forall {val}.
(ToClassName val, ToStyleValue val) =>
Name -> val -> Mod
trans Name
"width" PxRem
n
 where
  trans :: Name -> val -> Mod
trans Name
p val
px =
    Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
      ClassName -> Class
cls (ClassName
"t" ClassName -> val -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. val
px ClassName -> Name -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Name
p ClassName -> Ms -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Ms
ms)
        Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Ms -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"transition-duration" Ms
ms
        Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Name -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"transition-property" Name
p
        Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> val -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
p val
px


-- You MUST set the height/width manually when you attempt to transition it
data TransitionProperty
  = Width PxRem
  | Height PxRem
  deriving (Int -> TransitionProperty -> ShowS
[TransitionProperty] -> ShowS
TransitionProperty -> String
(Int -> TransitionProperty -> ShowS)
-> (TransitionProperty -> String)
-> ([TransitionProperty] -> ShowS)
-> Show TransitionProperty
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TransitionProperty -> ShowS
showsPrec :: Int -> TransitionProperty -> ShowS
$cshow :: TransitionProperty -> String
show :: TransitionProperty -> String
$cshowList :: [TransitionProperty] -> ShowS
showList :: [TransitionProperty] -> ShowS
Show)


textAlign :: Align -> Mod
textAlign :: Align -> Mod
textAlign Align
a =
  Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$
    ClassName -> Class
cls (ClassName
"ta" ClassName -> Align -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. Align
a)
      Class -> (Class -> Class) -> Class
forall a b. a -> (a -> b) -> b
& Name -> Align -> Class -> Class
forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
"text-align" Align
a


-- * Selector Modifiers


{- | Apply when hovering over an element

> el (bg Primary . hover (bg PrimaryLight)) "Hover"
-}
hover :: Mod -> Mod
hover :: Mod -> Mod
hover = Pseudo -> Mod -> Mod
applyPseudo Pseudo
Hover


-- | Apply when the mouse is pressed down on an element
active :: Mod -> Mod
active :: Mod -> Mod
active = Pseudo -> Mod -> Mod
applyPseudo Pseudo
Active


-- | Apply to even-numbered children
even :: Mod -> Mod
even :: Mod -> Mod
even = Pseudo -> Mod -> Mod
applyPseudo Pseudo
Even


-- | Apply to odd-numbered children
odd :: Mod -> Mod
odd :: Mod -> Mod
odd = Pseudo -> Mod -> Mod
applyPseudo Pseudo
Odd


{- | Apply when the Media matches the current window. This allows for responsive designs

> el (width 100 . media (MinWidth 800) (width 400))
>   "Big if window > 800"
-}
media :: Media -> Mod -> Mod
media :: Media -> Mod -> Mod
media Media
m = (Class -> Class) -> Mod -> Mod
mapModClass ((Class -> Class) -> Mod -> Mod) -> (Class -> Class) -> Mod -> Mod
forall a b. (a -> b) -> a -> b
$ \Class
c ->
  Class
c
    { selector = addMedia c.selector
    }
 where
  addMedia :: Selector -> Selector
  addMedia :: Selector -> Selector
addMedia (Selector Maybe Name
pr Maybe Pseudo
ps Maybe Media
_ ClassName
cn) = Maybe Name -> Maybe Pseudo -> Maybe Media -> ClassName -> Selector
Selector Maybe Name
pr Maybe Pseudo
ps (Media -> Maybe Media
forall a. a -> Maybe a
Just Media
m) ClassName
cn


{- | Apply when the element is somewhere inside an anscestor.

For example, the HTMX library applies an "htmx-request" class to the body when a request is pending. We can use this to create a loading indicator

> el (pad 10) $ do
>   el (parent "htmx-request" flexRow . hide) "Loading..."
>   el (parent "htmx-request" hide . flexRow) "Normal Content"
-}
parent :: Text -> Mod -> Mod
parent :: Name -> Mod -> Mod
parent Name
p = (Class -> Class) -> Mod -> Mod
mapModClass ((Class -> Class) -> Mod -> Mod) -> (Class -> Class) -> Mod -> Mod
forall a b. (a -> b) -> a -> b
$ \Class
c ->
  Class
c
    { selector = addParent c.selector
    }
 where
  addParent :: Selector -> Selector
  addParent :: Selector -> Selector
addParent (Selector Maybe Name
_ Maybe Pseudo
ps Maybe Media
m ClassName
c) = Maybe Name -> Maybe Pseudo -> Maybe Media -> ClassName -> Selector
Selector (Name -> Maybe Name
forall a. a -> Maybe a
Just Name
p) Maybe Pseudo
ps Maybe Media
m ClassName
c


-- Add a pseudo-class like Hover to your style
applyPseudo :: Pseudo -> Mod -> Mod
applyPseudo :: Pseudo -> Mod -> Mod
applyPseudo Pseudo
ps = (Class -> Class) -> Mod -> Mod
mapModClass ((Class -> Class) -> Mod -> Mod) -> (Class -> Class) -> Mod -> Mod
forall a b. (a -> b) -> a -> b
$ \Class
c ->
  Class
c
    { selector = addToSelector c.selector
    }
 where
  addToSelector :: Selector -> Selector
  addToSelector :: Selector -> Selector
addToSelector (Selector Maybe Name
pr Maybe Pseudo
_ Maybe Media
m ClassName
cn) = Maybe Name -> Maybe Pseudo -> Maybe Media -> ClassName -> Selector
Selector Maybe Name
pr (Pseudo -> Maybe Pseudo
forall a. a -> Maybe a
Just Pseudo
ps) Maybe Media
m ClassName
cn


mapModClass :: (Class -> Class) -> Mod -> Mod
mapModClass :: (Class -> Class) -> Mod -> Mod
mapModClass Class -> Class
fc Mod
fm Attributes
as =
  -- apply the function to all classes added by the mod
  -- ignore
  let as' :: Attributes
as' = Mod
fm Mod -> Mod
forall a b. (a -> b) -> a -> b
$ [Class] -> Map Name Name -> Attributes
Attributes [] []
   in Attributes
as'
        { classes = as.classes <> map fc as'.classes
        , other = as.other <> as'.other
        }


-- * Creating New Styles


{- | Add a single class

> width :: PxRem -> Mod
> width n =
>   addClass
>     $ cls ("w" -. n)
>     & prop "width" n
>     & prop @Int "flex-shrink" 0
-}
addClass :: Class -> Mod
addClass :: Class -> Mod
addClass Class
c Attributes
attributes =
  Attributes
    { classes :: [Class]
classes = Class
c Class -> [Class] -> [Class]
forall a. a -> [a] -> [a]
: Attributes
attributes.classes
    , other :: Map Name Name
other = Attributes
attributes.other
    }

-- | Construct a class from a ClassName
cls :: ClassName -> Class
cls :: ClassName -> Class
cls ClassName
n = Selector -> Styles -> Class
Class (ClassName -> Selector
selector ClassName
n) []

{- | Construct a mod from a ClassName with no CSS properties. Convenience for situations where external CSS classes need to be referenced.

> el (extClass "btn" . extClass "btn-primary") "Click me!"
-}
extClass :: ClassName -> Mod
extClass :: ClassName -> Mod
extClass = Class -> Mod
addClass (Class -> Mod) -> (ClassName -> Class) -> ClassName -> Mod
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ClassName -> Class
cls

-- | Add a property to a class
prop :: (ToStyleValue val) => Name -> val -> Class -> Class
prop :: forall val. ToStyleValue val => Name -> val -> Class -> Class
prop Name
n val
v Class
c =
  Class
c{properties = M.insert n (toStyleValue v) c.properties}


-- | Hyphneate classnames
(-.) :: (ToClassName a) => ClassName -> a -> ClassName
(ClassName Name
n) -. :: forall a. ToClassName a => ClassName -> a -> ClassName
-. a
a = Name -> ClassName
ClassName (Name -> ClassName) -> Name -> ClassName
forall a b. (a -> b) -> a -> b
$ Name
n Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
"-" Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> a -> Name
forall a. ToClassName a => a -> Name
toClassName a
a


infixl 6 -.