{-# 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 :: PxRem -> Mod
width :: PxRem -> Mod
width PxRem
n =
  Class -> Mod
addClass
    (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"w" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
n)
    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
"width" PxRem
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 :: PxRem -> Mod
height :: PxRem -> Mod
height PxRem
n =
  Class -> Mod
addClass
    (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"h" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
n)
    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
"height" PxRem
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 :: PxRem -> Mod
minWidth :: PxRem -> Mod
minWidth PxRem
n =
  Class -> Mod
addClass
    (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"mw" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
n)
    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
"min-width" PxRem
n


-- | Allow height to grow to contents but not shrink any smaller than value
minHeight :: PxRem -> Mod
minHeight :: PxRem -> Mod
minHeight PxRem
n =
  Class -> Mod
addClass
    (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"mh" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
n)
    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
"min-height" PxRem
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 PxRem -> Mod
pad :: Sides PxRem -> Mod
pad (All PxRem
n) =
  Class -> Mod
addClass
    (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"pad" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
n)
    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
"padding" PxRem
n
pad (Y PxRem
n) =
  Class -> Mod
addClass
    (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"pady" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
n)
    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
"padding-top" PxRem
n
    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
"padding-bottom" PxRem
n
pad (X PxRem
n) =
  Class -> Mod
addClass
    (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"padx" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
n)
    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
"padding-left" PxRem
n
    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
"padding-right" PxRem
n
pad (XY PxRem
x PxRem
y) =
  Class -> Mod
addClass
    (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"pad" 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
"padding-left" 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
"padding-right" 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
"padding-top" 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
"padding-bottom" PxRem
y
pad (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
"pad" 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
"padding-top" 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
"padding-right" 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
"padding-bottom" 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
"padding-left" PxRem
l


-- | The space between child elements. See 'pad'
gap :: PxRem -> Mod
gap :: PxRem -> Mod
gap PxRem
n = Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"gap" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
n) 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
"gap" PxRem
n


fontSize :: PxRem -> Mod
fontSize :: PxRem -> Mod
fontSize PxRem
n = Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"fs" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
n) 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
"font-size" PxRem
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 :: PxRem -> Mod
rounded :: PxRem -> Mod
rounded PxRem
n = Class -> Mod
addClass (Class -> Mod) -> Class -> Mod
forall a b. (a -> b) -> a -> b
$ ClassName -> Class
cls (ClassName
"rnd" ClassName -> PxRem -> ClassName
forall a. ToClassName a => ClassName -> a -> ClassName
-. PxRem
n) 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-radius" PxRem
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"


{- | 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" 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


data Align
  = Center
  deriving (Int -> Align -> ShowS
[Align] -> ShowS
Align -> String
(Int -> Align -> ShowS)
-> (Align -> String) -> ([Align] -> ShowS) -> Show Align
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Align -> ShowS
showsPrec :: Int -> Align -> ShowS
$cshow :: Align -> String
show :: Align -> String
$cshowList :: [Align] -> ShowS
showList :: [Align] -> ShowS
Show, Align -> Name
(Align -> Name) -> ToClassName Align
forall a. (a -> Name) -> ToClassName a
$ctoClassName :: Align -> Name
toClassName :: Align -> Name
ToClassName, Align -> StyleValue
(Align -> StyleValue) -> ToStyleValue Align
forall a. (a -> StyleValue) -> ToStyleValue a
$ctoStyleValue :: Align -> StyleValue
toStyleValue :: Align -> StyleValue
ToStyleValue)


-- * 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
    { $sel:selector:Class :: Selector
selector = Selector -> Selector
addMedia Class
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
    { $sel:selector:Class :: Selector
selector = Selector -> Selector
addParent Class
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
    { $sel:selector:Class :: Selector
selector = Selector -> Selector
addToSelector Class
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'
        { $sel:classes:Attributes :: [Class]
classes = Attributes
as.classes [Class] -> [Class] -> [Class]
forall a. Semigroup a => a -> a -> a
<> (Class -> Class) -> [Class] -> [Class]
forall a b. (a -> b) -> [a] -> [b]
map Class -> Class
fc Attributes
as'.classes
        , $sel:other:Attributes :: Map Name Name
other = Attributes
as.other Map Name Name -> Map Name Name -> Map Name Name
forall a. Semigroup a => a -> a -> a
<> Attributes
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
    { $sel:classes:Attributes :: [Class]
classes = Class
c Class -> [Class] -> [Class]
forall a. a -> [a] -> [a]
: Attributes
attributes.classes
    , $sel:other:Attributes :: 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) []


-- | 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{$sel:properties:Class :: Styles
properties = Name -> StyleValue -> Styles -> Styles
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Name
n (val -> StyleValue
forall a. ToStyleValue a => a -> StyleValue
toStyleValue val
v) Class
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 -.