packages feed

purview-0.2.0.0: src/Component.hs

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE GADTs #-}
module Component where

import           Data.Typeable
import           Events

type Hash = String

{-|

Attributes are collected until an 'HTML' constructor is hit, where they
are applied during rendering.

-}
data Attributes event where
  On :: ( Show event
        , Eq event
        , Typeable event
        )
     => String
     -> Identifier
     -> (Maybe String -> event)  -- the string here is information from the browser
     -> Attributes event
        -- ^ part of creating handlers for different events, e.g. On "click"
  Style :: (Hash, String) -> Attributes event
        -- ^ hash of the css, the css
  Generic :: String -> String -> Attributes event
        -- ^ for creating new Attributes to put on HTML, e.g. Generic "type" "radio" for type="radio".

instance Eq (Attributes event) where
  (Style a) == (Style b) = a == b
  (Style _) == _ = False

  (On kind ident _event) == (On kind' ident' _event') =
    kind == kind' && ident == ident'
  (On {}) == _ = False

  (Generic name value) == (Generic name' value') = name == name' && value == value'
  (Generic _ _) == _ = False

instance Show (Attributes event) where
  show (On kind ident evt) = "On " <> show kind <> " " <> show ident
  show (Style str) = "Style " <> show str
  show (Generic attrKey attrValue) = "Generic " <> show attrKey <> show attrValue

{-|

This is what you end up building using the various helpers.  It's hopefully rare
that you have to use these directly, but it may be useful to better understand
what's happening behind the scenes.

-}
data Purview event m where
  Attribute :: Attributes event -> Purview event m -> Purview event m
  Text :: String -> Purview event m
  Html :: String -> [Purview event m] -> Purview event m
  Value :: Show a => a -> Purview event m

  Receiver
    :: ( Show event
       , Eq event
       , Typeable event
       )
    => { parentIdentifier :: ParentIdentifier
       , identifier :: Identifier
       , name :: String  -- the name to be used to send an event
       , eventHandler :: Maybe String -> event  -- what to do with an event from the fn
       , child :: state -> Purview event m
       , state :: state
       }
    -> Purview event m

  EffectHandler
    :: ( Show state
       , Eq state
       , Typeable state
       , Typeable newEvent
       )
    => { parentIdentifier :: ParentIdentifier
       -- ^ The location of the parent effect handler (provided by prepareTree)
       , identifier       :: Identifier
       -- ^ The location of this effect handler (provided by prepareTree)
       , initialEvents    :: [DirectedEvent event newEvent]
       , state            :: state
       -- ^ The initial state
       , effectReducer    :: newEvent
                          -> state
                          -> m (state -> state, [DirectedEvent event newEvent])
       -- ^ Receive an event, change the state, and send messages
       , continuation     :: state -> Purview newEvent m
       }
    -> Purview event m

  Handler
    :: ( Show state
       , Eq state
       , Typeable state
       , Typeable newEvent
       )
    => { parentIdentifier :: ParentIdentifier
       , identifier       :: Identifier
       , initialEvents    :: [DirectedEvent event newEvent]
       , state            :: state
       , reducer          :: newEvent
                          -> state
                          -> (state -> state, [DirectedEvent event newEvent])
       , continuation     :: state -> Purview newEvent m
       }
    -> Purview event m

instance Show (Purview event m) where
  show (EffectHandler parentLocation location initialEvents state _event cont) =
    "EffectHandler "
      <> show parentLocation <> " "
      <> show location <> " "
      <> show state <> " "
      <> show (cont state)
  show (Handler parentLocation location initialEvents state _event cont) =
    "Handler "
      <> show parentLocation <> " "
      <> show location <> " "
      <> show state <> " "
      <> show (cont state)
  show (Receiver parentLocation location name handler child state) =
    "Receiver "
      <> show parentLocation <> " "
      <> show location <> " "
      <> show name <> " "
      <> show (child state)
  show (Attribute attrs cont) = "Attr " <> show attrs <> " " <> show cont
  show (Text str) = show str
  show (Html kind children) =
    kind <> " [ " <> concatMap ((<>) " " . show) children <> " ] "
  show (Value value) = show value

instance Eq (Purview event m) where
  a == b = show a == show b