diff --git a/docs/React.md b/docs/React.md index cc41134..067a560 100644 --- a/docs/React.md +++ b/docs/React.md @@ -160,6 +160,14 @@ type UISpec props state eff = { render :: Render props state eff, displayName :: A specification of a component. +#### `UIFactory` + +``` purescript +type UIFactory props = props -> UI +``` + +Factory function for components. + #### `spec` ``` purescript @@ -184,6 +192,14 @@ getRefs :: forall write eff. UIRef -> Eff (refs :: ReactRefs (Read write) | eff) Read the component refs. +#### `getChildren` + +``` purescript +getChildren :: forall props eff. UIRef -> Eff (props :: ReactProps props | eff) (Array UI) +``` + +Read the component children property. + #### `writeState` ``` purescript @@ -211,7 +227,7 @@ Transform the component state by applying a function. #### `mkUI` ``` purescript -mkUI :: forall props state eff. UISpec props state eff -> props -> UI +mkUI :: forall props state eff. UISpec props state eff -> UIFactory props ``` Create a component from a component spec. @@ -248,4 +264,12 @@ renderToElementById :: forall eff. String -> UI -> Eff (dom :: DOM | eff) UI Render a component to the element with the specified ID. +#### `createElement` + +``` purescript +createElement :: forall props. UIFactory props -> props -> Array UI -> UI +``` + +Create an element from a component factory. + diff --git a/src/React.js b/src/React.js index d5b17e5..5c4ca38 100644 --- a/src/React.js +++ b/src/React.js @@ -15,6 +15,12 @@ exports.getRefs = function(ctx) { }; }; +exports.getChildren = function(ctx) { + return function() { + return ctx.props.children; + }; +}; + exports.writeState = function(ctx) { return function(state) { return function() { @@ -79,3 +85,11 @@ exports.renderToElementById = function(id) { } } }; + +exports.createElement = function(factory) { + return function(props) { + return function(children){ + return React.createElement.apply(React, [factory, props].concat(children)); + }; + }; +}; diff --git a/src/React.purs b/src/React.purs index 6f4bd5c..a4dacf2 100644 --- a/src/React.purs +++ b/src/React.purs @@ -22,6 +22,7 @@ module React , Render() , UISpec() + , UIFactory() , Event() , MouseEvent() @@ -33,6 +34,7 @@ module React , getProps , getRefs + , getChildren , readState , writeState @@ -45,6 +47,7 @@ module React , renderToString , renderToBody , renderToElementById + , createElement ) where import Prelude @@ -202,6 +205,9 @@ type UISpec props state eff = ) Unit } +-- | Factory function for components. +type UIFactory props = props -> UI + -- | Create a component specification. spec :: forall props state eff. state -> Render props state eff -> UISpec props state eff spec st render = @@ -227,6 +233,11 @@ foreign import getRefs :: forall write eff. UIRef -> Eff (refs :: ReactRefs (Read write) | eff) Refs +-- | Read the component children property. +foreign import getChildren :: forall props eff. + UIRef -> + Eff (props :: ReactProps props | eff) (Array UI) + -- | Write the component state. foreign import writeState :: forall state eff. UIRef -> @@ -250,8 +261,7 @@ transformState ctx f = do -- | Create a component from a component spec. foreign import mkUI :: forall props state eff. UISpec props state eff -> - props -> - UI + UIFactory props -- | Create an event handler. foreign import handle :: forall eff ev props state result. @@ -266,3 +276,6 @@ foreign import renderToBody :: forall eff. UI -> Eff (dom :: DOM | eff) UI -- | Render a component to the element with the specified ID. foreign import renderToElementById :: forall eff. String -> UI -> Eff (dom :: DOM | eff) UI + +-- | Create an element from a component factory. +foreign import createElement :: forall props. UIFactory props -> props -> Array UI -> UI diff --git a/test/Container.purs b/test/Container.purs new file mode 100644 index 0000000..526409c --- /dev/null +++ b/test/Container.purs @@ -0,0 +1,19 @@ +module Test.Container where + +import Prelude + +import React + +import qualified React.DOM as D +import qualified React.DOM.Props as P + +container = mkUI $ spec unit \ctx -> do + children <- getChildren ctx + + let ui = D.div [ P.style { borderColor: "red" + , borderWidth: 2 + , padding: 10 + } + ] children + + return ui diff --git a/test/Main.purs b/test/Main.purs index 4bc8552..565bfc3 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -10,8 +10,10 @@ import React import qualified React.DOM as D import qualified React.DOM.Props as P -foreign import interval :: forall eff a. - Int -> +import Test.Container (container) + +foreign import interval :: forall eff a. + Int -> Eff eff a -> Eff eff Unit @@ -19,7 +21,7 @@ hello = mkUI $ spec unit \ctx -> do props <- getProps ctx return $ D.h1 [ P.className "Hello" , P.style { background: "lightgray" } - ] + ] [ D.text "Hello, " , D.text props.name ] @@ -44,5 +46,13 @@ counter = mkUI counterSpec ] main = do - let component = D.div' [ hello { name: "World" }, counter unit ] + let component = D.div' [ + hello { name: "World" }, + counter unit, + createElement container unit [ + D.p [] [ D.text "This is line one" ], + D.p [] [ D.text "This is line two" ] + ] + ] + renderToBody component