@rhi-zone/rainbow-ui 0.2.0-alpha.3 → 0.2.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,34 +1,34 @@
1
- import { h as g } from "./html-C8SnQjvU.js";
2
- import { above as l, beside as p, bindAttr as f, bindCheckbox as x, bindClass as S, bindInput as w, bindSelect as W, bindShow as v, bindText as y, checkboxWidget as k, concat as C, dynamic as E, each as F, eachKeyed as A, focus as I, foldWidget as K, inputWidget as L, map as N, match as B, mount as D, narrow as J, numberInputWidget as T, on as V, register as j, selectWidget as q, show as z, stack as G, subscribe as H, subscribeNow as M, template as O, textareaWidget as P, watchAll as Q, withScope as R } from "./widget.js";
3
- import { createForm as X, createFormState as Y, isDirty as Z, isFormValid as _, shouldShowError as $ } from "./form-state.js";
1
+ import { h as l } from "./html-C8SnQjvU.js";
2
+ import { above as g, beside as p, bindAttr as f, bindCheckbox as x, bindClass as S, bindInput as w, bindSelect as W, bindShow as v, bindText as y, checkboxWidget as k, concat as C, dynamic as E, each as F, eachKeyed as A, focus as I, foldWidget as K, h as L, inputWidget as N, lift as B, map as D, match as J, mount as T, narrow as V, numberInputWidget as j, on as q, prop as z, register as G, selectWidget as H, show as M, slot as O, stack as P, subscribe as Q, subscribeNow as R, template as U, textareaWidget as X, watchAll as Y, withScope as Z } from "./widget.js";
3
+ import { createForm as $, createFormState as ee, isDirty as te, isFormValid as ne, shouldShowError as oe } from "./form-state.js";
4
4
  import { signal as a } from "@rhi-zone/rainbow";
