content: {-# LANGUAGE OverloadedStrings, FlexibleInstances, DataKinds,
      ConstraintKinds #-}
  -- TODO(joel) rename to React.DOM?
  module React.Elements
      (
      -- * Class creation
        classParent
      , classLeaf
  
      -- * JS Interop
      , exportClassLeaf
      -- , exportNode
      , importLeafClass
      , importParentClass
  
      , ExportedNode
      , ExportedClass
      ) where
  
  import Control.Applicative
  import Data.Aeson as Aeson
  import qualified Data.HashMap.Strict as H
  import Data.IORef
  import Data.Monoid
  import Data.String
  import Data.Void
  import System.IO.Unsafe
  
  import React.Class
  import React.GHCJS
  import React.Imports
  import React.Interpret
  import React.Registry
  import React.Types
  
  
  classParent' :: ReactClass props state insig exsig ctx
               -> ReactNode insig
               -> props
               -> ReactNode exsig
  classParent' cls children props = ComponentElement
      (ReactComponentElement cls children Nothing Nothing props)
  
  
  classLeaf' :: ReactClass props state insig exsig ctx
             -> props
             -> ReactNode exsig
  classLeaf' cls props = ComponentElement
      (ReactComponentElement cls mempty Nothing Nothing props)
  
  
  classParent :: ClassCtx ctx
              => ClassConfig props state insig exsig ctx
              -> ReactNode insig
              -> props
              -> ReactNode exsig
  classParent = classParent' . createClass
  
  
  -- TODO refine this type to reflect that it can send back signals
  classLeaf :: ClassCtx ctx
            => ClassConfig props state insig exsig ctx
            -> props
            -> ReactNode exsig
  classLeaf = classLeaf' . createClass
  
  
  data ExportedClass_
  type ExportedClass = JSRef ExportedClass_
  
  newtype ExportedNode sig = ExportedNode (IO JSAny)
  
  instance ToJSRef (ExportedNode sig) where
      toJSRef (ExportedNode n) = castRef <$> n
  
  
  -- XXX
  -- Must make sure to get componentId to this class! Currently it's in props,
  -- but maybe should move...
  exportClassLeaf :: ClassCtx ctx
                  => ClassConfig props state insig exsig ctx
                  -> ExportedClass
  exportClassLeaf conf =
      castRef $ classForeign $ createClass conf
  
  
  -- XXX
  -- Must make sure to update state in JS when it changes in HS!
  -- exportNode :: (sig -> IO ()) -> ReactNode sig -> ExportedNode sig
  -- exportNode handler = ExportedNode . reactNodeToJSAny handler undefined
  
  
  
  -- Note: state here reflects the state managed by react-haskell, not the state
  -- of the component.
  -- TODO - figure out how to handle callbacks (change Void -> a)
  
  
  importLeafClass :: ToJSRef props
                  => ImportedClass props sig
                  -> props
                  -> ReactNode sig
  importLeafClass elem props = ForeignClass elem props mempty
  
  
  
  importParentClass :: ToJSRef props
                    => ImportedClass props sig
                    -> props
                    -> ReactNode sig
                    -> ReactNode sig
  importParentClass elem props children = ForeignClass elem props children
  