{-# LANGUAGE AllowAmbiguousTypes #-}
{-# OPTIONS_GHC -Wno-orphans #-}
{-# OPTIONS_GHC -Wno-term-variable-capture #-}

module Dashi.Style.Util where

import Clay hiding (Color, cast, fullWidth, var)
import Clay qualified
import Clay.Property ()
import Clay.Render (renderRefinement)
import Clay.Selector
    ( Fix (In)
    , Path (Elem)
    , Refinement (Refinement)
    , SelectorF (SelectorF)
    , refinementFromText
    )
import Clay.Stylesheet (App (Root), Rule (Nested), key, rule, runS)
import Dashi.Style.Colour ()
import Dashi.Style.Tokens
import Dashi.Util
import Data.String (IsString (..))
import Data.Text (Text)
import Data.Text qualified as Text
import Data.Text.Lazy qualified as LazyText
import Prelude

renderStyle :: (IsString s) => Css -> s
renderStyle :: forall s. IsString s => Css -> s
renderStyle = String -> s
forall a. IsString a => String -> a
fromString (String -> s) -> (Css -> String) -> Css -> s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyText -> String
LazyText.unpack (LazyText -> String) -> (Css -> LazyText) -> Css -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Config -> [App] -> Css -> LazyText
renderWith Config
pretty []

self :: Selector
self :: Selector
self = Selector
""

ariaBusy :: Bool -> Refinement
ariaBusy :: Bool -> Refinement
ariaBusy Bool
True = Text
"aria-busy" Text -> Text -> Refinement
@= Text
"true"
ariaBusy Bool
False = Refinement -> Refinement
forall a. Not a => a -> Refinement
Clay.not (Refinement -> Refinement) -> Refinement -> Refinement
forall a b. (a -> b) -> a -> b
$ Bool -> Refinement
ariaBusy Bool
True

ariaCurrent :: Bool -> Refinement
ariaCurrent :: Bool -> Refinement
ariaCurrent Bool
True = Text
"aria-current" Text -> Text -> Refinement
@= Text
"true"
ariaCurrent Bool
False = Refinement -> Refinement
forall a. Not a => a -> Refinement
Clay.not (Refinement -> Refinement) -> Refinement -> Refinement
forall a b. (a -> b) -> a -> b
$ Bool -> Refinement
ariaCurrent Bool
True

ariaRole :: Text -> Refinement
ariaRole :: Text -> Refinement
ariaRole = (Text
"aria-role" Text -> Text -> Refinement
@=)

fullWidth :: Css
fullWidth :: Css
fullWidth = Size Percentage -> Css
forall a. Size a -> Css
width (Size Percentage -> Css) -> Size Percentage -> Css
forall a b. (a -> b) -> a -> b
$ Number -> Size Percentage
pct Number
100

fullHeight :: Css
fullHeight :: Css
fullHeight = Size Percentage -> Css
forall a. Size a -> Css
height (Size Percentage -> Css) -> Size Percentage -> Css
forall a b. (a -> b) -> a -> b
$ Number -> Size Percentage
pct Number
100

fullSize :: Css
fullSize :: Css
fullSize = do
    Css
fullWidth
    Css
fullHeight

marginAll :: Size a -> Css
marginAll :: forall a. Size a -> Css
marginAll = (Key Text
"margin" Key Text -> Size a -> Css
forall v. Val v => Key Text -> v -> Css
~::)

paddingYX :: Size a -> Size a -> Css
paddingYX :: forall a. Size a -> Size a -> Css
paddingYX Size a
y Size a
x = Key Text
"padding" Key Text -> Value -> Css
forall v. Val v => Key Text -> v -> Css
~:: forall a. Monoid a => a -> [a] -> a
intercalate @Value Value
" " [Size a -> Value
forall a. Val a => a -> Value
value Size a
y, Size a -> Value
forall a. Val a => a -> Value
value Size a
x]

paddingAll :: Size a -> Css
paddingAll :: forall a. Size a -> Css
paddingAll = (Key Text
"padding" Key Text -> Size a -> Css
forall v. Val v => Key Text -> v -> Css
~::)

borderRadiusAll :: Size a -> Css
borderRadiusAll :: forall a. Size a -> Css
borderRadiusAll = (Key Text
"border-radius" Key Text -> Size a -> Css
forall v. Val v => Key Text -> v -> Css
~::)

varName :: (IsString s, Semigroup s) => s -> s
varName :: forall s. (IsString s, Semigroup s) => s -> s
varName = (s
"--dashi-" s -> s -> s
forall a. Semigroup a => a -> a -> a
<>)

var' :: (Val v, Other v) => Text -> [v] -> v
var' :: forall v. (Val v, Other v) => Text -> [v] -> v
var' Text
name' [v]
defaults = Value -> v
forall a. Other a => Value -> a
other (Value -> v) -> (Text -> Value) -> Text -> v
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Value
forall s. IsString s => Text -> s
fromText (Text -> v) -> Text -> v
forall a b. (a -> b) -> a -> b
$ Text
"var(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
Text.intercalate Text
"," [Text]
parts Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
  where
    parts :: [Text]
parts = Text
name' Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: (Prefixed -> Text
plain (Prefixed -> Text) -> (v -> Prefixed) -> v -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Prefixed
unValue (Value -> Prefixed) -> (v -> Value) -> v -> Prefixed
forall b c a. (b -> c) -> (a -> b) -> a -> c
. v -> Value
forall a. Val a => a -> Value
value (v -> Text) -> [v] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [v]
defaults)

var :: (Val v, Other v) => Text -> [v] -> v
var :: forall v. (Val v, Other v) => Text -> [v] -> v
var = Text -> [v] -> v
forall v. (Val v, Other v) => Text -> [v] -> v
var' (Text -> [v] -> v) -> (Text -> Text) -> Text -> [v] -> v
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
forall s. (IsString s, Semigroup s) => s -> s
varName

token :: (Token t, Val (ValueType t), Other (ValueType t)) => t -> ValueType t
token :: forall t.
(Token t, Val (ValueType t), Other (ValueType t)) =>
t -> ValueType t
token t
t = Text -> [ValueType t] -> ValueType t
forall v. (Val v, Other v) => Text -> [v] -> v
var (t -> Text
forall s. (IsString s, Semigroup s) => t -> s
forall t s. (Token t, IsString s, Semigroup s) => t -> s
tokenName t
t) []

token' :: (Token t, Val (ValueType t), Other (ValueType t)) => t -> ValueType t
token' :: forall t.
(Token t, Val (ValueType t), Other (ValueType t)) =>
t -> ValueType t
token' t
t = Text -> [ValueType t] -> ValueType t
forall v. (Val v, Other v) => Text -> [v] -> v
var' (t -> Text
forall s. (IsString s, Semigroup s) => t -> s
forall t s. (Token t, IsString s, Semigroup s) => t -> s
tokenName t
t) []

colorToken :: (Token t) => t -> Clay.Color
colorToken :: forall t. Token t => t -> Color
colorToken t
t = Text -> [Color] -> Color
forall v. (Val v, Other v) => Text -> [v] -> v
var (t -> Text
forall s. (IsString s, Semigroup s) => t -> s
forall t s. (Token t, IsString s, Semigroup s) => t -> s
tokenName t
t) []

colorToken' :: (Token t) => t -> Clay.Color
colorToken' :: forall t. Token t => t -> Color
colorToken' t
t = Text -> [Color] -> Color
forall v. (Val v, Other v) => Text -> [v] -> v
var' (t -> Text
forall s. (IsString s, Semigroup s) => t -> s
forall t s. (Token t, IsString s, Semigroup s) => t -> s
tokenName t
t) []

