From 9cac1c7bf46f0fee7392ec47ad445fe487bf6ef4 Mon Sep 17 00:00:00 2001
From: Joris
Date: Wed, 16 Apr 2025 09:20:45 +0200
Subject: Add interface to pick example to run
---
 README.md         | 16 +++++++---
 public/index.html |  1 +
 public/main.css   | 41 ++++++++++++++++++++++++
 src/example.ts    | 95 ++++++++++++++++++++++++++++++++++++++++---------------
 4 files changed, 124 insertions(+), 29 deletions(-)
 create mode 100644 public/main.css
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 @@
 
 
 
Rx
+
 
 
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>([], counters => {
+  rx.withState>([], 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('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-  = [
+    { 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)
-- 
cgit v1.2.3