react-flux 0.9.3 → 0.9.4
raw patch · 12 files changed
+186/−134 lines, 12 files
Files
- ChangeLog.md +8/−0
- example/routing/Router.hs +1/−1
- react-flux.cabal +1/−1
- src/React/Flux/Addons/Bootstrap.hs +3/−3
- src/React/Flux/Addons/React.hs +1/−1
- src/React/Flux/Export.hs +3/−3
- src/React/Flux/Internal.hs +104/−74
- src/React/Flux/Lifecycle.hs +8/−9
- src/React/Flux/PropertiesAndEvents.hs +32/−21
- src/React/Flux/Store.hs +5/−3
- src/React/Flux/Views.hs +19/−17
- test/client/TestClient.hs +1/−1
ChangeLog.md view
@@ -1,3 +1,11 @@+# 0.9.4++* Fix to build with latest ghcjs-base (requires at least aaa4d59117f37d1b9c60a154a9128b3bcc6301cd)+ of ghcjs-base), so you may need to recompile ghcjs and ghcjs-base.+* Add a function 'property' to create a property from any JSRef, not just Aeson values.+* Add a function 'elementProperty' to create a property from a ReactElementM, useful for+ interacting with foreign React classes.+ # 0.9.3 * Don't require web-routes dependency if not building the routing example
example/routing/Router.hs view
@@ -37,7 +37,7 @@ foreign import javascript unsafe "window.onhashchange = function() {$1(location.hash.toString());}"- js_attachtLocationHashCb :: (Callback (JSRef JSString -> IO ())) -> IO ()+ js_attachtLocationHashCb :: (Callback (JSRef -> IO ())) -> IO () foreign import javascript unsafe "window.location.hash = $1"
react-flux.cabal view
@@ -1,5 +1,5 @@ name: react-flux-version: 0.9.3+version: 0.9.4 synopsis: A binding to React based on the Flux application architecture for GHCJS category: Web homepage: https://bitbucket.org/wuzzeb/react-flux
src/React/Flux/Addons/Bootstrap.hs view
@@ -15,8 +15,8 @@ -- | A bootstrap <http://react-bootstrap.github.io/components.html component>. For example, -- -- >bootstrap_ "Alert" [ "bsStyle" $= "danger"--- , callback "onDismiss" (const $ dispatch CloseAlert)--- ] $+-- > , callback "onDismiss" (const $ dispatch CloseAlert)+-- > ] $ -- > p_ "Hello, World!" bootstrap_ :: String -- ^ The component name. Uses @window['ReactBootstrap'][name]@ to find the class, so@@ -33,7 +33,7 @@ foreign import javascript unsafe "window['ReactBootstrap'][$1]"- js_ReactBootstrap :: JSString -> JSRef ()+ js_ReactBootstrap :: JSString -> JSRef #else
src/React/Flux/Addons/React.hs view
@@ -57,7 +57,7 @@ foreign import javascript unsafe "React['addons']['CSSTransitionGroup']"- js_CSSTransitionGroup :: JSRef ()+ js_CSSTransitionGroup :: JSRef #else cssTransitionGroup _ x = x
src/React/Flux/Export.hs view
@@ -1,5 +1,5 @@--- | Replace this with Export from improved-base branch of ghcjs-base once--- the improved-base branch becomes the default+-- | At some point this should be replaced by GHCJS.Foreign.Export, but GHCJS.Foreign.Export+-- currently causes a bug in the Todo example application to appear. module React.Flux.Export where #ifdef __GHCJS__@@ -9,7 +9,7 @@ import GHCJS.Types -newtype Export a = Export (JSRef ())+newtype Export a = Export JSRef foreign import javascript unsafe "hsreact$export($1)"
src/React/Flux/Internal.hs view
@@ -8,6 +8,7 @@ , ReactElementRef(..) , HandlerArg(..) , PropertyOrHandler(..)+ , property , ReactElement(..) , ReactElementM(..) , elemText@@ -21,36 +22,42 @@ import Data.String (IsString(..)) import Data.Aeson-import Data.Aeson.Types (Pair) import Data.Typeable (Typeable) import Control.Monad.Writer import Control.Monad.Identity (Identity(..)) #ifdef __GHCJS__-import qualified Data.Text as T import Unsafe.Coerce import qualified Data.JSString as JSS import qualified JavaScript.Array as JSA import GHCJS.Foreign.Callback import qualified JavaScript.Object as JSO-import GHCJS.Types (JSRef, castRef, JSString)-import GHCJS.Marshal (toJSRef_aeson, ToJSRef(..), fromJSRef)+import GHCJS.Types (JSRef, JSString, IsJSRef, jsref)+import GHCJS.Marshal (ToJSRef(..), fromJSRef) import React.Flux.Export #else+import Data.Text (Text) type Callback a = ()-type JSRef a = ()+type JSRef = ()+class ToJSRef a+instance ToJSRef Value+instance ToJSRef Text+class IsJSRef a #endif -- type JSObject a = JSO.Object a -- | This type is for the return value of @React.createClass@-newtype ReactViewRef props = ReactViewRef { reactViewRef :: JSRef () }+newtype ReactViewRef props = ReactViewRef { reactViewRef :: JSRef }+instance IsJSRef (ReactViewRef props) -- | This type is for the return value of @React.createElement@-newtype ReactElementRef = ReactElementRef { reactElementRef :: JSRef () }+newtype ReactElementRef = ReactElementRef { reactElementRef :: JSRef }+instance IsJSRef ReactElementRef -- | The first parameter of an event handler registered with React.-newtype HandlerArg = HandlerArg (JSRef ())+newtype HandlerArg = HandlerArg JSRef+instance IsJSRef HandlerArg instance Show HandlerArg where show _ = "HandlerArg"@@ -60,7 +67,14 @@ -- The combination of all properties and event handlers are used to create the javascript object -- passed as the second argument to @React.createElement@. data PropertyOrHandler handler =- Property Pair+ forall ref. ToJSRef ref => Property+ { propertyName :: String+ , propertyVal :: ref+ }+ | ElementProperty+ { elementPropertyName :: String+ , elementValue :: ReactElementM handler ()+ } | EventHandler { evtHandlerName :: String , evtHandler :: HandlerArg -> handler@@ -71,20 +85,26 @@ } instance Functor PropertyOrHandler where- fmap _ (Property p) = Property p+ fmap _ (Property name val) = Property name val+ fmap f (ElementProperty name (ReactElementM mkElem)) =+ ElementProperty name $ ReactElementM $ mapWriter (\((),e) -> ((), fmap f e)) mkElem fmap f (EventHandler name h) = EventHandler name (f . h) fmap f (CallbackProperty name g) = CallbackProperty name (f . g) +-- | Create a property from anything that can be converted to a JSRef+property :: ToJSRef val => String -> val -> PropertyOrHandler handler+property = Property+ -- | Keys in React can either be strings or integers class ReactViewKey key where- toKeyRef :: key -> IO (JSRef ())+ toKeyRef :: key -> IO JSRef #if __GHCJS__ instance ReactViewKey String where toKeyRef = return . unsafeCoerce . toJSString instance ReactViewKey Int where- toKeyRef i = castRef <$> toJSRef i+ toKeyRef i = toJSRef i #else instance ReactViewKey String where toKeyRef = const $ return ()@@ -202,27 +222,81 @@ -- | Execute a ReactElementM to create a javascript React element and a list of callbacks attached -- to nodes within the element. These callbacks will need to be released with 'releaseCallback' -- once the class is re-rendered.-mkReactElement :: (eventHandler -> IO ())+mkReactElement :: forall eventHandler.+ (eventHandler -> IO ()) -> IO [ReactElementRef] -- ^ this.props.children -> ReactElementM eventHandler ()- -> IO (ReactElementRef, [Callback (JSRef () -> IO ())])+ -> IO (ReactElementRef, [Callback (JSRef -> IO ())]) #ifdef __GHCJS__ -mkReactElement runHandler getPropsChildren eM = runWriterT $ do- let e = execWriter $ runReactElementM eM- e' = case e of- Content txt -> ForeignElement (Left "span") [] (Content txt)- _ -> e- refs <- createElement getPropsChildren $ fmap runHandler e'- case refs of- [] -> lift $ js_ReactCreateElementNoChildren "div"- [x] -> return x- xs -> lift $ do- emptyObj <- JSO.create- let arr = JSA.fromList $ map reactElementRef xs- js_ReactCreateElementName "div" emptyObj arr+mkReactElement runHandler getPropsChildren = runWriterT . mToElem+ where+ -- Run the ReactElementM monad to create a ReactElementRef.+ mToElem :: ReactElementM eventHandler () -> MkReactElementM ReactElementRef+ mToElem eM = do+ let e = execWriter $ runReactElementM eM+ e' = case e of+ Content txt -> ForeignElement (Left "span") [] (Content txt)+ _ -> e+ refs <- createElement e'+ case refs of+ [] -> lift $ js_ReactCreateElementNoChildren "div"+ [x] -> return x+ xs -> lift $ do+ emptyObj <- JSO.create+ let arr = JSA.fromList $ map reactElementRef xs+ js_ReactCreateElementName "div" emptyObj arr + -- add the property or handler to the javascript object+ addPropOrHandlerToObj :: JSO.Object -> PropertyOrHandler eventHandler -> MkReactElementM ()+ addPropOrHandlerToObj obj (Property n val) = lift $ do+ vRef <- toJSRef val+ JSO.setProp (toJSString n) vRef obj+ addPropOrHandlerToObj obj (ElementProperty name rM) = do+ ReactElementRef ref <- mToElem rM+ lift $ JSO.setProp (toJSString name) ref obj+ addPropOrHandlerToObj obj (EventHandler str handler) = do+ -- this will be released by the render function of the class (jsbits/class.js)+ cb <- lift $ syncCallback1 ContinueAsync $ \evtRef ->+ runHandler $ handler $ HandlerArg evtRef+ tell [cb]+ lift $ JSO.setProp (toJSString str) (jsref cb) obj+ addPropOrHandlerToObj obj (CallbackProperty str handler) = do+ cb <- lift $ syncCallback1 ContinueAsync $ \argref -> do+ v <- fromJSRef argref+ runHandler $ handler $ maybe (error "Unable to decode callback value") id v+ tell [cb]+ lift $ JSO.setProp (toJSString str) (jsref cb) obj++ -- call React.createElement+ createElement :: ReactElement eventHandler -> MkReactElementM [ReactElementRef]+ createElement EmptyElement = return []+ createElement (Append x y) = (++) <$> createElement x <*> createElement y+ createElement (Content s) = return [js_ReactCreateContent s]+ createElement ChildrenPassedToView = lift getPropsChildren+ createElement (f@(ForeignElement{})) = do+ obj <- lift $ JSO.create+ mapM_ (addPropOrHandlerToObj obj) $ fProps f+ childNodes <- createElement $ fChild f+ let childArr = JSA.fromList $ map reactElementRef childNodes+ e <- lift $ case fName f of+ Left s -> js_ReactCreateElementName (toJSString s) obj childArr+ Right ref -> js_ReactCreateForeignElement ref obj childArr+ return [e]+ createElement (ViewElement { ceClass = rc, ceProps = props, ceKey = mkey, ceChild = child }) = do+ childNodes <- createElement child+ propsE <- lift $ export props -- this will be released inside the lifetime events for the class (jsbits/class.js)+ let arr = JSA.fromList $ map reactElementRef childNodes+ e <- lift $ case mkey of+ Just key -> do+ keyRef <- toKeyRef key+ js_ReactCreateKeyedElement rc keyRef propsE arr+ Nothing -> js_ReactCreateClass rc propsE arr+ return [e]++type MkReactElementM a = WriterT [Callback (JSRef -> IO ())] IO a+ foreign import javascript unsafe "React['createElement']($1)" js_ReactCreateElementNoChildren :: JSString -> IO ReactElementRef@@ -241,62 +315,18 @@ foreign import javascript unsafe "React['createElement']($1, {key: $2, hs:$3}, $4)"- js_ReactCreateKeyedElement :: ReactViewRef a -> JSRef key -> Export props -> JSA.JSArray -> IO ReactElementRef+ js_ReactCreateKeyedElement :: ReactViewRef a -> JSRef -> Export props -> JSA.JSArray -> IO ReactElementRef js_ReactCreateContent :: String -> ReactElementRef js_ReactCreateContent = ReactElementRef . unsafeCoerce . toJSString -addPropOrHandlerToObj :: JSO.Object -> PropertyOrHandler (IO ()) -> WriterT [Callback (JSRef () -> IO ())] IO ()-addPropOrHandlerToObj obj (Property (n, v)) = lift $ do- vRef <- toJSRef_aeson v- JSO.setProp (toJSString $ T.unpack n) vRef obj-addPropOrHandlerToObj obj (EventHandler str handler) = do- -- this will be released by the render function of the class (jsbits/class.js)- cb <- lift $ syncCallback1 ContinueAsync $ \evtRef ->- handler $ HandlerArg evtRef- tell [cb]- cbRef <- lift $ toJSRef cb- lift $ JSO.setProp (toJSString str) cbRef obj-addPropOrHandlerToObj obj (CallbackProperty str handler) = do- cb <- lift $ syncCallback1 ContinueAsync $ \argref -> do- v <- fromJSRef $ castRef argref- handler $ maybe (error "Unable to decode callback value") id v- tell [cb]- cbRef <- lift $ toJSRef cb- lift $ JSO.setProp (toJSString str) cbRef obj--createElement :: IO [ReactElementRef] -> ReactElement (IO ()) -> WriterT [Callback (JSRef () -> IO ())] IO [ReactElementRef]-createElement _ EmptyElement = return []-createElement c (Append x y) = (++) <$> createElement c x <*> createElement c y-createElement _ (Content s) = return [js_ReactCreateContent s]-createElement c ChildrenPassedToView = lift c-createElement c (f@(ForeignElement{})) = do- obj <- lift $ JSO.create- mapM_ (addPropOrHandlerToObj obj) $ fProps f- childNodes <- createElement c $ fChild f- let childArr = JSA.fromList $ map reactElementRef childNodes- e <- lift $ case fName f of- Left s -> js_ReactCreateElementName (toJSString s) obj childArr- Right ref -> js_ReactCreateForeignElement ref obj childArr- return [e]-createElement c (ViewElement { ceClass = rc, ceProps = props, ceKey = mkey, ceChild = child }) = do- childNodes <- createElement c child- propsE <- lift $ export props -- this will be released inside the lifetime events for the class (jsbits/class.js)- let arr = JSA.fromList $ map reactElementRef childNodes- e <- lift $ case mkey of- Just key -> do- keyRef <- toKeyRef key- js_ReactCreateKeyedElement rc keyRef propsE arr- Nothing -> js_ReactCreateClass rc propsE arr- return [e]- toJSString :: String -> JSString toJSString = JSS.pack #else+mkReactElement _ _ _ = return (ReactElementRef (), [])+ toJSString :: String -> String toJSString = id--mkReactElement _ _ _ = return (ReactElementRef (), []) #endif
src/React/Flux/Lifecycle.hs view
@@ -50,12 +50,11 @@ import GHCJS.Foreign (jsNull) import GHCJS.Foreign.Callback-import GHCJS.Marshal (ToJSRef(..))-import GHCJS.Types (JSRef, castRef)+import GHCJS.Types (JSRef, jsref) #endif -type HTMLElement = JSRef ()+type HTMLElement = JSRef -- | Actions to access the current properties and state. data LPropsAndState props state = LPropsAndState@@ -136,7 +135,7 @@ f (dom this) (setStateFn this) willRecvPropsCb <- mkLCallback2 (lComponentWillReceiveProps cfg) $ \f this newPropsE -> do- newProps <- parseExport $ Export $ castRef newPropsE+ newProps <- parseExport $ Export newPropsE f (dom this) (setStateFn this) newProps willUpdateCb <- mkLCallback2 (lComponentWillUpdate cfg) $ \f this argRef -> do@@ -166,7 +165,7 @@ mkLCallback1 :: (Typeable props, Typeable state) => Maybe (LPropsAndState props state -> f) -> (f -> ReactThis state props -> IO ())- -> IO (JSRef (Callback (JSRef () -> IO ())))+ -> IO JSRef mkLCallback1 Nothing _ = return jsNull mkLCallback1 (Just f) c = do cb <- syncCallback1 ThrowWouldBlock $ \thisRef -> do@@ -175,12 +174,12 @@ , lGetState = js_ReactGetState this >>= parseExport } c (f ps) this- toJSRef cb+ return $ jsref cb mkLCallback2 :: (Typeable props, Typeable state) => Maybe (LPropsAndState props state -> f)- -> (f -> ReactThis state props -> JSRef a -> IO ())- -> IO (JSRef (Callback (JSRef () -> JSRef a -> IO ())))+ -> (f -> ReactThis state props -> JSRef -> IO ())+ -> IO JSRef mkLCallback2 Nothing _ = return jsNull mkLCallback2 (Just f) c = do cb <- syncCallback2 ThrowWouldBlock $ \thisRef argRef -> do@@ -189,7 +188,7 @@ , lGetState = js_ReactGetState this >>= parseExport } c (f ps) this argRef- toJSRef cb+ return $ jsref cb #else
src/React/Flux/PropertiesAndEvents.hs view
@@ -5,6 +5,8 @@ PropertyOrHandler , (@=) , ($=)+ , property+ , elementProperty , callback -- * Events@@ -87,30 +89,38 @@ #ifdef __GHCJS__ import Data.Maybe (fromMaybe) -import qualified Data.JSString as JSS import GHCJS.Foreign (fromJSBool) import GHCJS.Marshal (FromJSRef(..))-import GHCJS.Types (JSRef, nullRef, JSString)+import GHCJS.Types (JSRef, nullRef, JSString, IsJSRef) import JavaScript.Array as JSA #else-type JSRef a = ()+type JSRef = () type JSString = String type JSArray = () class FromJSRef a+class IsJSRef a nullRef :: () nullRef = () #endif +-- TOOD: change these to take a String next time we bump the major version+ -- | Create a property. (@=) :: A.ToJSON a => T.Text -> a -> PropertyOrHandler handler-n @= a = Property (n, A.toJSON a)+n @= a = Property (T.unpack n) (A.toJSON a) -- | Create a text-valued property. This is here to avoid problems when OverloadedStrings extension -- is enabled ($=) :: T.Text -> T.Text -> PropertyOrHandler handler-n $= a = Property (n, A.toJSON a)+n $= a = Property (T.unpack n) a +-- | Some third-party React classes allow passing React elements as properties. This function+-- will first run the given 'ReactElementM' to obtain an element or elements, and then use that+-- element as the value for a property with the given key.+elementProperty :: String -> ReactElementM handler () -> PropertyOrHandler handler+elementProperty = ElementProperty+ -- | Create a callback property. This is primarily intended for foreign React classes which expect -- callbacks to be passed to them as properties. For events on DOM elements, you should instead use -- the handlers below.@@ -123,7 +133,8 @@ -- | A reference to the object that dispatched the event. -- <https://developer.mozilla.org/en-US/docs/Web/API/Event/target>-newtype EventTarget = EventTarget (JSRef ())+newtype EventTarget = EventTarget JSRef+instance IsJSRef EventTarget instance Show (EventTarget) where show _ = "EventTarget"@@ -226,11 +237,11 @@ foreign import javascript unsafe "$1['preventDefault']();"- js_preventDefault :: JSRef () -> IO ()+ js_preventDefault :: JSRef -> IO () foreign import javascript unsafe "$1['stopPropagation']();"- js_stopProp :: JSRef () -> IO ()+ js_stopProp :: JSRef -> IO () #else @@ -476,7 +487,7 @@ show (TouchEvent t1 t2 t3 _ t4 t5 t6 t7) = show (t1, t2, t3, t4, t5, t6, t7) -parseTouch :: JSRef a -> Touch+parseTouch :: JSRef -> Touch parseTouch o = Touch { touchIdentifier = o .: "identifier" , touchTarget = EventTarget $ js_getProp o "target"@@ -488,7 +499,7 @@ , touchPageY = o .: "pageY" } -parseTouchList :: JSRef a -> JSString -> [Touch]+parseTouchList :: JSRef -> JSString -> [Touch] parseTouchList obj key = unsafePerformIO $ do let arr = js_getArrayProp obj key len = arrayLength arr@@ -569,49 +580,49 @@ foreign import javascript unsafe "$1[$2]"- js_getProp :: JSRef a -> JSString -> JSRef b+ js_getProp :: JSRef -> JSString -> JSRef foreign import javascript unsafe "$1[$2]"- js_getArrayProp :: JSRef a -> JSString -> JSA.JSArray+ js_getArrayProp :: JSRef -> JSString -> JSA.JSArray -- | Access a property from an object. Since event objects are immutable, we can use -- unsafePerformIO without worry.-(.:) :: FromJSRef b => JSRef a -> JSString -> b+(.:) :: FromJSRef b => JSRef -> JSString -> b obj .: key = fromMaybe (error "Unable to decode event target") $ unsafePerformIO $ fromJSRef $ js_getProp obj key foreign import javascript unsafe "$1['getModifierState']($2)"- js_GetModifierState :: JSRef () -> JSString -> JSRef Bool+ js_GetModifierState :: JSRef -> JSString -> JSRef -getModifierState :: JSRef () -> String -> Bool+getModifierState :: JSRef -> String -> Bool getModifierState ref = fromJSBool . js_GetModifierState ref . toJSString arrayLength :: JSArray -> Int arrayLength = JSA.length -arrayIndex :: Int -> JSArray -> JSRef a+arrayIndex :: Int -> JSArray -> JSRef arrayIndex = JSA.index #else -js_getProp :: a -> String -> JSRef b+js_getProp :: a -> String -> JSRef js_getProp _ _ = () -js_getArrayProp :: a -> String -> JSRef b+js_getArrayProp :: a -> String -> JSRef js_getArrayProp _ _ = () -(.:) :: JSRef () -> String -> b+(.:) :: JSRef -> String -> b _ .: _ = undefined -getModifierState :: JSRef () -> String -> Bool+getModifierState :: JSRef -> String -> Bool getModifierState _ _ = False arrayLength :: JSArray -> Int arrayLength _ = 0 -arrayIndex :: Int -> JSArray -> JSRef ()+arrayIndex :: Int -> JSArray -> JSRef arrayIndex _ _ = () #endif
src/React/Flux/Store.hs view
@@ -16,14 +16,16 @@ import System.IO.Unsafe (unsafePerformIO) #ifdef __GHCJS__-import GHCJS.Types (JSRef, isNull)+import GHCJS.Types (JSRef, isNull, IsJSRef) import React.Flux.Export (Export, export) #else-type JSRef a = ()+type JSRef = ()+class IsJSRef a #endif -- | This type is used to represent the foreign javascript object part of the store.-newtype ReactStoreRef storeData = ReactStoreRef (JSRef ())+newtype ReactStoreRef storeData = ReactStoreRef JSRef+instance IsJSRef (ReactStoreRef storeData) -- | A store contains application state, receives actions from the dispatcher, and notifies -- component views to re-render themselves. You can have multiple stores; it should be the case
src/React/Flux/Views.hs view
@@ -13,11 +13,11 @@ import React.Flux.Export import JavaScript.Array import GHCJS.Foreign.Callback-import GHCJS.Types (JSRef, castRef, JSString)+import GHCJS.Types (JSRef, JSString, IsJSRef, jsref) import GHCJS.Marshal (ToJSRef(..)) #else-type JSRef a = ()+type JSRef = () #endif @@ -273,7 +273,8 @@ #ifdef __GHCJS__ -newtype ReactThis state props = ReactThis (JSRef ())+newtype ReactThis state props = ReactThis JSRef+instance IsJSRef (ReactThis state props) foreign import javascript unsafe "$1['state'].hs"@@ -293,30 +294,31 @@ foreign import javascript unsafe "React['findDOMNode']($1)"- js_ReactFindDOMNode :: ReactThis state props -> IO (JSRef a)+ js_ReactFindDOMNode :: ReactThis state props -> IO JSRef foreign import javascript unsafe "React['findDOMNode']($1['refs'][$2])"- js_ReactGetRef :: ReactThis state props -> JSString -> IO (JSRef a)+ js_ReactGetRef :: ReactThis state props -> JSString -> IO JSRef -newtype RenderCbArg = RenderCbArg (JSRef ())+newtype RenderCbArg = RenderCbArg JSRef+instance IsJSRef RenderCbArg foreign import javascript unsafe "$1.newCallbacks = $2; $1.elem = $3;"- js_RenderCbSetResults :: RenderCbArg -> JSRef [Callback (JSRef () -> IO ())] -> ReactElementRef -> IO ()+ js_RenderCbSetResults :: RenderCbArg -> JSRef -> ReactElementRef -> IO () foreign import javascript unsafe "hsreact$mk_ctrl_view($1, $2, $3)" js_createControllerView :: JSString -> ReactStoreRef storeData- -> Callback (JSRef () -> JSRef () -> IO ())+ -> Callback (JSRef -> JSRef -> IO ()) -> IO (ReactViewRef props) -- | Create a view with no state. foreign import javascript unsafe "hsreact$mk_view($1, $2)" js_createView :: JSString- -> Callback (JSRef () -> JSRef () -> IO ())+ -> Callback (JSRef -> JSRef -> IO ()) -> IO (ReactViewRef props) -- | Create a view which tracks its own state. Similar releasing needs to happen for callbacks and@@ -325,19 +327,19 @@ "hsreact$mk_stateful_view($1, $2, $3)" js_createStatefulView :: JSString -> Export state- -> Callback (JSRef () -> JSRef () -> IO ())+ -> Callback (JSRef -> JSRef -> IO ()) -> IO (ReactViewRef props) foreign import javascript unsafe "hsreact$mk_lifecycle_view($1, $2, $3, $4, $5, $6, $7, $8, $9)"- js_makeLifecycleView :: JSString -> Export state -> Callback (JSRef () -> JSRef () -> IO ())- -> JSRef a -> JSRef b -> JSRef c -> JSRef d -> JSRef e -> JSRef f -> IO (ReactViewRef props)+ js_makeLifecycleView :: JSString -> Export state -> Callback (JSRef -> JSRef -> IO ())+ -> JSRef -> JSRef -> JSRef -> JSRef -> JSRef -> JSRef -> IO (ReactViewRef props) mkRenderCallback :: Typeable props => (ReactThis state props -> IO state) -- ^ parse state -> (ReactThis state props -> eventHandler -> IO ()) -- ^ execute event args -> (state -> props -> IO (ReactElementM eventHandler ())) -- ^ renderer- -> IO (Callback (JSRef () -> JSRef () -> IO ()))+ -> IO (Callback (JSRef -> JSRef -> IO ())) mkRenderCallback parseState runHandler render = syncCallback2 ContinueAsync $ \thisRef argRef -> do let this = ReactThis thisRef arg = RenderCbArg argRef@@ -351,7 +353,7 @@ (element, evtCallbacks) <- mkReactElement (runHandler this) getPropsChildren node - evtCallbacksRef <- toJSRef evtCallbacks+ evtCallbacksRef <- toJSRef $ map jsref evtCallbacks js_RenderCbSetResults arg evtCallbacksRef element parseExport :: Typeable a => Export a -> IO a@@ -397,7 +399,7 @@ -- -- >foreign import javascript unsafe -- > "window['Select']"--- > js_ReactSelectClass :: JSRef ()+-- > js_ReactSelectClass :: JSRef -- > -- >reactSelect_ :: [PropertyOrHandler eventHandler] -> ReactElementM eventHandler () -- >reactSelect_ props = foreignClass js_ReactSelectClass props mempty@@ -422,7 +424,7 @@ -- > ] -- > , onSelectChange dispatchSomething -- > ]-foreignClass :: JSRef cl -- ^ The javascript reference to the class+foreignClass :: JSRef -- ^ The javascript reference to the class -> [PropertyOrHandler eventHandler] -- ^ properties and handlers to pass when creating an instance of this class. -> ReactElementM eventHandler a -- ^ The child element or elements -> ReactElementM eventHandler a@@ -431,7 +433,7 @@ foreignClass name attrs (ReactElementM child) = let (a, childEl) = runWriter child- in elementToM a $ ForeignElement (Right $ ReactViewRef $ castRef name) attrs childEl+ in elementToM a $ ForeignElement (Right $ ReactViewRef name) attrs childEl #else foreignClass _ _ x = x
test/client/TestClient.hs view
@@ -134,7 +134,7 @@ foreign import javascript unsafe "$1.id"- js_domGetId :: JSRef a -> IO (JSRef String)+ js_domGetId :: JSRef -> IO JSRef logDOM :: LDOM -> IO () logDOM dom = do