@rhi-zone/rainbow-ui 0.2.0-alpha.2 → 0.2.0-alpha.4

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, mount as B, narrow as D, numberInputWidget as J, on as T, register as V, selectWidget as j, show as q, stack as z, subscribe as G, subscribeNow as H, template as M, textareaWidget as O, watchAll as P, withScope as Q } from "./widget.js";
3
- import { createForm as U, createFormState as X, isDirty as Y, isFormValid as Z, shouldShowError as _ } from "./form-state.js";
1
+ import { h as u } 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, h as L, inputWidget as N, map as B, match as D, mount as J, narrow as T, numberInputWidget as V, on as j, prop as q, register as z, selectWidget as G, show as H, slot as M, stack as O, subscribe as P, subscribeNow as Q, template as R, textareaWidget as U, watchAll as X, withScope as Y } from "./widget.js";
3
+ import { createForm as _, createFormState as $, isDirty as ee, isFormValid as te, shouldShowError as ne } from "./form-state.js";
4
4
  import { signal as a } from "@rhi-zone/rainbow";
5
- import { attrBoolean as ee, attrJson as te, attrNumber as ne, attrString as ie, attrsFrom as oe, defineElement as re } from "./elements.js";
6
- function c(e, n, t, r, i) {
7
- const o = e(
5
+ import { attrBoolean as ie, attrJson as re, attrNumber as se, attrString as ae, attrsFrom as ce, defineElement as de } 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
26
  l as above,
27
- ee as attrBoolean,
28
- te as attrJson,
29
- ne as attrNumber,
30
- ie as attrString,
31
- oe as attrsFrom,
27
+ ie as attrBoolean,
28
+ re as attrJson,
29
+ se as attrNumber,
30
+ ae as attrString,
31
+ ce as attrsFrom,
32
32
  p as beside,
33
33
  f as bindAttr,
34
34
  x as bindCheckbox,
@@ -40,33 +40,37 @@ export {
40
40
  b as bindingsStoreSignal,
41
41
  k as checkboxWidget,
42
42
  C as concat,
43
- U as createForm,
44
- X as createFormState,
45
- re as defineElement,
43
+ _ as createForm,
44
+ $ as createFormState,
45
+ de 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
- Y as isDirty,
54
- Z as isFormValid,
55
- c as keybindsContext,
56
- N as map,
57
- B as mount,
58
- D as narrow,
59
- J as numberInputWidget,
60
- T as on,
61
- V as register,
62
- j as selectWidget,
63
- _ as shouldShowError,
64
- q as show,
65
- z as stack,
66
- G as subscribe,
67
- H as subscribeNow,
68
- M as template,
69
- O as textareaWidget,
70
- P as watchAll,
71
- Q as withScope
51
+ L as h,
52
+ u as html,
53
+ N as inputWidget,
54
+ ee as isDirty,
55
+ te as isFormValid,
56
+ d as keybindsContext,
57
+ B as map,
58
+ D as match,
59
+ J as mount,
60
+ T as narrow,
61
+ V as numberInputWidget,
62
+ j as on,
63
+ q as prop,
64
+ z as register,
65
+ G as selectWidget,
66
+ ne as shouldShowError,
67
+ H as show,
68
+ M as slot,
69
+ O as stack,
70
+ P as subscribe,
71
+ Q as subscribeNow,
72
+ R as template,
73
+ U as textareaWidget,
74
+ X as watchAll,
75
+ Y as withScope
72
76
  };
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)
@@ -379,6 +395,30 @@ export declare function bindShow(el: HTMLElement, s: ReadonlySignal<boolean>): (
379
395
  * success: (data) => renderData(data),
380
396
  * })
381
397
  */