5
- import { attrBoolean as te, attrJson as ne, attrNumber as ie, attrString as oe, attrsFrom as re, defineElement as se } from "./elements.js";
6
- function d(e, n, t, r, i) {
7
- const o = e(
5
+ import { attrBoolean as re, attrJson as se, attrNumber as ae, attrString as ce, attrsFrom as de, defineElement as be } from "./elements.js";
6
+ function d(e, n, t, r, o) {
7
+ const i = e(
8
8
  n,
9
9
  () => r(t.get()),
10
- i
10
+ o
11
11
  ), s = t.subscribe(() => {
12
12
  });
13
13
  return () => {
14
- s(), o();
14
+ s(), i();
15
15
  };
16
16
  }
17
17
  function b(e) {
18
18
  const n = a(e.get());
19
- function t(i) {
20
- const o = i;
21
- n.set(o.detail.bindings);
19
+ function t(o) {
20
+ const i = o;
21
+ n.set(i.detail.bindings);
22
22
  }
23
23
  return e.addEventListener("change", t), [n, () => e.removeEventListener("change", t)];
24
24
  }
25
25
  export {
26
- l as above,
27
- te as attrBoolean,
28
- ne as attrJson,
29
- ie as attrNumber,
30
- oe as attrString,
31
- re as attrsFrom,
26
+ g as above,
27
+ re as attrBoolean,
28
+ se as attrJson,
29
+ ae as attrNumber,
30
+ ce as attrString,
31
+ de as attrsFrom,
32
32
  p as beside,
33
33
  f as bindAttr,
34
34
  x as bindCheckbox,
@@ -40,34 +40,38 @@ export {
40
40
  b as bindingsStoreSignal,
41
41
  k as checkboxWidget,
42
42
  C as concat,
43
- X as createForm,
44
- Y as createFormState,
45
- se as defineElement,
43
+ $ as createForm,
44
+ ee as createFormState,
45
+ be as defineElement,
46
46
  E as dynamic,
47
47
  F as each,
48
48
  A as eachKeyed,
49
49
  I as focus,
50
50
  K as foldWidget,
51
- g as html,
52
- L as inputWidget,
53
- Z as isDirty,
54
- _ as isFormValid,
51
+ L as h,
52
+ l as html,
53
+ N as inputWidget,
54
+ te as isDirty,
55
+ ne as isFormValid,
55
56
  d as keybindsContext,
56
- N as map,
57
- B as match,
58
- D as mount,
59
- J as narrow,
60
- T as numberInputWidget,
61
- V as on,
62
- j as register,
63
- q as selectWidget,
64
- $ as shouldShowError,
65
- z as show,
66
- G as stack,
67
- H as subscribe,
68
- M as subscribeNow,
69
- O as template,
70
- P as textareaWidget,
71
- Q as watchAll,
72
- R as withScope
57
+ B as lift,
58
+ D as map,
59
+ J as match,
60
+ T as mount,
61
+ V as narrow,
62
+ j as numberInputWidget,
63
+ q as on,
64
+ z as prop,
65
+ G as register,
66
+ H as selectWidget,
67
+ oe as shouldShowError,
68
+ M as show,
69
+ O as slot,
70
+ P as stack,
71
+ Q as subscribe,
72
+ R as subscribeNow,
73
+ U as template,
74
+ X as textareaWidget,
75
+ Y as watchAll,
76
+ Z as withScope
73
77
  };
package/dist/widget.d.ts CHANGED
@@ -31,7 +31,7 @@
31
31
  * false and rebuild them when it becomes true again.
32
32
  */
33
33
  import { type Signal, type ReadonlySignal, type Lens, type Prism, type AsyncData } from "@rhi-zone/rainbow";
34
- import type { AnyEl, El, FlowContent, DivEl, InputEl, InputAttrs, TextareaEl, TextareaAttrs, SelectEl, SelectAttrs } from "./html.js";
34
+ import type { AnyEl, El, FlowContent, DivEl, InputEl, InputAttrs, TextareaEl, TextareaAttrs, SelectEl, SelectAttrs, GlobalAttrs } from "./html.js";
35
35
  /**
36
36
  * A widget is a pure function from a reactive signal to a typed DOM node.
37
37
  * Calling a widget subscribes it to the signal; the returned node is updated
@@ -91,6 +91,16 @@ export declare function mount<T, E extends AnyEl>(widget: Widget<T, E>, signal:
91
91
  * focus(opPicker, field('op'))
92
92
  */
93
93
  export declare function focus<A, B, E extends AnyEl>(w: Widget<B, E>, l: Lens<A, B>): Widget<A, E>;
94
+ /**
95
+ * Sugar for `focus(w, field(key))`. Zoom into a named property of the signal.
96
+ * The most common use of `focus` — use this instead when the lens is a simple
97
+ * field access.
98
+ *
99
+ * @example
100
+ * prop(each(rowWidget), 'items') // Widget<{ items: Row[] }>
101
+ * prop(nameWidget, 'name') // Widget<{ name: string }>
102
+ */
103
+ export declare function prop<T, K extends keyof T & string, E extends AnyEl>(w: Widget<T[K], E>, key: K): Widget<T, E>;
94
104
  /**
95
105
  * Zoom into a sum variant. The child widget renders when the prism matches;
96
106
  * renders an empty container when it doesn't. Container switches on match
@@ -199,14 +209,21 @@ export type RefsMap<R extends Record<string, keyof HTMLElementTagNameMap>> = {
199
209
  readonly [K in keyof R]: El<R[K] & string, HTMLElementTagNameMap[R[K]]>;
200
210
  };
201
211
  /**
202
- * Template combinator. Parses `innerHTML` once (at definition time), then for
203
- * each widget instantiation clones the template, queries out typed DOM refs via
204
- * `data-ref` attributes, and calls `bind` with the signal and those refs.
212
+ * **Performance escape hatch.** Prefer the reactive hyperscript factories
213
+ * (`h.div`, `h.span`, …) for normal widget authoring they are type-safe,
214
+ * compose naturally with slots and combinators, and avoid the `data-ref`
215
+ * indirection.
216
+ *
217
+ * Use `template` only when instantiation count is high and the clone-vs-create
218
+ * difference is measurable: it parses `innerHTML` once at definition time and
219
+ * calls `cloneNode(true)` on each instantiation, which is faster than N
220
+ * `createElement` calls for large identical subtrees (e.g. a `eachKeyed` row
221
+ * with many static nodes).
205
222
  *
206
223
  * Refs are queried as `tagName[data-ref="refName"]`, so `{ name: "span" }`
207
224
  * expects `<span data-ref="name">` in the template. Using `data-ref` rather
208
- * than `id` means the same template can be cloned many times (e.g. inside
209
- * `eachKeyed`) without duplicate-ID issues.
225
+ * than `id` means the same template can be cloned many times without
226
+ * duplicate-ID issues.
210
227
  *
211
228
  * `bind` is called inside the widget call context, so any `subscribe` calls
212
229
  * inside it are tracked and cleaned up by `mount` / parent combinators.
@@ -214,12 +231,11 @@ export type RefsMap<R extends Record<string, keyof HTMLElementTagNameMap>> = {
214
231
  * @throws if a declared ref is absent from the cloned template.
215
232
  *
216
233
  * @example
217
- * const cardWidget = template(
218
- * `<div class="card"><span data-ref="name"></span><b data-ref="score"></b></div>`,
219
- * { name: "span", score: "b" } as const,
234
+ * // High-volume row widget — justified use of template()
235
+ * const rowWidget = template(
236
+ * `<tr><td data-ref="name"></td><td data-ref="score"></td></tr>`,
237
+ * { name: "td", score: "td" } as const,
220
238
  * (s, { name, score }) => {
221
- * name.node.textContent = s.get().label
222
- * score.node.textContent = String(s.get().value)
223
239
  * subscribe(s, v => {
224
240
  * name.node.textContent = v.label
225
241
  * score.node.textContent = String(v.value)
@@ -441,4 +457,78 @@ export declare function selectWidget(options: {
441
457
  value: string;
442
458
  label: string;
443
459
  }[], attrs?: SelectAttrs): Widget<string, SelectEl>;
460
+ /**
461
+ * A reactive child: either a plain string or a widget that accepts the same
462
+ * signal type `T` and returns any element.
463
+ *
464
+ * `AnyEl` is intentionally excluded. Passing a pre-built element directly would
465
+ * require `cloneNode(true)` on each widget invocation, silently dropping event
466
+ * listeners. Use `lift(el)` to wrap a freshly-built element instead.
467
+ */
468
+ export type RChild<T> = string | Widget<T, AnyEl>;
469
+ /**
470
+ * Lift a static element into the widget context. Use this to pass a
471
+ * pre-built `AnyEl` as a child to an `h.*` reactive factory:
472
+ *
473
+ * h.div({}, lift(iconEl), reactiveChild)
474
+ *
475
+ * The element is inserted as-is — no cloning — so event listeners are
476
+ * preserved. Only use `lift` when the element is freshly built at widget
477
+ * call time (i.e. inside the widget function body). Do NOT lift a module-
478
+ * level static element — it can only have one parent at a time.
479
+ */
480
+ export declare function lift<T, E extends AnyEl>(el: E): Widget<T, E>;
481
+ /**
482
+ * Reactive hyperscript factories — the same element tags as `html.ts` but
483
+ * returning `Widget<T, El>` instead of `El`. Import as:
484
+ *
485
+ * import { h } from '@rhi-zone/rainbow-ui/widget'
486
+ *
487
+ * Widget children receive the same signal as their parent. String children
488
+ * create fresh text nodes. To pass a pre-built element, wrap it with `lift(el)`
489
+ * so it is inserted directly without cloning — preserving event listeners.
490
+ */
491
+ export declare const h: {
492
+ readonly div: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"div", HTMLDivElement>;
493
+ readonly section: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"section", HTMLElement>;
494
+ readonly article: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"article", HTMLElement>;
495
+ readonly header: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"header", HTMLElement>;
496
+ readonly footer: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"footer", HTMLElement>;
497
+ readonly main: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"main", HTMLElement>;
498
+ readonly nav: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"nav", HTMLElement>;
499
+ readonly h1: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"h1", HTMLHeadingElement>;
500
+ readonly h2: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"h2", HTMLHeadingElement>;
501
+ readonly h3: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"h3", HTMLHeadingElement>;
502
+ readonly h4: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"h4", HTMLHeadingElement>;
503
+ readonly h5: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"h5", HTMLHeadingElement>;
504
+ readonly h6: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"h6", HTMLHeadingElement>;
505
+ readonly p: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"p", HTMLParagraphElement>;
506
+ readonly span: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"span", HTMLSpanElement>;
507
+ readonly a: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"a", HTMLAnchorElement>;
508
+ readonly em: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"em", HTMLElement>;
509
+ readonly strong: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"strong", HTMLElement>;
510
+ readonly code: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"code", HTMLElement>;
511
+ readonly pre: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"pre", HTMLPreElement>;
512
+ readonly ul: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"ul", HTMLUListElement>;
513
+ readonly ol: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"ol", HTMLOListElement>;
514
+ readonly li: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"li", HTMLLIElement>;
515
+ readonly button: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"button", HTMLButtonElement>;
516
+ readonly label: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"label", HTMLLabelElement>;
517
+ readonly form: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"form", HTMLFormElement>;
518
+ readonly fieldset: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"fieldset", HTMLFieldSetElement>;
519
+ };
520
+ /** A widget that takes no meaningful signal and renders flow content. */
521
+ export type Slot = Widget<void, FlowContent>;
522
+ /** A widget that takes a typed signal `T` and renders flow content. */
523
+ export type ScopedSlot<T> = Widget<T, FlowContent>;
524
+ /**
525
+ * Mount a slot widget by replacing a placeholder element.
526
+ * If no slot is provided, removes the placeholder.
527
+ * The slot signal defaults to `s` (cast) if `slotSignal` is omitted.
528
+ *
529
+ * @example
530
+ * slot(placeholder, s, v => v.actionsSlot) // slot signal = s
531
+ * slot(placeholder, s, v => v.rowSlot, s.focus(rowLens)) // slot signal = focused
532
+ */
533
+ export declare function slot<Props, T>(placeholder: HTMLElement, s: Signal<Props>, extract: (props: Props) => Widget<T, FlowContent> | undefined, slotSignal?: Signal<T>): void;
444
534
  export {};
package/dist/widget.js CHANGED
@@ -1,144 +1,147 @@
1
- import { index as C, stateful as S, lens as L, tagged as W, signal as B } from "@rhi-zone/rainbow";
2
- import { i as N, s as $, o as F, t as I } from "./html-C8SnQjvU.js";
1
+ import { index as E, stateful as L, field as W, lens as B, tagged as $, signal as j } from "@rhi-zone/rainbow";
2
+ import { i as _, s as F, o as I, t as O } from "./html-C8SnQjvU.js";
3
3
  let k = null;
4
- function i(e) {
4
+ function l(e) {
5
5
  k == null || k.push(e);
6
6
  }
7
- function h(e) {
8
- const n = k, o = [];
7
+ function m(e) {
8
+ const t = k, o = [];
9
9
  k = o;
10
- const t = e();
11
- return k = n, [t, () => {
10
+ const n = e();
11
+ return k = t, [n, () => {
12
12
  for (const c of o) c();
13
13
  }];
14
14
  }
15
- function M(e) {
16
- return h(e);
15
+ function V(e) {
16
+ return m(e);
17
17
  }
18
- function v(e, n) {
19
- i(e.subscribe(n));
18
+ function w(e, t) {
19
+ l(e.subscribe(t));
20
20
  }
21
- function O(e) {
22
- i(e);
21
+ function H(e) {
22
+ l(e);
23
23
  }
24
- function T(e, n, o) {
25
- const [t, c] = h(() => e(n));
26
- return o.appendChild(t.node), () => {
27
- t.node.remove(), c();
24
+ function R(e, t, o) {
25
+ const [n, c] = m(() => e(t));
26
+ return o.appendChild(n.node), () => {
27
+ n.node.remove(), c();
28
28
  };
29
29
  }
30
- function V(e, n) {
31
- return (o) => e(o.focus(n));
30
+ function P(e, t) {
31
+ return (o) => e(o.focus(t));
32
+ }
33
+ function U(e, t) {
34
+ return P(e, W(t));
32
35
  }
33
- function H(e, n) {
36
+ function z(e, t) {
34
37
  return (o) => {
35
- const t = document.createElement("div");
36
- t.dataset.narrow = "";
38
+ const n = document.createElement("div");
39
+ n.dataset.narrow = "";
37
40
  let c = null, r = null;
38
41
  const u = o, d = () => {
39
- r = u.narrow(n);
40
- const [a, l] = h(() => e(r));
41
- c = l, t.appendChild(a.node);
42
+ r = u.narrow(t);
43
+ const [a, f] = m(() => e(r));
44
+ c = f, n.appendChild(a.node);
42
45
  };
43
- return v(o, (a) => {
44
- const l = n.view(a);
45
- l !== void 0 && c === null ? d() : l === void 0 && c !== null && (c(), c = null, r = null, t.replaceChildren());
46
- }), n.view(o.get()) !== void 0 && d(), i(() => c == null ? void 0 : c()), { _tag: "div", node: t };
46
+ return w(o, (a) => {
47
+ const f = t.view(a);
48
+ f !== void 0 && c === null ? d() : f === void 0 && c !== null && (c(), c = null, r = null, n.replaceChildren());
49
+ }), t.view(o.get()) !== void 0 && d(), l(() => c == null ? void 0 : c()), { _tag: "div", node: n };
47
50
  };
48
51
  }
49
- function R(e) {
50
- return (n) => {
51
- const o = n, t = document.createElement("div");
52
- t.dataset.each = "";
52
+ function D(e) {
53
+ return (t) => {
54
+ const o = t, n = document.createElement("div");
55
+ n.dataset.each = "";
53
56
  let c = [];
54
57
  const r = (d) => {
55
58
  for (const s of c) s();
56
- c = [], t.replaceChildren();
59
+ c = [], n.replaceChildren();
57
60
  for (let s = 0; s < d.length; s++) {
58
- const a = s, l = L(
59
- (f) => f[a],
60
- (f, p) => {
61
- const b = [...p];
62
- return b[a] = f, b;
61
+ const a = s, f = B(
62
+ (p) => p[a],
63
+ (p, h) => {
64
+ const g = [...h];
65
+ return g[a] = p, g;
63
66
  }
64
- ), g = o.focus(l), [m, w] = h(() => e(g));
65
- c.push(w), t.appendChild(m.node);
67
+ ), b = o.focus(f), [v, C] = m(() => e(b));
68
+ c.push(C), n.appendChild(v.node);
66
69
  }
67
70
  };
68
- r(n.get());
69
- const u = n.map((d) => d.length);
70
- return v(u, () => r(n.get())), i(() => {
71
+ r(t.get());
72
+ const u = t.map((d) => d.length);
73
+ return w(u, () => r(t.get())), l(() => {
71
74
  for (const d of c) d();
72
- }), { _tag: "div", node: t };
75
+ }), { _tag: "div", node: n };
73
76
  };
74
77
  }
75
- function U(e, n) {
78
+ function G(e, t) {
76
79
  return (o) => {
77
- const t = o, c = document.createElement("div");
80
+ const n = o, c = document.createElement("div");
78
81
  c.dataset.beside = "";
79
- const r = t.focus(C(0)), u = t.focus(C(1)), [d, s] = h(() => e(r)), [a, l] = h(() => n(u));
80
- return c.appendChild(d.node), c.appendChild(a.node), i(s), i(l), { _tag: "div", node: c };
82
+ const r = n.focus(E(0)), u = n.focus(E(1)), [d, s] = m(() => e(r)), [a, f] = m(() => t(u));
83
+ return c.appendChild(d.node), c.appendChild(a.node), l(s), l(f), { _tag: "div", node: c };
81
84
  };
82
85
  }
83
- function z(e, n) {
86
+ function J(e, t) {
84
87
  return (o) => {
85
- const t = o, c = document.createElement("div");
88
+ const n = o, c = document.createElement("div");
86
89
  c.dataset.above = "";
87
- const r = t.focus(C(0)), u = t.focus(C(1)), [d, s] = h(() => e(r)), [a, l] = h(() => n(u));
88
- return c.appendChild(d.node), c.appendChild(a.node), i(s), i(l), { _tag: "div", node: c };
90
+ const r = n.focus(E(0)), u = n.focus(E(1)), [d, s] = m(() => e(r)), [a, f] = m(() => t(u));
91
+ return c.appendChild(d.node), c.appendChild(a.node), l(s), l(f), { _tag: "div", node: c };
89
92
  };
90
93
  }
91
- function D(e, n) {
94
+ function Q(e, t) {
92
95
  return (o) => {
93
- const t = S(e, o);
94
- return n(t);
96
+ const n = L(e, o);
97
+ return t(n);
95
98
  };
96
99
  }
97
- function G(e, n) {
100
+ function X(e, t) {
98
101
  return (o) => {
99
- const t = o.narrow(n);
100
- return e(t);
102
+ const n = o.narrow(t);
103
+ return e(n);
101
104
  };
102
105
  }
103
- function J(e, n) {
106
+ function Y(e, t) {
104
107
  return (o) => {
105
- const t = document.createElement("div");
106
- t.dataset.show = "";
107
- const [c, r] = h(() => e(o));
108
- t.appendChild(c.node), i(r);
108
+ const n = document.createElement("div");
109
+ n.dataset.show = "";
110
+ const [c, r] = m(() => e(o));
111
+ n.appendChild(c.node), l(r);
109
112
  const u = (d) => {
110
- t.style.display = n(d) ? "" : "none";
113
+ n.style.display = t(d) ? "" : "none";
111
114
  };
112
- return u(o.get()), v(o, u), { _tag: "div", node: t };
115
+ return u(o.get()), w(o, u), { _tag: "div", node: n };
113
116
  };
114
117
  }
115
- function Q(e, n) {
118
+ function Z(e, t) {
116
119
  return (o) => {
117
- const t = document.createElement("div");
118
- t.dataset.concat = "";
119
- const [c, r] = h(() => e(o)), [u, d] = h(() => n(o));
120
- return t.appendChild(c.node), t.appendChild(u.node), i(r), i(d), { _tag: "div", node: t };
120
+ const n = document.createElement("div");
121
+ n.dataset.concat = "";
122
+ const [c, r] = m(() => e(o)), [u, d] = m(() => t(o));
123
+ return n.appendChild(c.node), n.appendChild(u.node), l(r), l(d), { _tag: "div", node: n };
121
124
  };
122
125
  }
123
- function X(...e) {
124
- return (n) => {
126
+ function ee(...e) {
127
+ return (t) => {
125
128
  const o = document.createElement("div");
126
129
  o.dataset.stack = "";
127
- for (const t of e) {
128
- const [c, r] = h(() => t(n));
129
- o.appendChild(c.node), i(r);
130
+ for (const n of e) {
131
+ const [c, r] = m(() => n(t));
132
+ o.appendChild(c.node), l(r);
130
133
  }
131
134
  return { _tag: "div", node: o };
132
135
  };
133
136
  }
134
- function Y(e, n, o) {
135
- const t = document.createElement("template");
136
- return t.innerHTML = e, (c) => {
137
+ function te(e, t, o) {
138
+ const n = document.createElement("template");
139
+ return n.innerHTML = e, (c) => {
137
140
  const r = document.createElement("div");
138
- r.dataset.templ = "", r.appendChild(t.content.cloneNode(!0));
141
+ r.dataset.templ = "", r.appendChild(n.content.cloneNode(!0));
139
142
  const u = {};
140
- for (const d of Object.keys(n)) {
141
- const s = n[d], a = r.querySelector(`${s}[data-ref="${d}"]`);
143
+ for (const d of Object.keys(t)) {
144
+ const s = t[d], a = r.querySelector(`${s}[data-ref="${d}"]`);
142
145
  if (a === null)
143
146
  throw new Error(
144
147
  `templ: ref "${d}" not found — expected <${s} data-ref="${d}"> in template`
@@ -148,221 +151,281 @@ function Y(e, n, o) {
148
151
  return o(c, u), { _tag: "div", node: r };
149
152
  };
150
153
  }
151
- function Z(e, n, o, t) {
152
- const c = (t == null ? void 0 : t.container) ?? "div", r = document.createElement(c);
154
+ function ne(e, t, o, n) {
155
+ const c = (n == null ? void 0 : n.container) ?? "div", r = document.createElement(c);
153
156
  r.dataset.eachKeyed = "";
154
- const u = /* @__PURE__ */ new Map(), d = (a, l) => {
155
- const g = B(l);
156
- let m = !1, w = () => {
157
+ const u = /* @__PURE__ */ new Map(), d = (a, f) => {
158
+ const b = j(f);
159
+ let v = !1, C = () => {
157
160
  };
158
- "set" in e && (w = g.subscribe((b) => {
159
- if (m) return;
160
- const E = e.get(), x = E.findIndex((y) => n(y) === a);
161
- if (x !== -1 && !Object.is(E[x], b)) {
162
- const y = [...E];
163
- y[x] = b, e.set(y);
161
+ "set" in e && (C = b.subscribe((g) => {
162
+ if (v) return;
163
+ const x = e.get(), N = x.findIndex((y) => t(y) === a);
164
+ if (N !== -1 && !Object.is(x[N], g)) {
165
+ const y = [...x];
166
+ y[N] = g, e.set(y);
164
167
  }
165
168
  }));
166
- const [f, p] = h(() => o(g));
169
+ const [p, h] = m(() => o(b));
167
170
  return {
168
- itemSignal: g,
169
- childNode: f.node,
171
+ itemSignal: b,
172
+ childNode: p.node,
170
173
  cleanup: () => {
171
- p(), w();
174
+ h(), C();
172
175
  },
173
- setFromParent: (b) => {
174
- m = !0, g.set(b), m = !1;
176
+ setFromParent: (g) => {
177
+ v = !0, b.set(g), v = !1;
175
178
  }
176
179
  };
177
180
  }, s = (a) => {
178
- var w;
179
- const l = a.map(n), g = new Set(l);
180
- for (const [f, p] of u)
181
- g.has(f) || (p.cleanup(), (w = p.childNode.parentNode) == null || w.removeChild(p.childNode), u.delete(f));
182
- for (let f = 0; f < a.length; f++) {
183
- const p = l[f], b = a[f];
184
- u.has(p) ? u.get(p).setFromParent(b) : u.set(p, d(p, b));
181
+ var C;
182
+ const f = a.map(t), b = new Set(f);
183
+ for (const [p, h] of u)
184
+ b.has(p) || (h.cleanup(), (C = h.childNode.parentNode) == null || C.removeChild(h.childNode), u.delete(p));
185
+ for (let p = 0; p < a.length; p++) {
186
+ const h = f[p], g = a[p];
187
+ u.has(h) ? u.get(h).setFromParent(g) : u.set(h, d(h, g));
185
188
  }
186
- let m = null;
187
- for (let f = a.length - 1; f >= 0; f--) {
188
- const p = u.get(l[f]);
189
- (p.childNode.parentNode !== r || p.childNode.nextSibling !== m) && r.insertBefore(p.childNode, m), m = p.childNode;
189
+ let v = null;
190
+ for (let p = a.length - 1; p >= 0; p--) {
191
+ const h = u.get(f[p]);
192
+ (h.childNode.parentNode !== r || h.childNode.nextSibling !== v) && r.insertBefore(h.childNode, v), v = h.childNode;
190
193
  }
191
194
  };
192
- return s(e.get()), v(e, s), i(() => {
195
+ return s(e.get()), w(e, s), l(() => {
193
196
  for (const a of u.values()) a.cleanup();
194
197
  }), { _tag: c, node: r };
195
198
  }
196
- function _(e, n, o) {
197
- const t = o;
198
- e.addEventListener(n, t), i(() => e.removeEventListener(n, t));
199
+ function A(e, t, o) {
200
+ const n = o;
201
+ e.addEventListener(t, n), l(() => e.removeEventListener(t, n));
199
202
  }
200
- function A(e, n) {
201
- e.value = n.get();
202
- const o = () => n.set(e.value);
203
+ function S(e, t) {
204
+ e.value = t.get();
205
+ const o = () => t.set(e.value);
203
206
  e.addEventListener("input", o);
204
- const t = n.subscribe((r) => {
207
+ const n = t.subscribe((r) => {
205
208
  e.value !== r && (e.value = r);
206
209
  }), c = () => {
207
- e.removeEventListener("input", o), t();
210
+ e.removeEventListener("input", o), n();
208
211
  };
209
- return i(c), c;
212
+ return l(c), c;
210
213
  }
211
- function P(e, n) {
212
- _(e, "change", () => n.set(e.value)), v(n, (o) => {
214
+ function T(e, t) {
215
+ A(e, "change", () => t.set(e.value)), w(t, (o) => {
213
216
  e.value !== o && (e.value = o);
214
217
  });
215
218
  }
216
- function j(e, n) {
217
- _(e, "change", () => n.set(e.checked)), v(n, (o) => {
219
+ function q(e, t) {
220
+ A(e, "change", () => t.set(e.checked)), w(t, (o) => {
218
221
  e.checked !== o && (e.checked = o);
219
222
  });
220
223
  }
221
- function ee(e, n) {
222
- n(e.get()), i(e.subscribe(n));
224
+ function oe(e, t) {
225
+ t(e.get()), l(e.subscribe(t));
223
226
  }
224
- function te(e, n) {
225
- e.textContent = n.get(), i(n.subscribe((o) => {
227
+ function ce(e, t) {
228
+ e.textContent = t.get(), l(t.subscribe((o) => {
226
229
  e.textContent = o;
227
230
  }));
228
231
  }
229
- function ne(e, n, o) {
230
- e.setAttribute(n, o.get()), i(o.subscribe((t) => {
231
- e.setAttribute(n, t);
232
+ function re(e, t, o) {
233
+ e.setAttribute(t, o.get()), l(o.subscribe((n) => {
234
+ e.setAttribute(t, n);
232
235
  }));
233
236
  }
234
- function oe(e, n, o) {
235
- e.classList.toggle(n, o.get()), i(o.subscribe((t) => {
236
- e.classList.toggle(n, t);
237
+ function ue(e, t, o) {
238
+ e.classList.toggle(t, o.get()), l(o.subscribe((n) => {
239
+ e.classList.toggle(t, n);
237
240
  }));
238
241
  }
239
- function ce(e, n) {
240
- n();
241
- const o = e.map((t) => t.subscribe(n));
242
+ function de(e, t) {
243
+ t();
244
+ const o = e.map((n) => n.subscribe(t));
242
245
  return () => {
243
- for (const t of o) t();
246
+ for (const n of o) n();
244
247
  };
245
248
  }
246
- function re(e, n) {
247
- return e.style.display = n.get() ? "" : "none", n.subscribe((o) => {
249
+ function ie(e, t) {
250
+ return e.style.display = t.get() ? "" : "none", t.subscribe((o) => {
248
251
  e.style.display = o ? "" : "none";
249
252
  });
250
253
  }
251
- function ue(e, n) {
254
+ function ae(e, t) {
252
255
  return (o) => {
253
- const t = document.createElement("div");
254
- t.dataset.match = "";
256
+ const n = document.createElement("div");
257
+ n.dataset.match = "";
255
258
  let c = null, r = null;
256
259
  const u = (d) => {
257
260
  const s = d[e];
258
261
  if (s === r) return;
259
- c == null || c(), c = null, t.replaceChildren(), r = s;
260
- const a = n[s];
262
+ c == null || c(), c = null, n.replaceChildren(), r = s;
263
+ const a = t[s];
261
264
  if (a == null) return;
262
- const l = o.narrow(W(e, s));
263
- let g;
264
- [g, c] = h(
265
- () => a(l)
266
- ), t.appendChild(g.node);
265
+ const f = o.narrow($(e, s));
266
+ let b;
267
+ [b, c] = m(
268
+ () => a(f)
269
+ ), n.appendChild(b.node);
267
270
  };
268
- return v(o, u), u(o.get()), i(() => c == null ? void 0 : c()), { _tag: "div", node: t };
271
+ return w(o, u), u(o.get()), l(() => c == null ? void 0 : c()), { _tag: "div", node: n };
269
272
  };
270
273
  }
271
- function de(e, n) {
274
+ function se(e, t) {
272
275
  const o = document.createElement("div");
273
276
  o.dataset.foldWidget = "";
274
- let t = null;
277
+ let n = null;
275
278
  const c = (r) => {
276
- t !== null && (t(), t = null), o.replaceChildren();
279
+ n !== null && (n(), n = null), o.replaceChildren();
277
280
  let u = null;
278
281
  switch (r.status) {
279
282
  case "notAsked":
280
- u = n.notAsked ?? null;
283
+ u = t.notAsked ?? null;
281
284
  break;
282
285
  case "loading":
283
- u = n.loading ?? null;
286
+ u = t.loading ?? null;
284
287
  break;
285
288
  case "failure":
286
- u = n.failure ? () => n.failure(r.error) : null;
289
+ u = t.failure ? () => t.failure(r.error) : null;
287
290
  break;
288
291
  case "success":
289
- u = n.success ? () => n.success(r.value) : null;
292
+ u = t.success ? () => t.success(r.value) : null;
290
293
  break;
291
294
  }
292
295
  if (u !== null) {
293
296
  let d;
294
- [d, t] = h(u), o.appendChild(d.node);
297
+ [d, n] = m(u), o.appendChild(d.node);
295
298
  }
296
299
  };
297
- return c(e.get()), i(e.subscribe(c)), i(() => t == null ? void 0 : t()), { _tag: "div", node: o };
300
+ return c(e.get()), l(e.subscribe(c)), l(() => n == null ? void 0 : n()), { _tag: "div", node: o };
298
301
  }
299
- function ae(e) {
300
- return (n) => {
301
- const o = n, t = N(e ?? {});
302
- return t.node.value = o.get(), A(t.node, o), t;
302
+ function le(e) {
303
+ return (t) => {
304
+ const o = t, n = _(e ?? {});
305
+ return n.node.value = o.get(), S(n.node, o), n;
303
306
  };
304
307
  }
305
- function se(e) {
306
- return (n) => {
307
- const o = n, t = I(e ?? {});
308
- return t.node.value = o.get(), A(t.node, o), t;
308
+ function fe(e) {
309
+ return (t) => {
310
+ const o = t, n = O(e ?? {});
311
+ return n.node.value = o.get(), S(n.node, o), n;
309
312
  };
310
313
  }
311
- function ie(e) {
312
- return (n) => {
313
- const o = n, t = N({ ...e, type: "checkbox" });
314
- return t.node.checked = o.get(), j(t.node, o), t;
314
+ function pe(e) {
315
+ return (t) => {
316
+ const o = t, n = _({ ...e, type: "checkbox" });
317
+ return n.node.checked = o.get(), q(n.node, o), n;
315
318
  };
316
319
  }
317
- function le(e) {
318
- return (n) => {
319
- const o = n, t = N({ ...e, type: "number" });
320
- return t.node.value = String(o.get()), _(t.node, "input", () => {
321
- const c = t.node.valueAsNumber;
320
+ function he(e) {
321
+ return (t) => {
322
+ const o = t, n = _({ ...e, type: "number" });
323
+ return n.node.value = String(o.get()), A(n.node, "input", () => {
324
+ const c = n.node.valueAsNumber;
322
325
  isNaN(c) || o.set(c);
323
- }), v(n, (c) => {
324
- t.node.valueAsNumber !== c && (t.node.value = String(c));
325
- }), t;
326
+ }), w(t, (c) => {
327
+ n.node.valueAsNumber !== c && (n.node.value = String(c));
328
+ }), n;
326
329
  };
327
330
  }
328
- function fe(e, n) {
331
+ function me(e, t) {
329
332
  return (o) => {
330
- const t = o, c = $(n ?? {}, ...e.map((r) => F({ value: r.value }, r.label)));
331
- return c.node.value = t.get(), P(c.node, t), c;
333
+ const n = o, c = F(t ?? {}, ...e.map((r) => I({ value: r.value }, r.label)));
334
+ return c.node.value = n.get(), T(c.node, n), c;
335
+ };
336
+ }
337
+ function be(e) {
338
+ return (t) => e;
339
+ }
340
+ function i(e) {
341
+ return (t, ...o) => (n) => {
342
+ const c = document.createElement(e);
343
+ for (const [r, u] of Object.entries(t))
344
+ u == null || u === !1 || c.setAttribute(r, u === !0 ? "" : String(u));
345
+ for (const r of o)
346
+ typeof r == "function" ? c.appendChild(r(n).node) : c.appendChild(document.createTextNode(r));
347
+ return { _tag: e, node: c };
332
348
  };
333
349
  }
350
+ const ge = {
351
+ // Sectioning / flow
352
+ div: i("div"),
353
+ section: i("section"),
354
+ article: i("article"),
355
+ header: i("header"),
356
+ footer: i("footer"),
357
+ main: i("main"),
358
+ nav: i("nav"),
359
+ // Headings
360
+ h1: i("h1"),
361
+ h2: i("h2"),
362
+ h3: i("h3"),
363
+ h4: i("h4"),
364
+ h5: i("h5"),
365
+ h6: i("h6"),
366
+ // Phrasing
367
+ p: i("p"),
368
+ span: i("span"),
369
+ a: i("a"),
370
+ em: i("em"),
371
+ strong: i("strong"),
372
+ code: i("code"),
373
+ pre: i("pre"),
374
+ // Lists
375
+ ul: i("ul"),
376
+ ol: i("ol"),
377
+ li: i("li"),
378
+ // Forms
379
+ button: i("button"),
380
+ label: i("label"),
381
+ form: i("form"),
382
+ fieldset: i("fieldset")
383
+ };
384
+ function ve(e, t, o, n) {
385
+ const c = o(t.get());
386
+ if (c === void 0) {
387
+ e.remove();
388
+ return;
389
+ }
390
+ const r = c(n ?? t);
391
+ e.replaceWith(r.node);
392
+ }
334
393
  export {
335
- z as above,
336
- U as beside,
337
- ne as bindAttr,
338
- j as bindCheckbox,
339
- oe as bindClass,
340
- A as bindInput,
341
- P as bindSelect,
342
- re as bindShow,
343
- te as bindText,
344
- ie as checkboxWidget,
345
- Q as concat,
346
- D as dynamic,
347
- R as each,
348
- Z as eachKeyed,
349
- V as focus,
350
- de as foldWidget,
351
- ae as inputWidget,
352
- G as map,
353
- ue as match,
354
- T as mount,
355
- H as narrow,
356
- le as numberInputWidget,
357
- _ as on,
358
- O as register,
359
- fe as selectWidget,
360
- J as show,
361
- X as stack,
362
- v as subscribe,
363
- ee as subscribeNow,
364
- Y as template,
365
- se as textareaWidget,
366
- ce as watchAll,
367
- M as withScope
394
+ J as above,
395
+ G as beside,
396
+ re as bindAttr,
397
+ q as bindCheckbox,
398
+ ue as bindClass,
399
+ S as bindInput,
400
+ T as bindSelect,
401
+ ie as bindShow,
402
+ ce as bindText,
403
+ pe as checkboxWidget,
404
+ Z as concat,
405
+ Q as dynamic,
406
+ D as each,
407
+ ne as eachKeyed,
408
+ P as focus,
409
+ se as foldWidget,
410
+ ge as h,
411
+ le as inputWidget,
412
+ be as lift,
413
+ X as map,
414
+ ae as match,
415
+ R as mount,
416
+ z as narrow,
417
+ he as numberInputWidget,
418
+ A as on,
419
+ U as prop,
420
+ H as register,
421
+ me as selectWidget,
422
+ Y as show,
423
+ ve as slot,
424
+ ee as stack,
425
+ w as subscribe,
426
+ oe as subscribeNow,
427
+ te as template,
428
+ fe as textareaWidget,
429
+ de as watchAll,
430
+ V as withScope
368
431
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rhi-zone/rainbow-ui",
3
- "version": "0.2.0-alpha.3",
3
+ "version": "0.2.0-alpha.5",
4
4
  "description": "Type-safe DOM factories and algebraic widget combinators for rainbow",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",