hyperbole-0.5.0: src/Web/Hyperbole/HyperView/Types.hs
{-# LANGUAGE UndecidableInstances #-}
module Web.Hyperbole.HyperView.Types where
import Data.Kind (Type)
import Effectful
import Effectful.Reader.Dynamic
import GHC.Generics
import Web.Hyperbole.Effect.Hyperbole (Hyperbole)
import Web.Hyperbole.HyperView.ViewAction
import Web.Hyperbole.HyperView.ViewId
import Web.Hyperbole.View (View, none)
{- | HyperViews are interactive subsections of a 'Page'
Create an instance with a unique view id type and a sum type describing the actions the HyperView supports. The View Id can contain context (a database id, for example)
@
#EMBED Example/Docs/Interactive.hs data Message
#EMBED Example/Docs/Interactive.hs instance HyperView Message es where
@
-}
class (ViewId id, ViewAction (Action id)) => HyperView id es where
-- | Outline all actions that are permitted in this HyperView
--
-- > data Action Message = SetMessage Text | ClearMessage
-- > deriving (Generic, ViewAction)
data Action id
-- | Include any child hyperviews here. The compiler will make sure that the page knows how to handle them
--
-- > type Require = '[ChildView]
type Require id :: [Type]
type Require id = '[]
-- | Specify how the view should be updated for each Action
--
-- > update (SetMessage msg) = pure $ messageView msg
-- > update ClearMessage = pure $ messageView ""
update :: (Hyperbole :> es) => Action id -> Eff (Reader id : es) (View id ())
-- | The top-level view returned by a 'Page'. It carries a type-level list of every 'HyperView' used in our 'Page' so the compiler can check our work and wire everything together.
data Root (views :: [Type]) = Root
deriving (Generic, ViewId)
instance HyperView (Root views) es where
data Action (Root views) = RootNone
deriving (Generic, ViewAction)
type Require (Root views) = views
update _ = pure none