{-# LANGUAGE OverloadedLists #-}
{-# OPTIONS_GHC -Wno-name-shadowing #-}

module Dashi.Components.Avatar where

import Clay hiding
    ( Content
    , action
    , content
    , img
    , shape
    , size
    , span_
    , transparent
    , url
    )
import Clay qualified
import Dashi.Components.Icon (Icon)
import Dashi.Prelude hiding (Image, has, rem, span, (#), (&))
import Dashi.Style.Background (BackgroundColour (BackgroundColour))
import Dashi.Style.Text (TextColour (TextColour))
import Dashi.Style.Tokens
import Dashi.Style.Util
import Miso.Html.Element (div_, img_, span_)
import Miso.Html.Property (class_, src_)

data Shape
    = Circle
    | Hexagon
    | Square
    deriving stock (Shape -> Shape -> Bool
(Shape -> Shape -> Bool) -> (Shape -> Shape -> Bool) -> Eq Shape
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Shape -> Shape -> Bool
== :: Shape -> Shape -> Bool
$c/= :: Shape -> Shape -> Bool
/= :: Shape -> Shape -> Bool
Eq, Shape
Shape -> Shape -> Bounded Shape
forall a. a -> a -> Bounded a
$cminBound :: Shape
minBound :: Shape
$cmaxBound :: Shape
maxBound :: Shape
Bounded, Int -> Shape
Shape -> Int
Shape -> [Shape]
Shape -> Shape
Shape -> Shape -> [Shape]
Shape -> Shape -> Shape -> [Shape]
(Shape -> Shape)
-> (Shape -> Shape)
-> (Int -> Shape)
-> (Shape -> Int)
-> (Shape -> [Shape])
-> (Shape -> Shape -> [Shape])
-> (Shape -> Shape -> [Shape])
-> (Shape -> Shape -> Shape -> [Shape])
-> Enum Shape
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Shape -> Shape
succ :: Shape -> Shape
$cpred :: Shape -> Shape
pred :: Shape -> Shape
$ctoEnum :: Int -> Shape
toEnum :: Int -> Shape
$cfromEnum :: Shape -> Int
fromEnum :: Shape -> Int
$cenumFrom :: Shape -> [Shape]
enumFrom :: Shape -> [Shape]
$cenumFromThen :: Shape -> Shape -> [Shape]
enumFromThen :: Shape -> Shape -> [Shape]
$cenumFromTo :: Shape -> Shape -> [Shape]
enumFromTo :: Shape -> Shape -> [Shape]
$cenumFromThenTo :: Shape -> Shape -> Shape -> [Shape]
enumFromThenTo :: Shape -> Shape -> Shape -> [Shape]
Enum)

instance Token Shape where
    tokenName :: forall s. (IsString s, Semigroup s) => Shape -> s
tokenName Shape
Circle = s
"circle"
    tokenName Shape
Hexagon = s
"hexagon"
    tokenName Shape
Square = s
"square"

data Content
    = Image MisoString
    | Icon Icon
    | Initials MisoString

data Avatar = Avatar
    { Avatar -> Shape
shape :: Shape
    , Avatar -> SizeToken
size :: SizeToken
    , Avatar -> Content
content :: Content
    }

instance Widget Avatar model action where
    widget' :: [Attribute action] -> Avatar -> View model action
widget' [Attribute action]
attrs Avatar{SizeToken
Content
Shape
shape :: Avatar -> Shape
size :: Avatar -> SizeToken
content :: Avatar -> Content
shape :: Shape
size :: SizeToken
content :: Content
..} =
        [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
span_
            (MisoString -> Attribute action
forall action. MisoString -> Attribute action
class_ MisoString
"avatar" Attribute action -> [Attribute action] -> [Attribute action]
forall a. a -> [a] -> [a]
: Shape -> Attribute action
forall t action. Token t => t -> Attribute action
forall action. Shape -> Attribute action
tokenAttr Shape
shape Attribute action -> [Attribute action] -> [Attribute action]
forall a. a -> [a] -> [a]
: SizeToken -> Attribute action
forall action. SizeToken -> Attribute action
forall t action. Token t => t -> Attribute action
tokenAttr SizeToken
size Attribute action -> [Attribute action] -> [Attribute action]
forall a. a -> [a] -> [a]
: [Attribute action]
attrs)
            [ case Content
content of
                Image MisoString
url -> MisoString -> View model action
image MisoString
url
                Icon Icon
icon -> Icon -> View model action
forall w model action.
Widget w model action =>
w -> View model action
widget Icon
icon
                Initials MisoString
str -> MisoString -> View model action
forall model action. MisoString -> View model action
text MisoString
str
            ]
      where
        image :: MisoString -> View model action
        image :: MisoString -> View model action
image = [Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
img_ ([Attribute action] -> View model action)
-> (MisoString -> [Attribute action])
-> MisoString
-> View model action
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Attribute action -> [Attribute action]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Attribute action -> [Attribute action])
-> (MisoString -> Attribute action)
-> MisoString
-> [Attribute action]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. MisoString -> Attribute action
forall action. MisoString -> Attribute action
src_
    style :: Css
style =
        Selector
".avatar" Selector -> Css -> Css
? do
            Key MisoString
"image-rendering" Key MisoString -> MisoString -> Css
-: MisoString
"pixelated"
            (SizeToken -> Css) -> Css
forall t. Token t => (t -> Css) -> Css
byTokens \SizeToken
size -> do
                let sizeEm :: Number
sizeEm = case SizeToken
size of
                        SizeToken
XSmall -> Number
1
                        SizeToken
Small -> Number
1.75
                        SizeToken
Medium -> Number
2
                        SizeToken
Large -> Number
2.5
                        SizeToken
XLarge -> Number
6
                Size LengthUnit -> Css
forall a. Size a -> Css
width (Size LengthUnit -> Css) -> Size LengthUnit -> Css
forall a b. (a -> b) -> a -> b
$ Number -> Size LengthUnit
rem Number
sizeEm
                Size LengthUnit -> Css
forall a. Size a -> Css
height (Size LengthUnit -> Css) -> Size LengthUnit -> Css
forall a b. (a -> b) -> a -> b
$ Number -> Size LengthUnit
rem Number
sizeEm
                Size LengthUnit -> Css
forall a. Size a -> Css
lineHeight (Size LengthUnit -> Css) -> Size LengthUnit -> Css
forall a b. (a -> b) -> a -> b
$ Number -> Size LengthUnit
rem Number
sizeEm
                Size LengthUnit -> Css
forall a. Size a -> Css
Clay.fontSize (Number -> Size LengthUnit
rem (Number -> Size LengthUnit) -> Number -> Size LengthUnit
forall a b. (a -> b) -> a -> b
$ Number
sizeEm Number -> Number -> Number
forall a. Fractional a => a -> a -> a
/ Number
3)
            Overflow -> Css
overflow Overflow
forall a. Hidden a => a
hidden
            BackgroundColour -> Css
forall t. Token t => t -> Css
backgroundColor' (Appearance -> BackgroundColour
BackgroundColour Appearance
Primary)
            FontWeight -> Css
fontWeight (FontWeight -> Css) -> FontWeight -> Css
forall a b. (a -> b) -> a -> b
$ Integer -> FontWeight
weight Integer
600
            TextColour -> Css
forall t. Token t => t -> Css
color' (TextColour -> Css) -> TextColour -> Css
forall a b. (a -> b) -> a -> b
$ Appearance -> TextColour
TextColour Appearance
Subtle
            Display -> Css
display Display
inlineFlex
            AlignItemsValue -> Css
alignItems AlignItemsValue
forall a. Center a => a
center
            JustifyContentValue -> Css
justifyContent JustifyContentValue
forall a. Center a => a
center
            Selector
Clay.img Selector -> Css -> Css
? do
                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
                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
            Shape -> Refinement
forall t. Token t => t -> Refinement
byToken Shape
Square Refinement -> Css -> Css
& do
                SizeToken -> Css
borderRadiusAll' SizeToken
Medium
            Shape -> Refinement
forall t. Token t => t -> Refinement
byToken Shape
Circle Refinement -> Css -> Css
& do
                Size LengthUnit -> Css
forall a. Size a -> Css
borderRadiusAll (Size LengthUnit -> Css) -> Size LengthUnit -> Css
forall a b. (a -> b) -> a -> b
$ Number -> Size LengthUnit
vh Number
100
            Shape -> Refinement
forall t. Token t => t -> Refinement
byToken Shape
Hexagon Refinement -> Css -> Css
& do
                Key MisoString
"clip-path"
                    Key MisoString -> MisoString -> Css
-: MisoString
"polygon(45% 1.33975%, 46.5798% 0.60307%, 48.26352% 0.15192%, 50% 0%, 51.73648% 0.15192%, 53.4202% 0.60307%, 55% 1.33975%, 89.64102% 21.33975%, 91.06889% 22.33956%, 92.30146% 23.57212%, 93.30127% 25%, 94.03794% 26.5798%, 94.48909% 28.26352%, 94.64102% 30%, 94.64102% 70%, 94.48909% 71.73648%, 94.03794% 73.4202%, 93.30127% 75%, 92.30146% 76.42788%, 91.06889% 77.66044%, 89.64102% 78.66025%, 55% 98.66025%, 53.4202% 99.39693%, 51.73648% 99.84808%, 50% 100%, 48.26352% 99.84808%, 46.5798% 99.39693%, 45% 98.66025%, 10.35898% 78.66025%, 8.93111% 77.66044%, 7.69854% 76.42788%, 6.69873% 75%, 5.96206% 73.4202%, 5.51091% 71.73648%, 5.35898% 70%, 5.35898% 30%, 5.51091% 28.26352%, 5.96206% 26.5798%, 6.69873% 25%, 7.69854% 23.57212%, 8.93111% 22.33956%, 10.35898% 21.33975%)"

data AvatarItem = AvatarItem
    { AvatarItem -> Avatar
avatar :: Avatar
    , AvatarItem -> Maybe MisoString
primaryText :: Maybe MisoString
    , AvatarItem -> Maybe MisoString
secondaryText :: Maybe MisoString
    }

instance Widget AvatarItem model action where
    widget' :: [Attribute action] -> AvatarItem -> View model action
widget' [Attribute action]
attrs AvatarItem{Maybe MisoString
Avatar
avatar :: AvatarItem -> Avatar
primaryText :: AvatarItem -> Maybe MisoString
secondaryText :: AvatarItem -> Maybe MisoString
avatar :: Avatar
primaryText :: Maybe MisoString
secondaryText :: Maybe MisoString
..} =
        [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
div_
            (MisoString -> Attribute action
forall action. MisoString -> Attribute action
class_ MisoString
"avatar-item" Attribute action -> [Attribute action] -> [Attribute action]
forall a. a -> [a] -> [a]
: [Attribute action]
attrs)
            ([View model action] -> View model action)
-> ([[View model action]] -> [View model action])
-> [[View model action]]
-> View model action
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [[View model action]] -> [View model action]
forall a. Monoid a => [a] -> a
mconcat
            ([[View model action]] -> View model action)
-> [[View model action]] -> View model action
forall a b. (a -> b) -> a -> b
$ [ [Avatar -> View model action
forall w model action.
Widget w model action =>
w -> View model action
widget Avatar
avatar]
              , [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
span_ [MisoString -> Attribute action
forall action. MisoString -> Attribute action
class_ MisoString
"primary"] ([View model action] -> View model action)
-> (MisoString -> [View model action])
-> MisoString
-> View model action
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. View model action -> [View model action]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (View model action -> [View model action])
-> (MisoString -> View model action)
-> MisoString
-> [View model action]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. MisoString -> View model action
forall model action. MisoString -> View model action
text (MisoString -> View model action)
-> [MisoString] -> [View model action]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe MisoString -> [MisoString]
forall a. Maybe a -> [a]
maybeToList Maybe MisoString
primaryText
              , [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
span_ [MisoString -> Attribute action
forall action. MisoString -> Attribute action
class_ MisoString
"secondary"] ([View model action] -> View model action)
-> (MisoString -> [View model action])
-> MisoString
-> View model action
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. View model action -> [View model action]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (View model action -> [View model action])
-> (MisoString -> View model action)
-> MisoString
-> [View model action]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. MisoString -> View model action
forall model action. MisoString -> View model action
text (MisoString -> View model action)
-> [MisoString] -> [View model action]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe MisoString -> [MisoString]
forall a. Maybe a -> [a]
maybeToList Maybe MisoString
secondaryText
              ]
    style :: Css
style =
        Selector
".avatar-item" Selector -> Css -> Css
? do
            Selector
".avatar" Selector -> Css -> Css
? (Key MisoString
"grid-area" Key MisoString -> MisoString -> Css
-: MisoString
"avatar")
            Selector
".primary" Selector -> Css -> Css
? FontWeight -> Css
fontWeight (Integer -> FontWeight
weight Integer
500)
            Selector
".secondary" Selector -> Css -> Css
? do
                TextColour -> Css
forall t. Token t => t -> Css
color' (TextColour -> Css) -> TextColour -> Css
forall a b. (a -> b) -> a -> b
$ Appearance -> TextColour
TextColour Appearance
Subtle
                SizeToken -> Css
fontSize' SizeToken
Small
            Display -> Css
display Display
flex
            SizeToken -> Css
columnGap' SizeToken
Small
            AlignItemsValue -> Css
alignItems AlignItemsValue
forall a. Center a => a
center
            AlignContentValue -> Css
alignContent AlignContentValue
forall a. Center a => a
center
            FlexDirection -> Css
flexDirection FlexDirection
row
            NonEmpty Refinement -> Refinement
forall a. Semigroup a => NonEmpty a -> a
sconcat [Selector -> Refinement
has Selector
".primary", Selector -> Refinement
has Selector
".secondary"] Refinement -> Css -> Css
& do
                Display -> Css
display Display
grid
                [[Value]] -> Css
gridTemplateAreas
                    [ [Item [Value]
Value
"avatar", Item [Value]
Value
"primary"]
                    , [Item [Value]
Value
"avatar", Item [Value]
Value
"secondary"]
                    ]
                Key MisoString
"grid-auto-columns" Key MisoString -> MisoString -> Css
-: MisoString
"max-content"
                Selector
".primary" Selector -> Css -> Css
? do
                    Key MisoString
"grid-area" Key MisoString -> MisoString -> Css
-: MisoString
"primary"
                    AlignSelfValue -> Css
alignSelf (AlignSelfValue -> Css) -> AlignSelfValue -> Css
forall a b. (a -> b) -> a -> b
$ Value -> AlignSelfValue
AlignSelfValue Value
"end"
                Selector
".secondary" Selector -> Css -> Css
? do
                    Key MisoString
"grid-area" Key MisoString -> MisoString -> Css
-: MisoString
"secondary"
                    AlignSelfValue -> Css
alignSelf (AlignSelfValue -> Css) -> AlignSelfValue -> Css
forall a b. (a -> b) -> a -> b
$ Value -> AlignSelfValue
AlignSelfValue Value
"start"
            Selector -> Refinement
has (Selector
".avatar" Selector -> Refinement -> Selector
# SizeToken -> Refinement
forall t. Token t => t -> Refinement
byToken SizeToken
XLarge) Refinement -> Css -> Css
& SizeToken -> Css
fontSize' SizeToken
XLarge