{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
module Reflex.Dom.Widget.SVG
( AsSVGTag (..)
, BasicSVG (..)
, BasicInner (..)
, SVG_Root (..)
, CanBeNested
, SVGEl (..)
, svg_
, svgBasicDyn
, svgBasicDyn_
, svgElDynAttr'
, svgElDynAttr_
) where
import Control.Monad.Fix (MonadFix)
import Data.Text (Text)
import Reflex (Dynamic, MonadHold)
import qualified Reflex as R
import Reflex.Dom.Core (Element, EventResult, DomBuilderSpace, DomBuilder, PostBuild)
import qualified Reflex.Dom.Core as RD
import Data.Map (Map)
import Reflex.Dom.Widget.SVG.Types (SVG_El, makeSVGProps)
class AsSVGTag s where
svgTagName :: s -> Text
instance AsSVGTag BasicSVG where
svgTagName Rectangle = "rect"
svgTagName Circle = "circle"
svgTagName Ellipse = "ellipse"
svgTagName Path = "path"
svgTagName Line = "line"
svgTagName PolyLine = "polyline"
svgTagName Polygon = "polygon"
instance AsSVGTag BasicInner where
svgTagName Animate = "animate"
instance AsSVGTag SVG_Root where
svgTagName SVG_Root = "svg"
data SVG_Root = SVG_Root
data BasicSVG
= Rectangle
| Circle
| Ellipse
| Path
| Line
| PolyLine
| Polygon
deriving (Show, Eq)
data BasicInner
= Animate
deriving (Eq, Ord)
type family CanBeNested a :: *
type instance CanBeNested BasicSVG = BasicInner
data SVGEl t m a = SVGEl
{ _svgEl_el :: Element EventResult (DomBuilderSpace m) t
, _svgEl_children :: Dynamic t (Map (CanBeNested a) (Element EventResult (DomBuilderSpace m) t))
}
svgXMLNamespace :: Text
svgXMLNamespace = "http://www.w3.org/2000/svg"
svgElDynAttr'
:: forall t m a e. ( DomBuilder t m
, PostBuild t m
, AsSVGTag e
)
=> e
-> Dynamic t (Map Text Text)
-> m a
-> m (Element EventResult (DomBuilderSpace m) t, a)
svgElDynAttr' = RD.elDynAttrNS'
(Just svgXMLNamespace)
. svgTagName
svgElDynAttr_
:: forall t m e. ( DomBuilder t m
, PostBuild t m
, AsSVGTag e
)
=> e
-> Dynamic t (Map Text Text)
-> m (Element EventResult (DomBuilderSpace m) t)
svgElDynAttr_ t dAttrs = fst <$> RD.elDynAttrNS'
(Just svgXMLNamespace)
(svgTagName t)
dAttrs
RD.blank
svg_
:: ( DomBuilder t m
, PostBuild t m
, R.Reflex t
, AsSVGTag a
)
=> Dynamic t SVG_El
-> m ( SVGEl t m a )
-> m ( Element EventResult (DomBuilderSpace m) t, SVGEl t m a)
svg_ dAttrs =
svgElDynAttr' SVG_Root (makeSVGProps <$> dAttrs)
svgBasicDyn
:: ( DomBuilder t m
, PostBuild t m
, MonadFix m
, MonadHold t m
, AsSVGTag s
, AsSVGTag (CanBeNested s)
, Ord (CanBeNested s)
)
=> s
-> ( p -> Map Text Text )
-> Dynamic t p
-> Dynamic t ( Map (CanBeNested s) (Map Text Text) )
-> m ( SVGEl t m s )
svgBasicDyn t propFn dProps dInnerElMap =
fmap ( uncurry SVGEl ) . svgElDynAttr' t (propFn <$> dProps) $ RD.listWithKey dInnerElMap
(\innerS dInnerAttrs -> fst <$> svgElDynAttr' innerS dInnerAttrs RD.blank)
svgBasicDyn_
:: ( DomBuilder t m
, PostBuild t m
, MonadFix m
, MonadHold t m
, AsSVGTag s
, AsSVGTag (CanBeNested s)
, Ord (CanBeNested s)
)
=> s
-> ( p -> Map Text Text )
-> Dynamic t p
-> m ( SVGEl t m s )
svgBasicDyn_ t propFn dProps =
svgBasicDyn t propFn dProps (pure mempty)