content: {-# 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
  