objs-core 1.1.1 → 2.0.1

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.
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @fileoverview Objs-core library
3
+ * @version 2.0
4
+ * @author Roman Torshin
5
+ * @license Apache-2.0
6
+ */const Y=!0,t=n=>{let e={els:[],ie:{},delegated:{},parented:{},store:{},refs:{},states:[],isDebug:!1,currentState:"",savedStates:{},isRoot:!1,_parent:null},o=1,r=2,c=3,w="boolean",a="object",h="function",S="string",C="number",l="notEmptyString",k="undefined",m="dangerouslySetInnerHTML",E,f=t.D,v=-1,u=0,y=0,x=typeof process<"u"||t.D===t.DocumentMVP,b=0,D=0;const I=e,O=s=>typeof s,R=(s,i)=>{for(const g in s)Object.hasOwn(s,g)&&i(g,s)},U=t.onError,L=s=>t.verify(s),$=(s,i="")=>(...g)=>{(t.debug||e.isDebug)&&console.log(i?`${i}()`:s,g.length?"with "+g.join(", "):"without parameters");try{const p=s(g[0],g[o],g[r],g[c]);return p!==E?p:e}catch(p){U(p,i)}},N=s=>{for(b=u;b<=v;b++)s()},M=s=>s?.els?s.el:(O(s)!==a&&(s=t.first(s).el),s),P=(s=!0,i=e.els)=>{const g=i.length;e.length=g,v=g-o,u=0,e.el=g?i[0]:E,e.last=g?i[v]:E,s&&(R(e.states,(p,d)=>{delete e[d[p]]}),e.states=[],e.ie={})};e.reset=t;const H=(s,i,g)=>{R(i,p=>{let d=i[p];O(d)===h&&(d=d(g)),p==="append"&&O(d)===a&&(d.els&&(d=[d]),d[0]?.els&&(valueBuff=[],R(d,T=>{valueBuff.push(...d[T].els)}),d=valueBuff)),d!==E&&s.getAttribute(p)!==d&&!["tag","tagName","name","sample","state","events","ssr","nodeName","revertChildren","root","ref"].includes(p)&&(["html","innerHTML"].includes(p)?s.innerHTML=d:p==="className"?s.setAttribute("class",d):p==="dataset"&&O(d)===a?R(d,T=>{s.dataset[T]=d[T]}):p==="toggleClass"?s.classList.toggle(d):p==="addClass"?O(d)===a?s.classList.add(...d):s.classList.add(d):p==="removeClass"?s.classList.remove(d):p==="style"&&O(d)===a?R(d,T=>{s.style[T]=d[T]}):(p==="append"||p==="children"||p==="childNodes")&&O(d)===a?R(d.length?d:[d],T=>{p==="append"||!s.childNodes[T]?s.appendChild(d[T]):s.childNodes[T]!==d[T]&&s.childNodes[T].replaceWith(d[T])}):s.setAttribute(p,d))}),s.dataset.oState=i.state,t.autotag&&i.name&&(s.dataset[t.autotag]=t.camelToKebab(i.name))};e.debug=$(()=>{e.isDebug=!0},"debug ON"),e.saveAs=$(s=>{L([[s,[l]]]),t.getSaved[s]?(t.debug||e.isDebug)&&console.warn("the key exists (not saved):"+s):t.getSaved[s]=e},"saveAs"),e.unmount=()=>((t.debug||e.isDebug)&&console.log("unmount() for initID:"+e.initID),O(e.remove)===h?e.remove():e.els?.length&&e.els.forEach(s=>{s?.parentNode&&s.parentNode.removeChild(s)}),t.inits[e.initID]=void 0,e={},!0),e.init=$(s=>{L([[s,[a,h]]]);const i=e.initID||t.inits.length||0;if(e.initID=i,P(),t.inits[e.initID]=e,O(s)==="function"){e.render=$(p=>{const d=f.createElement("div");setTimeout(()=>{t.reactRender(s,d,p)}),e.add(d)});return}(O(s)!==a||s.render===E)&&(s={render:s}),R(s,p=>{e?.render&&p==="render"||(e.states.push(p),e[p]=$((d=[{}])=>{e.currentState=p;const T=s[p]||{tag:"div"},A=Array.isArray(e.els)?e.els.slice(u,v+o):[],B=A.length?A:e.els||[];O(T)===a&&(T.state=p,T["data-o-init"]=i);const q=(_,F={})=>{if(O(T)===a)return f.createElement(T.tag||T.tagName||"div");{const j=f.createElement("div");return j.innerHTML=O(T)===h?T(F):T,j.children.length>o||!j.firstElementChild?(j.dataset.oInit=_,j):(j.firstElementChild.dataset.oInit=_,j.firstElementChild)}},z=d;d.length||(d=[d]);const X=!B[0]&&p==="render";d=d.map((_,F)=>{const j=Object.assign({},O(_)===a?_:{},{self:e,o:t,i:_.i===E?F:_.i,parent:e._parent,data:Array.isArray(z)?z[F]:z});return X&&(!T.ssr||x)&&B.push(q(i,j)),j}),X&&(e.els=B,P(!1));const V=()=>{R(T.events,_=>{e.on(_,T.events[_])})};B&&(D=B.length===d.length,B.map((_,F)=>{d[D?F:0].i=F+u;const j=O(T)===h?T(d[D?F:0]):T;O(j)===a&&(j.state=p,X&&(j["data-o-init"]=i,j["data-o-init-i"]=F),H(_,j,d[D?F:0]))}),X&&(e.refs={},e.els.forEach(_=>{_.querySelectorAll&&_.querySelectorAll("[ref]").forEach(F=>{e.refs[F.getAttribute("ref")]=t(F),F.removeAttribute("ref")})}))),X&&O(T)===a&&T.events&&!x&&!T.ssr&&V()}))});const g=s.render||s;!x&&O(g)===a&&g.events&&g.ssr&&(e.initSSRAfterGettingSSR=()=>{e.refs={},e.els.forEach(p=>{p.querySelectorAll&&p.querySelectorAll("[ref]").forEach(d=>{e.refs[d.getAttribute("ref")]=t(d),d.removeAttribute("ref")})}),R(g.events,p=>{e.on(p,g.events[p])})})},"init"),e.connect=$((s,i="render",g)=>{L([[s,[a]],[i,[l]],[g,[S,k]]]),s.connect(I,i,g)},"connect"),e.getSSR=$(s=>{L([[s,[C,k]]]);const i=s!==void 0?s:e.initID;if(x||O(s)===k&&O(e.initID)===k)return;const g=t.D.querySelectorAll(`[data-o-init="${i}"]`);g.length&&!e.els.length&&(e.els=Array.from(g),e.initID=s,t.inits[s]=e,P(!1),O(e.initSSRAfterGettingSSR)===h&&(e.initSSRAfterGettingSSR(),delete e.initSSRAfterGettingSSR))},"getSSR"),e.initState=$((s,i)=>{L([[s,[a]],[i,[a,k]]]),e.init(s).render(i)},"initState");const J=(s,i,g)=>{const p=s.attributes,d={tagName:s.tagName.toLowerCase()};for(const T of p)d[T.nodeName]=T.value;if(g){d.innerHTML=s.innerHTML,d.revertChildren=[];const T=s.querySelectorAll("[data-o-init]");for(const A of T){const B=A.getAttribute("data-o-init");d.revertChildren.push(B),t.inits[B]?.saveState(i,!1)}}return d};return e.saveState=$((s,i=!0)=>{if(L([[s,[l,k]],[i,[w]]]),!e.el)throw Error("saveState(): There are no elements to save");const g=s||"fastSavedState",p={els:[],parentNode:e.el.parentNode,root:i};N(()=>{p.els.push(J(e.els[b],g,i))}),p.ie=Object.assign({},e.ie),p.delegated=Object.assign({},e.delegated),p.store=Object.assign({},e.store),e.isRoot=e.isRoot||i,e.savedStates[g]=p},"saveState"),e.revertState=$(s=>{L([[s,[l,k]]]);const i=s||"fastSavedState";if(!e.savedStates[i])throw Error(`revertState(): The state "${i}" should have been saved by saveState()`);const g=e.savedStates[i];e.offAll(),e.offDelegate(),e.store=Object.assign({},g.store),g.els.forEach((p,d)=>{if(!e.els[d]){const T=t.D.createElement(p.tagName);g.parentNode&&(d?e.els[d-1].after(T):g.parentNode.append(T)),e.add(T)}H(e.els[d],p)}),e.delegated=Object.assign({},g.delegated),e.ie=Object.assign({},g.ie),e.onAll(),R(g.delegated,p=>{g.delegated[p].forEach(d=>{N(()=>{e.els[b].addEventListener(p,d)})})}),e.currentState=i,g.root&&g.els.forEach(({rootElement:p})=>{p.revertChildren.forEach(d=>{t.inits[d]?.revertState(i),t('[data-o-init="'+d+'"]').els.forEach((T,A)=>{T.replaceWith(t.inits[d]?.els[A])})})})},"revertState"),e.loseState=$(s=>{L([[s,[l]]]),e.savedStates[s]&&(delete e.savedStates[s],N(()=>{const i=e.els[b].querySelectorAll("[data-o-init]");for(const g of i){const p=g.getAttribute("data-o-init");t.inits[p]?.loseState(s)}}))},"sample"),e.sample=$((s="render")=>(L([[s,[l]]]),{[s]:J(e.els[u])}),"sample"),e.select=$(s=>{L([[s,[C,k]]]),s===E&&(s=e.length-o),v=s,u=s,e.el=e.els[s],y=o},"select"),e.all=$(()=>{v=e.length-o,u=0,e.el=e.els[0],y=0},"all"),e.remove=$(s=>{if(L([[s,[C,k]]]),s===E&&y&&(s=u),s!==E){const i=e.els[s];i?.parentNode?i.parentNode.removeChild(i):i===void 0&&s>=e.els.length&&t.onError&&t.onError("remove("+s+"): index out of bounds","remove")}else N(()=>{const i=e.els[b];i?.parentNode&&i.parentNode.removeChild(i)});P(!1)},"remove"),e.skip=$(s=>{L([[s,[C,k]]]),s===E&&(s=u),e.els.splice(b,o),P()},"skip"),e.add=$(s=>{L([[s,[S,a,C]]]),e.initID===E&&(O(s)==="string"&&s!==""?e.els.push(...Array.from(f.querySelectorAll(s))):O(s)===a?s.tagName?e.els.push(s):s.els?e.els.push(...s.els):s.length&&s[0].tagName&&e.els.push(...s):O(s)==="number"&&t.inits[s]&&(e=t.inits[s]),P(!1),e.initID!==E&&e.dataset({oInit:e.initID}))},"add"),e.appendInside=$(s=>{L([[s,[a,l]]]),s?.els&&(e._parent=s),N(()=>{M(s).appendChild(e.els[b])})},"appendInside"),e.appendBefore=$(s=>{L([[s,[a,l]]]),N(()=>{M(s).parentNode.insertBefore(e.els[b],M(s))})},"appendBefore"),e.appendAfter=$(s=>{L([[s,[a,l]]]),N(()=>{M(s).after(...e.els)})},"appendAfter"),e.find=$((s="")=>{L([[s,S]]);const i=[];return N(()=>{i.push(...Array.from(e.els[b].querySelectorAll(":scope "+s)))}),t(i)},"find"),e.first=$((s="")=>{L([[s,S]]);let i=E;const g=[];return N(()=>{i=e.els[b].querySelector(s),i&&g.push(i)}),t(g)},"first"),e.attr=$((s,i)=>{if(i!==null&&L([[s,S],[i,[S,k]]]),i===E){const g=[];return N(()=>{g[b]=e.els[b].getAttribute(s)}),y?g[0]:g}else N(i!==null?()=>{e.els[b].setAttribute(s,i)}:()=>{e.els[b].removeAttribute(s)})},"attr"),e.attrs=$(()=>{const s=[];return N(()=>{const i={};[...e.els[b].attributes].forEach(g=>{i[g.nodeName]=g.nodeValue}),s.push(i)}),y?s[0]:s},"attrs"),e.dataset=$(s=>{if(L([[s,[a,k]]]),typeof s===a)N(()=>{R(s,i=>{e.els[b].dataset[i]=s[i]})});else{const i=[];return N(()=>{i.push({...e.els[b].dataset})}),y?i[0]:i}},"dataset"),e.style=$(s=>{s!==null&&L([[s,[S,k]]]),e.attr("style",s)},"style"),e.css=$((s={})=>{if(s===null){e.style(null);return}L([[s,a]]);let i="";R(s,g=>{i+=g+":"+s[g].replace('"',"'")+";"}),e.style(i||null)},"css"),e.setClass=$(s=>{L([[s,S]]),N(()=>{e.els[b].setAttribute("class",s)})},"setClass"),e.addClass=$((...s)=>{N(()=>{e.els[b].classList.add(...s)})},"addClass"),e.removeClass=$((...s)=>{N(()=>{e.els[b].classList.remove(...s)})},"removeClass"),e.toggleClass=$((s,i)=>{L([[s,l],[i,[w,k]]]),N(()=>{e.els[b].classList.toggle(s,i)})},"toggleClass"),e.haveClass=s=>{L([[s,l]]);let i=!0;return N(()=>{e.els[b].classList.contains(s)||(i=!1)}),(e.isDebug||t.debug)&&console.log("haveClass() with",s),i},e.innerHTML=$(s=>{if(L([[s,[S,k]]]),s!==E)N(()=>{e.els[b].innerHTML=s});else{let i="";return N(()=>{i+=x&&e.els[b].innerHTML.length===0?t.D.parseElement(e.els[b],!1):e.els[b].innerHTML}),i}},"innerHTML"),e.innerText=$(s=>{L([[s,[S]]]),N(()=>{e.els[b].innerText=s})},"innerText"),e.textContent=$(s=>{L([[s,[S]]]),N(()=>{e.els[b].textContent=s})},"textContent"),e.html=$(s=>{if(L([[s,[S,k]]]),s!==void 0)e.innerHTML(s);else{let i="";return N(()=>{i+=x?e.els[b].outerHTML():e.els[b].outerHTML}),i}},"html"),e.val=$(s=>{if(s===void 0)return e.el?.value;N(()=>{e.els[b].value=s})},"val"),e.forEach=$(s=>{L([[s,[h]]]),N(()=>{s({self:e,i:b,o:t,el:e.els[b]})})},"forEach"),e.prepareFor=$((s,i)=>{L([[s,[a,h,k]],[i,[h,k]]]);const g=s&&O(s)===a&&s.createElement;if(!g&&O(s)!==h)throw Error("prepareFor(): pass React (full object) or React.createElement as first argument");const p=g?s.createElement:s,d=g?s.useEffect:void 0;return T=>{if(T.ref===E)throw Error("No ref property to convert Objs to React");const A=Object.assign({},T),B=p("div",{ref:T.ref});return delete A.ref,d(()=>{R(A,q=>{if(q.substring(0,1)==="on"){const z=t.camelToKebab(q).split("-")[1];e.on(z,A[q]),delete A[q]}}),e.render(A),e.appendInside(B.ref.current)},[]),B}},"prepareFor"),e.on=$((s,i,g,p)=>{L([[s,[l]],[i,[h]],[g,[a,k]],[p,[w,k]]]),s.split(", ").forEach(d=>{N(()=>{e.els[b].addEventListener(d,i,g,p)}),e.ie[d]||(e.ie[d]=[]),e.ie[d].push([i,g,p])})},"on"),e.off=$((s,i,g)=>{L([[s,[l]],[i,[h]],[g,[a,k]]]),s.split(", ").forEach(p=>{N(()=>{e.els[b].removeEventListener(p,i,g)}),e.ie[p]&&(e.ie[p]=e.ie[p].filter(d=>d[0]!==i))})},"off"),e.onDelegate=$((s,i,g)=>{L([[s,[l]],[i,[l]],[g,[h]]]),s.split(", ").forEach(p=>{const d=T=>{const A=T.target.closest(i);A&&(T.delegate=A,T.objs=e,g(T))};N(()=>{e.els[b].addEventListener(p,d)}),e.delegated[p]||(e.delegated[p]=[]),e.delegated[p].push(d)})},"onDelegate"),e.offDelegate=$(s=>{L([[s,[l]]]),R(e.delegated,i=>{if(!s||s===i)for(;e.delegated[i].length;){const g=e.delegated[i].pop();N(()=>{e.els[b].removeEventListener(i,g)})}}),e.delegated={}},"offDelegate"),e.onParent=$((s,i,g)=>{L([[s,[l]],[i,[l,a]],[g,[h]]]);const p=O(i)===a?i:t.D.querySelector(i);s.split(", ").forEach(d=>{const T=A=>{A.objs=e,g(A)};p.addEventListener(d,T),e.parented[d]||(e.parented[d]=[]),e.parented[d].push(T)})},"onParent"),e.offParent=$((s,i)=>{L([[s,[l]],[i,[l,a]]]);const g=O(i)===a?i:t.D.querySelector(i);R(e.parented,p=>{(!s||s===p)&&(e.parented[p].forEach(d=>{g.removeEventListener(p,d)}),delete e.parented[p])})},"offParent"),e.onAll=$((s,i)=>{L([[s,[l,k]],[i,[w,k]]]),R(e.ie,(g,p)=>{(!s||s===g)&&p[g].forEach(d=>{N(()=>{i?e.els[b].removeEventListener(g,d[0]):e.els[b].addEventListener(g,d[0],d[o],d[r])})})})},"onAll"),e.offAll=$(s=>{L([[s,[l]]]),e.onAll(s,o)},"offAll"),n&&e.add(n),e.take=s=>{if(L([[s,[S,a,C]]]),e.add(s),e.el){const i=e.el.dataset.oInit;if(i!==E&&t.inits[i])return e.length===o?(D=e.els[0],Object.assign(e,t.inits[i]),e.els=[D]):e=t.inits[i],P(!1,e.els),e}},e};t.first=n=>(t.verify([[n,["notEmptyString"]]]),t.debug&&console.log(n," -> ","o.first()"),t(t.D.querySelector(n)).select(0)),t.inits=[],t.getSaved={},t.errors=[],t.showErrors=!1,t.logErrors=()=>{t.errors.length?t.errors.forEach(n=>console.error(n)):console.log("No errors")},t.onError=(n,e)=>{t.showErrors?console.error(n,e):(t.errors.push(n),e&&t.errors.push(e))},t.reactRender=()=>new Error("React render function is not defined"),t.autotag=void 0,t.reactQA=n=>({["data-"+(t.autotag||"qa")]:n.replace(/([A-Z])/g,(e,o)=>"-"+o.toLowerCase()).replace(/^-/,"")}),t.specialTypes={notEmptyString:(n,e)=>e==="string"&&n.length,array:n=>Array.isArray(n),promise:n=>n instanceof Promise||!!(n&&typeof n.then=="function")},t.verify=(n,e=!1)=>{for(const o of n){const r=typeof o[0];let c=Array.isArray(o[1])?o[1]:[o[1]],w=!1;if(c.includes(r))return!0;c=c.filter(a=>!!t.specialTypes[a]);for(const a of c)if(w=t.specialTypes[a](o[0],r),w)return!0}return e?!1:new Error("Type verification failed")},t.safeVerify=n=>t.verify(n,!0),t.init=(n,e)=>t().init(n,e),t.initState=(n,e)=>t().init(n).render(e),t.take=n=>t().take(n),t.getStates=()=>t.inits.reduce((n,e)=>(n.push(e?.states),n),[]),t.getStores=()=>t.inits.reduce((n,e)=>(n.push(e?.store),n),[]),t.getListeners=()=>t.inits.reduce((n,e)=>(n.push(e?.ie),n),[]),t.createStore=n=>{const e=Object.assign({},n);return e._defaults=Object.assign({},n),e._listeners=[],e.subscribe=function(o,r){return this._listeners.push(c=>o[r]?.(c)),this},e.notify=function(){this._listeners.forEach(o=>o(this))},e.reset=function(){const o={_listeners:1,subscribe:1,notify:1,_defaults:1,reset:1};for(const r of Object.keys(this._defaults))o[r]||(this[r]=this._defaults[r])},e},t.U=void 0,t.W=2,t.H=100,t.F=!1,t.C=(n,e)=>Object.hasOwn(n,e),t.kebabToCamel=n=>n.replace(/-./g,e=>e.toUpperCase()[1]),t.camelToKebab=n=>n.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),t.route=(n,e)=>{t.verify([[n,["notEmptyString","function","boolean"]],[e,["function","object"]]]);const o=typeof n=="function"?n(window.location.pathname):n;return o===!0||window.location.pathname===o?e?typeof e=="function"?(e(),!0):e:t:typeof e=="function"?!1:{}},t.router=(n={})=>{t.verify([[n,["object"]]]);for(const e in n)if(t.C(n,e)&&window.location.pathname===e)return typeof n[e]=="function"?(n[e](),!0):n[e];return!1},t.DocumentMVP={addEventListener:()=>{},parseElement:(n,e=!0)=>{t.verify([[n,["object","string"]],[e,["boolean"]]]);const o=(r,c="")=>{let w="";for(const a in r)t.C(r,a)&&(w+=` ${c}${t.camelToKebab(a)}="${typeof r[a]!="object"?r[a]:Object.entries(r[a]).map(h=>`${h[0]}: ${h[1]};`).join(" ")}"`);return w};if(typeof n=="string")return n;if(e){const r=["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"],c=n.tagName.toLowerCase(),w=n.attributes["data-o-init"],a=w!==void 0?` data-o-init="${w}"`:"";return`<${c}${n.className?` class="${n.className}"`:""}${o(n.attributes)}${a}${o(n.dataset,"data-")}${r.includes(c)?"/":""}>${r.includes(c)?"":n.innerHTML.length?n.innerHTML:n.children.map(h=>t.D.parseElement(h)).join("")}${r.includes(c)?"":`</${c}>`}`}return n.innerHTML.length?n.innerHTML:n.children.map(r=>t.D.parseElement(r)).join("")},createElement:n=>{t.verify([[n,["notEmptyString"]]]);const e={tagName:n.toUpperCase(),attributes:{},innerHTML:"",children:[],dataset:{},className:"",classArray:[],style:{},addEventListener:()=>{},removeEventListener:()=>{}};return e.classList={add:(...o)=>{t.verify([[o,["array"]]]),e.classArray.push(o),e.className=e.classArray.join(" ")},has:o=>(t.verify([[o,["notEmptyString"]]]),e.classArray.includes(o)),remove:o=>{t.verify([[o,["notEmptyString"]]]),e.classArray=e.classArray.filter(r=>o!==r),e.className=e.classArray.join(" ")}},e.classList.toggle=o=>{t.verify([[o,["notEmptyString"]]]),e.classList.has(o)?e.classList.remove(o):e.classList.add(o)},e.setAttribute=(o,r)=>{t.verify([[o,["notEmptyString"]],[r,["string","number","boolean","undefined"]]]),e.attributes[o]=r},e.getAttribute=o=>(t.verify([[o,["notEmptyString"]]]),e.attributes[o]),e.removeAttribute=o=>{t.verify([[o,["notEmptyString"]]]),delete e.attributes[o]},e.appendChild=o=>{t.verify([[o,["object"]]]),e.children.push(o),e.firstElementChild=e.children[0]},e.outerHTML=()=>t.D.parseElement(e),e}},t.D=typeof document<"u"&&typeof process>"u"?document:t.DocumentMVP,t.setCookie=(n,e="",o={})=>{if(t.verify([[n,["notEmptyString"]],[e,["string","number","boolean"]],[o,["object"]]]),t.D.cookie===void 0){console.log("Cookies are not supported on server side");return}let r=encodeURIComponent(n)+"="+encodeURIComponent(e);o={path:"/",...o},o.expires instanceof Date?o.expires=o.expires.toUTCString():typeof o.expires=="number"&&(o.expires=new Date(o.expires).toUTCString());for(const c in o){r+="; "+c;const w=o[c];w!==!0&&(r+="="+w)}t.D.cookie=r},t.getCookie=n=>{if(t.verify([[n,["notEmptyString"]]]),t.D.cookie===void 0){console.log("Cookies are not supported on server side");return}const e=t.D.cookie.match(RegExp("(?:^|; )"+n.replace(/([.$?*|{}()[\]\\/+^])/g,"\\$1")+"=([^;]*)"));return e?decodeURIComponent(e[1]):void 0},t.deleteCookie=n=>{t.verify([[n,["notEmptyString"]]]),t.setCookie(n,"",{"max-age":0})},t.clearCookies=()=>{if(t.D.cookie===void 0){console.log("Cookies are not supported on server side");return}const n=t.D.cookie.split(";");for(;n.length;){let e=n.pop();for(;e.charAt(0)===" ";)e=e.substring(1);const o=e.split("=")[0];t.deleteCookie(o)}},t.clearLocalStorage=n=>{if(t.verify([[n,["boolean","undefined"]]]),!(typeof localStorage>"u"))if(n)localStorage.clear();else for(let e=localStorage.length-1;e>=0;e--){const o=localStorage.key(e);o.indexOf("oInc-")===-1&&o.indexOf("oTest-")===-1&&localStorage.removeItem(o)}},t.clearSessionStorage=n=>{if(t.verify([[n,["boolean","undefined"]]]),!(typeof sessionStorage>"u"))if(!n)sessionStorage.clear();else for(let e=sessionStorage.length-1;e>=0;e--){const o=sessionStorage.key(e);o&&o.indexOf("oTest-")===0&&sessionStorage.removeItem(o)}},t.clearTestsStorage=()=>{t.clearSessionStorage(1)},t.clearAfterTests=()=>{t.clearCookies(),t.clearLocalStorage(!1),t.clearTestsStorage()},t.ajax=(n,e={})=>{t.verify([[n,["notEmptyString"]],[e,["object"]]]);const o=new URLSearchParams;if(e.data&&typeof e.data=="object"){for(const r in e.data)t.C(e.data,r)&&(typeof e.data[r]=="object"?o.set(r,encodeURIComponent(JSON.stringify(e.data[r]))):o.set(r,e.data[r]));e.method.toLowerCase()==="get"?n+="?"+o.toString():e.body||(e.body=o),delete e.data}return e.headers||(e.headers={"X-Requested-With":"XMLHttpRequest"}),fetch(n,e)},t.get=(n,e={})=>(t.verify([[n,["notEmptyString"]],[e,["object"]]]),t.ajax(n,{...e,method:"GET"})),t.post=(n,e={})=>(t.verify([[n,["notEmptyString"]],[e,["object"]]]),t.ajax(n,{...e,method:"POST"})),t.newLoader=n=>{t.verify([[n,["promise","undefined"]]]);let e=[],o=null,r=!1,c=!1;const w=a=>{r=!1,c=!1,o=null,setTimeout(()=>{a.then(h=>{r=!0,!h.ok&&typeof h.ok<"u"?(c=!0,e.forEach(([S,C,l])=>{l&&S[l](h)})):typeof h.json=="function"?h.json().then(S=>{o=S,e.forEach(([C,l])=>{C[l](o)})}):(o=h,e.forEach(([S,C])=>{S[C](o)}))}).catch(h=>{c=!0,e.forEach(([S,C,l])=>{l&&S[l](h)})})},33)};return n&&w(n),{reload:w,isObjsLoader:!0,listeners:e,isFinished:()=>r,getStore:()=>o,connect:(a,h="render",S)=>{t.verify([[a,["object"]],[h,["notEmptyString"]],[S,["string","undefined"]]]),r?c?S&&a[S]():typeof a[h]=="function"&&a[h](o):e.push([a,h,S])},disconnect:a=>{t.verify([[a,["object"]]]),e=e.filter(([h])=>h!==a)}}},t.getParams=n=>{t.verify([[n,["string","undefined"]]]);const e={},o=new URLSearchParams(window.location.search).entries();for(const r of o)e[r[0]]=r[1];return n?e[n]:e},t.incCache=!0,t.incCacheExp=1e3*60*60*24,t.incTimeout=6e3,t.incSource="",t.incForce=t.F,t.incAsync=!0,t.incCors=t.F,t.incSeparator="?",t.incFns={},t.incSet=[0],t.incReady=[0],t.incN=0,t.incGetHash=n=>n.split(t.incSeparator)[1]||"",t.incCheck=(n=0,e,o=0)=>(t.verify([[n,["number"]],[e,["number","undefined"]],[o,["number"]]]),!o&&n&&e===t.U&&t.incReady[n]?t.incSet[n]===1:t.incReady[n]===t.U||t.incReady[n][e]===t.U?t.F:(t.incReady[n][e].loaded=o,t.incFns[t.incReady[n][e].name]=o,t.incReady[n][0]+=o,n&&t.incReady[n].length===t.incReady[n][0]&&(typeof t.incSet[n]=="function"&&t.incSet[n](n),t.incSet[n]=1),t.incSet[n]===1)),t.incCacheClear=(n=t.F)=>{t.verify([[n,["boolean"]]]);for(const e in t.incFns)t.C(t.incFns,e)&&(localStorage.removeItem("oInc-"+e),localStorage.removeItem("oInc-"+e+"-expires"));return n&&(t.incReady.forEach((e,o)=>{o&&e.forEach((r,c)=>{c&&t("#oInc-"+o+"-"+c).remove()})}),t.incN=0,t.incFns={},t.incSet=[0],t.incReady=[0]),!0},t.inc=(n,e,o)=>{if(t.verify([[n,["object","undefined"]],[e,["function","undefined"]],[o,["function","undefined"]]]),typeof localStorage>"u")return;let r=0,c=0,w="",a=!1;const h="function",S=-1;if(typeof n!="object"||!n)return t.incSet[0];t.incSet[0]++;const C=t.incSet[0];t.incSet[C]=e||0,t.incReady[C]=[];const l=t.incReady[C];l[0]=1;const k={};for(const m in n)if(t.C(n,m)){if(m==="preload"){a=!0;continue}w=t.incGetHash(n[m]),r++,t.incN++;const E=n[m].indexOf(".css")>S?"style":"script";if(n[m]=(t.incSource?t.incSource+"/":"")+n[m],Number.isNaN(Number(m))&&t.C(t.incFns,m)&&t.incFns[m]&&!t.incForce){l[r]={name:m,loaded:1},c++;continue}if(l[r]={name:m,loaded:0},Number.isNaN(Number(m))&&(t.incFns[m]=0),Number.isNaN(Number(m))&&t.incCache&&(n[m].substring(0,4)!=="http"||!t.incCors)&&window.location.protocol!=="file:"&&(n[m].indexOf(".css")>S||n[m].indexOf(".js")>S)){const f=localStorage,v=f.getItem("oInc-"+m),u=f.getItem("oInc-"+m+"-expires"),y=f.getItem("oInc-"+m+"-hash");v&&u&&Date.now()<u&&y===w?(a||t.initState({tag:E,id:"oInc-"+C+"-"+r,innerHTML:v,"data-o-inc":C}).appendInside("head"),l[r].loaded=1,t.incFns[m]=1,c++):(k[m]=r,t.get(n[m],{mode:t.incCors?"cors":"same-origin"}).then(x=>{if(x.status!==200){t.onError&&t.onError({message:t.incSource+n[m]+" was not loaded"});return}x.text().then(b=>{f.setItem("oInc-"+m,b),f.setItem("oInc-"+m+"-expires",Date.now()+t.incCacheExp),f.setItem("oInc-"+m+"-hash",w),a||t.initState({tag:E,id:"oInc-"+C+"-"+k[m],innerHTML:b,"data-o-inc":C}).appendInside("head"),t.incCheck(C,k[m],1)})}))}else{const f={tag:E,id:"oInc-"+C+"-"+r,"data-o-inc":C,async:t.incAsync,onload:"o.incCheck("+C+","+r+",1)"};n[m].indexOf(".css")>S?(f.tag="link",f.rel="stylesheet",f.href=n[m]):(n[m].indexOf(".js")>S||(f.tag="img",f.style="display:none;"),f.src=n[m]),t.initState(f).appendInside(f.style?"body":"head")}}return l[0]+=c,r!==0&&(c===r?typeof e===h&&e(C):setTimeout(m=>{t.incReady[m]&&t.incReady[m].length<t.incReady[m][0]&&(t.incSet[m]=0,typeof o===h&&o(C))},t.incTimeout,C)),t.incSet[0]},t.connectRedux=(n,e,o,r="render")=>{t.verify([[n,["object"]],[e,["function"]],[o,["object"]],[r,["notEmptyString"]]]);const c=()=>{if(typeof o[r]=="function"){const w=e(n.getState());o[r](w!==null&&typeof w=="object"?w:{value:w})}};return c(),n.subscribe(c)},t.connectMobX=(n,e,o,r,c="render")=>(t.verify([[n,["object"]],[e,["object"]],[o,["function"]],[r,["object"]],[c,["notEmptyString"]]]),n.autorun(()=>{if(typeof r[c]=="function"){const w=o(e);r[c](w!==null&&typeof w=="object"?w:{value:w})}})),t.ObjsContext=null,t.withReactContext=(n,e,o,r,c="render")=>function(){const a=n.useContext(e);return n.useEffect(()=>{if(typeof r[c]=="function"){const h=o(a);r[c](h!==null&&typeof h=="object"?h:{value:h})}},[a]),null},t.debug=!1,t.tLog=[],t.tRes=[],t.tStatus=[],t.tFns=[],t.tShowOk=t.F,t.tStyled=t.F,t.tTime=2e3,t.tests=[],t.tAutolog=t.F,t.tBeforeEach=void 0,t.tAfterEach=void 0,t.addTest=(n,...e)=>{t.verify([[n,["notEmptyString"]],[e,["array"]]]);let o={};e.length&&typeof e[e.length-1]=="object"&&!Array.isArray(e[e.length-1])&&(o=e.pop());const r=t.tests.length;return t.tests[r]={title:n,tests:e,hooks:o},{run:()=>{typeof o.before=="function"&&(t.tBeforeEach=o.before),typeof o.after=="function"&&(t.tAfterEach=o.after),t.runTest(r)},autorun:()=>{typeof o.before=="function"&&(t.tBeforeEach=o.before),typeof o.after=="function"&&(t.tAfterEach=o.after),t.runTest(r,!0)},testId:r}},t.updateLogs=()=>{for(let n=0;n<t.tests.length;n++)t.tLog[n]=t.tLog[testN]=sessionStorage.getItem(`oTest-Log-${testN}`)||"";return t.tLog},t.runTest=(n=0,e,o)=>{if(t.verify([[n,["number"]],[e,["boolean","undefined"]],[o,["boolean","undefined"]]]),!t.tests[n])return;o||(sessionStorage?.removeItem(`oTest-Log-${n}`),sessionStorage?.removeItem(`oTest-Res-${n}`),sessionStorage?.removeItem(`oTest-Status-${n}`)),sessionStorage?.setItem("oTest-Run",n),e?sessionStorage?.setItem("oTest-Autorun",e):sessionStorage?.removeItem("oTest-Autorun");const r=t.tests[n];let c=r.tests.pop();typeof c!="function"&&(r.tests.push(c),c=()=>{}),r.tests.push(w=>{c(w),sessionStorage.setItem("dddd",1),sessionStorage?.removeItem("oTest-Run"),e&&t.runTest(n+1,e)}),t.test(r.title,...r.tests)},t.tPre='<div style="font-family:monospace;text-align:left;">',t.tOk='<span style="background:#cfc;padding: 0 15px;">OK</span> ',t.tXx='<div style="background:#fcc;padding:3px;">',t.tDc="</div>",t.test=(n="",...e)=>{t.verify([[n,["notEmptyString"]],[e,["array"]]]);const o=sessionStorage?.getItem("oTest-Run"),r=o||t.tLog.length;let c=0,w="\u251C OK: ",a="\u251C \u2718 ",h=`
7
+ `,S=`
8
+ `,C="",l=e.length,k=0;const m=(E="",f=!1,v=!1)=>{t.tAutolog&&(f?console.error(E):(t.tShowOk||v)&&console.log(E))};if(typeof e[l-1]=="function"&&(t.tFns[r]=e[l-1],l--),o){t.tLog[r]=sessionStorage.getItem(`oTest-Log-${r}`)||"",t.tRes[r]=sessionStorage.getItem(`oTest-Res-${r}`)||!1,t.tStatus[r]=JSON.parse(sessionStorage.getItem(`oTest-Status-${r}`)||"[]");for(let E=0;E<t.tStatus[r].length;E++){const f=t.tStatus[r][E];(f===!0||f===!1)&&k++}}t.tStyled&&(w=t.tPre+t.tOk,a=t.tPre+t.tXx,h=t.tDc,S=h+h),(!o||t.tLog[r].length===0)&&(m("\u2552 "+n+" #"+r,!1,!0),t.tStyled?t.tLog[r]="<div><b>"+n+" #"+r+"</b></div>":t.tLog[r]="\u2552 "+n+" #"+r+`
9
+ `,t.tRes[r]=t.F,t.tStatus[r]=[]);for(let E=t.tStatus[r].length;E<l;E++){const f={n:r,i:E,title:e[E][0],tShowOk:t.tShowOk,tStyled:t.tStyled};let v=e[E][1];if(typeof v>"u"){t.tStyled?t.tLog[r]+="<div>"+f.title+"</div>":t.tLog[r]+=f.title+`
10
+ `,m("\u251C "+f.title,!1,!0),t.tStatus[r][E]=!0,k++;continue}if(typeof t.tBeforeEach=="function"&&t.tBeforeEach(f),typeof v=="function")try{v=v(f)}catch(u){v=u.message,t.onError&&t.onError(u)}if(typeof t.tAfterEach=="function"&&t.tAfterEach(f,v),v&&typeof v.then=="function"){c++;const u=setTimeout(()=>{f.title+=" (timeout)",t.testUpdate(f)},t.tTime);v.then(y=>{clearTimeout(u);const x=y===!0||y&&y.ok===!0,b=y&&y.errors&&y.errors.length?y.errors.join("; "):typeof y=="string"?y:"";t.testUpdate(f,x,x?"":b?": "+b:"")}).catch(y=>{clearTimeout(u),t.testUpdate(f,!1,y.message||"Promise rejected")});continue}if(typeof t.tStatus[r][E]>"u")t.tStatus[r][E]=typeof v=="string"?t.F:v;else{sessionStorage.setItem(`oTest-Status-${r}`,JSON.stringify(t.tStatus[r]));return}v===!0?(k++,t.tShowOk&&(t.tLog[r]+=w+e[E][0]+h,m("\u251C OK: "+e[E][0]))):v!==t.U?(t.tLog[r]+=a+e[E][0]+(v!==t.F?": "+v:"")+S,m("\u251C \u2718 "+e[E][0]+(v!==t.F?": "+v:""),!0)):(c++,setTimeout(u=>{u.title+=" (timeout)",t.testUpdate(u)},t.tTime,f))}return t.tRes[r]=k===l,C=c?"\u251C ":"\u2558 ",C+="DONE "+k+"/"+l+(c?", waiting: "+c:""),m(C,k+c!==l),c||m(),t.tStyled?t.tLog[r]+=t.tPre+'<div style="color:'+(k+c!==l?"red":"green")+';"><b>DONE '+k+"/"+l+(c?", waiting: "+c:"")+"</b>"+t.tDc+t.tDc:t.tLog[r]+=C+`
11
+ `,o&&(sessionStorage.setItem(`oTest-Log-${r}`,t.tLog[r]),sessionStorage.setItem(`oTest-Res-${r}`,t.tRes[r]),sessionStorage.setItem(`oTest-Status-${r}`,JSON.stringify(t.tStatus[r]))),!c&&typeof t.tFns[r]=="function"&&t.tFns[r](r),r},t.testUpdate=(n,e=t.F,o="")=>{t.verify([[n,["object"]],[e,["boolean","string"]],[o,["string"]]]);let r="";const c=n.n,w=(a="",h=!1)=>{t.tAutolog&&(h?console.error(a):console.log(a))};if(t.tStatus[c][n.i]===t.U||t.tStatus[c][n.i]===null){t.tStatus[c][n.i]=e===!0,e===!0?n.tShowOk&&(r="\u251C OK: "+n.title+o,w(r),n.tStyled?t.tLog[c]+=t.tPre+t.tOk+n.title+o+t.tDc:t.tLog[c]+=r+`
12
+ `):(t.tRes[c]=t.F,r="\u251C \u2718 "+n.title+(e?": "+e:"")+o,w(r,!0),n.tStyled?t.tLog[c]+=t.tPre+t.tXx+n.title+o+(e?": "+e:"")+t.tDc+t.tDc:t.tLog[c]+=r+`
13
+ `);let a=0,h=0;for(const S of t.tStatus[c]){if(S===t.U||S===null)return;S||a++,h++}if(sessionStorage?.getItem("oTest-Run")===c&&(sessionStorage.setItem(`oTest-Log-${c}`,t.tLog[c]),sessionStorage.setItem(`oTest-Res-${c}`,t.tRes[c]),sessionStorage.setItem(`oTest-Status-${c}`,JSON.stringify(t.tStatus[c])),h<t.tests[c].tests.length))return;t.tRes[c]=!a,r=a?"FAILED "+a+"/"+h:"DONE "+h+"/"+h,w("\u2558 "+r,!!a),w(),n.tStyled?t.tLog[c]+=t.tPre+'<b style="color:'+(a?"red":"green")+';">'+r+"</b>"+t.tDc:t.tLog[c]+="\u2558 "+r+`
14
+ `,typeof t.tFns[c]=="function"&&t.tFns[c](c)}},sessionStorage?.getItem("oTest-Run")&&window?.addEventListener("load",()=>{t.runTest(sessionStorage?.getItem("oTest-Run"),sessionStorage?.getItem("oTest-Autorun")||t.F,!0)},!1),t.measure=n=>{if(!n)return{};const e=n.getBoundingClientRect(),o=window.getComputedStyle(n);return{width:e.width,height:e.height,top:e.top,left:e.left,visible:o.display!=="none"&&o.visibility!=="hidden"&&e.width>0,opacity:o.opacity,zIndex:o.zIndex}},t.assertVisible=n=>!!t.measure(n).visible,t.assertSize=(n,e={})=>{if(!n)return"element is null";const o=t.measure(n);if(e.w!==void 0&&Math.round(o.width)!==e.w)return`width: expected ${e.w}, got ${Math.round(o.width)}`;if(e.h!==void 0&&Math.round(o.height)!==e.h)return`height: expected ${e.h}, got ${Math.round(o.height)}`;const r=c=>{const w=window.getComputedStyle(n).getPropertyValue(c);return w?parseFloat(w):0};return e.padding!==void 0&&r("padding-top")!==e.padding?`padding: expected ${e.padding}, got ${r("padding-top")}`:e.paddingTop!==void 0&&r("padding-top")!==e.paddingTop?`paddingTop: expected ${e.paddingTop}, got ${r("padding-top")}`:e.paddingRight!==void 0&&r("padding-right")!==e.paddingRight?`paddingRight: expected ${e.paddingRight}, got ${r("padding-right")}`:e.paddingBottom!==void 0&&r("padding-bottom")!==e.paddingBottom?`paddingBottom: expected ${e.paddingBottom}, got ${r("padding-bottom")}`:e.paddingLeft!==void 0&&r("padding-left")!==e.paddingLeft?`paddingLeft: expected ${e.paddingLeft}, got ${r("padding-left")}`:e.margin!==void 0&&r("margin-top")!==e.margin?`margin: expected ${e.margin}, got ${r("margin-top")}`:e.marginTop!==void 0&&r("margin-top")!==e.marginTop?`marginTop: expected ${e.marginTop}, got ${r("margin-top")}`:e.marginRight!==void 0&&r("margin-right")!==e.marginRight?`marginRight: expected ${e.marginRight}, got ${r("margin-right")}`:e.marginBottom!==void 0&&r("margin-bottom")!==e.marginBottom?`marginBottom: expected ${e.marginBottom}, got ${r("margin-bottom")}`:e.marginLeft!==void 0&&r("margin-left")!==e.marginLeft?`marginLeft: expected ${e.marginLeft}, got ${r("margin-left")}`:!0},t.recorder={active:!1,actions:[],mocks:{},initialData:{},assertions:[],observeRoot:null,_originalFetch:null,_listeners:[],_observer:null},t.startRecording=(n,e,o)=>{if(t.recorder.active)return;const r=["click","mouseover","scroll","input","change"],c={click:100,mouseover:50,scroll:30,input:50,change:50},w=e||r,a=Object.assign({},c,o||{}),h={scroll:30,mouseover:50},S=t.recorder;S.active=!0,S.actions=[],S.mocks={},S.stepDelays=a,S.initialData={url:window.location.href,timestamp:Date.now()},S.observeRoot=n||null,S.assertions=[],t.inits.forEach((f,v)=>{f?.store&&(S.initialData["init_"+v]=JSON.parse(JSON.stringify(f.store)))}),S._originalFetch=window.fetch,window.fetch=async(f,v={})=>{const u=(v.method||"GET").toUpperCase();let y;try{y=v.body?JSON.parse(v.body):void 0}catch{y=v.body}const x=await S._originalFetch(f,v),b=x.clone();let D;try{D=await b.json()}catch{D=await b.text().catch(()=>null)}const I=u+":"+f;return S.mocks[I]={url:f,method:u,request:y,response:D,status:x.status},x};const C={"data-o-init":1,"data-o-init-i":1,"data-o-state":1},l=(f,v)=>{if(t.D.querySelectorAll(f).length<=1)return f;let u=v;for(;u&&u!==t.D.body;){let y=u.id?"#"+u.id:null;if(!y&&u.attributes){const x=t.autotag?"data-"+t.autotag:null;if(x){const b=u.getAttribute(x);b!=null&&(y=`[${x}="${b}"]`)}if(!y){for(const b of u.attributes)if(b.name.startsWith("data-")&&!C[b.name]){y=`[${b.name}="${b.value}"]`;break}}}if(y){const x=y+" "+f;if(t.D.querySelectorAll(x).length===1)return x}u=u.parentElement}return f},k=f=>{if(!f||f.nodeType!==1)return"";let v="";if(f.dataset){const u=t.autotag&&f.dataset[t.autotag];u&&(v=l(`[data-${t.autotag}="${u}"]`,f.parentElement))}if(!v&&f.tagName){const u=f.id?"#"+f.id:f.className?f.tagName.toLowerCase()+"."+[...f.classList].join("."):f.tagName.toLowerCase();v=f.id?u:l(u,f.parentElement)}return v},m=n&&t.D.querySelector(n)||t.D.body;S._observer=new MutationObserver(f=>{const v=S.actions.length-1;v<0||f.forEach(u=>{const y=(x,b)=>{let D,I;if(x&&m&&m.querySelectorAll(x).length>1){let R=b;for(;R&&R!==m&&R.nodeType===1;){const U=t.autotag&&R.dataset&&R.dataset[t.autotag];if(U){const L=`[data-${t.autotag}="${U}"]`,$=m.querySelectorAll(L);if($.length>1){const N=[...$].indexOf(R);if(N!==-1){D=L,I=N;break}}}R=R.parentElement}}return{listSelector:D,index:I}};if(u.type==="childList"&&u.addedNodes.forEach(x=>{if(x.nodeType!==1||!x.offsetParent)return;const b=k(x);if(!b||S.assertions.some(L=>L.actionIdx===v&&L.selector===b&&L.type==="visible"))return;const I=((x.querySelector?.(".task-text")||x).textContent?.trim()||x.textContent?.trim()||"").slice(0,80)||void 0,{listSelector:O,index:R}=y(b,x),U={actionIdx:v,type:"visible",selector:b,text:I};O!=null&&(U.listSelector=O),R!=null&&(U.index=R),S.assertions.push(U)}),u.type==="attributes"){const x=k(u.target);if(!x||S.assertions.some(O=>O.actionIdx===v&&O.selector===x&&O.type==="class"))return;const{listSelector:b,index:D}=y(x,u.target),I={actionIdx:v,type:"class",selector:x,className:u.target.className};b!=null&&(I.listSelector=b),D!=null&&(I.index=D),S.assertions.push(I)}})}),S._observer.observe(m,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["class","style","hidden","disabled","aria-expanded","aria-checked"]});const E={};w.forEach(f=>{const v=u=>{const y=u.target;if(n&&m&&y?.nodeType===1&&!m.contains(y))return;let x="";if(y?.dataset){const N=t.autotag&&y.dataset[t.autotag];N&&(x=l(`[data-${t.autotag}="${N}"]`,y.parentElement))}if(!x&&y?.tagName){const N=y.id?"#"+y.id:y.className?y.tagName.toLowerCase()+"."+[...y.classList].join("."):y.tagName.toLowerCase();x=y.id?N:l(N,y.parentElement)}let b,D;if(x&&m&&m.querySelectorAll(x).length>1){let M=y;for(;M&&M!==m&&M.nodeType===1;){const P=t.autotag&&M.dataset&&M.dataset[t.autotag];if(P){const H=`[data-${t.autotag}="${P}"]`,J=m.querySelectorAll(H);if(J.length>1){const s=[...J].indexOf(M);if(s!==-1){b=H,D=s;break}}}M=M.parentElement}}const I=y?.tagName?y.tagName.toLowerCase()+(y.type?":"+y.type:""):void 0,O=f==="scroll"?window.scrollY:void 0,R=f==="input"||f==="change"?y?.value:void 0,U=f==="change"&&(y?.type==="checkbox"||y?.type==="radio")?y?.checked:void 0,L=a[f]!==void 0?a[f]:h[f]??0,$=()=>{const N={type:f,target:x,time:Date.now()};I&&(N.targetType=I),O!==void 0&&(N.scrollY=O),R!==void 0&&(N.value=R),U!==void 0&&(N.checked=U),b!=null&&(N.listSelector=b),D!=null&&(N.targetIndex=D),S.actions.push(N)};L===0?$():(clearTimeout(E[f]),E[f]=setTimeout($,L))};t.D.addEventListener(f,v,!0),S._listeners.push({ev:f,handler:v})})},t.stopRecording=()=>{const n=t.recorder;return n.active=!1,n._originalFetch&&(window.fetch=n._originalFetch,n._originalFetch=null),n._listeners.forEach(({ev:e,handler:o})=>{t.D.removeEventListener(e,o,!0)}),n._listeners=[],n._observer&&(n._observer.disconnect(),n._observer=null),{actions:[...n.actions],mocks:{...n.mocks},initialData:{...n.initialData},stepDelays:{...n.stepDelays},assertions:[...n.assertions||[]],observeRoot:n.observeRoot||null}},t.clearRecording=n=>{if(n!==void 0)sessionStorage?.removeItem("oTest-Recording-"+n);else for(let e=sessionStorage?.length-1;e>=0;e--){const o=sessionStorage?.key(e);o&&o.indexOf("oTest-Recording-")===0&&sessionStorage?.removeItem(o)}},t.exportTest=n=>{const e=n.actions.map(r=>{let c;return r.type==="scroll"?c=` window.scrollTo(0, ${r.scrollY||0}); return true;
15
+ `:r.type==="input"||r.type==="change"?c=(r.value!==void 0?` el.value = ${JSON.stringify(r.value)};
16
+ `:"")+(r.checked!==void 0?` el.checked = ${r.checked};
17
+ `:"")+` el.dispatchEvent(new Event('${r.type}', {bubbles:true})); return true;
18
+ `:c=r.type==="click"?` el.click(); return true;
19
+ `:` el.dispatchEvent(new MouseEvent('${r.type}', {bubbles:true,cancelable:true})); return true;
20
+ `,` ['${r.type} on ${r.target}', () => {
21
+ const el = document.querySelector('${r.target}');
22
+ if (!el) return 'element not found';
23
+ `+c+" }],"}).join(`
24
+ `);return`// Auto-generated by o.exportTest() \u2014 review and anonymize mocks before committing
25
+ const recordingMocks = ${Object.keys(n.mocks).length?JSON.stringify(n.mocks,null,2):"{}"};
26
+
27
+ o.addTest('Recorded test', [
28
+ ${e}
29
+ ], () => {
30
+ // teardown
31
+ });
32
+ `},t.exportPlaywrightTest=(n,e={})=>{const o=e.testName||"Recorded session",r=n.initialData?.url??"/";let c="/";try{c=new URL(r).pathname||"/"}catch{c=r}const w=e.baseUrl||c,a=Object.values(n.mocks).map(l=>{const k=l.url.startsWith("/")?l.url:"/"+l.url,m=JSON.stringify(l.response);return` await page.route('**${k}', async route => {
33
+ await route.fulfill({ status: ${l.status||200}, contentType: 'application/json',
34
+ body: JSON.stringify(${m}) });
35
+ });`}).join(`
36
+ `),h=Object.assign({click:100,mouseover:50,scroll:30,input:50,change:50},n.stepDelays||{}),S=n.actions.map((l,k)=>{const m=l.listSelector!=null&&l.targetIndex!=null?l.target!==l.listSelector?`page.locator(${JSON.stringify(l.listSelector)}).nth(${l.targetIndex}).locator(${JSON.stringify(l.target)})`:`page.locator(${JSON.stringify(l.listSelector)}).nth(${l.targetIndex})`:`page.locator(${JSON.stringify(l.target)})`,E=` await page.waitForTimeout(${h[l.type]||50});`;let f;if(l.type==="scroll")f=` await page.evaluate(() => window.scrollTo(0, ${l.scrollY||0}));`;else if(l.type==="mouseover")f=` await ${m}.hover();
37
+ // Pure CSS :hover \u2014 no DOM mutation to assert.
38
+ // Fix: toggle a class in a mouseover handler, or add a page.screenshot() visual check.`;else if(l.type==="input")f=` await ${m}.fill(${JSON.stringify(l.value||"")});`;else if(l.type==="change"){const u=l.targetType||"";if(u.indexOf(":checkbox")!==-1||u.indexOf(":radio")!==-1){const y=l.checked!==void 0?l.checked:l.value==="true"||l.value==="on";f=` await ${m}.${y?"check":"uncheck"}();`}else u.indexOf("select")!==-1?f=` await ${m}.selectOption(${JSON.stringify(l.value||"")});`:f=` await ${m}.fill(${JSON.stringify(l.value||"")});`}else f=` await ${m}.click();`;const v=(n.assertions||[]).filter(u=>u.actionIdx===k).filter((u,y,x)=>x.findIndex(b=>b.selector===u.selector&&b.type===u.type&&b.index===u.index)===y).map(u=>{const y=u.listSelector!=null&&u.index!=null?u.selector!==u.listSelector?`page.locator(${JSON.stringify(u.listSelector)}).nth(${u.index}).locator(${JSON.stringify(u.selector)})`:`page.locator(${JSON.stringify(u.listSelector)}).nth(${u.index})`:`page.locator(${JSON.stringify(u.selector)})`;if(u.type==="visible"){let x=` await expect(${y}).toBeVisible();`;return u.text&&(x+=`
39
+ await expect(${y}).toContainText(${JSON.stringify(u.text)});`),x}return u.type==="class"?` // class on ${u.selector} changed to: "${u.className}"`:""}).filter(Boolean).join(`
40
+ `);return f+`
41
+ `+E+(v?`
42
+ `+v:"")}).join(`
43
+ `),C=(n.assertions||[]).length>0;return`// Auto-generated by o.exportPlaywrightTest() \u2014 review and anonymize mocks before committing
44
+ // Prerequisites: npm install @playwright/test && npx playwright install chromium
45
+ // Run: npx playwright test recorded.spec.ts
46
+ import { test, expect } from '@playwright/test';
47
+
48
+ test(${JSON.stringify(o)}, async ({ page }) => {
49
+ `+(a?` // Network mocks \u2014 edit/anonymize before committing
50
+ `+a+`
51
+
52
+ `:"")+` // Set baseURL in playwright.config.ts: { use: { baseURL: 'https://staging.example.com' } }
53
+ await page.goto(${JSON.stringify(w)});
54
+
55
+ `+(S?S+`
56
+
57
+ `:"")+(C?` // Auto-generated assertions above \u2014 review for correctness before committing
58
+ `:` // TODO: Add assertions before committing, e.g.:
59
+ // await expect(page.locator('[data-qa="success-panel"]')).toBeVisible();
60
+ // await expect(page).toHaveURL(/\\/confirmation/);
61
+ // await expect(page.locator('[data-qa="error-banner"]')).not.toBeVisible();
62
+ `)+`});
63
+ `},t.playRecording=(n,e={})=>{const o=Object.assign({},n.mocks,e),r=window.fetch;window.fetch=(a,h={})=>{const C=(h.method||"GET").toUpperCase()+":"+a;if(o[C]){const l=o[C],k=typeof l.response=="string"?l.response:JSON.stringify(l.response);return Promise.resolve(new Response(k,{status:l.status||200}))}return r(a,h)};const c=n.actions.map(a=>[`${a.type} on ${a.target}`,()=>{let h=null;if(a.target)if(a.listSelector!=null&&a.targetIndex!=null){const C=t.D.querySelectorAll(a.listSelector)[a.targetIndex];C&&(h=a.target!==a.listSelector?C.querySelector(a.target):C,!h&&a.target!==a.listSelector&&(h=C))}else h=t.D.querySelector(a.target);return!h&&a.type!=="scroll"?`element not found: ${a.target}`:(a.type==="scroll"?window.scrollTo(0,a.scrollY||0):a.type==="input"||a.type==="change"?(a.value!==void 0&&(h.value=a.value),a.checked!==void 0&&(h.checked=a.checked),h.dispatchEvent(new Event(a.type,{bubbles:!0}))):a.type==="click"?h.click():h.dispatchEvent(new MouseEvent(a.type,{bubbles:!0,cancelable:!0})),!0)}]);return t.test("Recorded playback",...c,()=>{window.fetch=r})},t.testOverlay=()=>{const n="o-test-overlay-btn",e="o-test-overlay-panel";if(t("#"+n).el)return;const o=()=>{const l=t("#"+e);if(!l.el)return;const k=t.tRes.length;let E=`<b>Tests: ${t.tRes.filter(Boolean).length}/${k}</b><hr style="margin:4px 0">`;t.tLog.forEach((f,v)=>{const u=t.tRes[v];E+=`<div style="margin:2px 0;padding:2px 4px;border-radius:3px;background:${u?"#d4edda":"#f8d7da"};color:${u?"#155724":"#721c24"};font-size:11px;white-space:pre-wrap">${f||"Test #"+v}</div>`}),E+='<button id="o-test-export" style="margin-top:6px;padding:4px 8px;font-size:11px;cursor:pointer">Export results</button>',l.html(E),t("#o-test-export").on("click",()=>{const f=JSON.stringify({results:t.tRes,logs:t.tLog},null,2),v=new Blob([f],{type:"application/json"}),u=t.D.createElement("a");u.href=URL.createObjectURL(v),u.download="objs-test-results.json",u.click()})},r={position:"fixed",left:"50%",bottom:"50px",transform:"translateX(-50%)","z-index":"999999",width:"fit-content","max-width":"min(90vw, 420px)","font-family":"system-ui,sans-serif",cursor:"grab","user-select":"text"},c=t.initState({tag:"div",id:n,className:"o-test-overlay",style:"position:fixed;left:50%;bottom:50px;transform:translateX(-50%);z-index:999999;width:fit-content;max-width:min(90vw,420px);font-family:system-ui,sans-serif;cursor:grab;user-select:text;",html:`<div class="o-test-overlay-bar" style="display:flex;flex-direction:column;align-items:stretch;padding:10px 14px;background:#1e293b;color:#e2e8f0;border:1px solid #334155;border-radius:8px;font-size:14px;cursor:grab;min-width:200px;"><div style="display:flex;align-items:center;gap:12px;"><span class="o-test-overlay-summary" style="flex:1;font-size:13px;">Tests: 0/0</span><button type="button" class="o-test-overlay-toggle" style="padding:6px 10px;background:#334155;color:#e2e8f0;border:none;border-radius:6px;cursor:pointer;font-size:12px;">List</button><button type="button" class="o-test-overlay-close" style="padding:4px 8px;background:transparent;color:#94a3b8;border:none;border-radius:4px;cursor:pointer;font-size:16px;line-height:1;" title="Close">\xD7</button></div></div><div id="${e}" style="display:none;margin-top:4px;padding:8px;background:#fff;border:1px solid #334155;border-radius:6px;max-height:60vh;overflow-y:auto;box-shadow:0 2px 8px rgba(0,0,0,.15);font-size:11px;user-select:text;cursor:text;"></div>`}).appendInside("body"),w=()=>{c.css(r)};let a=null;const h=l=>{a&&(r.left=a.left+(l.clientX-a.startX)+"px",r.top=a.top+(l.clientY-a.startY)+"px",delete r.bottom,r.transform="none",w())},S=()=>{a&&(r.cursor="grab",w()),a=null};c.on("mousedown",l=>{if(l.target.closest(".o-test-overlay-close")||l.target.closest(".o-test-overlay-toggle")||l.target.closest("#"+e))return;const k=c.el.getBoundingClientRect();a={startX:l.clientX,startY:l.clientY,left:k.left,top:k.top},r.cursor="grabbing",w()}),t.D.addEventListener("mousemove",h),t.D.addEventListener("mouseup",S);const C=()=>{const l=t(".o-test-overlay-summary");l.els.length&&l.innerText(`Tests: ${t.tRes.filter(Boolean).length}/${t.tRes.length}`)};c.first(".o-test-overlay-toggle").on("click",()=>{const l=t("#"+e);if(!l.el)return;const k=l.el.style.display!=="none";l.css({display:k?"none":"block"}),k||o()}),c.first(".o-test-overlay-close").on("click",()=>{t.D.removeEventListener("mousemove",h),t.D.removeEventListener("mouseup",S),c.remove()}),t.testOverlay.showPanel=()=>{const l=t("#"+e);l.el&&(l.css({display:"block"}),o(),C())},t._testOverlayBase||(t._testOverlayBase=t.test),t.test=(...l)=>{const k=t._testOverlayBase(...l),m=t.tFns[k];return t.tFns[k]=E=>{typeof m=="function"&&m(E);const f=t("#"+e);f.el&&f.el.style.display!=="none"&&o(),C()},k}},t.testConfirm=(n,e=[],o={})=>new Promise(r=>{t(".o-tc-overlay").remove();const c=o.confirm||"Continue",w=e.length>0,a=w?"#dc2626":"#2563eb",h=e.map((y,x)=>"o-tc-cb-"+x),C=w?`<style>.o-tc-item-cb{appearance:none;-webkit-appearance:none;width:16px;height:16px;border:2px solid #ef4444;border-radius:3px;background:#fef2f2;flex-shrink:0;cursor:pointer;}.o-tc-item-cb:checked{border-color:#22c55e;background:#22c55e;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");background-size:12px 12px;background-position:center;}</style><ul class="o-tc-list" style="margin:8px 0 0;padding:0;list-style:none;font-size:13px;color:#cbd5e1;">`+e.map((y,x)=>`<li style="margin-bottom:4px;"><label for="${h[x]}" style="display:flex;align-items:center;gap:8px;cursor:pointer;user-select:none;"><input type="checkbox" id="${h[x]}" class="o-tc-item-cb"> <span>${y}</span></label></li>`).join("")+"</ul>":"",l=t.initState({tag:"div",className:"o-tc-overlay",style:"position:fixed;left:50%;bottom:50px;transform:translateX(-50%);z-index:999999;width:fit-content;max-width:min(90vw,400px);font-family:system-ui,sans-serif;cursor:grab;user-select:text;",html:`<div class="o-tc-bar" style="display:flex;flex-direction:column;align-items:stretch;padding:10px 14px;background:#1e293b;color:#e2e8f0;border:1px solid #334155;border-radius:8px;font-size:14px;cursor:grab;min-width:280px;"><div style="display:flex;align-items:center;gap:12px;"><span class="o-tc-label" style="flex:1;">${n}: Paused</span><button type="button" class="o-tc-ok" style="padding:6px 14px;background:${a};color:#fff;border:none;border-radius:6px;font-weight:600;cursor:pointer;font-size:13px;flex-shrink:0;">${c}</button></div>`+C+"</div>"}).appendInside("body"),k={padding:"6px 14px",background:w?"#dc2626":"#2563eb",color:"#fff",border:"none","border-radius":"6px","font-weight":"600",cursor:"pointer","font-size":"13px","flex-shrink":"0"};if(w){const y=l.first(".o-tc-ok"),x=t(".o-tc-overlay .o-tc-item-cb"),b=()=>{const D=x.length>0&&x.els.every(I=>I.checked);y.css({...k,background:D?"#16a34a":"#dc2626"})};x.on("change",b)}let m=null;const E={position:"fixed",left:"50%",bottom:"50px",transform:"translateX(-50%)","z-index":"999999",width:"fit-content","max-width":"min(90vw, 400px)","font-family":"system-ui,sans-serif",cursor:"grab","user-select":"text"},f=()=>{l.css(E)},v=y=>{m&&(E.left=m.left+(y.clientX-m.startX)+"px",E.top=m.top+(y.clientY-m.startY)+"px",delete E.bottom,E.transform="none",f())},u=()=>{m&&(E.cursor="grab",f()),m=null};l.on("mousedown",y=>{if(y.target.closest(".o-tc-ok"))return;const x=l.el.getBoundingClientRect();m={startX:y.clientX,startY:y.clientY,left:x.left,top:x.top},E.cursor="grabbing",f()}),t.D.addEventListener("mousemove",v),t.D.addEventListener("mouseup",u),l.first(".o-tc-ok").on("click",()=>{t.D.removeEventListener("mousemove",v),t.D.removeEventListener("mouseup",u);let y=[];w&&t(".o-tc-overlay .o-tc-item-cb").els.forEach((b,D)=>{!b.checked&&e[D]!==void 0&&y.push(e[D])}),l.remove(),y.length===0?r({ok:!0}):r({ok:!1,errors:y})})});
64
+
65
+ export { o };
66
+ export default o;
67
+ if (typeof window !== "undefined") window.o = o;
package/objs.d.ts ADDED
@@ -0,0 +1,455 @@
1
+ /**
2
+ * Objs-core v2.0 TypeScript definitions
3
+ * @license Apache-2.0
4
+ */
5
+
6
+ // ─── Core instance types ──────────────────────────────────────────────────
7
+
8
+ /** State definition object for o.init(). `render` is the reserved creation state. */
9
+ export interface StateObject {
10
+ tag?: string;
11
+ tagName?: string;
12
+ /** Component name — used for o.autotag data-* attribute (camelCase → kebab-case) */
13
+ name?: string;
14
+ class?: string;
15
+ /** React-style alias for `class` */
16
+ className?: string;
17
+ id?: string;
18
+ html?: string;
19
+ innerHTML?: string;
20
+ style?: string | Record<string, string>;
21
+ dataset?: Record<string, string>;
22
+ events?: Record<string, EventListener>;
23
+ [attr: string]: unknown;
24
+ }
25
+
26
+ /** Parameter object passed to every state function.
27
+ *
28
+ * State functions receive ONE merged object: { ...passedProps, self, o, i, parent, data }.
29
+ * - Properties from the calling argument are spread into the context.
30
+ * - `data` holds the raw first argument (useful for primitives: `comp.setState(5)` → `data = 5`).
31
+ * - `parent` is the ObjsInstance that this component was `appendInside()` into (if any).
32
+ *
33
+ * @example
34
+ * // Passing an object — destructure its keys:
35
+ * sync: ({ self, values, errors }) => { ... } // comp.sync(store)
36
+ * // Passing a primitive — use `data`:
37
+ * setCount: ({ self, data }) => { self.html(data); } // comp.setCount(5)
38
+ */
39
+ export interface StateParams {
40
+ self: ObjsInstance;
41
+ o: typeof o;
42
+ i: number;
43
+ /** The ObjsInstance this component was appendInside() into, or null */
44
+ parent: ObjsInstance | null;
45
+ /** The raw first argument passed when the state method was called */
46
+ data: unknown;
47
+ [key: string]: unknown;
48
+ }
49
+
50
+ /** State function signature */
51
+ export type StateFunction = (params: StateParams) => void | unknown;
52
+
53
+ /** States map passed to o.init() */
54
+ export type StatesMap = {
55
+ render?: StateObject | StateFunction | string;
56
+ [stateName: string]: StateObject | StateFunction | string | undefined;
57
+ };
58
+
59
+ /** Test case tuple: [title, testFn | true | false | string] */
60
+ export type TestCase = [string, ((info: TestInfo) => boolean | string | undefined) | boolean | string | undefined];
61
+
62
+ export interface TestInfo {
63
+ n: number;
64
+ i: number;
65
+ title: string;
66
+ tShowOk: boolean;
67
+ tStyled: boolean;
68
+ }
69
+
70
+ /** Object returned by o.addTest() */
71
+ export interface TestHandle {
72
+ testId: number;
73
+ run(): void;
74
+ autorun(): void;
75
+ }
76
+
77
+ /** Object returned by o.newLoader() */
78
+ export interface ObjsLoader<T = unknown> {
79
+ reload(promise: Promise<T>): void;
80
+ isObjsLoader: true;
81
+ listeners: Array<[ObjsInstance, string, string?]>;
82
+ isFinished(): boolean;
83
+ getStore(): T | null;
84
+ connect(listener: ObjsInstance, state?: string, fail?: string): void;
85
+ disconnect(listener: ObjsInstance): void;
86
+ }
87
+
88
+ /** Element measurement result from o.measure() */
89
+ export interface MeasureResult {
90
+ width: number;
91
+ height: number;
92
+ top: number;
93
+ left: number;
94
+ visible: boolean;
95
+ opacity: string;
96
+ zIndex: string;
97
+ }
98
+
99
+ /** Recorded action entry */
100
+ export interface RecordedAction {
101
+ type: string;
102
+ target: string;
103
+ time: number;
104
+ scrollY?: number;
105
+ value?: string;
106
+ /** When target matches multiple elements, selector for the repeated list item container */
107
+ listSelector?: string;
108
+ /** Index within listSelector matches for replay by index */
109
+ targetIndex?: number;
110
+ }
111
+
112
+ export type Assertion = {
113
+ actionIdx: number;
114
+ type: 'visible' | 'class';
115
+ selector: string;
116
+ text?: string;
117
+ className?: string;
118
+ /** When selector matches multiple, selector for the list item container */
119
+ listSelector?: string;
120
+ /** Index within listSelector matches */
121
+ index?: number;
122
+ };
123
+
124
+ /** Full recording object */
125
+ export interface Recording {
126
+ actions: RecordedAction[];
127
+ mocks: Record<string, { url: string; method: string; request: unknown; response: unknown; status: number }>;
128
+ initialData: Record<string, unknown>;
129
+ stepDelays?: Record<string, number>;
130
+ assertions: Assertion[];
131
+ observeRoot: string | null;
132
+ }
133
+
134
+ /**
135
+ * Reactive store returned by o.createStore().
136
+ * Components subscribe via store.subscribe(component, stateName).
137
+ * When store.notify() is called, each subscribed component's state method
138
+ * receives the full store object, whose properties are merged into the
139
+ * state context: { ...storeProps, self, o, i, parent, data }.
140
+ */
141
+ export interface ObjsStore<T extends object = Record<string, unknown>> {
142
+ _listeners: Array<(store: this) => void>;
143
+ /** Subscribe an Objs component state to this store.
144
+ * On every notify(), component[stateName](store) is called. */
145
+ subscribe(component: ObjsInstance, stateName: string): this;
146
+ /** Notify all subscribers — passes `this` store as the argument. */
147
+ notify(): void;
148
+ /** Restore store data from initial defaults; does not replace subscribe, notify, _listeners. */
149
+ reset(): void;
150
+ }
151
+
152
+ // ─── ObjsInstance (chainable result of o() / o.init()) ────────────────────
153
+
154
+ export interface ObjsInstance {
155
+ // Properties
156
+ els: Element[];
157
+ el: Element | undefined;
158
+ last: Element | undefined;
159
+ length: number;
160
+ initID: number | undefined;
161
+ ie: Record<string, Array<[EventListener, unknown?, unknown?]>>;
162
+ delegated: Record<string, EventListener[]>;
163
+ store: Record<string, unknown>;
164
+ states: string[];
165
+ isDebug: boolean;
166
+ currentState: string;
167
+ savedStates: Record<string, unknown>;
168
+ isRoot: boolean;
169
+ /** The ObjsInstance this component was appendInside() into, or null */
170
+ _parent: ObjsInstance | null;
171
+ /**
172
+ * Named sub-elements collected from `ref="name"` attributes in the rendered HTML.
173
+ * Populated automatically on first render; `ref` attributes are removed from the DOM.
174
+ * @example
175
+ * // In render: html: `<div ref="body"></div>`
176
+ * // After render: component.refs.body → ObjsInstance wrapping that div
177
+ */
178
+ refs: Record<string, ObjsInstance>;
179
+
180
+ // Selection
181
+ reset(query: QueryArg): ObjsInstance;
182
+ select(i?: number): ObjsInstance;
183
+ all(): ObjsInstance;
184
+ find(query: string): ObjsInstance;
185
+ first(query?: string): ObjsInstance;
186
+ add(el: QueryArg): ObjsInstance;
187
+ skip(i?: number): ObjsInstance;
188
+ remove(i?: number): ObjsInstance;
189
+
190
+ // State
191
+ init(states: StatesMap | StateFunction | string): ObjsInstance;
192
+ initState(state: StateObject, props?: Record<string, unknown>): ObjsInstance;
193
+ sample(state?: string): StatesMap;
194
+ saveState(stateId?: string, root?: boolean): ObjsInstance;
195
+ revertState(stateId?: string): ObjsInstance;
196
+ loseState(stateId: string): ObjsInstance;
197
+
198
+ // DOM manipulation
199
+ html(html?: string): string | ObjsInstance;
200
+ innerHTML(html?: string): string[] | ObjsInstance;
201
+ innerText(text: string): ObjsInstance;
202
+ textContent(content: string): ObjsInstance;
203
+ val(value?: string): string | ObjsInstance;
204
+ attr(attr: string, value?: string | null): string | string[] | ObjsInstance;
205
+ attrs(): Record<string, string> | Array<Record<string, string>>;
206
+ dataset(values?: Record<string, string>): Record<string, string> | Array<Record<string, string>> | ObjsInstance;
207
+ style(value?: string | null): ObjsInstance;
208
+ css(styles: Record<string, string> | null): ObjsInstance;
209
+ setClass(value: string): ObjsInstance;
210
+ addClass(...cls: string[]): ObjsInstance;
211
+ removeClass(...cls: string[]): ObjsInstance;
212
+ toggleClass(cls: string, rule?: boolean): ObjsInstance;
213
+ haveClass(cls: string): boolean;
214
+
215
+ // Events
216
+ on(events: string, handler: EventListener, options?: EventListenerOptions): ObjsInstance;
217
+ off(events: string, handler: EventListener, options?: EventListenerOptions): ObjsInstance;
218
+ offAll(event?: string): ObjsInstance;
219
+ onAll(event?: string): ObjsInstance;
220
+ onDelegate(events: string, selector: string, handler: EventListener): ObjsInstance;
221
+ offDelegate(event?: string): ObjsInstance;
222
+ onParent(events: string, selectorOrEl: string | Element, handler: EventListener): ObjsInstance;
223
+ offParent(events: string, query: string): ObjsInstance;
224
+
225
+ // DOM insertion
226
+ appendInside(el: QueryArg): ObjsInstance;
227
+ appendBefore(el: QueryArg): ObjsInstance;
228
+ appendAfter(el: QueryArg): ObjsInstance;
229
+
230
+ // Misc
231
+ forEach(fn: (ctx: { o: typeof o; self: ObjsInstance; i: number; el: Element }) => void): ObjsInstance;
232
+ connect(loader: ObjsLoader, state?: string, fail?: string): ObjsInstance;
233
+ getSSR(initId?: number): ObjsInstance;
234
+ saveAs(key: string): ObjsInstance;
235
+ unmount(): boolean;
236
+ take(query: QueryArg): ObjsInstance;
237
+
238
+ // React
239
+ prepareFor(createElement: Function, component?: Function): unknown;
240
+
241
+ // Debug (behind __DEV__ in build)
242
+ debug?: () => ObjsInstance;
243
+
244
+ // Dynamic state methods added by init()
245
+ render?: (props?: Record<string, unknown> | Array<Record<string, unknown>>) => ObjsInstance;
246
+ [stateName: string]: unknown;
247
+ }
248
+
249
+ type QueryArg = string | Element | Element[] | ObjsInstance | number;
250
+
251
+ // ─── o() function and static API ─────────────────────────────────────────
252
+
253
+ declare function o(query?: QueryArg): ObjsInstance;
254
+
255
+ declare namespace o {
256
+ // Core
257
+ const inits: ObjsInstance[];
258
+ const getSaved: Record<string, ObjsInstance>;
259
+ const errors: Error[];
260
+ let debug: boolean;
261
+ let showErrors: boolean;
262
+ function logErrors(): void;
263
+ function onError(error: Error, name?: string): void;
264
+ function reactRender(...args: unknown[]): unknown;
265
+
266
+ // Autotag
267
+ let autotag: string | undefined;
268
+
269
+ function reactQA(componentName: string): Record<string, string>;
270
+
271
+ // Element selection
272
+ function first(query: string): ObjsInstance;
273
+ function take(query: QueryArg): ObjsInstance;
274
+
275
+ // State
276
+ function init(states: StatesMap | StateFunction | string): ObjsInstance;
277
+ function initState(state: StateObject, props?: Record<string, unknown>): ObjsInstance;
278
+ function getStates(): (string[] | undefined)[];
279
+ function getStores(): (Record<string, unknown> | undefined)[];
280
+ function getListeners(): (Record<string, unknown> | undefined)[];
281
+
282
+ /**
283
+ * Create a reactive store — plain object with built-in subscribe / notify.
284
+ * Components subscribed via store.subscribe(comp, 'state') receive the store
285
+ * as their merged state context: { ...storeProps, self, o, i, parent, data }.
286
+ * @example
287
+ * const store = o.createStore({ count: 0, inc() { this.count++; this.notify(); } });
288
+ * store.subscribe(badge, 'sync'); // badge.sync(store) on every notify
289
+ */
290
+ function createStore<T extends object>(defaults: T): T & ObjsStore<T>;
291
+
292
+ // AJAX
293
+ function ajax(url: string, props?: Record<string, unknown>): Promise<Response>;
294
+ function get(url: string, props?: Record<string, unknown>): Promise<Response>;
295
+ function post(url: string, props?: Record<string, unknown>): Promise<Response>;
296
+ function getParams(key?: string): Record<string, string> | string;
297
+
298
+ // Loader
299
+ function newLoader<T = unknown>(promise?: Promise<T>): ObjsLoader<T>;
300
+
301
+ // Include
302
+ let incCache: boolean;
303
+ let incCacheExp: number;
304
+ let incTimeout: number;
305
+ let incSource: string;
306
+ let incForce: boolean;
307
+ let incAsync: boolean;
308
+ let incCors: boolean;
309
+ let incFns: Record<string, number>;
310
+ function inc(sources: Record<string, string>, callBack?: (setId: number) => void, callBad?: (setId: number) => void): number;
311
+ function incCheck(set?: number, fnId?: number, loaded?: number): boolean;
312
+ function incCacheClear(all?: boolean): boolean;
313
+
314
+ // Routing
315
+ function route(path: string | boolean | ((path: string) => boolean), task?: Function | object): boolean | object;
316
+ function router(routes: Record<string, Function | object>): boolean;
317
+
318
+ // Cookies
319
+ function setCookie(title: string, value?: string | number | boolean, params?: Record<string, unknown>): void;
320
+ function getCookie(title: string): string | undefined;
321
+ function deleteCookie(title: string): void;
322
+ function clearCookies(): void;
323
+ /** Clear cookies, localStorage, and test-related sessionStorage. Call after Cookies/LS/SS tests. */
324
+ function clearAfterTests(): void;
325
+
326
+ // Storage
327
+ function clearLocalStorage(all?: boolean): void;
328
+ function clearSessionStorage(onlyTests?: boolean): void;
329
+ function clearTestsStorage(): void;
330
+
331
+ // Utilities
332
+ function camelToKebab(str: string): string;
333
+ function kebabToCamel(str: string): string;
334
+ function verify(pairs: Array<[unknown, string | string[]]>, safe?: boolean): boolean | Error;
335
+ function safeVerify(pairs: Array<[unknown, string | string[]]>): boolean;
336
+ const C: (obj: object, key: string) => boolean;
337
+ const F: false;
338
+ const U: undefined;
339
+
340
+ // Store adapters (always present, prod + dev)
341
+ function connectRedux<S = unknown>(
342
+ store: { getState(): S; subscribe(listener: () => void): () => void },
343
+ selector: (state: S) => unknown,
344
+ component: ObjsInstance,
345
+ state?: string
346
+ ): () => void;
347
+
348
+ function connectMobX<T = unknown>(
349
+ mobx: { autorun(fn: () => void): () => void },
350
+ observable: T,
351
+ accessor: (obs: T) => unknown,
352
+ component: ObjsInstance,
353
+ state?: string
354
+ ): () => void;
355
+
356
+ let ObjsContext: unknown;
357
+
358
+ function withReactContext<C = unknown>(
359
+ React: { useContext(ctx: unknown): C; useEffect(fn: () => void, deps: unknown[]): void },
360
+ Context: unknown,
361
+ selector: (value: C) => unknown,
362
+ component: ObjsInstance,
363
+ state?: string
364
+ ): () => null;
365
+
366
+ // SSR
367
+ const DocumentMVP: {
368
+ createElement(tag: string): unknown;
369
+ addEventListener(): void;
370
+ parseElement(elem: unknown, outer?: boolean): string;
371
+ };
372
+ let D: Document | typeof DocumentMVP;
373
+
374
+ const recorder: {
375
+ active: boolean;
376
+ actions: RecordedAction[];
377
+ mocks: Recording['mocks'];
378
+ initialData: Record<string, unknown>;
379
+ assertions: Assertion[];
380
+ observeRoot: string | null;
381
+ _observer: MutationObserver | null;
382
+ };
383
+ /**
384
+ * Start recording user interactions.
385
+ * Available in all builds — QA testers can record on staging/production.
386
+ * @param observe CSS selector to scope the MutationObserver (reduces assertion noise)
387
+ * @param events Events to record (default: click, mouseover, scroll, input, change)
388
+ * @param timeouts Debounce delays per event type in ms
389
+ */
390
+ function startRecording(observe?: string, events?: string[], timeouts?: Record<string, number>): void;
391
+ function stopRecording(): Recording;
392
+ function clearRecording(id?: number): void;
393
+ function exportTest(recording: Recording): string;
394
+ function exportPlaywrightTest(
395
+ recording: Recording,
396
+ options?: { testName?: string; baseUrl?: string }
397
+ ): string;
398
+
399
+ // Test framework
400
+ let tLog: string[];
401
+ let tRes: boolean[];
402
+ let tStatus: Array<Array<boolean | undefined>>;
403
+ let tFns: Array<((testN: number) => void) | undefined>;
404
+ let tShowOk: boolean;
405
+ let tStyled: boolean;
406
+ let tTime: number;
407
+ let tests: Array<{ title: string; tests: TestCase[]; hooks: { before?: Function; after?: Function } }>;
408
+ let tAutolog: boolean;
409
+ let tBeforeEach: ((info: TestInfo) => void) | undefined;
410
+ let tAfterEach: ((info: TestInfo, result: unknown) => void) | undefined;
411
+
412
+ function test(title: string, ...cases: Array<TestCase | (() => void)>): number;
413
+ function addTest(title: string, ...cases: Array<TestCase | { before?: Function; after?: Function }>): TestHandle;
414
+ function runTest(testId?: number, autoRun?: boolean, savePrev?: boolean): void;
415
+ function testUpdate(info: TestInfo, result?: boolean | string, suffix?: string): void;
416
+ function updateLogs(): string[];
417
+
418
+ // Measurements
419
+ function measure(el: Element): MeasureResult;
420
+ function assertVisible(el: Element): boolean;
421
+ /** Expected size/padding/margin for design system or UI verification. All values in px. */
422
+ function assertSize(
423
+ el: Element,
424
+ expected?: {
425
+ w?: number;
426
+ h?: number;
427
+ padding?: number;
428
+ paddingTop?: number;
429
+ paddingRight?: number;
430
+ paddingBottom?: number;
431
+ paddingLeft?: number;
432
+ margin?: number;
433
+ marginTop?: number;
434
+ marginRight?: number;
435
+ marginBottom?: number;
436
+ marginLeft?: number;
437
+ }
438
+ ): boolean | string;
439
+
440
+ // Dev-only replay + overlay (depend on o.test framework)
441
+ function playRecording(recording: Recording, mockOverrides?: Recording['mocks']): number;
442
+ function testOverlay(): void;
443
+ /**
444
+ * Pause an Objs browser test; shows a draggable bar with "Test title: Paused", optional checklist (labels + checkboxes), and Continue.
445
+ * Dev-only. Returns ok: true if all items checked; ok: false with errors = list of unchecked item texts.
446
+ */
447
+ function testConfirm(
448
+ label: string,
449
+ items?: string[],
450
+ opts?: { confirm?: string }
451
+ ): Promise<{ ok: boolean; errors?: string[] }>;
452
+ }
453
+
454
+ export { o };
455
+ export default o;