398
+ /**
399
+ * Render a discriminated union by tag. Exhaustively maps each variant to a
400
+ * widget; swaps the rendered child when the tag changes.
401
+ *
402
+ * Compared to N `narrow` + `stack` calls:
403
+ * - Single container div (not N+1)
404
+ * - Exhaustiveness checked at compile time — missing variant = type error
405
+ * - No `tagged()` declarations at the call site
406
+ *
407
+ * Must be called during a widget call context.
408
+ *
409
+ * @example
410
+ * type Screen =
411
+ * | { screen: 'list'; items: Item[] }
412
+ * | { screen: 'detail'; item: Item }
413
+ *
414
+ * match('screen', {
415
+ * list: (s) => listWidget(s),
416
+ * detail: (s) => detailWidget(s),
417
+ * })
418
+ */
419
+ export declare function match<S extends Record<K, string>, K extends keyof S & string>(key: K, cases: {
420
+ [V in S[K] & string]: Widget<Extract<S, Record<K, V>>, FlowContent>;
421
+ }): Widget<S, DivEl>;
382
422
  export declare function foldWidget<T, E>(s: Signal<AsyncData<T, E>> | ReadonlySignal<AsyncData<T, E>>, cases: {
383
423
  notAsked?: () => AnyEl;
384
424
  loading?: () => AnyEl;
@@ -417,4 +457,62 @@ export declare function selectWidget(options: {
417
457
  value: string;
418
458
  label: string;
419
459
  }[], attrs?: SelectAttrs): Widget<string, SelectEl>;
460
+ /**
461
+ * A reactive child: either a static element, a string, or a widget that
462
+ * accepts the same signal type `T` and returns any element.
463
+ */
464
+ export type RChild<T> = AnyEl | string | Widget<T, AnyEl>;
465
+ /**
466
+ * Reactive hyperscript factories — the same element tags as `html.ts` but
467
+ * returning `Widget<T, El>` instead of `El`. Import as:
468
+ *
469
+ * import { h } from '@rhi-zone/rainbow-ui/widget'
470
+ *
471
+ * Widget children receive the same signal as their parent. Static children
472
+ * (`AnyEl`) are deep-cloned on each widget invocation so that the same static
473
+ * node can be safely reused across multiple widget instances.
474
+ */
475
+ export declare const h: {
476
+ readonly div: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"div", HTMLDivElement>;
477
+ readonly section: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"section", HTMLElement>;
478
+ readonly article: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"article", HTMLElement>;
479
+ readonly header: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"header", HTMLElement>;
480
+ readonly footer: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"footer", HTMLElement>;
481
+ readonly main: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"main", HTMLElement>;
482
+ readonly nav: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"nav", HTMLElement>;
483
+ readonly h1: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"h1", HTMLHeadingElement>;
484
+ readonly h2: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"h2", HTMLHeadingElement>;
485
+ readonly h3: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"h3", HTMLHeadingElement>;
486
+ readonly h4: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"h4", HTMLHeadingElement>;
487
+ readonly h5: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"h5", HTMLHeadingElement>;
488
+ readonly h6: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"h6", HTMLHeadingElement>;
489
+ readonly p: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"p", HTMLParagraphElement>;
490
+ readonly span: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"span", HTMLSpanElement>;
491
+ readonly a: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"a", HTMLAnchorElement>;
492
+ readonly em: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"em", HTMLElement>;
493
+ readonly strong: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"strong", HTMLElement>;
494
+ readonly code: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"code", HTMLElement>;
495
+ readonly pre: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"pre", HTMLPreElement>;
496
+ readonly ul: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"ul", HTMLUListElement>;
497
+ readonly ol: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"ol", HTMLOListElement>;
498
+ readonly li: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"li", HTMLLIElement>;
499
+ readonly button: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"button", HTMLButtonElement>;
500
+ readonly label: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"label", HTMLLabelElement>;
501
+ readonly form: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"form", HTMLFormElement>;
502
+ readonly fieldset: <T>(attrs: GlobalAttrs, ...children: RChild<T>[]) => (s: Signal<T>) => El<"fieldset", HTMLFieldSetElement>;
503
+ };
504
+ /** A widget that takes no meaningful signal and renders flow content. */
505
+ export type Slot = Widget<void, FlowContent>;
506
+ /** A widget that takes a typed signal `T` and renders flow content. */
507
+ export type ScopedSlot<T> = Widget<T, FlowContent>;
508
+ /**
509
+ * Mount a slot widget by replacing a placeholder element.
510
+ * If no slot is provided, removes the placeholder.
511
+ * The slot signal defaults to `s` (cast) if `slotSignal` is omitted.
512
+ *
513
+ * @example
514
+ * slot(placeholder, s, v => v.actionsSlot) // slot signal = s
515
+ * slot(placeholder, s, v => v.rowSlot, s.focus(rowLens)) // slot signal = focused
516
+ */
517
+ export declare function slot<Props, T>(placeholder: HTMLElement, s: Signal<Props>, extract: (props: Props) => Widget<T, FlowContent> | undefined, slotSignal?: Signal<T>): void;
420
518
  export {};
package/dist/widget.js CHANGED
@@ -1,347 +1,427 @@
1
- import { index as C, stateful as S, lens as L, signal as W } from "@rhi-zone/rainbow";
2
- import { i as N, s as B, o as $, t as F } from "./html-C8SnQjvU.js";
3
- let k = null;
4
- function i(e) {
5
- k == null || k.push(e);
6
- }
7
- function b(e) {
8
- const t = k, o = [];
9
- k = o;
10
- const n = e();
11
- return k = t, [n, () => {
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
+ let y = null;
4
+ function l(e) {
5
+ y == null || y.push(e);
6
+ }
7
+ function g(e) {
8
+ const n = y, o = [];
9
+ y = o;
10
+ const t = e();
11
+ return y = n, [t, () => {
12
12
  for (const c of o) c();
13
13
  }];
14
14
  }
15
- function K(e) {
16
- return b(e);
15
+ function V(e) {
16
+ return g(e);
17
17
  }
18
- function w(e, t) {
19
- i(e.subscribe(t));
18
+ function w(e, n) {
19
+ l(e.subscribe(n));
20
20
  }
21
- function M(e) {
22
- i(e);
21
+ function H(e) {
22
+ l(e);
23
23
  }
24
- function O(e, t, o) {
25
- const [n, c] = b(() => e(t));
26
- return o.appendChild(n.node), () => {
27
- n.node.remove(), c();
24
+ function R(e, n, o) {
25
+ const [t, c] = g(() => e(n));
26
+ return o.appendChild(t.node), () => {
27
+ t.node.remove(), c();
28
28
  };
29
29
  }
30
- function T(e, t) {
31
- return (o) => e(o.focus(t));
30
+ function P(e, n) {
31
+ return (o) => e(o.focus(n));
32
32
  }
33
- function H(e, t) {
33
+ function U(e, n) {
34
+ return P(e, W(n));
35
+ }
36
+ function z(e, n) {
34
37
  return (o) => {
35
- const n = document.createElement("div");
36
- n.dataset.narrow = "";
38
+ const t = document.createElement("div");
39
+ t.dataset.narrow = "";
37
40
  let c = null, r = null;
38
- const u = o, d = () => {
39
- r = u.narrow(t);
40
- const [s, p] = b(() => e(r));
41
- c = p, n.appendChild(s.node);
41
+ const d = o, u = () => {
42
+ r = d.narrow(n);
43
+ const [a, f] = g(() => e(r));
44
+ c = f, t.appendChild(a.node);
42
45
  };
43
- return w(o, (s) => {
44
- const p = t.view(s);
45
- p !== void 0 && c === null ? d() : p === void 0 && c !== null && (c(), c = null, r = null, n.replaceChildren());
46
- }), t.view(o.get()) !== void 0 && d(), i(() => c == null ? void 0 : c()), { _tag: "div", node: n };
46
+ return w(o, (a) => {
47
+ const f = n.view(a);
48
+ f !== void 0 && c === null ? u() : f === void 0 && c !== null && (c(), c = null, r = null, t.replaceChildren());
49
+ }), n.view(o.get()) !== void 0 && u(), l(() => c == null ? void 0 : c()), { _tag: "div", node: t };
47
50
  };
48
51
  }
49
- function R(e) {
50
- return (t) => {
51
- const o = t, n = document.createElement("div");
52
- n.dataset.each = "";
52
+ function D(e) {
53
+ return (n) => {
54
+ const o = n, t = document.createElement("div");
55
+ t.dataset.each = "";
53
56
  let c = [];
54
- const r = (d) => {
55
- for (const a of c) a();
56
- c = [], n.replaceChildren();
57
- for (let a = 0; a < d.length; a++) {
58
- const s = a, p = L(
59
- (l) => l[s],
60
- (l, f) => {
61
- const h = [...f];
62
- return h[s] = l, h;
57
+ const r = (u) => {
58
+ for (const s of c) s();
59
+ c = [], t.replaceChildren();
60
+ for (let s = 0; s < u.length; s++) {
61
+ const a = s, f = B(
62
+ (p) => p[a],
63
+ (p, h) => {
64
+ const b = [...h];
65
+ return b[a] = p, b;
63
66
  }
64
- ), m = o.focus(p), [g, v] = b(() => e(m));
65
- c.push(v), n.appendChild(g.node);
67
+ ), m = o.focus(f), [v, C] = g(() => e(m));
68
+ c.push(C), t.appendChild(v.node);
66
69
  }
67
70
  };
68
- r(t.get());
69
- const u = t.map((d) => d.length);
70
- return w(u, () => r(t.get())), i(() => {
71
- for (const d of c) d();
72
- }), { _tag: "div", node: n };
71
+ r(n.get());
72
+ const d = n.map((u) => u.length);
73
+ return w(d, () => r(n.get())), l(() => {
74
+ for (const u of c) u();
75
+ }), { _tag: "div", node: t };
73
76
  };
74
77
  }
75
- function U(e, t) {
78
+ function G(e, n) {
76
79
  return (o) => {
77
- const n = o, c = document.createElement("div");
80
+ const t = o, c = document.createElement("div");
78
81
  c.dataset.beside = "";
79
- const r = n.focus(C(0)), u = n.focus(C(1)), [d, a] = b(() => e(r)), [s, p] = b(() => t(u));
80
- return c.appendChild(d.node), c.appendChild(s.node), i(a), i(p), { _tag: "div", node: c };
82
+ const r = t.focus(E(0)), d = t.focus(E(1)), [u, s] = g(() => e(r)), [a, f] = g(() => n(d));
83
+ return c.appendChild(u.node), c.appendChild(a.node), l(s), l(f), { _tag: "div", node: c };
81
84
  };
82
85
  }
83
- function V(e, t) {
86
+ function J(e, n) {
84
87
  return (o) => {
85
- const n = o, c = document.createElement("div");
88
+ const t = o, c = document.createElement("div");
86
89
  c.dataset.above = "";
87
- const r = n.focus(C(0)), u = n.focus(C(1)), [d, a] = b(() => e(r)), [s, p] = b(() => t(u));
88
- return c.appendChild(d.node), c.appendChild(s.node), i(a), i(p), { _tag: "div", node: c };
90
+ const r = t.focus(E(0)), d = t.focus(E(1)), [u, s] = g(() => e(r)), [a, f] = g(() => n(d));
91
+ return c.appendChild(u.node), c.appendChild(a.node), l(s), l(f), { _tag: "div", node: c };
89
92
  };
90
93
  }
91
- function z(e, t) {
94
+ function Q(e, n) {
92
95
  return (o) => {
93
- const n = S(e, o);
94
- return t(n);
96
+ const t = L(e, o);
97
+ return n(t);
95
98
  };
96
99
  }
97
- function D(e, t) {
100
+ function X(e, n) {
98
101
  return (o) => {
99
- const n = o.narrow(t);
100
- return e(n);
102
+ const t = o.narrow(n);
103
+ return e(t);
101
104
  };
102
105
  }
103
- function G(e, t) {
106
+ function Y(e, n) {
104
107
  return (o) => {
105
- const n = document.createElement("div");
106
- n.dataset.show = "";
107
- const [c, r] = b(() => e(o));
108
- n.appendChild(c.node), i(r);
109
- const u = (d) => {
110
- n.style.display = t(d) ? "" : "none";
108
+ const t = document.createElement("div");
109
+ t.dataset.show = "";
110
+ const [c, r] = g(() => e(o));
111
+ t.appendChild(c.node), l(r);
112
+ const d = (u) => {
113
+ t.style.display = n(u) ? "" : "none";
111
114
  };
112
- return u(o.get()), w(o, u), { _tag: "div", node: n };
115
+ return d(o.get()), w(o, d), { _tag: "div", node: t };
113
116
  };
114
117
  }
115
- function J(e, t) {
118
+ function Z(e, n) {
116
119
  return (o) => {
117
- const n = document.createElement("div");
118
- n.dataset.concat = "";
119
- const [c, r] = b(() => e(o)), [u, d] = b(() => t(o));
120
- return n.appendChild(c.node), n.appendChild(u.node), i(r), i(d), { _tag: "div", node: n };
120
+ const t = document.createElement("div");
121
+ t.dataset.concat = "";
122
+ const [c, r] = g(() => e(o)), [d, u] = g(() => n(o));
123
+ return t.appendChild(c.node), t.appendChild(d.node), l(r), l(u), { _tag: "div", node: t };
121
124
  };
122
125
  }
123
- function Q(...e) {
124
- return (t) => {
126
+ function ee(...e) {
127
+ return (n) => {
125
128
  const o = document.createElement("div");
126
129
  o.dataset.stack = "";
127
- for (const n of e) {
128
- const [c, r] = b(() => n(t));
129
- o.appendChild(c.node), i(r);
130
+ for (const t of e) {
131
+ const [c, r] = g(() => t(n));
132
+ o.appendChild(c.node), l(r);
130
133
  }
131
134
  return { _tag: "div", node: o };
132
135
  };
133
136
  }
134
- function X(e, t, o) {
135
- const n = document.createElement("template");
136
- return n.innerHTML = e, (c) => {
137
+ function te(e, n, o) {
138
+ const t = document.createElement("template");
139
+ return t.innerHTML = e, (c) => {
137
140
  const r = document.createElement("div");
138
- r.dataset.templ = "", r.appendChild(n.content.cloneNode(!0));
139
- const u = {};
140
- for (const d of Object.keys(t)) {
141
- const a = t[d], s = r.querySelector(`${a}[data-ref="${d}"]`);
142
- if (s === null)
141
+ r.dataset.templ = "", r.appendChild(t.content.cloneNode(!0));
142
+ const d = {};
143
+ for (const u of Object.keys(n)) {
144
+ const s = n[u], a = r.querySelector(`${s}[data-ref="${u}"]`);
145
+ if (a === null)
143
146
  throw new Error(
144
- `templ: ref "${d}" not found — expected <${a} data-ref="${d}"> in template`
147
+ `templ: ref "${u}" not found — expected <${s} data-ref="${u}"> in template`
145
148
  );
146
- u[d] = { _tag: a, node: s };
149
+ d[u] = { _tag: s, node: a };
147
150
  }
148
- return o(c, u), { _tag: "div", node: r };
151
+ return o(c, d), { _tag: "div", node: r };
149
152
  };
150
153
  }
151
- function Y(e, t, o, n) {
152
- const c = (n == null ? void 0 : n.container) ?? "div", r = document.createElement(c);
154
+ function ne(e, n, o, t) {
155
+ const c = (t == null ? void 0 : t.container) ?? "div", r = document.createElement(c);
153
156
  r.dataset.eachKeyed = "";
154
- const u = /* @__PURE__ */ new Map(), d = (s, p) => {
155
- const m = W(p);
156
- let g = !1, v = () => {
157
+ const d = /* @__PURE__ */ new Map(), u = (a, f) => {
158
+ const m = j(f);
159
+ let v = !1, C = () => {
157
160
  };
158
- "set" in e && (v = m.subscribe((h) => {
159
- if (g) return;
160
- const x = e.get(), E = x.findIndex((y) => t(y) === s);
161
- if (E !== -1 && !Object.is(x[E], h)) {
162
- const y = [...x];
163
- y[E] = h, e.set(y);
161
+ "set" in e && (C = m.subscribe((b) => {
162
+ if (v) return;
163
+ const x = e.get(), N = x.findIndex((k) => n(k) === a);
164
+ if (N !== -1 && !Object.is(x[N], b)) {
165
+ const k = [...x];
166
+ k[N] = b, e.set(k);
164
167
  }
165
168
  }));
166
- const [l, f] = b(() => o(m));
169
+ const [p, h] = g(() => o(m));
167
170
  return {
168
171
  itemSignal: m,
169
- childNode: l.node,
172
+ childNode: p.node,
170
173
  cleanup: () => {
171
- f(), v();
174
+ h(), C();
172
175
  },
173
- setFromParent: (h) => {
174
- g = !0, m.set(h), g = !1;
176
+ setFromParent: (b) => {
177
+ v = !0, m.set(b), v = !1;
175
178
  }
176
179
  };
177
- }, a = (s) => {
178
- var v;
179
- const p = s.map(t), m = new Set(p);
180
- for (const [l, f] of u)
181
- m.has(l) || (f.cleanup(), (v = f.childNode.parentNode) == null || v.removeChild(f.childNode), u.delete(l));
182
- for (let l = 0; l < s.length; l++) {
183
- const f = p[l], h = s[l];
184
- u.has(f) ? u.get(f).setFromParent(h) : u.set(f, d(f, h));
180
+ }, s = (a) => {
181
+ var C;
182
+ const f = a.map(n), m = new Set(f);
183
+ for (const [p, h] of d)
184
+ m.has(p) || (h.cleanup(), (C = h.childNode.parentNode) == null || C.removeChild(h.childNode), d.delete(p));
185
+ for (let p = 0; p < a.length; p++) {
186
+ const h = f[p], b = a[p];
187
+ d.has(h) ? d.get(h).setFromParent(b) : d.set(h, u(h, b));
185
188
  }
186
- let g = null;
187
- for (let l = s.length - 1; l >= 0; l--) {
188
- const f = u.get(p[l]);
189
- (f.childNode.parentNode !== r || f.childNode.nextSibling !== g) && r.insertBefore(f.childNode, g), g = f.childNode;
189
+ let v = null;
190
+ for (let p = a.length - 1; p >= 0; p--) {
191
+ const h = d.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 a(e.get()), w(e, a), i(() => {
193
- for (const s of u.values()) s.cleanup();
195
+ return s(e.get()), w(e, s), l(() => {
196
+ for (const a of d.values()) a.cleanup();
194
197
  }), { _tag: c, node: r };
195
198
  }
196
- function A(e, t, o) {
197
- const n = o;
198
- e.addEventListener(t, n), i(() => e.removeEventListener(t, n));
199
+ function A(e, n, o) {
200
+ const t = o;
201
+ e.addEventListener(n, t), l(() => e.removeEventListener(n, t));
199
202
  }
200
- function _(e, t) {
201
- e.value = t.get();
202
- const o = () => t.set(e.value);
203
+ function S(e, n) {
204
+ e.value = n.get();
205
+ const o = () => n.set(e.value);
203
206
  e.addEventListener("input", o);
204
- const n = t.subscribe((r) => {
207
+ const t = n.subscribe((r) => {
205
208
  e.value !== r && (e.value = r);
206
209
  }), c = () => {
207
- e.removeEventListener("input", o), n();
210
+ e.removeEventListener("input", o), t();
208
211
  };
209
- return i(c), c;
212
+ return l(c), c;
210
213
  }
211
- function I(e, t) {
212
- A(e, "change", () => t.set(e.value)), w(t, (o) => {
214
+ function T(e, n) {
215
+ A(e, "change", () => n.set(e.value)), w(n, (o) => {
213
216
  e.value !== o && (e.value = o);
214
217
  });
215
218
  }
216
- function P(e, t) {
217
- A(e, "change", () => t.set(e.checked)), w(t, (o) => {
219
+ function q(e, n) {
220
+ A(e, "change", () => n.set(e.checked)), w(n, (o) => {
218
221
  e.checked !== o && (e.checked = o);
219
222
  });
220
223
  }
221
- function Z(e, t) {
222
- t(e.get()), i(e.subscribe(t));
224
+ function oe(e, n) {
225
+ n(e.get()), l(e.subscribe(n));
223
226
  }
224
- function ee(e, t) {
225
- e.textContent = t.get(), i(t.subscribe((o) => {
227
+ function ce(e, n) {
228
+ e.textContent = n.get(), l(n.subscribe((o) => {
226
229
  e.textContent = o;
227
230
  }));
228
231
  }
229
- function ne(e, t, o) {
230
- e.setAttribute(t, o.get()), i(o.subscribe((n) => {
231
- e.setAttribute(t, n);
232
+ function re(e, n, o) {
233
+ e.setAttribute(n, o.get()), l(o.subscribe((t) => {
234
+ e.setAttribute(n, t);
232
235
  }));
233
236
  }
234
- function te(e, t, o) {
235
- e.classList.toggle(t, o.get()), i(o.subscribe((n) => {
236
- e.classList.toggle(t, n);
237
+ function de(e, n, o) {
238
+ e.classList.toggle(n, o.get()), l(o.subscribe((t) => {
239
+ e.classList.toggle(n, t);
237
240
  }));
238
241
  }
239
- function oe(e, t) {
240
- t();
241
- const o = e.map((n) => n.subscribe(t));
242
+ function ue(e, n) {
243
+ n();
244
+ const o = e.map((t) => t.subscribe(n));
242
245
  return () => {
243
- for (const n of o) n();
246
+ for (const t of o) t();
244
247
  };
245
248
  }
246
- function ce(e, t) {
247
- return e.style.display = t.get() ? "" : "none", t.subscribe((o) => {
249
+ function ie(e, n) {
250
+ return e.style.display = n.get() ? "" : "none", n.subscribe((o) => {
248
251
  e.style.display = o ? "" : "none";
249
252
  });
250
253
  }
251
- function re(e, t) {
254
+ function ae(e, n) {
255
+ return (o) => {
256
+ const t = document.createElement("div");
257
+ t.dataset.match = "";
258
+ let c = null, r = null;
259
+ const d = (u) => {
260
+ const s = u[e];
261
+ if (s === r) return;
262
+ c == null || c(), c = null, t.replaceChildren(), r = s;
263
+ const a = n[s];
264
+ if (a == null) return;
265
+ const f = o.narrow($(e, s));
266
+ let m;
267
+ [m, c] = g(
268
+ () => a(f)
269
+ ), t.appendChild(m.node);
270
+ };
271
+ return w(o, d), d(o.get()), l(() => c == null ? void 0 : c()), { _tag: "div", node: t };
272
+ };
273
+ }
274
+ function se(e, n) {
252
275
  const o = document.createElement("div");
253
276
  o.dataset.foldWidget = "";
254
- let n = null;
277
+ let t = null;
255
278
  const c = (r) => {
256
- n !== null && (n(), n = null), o.replaceChildren();
257
- let u = null;
279
+ t !== null && (t(), t = null), o.replaceChildren();
280
+ let d = null;
258
281
  switch (r.status) {
259
282
  case "notAsked":
260
- u = t.notAsked ?? null;
283
+ d = n.notAsked ?? null;
261
284
  break;
262
285
  case "loading":
263
- u = t.loading ?? null;
286
+ d = n.loading ?? null;
264
287
  break;
265
288
  case "failure":
266
- u = t.failure ? () => t.failure(r.error) : null;
289
+ d = n.failure ? () => n.failure(r.error) : null;
267
290
  break;
268
291
  case "success":
269
- u = t.success ? () => t.success(r.value) : null;
292
+ d = n.success ? () => n.success(r.value) : null;
270
293
  break;
271
294
  }
272
- if (u !== null) {
273
- let d;
274
- [d, n] = b(u), o.appendChild(d.node);
295
+ if (d !== null) {
296
+ let u;
297
+ [u, t] = g(d), o.appendChild(u.node);
275
298
  }
276
299
  };
277
- return c(e.get()), i(e.subscribe(c)), i(() => n == null ? void 0 : n()), { _tag: "div", node: o };
300
+ return c(e.get()), l(e.subscribe(c)), l(() => t == null ? void 0 : t()), { _tag: "div", node: o };
278
301
  }
279
- function ue(e) {
280
- return (t) => {
281
- const o = t, n = N(e ?? {});
282
- return n.node.value = o.get(), _(n.node, o), n;
302
+ function le(e) {
303
+ return (n) => {
304
+ const o = n, t = _(e ?? {});
305
+ return t.node.value = o.get(), S(t.node, o), t;
283
306
  };
284
307
  }
285
- function de(e) {
286
- return (t) => {
287
- const o = t, n = F(e ?? {});
288
- return n.node.value = o.get(), _(n.node, o), n;
308
+ function fe(e) {
309
+ return (n) => {
310
+ const o = n, t = O(e ?? {});
311
+ return t.node.value = o.get(), S(t.node, o), t;
289
312
  };
290
313
  }
291
- function se(e) {
292
- return (t) => {
293
- const o = t, n = N({ ...e, type: "checkbox" });
294
- return n.node.checked = o.get(), P(n.node, o), n;
314
+ function pe(e) {
315
+ return (n) => {
316
+ const o = n, t = _({ ...e, type: "checkbox" });
317
+ return t.node.checked = o.get(), q(t.node, o), t;
295
318
  };
296
319
  }
297
- function ie(e) {
298
- return (t) => {
299
- const o = t, n = N({ ...e, type: "number" });
300
- return n.node.value = String(o.get()), A(n.node, "input", () => {
301
- const c = n.node.valueAsNumber;
320
+ function he(e) {
321
+ return (n) => {
322
+ const o = n, t = _({ ...e, type: "number" });
323
+ return t.node.value = String(o.get()), A(t.node, "input", () => {
324
+ const c = t.node.valueAsNumber;
302
325
  isNaN(c) || o.set(c);
303
- }), w(t, (c) => {
304
- n.node.valueAsNumber !== c && (n.node.value = String(c));
305
- }), n;
326
+ }), w(n, (c) => {
327
+ t.node.valueAsNumber !== c && (t.node.value = String(c));
328
+ }), t;
306
329
  };
307
330
  }
308
- function ae(e, t) {
331
+ function ge(e, n) {
309
332
  return (o) => {
310
- const n = o, c = B(t ?? {}, ...e.map((r) => $({ value: r.value }, r.label)));
311
- return c.node.value = n.get(), I(c.node, n), c;
333
+ const t = o, c = F(n ?? {}, ...e.map((r) => I({ value: r.value }, r.label)));
334
+ return c.node.value = t.get(), T(c.node, t), c;
335
+ };
336
+ }
337
+ function i(e) {
338
+ return (n, ...o) => (t) => {
339
+ const c = document.createElement(e);
340
+ for (const [r, d] of Object.entries(n))
341
+ d == null || d === !1 || c.setAttribute(r, d === !0 ? "" : String(d));
342
+ for (const r of o)
343
+ typeof r == "function" ? c.appendChild(r(t).node) : typeof r == "string" ? c.appendChild(document.createTextNode(r)) : c.appendChild(r.node.cloneNode(!0));
344
+ return { _tag: e, node: c };
312
345
  };
313
346
  }
347
+ const me = {
348
+ // Sectioning / flow
349
+ div: i("div"),
350
+ section: i("section"),
351
+ article: i("article"),
352
+ header: i("header"),
353
+ footer: i("footer"),
354
+ main: i("main"),
355
+ nav: i("nav"),
356
+ // Headings
357
+ h1: i("h1"),
358
+ h2: i("h2"),
359
+ h3: i("h3"),
360
+ h4: i("h4"),
361
+ h5: i("h5"),
362
+ h6: i("h6"),
363
+ // Phrasing
364
+ p: i("p"),
365
+ span: i("span"),
366
+ a: i("a"),
367
+ em: i("em"),
368
+ strong: i("strong"),
369
+ code: i("code"),
370
+ pre: i("pre"),
371
+ // Lists
372
+ ul: i("ul"),
373
+ ol: i("ol"),
374
+ li: i("li"),
375
+ // Forms
376
+ button: i("button"),
377
+ label: i("label"),
378
+ form: i("form"),
379
+ fieldset: i("fieldset")
380
+ };
381
+ function be(e, n, o, t) {
382
+ const c = o(n.get());
383
+ if (c === void 0) {
384
+ e.remove();
385
+ return;
386
+ }
387
+ const r = c(t ?? n);
388
+ e.replaceWith(r.node);
389
+ }
314
390
  export {
315
- V as above,
316
- U as beside,
317
- ne as bindAttr,
318
- P as bindCheckbox,
319
- te as bindClass,
320
- _ as bindInput,
321
- I as bindSelect,
322
- ce as bindShow,
323
- ee as bindText,
324
- se as checkboxWidget,
325
- J as concat,
326
- z as dynamic,
327
- R as each,
328
- Y as eachKeyed,
329
- T as focus,
330
- re as foldWidget,
331
- ue as inputWidget,
332
- D as map,
333
- O as mount,
334
- H as narrow,
335
- ie as numberInputWidget,
391
+ J as above,
392
+ G as beside,
393
+ re as bindAttr,
394
+ q as bindCheckbox,
395
+ de as bindClass,
396
+ S as bindInput,
397
+ T as bindSelect,
398
+ ie as bindShow,
399
+ ce as bindText,
400
+ pe as checkboxWidget,
401
+ Z as concat,
402
+ Q as dynamic,
403
+ D as each,
404
+ ne as eachKeyed,
405
+ P as focus,
406
+ se as foldWidget,
407
+ me as h,
408
+ le as inputWidget,
409
+ X as map,
410
+ ae as match,
411
+ R as mount,
412
+ z as narrow,
413
+ he as numberInputWidget,
336
414
  A as on,
337
- M as register,
338
- ae as selectWidget,
339
- G as show,
340
- Q as stack,
415
+ U as prop,
416
+ H as register,
417
+ ge as selectWidget,
418
+ Y as show,
419
+ be as slot,
420
+ ee as stack,
341
421
  w as subscribe,
342
- Z as subscribeNow,
343
- X as template,
344
- de as textareaWidget,
345
- oe as watchAll,
346
- K as withScope
422
+ oe as subscribeNow,
423
+ te as template,
424
+ fe as textareaWidget,
425
+ ue as watchAll,
426
+ V as withScope
347
427
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rhi-zone/rainbow-ui",
3
- "version": "0.2.0-alpha.2",
3
+ "version": "0.2.0-alpha.4",
4
4
  "description": "Type-safe DOM factories and algebraic widget combinators for rainbow",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",