diff options
author | Joris | 2023-02-18 14:30:45 +0100 |
---|---|---|
committer | Joris | 2023-02-19 13:25:29 +0100 |
commit | e1aaa513a444a32c56a9591dd92beb24e66bcf42 (patch) | |
tree | 227fd22cfe5be446955a0c5cb6109b6107632090 | |
parent | cda836c875043572eb752a4f68368e7e1c6672f6 (diff) |
Integrate update function with Var
But still don’t expose `Var`, so that it would be still passed as a Rx.
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | README.md | 11 | ||||
-rw-r--r-- | src/example.ts | 56 | ||||
-rw-r--r-- | src/rx.ts | 14 |
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/ @@ -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) @@ -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: () => { |