diff --git a/README.md b/README.md
index 3986040..0b173ba 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,6 @@
-purescript-react
-================
+# purescript-react
-[](http://github.com/paf31) 
+[](http://github.com/paf31) 
Low-level React Bindings for PureScript.
@@ -9,71 +8,10 @@ For a more high-level set of bindings, you might like to look at `purescript-the
- [Module Documentation](docs/)
-## Dynamic children
-
-There are two ways that child elements can be passed to components:
-- The first way is to spread the child element array when passing them to React's `createElement` function. The [React.DOM](docs/React/DOM.md) and [React.DOM.SVG](docs/React/DOM/SVG.md) spread the child element array.
-- The second way is to pass the child element array to `createElement` without spreading. This is useful when dealing with [dynamic children](https://facebook.github.io/react/docs/multiple-components.html#dynamic-children). In this case a `key` property should be assigned direclty to each child. The [React.DOM.Dynamic](docs/React/DOM/Dynamic.md) and [React.DOM.SVG.Dynamic](docs/React/DOM/SVG/Dynamic.md) pass the child element array without spreading.
-
-Note that this module provides functions `createElement` and `createElementDynamic` to handle the two cases above for component classes.
-
-## Building
-
-The library and example can be built with Pulp as follows:
-
- pulp dep update
- pulp build
-
- pulp test -r cat > example/index.js
- open example/index.html
+```
+bower install purescript-react
+```
## Example
-```purescript
-module Main where
-
-import Prelude
-
-import Control.Monad.Eff
-
-import Data.Maybe.Unsafe (fromJust)
-import Data.Nullable (toMaybe)
-
-import DOM (DOM())
-import DOM.HTML (window)
-import DOM.HTML.Document (body)
-import DOM.HTML.Types (htmlElementToElement)
-import DOM.HTML.Window (document)
-
-import DOM.Node.Types (Element())
-
-import React
-
-import qualified React.DOM as D
-import qualified React.DOM.Props as P
-
-incrementCounter ctx e = do
- val <- readState ctx
- writeState ctx (val + 1)
-
-counter = createClass $ spec 0 \ctx -> do
- val <- readState ctx
- return $ D.p [ P.className "Counter"
- , P.onClick (incrementCounter ctx)
- ]
- [ D.text (show val)
- , D.text " Click me to increment!"
- ]
-
-main = container >>= render ui
- where
- ui :: ReactElement
- ui = D.div [] [ createFactory counter {} ]
-
- container :: forall eff. Eff (dom :: DOM | eff) Element
- container = do
- win <- window
- doc <- document win
- elm <- fromJust <$> toMaybe <$> body doc
- return $ htmlElementToElement elm
-```
+Please refer to [purescript-react-example](https://github.com/purescript-contrib/purescript-react)
diff --git a/bower.json b/bower.json
index 85aa2d2..93e66b0 100644
--- a/bower.json
+++ b/bower.json
@@ -1,29 +1,23 @@
{
"name": "purescript-react",
- "version": "0.0.5",
"homepage": "https://github.com/purescript-contrib/purescript-react",
- "description": "Purescript bindings for React.js",
+ "description": "PureScript bindings for react",
+ "main": "",
"keywords": [
"purescript",
"react"
],
"license": "MIT",
"ignore": [
- "**/.*",
- "node_modules",
- "bower_components",
- "test",
- "tests"
+ "*",
+ "!src/**/*"
],
"repository": {
"type": "git",
"url": "git://github.com/purescript-contrib/purescript-react.git"
},
"dependencies": {
- "purescript-dom": "~0.2.6"
- },
- "devDependencies": {
- "purescript-console": "~0.1.1",
- "react": "~0.13.3"
+ "purescript-eff": "~0.1.2",
+ "purescript-unsafe-coerce": "~0.1.0"
}
}
diff --git a/docs/React.md b/docs/React.md
index 08ab7bb..b8a73b9 100644
--- a/docs/React.md
+++ b/docs/React.md
@@ -18,6 +18,14 @@ data ReactElement :: *
A virtual DOM node, or component.
+#### `ReactComponent`
+
+``` purescript
+data ReactComponent :: *
+```
+
+A mounted react component
+
#### `ReactThis`
``` purescript
@@ -302,6 +310,14 @@ createClass :: forall props state eff. ReactSpec props state eff -> ReactClass p
Create a React class from a specification.
+#### `createClassStateless`
+
+``` purescript
+createClassStateless :: forall props. (props -> ReactElement) -> ReactClass props
+```
+
+Create a stateless React class.
+
#### `handle`
``` purescript
@@ -350,20 +366,4 @@ createFactory :: forall props. ReactClass props -> props -> ReactElement
Create a factory from a React class.
-#### `render`
-
-``` purescript
-render :: forall eff. ReactElement -> Element -> Eff (dom :: DOM | eff) ReactElement
-```
-
-Render a React element in a document element.
-
-#### `renderToString`
-
-``` purescript
-renderToString :: ReactElement -> String
-```
-
-Render a React element as a string.
-
diff --git a/example/.gitignore b/example/.gitignore
deleted file mode 100644
index 012a3cd..0000000
--- a/example/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-index.js
diff --git a/example/index.html b/example/index.html
deleted file mode 100644
index 3c2916c..0000000
--- a/example/index.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
- purescript-react example
-
-
-
-
-
-
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..d6126cc
--- /dev/null
+++ b/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "purescript-react",
+ "files": [],
+ "peerDependencies": {
+ "react": "^0.14.3"
+ }
+}
diff --git a/src/React.js b/src/React.js
index c35c5bc..2d42dd1 100644
--- a/src/React.js
+++ b/src/React.js
@@ -3,21 +3,25 @@
// module React
-exports.getProps = function(ctx) {
- return function() {
- return ctx.props;
- };
-};
+var React = require('react');
-exports.getRefs = function(ctx) {
- return function() {
- return ctx.refs;
- };
-};
+function getProps(this_) {
+ return function(){
+ return this_.props;
+ };
+}
+exports.getProps = getProps;
+
+function getRefs(this_) {
+ return function(){
+ return this_.refs;
+ };
+}
+exports.getRefs = getRefs;
-exports.getChildren = function(ctx) {
- return function() {
- var children = ctx.props.children;
+function getChildren(this_) {
+ return function(){
+ var children = this_.props.children;
var result = [];
@@ -27,115 +31,94 @@ exports.getChildren = function(ctx) {
return result;
};
-};
-
-exports.writeState = function(ctx) {
- return function(state) {
- return function() {
- ctx.replaceState({
- state: state
- });
- return function() {
- return state;
- }
- };
- };
-};
-
-exports.readState = function(ctx) {
- return function() {
- return ctx.state.state;
+}
+exports.getChildren = getChildren;
+
+function writeState(this_) {
+ return function(state){
+ return function(){
+ this_.setState({
+ state: state
+ });
+ return state;
};
-};
+ };
+}
+exports.writeState = writeState;
-exports.createClass = function(ss) {
- var result = {};
- for (var s in ss) {
- if (ss.hasOwnProperty(s)) {
- if (s === "displayName") {
- result[s] = ss[s];
- }
- else if (s === "componentWillReceiveProps") {
- result[s] = (function(impl) {
- return function(nextProps) {
- return impl(this)(nextProps)();
- }
- })(ss[s]);
- }
- else if (s === "shouldComponentUpdate") {
- result[s] = (function(impl) {
- return function(nextProps, nextState) {
- return impl(this)(nextProps)(nextState.state)();
- }
- })(ss[s]);
- }
- else if (s === "componentWillUpdate") {
- result[s] = (function(impl) {
- return function(nextProps, nextState) {
- return impl(this)(nextProps)(nextState.state)();
- }
- })(ss[s]);
- }
- else if (s === "componentDidUpdate") {
- result[s] = (function(impl) {
- return function(prevProps, prevState) {
- return impl(this)(prevProps)(prevState.state)();
- }
- })(ss[s]);
- }
- else {
- result[s] = (function(impl) {
- return function() {
- return impl(this)();
- }
- })(ss[s]);
- }
- }
+function readState(this_) {
+ return function(){
+ return this_.state.state;
+ };
+}
+exports.readState = readState;
+
+function createClass(spec) {
+ var result = {
+ displayName: spec.displayName,
+ render: function(){
+ return spec.render(this)();
+ },
+ getInitialState: function(){
+ return {
+ state: spec.getInitialState(this)()
+ };
+ },
+ componentWillMount: function(){
+ return spec.componentWillMount(this)();
+ },
+ componentDidMount: function(){
+ return spec.componentDidMount(this)();
+ },
+ componentWillReceiveProps: function(nextProps){
+ return spec.componentWillReceiveProps(this)(nextProps)();
+ },
+ shouldComponentUpdate: function(nextProps, nextState){
+ return spec.shouldComponentUpdate(this)(nextProps)(nextState.state)();
+ },
+ componentWillUpdate: function(nextProps, nextState){
+ return spec.componentWillUpdate(this)(nextProps)(nextState.state)();
+ },
+ componentDidUpdate: function(prevProps, prevState){
+ return spec.componentDidUpdate(this)(prevProps)(prevState.state)();
+ },
+ componentWillUnmount: function(){
+ return spec.componentWillUnmount(this)();
}
- result.getInitialState = function() {
- return {
- state: ss.getInitialState(this)()
- };
- };
- return React.createClass(result);
-};
+ };
-exports.handle = function(f) {
- return function(e) {
- return f(e)();
- };
+ return React.createClass(result);
+}
+exports.createClass = createClass;
+
+function handle(f) {
+ return function(e){
+ return f(e)();
+ };
};
+exports.handle = handle;
-function createElement(value) {
- return function(props) {
+function createElement(class_) {
+ return function(props){
return function(children){
- return React.createElement.apply(React, [value, props].concat(children));
+ return React.createElement.apply(React, [class_, props].concat(children));
};
};
-};
+}
exports.createElement = createElement;
exports.createElementTagName = createElement;
-function createElementDynamic(value) {
+function createElementDynamic(class_) {
return function(props) {
return function(children){
- return React.createElement(value, props, children);
+ return React.createElement(class_, props, children);
};
};
};
exports.createElementDynamic = createElementDynamic;
exports.createElementTagNameDynamic = createElementDynamic;
-exports.createFactory = function(clazz) {
- return React.createFactory(clazz);
-};
-
-exports.render = function(element) {
- return function(container) {
- return function() {
- return React.render(element, container);
- }
- };
-};
-
-exports.renderToString = React.renderToString;
+function createFactory(class_) {
+ return React.createFactory(class_);
+}
+exports.createFactory = createFactory;
diff --git a/src/React.purs b/src/React.purs
index 506706d..a5c63fb 100644
--- a/src/React.purs
+++ b/src/React.purs
@@ -2,6 +2,7 @@
module React
( ReactElement()
+ , ReactComponent()
, ReactThis()
, TagName()
@@ -51,29 +52,29 @@ module React
, handle
, createClass
+ , createClassStateless
, createElement
, createElementDynamic
, createElementTagName
, createElementTagNameDynamic
, createFactory
-
- , render
- , renderToString
) where
import Prelude (Unit(), ($), bind, pure, return, unit)
-import DOM (DOM())
-import DOM.Node.Types (Element())
-
import Control.Monad.Eff (Eff())
+import Unsafe.Coerce (unsafeCoerce)
+
-- | Name of a tag.
type TagName = String
-- | A virtual DOM node, or component.
foreign import data ReactElement :: *
+-- | A mounted react component
+foreign import data ReactComponent :: *
+
-- | A reference to a component, essentially React's `this`.
foreign import data ReactThis :: * -> * -> *
@@ -291,6 +292,10 @@ transformState ctx f = do
-- | Create a React class from a specification.
foreign import createClass :: forall props state eff. ReactSpec props state eff -> ReactClass props
+-- | Create a stateless React class.
+createClassStateless :: forall props. (props -> ReactElement) -> ReactClass props
+createClassStateless = unsafeCoerce
+
-- | Create an event handler.
foreign import handle :: forall eff ev props state result. (ev -> EventHandlerContext eff props state result) -> EventHandler ev
@@ -308,9 +313,3 @@ foreign import createElementTagNameDynamic :: forall props. TagName -> props ->
-- | Create a factory from a React class.
foreign import createFactory :: forall props. ReactClass props -> props -> ReactElement
-
--- | Render a React element in a document element.
-foreign import render :: forall eff. ReactElement -> Element -> Eff (dom :: DOM | eff) ReactElement
-
--- | Render a React element as a string.
-foreign import renderToString :: ReactElement -> String
diff --git a/src/React/DOM/Props.js b/src/React/DOM/Props.js
index f2a5eef..4edff94 100644
--- a/src/React/DOM/Props.js
+++ b/src/React/DOM/Props.js
@@ -3,43 +3,47 @@
// module React.DOM.Props
-exports.unsafeMkProps = function(key) {
- return function(value) {
- var result = {};
- result[key] = value;
- return result;
- };
-};
+var React = require('react');
-exports.unsafeUnfoldProps = function(key) {
- return function(value) {
- var result = {};
- var props = {};
- props[key] = result;
+function unsafeMkProps(key) {
+ return function(value){
+ var result = {};
+ result[key] = value;
+ return result;
+ };
+}
+exports.unsafeMkProps = unsafeMkProps;
- for (var subprop in value) {
- if (value.hasOwnProperty(subprop)) {
- result[subprop] = value[subprop];
- }
- }
+function unsafeUnfoldProps(key) {
+ return function(value){
+ var result = {};
+ var props = {};
+ props[key] = result;
- return props;
- };
-};
+ for (var subprop in value) {
+ if (value.hasOwnProperty(subprop)) {
+ result[subprop] = value[subprop];
+ }
+ }
+
+ return props;
+ };
+}
+exports.unsafeUnfoldProps = unsafeUnfoldProps;
function unsafeFromPropsArray(props) {
- var result = {};
+ var result = {};
- for (var i = 0, len = props.length; i < len; i++) {
- var prop = props[i];
+ for (var i = 0, len = props.length; i < len; i++) {
+ var prop = props[i];
- for (var key in prop) {
- if (prop.hasOwnProperty(key)) {
- result[key] = prop[key];
- }
- }
+ for (var key in prop) {
+ if (prop.hasOwnProperty(key)) {
+ result[key] = prop[key];
+ }
}
+ }
- return result;
+ return result;
};
exports.unsafeFromPropsArray = unsafeFromPropsArray;
diff --git a/test/Container.purs b/test/Container.purs
deleted file mode 100644
index 3fbfb3d..0000000
--- a/test/Container.purs
+++ /dev/null
@@ -1,20 +0,0 @@
-module Test.Container where
-
-import Prelude
-
-import React
-
-import qualified React.DOM as D
-import qualified React.DOM.Props as P
-
-container :: forall props. ReactClass props
-container = createClass $ 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.js b/test/Main.js
deleted file mode 100644
index d78c8de..0000000
--- a/test/Main.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/* global exports */
-"use strict";
-
-// module Test.Main
-
-exports.interval = function(ms) {
- return function(action) {
- return function() {
- return setInterval(action, ms);
- }
- }
-};
diff --git a/test/Main.purs b/test/Main.purs
deleted file mode 100644
index 32c266e..0000000
--- a/test/Main.purs
+++ /dev/null
@@ -1,79 +0,0 @@
-module Test.Main where
-
-import Prelude
-
-import Control.Monad.Eff
-import Control.Monad.Eff.Console
-
-import Data.Maybe.Unsafe (fromJust)
-import Data.Nullable (toMaybe)
-
-import DOM (DOM())
-import DOM.HTML (window)
-import DOM.HTML.Document (body)
-import DOM.HTML.Types (htmlElementToElement)
-import DOM.HTML.Window (document)
-
-import DOM.Node.Types (Element())
-
-import React
-
-import qualified React.DOM as D
-import qualified React.DOM.Props as P
-
-import Test.Container (container)
-
-foreign import interval :: forall eff a.
- Int ->
- Eff eff a ->
- Eff eff Unit
-
-hello :: forall props. ReactClass { name :: String | props }
-hello = createClass $ spec unit \ctx -> do
- props <- getProps ctx
- return $ D.h1 [ P.className "Hello"
- , P.style { background: "lightgray" }
- ]
- [ D.text "Hello, "
- , D.text props.name
- ]
-
-counter :: forall props. ReactClass props
-counter = createClass counterSpec
- where
- counterSpec = (spec 0 render)
- { componentDidMount = \ctx ->
- interval 1000 $ do
- val <- readState ctx
- print val
- }
-
- render ctx = do
- val <- readState ctx
- return $ D.button [ P.className "Counter"
- , P.onClick \_ -> do
- val <- readState ctx
- writeState ctx (val + 1)
- ]
- [ D.text (show val)
- , D.text " Click me to increment!"
- ]
-
-main :: forall eff. Eff (dom :: DOM | eff) Unit
-main = void (body' >>= render ui)
- where
- ui :: ReactElement
- ui = D.div' [ createFactory hello { name: "World" }
- , createFactory counter unit
- , createElement container unit
- [ D.p [] [ D.text "This is line one" ]
- , D.p [] [ D.text "This is line two" ]
- ]
- ]
-
- body' :: Eff (dom :: DOM | eff) Element
- body' = do
- win <- window
- doc <- document win
- elm <- fromJust <$> toMaybe <$> body doc
- return $ htmlElementToElement elm