(~:) :: Key Text -> Value -> Css
Key Text
k ~: :: Key Text -> Value -> Css
~: Value
v = Key Value -> Value -> Css
forall a. Val a => Key a -> a -> Css
key (Key Text -> Key Value
forall a b. Key a -> Key b
cast Key Text
k) Value
v

(~::) :: (Val v) => Key Text -> v -> Css
Key Text
k ~:: :: forall v. Val v => Key Text -> v -> Css
~:: v
v = Key Text
k Key Text -> Value -> Css
~: v -> Value
forall a. Val a => a -> Value
value v
v

cast :: Key a -> Key b
cast :: forall a b. Key a -> Key b
cast (Key Prefixed
k) = Prefixed -> Key b
forall a. Prefixed -> Key a
Key Prefixed
k

rawSelector :: Text -> Selector
rawSelector :: Text -> Selector
rawSelector = SelectorF Selector -> Selector
forall (f :: * -> *). f (Fix f) -> Fix f
In (SelectorF Selector -> Selector)
-> (Text -> SelectorF Selector) -> Text -> Selector
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Refinement -> Path Selector -> SelectorF Selector
forall a. Refinement -> Path a -> SelectorF a
SelectorF ([Predicate] -> Refinement
Refinement []) (Path Selector -> SelectorF Selector)
-> (Text -> Path Selector) -> Text -> SelectorF Selector
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Path Selector
forall f. Text -> Path f
Elem

