packages feed

ghcjs-vdom-0.2.0.0: src/GHCJS/VDOM/DOMComponent.hs

{- |
   DOM components manage a normal DOM subtree inside a virtual-dom tree.

   The component has callbacks for mounting and unmounting. The mount
   callback returns a DOM tree that stays in the document until the
   unmount callback is called.

   A single component can be mounted multiple times. The mount callback
   is called for each mount, and is expected to return a fresh DOM
   tree every time.
 -}

{-# LANGUAGE ForeignFunctionInterface, JavaScriptFFI, QuasiQuotes #-}
module GHCJS.VDOM.DOMComponent ( DComp
                               , mkComponent
                               , toNode
                               ) where

import           GHCJS.Foreign.QQ
import           GHCJS.Marshal.Pure
import           GHCJS.Types

import           GHCJS.VDOM.Internal.Types

import qualified GHCJS.VDOM.Internal       as I


toNode :: DComp -> VNode
toNode (DComp v) = VNode v
{-# INLINE toNode #-}

mkComponent :: (Int -> IO JSVal)     -- ^ mount action, return a DOM node
            -> (Int -> JSVal -> IO ()) -- ^ unmount action
            -> IO DComp
mkComponent mount unmount =
  let mountE   = I.unsafeExportValue (mountComponent mount)
      unmountE = I.unsafeExportValue (unmountComponent unmount)
  in  DComp <$> [jsu| h$vdom.c(null, `mountE, `unmountE, null) |]


mountComponent :: (Int -> IO JSVal) -> JSVal -> JSVal -> IO ()
mountComponent f mnt c = do
  node <- f (pFromJSVal mnt)
  [jsu| `c.updateMount(`mnt, `node); |]

unmountComponent :: (Int -> JSVal -> IO ()) -> JSVal -> JSVal -> IO ()
unmountComponent f mnt node = f (pFromJSVal mnt) node