Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
651 changes: 391 additions & 260 deletions MODULE.md

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"purescript-free": "~0.3.0",
"purescript-lens": "~0.6.0",
"purescript-options": "~0.0.1",
"purescript-monoid": "~0.2.0"
"purescript-monoid": "~0.2.0",
"purescript-monad-eff": "~0.1.0"
}
}
21 changes: 0 additions & 21 deletions examples/Todomvc/Todomvc/Main.purs

This file was deleted.

3 changes: 2 additions & 1 deletion examples/Todomvc/bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"purescript-argonaut": "~0.4.0",
"purescript-either": "~0.1.4",
"purescript-maybe": "~0.2.1",
"purescript-arrays": "~0.3.2"
"purescript-arrays": "~0.3.2",
"purescript-monad-eff": "~0.1.0"
}
}
2 changes: 1 addition & 1 deletion examples/Todomvc/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var Main = require('./Todomvc/Main.purs');
var Main = require('./src/Main.purs');

var _cssBase = require('todomvc-common/base.css');

Expand Down
3 changes: 1 addition & 2 deletions examples/Todomvc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
"name": "todomvc",
"version": "0.0.0",
"scripts": {
"build": "NODE_PATH=\"output\" ./node_modules/.bin/webpack",
"run": "NODE_PATH=\"output\" ./node_modules/.bin/webpack && NODE_PATH=\"output\" ./node_modules/.bin/webpack-dev-server"
"run": "NODE_PATH=\"output\" ./node_modules/.bin/webpack && NODE_PATH=\"output\" ./node_modules/.bin/webpack-dev-server --progress --colors"
},
"license": "MIT",
"private": true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
module Todomvc.Footer
( FooterProps()
, FooterState()
, spec
, footer
) where
Expand All @@ -24,22 +23,17 @@ import Todomvc.Types

type FooterProps = { remainingCount :: Number
, todosCount :: Number
, onClearCompleted :: TodomvcComponentEff
, onClearCompleted :: TodomvcComponent
}

type FooterState = Unit

props :: Props FooterProps
props = Props { remainingCount: 0
, todosCount: 0
, onClearCompleted: pure $ pure unit
, onClearCompleted: pure unit
}

state :: State FooterState
state = State unit

render :: RenderFn FooterProps FooterState
render ref (Props props) (State state) =
render :: PureRenderFn FooterProps
render (Props props) =
Dom.footer (Attr.id := "footer") mempty
.> [ Dom.span (Attr.id := "todo-count") mempty
.> [ Dom.strong (Attr.style := {paddingRight: "5px"}) mempty
Expand All @@ -66,9 +60,9 @@ render ref (Props props) (State state) =
where
onClearCompleted (Evt.SyntheticMouseEvent e) = props.onClearCompleted

spec :: forall eff. Specification eff FooterProps FooterState
spec = R.spec props state render #
spec :: Specification _ FooterProps _
spec = R.pureSpec props render #
R.setDisplayName .~ "Footer"

footer :: React (Class FooterProps FooterState)
footer :: React (Class FooterProps _)
footer = createClass spec
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Todomvc.Header
, header
) where

import Control.Monad.Eff.Unsafe (unsafeInterleaveEff)
import Control.Monad.Eff.Class (liftEff)

import Data.Monoid (mempty)
import Data.Options ((:=))
Expand All @@ -25,12 +25,12 @@ import qualified React.Spec as R
import Todomvc.Todo (Todo())
import Todomvc.Types

type HeaderProps = { onSubmit :: String -> TodomvcComponentEff }
type HeaderProps = { onSubmit :: String -> TodomvcComponent }

type HeaderState = { title :: String }

props :: Props HeaderProps
props = Props { onSubmit: const $ pure $ pure unit }
props = Props { onSubmit: const $ pure unit }

state :: State HeaderState
state = State { title: "" }
Expand All @@ -49,14 +49,17 @@ render ref (Props props) (State state) =
]
where
onChange (Evt.SyntheticInputEvent e) =
pure $ setStateAsync ref $ State { title: eventTargetValue e.target }
setStateAsync ref $ State { title: eventTargetValue e.target }

onSubmit evt@(Evt.SyntheticInputEvent e) = do
liftEff $ effApplyFn0 e.preventDefault evt
props.onSubmit state.title
setStateAsync ref $ State { title: "" }
return unit