rawQuery :: Text -> Css -> Css
rawQuery :: Text -> Css -> Css
rawQuery Text
t = Rule -> Css
rule (Rule -> Css) -> (Css -> Rule) -> Css -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. App -> [Rule] -> Rule
Nested (Selector -> App
Root (Selector -> App) -> Selector -> App
forall a b. (a -> b) -> a -> b
$ Text -> Selector
rawSelector Text
t) ([Rule] -> Rule) -> (Css -> [Rule]) -> Css -> Rule
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Css -> [Rule]
runS

fontList :: [Value] -> Value
fontList :: [Value] -> Value
fontList = Value -> [Value] -> Value
forall a. Monoid a => a -> [a] -> a
intercalate Value
","

instance Font Value

fontFamily' :: Value -> Css
fontFamily' :: Value -> Css
fontFamily' = [Text] -> [GenericFontFamily] -> Css
fontFamily [] ([GenericFontFamily] -> Css)
-> (Value -> [GenericFontFamily]) -> Value -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenericFontFamily -> [GenericFontFamily]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (GenericFontFamily -> [GenericFontFamily])
-> (Value -> GenericFontFamily) -> Value -> [GenericFontFamily]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> GenericFontFamily
forall a. Other a => Value -> a
other

underlinedOnHover :: Css
underlinedOnHover :: Css
underlinedOnHover = do
    Refinement
hover Refinement -> Css -> Css
& Selector
star Selector -> Css -> Css
? TextDecoration -> Css
textDecoration TextDecoration
underline
    Refinement
focusVisible Refinement -> Css -> Css
& Selector
star Selector -> Css -> Css
? TextDecoration -> Css
textDecoration TextDecoration
underline

focusVisible :: Refinement
focusVisible :: Refinement
focusVisible = Refinement
":focus-visible"

color' :: (Token t) => t -> Css
color' :: forall t. Token t => t -> Css
color' = Color -> Css
color (Color -> Css) -> (t -> Color) -> t -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. t -> Color
forall t. Token t => t -> Color
colorToken

borderColor' :: (Token t) => t -> Css
borderColor' :: forall t. Token t => t -> Css
borderColor' = Color -> Css
borderColor (Color -> Css) -> (t -> Color) -> t -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. t -> Color
forall t. Token t => t -> Color
colorToken

backgroundColor' :: (Token t) => t -> Css
backgroundColor' :: forall t. Token t => t -> Css
backgroundColor' = Color -> Css
backgroundColor (Color -> Css) -> (t -> Color) -> t -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. t -> Color
forall t. Token t => t -> Color
colorToken

paddingYX' :: SizeToken -> SizeToken -> Css
paddingYX' :: SizeToken -> SizeToken -> Css
paddingYX' SizeToken
y SizeToken
x = Size LengthUnit -> Size LengthUnit -> Css
forall a. Size a -> Size a -> Css
paddingYX (Space -> ValueType Space
forall t.
(Token t, Val (ValueType t), Other (ValueType t)) =>
t -> ValueType t
token (Space -> ValueType Space) -> Space -> ValueType Space
forall a b. (a -> b) -> a -> b
$ SizeToken -> Space
Space SizeToken
y) (Space -> ValueType Space
forall t.
(Token t, Val (ValueType t), Other (ValueType t)) =>
t -> ValueType t
token (Space -> ValueType Space) -> Space -> ValueType Space
forall a b. (a -> b) -> a -> b
$ SizeToken -> Space
Space SizeToken
x)

