Modified Components declaration of Props.

Props are now added using add(...) functions in a Monad block, and the
Html is "return"ed.
This commit is contained in:
Etienne Werly 2023-06-19 22:02:28 +02:00
parent 454b7f48f0
commit 4a900ab57c
12 changed files with 79 additions and 66 deletions

View file

@ -4,6 +4,9 @@ module Components
, Component(..)
, new
, (<.>)
, addCss
, addAsset
, addAsset'
, getHtml
, getCss
) where
@ -14,10 +17,10 @@ import Clay ( Css
)
import Core.Writer
import qualified Data.Map as Map
import qualified Data.Set as Set
import Data.Text.Lazy ( unpack )
import Routes
import Text.Blaze.Html
import Text.Blaze.Html.Renderer.String
import Text.Blaze.Html5 ( Html )
import Utils.FileTree
-- |Props are data on top of a component's html. They are aggregated when components are combined. The choice of structures for Prop ensures that there is no duplicate at compile time (e.g. the css of a button used 5 times is only rendered once.)
@ -27,33 +30,36 @@ data Prop = Prop
}
instance Semigroup Prop where
p1 <> p2 =
Prop (Map.union (cssMap p1) (cssMap p2)) (assetsTree p1 <> assetsTree p2)
p1 <> p2 = Prop { cssMap = Map.union (cssMap p1) (cssMap p2)
, assetsTree = assetsTree p1 <> assetsTree p2
}
instance Monoid Prop where
mempty = Prop Map.empty mempty
-- |Construct a Prop with a name, css.
prop :: String -> Css -> Prop
prop name css = Prop (Map.singleton name css)
type Component = Writer Prop
prop :: String -> Css -> Prop
prop name css = Prop (Map.singleton name css) mempty
-- |Add a name and css to a Prop.
addCss :: String -> Css -> Component ()
addCss name css = tell $ Prop (Map.singleton name css) mempty
-- |Add an asset to the Prop's tree.
addAsset :: FilePath -> Component ()
addAsset fp = tell $ Prop Map.empty (build fp)
addAsset' :: Route -> Component ()
addAsset' r = tell $ Prop Map.empty (build' r)
-- |Get a Component's Html
getHtml :: Component Html -> Html
getHtml = fst . runWriter
---- |Return a Component's Css as a String
--toCss :: Component a -> String
--toCss =
-- unpack
-- . renderWith compact []
-- . mconcat
-- . map snd
-- . Map.toList
-- . cssMap
-- . snd
-- . runWriter
-- |Get a Component's Css
getCss :: Component a -> Css
getCss = mconcat . map snd . Map.toList . cssMap . snd . runWriter
-- |Get a Component's assets tree
getFileTree :: Component a -> FileTree
getFileTree = assetsTree . snd . runWriter

View file