onSubmit (Evt.SyntheticInputEvent e) = do
e.preventDefault
unsafeInterleaveEff $ props.onSubmit state.title

spec :: forall eff. Specification eff HeaderProps HeaderState
spec = R.spec props state render #
spec = R.impureSpec props state render #
R.setDisplayName .~ "Header"

header :: React (Class HeaderProps HeaderState)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
module Todomvc.Info
( InfoProps()
, InfoState()
, spec
, info
) where
Expand All @@ -22,16 +21,11 @@ import Todomvc.Types

type InfoProps = Unit

type InfoState = Unit

props :: Props InfoProps
props = Props unit

state :: State InfoState
state = State unit

render :: RenderFn InfoProps InfoState
render ref (Props props) (State state) =
render :: PureRenderFn InfoProps
render _ =
Dom.footer (Attr.id := "info") mempty
.> [ Dom.p'
.> Dom.textnode "Double-click to edit a todo"
Expand Down Expand Up @@ -64,9 +58,9 @@ render ref (Props props) (State state) =
style = { paddingLeft: "5px" }
style' = { paddingLeft: "5px", paddingRight: "5px" }

spec :: forall eff. Specification eff InfoProps InfoState
spec = R.spec props state render #
spec :: Specification _ InfoProps _
spec = R.pureSpec props render #
R.setDisplayName .~ "Info"

info :: React (Class InfoProps InfoState)
info :: React (Class InfoProps _)
info = createClass spec
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
module Todomvc.List
( ListProps()
, ListState()
, spec
, list
) where
Expand All @@ -23,22 +22,17 @@ import Todomvc.Todo
import Todomvc.Types

type ListProps = { todos :: [Todo]
, onCompleted :: Todo -> TodomvcComponentEff
, onRemoved :: Todo -> TodomvcComponentEff
, onCompleted :: Todo -> TodomvcComponent
, onRemoved :: Todo -> TodomvcComponent
}

type ListState = Unit

props :: Props ListProps
props = Props { todos: []
, onCompleted: const $ pure $ pure unit
, onRemoved: const $ pure $ pure unit
, onCompleted: const $ pure unit
, onRemoved: const $ pure unit
}

state :: State ListState
state = State unit

renderTodo ref props todo@(Todo a) =
renderTodo props todo@(Todo a) =
Dom.li (Attr.className := if a.completed then "completed" else "") mempty
.> Dom.div (Attr.className := "view") mempty
.> [ Dom.input (Attr.className := "toggle" <>
Expand All @@ -56,19 +50,19 @@ renderTodo ref props todo@(Todo a) =
onChange todo (Evt.SyntheticInputEvent e) = props.onCompleted todo
onRemove todo (Evt.SyntheticMouseEvent e) = props.onRemoved todo

render :: RenderFn ListProps ListState
render ref (Props props) (State state) =
render :: PureRenderFn ListProps
render (Props props) =
Dom.section (Attr.id := "main") mempty
.> [ Dom.input (Attr.id := "toggle-all" <> Attr._type := "checkbox") mempty mempty
, Dom.label (Attr.htmlFor := "toggle-all") mempty
.> Dom.textnode "Mark all as completed"
, Dom.ul (Attr.id := "todo-list") mempty
.> renderTodo ref props <$> props.todos
.> renderTodo props <$> props.todos
]

spec :: forall eff. Specification eff ListProps ListState
spec = R.spec props state render #
spec :: Specification _ ListProps _
spec = R.pureSpec props render #
R.setDisplayName .~ "List"

list :: React (Class ListProps ListState)
list :: React (Class ListProps _)
list = createClass spec
33 changes: 33 additions & 0 deletions examples/Todomvc/src/Main.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module Todomvc.Main (main) where

import Data.Monoid (mempty)

import React.ComponentF
import React.ReactF
import React.ReactI
import React.Types

import qualified Todomvc.Header as Header
import qualified Todomvc.List as List
import qualified Todomvc.Footer as Footer
import qualified Todomvc.Info as Info
import qualified Todomvc.Todomvc as Todomvc

foreign import dom "var dom = document.body;" :: DOMElement

foreign import reactjs "var reactjs = require('react/addons');" :: ReactJsImport

program = do
headerClass <- Header.header
listClass <- List.list
footerClass <- Footer.footer
infoClass <- Info.info
todomvcClass <- Todomvc.todomvc { header: headerClass
, list: listClass
, footer: footerClass
, info: infoClass
}
todomvcEl <- createElementFromClass todomvcClass (Props unit) mempty mempty
renderAsync todomvcEl dom

main = run (ReactJsAddons reactjs) program
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
module Todomvc.Todomvc
( TodomvcSpecification()
, Classes(..)
, spec
, todomvc
) where

import Control.Monad.Eff (Eff())
import Control.Monad.Eff.Class (liftEff)

import Data.Array (filter, length)
import Data.Maybe (fromMaybe)
Expand Down Expand Up @@ -44,13 +45,14 @@ storageId = "reactjsf:todomvc:todos"

componentDidMount :: forall eff. TodomvcComponentDidMount eff
componentDidMount ref = do
maybeTodos <- LocalStorage.get storageId
maybeTodos <- liftEff $ LocalStorage.get storageId
let todos = fromMaybe [] maybeTodos
return $ setStateAsync ref (State { todos: todos })
setStateAsync ref (State { todos: todos })

update :: Reference TodomvcProps TodomvcState -> [Todo] -> TodomvcComponent
update ref todos = do
LocalStorage.put storageId (todos :: [Todo])
return $ setStateAsync ref (State { todos: todos })
liftEff $ LocalStorage.put storageId todos
setStateAsync ref (State { todos: todos })

addTodo ref todos title =
update ref updated
Expand All @@ -70,12 +72,8 @@ clearCompletedTodos ref todos =
update ref updated
where updated = filter (\(Todo a) -> not a.completed) todos

render :: RenderFn TodomvcProps TodomvcState
render ref (Props props) (State state) = do
headerClass <- Header.header
listClass <- List.list
footerClass <- Footer.footer
infoClass <- Info.info
render :: Classes -> RenderFn TodomvcProps TodomvcState
render cls ref (Props props) (State state) = do

let remaining = filter (\(Todo a) -> not a.completed) state.todos
headerProps = Props { onSubmit: addTodo ref state.todos }
Expand All @@ -91,19 +89,26 @@ render ref (Props props) (State state) = do

html <- Dom.div'
.> [ Dom.section (Attr.id := "todoapp") mempty
.> [ createElementFromClass headerClass headerProps mempty mempty
, createElementFromClass listClass listProps mempty mempty
, createElementFromClass footerClass footerProps mempty mempty
.> [ createElementFromClass cls.header headerProps mempty mempty
, createElementFromClass cls.list listProps mempty mempty
, createElementFromClass cls.footer footerProps mempty mempty
]
, createElementFromClass infoClass infoProps mempty mempty
, createElementFromClass cls.info infoProps mempty mempty
]

return html

spec :: forall eff. TodomvcSpecification eff
spec = R.spec props state render #
R.setDisplayName .~ "Todomvc" #
R.setComponentDidMount .~ componentDidMount
type Classes
= { header :: Class Header.HeaderProps Header.HeaderState
, list :: Class List.ListProps (State Unit)
, footer :: Class Footer.FooterProps (State Unit)
, info :: Class Info.InfoProps (State Unit)
}

todomvc :: React (Class TodomvcProps TodomvcState)
todomvc = createClass spec
spec :: forall eff. Classes -> TodomvcSpecification eff
spec cls = R.impureSpec props state (render cls) #
R.setDisplayName .~ "Todomvc" #
R.setComponentDidMount .~ componentDidMount

todomvc :: Classes -> React (Class TodomvcProps TodomvcState)
todomvc cls = createClass $ spec cls
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@ module Todomvc.Types
( TodomvcProps()
, TodomvcState()
, TodomvcComponent()
, TodomvcComponentEff()
) where

import Control.Monad.Eff (Eff())

import Data.Options
import Data.Function

Expand All @@ -19,6 +16,4 @@ type TodomvcProps = Unit

type TodomvcState = { todos :: [Todo] }

type TodomvcComponent = Component TodomvcProps TodomvcState Unit

type TodomvcComponentEff = Eff (localStorage :: LocalStorageE) TodomvcComponent
type TodomvcComponent = Component (localStorage :: LocalStorageE) Unit
Loading