paddingAll' :: SizeToken -> Css
paddingAll' :: SizeToken -> Css
paddingAll' = Size LengthUnit -> Css
forall a. Size a -> Css
paddingAll (Size LengthUnit -> Css)
-> (SizeToken -> Size LengthUnit) -> SizeToken -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Space -> Size LengthUnit
Space -> ValueType Space
forall t.
(Token t, Val (ValueType t), Other (ValueType t)) =>
t -> ValueType t
token (Space -> Size LengthUnit)
-> (SizeToken -> Space) -> SizeToken -> Size LengthUnit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SizeToken -> Space
Space

marginAll' :: SizeToken -> Css
marginAll' :: SizeToken -> Css
marginAll' = Size LengthUnit -> Css
forall a. Size a -> Css
marginAll (Size LengthUnit -> Css)
-> (SizeToken -> Size LengthUnit) -> SizeToken -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Space -> Size LengthUnit
Space -> ValueType Space
forall t.
(Token t, Val (ValueType t), Other (ValueType t)) =>
t -> ValueType t
token (Space -> Size LengthUnit)
-> (SizeToken -> Space) -> SizeToken -> Size LengthUnit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SizeToken -> Space
Space

borderRadiusAll' :: SizeToken -> Css
borderRadiusAll' :: SizeToken -> Css
borderRadiusAll' = Size LengthUnit -> Css
forall a. Size a -> Css
borderRadiusAll (Size LengthUnit -> Css)
-> (SizeToken -> Size LengthUnit) -> SizeToken -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Radius -> Size LengthUnit
Radius -> ValueType Radius
forall t.
(Token t, Val (ValueType t), Other (ValueType t)) =>
t -> ValueType t
token (Radius -> Size LengthUnit)
-> (SizeToken -> Radius) -> SizeToken -> Size LengthUnit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SizeToken -> Radius
Radius

gap' :: SizeToken -> Css
gap' :: SizeToken -> Css
gap' = (Key Text
"gap" Key Text -> Size LengthUnit -> Css
forall v. Val v => Key Text -> v -> Css
~::) (Size LengthUnit -> Css)
-> (SizeToken -> Size LengthUnit) -> SizeToken -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Space -> Size LengthUnit
Space -> ValueType Space
forall t.
(Token t, Val (ValueType t), Other (ValueType t)) =>
t -> ValueType t
token (Space -> Size LengthUnit)
-> (SizeToken -> Space) -> SizeToken -> Size LengthUnit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SizeToken -> Space
Space

rowGap' :: SizeToken -> Css
rowGap' :: SizeToken -> Css
rowGap' = (Key Text
"row-gap" Key Text -> Size LengthUnit -> Css
forall v. Val v => Key Text -> v -> Css
~::) (Size LengthUnit -> Css)
-> (SizeToken -> Size LengthUnit) -> SizeToken -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Space -> Size LengthUnit
Space -> ValueType Space
forall t.
(Token t, Val (ValueType t), Other (ValueType t)) =>
t -> ValueType t
token (Space -> Size LengthUnit)
-> (SizeToken -> Space) -> SizeToken -> Size LengthUnit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SizeToken -> Space
Space

columnGap' :: SizeToken -> Css
columnGap' :: SizeToken -> Css
columnGap' = (Key Text
"column-gap" Key Text -> Size LengthUnit -> Css
forall v. Val v => Key Text -> v -> Css
~::) (Size LengthUnit -> Css)
-> (SizeToken -> Size LengthUnit) -> SizeToken -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Space -> Size LengthUnit
Space -> ValueType Space
forall t.
(Token t, Val (ValueType t), Other (ValueType t)) =>
t -> ValueType t
token (Space -> Size LengthUnit)
-> (SizeToken -> Space) -> SizeToken -> Size LengthUnit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SizeToken -> Space
Space

