module Graphics.UI.Threepenny.Ext.Flexbox (
ParentProps (..), parentProps,
ChildProps (..), childProps,
flexbox, setProps, toStyle,
column, row
) where
import qualified Clay.Common as CC
import Clay.Display (Display)
import qualified Clay.Display as CD
import Clay.Flexbox (AlignContentValue,
AlignItemsValue, AlignSelfValue,
FlexDirection, FlexWrap,
JustifyContentValue)
import qualified Clay.Flexbox as CF
import Clay.Property (unKeys, unPlain, unValue)
import Clay.Size (LengthUnit, Size)
import Clay.Stylesheet (Rule (Property), runS)
import Data.Text (unpack)
import qualified Graphics.UI.Threepenny as UI
import Graphics.UI.Threepenny.Core hiding (column, row)
class ToStyle a where
toStyle :: a -> [(String, String)]
instance ToStyle Rule where
toStyle (Property k v) =
[(unpack $ unPlain $ unKeys k, unpack $ unPlain $ unValue v)]
data ParentProps = ParentProps {
pDisplay :: Display
, pFlexDirection :: FlexDirection
, pFlexWrap :: FlexWrap
, pJustifyContent :: JustifyContentValue
, pAlignItems :: AlignItemsValue
, pAlignContent :: AlignContentValue
}
instance ToStyle ParentProps where
toStyle p = concatMap toStyle $ concatMap runS [
CD.display $ pDisplay p
, CF.flexDirection $ pFlexDirection p
, CF.flexWrap $ pFlexWrap p
, CF.justifyContent $ pJustifyContent p
, CF.alignItems $ pAlignItems p
, CF.alignContent $ pAlignContent p
]
parentProps :: ParentProps
parentProps = ParentProps {
pDisplay = CD.flex
, pFlexDirection = CF.row
, pFlexWrap = CF.nowrap
, pJustifyContent = CF.flexStart
, pAlignItems = CF.stretch
, pAlignContent = CF.stretch
}
data ChildProps = ChildProps {
cOrder :: Int
, cFlexGrow :: Int
, cFlexShrink :: Int
, cFlexBasis :: Size LengthUnit
, cAlignSelf :: AlignSelfValue
}
instance ToStyle ChildProps where
toStyle c = concatMap toStyle $ concatMap runS [
CF.order $ cOrder c
, CF.flexGrow $ cFlexGrow c
, CF.flexShrink $ cFlexShrink c
, CF.flexBasis $ cFlexBasis c
, CF.alignSelf $ cAlignSelf c
]
childProps :: ChildProps
childProps = ChildProps {
cOrder = 1
, cFlexGrow = 0
, cFlexShrink = 1
, cFlexBasis = CC.auto
, cAlignSelf = CC.auto
}
setProps :: ToStyle a => UI Element -> a -> UI Element
setProps el props = el # set UI.style (toStyle props)
flexbox ::
UI Element
-> ParentProps
-> [(UI Element, ChildProps)]
-> UI Element
flexbox p pProps cs = do
p' <- setProps p pProps
cs' <- mapM (uncurry setProps) cs
element p' #+ map element cs'
column :: UI Element -> [UI Element] -> UI Element
column p cs = flexbox p parentProps { pFlexDirection = CF.column } $
zip cs $ repeat childProps
row :: UI Element -> [UI Element] -> UI Element
row p cs = flexbox p parentProps $ zip cs $ repeat childProps