aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md16
-rw-r--r--public/index.html1
-rw-r--r--public/main.css41
-rw-r--r--src/example.ts95
4 files changed, 124 insertions, 29 deletions
diff --git a/README.md b/README.md
index 41303b0..2354819 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ Limitations:
```typescript
import { h, mount } from 'rx'
-mount(h('div', 'Hello World!'))
+mount(document.body, h('div', 'Hello World!'))
```
### Attributes
@@ -29,7 +29,7 @@ mount(h('div', 'Hello World!'))
```typescript
import { h, mount } from 'rx'
-mount(h('button',
+mount(document.body, h('button',
{ className: 'g-Button',
color: 'green',
onclick: () => console.log('Clicked!')
@@ -45,6 +45,7 @@ Counter with `-` and `+` buttons:
import { h, withState, mount } from 'rx'
mount(
+ document.body,
withState(0, value => [
value,
h('button', { onclick: () => value.update(n => n - 1) }, '-'),
@@ -59,10 +60,11 @@ Chronometer updating every second:
import { h, withState, mount } from 'rx'
mount(
+ document.body,
withState(0, value => {
const interval = window.setInterval(() => value.update(n => n + 1), 1000)
return h('div',
- { onunmount: () => clearInterval(interval) },
+ { onunmount: () => clearInterval(interval) },
value
)
}))
@@ -72,9 +74,15 @@ mount(
`onmount` is available as well. Those functions can take the `element` as an
argument.
+## Examples
+
+Run examples with:
+
+ nix develop --command bin/dev-server
+
## Ideas
-- API:
+- API:
- Rx debounce, filter,
- Routeur with sub-page support.
- Optimization: store intermediate rx instead of recomputing each time for multiple subscribers?
diff --git a/public/index.html b/public/index.html
index 2cb9f22..3775afa 100644
--- a/public/index.html
+++ b/public/index.html
@@ -2,5 +2,6 @@
<html lang="fr">
<meta charset="utf-8">
<title>Rx</title>
+<link rel="stylesheet" href="main.css">
<body></body>
<script src="example.js"></script>
diff --git a/public/main.css b/public/main.css
new file mode 100644
index 0000000..8a0da32
--- /dev/null
+++ b/public/main.css
@@ -0,0 +1,41 @@
+body {
+ margin: 0;
+ font-family: sans-serif;
+}
+
+header {
+ padding: 1rem;
+ background-color: #333;
+ color: white;
+}
+
+h1 {
+ margin: 0;
+}
+
+nav button {
+ margin-bottom: 0.5rem;
+ padding: 0.5rem;
+ width: 100%;
+ cursor: pointer;
+ border: none;
+ font-size: 1rem;
+}
+
+nav button.selected {
+ background-color: #833;
+ color: white;
+}
+
+main {
+ display: flex;
+}
+
+ul {
+ list-style-type: none;
+ padding: 0 1rem;
+}
+
+section {
+ margin: 1rem;
+}
diff --git a/src/example.ts b/src/example.ts
index 5a22419..9b19c28 100644
--- a/src/example.ts
+++ b/src/example.ts
@@ -1,7 +1,8 @@
-import { h, withState, mount, sequence2, RxAble } from 'rx'
+import { h, Html, RxAble } from 'rx'
+import * as rx from 'rx'
const imbricatedMaps =
- withState(1, counter => [
+ rx.withState(1, counter => [
counterComponent({
value: counter,
onSub: () => counter.update(n => n - 1),
@@ -20,7 +21,7 @@ const imbricatedMaps =
])
const flatMap =
- withState(1, counter => [
+ rx.withState(1, counter => [
counterComponent({
value: counter,
onSub: () => counter.update(n => n - 1),
@@ -36,17 +37,17 @@ const flatMap =
])
const checkbox =
- withState(false, checked => [
+ rx.withState(false, checked => [
checkboxComponent({
label: 'Checkbox',
isChecked: checked,
onCheck: (isChecked: boolean) => checked.update(_ => isChecked),
}),
- checked.map(isChecked => isChecked ? 'C’est coché!' : 'Ça n’est pas coché')
+ h('div', checked.map(isChecked => isChecked ? 'C’est coché!' : 'Ça n’est pas coché'))
])
const rxChildren =
- withState(3, count => [
+ rx.withState(3, count => [
h('input', {
type: 'number',
value: count,
@@ -60,7 +61,7 @@ const rxChildren =
])
const nodesCancel =
- withState(false, checked => [
+ rx.withState(false, checked => [
checkboxComponent({
label: 'Checkbox',
isChecked: checked,
@@ -70,7 +71,7 @@ const nodesCancel =
])
const counters =
- withState<Array<number>>([], counters => {
+ rx.withState<Array<number>>([], counters => {
return [
counterComponent({
value: counters.map(cs => cs.length),
@@ -97,7 +98,7 @@ const counters =
})
const rows =
- withState(1, count => [
+ rx.withState(1, count => [
h('input', {
type: 'number',
value: count,
@@ -107,13 +108,13 @@ const rows =
])
const chrono =
- withState(false, isChecked => [
+ rx.withState(false, isChecked => [
checkboxComponent({
label: 'Show counter',
isChecked,
onCheck: b => isChecked.update(_ => b)
}),
- isChecked.map(b => b && withState(0, elapsed => {
+ isChecked.map(b => b && rx.withState(0, elapsed => {
const interval = window.setInterval(
() => elapsed.update(n => n + 1),
1000
@@ -127,8 +128,8 @@ const chrono =
])
const doubleMapChild =
- withState(true, isEven =>
- withState('', search => {
+ rx.withState(true, isEven =>
+ rx.withState('', search => {
const books = [...Array(50).keys()]
const filteredBooks = isEven.flatMap(f => search.map(s =>
@@ -162,9 +163,9 @@ const doubleMapChild =
)
const seq =
- withState(0, a =>
- withState(0, b =>
- withState(0, c => [
+ rx.withState(0, a =>
+ rx.withState(0, b =>
+ rx.withState(0, c => [
counterComponent({
value: a,
onSub: () => a.update(n => n - 1),
@@ -180,13 +181,13 @@ const seq =
onSub: () => c.update(n => n - 1),
onAdd: () => c.update(n => n + 1)
}),
- sequence2([a, b, c]).map(xs => xs.reduce((a, b) => a + b, 0))
+ rx.sequence2([a, b, c]).map(xs => xs.reduce((a, b) => a + b, 0))
])
)
)
const indirectCheckbox =
- withState(false, checked => [
+ rx.withState(false, checked => [
checkboxComponent({
label: 'C1',
isChecked: checked,
@@ -199,13 +200,6 @@ const indirectCheckbox =
})
])
-const view = h('main',
- h('h1', 'Rx'),
- indirectCheckbox
-)
-
-mount(document.body, view)
-
// Checkbox
interface CheckboxParams {
@@ -242,3 +236,54 @@ function counterComponent({ value, onAdd, onSub}: CounterParams) {
]
)
}
+
+// View
+
+interface Item {
+ name: string
+ html: Html
+}
+
+const view = rx.withState<string>('imbricatedMaps', exVar => {
+ const menuItem = ({ name }: Item) =>
+ h('li',
+ h('button',
+ {
+ onclick: () => exVar.update(_ => name),
+ className: exVar.map(ex => ex == name && 'selected')
+ },
+ name
+ )
+ )
+
+ const items: Array<Item> = [
+ { name: 'imbricatedMaps', html: imbricatedMaps },
+ { name: 'flatMap', html: flatMap },
+ { name: 'checkbox', html: checkbox },
+ { name: 'rxChildren', html: rxChildren },
+ { name: 'nodesCancel', html: nodesCancel },
+ { name: 'counters', html: counters },
+ { name: 'rows', html: rows },
+ { name: 'chrono', html: chrono },
+ { name: 'doubleMapChild', html: doubleMapChild },
+ { name: 'seq', html: seq },
+ { name: 'indirectCheckbox', html: indirectCheckbox },
+ ]
+
+ return [
+ h('header', h('h1', 'Rx')),
+ h('main',
+ h('nav',
+ h('ul', items.map(menuItem))
+ ),
+ h('section',
+ exVar.map(ex => {
+ const item = items.find(item => item.name == ex)
+ return item && item.html
+ })
+ )
+ )
+ ]
+})
+
+rx.mount(document.body, view)