gridTemplateAreas :: [[Value]] -> Css
gridTemplateAreas :: [[Value]] -> Css
gridTemplateAreas [[Value]]
areas = Key Text
"grid-template-areas" Key Text -> Value -> Css
~: Value -> [Value] -> Value
forall a. Monoid a => a -> [a] -> a
intercalate Value
"\n    " (Value
"" Value -> [Value] -> [Value]
forall a. a -> [a] -> [a]
: ([Value] -> Value
areaRow ([Value] -> Value) -> [[Value]] -> [Value]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [[Value]]
areas))
  where
    areaRow :: [Value] -> Value
    areaRow :: [Value] -> Value
areaRow [] = Value
""
    areaRow [Value]
xs = Value
"'" Value -> Value -> Value
forall a. Semigroup a => a -> a -> a
<> forall a. Monoid a => a -> [a] -> a
intercalate @Value Value
" " [Value]
xs Value -> Value -> Value
forall a. Semigroup a => a -> a -> a
<> Value
"'"

fontSize' :: SizeToken -> Css
fontSize' :: SizeToken -> Css
fontSize' = Size Percentage -> Css
forall a. Size a -> Css
Clay.fontSize (Size Percentage -> Css)
-> (SizeToken -> Size Percentage) -> SizeToken -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FontSize -> Size Percentage
FontSize -> ValueType FontSize
forall t.
(Token t, Val (ValueType t), Other (ValueType t)) =>
t -> ValueType t
token (FontSize -> Size Percentage)
-> (SizeToken -> FontSize) -> SizeToken -> Size Percentage
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SizeToken -> FontSize
FontSize

isOneOf :: [Refinement] -> Refinement
isOneOf :: [Refinement] -> Refinement
isOneOf [Refinement]
refinements =
    Text -> Refinement
refinementFromText (Text -> Refinement)
-> (LazyText -> Text) -> LazyText -> Refinement
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyText -> Text
LazyText.toStrict (LazyText -> Refinement) -> LazyText -> Refinement
forall a b. (a -> b) -> a -> b
$
        LazyText
":is("
            LazyText -> LazyText -> LazyText
forall a. Semigroup a => a -> a -> a
<> LazyText -> [LazyText] -> LazyText
LazyText.intercalate LazyText
"," ((Refinement -> [LazyText]) -> [Refinement] -> [LazyText]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Refinement -> [LazyText]
renderRefinement [Refinement]
refinements)
            LazyText -> LazyText -> LazyText
forall a. Semigroup a => a -> a -> a
<> LazyText
")"

isOneOf' :: (Token t) => [t] -> Refinement
isOneOf' :: forall t. Token t => [t] -> Refinement
isOneOf' = [Refinement] -> Refinement
isOneOf ([Refinement] -> Refinement)
-> ([t] -> [Refinement]) -> [t] -> Refinement
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (t -> Refinement) -> [t] -> [Refinement]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap t -> Refinement
forall t. Token t => t -> Refinement
byToken

isOneOfAll' :: forall t. (Token t) => Refinement
isOneOfAll' :: forall t. Token t => Refinement
isOneOfAll' = [t] -> Refinement
forall t. Token t => [t] -> Refinement
isOneOf' ([t] -> Refinement) -> [t] -> Refinement
forall a b. (a -> b) -> a -> b
$ forall t l. (Token t, IsList l, Item l ~ t) => l
allTokens @t

has :: Selector -> Refinement
has :: Selector -> Refinement
has Selector
selector =
    Text -> Refinement
refinementFromText (Text -> Refinement)
-> (LazyText -> Text) -> LazyText -> Refinement
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyText -> Text
LazyText.toStrict (LazyText -> Refinement) -> LazyText -> Refinement
forall a b. (a -> b) -> a -> b
$
        LazyText
":has(" LazyText -> LazyText -> LazyText
forall a. Semigroup a => a -> a -> a
<> Selector -> LazyText
renderSelector Selector
selector LazyText -> LazyText -> LazyText
forall a. Semigroup a => a -> a -> a
<> LazyText
")"