packages feed

reflex-classhss-0.1.0.0: src/Classh/Reflex/El.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
--------------------------------------------------------------------------------
-- |
--  Module      :  Classh.Reflex.Text
--  Copyright   :  (c) 2024, Galen Sprout
--  License     :  BSD-style (see end of this file)
--
--  Maintainer  :  Galen Sprout <galen.sprout@gmail.com>
--  Stability   :  provisional
--  Portability :  portable
--
--  A collection of Classh-typed versions of elClass and similar funcs using classhUnsafe
--
-------------------------------------------------------------------------------


module Classh.Reflex.El where

import Reflex.Dom.Core
import Classh
import Control.Monad (void)
import qualified Data.Map as Map
import qualified Data.Text as T




type Shell m a = m a -> m a

-- | is elClass except that it takes a BoxConfig instead of a string for classes
elTW :: DomBuilder t m => T.Text -> BoxConfig -> m a -> m a
elTW etag cfg ma = elClass etag (defaultClasses <> " " <> showTW cfg) ma

-- | is elClass' except that it takes a BoxConfig instead of a string for classes.
elTW' :: DomBuilder t m => T.Text -> BoxConfig -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
elTW' etag cfg ma = elClass' etag (defaultClasses <> " " <> showTW cfg) ma

-- | is elDynClass except that it takes a BoxConfig instead of a string for classes
elDynTW :: (PostBuild t m, DomBuilder t m) => T.Text -> Dynamic t BoxConfig -> m a -> m a
elDynTW etag cfgDyn ma = elDynClass etag ( (\cfg -> defaultClasses <> " " <> showTW cfg) <$> cfgDyn ) ma

-- | is elDynClass' except that it takes a BoxConfig instead of a string for classes
elDynTW' :: (PostBuild t m, DomBuilder t m) => T.Text -> Dynamic t BoxConfig -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
elDynTW' etag cfgDyn ma = elDynClass' etag ( (\cfg -> defaultClasses <> " " <> showTW cfg) <$> cfgDyn ) ma

div_ :: DomBuilder t m => m a -> m a
div_ = el "div"

-- | When we want to do absolutely nothing but create an area devoid of influence by outside
-- | Most common case is for differing displays like inline-block vs grid
-- |
-- | In practice this can also be used to solve a common problem where
-- | helper functions unnecessarily restrict size of children.
-- |
-- | TODO: we need to probably use this everywhere
in_ :: DomBuilder t m => m a -> m a
in_ = divClass $(classh' [h .~~ pct 100, w .~~ pct 100])

-- | Example Use Case:
-- | divClass $(classh' [pos .~~ centered]) $ do
-- |   inH_ leaf
inH_ :: DomBuilder t m => m a -> m a
inH_ = divClass $(classh' [h .~~ pct 100])


type PlaceHolder = T.Text
inputEl :: DomBuilder t m => T.Text -> T.Text -> PlaceHolder -> m ()
inputEl elClasses textClasses placeholder = void $ inputElement $ def & inputElementConfig_elementConfig . initialAttributes .~
  ("class" =: (elClasses <&> textClasses)
  <> "placeholder" =: placeholder
  )

type TextAreaRows = Int
textAreaEl :: DomBuilder t m => TextAreaRows -> T.Text -> T.Text -> PlaceHolder -> m ()
textAreaEl rows elClasses textClasses placeholder =
  void $ textAreaElement $ def & textAreaElementConfig_elementConfig . initialAttributes .~
  ("class" =: (elClasses <&> textClasses)
  <> "rows" =: tshow rows
  <> "placeholder" =: placeholder
  )

-- <img
--   src="dog-600.jpg"
--   srcset="
--     dog-300.jpg 300w,
--     dog-450.jpg 450w,
--     dog-600.jpg 600w,
--     dog-900.jpg 900w,
--     dog-1200.jpg 1200w,
--     dog-1600.jpg 1600w
--   "
--   sizes="(max-width: 600px) 100vw, (max-width: 900px) 50vw, 33vw"
--   alt="Dog running through the field" />
type ScreenWidth = DimensionConstraint
imgResponsive
  :: DomBuilder t m
  => [ (StaticImagePath
       , (CSSSize, ScreenWidth)
       )
     ]
  -> CompiledS
  -> m ()
imgResponsive imageInfo classes = elAttr "img" (imgSrcSet imageInfo classes) blank

-- example = imgResponsive (imgSrcSet [] "")

--imgSrcSet
type StaticImagePath = T.Text
type Pixels = Int

imgSrcSet :: [(StaticImagePath, (CSSSize, DimensionConstraint))] -> CompiledS -> Map.Map T.Text T.Text
imgSrcSet [] _ = error "No images given to Classh.Reflex.imgSrcSet" -- we know this must be the start, there is no recursion
imgSrcSet xs classes =
  let
    mkPair = \(src',(w_,_)) -> src' <&> (renderCSS w_) <> "w"
    pairs = mkPair <$> xs

    showMW :: DimensionConstraint -> T.Text
    showMW m_ = "(max-width: " <> showTW m_ <> ")"

    mkFuckingAlgebraicSizes :: [(StaticImagePath, (CSSSize, DimensionConstraint))] -> T.Text
    mkFuckingAlgebraicSizes [] = error "mkFuckingAlgebraicSizes received no input"
    mkFuckingAlgebraicSizes ((_,(w_, maxW__)):xs_) =
      if null xs_
      then renderCSS w_
      else showMW maxW__ <> renderCSS w_ <> "," <> mkFuckingAlgebraicSizes xs_
  in
    "srcset" =: (T.intercalate "," pairs)
    <> "sizes" =: (mkFuckingAlgebraicSizes xs)
    <> "class" =: classes

divClassh :: BoxConfig -> [BoxConfig -> BoxConfig] -> Compiled Expression
divClassh base muts = case compileS $ foldl (\acc f -> f acc) base muts of
  Left e -> fail $ T.unpack e
  Right styleString -> [| divClass styleString |]

divClassh' :: [BoxConfig -> BoxConfig] -> Compiled Expression
divClassh' muts = case compileS $ foldl (\acc f -> f acc) def muts of
  Left e -> fail $ T.unpack e
  Right styleString -> [| divClass styleString |]

textClassh :: TextConfigTW -> [TextConfigTW -> TextConfigTW] -> Compiled Expression
textClassh base muts = case compileS $ foldl (\acc f -> f acc) base muts of
  Left e -> fail $ T.unpack e
  Right styleString -> [| textS styleString |]

textClassh' :: [TextConfigTW -> TextConfigTW] -> Compiled Expression
textClassh' muts = case compileS $ foldl (\acc f -> f acc) def muts of
  Left e -> fail $ T.unpack e
  Right styleString -> [| textS styleString |]

textPos' :: [TextPosition -> TextPosition] -> Compiled Expression
textPos' muts = case compileS $ foldl (\acc f -> f acc) def muts of
  Left e -> fail $ T.unpack e
  Right styleString -> [| textPosition styleString |]

textPos :: TextPosition -> [TextPosition -> TextPosition] -> Compiled Expression
textPos base muts = case compileS $ foldl (\acc f -> f acc) base muts of
  Left e -> fail $ T.unpack e
  Right styleString -> [| textPosition styleString |]