diff options
| author | Joris | 2025-04-16 09:20:45 +0200 | 
|---|---|---|
| committer | Joris | 2025-04-16 09:20:45 +0200 | 
| commit | 9cac1c7bf46f0fee7392ec47ad445fe487bf6ef4 (patch) | |
| tree | 46d19a695634a464c54f5ea04ab2ba5b69ccc7d3 | |
| parent | 0561c607d8dbb4e927897066ceccd45269a45cbd (diff) | |
Add interface to pick example to run
| -rw-r--r-- | README.md | 16 | ||||
| -rw-r--r-- | public/index.html | 1 | ||||
| -rw-r--r-- | public/main.css | 41 | ||||
| -rw-r--r-- | src/example.ts | 95 | 
4 files changed, 124 insertions, 29 deletions
@@ -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)  | 
