Skip to content

Commit 3345f8e

Browse files
author
Michael Trotter
committed
api experiment
1 parent f44fb99 commit 3345f8e

16 files changed

Lines changed: 411 additions & 4619 deletions

File tree

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"editor.formatOnSave": true
3+
}

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"dependencies": {
1515
"purescript-functions": "^4.0.0",
1616
"purescript-unsafe-coerce": "^4.0.0",
17-
"purescript-nullable": "^4.0.0",
17+
"purescript-nullable": "^4.1.0",
1818
"purescript-typelevel-prelude": "^3.0.0",
1919
"purescript-record": "^1.0.0",
2020
"purescript-effect": "^2.0.0",

codegen/index.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
const fs = require('fs');
2-
const { props, voids, types, reserved } = require('./consts');
1+
const fs = require("fs");
2+
const { props, voids, types, reserved } = require("./consts");
33
const genFile = "../src/React/Basic/DOM/Generated.purs";
44

55
const header = `-- | ----------------------------------------
@@ -15,14 +15,15 @@ import React.Basic.Events (EventHandler)
1515
1616
`;
1717

18-
const printRecord = (elProps) => elProps.length ? `
19-
( ${ elProps.map((p) =>
20-
`${p} :: ${types[p] || "String"}`).join("\n , ")
21-
}
22-
)` : "()"
18+
const printRecord = elProps =>
19+
elProps.length
20+
? `
21+
( ${elProps.map(p => `${p} :: ${types[p] || "String"}`).join("\n , ")}
22+
)`
23+
: "()";
2324

2425
const domTypes = props.elements.html
25-
.map((e) => {
26+
.map(e => {
2627
const noChildren = voids.includes(e);
2728
const symbol = reserved.includes(e) ? `${e}'` : e;
2829
return `
@@ -36,13 +37,17 @@ const domTypes = props.elements.html
3637
=> Record attrs
3738
-> JSX
3839
${symbol} = element (unsafeCreateDOMComponent "${e}")${
39-
noChildren ? "" : `
40+
noChildren
41+
? ""
42+
: `
4043
4144
${e}_ :: Array JSX -> JSX
4245
${e}_ children = ${symbol} { children }`
4346
}
4447
`;
45-
}).map((x) => x.replace(/^\n\ {4}/, "").replace(/\n\ {4}/g, "\n")).join("\n");
48+
})
49+
.map(x => x.replace(/^\n\ {4}/, "").replace(/\n\ {4}/g, "\n"))
50+
.join("\n");
4651

4752
console.log(`Writing "${genFile}" ...`);
4853
fs.writeFileSync(genFile, header + domTypes);
Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
module Container where
22

3-
import React.Basic as React
3+
import Prelude
4+
5+
import React.Basic (JSX, StatelessComponent, createComponent, makeStateless)
46
import React.Basic.DOM as R
57
import ToggleButton as ToggleButton
68

7-
component :: React.Component {}
8-
component = React.stateless { displayName: "Container", render }
9-
where
10-
render _ =
11-
R.div
12-
{ children:
13-
[ React.element ToggleButton.component { label: "A" }
14-
, React.element ToggleButton.component { label: "B" }
15-
]
16-
}
9+
render :: JSX
10+
render = {} # makeStateless component \_ ->
11+
R.div
12+
{ children:
13+
[ ToggleButton.render { label: "A" }
14+
, ToggleButton.render { label: "B" }
15+
]
16+
}
17+
18+
component :: StatelessComponent {}
19+
component = createComponent "Container"

examples/component/src/Main.purs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import Container as Container
66
import Data.Maybe (Maybe(..))
77
import Effect (Effect)
88
import Effect.Exception (throw)
9-
import React.Basic (element)
109
import React.Basic.DOM (render)
1110
import Web.DOM.NonElementParentNode (getElementById)
1211
import Web.HTML (window)
@@ -19,5 +18,5 @@ main = do
1918
case container of
2019
Nothing -> throw "Container element not found."
2120
Just c ->
22-
let app = element Container.component {}
21+
let app = Container.render
2322
in render app c

examples/component/src/ToggleButton.purs

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,41 @@ module ToggleButton where
22

33
import Prelude
44

5-
import React.Basic as React
5+
import React.Basic (JSX, Update, Component, StateUpdate(..), make, createComponent)
66
import React.Basic.DOM as R
77
import React.Basic.Events as Events
88

99
type Props =
1010
{ label :: String
1111
}
1212

13-
component :: React.Component Props
14-
component = React.component { displayName: "ToggleButton", initialState, receiveProps, render }
15-
where
16-
initialState =
17-
{ on: false
18-
}
19-
20-
receiveProps _ =
21-
pure unit
22-
23-
render { props, state, setState } =
24-
R.button
25-
{ onClick: Events.handler_ do
26-
setState \s -> s { on = not s.on }
27-
, children:
28-
[ R.text props.label
29-
, R.text if state.on
30-
then " On"
31-
else " Off"
32-
]
33-
}
13+
data Action
14+
= Toggle
15+
16+
type State =
17+
{ on :: Boolean
18+
}
19+
20+
initialState :: State
21+
initialState =
22+
{ on: false
23+
}
24+
25+
update :: Update Props State Action
26+
update self = case _ of
27+
Toggle -> Update self.state { on = not self.state.on }
28+
29+
render :: Props -> JSX
30+
render = make component initialState update \self ->
31+
R.button
32+
{ onClick: Events.handler_ do self.send Toggle
33+
, children:
34+
[ R.text self.props.label
35+
, R.text if self.state.on
36+
then " On"
37+
else " Off"
38+
]
39+
}
40+
41+
component :: Component Props State Action
42+
component = createComponent "ToggleButton"

examples/controlled-input/src/ControlledInput.purs

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,47 @@ module ControlledInput where
33
import Prelude
44

55
import Data.Maybe (Maybe(..), fromMaybe, maybe)
6+
import React.Basic (JSX, Update, Component, StateUpdate(..), make, createComponent)
67
import React.Basic as React
78
import React.Basic.DOM as R
89
import React.Basic.DOM.Events (preventDefault, targetValue, timeStamp)
910
import React.Basic.Events as Events
1011

11-
component :: React.Component {}
12-
component = React.component { displayName: "ControlledInput", initialState, receiveProps, render }
13-
where
14-
initialState =
15-
{ value: "hello world"
16-
, timeStamp: Nothing
17-
}
18-
19-
receiveProps _ =
20-
pure unit
21-
22-
render { state, setState } =
23-
React.fragment
24-
[ R.input
25-
{ onChange:
26-
Events.handler
27-
(preventDefault >>> Events.merge { targetValue, timeStamp })
28-
\{ timeStamp, targetValue } ->
29-
setState _ { value = fromMaybe "" targetValue
30-
, timeStamp = Just timeStamp
31-
}
32-
, value: state.value
33-
}
34-
, R.p_ [ R.text ("Current value = " <> show state.value) ]
35-
, R.p_ [ R.text ("Changed at = " <> maybe "never" show state.timeStamp) ]
36-
]
12+
type Props = {}
13+
14+
type State =
15+
{ value :: String
16+
, timestamp :: Maybe Number
17+
}
18+
19+
initialState :: State
20+
initialState =
21+
{ value: "hello world"
22+
, timestamp: Nothing
23+
}
24+
25+
data Action
26+
= ValueChanged String Number
27+
28+
update :: Update Props State Action
29+
update self = case _ of
30+
ValueChanged value timestamp ->
31+
Update self.state { value = value, timestamp = Just timestamp }
32+
33+
render :: Props -> JSX
34+
render = make component initialState update \{ props, state, send } ->
35+
React.fragment
36+
[ R.input
37+
{ onChange:
38+
Events.handler
39+
(preventDefault >>> Events.merge { targetValue, timeStamp })
40+
\{ timeStamp, targetValue } ->
41+
send $ ValueChanged (fromMaybe "" targetValue) timeStamp
42+
, value: state.value
43+
}
44+
, R.p_ [ R.text ("Current value = " <> show state.value) ]
45+
, R.p_ [ R.text ("Changed at = " <> maybe "never" show state.timestamp) ]
46+
]
47+
48+
component :: Component Props State Action
49+
component = createComponent "ControlledInput"

examples/controlled-input/src/Main.purs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import ControlledInput as ControlledInput
66
import Data.Maybe (Maybe(..))
77
import Effect (Effect)
88
import Effect.Exception (throw)
9-
import React.Basic (element)
109
import React.Basic.DOM (render)
1110
import Web.DOM.NonElementParentNode (getElementById)
1211
import Web.HTML (window)
@@ -19,5 +18,5 @@ main = do
1918
case container of
2019
Nothing -> throw "Container element not found."
2120
Just c ->
22-
let app = element ControlledInput.component {}
21+
let app = ControlledInput.render {}
2322
in render app c

examples/counter/src/Counter.purs

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,36 @@ module Counter where
22

33
import Prelude
44

5-
import React.Basic as React
5+
import React.Basic (JSX, Update, Component, StateUpdate(..), make, createComponent)
66
import React.Basic.DOM as R
77
import React.Basic.Events as Events
88

9-
-- The props for the component
109
type Props =
1110
{ label :: String
1211
}
1312

14-
-- Create a component by passing a record to the `react` function.
15-
-- The `render` function takes the props and current state, as well as a
16-
-- state update callback, and produces a document.
17-
component :: React.Component Props
18-
component = React.component { displayName: "Counter", initialState, receiveProps, render }
19-
where
20-
initialState =
21-
{ counter: 0
22-
}
23-
24-
receiveProps _ =
25-
pure unit
26-
27-
render { props, state, setState } =
28-
R.button
29-
{ onClick: Events.handler_ do
30-
setState \s -> s { counter = s.counter + 1 }
31-
, children: [ R.text (props.label <> ": " <> show state.counter) ]
32-
}
13+
data Action
14+
= Increment
15+
16+
type State =
17+
{ counter :: Int
18+
}
19+
20+
initialState :: State
21+
initialState =
22+
{ counter: 0
23+
}
24+
25+
update :: Update Props State Action
26+
update self = case _ of
27+
Increment -> Update self.state { counter = self.state.counter + 1 }
28+
29+
render :: Props -> JSX
30+
render = make component initialState update \self ->
31+
R.button
32+
{ onClick: Events.handler_ do self.send Increment
33+
, children: [ R.text (self.props.label <> ": " <> show self.state.counter) ]
34+
}
35+
36+
component :: Component Props State Action
37+
component = createComponent "Counter"

examples/counter/src/Main.purs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,22 @@ import Counter as Counter
66
import Data.Maybe (Maybe(..))
77
import Effect (Effect)
88
import Effect.Exception (throw)
9-
import React.Basic (element)
109
import React.Basic.DOM (render)
1110
import Web.DOM.NonElementParentNode (getElementById)
1211
import Web.HTML (window)
1312
import Web.HTML.HTMLDocument (toNonElementParentNode)
1413
import Web.HTML.Window (document)
1514

15+
-- dummy :: Component
16+
-- dummy = stateless { displayName: "dummy", render }
17+
-- where
18+
-- render _ =
19+
1620
main :: Effect Unit
1721
main = do
1822
container <- getElementById "container" =<< (map toNonElementParentNode $ document =<< window)
1923
case container of
2024
Nothing -> throw "Container element not found."
2125
Just c ->
22-
let app = element Counter.component { label: "Increment" }
26+
let app = Counter.render { label: "Increment" }
2327
in render app c

0 commit comments

Comments
 (0)