@ -1,5 +1,6 @@
module Core.Writer
( Writer
, tell
, runWriter
, new
, (<.>)

View file

@ -13,5 +13,7 @@ css = C.button ? do
color white
fontWeight bold
buttonWithText :: Html -> Component Html
buttonWithText = new (prop "buttonWithText" css) . H.button
buttonWithText :: Component (Html -> Html)
buttonWithText = do
addCss "buttonWithText" css
return H.button

View file

@ -31,5 +31,7 @@ css = C.a # byClass "button" ? do
color (grays @ 100)
backgroundColor (grays @ 70)
buttonLink :: Route -> Html -> Component Html
buttonLink ref = new (prop "buttonLink" css) . buttonLinkHtml ref
buttonLink :: Route -> Component (Html -> Html)
buttonLink ref = do
addCss "buttonLink" css
return $ buttonLinkHtml ref

View file

@ -13,4 +13,6 @@ css = element ".container" ? do
marginLeft <> marginRight $ auto
container :: Component (Html -> Html)
container = new (prop "container" css) $ H.div H.! class_ "container"
container = do
addCss "container" css
return $ H.div H.! class_ "container"

View file

@ -20,4 +20,6 @@ css = C.header ? do
header' :: Component (Html -> Html)
header' = new (prop "header" css) H.header
header' = do
addCss "header" css
return H.header

View file

@ -19,38 +19,32 @@ baseCss = C.img ? do
maxWidth (pct 100)
img' :: FilePath -> String -> Component Html
img' file description =
new (prop "img" baseCss)
$ H.img
H.! A.src (stringValue . path . Img $ file)
H.! A.alt (stringValue description)
img' file description = do
addCss "img" baseCss
addAsset' $ Img file
return $ H.img H.! A.src (stringValue . path . Img $ file) H.! A.alt
(stringValue description)
imgWithShape :: Shape -> FilePath -> String -> Component Html
imgWithShape Square file description = img' file description
imgWithShape Circle file description =
new
(prop "img circle"
(C.img # byClass "circle" ? uniform borderRadius (pct 50))
)
(H.! class_ "circle")
<*> img' file description
do
addCss "img circle"
(C.img # byClass "circle" ? uniform borderRadius (pct 50))
return (H.! class_ "circle")
<*> img' file description
imgWithShape Rounded file description =
new
(prop "img rounded"
(C.img # byClass "rounded" ? uniform borderRadius (pct 10))
)
(H.! class_ "rounded")
<*> img' file description
do
addCss "img rounded"
(C.img # byClass "rounded" ? uniform borderRadius (pct 10))
return (H.! class_ "rounded")
<*> img' file description
imgWithShape Drop file description =
new
(prop
"img drop"
(C.img # byClass "drop" ? borderRadius (pct 50)
(pct 50)
(pct 50)
(pct 10)
)
do
addCss
"img drop"
(C.img # byClass "drop" ? borderRadius (pct 50) (pct 50) (pct 50) (pct 10)
)
(H.! class_ "drop")
<*> img' file description
return (H.! class_ "drop")
<*> img' file description

View file

@ -9,8 +9,6 @@ import Text.Blaze.Html5
import Text.Blaze.Html5.Attributes
stylesheet :: Route -> Css -> Component Html
stylesheet route css =
new (prop (path route) css)
$ link
! rel "stylesheet"
! (href . stringValue . path $ route)
stylesheet route css = do
addCss (path route) css
return $ link ! rel "stylesheet" ! (href . stringValue . path $ route)

View file

@ -20,6 +20,6 @@ css = byClass "profile-bio" & do
C.width (C.em 20)
profileBio :: String -> Component Html
profileBio bio =
new (prop "profileBio" css) $ H.div H.! class_ "profile-bio" $ H.p
(toHtml bio)
profileBio bio = do
addCss "profileBio" css
return $ H.div H.! class_ "profile-bio" $ H.p (toHtml bio)

View file

@ -16,8 +16,9 @@ css = byClass "profile-content" & do
borderLeft (px 10) solid $ secondary @ 50
profileContent :: String -> String -> Component Html
profileContent auth desc =
new (prop "profileContent" css)
profileContent auth desc = do
addCss "profileContent" css
return
$ H.div
H.! class_ "profile-content"
$ H.hgroup

View file

@ -21,5 +21,7 @@ css = byClass "profile-pic" & do
profilePic :: FilePath -> String -> Component Html
profilePic file altText =
new (prop "profilePic" css) (H.div H.! class_ "profile-pic")
<*> imgWithShape Rounded file altText
do
addCss "profilePic" css
return $ H.div H.! class_ "profile-pic"
<*> imgWithShape Rounded file altText

View file

@ -15,8 +15,11 @@ import Text.Blaze.Html5 as H
import Text.Blaze.Html5.Attributes as A
indexBody :: Component Html
indexBody =
mconcat [profileHeader, buttonWithText "Click!", buttonLink Blog "All posts"]
indexBody = mconcat
[ profileHeader
, buttonWithText <*> pure "Click!"
, buttonLink Blog <*> pure "All posts"
]
indexTemplate :: Component Html
indexTemplate =