ajo 0.1.21 → 0.1.22

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/html.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const{isArray:m,from:$}=Array,p="",{create:v,assign:g,entries:x,prototype:{hasOwnProperty:w},hasOwn:k=(e,t)=>w.call(e,t)}=Object,c=e=>$(d(e)).join(""),d=function*(e){for(e of u(e))if(typeof e=="string")yield f(e);else{const{nodeName:t,skip:o,children:r=""}=e;let n="";for(const[l,i]of x(e))N.has(l)||l.startsWith("set:")||i==null||i===!1||(n+=i===!0?` ${l}`:` ${l}="${f(String(i))}"`);S.has(t)?yield`<${t}${n}>`:o?yield`<${t}${n}></${t}>`:(yield`<${t}${n}>`,typeof r=="string"&&r.startsWith(p)?yield r.slice(1):yield*d(r),yield`</${t}>`)}},u=function*(e,t={value:""},o=!0){for(e of m(e)?e:[e])if(!(e==null||typeof e=="boolean"))if(k(e,"nodeName")){const{value:r}=t,{nodeName:n}=e;if(r&&(yield r,t.value=""),typeof n=="function")if(n.constructor.name==="GeneratorFunction"){const l={},i=g({},n.attrs);for(const a in e){const y=e[a];a.startsWith("attr:")?i[a.slice(5)]=y:l[a]=y}i.nodeName=n.is??"div",i.children=O(n,l),yield i}else yield*u(n(e),t,!1);else yield e}else m(e)?yield*u(e,t,!1):t.value+=e;o&&t.value&&(yield t.value)},S=new Set("area,base,br,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr".split(",")),N=new Set("nodeName,key,skip,memo,ref,children".split(",")),f=e=>e.replace(/[&<>"']/g,t=>`&#${t.charCodeAt(0)};`);let s=null;const O=(e,t)=>{let o,r;try{const n=e.call(o={$args:t,$context:v((s==null?void 0:s.$context)??null),render(){s!==o&&o.next()},next(){const l=s;s=o,r=c(n.next().value),s=l},throw(l){r=c(n.throw(l).value)},return(){n.return()}},t);o.next()}catch(n){o.throw(n)}finally{o.return()}return p+r},j=(e,t=Symbol())=>function(){const o=this??s;return o?arguments.length===0?t in o.$context?o.$context[t]:e:o.$context[t]=arguments[0]:e};exports.context=j;exports.html=d;exports.render=c;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=Symbol.for("ajo.args"),c=Symbol.for("ajo.context"),f="",$=new Set(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),p=new Set(["key","skip","memo","ref"]),S=new Set(["nodeName","children"].concat(Array.from(p))),m=e=>Array.from(y(e)).join(""),y=function*(e){for(e of N(e))if(typeof e=="string")yield u(e);else{let t="";for(const[n,o]of Object.entries(e))S.has(n)||n.startsWith("set:")||o==null||o===!1||(t+=o===!0?` ${n}`:` ${n}="${u(String(o))}"`);$.has(e.nodeName)?yield`<${e.nodeName}${t}>`:e.skip?yield`<${e.nodeName}${t}></${e.nodeName}>`:(yield`<${e.nodeName}${t}>`,typeof e.children=="string"&&e.children.startsWith(f)?yield e.children.slice(1):yield*y(e.children),yield`</${e.nodeName}>`)}},N=function*(e,t={h:""},n=!0){for(e of Array.isArray(e)?e.flat(1/0):[e]){const o=typeof e;if(!(e==null||o==="boolean"))if(o==="object"&&"nodeName"in e)if(t.h&&(yield t.h,t.h=""),typeof e.nodeName=="function")if(e.nodeName.constructor.name==="GeneratorFunction"){const r=Object.assign({},e.nodeName.attrs),l=Object.assign({},e.nodeName.args);for(const a in e){const d=e[a];a.startsWith("attr:")?r[a.slice(5)]=d:p.has(a)||a.startsWith("set:")?r[a]=d:l[a]=d}r.nodeName=e.nodeName.is??"div",r.children=b(e.nodeName,l),yield r}else yield*N(e.nodeName(e),t,!1);else yield e;else t.h+=e}n&&t.h&&(yield t.h)},u=e=>e.replace(/[&<>"']/g,t=>`&#${t.charCodeAt(0)};`),s=()=>{};let i=null;const b=(e,t)=>{let n,o;try{const r=e.call(n={*[Symbol.iterator](){for(;;)yield t},[g]:t,[c]:Object.create((i==null?void 0:i[c])??null),render:s,queueMicrotask:s,requestAnimationFrame:s,effect:s,cleanup:s,next(){if(i===n)return;const l=i;i=n,o=m(r.next().value),i=l},throw(l){o=m(r.throw(l).value)},return(){r.return()}},t);n.next()}catch(r){n.throw(r)}finally{n.return()}return f+o},j=(e,t=Symbol())=>function(...n){const o=this??i;return o?n.length==0?t in o[c]?o[c][t]:e:o[c][t]=n[0]:e};exports.context=j;exports.html=y;exports.render=m;
package/dist/html.js CHANGED
@@ -1,65 +1,72 @@
1
- const { isArray: d, from: $ } = Array, m = "", { create: v, assign: x, entries: g, prototype: { hasOwnProperty: w }, hasOwn: k = (e, t) => w.call(e, t) } = Object, y = (e) => $(p(e)).join(""), p = function* (e) {
2
- for (e of c(e))
3
- if (typeof e == "string") yield f(e);
1
+ const $ = Symbol.for("ajo.args"), c = Symbol.for("ajo.context"), f = "", g = /* @__PURE__ */ new Set(["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"]), u = /* @__PURE__ */ new Set(["key", "skip", "memo", "ref"]), S = new Set(["nodeName", "children"].concat(Array.from(u))), m = (e) => Array.from(p(e)).join(""), p = function* (e) {
2
+ for (e of N(e))
3
+ if (typeof e == "string") yield y(e);
4
4
  else {
5
- const { nodeName: t, skip: o, children: l = "" } = e;
6
- let n = "";
7
- for (const [r, i] of g(e))
8
- S.has(r) || r.startsWith("set:") || i == null || i === !1 || (n += i === !0 ? ` ${r}` : ` ${r}="${f(String(i))}"`);
9
- N.has(t) ? yield `<${t}${n}>` : o ? yield `<${t}${n}></${t}>` : (yield `<${t}${n}>`, typeof l == "string" && l.startsWith(m) ? yield l.slice(1) : yield* p(l), yield `</${t}>`);
5
+ let t = "";
6
+ for (const [n, o] of Object.entries(e))
7
+ S.has(n) || n.startsWith("set:") || o == null || o === !1 || (t += o === !0 ? ` ${n}` : ` ${n}="${y(String(o))}"`);
8
+ g.has(e.nodeName) ? yield `<${e.nodeName}${t}>` : e.skip ? yield `<${e.nodeName}${t}></${e.nodeName}>` : (yield `<${e.nodeName}${t}>`, typeof e.children == "string" && e.children.startsWith(f) ? yield e.children.slice(1) : yield* p(e.children), yield `</${e.nodeName}>`);
10
9
  }
11
- }, c = function* (e, t = { value: "" }, o = !0) {
12
- for (e of d(e) ? e : [e])
13
- if (!(e == null || typeof e == "boolean"))
14
- if (k(e, "nodeName")) {
15
- const { value: l } = t, { nodeName: n } = e;
16
- if (l && (yield l, t.value = ""), typeof n == "function")
17
- if (n.constructor.name === "GeneratorFunction") {
18
- const r = {}, i = x({}, n.attrs);
10
+ }, N = function* (e, t = { h: "" }, n = !0) {
11
+ for (e of Array.isArray(e) ? e.flat(1 / 0) : [e]) {
12
+ const o = typeof e;
13
+ if (!(e == null || o === "boolean"))
14
+ if (o === "object" && "nodeName" in e)
15
+ if (t.h && (yield t.h, t.h = ""), typeof e.nodeName == "function")
16
+ if (e.nodeName.constructor.name === "GeneratorFunction") {
17
+ const r = Object.assign({}, e.nodeName.attrs), l = Object.assign({}, e.nodeName.args);
19
18
  for (const a in e) {
20
- const u = e[a];
21
- a.startsWith("attr:") ? i[a.slice(5)] = u : r[a] = u;
19
+ const d = e[a];
20
+ a.startsWith("attr:") ? r[a.slice(5)] = d : u.has(a) || a.startsWith("set:") ? r[a] = d : l[a] = d;
22
21
  }
23
- i.nodeName = n.is ?? "div", i.children = A(n, r), yield i;
24
- } else yield* c(n(e), t, !1);
22
+ r.nodeName = e.nodeName.is ?? "div", r.children = j(e.nodeName, l), yield r;
23
+ } else yield* N(e.nodeName(e), t, !1);
25
24
  else yield e;
26
- } else d(e) ? yield* c(e, t, !1) : t.value += e;
27
- o && t.value && (yield t.value);
28
- }, N = new Set("area,base,br,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr".split(",")), S = new Set("nodeName,key,skip,memo,ref,children".split(",")), f = (e) => e.replace(/[&<>"']/g, (t) => `&#${t.charCodeAt(0)};`);
29
- let s = null;
30
- const A = (e, t) => {
31
- let o, l;
25
+ else t.h += e;
26
+ }
27
+ n && t.h && (yield t.h);
28
+ }, y = (e) => e.replace(/[&<>"']/g, (t) => `&#${t.charCodeAt(0)};`), s = () => {
29
+ };
30
+ let i = null;
31
+ const j = (e, t) => {
32
+ let n, o;
32
33
  try {
33
- const n = e.call(o = {
34
- $args: t,
35
- $context: v((s == null ? void 0 : s.$context) ?? null),
36
- render() {
37
- s !== o && o.next();
34
+ const r = e.call(n = {
35
+ *[Symbol.iterator]() {
36
+ for (; ; ) yield t;
38
37
  },
38
+ [$]: t,
39
+ [c]: Object.create((i == null ? void 0 : i[c]) ?? null),
40
+ render: s,
41
+ queueMicrotask: s,
42
+ requestAnimationFrame: s,
43
+ effect: s,
44
+ cleanup: s,
39
45
  next() {
40
- const r = s;
41
- s = o, l = y(n.next().value), s = r;
46
+ if (i === n) return;
47
+ const l = i;
48
+ i = n, o = m(r.next().value), i = l;
42
49
  },
43
- throw(r) {
44
- l = y(n.throw(r).value);
50
+ throw(l) {
51
+ o = m(r.throw(l).value);
45
52
  },
46
53
  return() {
47
- n.return();
54
+ r.return();
48
55
  }
49
56
  }, t);
50
- o.next();
51
- } catch (n) {
52
- o.throw(n);
57
+ n.next();
58
+ } catch (r) {
59
+ n.throw(r);
53
60
  } finally {
54
- o.return();
61
+ n.return();
55
62
  }
56
- return m + l;
57
- }, O = (e, t = Symbol()) => function() {
58
- const o = this ?? s;
59
- return o ? arguments.length === 0 ? t in o.$context ? o.$context[t] : e : o.$context[t] = arguments[0] : e;
63
+ return f + o;
64
+ }, w = (e, t = Symbol()) => function(...n) {
65
+ const o = this ?? i;
66
+ return o ? n.length == 0 ? t in o[c] ? o[c][t] : e : o[c][t] = n[0] : e;
60
67
  };
61
68
  export {
62
- O as context,
69
+ w as context,
63
70
  p as html,
64
- y as render
71
+ m as render
65
72
  };
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=({children:t})=>t,N=function(t,n){return(n??(n=$(null))).nodeName=t,"children"in n||arguments.length<3||(n.children=arguments.length===3?arguments[2]:k.call(arguments,2)),n},d=(t,n)=>{let e=n.firstChild;for(t of h(t)){let o=e;if(typeof t=="string"){for(;o&&o.nodeType!=3;)o=o.nextSibling;o?o.data!=t&&(o.data=t):o=document.createTextNode(t)}else{const{nodeName:i,key:a,skip:c,memo:s,ref:f,children:w}=t;for(;o&&!(o.localName===i&&(o.$key??(o.$key=a))==a);)o=o.nextSibling;if(o??(o=m(document.createElementNS(t.xmlns??i==="svg"?O:n.namespaceURI,i),{$key:a})),s==null||F(o.$memo,o.$memo=s)){const{$props:y}=o,x={};for(const l of p(m({},y,t))){if(T.has(l))continue;const u=x[l]=t[l];u!==(y==null?void 0:y[l])&&(l.startsWith("set:")?o[l.slice(4)]=u:u==null||u===!1?o.removeAttribute(l):o.setAttribute(l,u===!0?"":u))}o.$props=x,c||d(w,o),typeof f=="function"&&(o.$ref=f)(o)}}o===e?e=e.nextSibling:C(n,o,e)}for(;e;){const o=e.nextSibling;e.nodeType===1&&v(e),n.removeChild(e),e=o}},{isArray:g,prototype:{slice:k}}=Array,{create:$,assign:m,keys:p,prototype:{hasOwnProperty:b},hasOwn:A=(t,n)=>b.call(t,n)}=Object,O="http://www.w3.org/2000/svg",T=new Set("nodeName,key,skip,memo,ref,children".split(",")),F=(t,n)=>g(t)&&g(n)?t.some((e,o)=>e!==n[o]):t!==n,h=function*(t,n={value:""},e=!0){for(t of g(t)?t:[t])if(!(t==null||typeof t=="boolean"))if(A(t,"nodeName")){const{value:o}=n,{nodeName:i}=t;if(o&&(yield o,n.value=""),typeof i=="function")if(i.constructor.name==="GeneratorFunction"){const a={},c=m({},i.attrs);for(const s of p(t)){const f=t[s];s.startsWith("attr:")?c[s.slice(5)]=f:s==="key"||s==="memo"?c[s]=f:a[s]=f}c.nodeName=i.is??"div",c.skip=!0,c.ref=j.bind(null,i,a),yield c}else yield*h(i(t),n,!1);else yield t}else g(t)?yield*h(t,n,!1):n.value+=t;e&&n.value&&(yield n.value)},j=(t,n,e)=>{if(!e)return;e.$generator??(e.$generator=(m(e,E),e.$context??(e.$context=$((r==null?void 0:r.$context)??null)),t));const{skip:o,ref:i,...a}=n;e.$ref=B.bind(null,i,e),m(e.$args??(e.$args={}),a),o||e.next()},B=(t,n,e)=>{typeof t=="function"&&t(e),e||n.return()},C=(t,n,e)=>{if(n.contains(document.activeElement)){const o=n.nextSibling;for(;e&&e!=n;){const i=e.nextSibling;t.insertBefore(e,o),e=i}}else t.insertBefore(n,e)},v=t=>{for(const e of t.children)v(e);const{$ref:n}=t;typeof n=="function"&&n(null)};let r=null;const E={render(){r!=null&&r.contains(this)||this.next()},next(){const t=r;r=this;try{d((this.$iterator??(this.$iterator=this.$generator.call(this,this.$args))).next().value,this),typeof this.$ref=="function"&&this.$ref(this)}catch(n){this.throw(n)}finally{r=t}},throw(t){var n;for(let e=this;e;e=e.parentNode)if(typeof((n=e.$iterator)==null?void 0:n.throw)=="function")try{return d(e.$iterator.throw(t).value,e)}catch{}throw t},return(){var t;try{(t=this.$iterator)==null||t.return()}catch(n){this.throw(n)}finally{this.$iterator=null}}},P=(t,n=Symbol())=>function(){const e=this??r;return e?arguments.length===0?n in e.$context?e.$context[n]:t:e.$context[n]=arguments[0]:t};exports.Fragment=S;exports.context=P;exports.h=N;exports.render=d;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=Symbol.for("ajo.key"),k=Symbol.for("ajo.memo"),p=Symbol.for("ajo.ref"),v=Symbol.for("ajo.cache"),T=new Set(["nodeName","children","key","skip","memo","ref"]),W=t=>t.children,B=(t,n,...e)=>((n??(n={})).nodeName=t,!("children"in n)&&e.length&&(n.children=e.length==1?e[0]:e),n),S=(t,n,e=n.firstChild,i)=>{for(t of O(t)){let o=e;if(typeof t=="string"){for(;o&&o.nodeType!=3;)o=o.nextSibling;o?o.data!=t&&(o.data=t):o=document.createTextNode(t)}else if(t instanceof Node)o=t;else{for(;o&&!(o.localName==t.nodeName&&(o[b]??(o[b]=t.key))==t.key);)o=o.nextSibling;if(o??(o=Object.assign(document.createElementNS(t.xmlns??n.namespaceURI,t.nodeName),{[b]:t.key})),t.memo==null||R(o[k],o[k]=t.memo)){let s,m={},w=o[v]??Array.from(o.attributes).reduce((r,N)=>(r[N.name]=N.value,r),{});for(const r of Object.keys(Object.assign({},w,t)))T.has(r)||w[r]===(s=m[r]=t[r])||(r.startsWith("set:")?o[r.slice(4)]=s:s==null||s===!1?o.removeAttribute(r):o.setAttribute(r,s===!0?"":s));o[v]=m,t.skip||S(t.children,o),typeof t.ref=="function"&&(o[p]=t.ref)(o)}}o===e?e=e.nextSibling:I(n,o,e)}for(;e&&e!=i;){const o=e.nextSibling;e.nodeType==1&&C(e),n.removeChild(e),e=o}},R=(t,n)=>Array.isArray(t)&&Array.isArray(n)?t.some((e,i)=>e!==n[i]):t!==n,O=function*(t,n={h:""},e=!0){for(t of Array.isArray(t)?t.flat(1/0):[t])if(!(t==null||typeof t=="boolean"))if(typeof t=="object"&&"nodeName"in t)if(n.h&&(yield n.h,n.h=""),typeof t.nodeName=="function")if(t.nodeName.constructor.name=="GeneratorFunction"){const i=Object.assign({},t.nodeName.attrs),o=Object.assign({},t.nodeName.args);for(const s in t){const m=t[s];s.startsWith("attr:")?i[s.slice(5)]=m:s=="key"||s=="memo"||s.startsWith("set:")?i[s]=m:o[s]=m}i.nodeName=t.nodeName.is??"div",i.skip=!0,i.ref=P.bind(null,t.nodeName,o),yield i}else yield*O(t.nodeName(t),n,!1);else yield t;else n.h+=t;e&&n.h&&(yield n.h)},I=(t,n,e)=>{if(n.contains(document.activeElement)){const i=n.nextSibling;for(;e&&e!=n;){const o=e.nextSibling;t.insertBefore(e,i),e=o}}else t.insertBefore(n,e)},C=t=>{var n;for(const e of t.children)C(e);(n=t[p])==null||n.call(t,null)},g=Symbol.for("ajo.generator"),f=Symbol.for("ajo.iterator"),l=Symbol.for("ajo.args"),d=Symbol.for("ajo.context"),y=Symbol.for("ajo.effects"),c=Symbol.for("ajo.disposers"),h=Symbol.for("ajo.cleanups"),P=(t,n,e)=>{if(!e)return;e[g]??(e[g]=(Object.assign(e,G),e[d]=Object.create((a==null?void 0:a[d])??null),t));const{skip:i,ref:o,...s}=n;e[p]=U.bind(null,o,e),Object.assign(e[l]??(e[l]={}),s),i||e.next()},U=(t,n,e)=>{typeof t=="function"&&t(e),e||n.return()},M=t=>t.isConnected&&t.render(),u=(t,n=y)=>{var e;if(n==y)for(const i of t.children)u(i,n);if((e=t[n])!=null&&e.size)for(const i of t[n]){t[n].delete(i);try{const o=i();n==y&&typeof o=="function"&&(t[c]??(t[c]=new Set)).add(o)}catch(o){t.throw(o)}}},x=(t,n)=>{for(const e of t.set)n(e);t.set.clear(),t.queued=!1},z=()=>queueMicrotask.bind(null,x.bind(null,z,M)),E=()=>requestAnimationFrame.bind(null,x.bind(null,E,M)),F=()=>{const t=new MessageChannel;return t.port1.onmessage=x.bind(null,F,u),t.port2.postMessage.bind(t.port2,null)},j=(t,n)=>{t.queued||((t.run??(t.run=t()))(),t.queued=!0);const e=t.set??(t.set=new Set);for(const i of e){if(i.contains(n))return;n.contains(i)&&e.delete(i)}e.add(n)},A=(t,n,e)=>{if(typeof e=="function")return(t[n]??(t[n]=new Set)).add(e),()=>t[n].delete(e)};let a=null;const G={*[Symbol.iterator](){for(;;)yield this[l]},render(){a!=null&&a.contains(this)||this.next()},queueMicrotask(){j(z,this)},requestAnimationFrame(){j(E,this)},effect(t){return A(this,y,t)},cleanup(t){return A(this,h,t)},next(){var n,e,i;const t=a;a=this;try{(n=this[c])!=null&&n.size&&u(this,c);const o=(this[f]??(this[f]=this[g].call(this,this[l]))).next();(e=this[y])!=null&&e.size&&j(F,this),S(o.value,this),(i=this[p])==null||i.call(this,this),o.done&&this.return()}catch(o){this.throw(o)}finally{a=t}},throw(t){var n;for(let e=this;e;e=e.parentNode)if(typeof((n=e[f])==null?void 0:n.throw)=="function")try{return S(e[f].throw(t).value,e)}catch(i){t=new Error(i instanceof Error?i.message:i,{cause:t})}throw t},return(){var t,n,e;try{(t=this[c])!=null&&t.size&&u(this,c),(n=this[h])!=null&&n.size&&u(this,h),(e=this[f])==null||e.return()}catch(i){this.throw(i)}finally{this[f]=null}}},H=(t,n=Symbol())=>function(...e){const i=this??a;return i?e.length==0?n in i[d]?i[d][n]:t:i[d][n]=e[0]:t};exports.Fragment=W;exports.context=H;exports.h=B;exports.render=S;
package/dist/index.js CHANGED
@@ -1,109 +1,151 @@
1
- const F = ({ children: t }) => t, W = function(t, n) {
2
- return (n ?? (n = h(null))).nodeName = t, "children" in n || arguments.length < 3 || (n.children = arguments.length === 3 ? arguments[2] : N.call(arguments, 2)), n;
3
- }, g = (t, n) => {
4
- let e = n.firstChild;
5
- for (t of x(t)) {
6
- let i = e;
1
+ const b = Symbol.for("ajo.key"), k = Symbol.for("ajo.memo"), S = Symbol.for("ajo.ref"), A = Symbol.for("ajo.cache"), T = /* @__PURE__ */ new Set(["nodeName", "children", "key", "skip", "memo", "ref"]), G = (t) => t.children, H = (t, e, ...n) => ((e ?? (e = {})).nodeName = t, !("children" in e) && n.length && (e.children = n.length == 1 ? n[0] : n), e), x = (t, e, n = e.firstChild, i) => {
2
+ for (t of O(t)) {
3
+ let o = n;
7
4
  if (typeof t == "string") {
8
- for (; i && i.nodeType != 3; ) i = i.nextSibling;
9
- i ? i.data != t && (i.data = t) : i = document.createTextNode(t);
10
- } else {
11
- const { nodeName: o, key: a, skip: c, memo: s, ref: f, children: w } = t;
12
- for (; i && !(i.localName === o && (i.$key ?? (i.$key = a)) == a); ) i = i.nextSibling;
13
- if (i ?? (i = m(document.createElementNS(t.xmlns ?? o === "svg" ? b : n.namespaceURI, o), { $key: a })), s == null || O(i.$memo, i.$memo = s)) {
14
- const { $props: y } = i, $ = {};
15
- for (const l of p(m({}, y, t))) {
16
- if (A.has(l)) continue;
17
- const u = $[l] = t[l];
18
- u !== (y == null ? void 0 : y[l]) && (l.startsWith("set:") ? i[l.slice(4)] = u : u == null || u === !1 ? i.removeAttribute(l) : i.setAttribute(l, u === !0 ? "" : u));
19
- }
20
- i.$props = $, c || g(w, i), typeof f == "function" && (i.$ref = f)(i);
5
+ for (; o && o.nodeType != 3; ) o = o.nextSibling;
6
+ o ? o.data != t && (o.data = t) : o = document.createTextNode(t);
7
+ } else if (t instanceof Node)
8
+ o = t;
9
+ else {
10
+ for (; o && !(o.localName == t.nodeName && (o[b] ?? (o[b] = t.key)) == t.key); ) o = o.nextSibling;
11
+ if (o ?? (o = Object.assign(document.createElementNS(t.xmlns ?? e.namespaceURI, t.nodeName), { [b]: t.key })), t.memo == null || W(o[k], o[k] = t.memo)) {
12
+ let s, m = {}, w = o[A] ?? Array.from(o.attributes).reduce((r, N) => (r[N.name] = N.value, r), {});
13
+ for (const r of Object.keys(Object.assign({}, w, t)))
14
+ T.has(r) || w[r] === (s = m[r] = t[r]) || (r.startsWith("set:") ? o[r.slice(4)] = s : s == null || s === !1 ? o.removeAttribute(r) : o.setAttribute(r, s === !0 ? "" : s));
15
+ o[A] = m, t.skip || x(t.children, o), typeof t.ref == "function" && (o[S] = t.ref)(o);
21
16
  }
22
17
  }
23
- i === e ? e = e.nextSibling : C(n, i, e);
18
+ o === n ? n = n.nextSibling : B(e, o, n);
24
19
  }
25
- for (; e; ) {
26
- const i = e.nextSibling;
27
- e.nodeType === 1 && v(e), n.removeChild(e), e = i;
20
+ for (; n && n != i; ) {
21
+ const o = n.nextSibling;
22
+ n.nodeType == 1 && C(n), e.removeChild(n), n = o;
28
23
  }
29
- }, { isArray: d, prototype: { slice: N } } = Array, { create: h, assign: m, keys: p, prototype: { hasOwnProperty: S }, hasOwn: k = (t, n) => S.call(t, n) } = Object, b = "http://www.w3.org/2000/svg", A = new Set("nodeName,key,skip,memo,ref,children".split(",")), O = (t, n) => d(t) && d(n) ? t.some((e, i) => e !== n[i]) : t !== n, x = function* (t, n = { value: "" }, e = !0) {
30
- for (t of d(t) ? t : [t])
24
+ }, W = (t, e) => Array.isArray(t) && Array.isArray(e) ? t.some((n, i) => n !== e[i]) : t !== e, O = function* (t, e = { h: "" }, n = !0) {
25
+ for (t of Array.isArray(t) ? t.flat(1 / 0) : [t])
31
26
  if (!(t == null || typeof t == "boolean"))
32
- if (k(t, "nodeName")) {
33
- const { value: i } = n, { nodeName: o } = t;
34
- if (i && (yield i, n.value = ""), typeof o == "function")
35
- if (o.constructor.name === "GeneratorFunction") {
36
- const a = {}, c = m({}, o.attrs);
37
- for (const s of p(t)) {
38
- const f = t[s];
39
- s.startsWith("attr:") ? c[s.slice(5)] = f : s === "key" || s === "memo" ? c[s] = f : a[s] = f;
27
+ if (typeof t == "object" && "nodeName" in t)
28
+ if (e.h && (yield e.h, e.h = ""), typeof t.nodeName == "function")
29
+ if (t.nodeName.constructor.name == "GeneratorFunction") {
30
+ const i = Object.assign({}, t.nodeName.attrs), o = Object.assign({}, t.nodeName.args);
31
+ for (const s in t) {
32
+ const m = t[s];
33
+ s.startsWith("attr:") ? i[s.slice(5)] = m : s == "key" || s == "memo" || s.startsWith("set:") ? i[s] = m : o[s] = m;
40
34
  }
41
- c.nodeName = o.is ?? "div", c.skip = !0, c.ref = T.bind(null, o, a), yield c;
42
- } else yield* x(o(t), n, !1);
35
+ i.nodeName = t.nodeName.is ?? "div", i.skip = !0, i.ref = R.bind(null, t.nodeName, o), yield i;
36
+ } else yield* O(t.nodeName(t), e, !1);
43
37
  else yield t;
44
- } else d(t) ? yield* x(t, n, !1) : n.value += t;
45
- e && n.value && (yield n.value);
46
- }, T = (t, n, e) => {
47
- if (!e) return;
48
- e.$generator ?? (e.$generator = (m(e, E), e.$context ?? (e.$context = h((r == null ? void 0 : r.$context) ?? null)), t));
49
- const { skip: i, ref: o, ...a } = n;
50
- e.$ref = B.bind(null, o, e), m(e.$args ?? (e.$args = {}), a), i || e.next();
51
- }, B = (t, n, e) => {
52
- typeof t == "function" && t(e), e || n.return();
53
- }, C = (t, n, e) => {
54
- if (n.contains(document.activeElement)) {
55
- const i = n.nextSibling;
56
- for (; e && e != n; ) {
57
- const o = e.nextSibling;
58
- t.insertBefore(e, i), e = o;
38
+ else e.h += t;
39
+ n && e.h && (yield e.h);
40
+ }, B = (t, e, n) => {
41
+ if (e.contains(document.activeElement)) {
42
+ const i = e.nextSibling;
43
+ for (; n && n != e; ) {
44
+ const o = n.nextSibling;
45
+ t.insertBefore(n, i), n = o;
46
+ }
47
+ } else t.insertBefore(e, n);
48
+ }, C = (t) => {
49
+ var e;
50
+ for (const n of t.children) C(n);
51
+ (e = t[S]) == null || e.call(t, null);
52
+ }, g = Symbol.for("ajo.generator"), f = Symbol.for("ajo.iterator"), l = Symbol.for("ajo.args"), d = Symbol.for("ajo.context"), y = Symbol.for("ajo.effects"), c = Symbol.for("ajo.disposers"), p = Symbol.for("ajo.cleanups"), R = (t, e, n) => {
53
+ if (!n) return;
54
+ n[g] ?? (n[g] = (Object.assign(n, U), n[d] = Object.create((a == null ? void 0 : a[d]) ?? null), t));
55
+ const { skip: i, ref: o, ...s } = e;
56
+ n[S] = I.bind(null, o, n), Object.assign(n[l] ?? (n[l] = {}), s), i || n.next();
57
+ }, I = (t, e, n) => {
58
+ typeof t == "function" && t(n), n || e.return();
59
+ }, z = (t) => t.isConnected && t.render(), u = (t, e = y) => {
60
+ var n;
61
+ if (e == y) for (const i of t.children) u(i, e);
62
+ if ((n = t[e]) != null && n.size) for (const i of t[e]) {
63
+ t[e].delete(i);
64
+ try {
65
+ const o = i();
66
+ e == y && typeof o == "function" && (t[c] ?? (t[c] = /* @__PURE__ */ new Set())).add(o);
67
+ } catch (o) {
68
+ t.throw(o);
59
69
  }
60
- } else t.insertBefore(n, e);
61
- }, v = (t) => {
62
- for (const e of t.children) v(e);
63
- const { $ref: n } = t;
64
- typeof n == "function" && n(null);
70
+ }
71
+ }, j = (t, e) => {
72
+ for (const n of t.set) e(n);
73
+ t.set.clear(), t.queued = !1;
74
+ }, E = () => queueMicrotask.bind(null, j.bind(null, E, z)), M = () => requestAnimationFrame.bind(null, j.bind(null, M, z)), F = () => {
75
+ const t = new MessageChannel();
76
+ return t.port1.onmessage = j.bind(null, F, u), t.port2.postMessage.bind(t.port2, null);
77
+ }, h = (t, e) => {
78
+ t.queued || ((t.run ?? (t.run = t()))(), t.queued = !0);
79
+ const n = t.set ?? (t.set = /* @__PURE__ */ new Set());
80
+ for (const i of n) {
81
+ if (i.contains(e)) return;
82
+ e.contains(i) && n.delete(i);
83
+ }
84
+ n.add(e);
85
+ }, v = (t, e, n) => {
86
+ if (typeof n == "function")
87
+ return (t[e] ?? (t[e] = /* @__PURE__ */ new Set())).add(n), () => t[e].delete(n);
65
88
  };
66
- let r = null;
67
- const E = {
89
+ let a = null;
90
+ const U = {
91
+ *[Symbol.iterator]() {
92
+ for (; ; ) yield this[l];
93
+ },
68
94
  render() {
69
- r != null && r.contains(this) || this.next();
95
+ a != null && a.contains(this) || this.next();
96
+ },
97
+ queueMicrotask() {
98
+ h(E, this);
99
+ },
100
+ requestAnimationFrame() {
101
+ h(M, this);
102
+ },
103
+ effect(t) {
104
+ return v(this, y, t);
105
+ },
106
+ cleanup(t) {
107
+ return v(this, p, t);
70
108
  },
71
109
  next() {
72
- const t = r;
73
- r = this;
110
+ var e, n, i;
111
+ const t = a;
112
+ a = this;
74
113
  try {
75
- g((this.$iterator ?? (this.$iterator = this.$generator.call(this, this.$args))).next().value, this), typeof this.$ref == "function" && this.$ref(this);
76
- } catch (n) {
77
- this.throw(n);
114
+ (e = this[c]) != null && e.size && u(this, c);
115
+ const o = (this[f] ?? (this[f] = this[g].call(this, this[l]))).next();
116
+ (n = this[y]) != null && n.size && h(F, this), x(o.value, this), (i = this[S]) == null || i.call(this, this), o.done && this.return();
117
+ } catch (o) {
118
+ this.throw(o);
78
119
  } finally {
79
- r = t;
120
+ a = t;
80
121
  }
81
122
  },
82
123
  throw(t) {
83
- var n;
84
- for (let e = this; e; e = e.parentNode) if (typeof ((n = e.$iterator) == null ? void 0 : n.throw) == "function") try {
85
- return g(e.$iterator.throw(t).value, e);
86
- } catch {
124
+ var e;
125
+ for (let n = this; n; n = n.parentNode) if (typeof ((e = n[f]) == null ? void 0 : e.throw) == "function") try {
126
+ return x(n[f].throw(t).value, n);
127
+ } catch (i) {
128
+ t = new Error(i instanceof Error ? i.message : i, { cause: t });
87
129
  }
88
130
  throw t;
89
131
  },
90
132
  return() {
91
- var t;
133
+ var t, e, n;
92
134
  try {
93
- (t = this.$iterator) == null || t.return();
94
- } catch (n) {
95
- this.throw(n);
135
+ (t = this[c]) != null && t.size && u(this, c), (e = this[p]) != null && e.size && u(this, p), (n = this[f]) == null || n.return();
136
+ } catch (i) {
137
+ this.throw(i);
96
138
  } finally {
97
- this.$iterator = null;
139
+ this[f] = null;
98
140
  }
99
141
  }
100
- }, j = (t, n = Symbol()) => function() {
101
- const e = this ?? r;
102
- return e ? arguments.length === 0 ? n in e.$context ? e.$context[n] : t : e.$context[n] = arguments[0] : t;
142
+ }, J = (t, e = Symbol()) => function(...n) {
143
+ const i = this ?? a;
144
+ return i ? n.length == 0 ? e in i[d] ? i[d][e] : t : i[d][e] = n[0] : t;
103
145
  };
104
146
  export {
105
- F as Fragment,
106
- j as context,
107
- W as h,
108
- g as render
147
+ G as Fragment,
148
+ J as context,
149
+ H as h,
150
+ x as render
109
151
  };
package/license CHANGED
@@ -1,6 +1,6 @@
1
1
  ISC License
2
2
 
3
- Copyright (c) 2024, Cristian Falcone
3
+ Copyright (c) 2022-2025, Cristian Falcone
4
4
 
5
5
  Permission to use, copy, modify, and/or distribute this software for any
6
6
  purpose with or without fee is hereby granted, provided that the above
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ajo",
3
- "version": "0.1.21",
3
+ "version": "0.1.22",
4
4
  "description": "ajo is a JavaScript view library for building user interfaces",
5
5
  "type": "module",
6
6
  "module": "./dist/index.js",
@@ -8,14 +8,14 @@
8
8
  "types": "./types.ts",
9
9
  "exports": {
10
10
  ".": {
11
+ "types": "./types.ts",
11
12
  "import": "./dist/index.js",
12
- "require": "./dist/index.cjs",
13
- "types": "./types.ts"
13
+ "require": "./dist/index.cjs"
14
14
  },
15
15
  "./html": {
16
+ "types": "./types.ts",
16
17
  "import": "./dist/html.js",
17
- "require": "./dist/html.cjs",
18
- "types": "./types.ts"
18
+ "require": "./dist/html.cjs"
19
19
  }
20
20
  },
21
21
  "files": [
@@ -23,10 +23,11 @@
23
23
  "types.ts"
24
24
  ],
25
25
  "devDependencies": {
26
- "@types/node": "^22.2.0",
27
- "jsdom": "24.1.1",
28
- "vite": "5.4.0",
29
- "vitest": "2.0.5"
26
+ "@types/node": "22.15.29",
27
+ "happy-dom": "17.6.1",
28
+ "vite": "6.3.5",
29
+ "vite-tsconfig-paths": "5.1.4",
30
+ "vitest": "3.2.0"
30
31
  },
31
32
  "keywords": [
32
33
  "ui",
package/readme.md CHANGED
@@ -40,6 +40,7 @@ import { h, render } from 'ajo'
40
40
  const Greeting = ({ name }) => <h1>Hello, {name}!</h1>
41
41
 
42
42
  function* Counter() {
43
+
43
44
  let count = 0
44
45
 
45
46
  const increment = () => {
@@ -47,25 +48,21 @@ function* Counter() {
47
48
  this.render()
48
49
  }
49
50
 
50
- while (true) {
51
- yield (
52
- <>
53
- <p>Count: {count}</p>
54
- <button set:onclick={increment}>Increment</button>
55
- </>
56
- )
57
- }
51
+ while (true) yield (
52
+ <>
53
+ <p>Count: {count}</p>
54
+ <button set:onclick={increment}>Increment</button>
55
+ </>
56
+ )
58
57
  }
59
58
 
60
59
  function* App() {
61
- while (true) {
62
- yield (
63
- <>
64
- <Greeting name="Ajo Developer" />
65
- <Counter />
66
- </>
67
- )
68
- }
60
+ while (true) yield (
61
+ <>
62
+ <Greeting name="Ajo Developer" />
63
+ <Counter />
64
+ </>
65
+ )
69
66
  }
70
67
 
71
68
  render(<App />, document.body)
@@ -124,57 +121,64 @@ Stateful components use generator functions:
124
121
 
125
122
  ```jsx
126
123
  function* Counter() {
124
+
127
125
  let count = 0
128
- while (true) {
129
- yield (
130
- <button set:onclick={() => { count++; this.render(); }}>
131
- {count}
132
- </button>
133
- )
134
- }
126
+
127
+ while (true) yield (
128
+ <button set:onclick={() => { count++; this.render(); }}>
129
+ {count}
130
+ </button>
131
+ )
135
132
  }
136
133
  ```
137
134
 
138
135
  State handling in Ajo is straightforward:
139
136
  - State is managed using regular variables within the generator function.
140
137
  - The `this.render()` method triggers a re-render when state changes.
138
+ - The `this.cleanup()` method is used to clean up resources when the component unmounts.
141
139
  - Each iteration of the generator function represents a new render cycle.
142
140
 
143
141
  ```jsx
144
142
  function* Timer() {
143
+
145
144
  let seconds = 0
145
+
146
146
  const intervalId = setInterval(() => {
147
147
  seconds++
148
148
  this.render() // Trigger a re-render
149
149
  }, 1000)
150
150
 
151
- try {
152
- while (true) {
153
- yield <div>Seconds: {seconds}</div>
154
- }
155
- } finally {
156
- clearInterval(intervalId) // Cleanup
157
- }
151
+ this.cleanup(() => clearInterval(intervalId)) // Cleanup
152
+
153
+ while (true) yield <div>Seconds: {seconds}</div>
158
154
  }
159
155
  ```
160
156
 
161
157
  ### Component Lifecycle
162
158
 
163
- Stateful components have a simple lifecycle:
164
- - Initialization: When the generator is first called
165
- - Rendering: Each time the generator yields
166
- - Cleanup: When the generator's `finally` block is executed
159
+ Stateful components have a simple lifecycle pattern:
160
+ - After mount: Component's element is mounted and the generator function is called. You can initialize resources here.
161
+ - Before render: Before component's children render
162
+ - After render: After component's children render
163
+ - Before re-render: Before component's children re-render
164
+ - Before unmount: Component's element is about to be unmounted. You can clean up resources here.
167
165
 
168
166
  ```jsx
169
167
  function* LifecycleDemo() {
170
- console.log('Initialized')
171
- try {
172
- while (true) {
173
- console.log('Rendering')
174
- yield <div>Hello, Ajo!</div>
175
- }
176
- } finally {
177
- console.log('Cleanup')
168
+
169
+ console.log('After mount')
170
+
171
+ this.cleanup(() => console.log('Before unmount'))
172
+
173
+ while (true) {
174
+
175
+ console.log('Before render')
176
+
177
+ this.effect(() => console.log('After render'))
178
+
179
+ yield <div>Hello, Ajo!</div>
180
+
181
+ console.log('Before re-render')
178
182
  }
179
183
  }
180
184
  ```
@@ -195,21 +199,30 @@ CustomButton.is = 'button'
195
199
  </CustomButton>
196
200
  ```
197
201
 
198
- ### Component.attrs and Component.is
202
+ ### Component.attrs, Component.args and Component.is
199
203
 
200
204
  Use `Component.attrs` to set default attributes for a component:
201
205
 
202
206
  ```jsx
203
- function* CustomButton(props) {
207
+ function* CustomButton(args) {
204
208
  while (true) yield <>{props.children}</>
205
209
  }
206
210
  CustomButton.attrs = { class: 'btn btn-primary' }
207
211
  ```
208
212
 
213
+ Use `Component.args` to set default arguments for a component:
214
+
215
+ ```jsx
216
+ function* Greeting(args) {
217
+ while (true) yield <>Hello, {props.name}!</>
218
+ }
219
+ Greeting.args = { name: 'Guest' }
220
+ ```
221
+
209
222
  Use `Component.is` to specify the HTML element for a component:
210
223
 
211
224
  ```jsx
212
- function* CustomInput(props) {
225
+ function* CustomInput(args) {
213
226
  while (true) yield <>{props.children}</>
214
227
  }
215
228
  CustomInput.is = 'input'
@@ -271,11 +284,13 @@ function* StatefulComponent() {
271
284
 
272
285
  // Setting context value:
273
286
  function* App() {
287
+
274
288
  ThemeContext('dark')
289
+
275
290
  while (true) {
276
291
  yield (
277
292
  <>
278
- <FunctionalComponent />
293
+ <StatelessComponent />
279
294
  <StatefulComponent />
280
295
  </>
281
296
  )
@@ -302,65 +317,120 @@ Component methods:
302
317
 
303
318
  ```javascript
304
319
  function* Counter() {
320
+
305
321
  let count = 0
322
+
306
323
  const increment = () => {
307
324
  count++
308
325
  this.render() // Re-render to reflect the new count
309
326
  }
327
+
310
328
  while (true) {
311
329
  yield <button set:onclick={increment}>{count}</button>
312
330
  }
313
331
  }
314
332
  ```
315
333
 
316
- - `this.next()`: Advances the generator to the next yield point. It's automatically called by `this.render()` and is rarely used directly.
317
-
318
- - `this.throw(error)`: Throws an error in the generator. Useful for error propagation and creating error boundaries. Ajo automatically calls this method when an error occurs during rendering.
334
+ - `this.queueMicrotasks()`: Schedules an asynchronous re-render of the component. This is useful for batching multiple updates together for better performance.
319
335
 
320
336
  ```javascript
321
- function* ErrorBoundary(props) {
322
- try {
323
- while (true) {
324
- yield <div>{props.children}</div>
325
- }
326
- } catch (error) {
327
- yield <div>An error occurred: {error.message}</div>
337
+ function* AsyncCounter() {
338
+
339
+ let count = 0
340
+
341
+ const increment = () => {
342
+ count++
343
+ this.queueMicrotask() // Schedule an asynchronous re-render
344
+ }
345
+
346
+ while (true) {
347
+ yield <button set:onclick={increment}>{count}</button>
328
348
  }
329
349
  }
330
350
  ```
331
351
 
332
- - `this.return()`: Completes the generator execution. It's automatically called by Ajo when a component is unmounted, but can be used manually to reset a component's state.
352
+ - `this.requestAnimationFrame()`: Similar to `this.queueMicrotask()`, but uses `requestAnimationFrame` for smooth animations.
333
353
 
334
354
  ```javascript
335
- function* ResetableComponent() {
355
+ function* AnimatedCounter() {
356
+
336
357
  let count = 0
337
- const reset = () => {
338
- this.return() // Reset the generator
339
- this.render() // Re-render from the beginning
358
+
359
+ const increment = () => {
360
+ count++
361
+ this.requestAnimationFrame() // Schedule a re-render on the next animation frame
362
+ }
363
+
364
+ while (true) {
365
+ yield <button set:onclick={increment}>{count}</button>
366
+ }
367
+ }
368
+ ```
369
+
370
+ - `this.cleanup(fn)`: Registers a callback to be executed when the component unmounts. This is useful for cleaning up resources or subscriptions.
371
+
372
+ ```javascript
373
+ function* TimerComponent() {
374
+
375
+ let seconds = 0
376
+
377
+ const timer = setInterval(() => {
378
+ seconds++
379
+ this.render()
380
+ }, 1000)
381
+
382
+ this.cleanup(() => clearInterval(timer)) // Clean up the timer when unmounting
383
+
384
+ while (true) {
385
+ yield <div>Seconds: {seconds}</div>
340
386
  }
387
+ }
388
+ ```
389
+
390
+ - `this.effect(fn)`: Registers a callback to be run after the next render.
391
+
392
+ ```javascript
393
+ function* DataFetchingComponent() {
394
+
395
+ let data = null
396
+
397
+ this.effect(async () => {
398
+ const response = await fetch('https://api.example.com/data')
399
+ data = await response.json()
400
+ this.render()
401
+ })
402
+
341
403
  while (true) {
342
- yield (
343
- <div>
344
- <p>Count: {count}</p>
345
- <button set:onclick={() => { count++; this.render(); }}>Increment</button>
346
- <button set:onclick={reset}>Reset</button>
347
- </div>
348
- )
404
+ yield data ? <div>{JSON.stringify(data)}</div> : <div>Loading...</div>
349
405
  }
350
406
  }
351
407
  ```
352
408
 
353
- - `this.$args`: Provides access to the current args of the component.
409
+ If you want to execute an effect after each render, place it inside the main loop:
354
410
 
355
411
  ```javascript
356
- function* DynamicGreeting() {
412
+ function* EffectfulComponent() {
413
+
414
+ let count = 0
415
+
357
416
  while (true) {
358
- yield <h1>Hello, {this.$args.name}!</h1>
417
+
418
+ this.effect(() => console.log(`Count updated to ${count}`))
419
+
420
+ yield <button set:onclick={() => { count++; this.render() }}>{count}</button>
421
+
422
+ console.log(`Optionally you can clean up effect for count ${count} here`)
359
423
  }
360
424
  }
361
425
  ```
362
426
 
363
- These methods provide powerful control over the component's lifecycle and state management, allowing for efficient and flexible UI updates. Note that `this.throw()` and `this.return()` are often called automatically by Ajo in response to errors or component unmounting, respectively, but can also be used manually when needed.
427
+ - `this.next()`: Advances the generator to the next yield point. It's automatically called by `this.render()` and is rarely used directly.
428
+
429
+ - `this.throw(error)`: Throws an error in the generator. Useful for error propagation and creating error boundaries.
430
+
431
+ - `this.return()`: Completes the generator execution. It's automatically called when a component is unmounted, but can be used manually to reset a component's state.
432
+
433
+ These methods provide powerful control over the component's lifecycle, state management, and side effects, allowing for efficient and flexible UI updates. Note that `this.throw()` and `this.return()` are often called automatically by Ajo in response to errors or component unmounting, respectively, but can also be used manually when needed.
364
434
 
365
435
  ### `ajo/html` module
366
436
 
@@ -393,4 +463,4 @@ for (const chunk of html(<App />)) {
393
463
 
394
464
  ## License
395
465
 
396
- ISC © [Cristian Falcone](cristianfalcone.com)
466
+ ISC © [Cristian Falcone](cristianfalcone.com)
package/types.ts CHANGED
@@ -2,13 +2,17 @@ declare module 'ajo' {
2
2
 
3
3
  type Tag = keyof (HTMLElementTagNameMap & SVGElementTagNameMap)
4
4
 
5
- type Type = Tag | Function | Component
5
+ type Type = Tag | Stateless | Stateful
6
6
 
7
- type Attrs = Record<string, unknown>
7
+ type Component = Stateless | Stateful
8
8
 
9
- type VNode<TTag extends Type> = { nodeName: TTag } & Attrs
9
+ type Props = Record<string, unknown>
10
10
 
11
- type Children = any
11
+ type VNode<TTag extends Type, TProps extends Props = Props> = TProps & {
12
+ nodeName: TTag,
13
+ }
14
+
15
+ type Children = unknown
12
16
 
13
17
  type ElementType<TTag = Tag> = TTag extends keyof HTMLElementTagNameMap
14
18
  ? HTMLElementTagNameMap[TTag]
@@ -16,11 +20,11 @@ declare module 'ajo' {
16
20
  ? SVGElementTagNameMap[TTag]
17
21
  : never
18
22
 
19
- type AjoAttrs<TElement> = {
20
- key: unknown
21
- skip: boolean
22
- memo: unknown
23
- ref: (el: TElement | null) => void
23
+ type SpecialProps<TElement> = {
24
+ key: unknown,
25
+ skip: boolean,
26
+ memo: unknown,
27
+ ref: (el: TElement | null) => void,
24
28
  } & ElementChildrenAttribute
25
29
 
26
30
  type PropSetter<TTag = Tag> = {
@@ -31,35 +35,44 @@ declare module 'ajo' {
31
35
  [key: `attr:${string}`]: unknown
32
36
  }
33
37
 
34
- type Function<TArguments extends Attrs = Attrs> = (args: TArguments) => Children
38
+ type Stateless<TArguments extends Props = Props> = (args: TArguments) => Children
35
39
 
36
- type Component<TArguments extends Attrs = Attrs, TTag extends Tag = 'div'> = {
37
- (this: ComponentElement<TArguments, TTag>, args: ComponentProps<TArguments, TTag>): Iterator<Children, unknown, unknown>
38
- } & (TTag extends 'div' ? { is?: TTag } : { is: TTag })
40
+ type Stateful<TArguments extends Props = Props, TTag extends Tag = 'div'> = {
41
+ (this: StatefulElement<TArguments, TTag>, args: StatefulProps<TArguments, TTag>): Iterator<Children>
42
+ } & (TTag extends 'div' ? { is?: TTag } : { is: TTag }) & { attrs?: Partial<PropSetter<TTag>> & Props, args?: Partial<TArguments> }
39
43
 
40
- type ComponentProps<TArguments extends Attrs = Attrs, TTag extends Tag = 'div'> =
41
- Partial<PropSetter<TTag> & AjoAttrs<ComponentElement<TArguments, TTag>>> &
44
+ type StatefulProps<TArguments extends Props = Props, TTag extends Tag = 'div'> =
45
+ Partial<SpecialProps<StatefulElement<TArguments, TTag>> & PropSetter<TTag>> &
42
46
  AttrSetter &
43
47
  TArguments
44
48
 
45
- type ComponentElement<TArguments extends Attrs = Attrs, TTag extends Tag = Tag> = ElementType<TTag> & {
46
- $args: TArguments,
47
- $context: { [key: symbol]: unknown },
49
+ type StatefulElement<TArguments extends Props = Props, TTag extends Tag = Tag> = ElementType<TTag> & {
50
+ [Symbol.iterator]: () => Iterator<TArguments>,
48
51
  render: () => void,
49
- next: () => void
50
- throw: (value?: unknown) => void
51
- return: () => void
52
+ queueMicrotask: () => void,
53
+ requestAnimationFrame: () => void,
54
+ effect: (fn: () => void | (() => void)) => () => void,
55
+ cleanup: (fn: () => void) => () => void,
56
+ next: () => void,
57
+ throw: (value?: unknown) => void,
58
+ return: () => void,
52
59
  }
53
60
 
54
61
  type IntrinsicElements = {
55
- [TTag in Tag]: Partial<PropSetter<TTag> & AjoAttrs<ElementType<TTag>>> & Attrs
62
+ [TTag in Tag]: Partial<PropSetter<TTag> & SpecialProps<ElementType<TTag>>> & Props
56
63
  }
57
64
 
58
65
  type ElementChildrenAttribute = { children: Children }
59
66
 
60
67
  function Fragment({ children }: ElementChildrenAttribute): typeof children
61
- function h<TTag extends Tag>(tag: TTag, props?: Attrs | null, ...children: Array<unknown>): VNode<TTag>
62
- function render(h: Children, el: Element): void
68
+ function h(tag: Type, props?: Props | null, ...children: Children[]): VNode<Type, Props>
69
+ function render(h: Children, el: Element, child?: Node, ref?: Node): void
70
+ function context<T>(fallback?: T): (value?: T) => T
71
+ }
72
+
73
+ declare module 'ajo/html' {
74
+ function render(h: import('ajo').Children): string
75
+ function html(h: import('ajo').Children): IterableIterator<string>
63
76
  function context<T>(fallback?: T): (value?: T) => T
64
77
  }
65
78
 
@@ -67,9 +80,3 @@ declare namespace JSX {
67
80
  type ElementChildrenAttribute = import('ajo').ElementChildrenAttribute
68
81
  type IntrinsicElements = import('ajo').IntrinsicElements
69
82
  }
70
-
71
- declare namespace React {
72
- const createElement: typeof import('ajo').h
73
- const Fragment: typeof import('ajo').Fragment
74
- type ReactNode = import('ajo').Children
75
- }