aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoris2023-02-18 14:30:45 +0100
committerJoris2023-02-19 13:25:29 +0100
commite1aaa513a444a32c56a9591dd92beb24e66bcf42 (patch)
tree227fd22cfe5be446955a0c5cb6109b6107632090
parentcda836c875043572eb752a4f68368e7e1c6672f6 (diff)
downloadrx-e1aaa513a444a32c56a9591dd92beb24e66bcf42.tar.gz
rx-e1aaa513a444a32c56a9591dd92beb24e66bcf42.tar.bz2
rx-e1aaa513a444a32c56a9591dd92beb24e66bcf42.zip
Integrate update function with Var
But still don’t expose `Var`, so that it would be still passed as a Rx.
-rw-r--r--.gitignore1
-rw-r--r--README.md11
-rw-r--r--src/example.ts56
-rw-r--r--src/rx.ts14
4 files changed, 41 insertions, 41 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..89f9ac0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+out/
diff --git a/README.md b/README.md
index f878b62..d2ab8a7 100644
--- a/README.md
+++ b/README.md
@@ -45,10 +45,10 @@ Counter with `-` and `+` buttons:
import { h, withVar, mount } from 'rx'
mount(
- withVar(0, (value, update) => [
+ withVar(0, value => [
value,
- h('button', { onclick: () => update(n => n - 1) }, '-'),
- h('button', { onclick: () => update(n => n + 1) }, '+')]))
+ h('button', { onclick: () => value.update(n => n - 1) }, '-'),
+ h('button', { onclick: () => value.update(n => n + 1) }, '+')]))
```
### Subscriptions
@@ -59,8 +59,8 @@ Chronometer updating every second:
import { h, withVar, mount } from 'rx'
mount(
- withVar(0, (value, update) => {
- const interval = window.setInterval(() => update(n => n + 1), 1000)
+ withVar(0, value => {
+ const interval = window.setInterval(() => value.update(n => n + 1), 1000)
return h('div',
{ onunmount: () => clearInterval(interval) },
value
@@ -82,4 +82,3 @@ argument.
## Inspiration
- https://github.com/OlivierBlanvillain/monadic-html
-- https://www.solidjs.com
diff --git a/src/example.ts b/src/example.ts
index 360bf8b..1362fbd 100644
--- a/src/example.ts
+++ b/src/example.ts
@@ -1,11 +1,11 @@
import { h, withVar, mount, RxAble } from 'rx'
const imbricatedMaps =
- withVar(1, (counter, updateCounter) => [
+ withVar(1, counter => [
counterComponent({
value: counter,
- onSub: () => updateCounter(n => n - 1),
- onAdd: () => updateCounter(n => n + 1)
+ onSub: () => counter.update(n => n - 1),
+ onAdd: () => counter.update(n => n + 1)
}),
counter.map(c1 => {
console.log('c1')
@@ -20,11 +20,11 @@ const imbricatedMaps =
])
const flatMap =
- withVar(1, (counter, updateCounter) => [
+ withVar(1, counter => [
counterComponent({
value: counter,
- onSub: () => updateCounter(n => n - 1),
- onAdd: () => updateCounter(n => n + 1)
+ onSub: () => counter.update(n => n - 1),
+ onAdd: () => counter.update(n => n + 1)
}),
counter.flatMap(c1 => {
console.log('c1')
@@ -36,21 +36,21 @@ const flatMap =
])
const checkbox =
- withVar(false, (checked, update) => [
+ withVar(false, checked => [
checkboxComponent({
label: 'Checkbox',
isChecked: checked,
- onCheck: (isChecked: boolean) => update(_ => isChecked),
+ onCheck: (isChecked: boolean) => checked.update(_ => isChecked),
}),
checked.map(isChecked => isChecked ? 'C’est coché!' : 'Ça n’est pas coché')
])
const rxChildren =
- withVar(3, (count, update) => [
+ withVar(3, count => [
h('input', {
type: 'number',
value: count,
- onchange: (event: Event) => update(_ => parseInt((event.target as HTMLInputElement).value))
+ onchange: (event: Event) => count.update(_ => parseInt((event.target as HTMLInputElement).value))
}),
h('div', 'FOO'),
count.map(n => Array(n).fill(null).map((_, i) => h('div', `A ${i}!`))),
@@ -60,33 +60,33 @@ const rxChildren =
])
const nodesCancel =
- withVar(false, (checked, update) => [
+ withVar(false, checked => [
checkboxComponent({
label: 'Checkbox',
isChecked: checked,
- onCheck: (isChecked: boolean) => update(_ => isChecked),
+ onCheck: (isChecked: boolean) => checked.update(_ => isChecked),
}),
checked.map(isChecked => isChecked ? rxChildren : undefined)
])
const counters =
- withVar<Array<number>>([], (counters, update) => {
+ withVar<Array<number>>([], counters => {
return [
counterComponent({
value: counters.map(cs => cs.length),
- onSub: () => update(cs => cs.slice(0, -1)),
- onAdd: () => update(cs => cs.concat(0))
+ onSub: () => counters.update(cs => cs.slice(0, -1)),
+ onAdd: () => counters.update(cs => cs.concat(0))
}),
h('hr'),
h('div', { style: 'margin-top: 1rem' }, counters.map(cs =>
cs.map((c, i) =>
counterComponent({
value: c,
- onSub: () => update(cs => {
+ onSub: () => counters.update(cs => {
cs[i] = c - 1
return cs
}),
- onAdd: () => update(cs => {
+ onAdd: () => counters.update(cs => {
cs[i] = c + 1
return cs
})
@@ -97,25 +97,25 @@ const counters =
})
const rows =
- withVar(1, (count, updateCount) => [
+ withVar(1, count => [
h('input', {
type: 'number',
value: count,
- onchange: (event: Event) => updateCount(_ => parseInt((event.target as HTMLInputElement).value))
+ onchange: (event: Event) => count.update(_ => parseInt((event.target as HTMLInputElement).value))
}),
count.map(n => Array(n).fill(null).map((_, i) => h('div', i)))
])
const chrono =
- withVar(false, (isChecked, updateCheck) => [
+ withVar(false, isChecked => [
checkboxComponent({
label: 'Show counter',
isChecked,
- onCheck: b => updateCheck(_ => b)
+ onCheck: b => isChecked.update(_ => b)
}),
- isChecked.map(b => b && withVar(0, (elapsed, updateElapsed) => {
+ isChecked.map(b => b && withVar(0, elapsed => {
const interval = window.setInterval(
- () => updateElapsed(n => n + 1),
+ () => elapsed.update(n => n + 1),
1000
)
return h(
@@ -127,8 +127,8 @@ const chrono =
])
const doubleMapChild =
- withVar(true, (isEven, updateIsEven) =>
- withVar('', (search, updateSearch) => {
+ withVar(true, isEven =>
+ withVar('', search => {
const books = [...Array(50).keys()]
const filteredBooks = isEven.flatMap(f => search.map(s =>
@@ -140,11 +140,11 @@ const doubleMapChild =
checkboxComponent({
label: 'Even?',
isChecked: isEven,
- onCheck: checked => updateIsEven(_ => checked)
+ onCheck: checked => isEven.update(_ => checked)
}),
h(
'input',
- { oninput: (event: Event) => updateSearch(_ => (event.target as HTMLInputElement).value)
+ { oninput: (event: Event) => search.update(_ => (event.target as HTMLInputElement).value)
, style: 'margin-left: 1rem'
}
),
@@ -163,7 +163,7 @@ const doubleMapChild =
const view = h('main',
h('h1', 'Rx'),
- doubleMapChild
+ chrono
)
mount(view)
diff --git a/src/rx.ts b/src/rx.ts
index 3f3b8d9..5028ec1 100644
--- a/src/rx.ts
+++ b/src/rx.ts
@@ -1,5 +1,3 @@
-// [1.1.0] 2023-02-13
-
// Html
export type Html
@@ -24,7 +22,7 @@ interface Tag {
interface WithVar<A> {
type: 'WithVar'
init: A
- getChildren: (v: Var<A>, update: (f: (value: A) => A) => void) => Html
+ getChildren: (v: Var<A>) => Html
}
interface Attributes {
@@ -90,7 +88,7 @@ export function h(
}
}
-export function withVar<A>(init: A, getChildren: (v: Var<A>, update: (f: (value: A) => A) => void) => Html): WithVar<A> {
+export function withVar<A>(init: A, getChildren: (v: Var<A>) => Html): WithVar<A> {
return {
type: 'WithVar',
init,
@@ -115,11 +113,13 @@ export class Rx<A> {
class Var<A> extends Rx<A> {
readonly type: 'Var'
readonly id: string
+ readonly update: (f: (value: A) => A) => void
- constructor(id: string) {
+ constructor(id: string, update: (v: Var<A>) => ((f: ((value: A) => A)) => void)) {
super()
this.id = id
this.type = 'Var'
+ this.update = update(this)
}
}
@@ -172,7 +172,7 @@ class State {
}
register<A>(initValue: A) {
- const v = new Var(this.varCounter.toString())
+ const v = new Var(this.varCounter.toString(), v => (f => this.update(v, f)))
this.varCounter += BigInt(1)
this.state[v.id] = {
value: initValue,
@@ -325,7 +325,7 @@ function appendChild(state: State, element: Element, child: Html, lastAdded?: No
} else if (isWithVar(child)) {
const { init, getChildren } = child
const v = state.register(init)
- const children = getChildren(v, f => state.update(v, f))
+ const children = getChildren(v)
const appendRes = appendChild(state, element, children)
return {
cancel: () => {