olova 1.0.23 → 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.
Files changed (3) hide show
  1. package/README.md +38 -49
  2. package/dist/olova.js +1139 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,65 +1,54 @@
1
- # olova
1
+ # Olova JavaScript Framework
2
2
 
3
- ## Example
3
+ Olova is a lightweight and reactive JavaScript framework that simplifies UI
4
+ development with a clean, intuitive syntax. It provides a reactivity system and
5
+ hooks to manage state and side effects, allowing developers to build modern web
6
+ applications with ease.
4
7
 
5
- ```html
6
- <div id="app">
7
- <template>
8
- <div>
9
- <div>{ count }</div>
10
- <button @click="increment">Increment</button>
11
- </div>
12
- </template>
13
- </div>
8
+ ## Features
14
9
 
15
- <script type="module">
16
- import { createApp } from "//unpkg.com/olova";
17
-
18
- const app = createApp({
19
- data: {
20
- count: 0,
21
- },
22
- methods: {
23
- increment() {
24
- this.count++;
25
- },
26
- },
27
- });
28
- app.mount("#app");
29
- </script>
30
- ```
10
+ - **State Management**: Use the `State` hook to manage reactive state in your
11
+ components.
12
+ - **Side Effects**: Use the `Effect` hook to run side effects in response to
13
+ state changes.
14
+ - **JSX-style Syntax**: Write UI components using a simple, declarative
15
+ JSX-style syntax.
16
+ - **Reactivity**: Automatically re-render components when state changes.
31
17
 
32
18
  ## Installation
33
19
 
20
+ To get started with Olova, first install the core library via npm or yarn.
21
+
34
22
  ```bash
35
23
  npm install olova
36
24
  ```
37
25
 
38
- ## Usage
26
+ or
39
27
 
40
- ```js
41
- import { createApp } from "olova";
28
+ ```bash
29
+ yarn add olova
42
30
  ```
43
31
 
44
- ```js
45
- const app = createApp({
46
- data: {
47
- count: 0,
48
- },
49
- methods: {
50
- increment() {
51
- this.count++;
52
- },
53
- },
54
- template: `
55
- <div>
56
- <div>{ count }</div>
57
- <button @click="increment">Increment</button>
58
- </div>
59
- `,
60
- });
61
- ```
32
+ ## Example Usage
33
+
34
+ Here is an example of a basic component in Olova:
62
35
 
63
36
  ```js
64
- app.mount("#app");
37
+ import Olova, { State, Effect } from "olova";
38
+
39
+ export default function Home() {
40
+ const [count, setCount] = State(0);
41
+
42
+ Effect(() => {
43
+ console.log("Home is rendered");
44
+ console.log(count);
45
+ }, [count]);
46
+
47
+ return (
48
+ <>
49
+ <h1>{count}</h1>
50
+ <button onClick={() => setCount(count + 1)}>Increment</button>
51
+ </>
52
+ );
53
+ }
65
54
  ```
package/dist/olova.js CHANGED
@@ -1 +1,1139 @@
1
- const createApp=({data:e={},computed:t={},methods:r={},watch:n={},mounted:o,beforeMount:a,beforeUpdate:i,template:c,plugins:s=[],components:l={},mixins:u=[],directives:d={}}={})=>{let f;const h={},p={},m={},y={},E={...d},b=new Map,v=new Map,w=new Map,g=(e,t)=>{v.set(e.toLowerCase(),t);const r=t({});if(r.styles){const t=`olova-component-${e}`;if(!document.getElementById(t)){const e=document.createElement("style");e.id=t,e.textContent=r.styles,document.head.appendChild(e)}w.set(e,t)}},A=(e,t)=>{E[e]=t},T=e=>new Proxy(e,{get:(e,t)=>"object"==typeof e[t]&&null!==e[t]?T(e[t]):e[t],set:(e,t,r)=>(e[t]!==r&&(e[t]=r,$(t)),!0)});Error;class C extends Error{constructor(e){super(e),this.name="StateError"}}const L="undefined"!=typeof process&&"production"===process.env?.NODE_ENV,x=(e,t,r=Error)=>function(...n){try{return e.apply(this,n)}catch(e){if(L)return void(e=>{console.error("[Olova Error]:",e)})(e);throw new r(`${t}: ${e.message}`)}};a&&x(a,"Error in beforeMount hook",C).call(H);new Set;const M=e=>{h[e]&&h[e].forEach(x((t=>{t.node?t.node.textContent=t.originalText.replace(/\{(.*?)\}/g,((e,t)=>{try{return new Function("state","helpers",`with(state) { with(helpers) { return ${t} } }`)(H,Y)}catch(e){return console.error(`Error evaluating expression: ${t}`,e),""}})):t.element&&t.attrName?(t.element.setAttribute(t.attrName,H[e]),t.element.removeAttribute(`:${t.attrName}`)):t.update&&t.update()}),"Error updating bindings"))},$=e=>{Object.entries(O).forEach((([t,r])=>{r.has&&r.has(e)&&(delete p[t],M(t))})),i&&i.call(H,e),M(e),N(e),m.__updated__&&m.__updated__.forEach((e=>e.callback.call(H)))},N=e=>{m[e]&&m[e].forEach((t=>{t.debounce?(clearTimeout(t.timeout),t.timeout=setTimeout((()=>t.callback.call(H,H[e])),t.debounce)):t.throttle?(!t.lastCalled||Date.now()-t.lastCalled>t.throttle)&&(t.callback.call(H,H[e]),t.lastCalled=Date.now()):t.callback.call(H,H[e])}))};n&&Object.entries(n).forEach((([e,t])=>{m[e]=Array.isArray(t)?t.map((e=>({callback:e}))):["function"==typeof t?{callback:t}:{...t}]}));const H=T({...e,$refs:new Proxy(y,{get:(e,t)=>{const r=e[t];return r instanceof HTMLElement?new Proxy(r,{get:(e,t)=>"function"==typeof e[t]?e[t].bind(e):e[t]}):r},set:()=>{throw new Error("$refs is read-only")}})}),O={};t&&Object.entries(t).forEach((([e,t])=>{O[e]=new Set,Object.defineProperty(H,e,{get(){if(!p.hasOwnProperty(e)){const r=new Proxy(H,{get:(t,r)=>(r!==e&&O[e].add(r),t[r])});p[e]=t.call(r)}return p[e]},enumerable:!0,configurable:!0})}));const S=()=>{const e=new WeakMap,t={};f.querySelectorAll("[\\i-model]").forEach((r=>{const n=r.getAttribute("i-model");if(!n)return;const o=()=>{const e=(e=>e instanceof HTMLInputElement?"checkbox"===e.type?e.checked:"radio"===e.type?e.checked?e.value:void 0:e.value:e instanceof HTMLSelectElement?e.multiple?Array.from(e.selectedOptions).map((e=>e.value)):e.value:e instanceof HTMLTextAreaElement?e.value:void 0)(r);void 0!==e&&(H[n]=e,$(n))},a=()=>{((e,t)=>{e instanceof HTMLInputElement?"checkbox"===e.type?e.checked=!!t:"radio"===e.type?e.checked=e.value===t:e.value=t:e instanceof HTMLSelectElement?e.multiple?Array.from(e.options).forEach((e=>{e.selected=t.includes(e.value)})):e.value=t:e instanceof HTMLTextAreaElement&&(e.value=t)})(r,H[n])};if(e.has(r)){e.get(r).forEach((([e,t])=>{r.removeEventListener(e,t)}))}const i=[];if(r instanceof HTMLSelectElement||"checkbox"===r.type||"radio"===r.type){const e=()=>o();r.addEventListener("change",e),i.push(["change",e])}else{const e=()=>o();r.addEventListener("input",e),i.push(["input",e])}e.set(r,i),r instanceof HTMLInputElement&&"radio"===r.type&&(t[n]||(t[n]=[]),t[n].push(r),r.name=`radio-group-${n}`),(h[n]??=[]).push({element:r,updateModel:a}),a(),r.removeAttribute("i-model")})),Object.entries(t).forEach((([e,t])=>{(h[e]??=[]).push({updateModel:()=>{t.forEach((t=>{t.checked=t.value===H[e]}))}})}))},k=e=>{e.querySelectorAll("[i-for]").forEach((e=>{e instanceof HTMLElement&&U(e)})),e.querySelectorAll("*").forEach((e=>{if(e instanceof HTMLElement){if(e.closest("[data-i-for-id]"))return;(e=>{Array.from(e.attributes).forEach((t=>{const r=t.name.startsWith("i-")?t.name.slice(1):null;r&&E[r]&&(E[r](e,t.value,H),e.removeAttribute(t.name))}))})(e),(e=>{if(!(e instanceof HTMLElement))return;const t=e.getAttribute("i-if");if(!t)return;const r=[];let n=null,o=e.nextElementSibling;for(;o&&(o.hasAttribute("i-else-if")||o.hasAttribute("i-else"));){if(o.hasAttribute("i-else-if"))r.push(o);else if(o.hasAttribute("i-else")){n=o;break}o=o.nextElementSibling}const a=e.parentNode,i=document.createComment("i-if placeholder");a?.insertBefore(i,e);const c=()=>{try{if(_(t))e.isConnected||a?.insertBefore(e,i.nextSibling),r.forEach((e=>{e.isConnected&&a?.removeChild(e)})),n?.isConnected&&a?.removeChild(n);else{let t=!1;e.isConnected&&a?.removeChild(e);for(const e of r){const r=e.getAttribute("i-else-if");if(_(r)){e.isConnected||a?.insertBefore(e,i.nextSibling),t=!0;break}e.isConnected&&a?.removeChild(e)}!t&&n?n.isConnected||a?.insertBefore(n,i.nextSibling):n?.isConnected&&a?.removeChild(n)}}catch(e){console.error("Error evaluating i-if directive:",e)}};c(),(h[t]??=[]).push({element:e,update:c}),e.removeAttribute("i-if"),r.forEach((e=>e.removeAttribute("i-else-if"))),n?.removeAttribute("i-else")})(e),B(e),(e=>{e instanceof HTMLElement&&Array.from(e.attributes).forEach((t=>{const r=t.name.match(/^(?:i-bind:|:)(.+)$/);if(!r)return;const[,n]=r,o=t.value,a=()=>{try{let t=_(o);"class"===n?"object"==typeof t&&null!==t?Object.entries(t).forEach((([t,r])=>{e.classList.toggle(t,!!r)})):e.className=t:"style"===n?"object"==typeof t&&null!==t?Object.entries(t).forEach((([t,r])=>{e.style[t]=r})):e.setAttribute("style",t):!1===t?e.removeAttribute(n):e.setAttribute(n,!0===t?"":t)}catch(e){console.error(`Error applying bind directive for ${n}:`,e)}};a(),F(o).forEach((e=>{(h[e]??=[]).push({update:a})})),e.removeAttribute(t.name)}))})(e)}})),j(e)},j=e=>{const t=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,null,!1);let r;for(;r=t.nextNode();){const e=r.textContent;if(e.includes("{")&&e.includes("}")){const t=e.split(/(\{@html\s+.*?\}|\{.*?\})/),n=document.createDocumentFragment();t.forEach((e=>{if(e.startsWith("{@html")&&e.endsWith("}")){const t=e.slice(6,-1).trim(),r=document.createElement("span"),o=()=>{try{const e=_(t);r.innerHTML=e,r.querySelectorAll("*").forEach((e=>{e instanceof HTMLElement&&k(e)}))}catch(e){console.error(`Error evaluating HTML expression: ${t}`,e)}};o();F(t).forEach((e=>{(h[e]??=[]).push({update:o})})),n.appendChild(r)}else if(e.startsWith("{")&&e.endsWith("}")){const t=e.slice(1,-1).trim(),r=document.createTextNode(""),o=()=>{try{r.textContent=_(t)}catch(e){console.error(`Error evaluating expression: ${t}`,e)}};o();F(t).forEach((e=>{(h[e]??=[]).push({update:o})})),n.appendChild(r)}else n.appendChild(document.createTextNode(e))})),r.parentNode.replaceChild(n,r)}}},_=e=>{try{return new Function("state","helpers",`with(state) { with(helpers) { return ${e} } }`)(H,Y)}catch(t){return console.error(`Error evaluating expression: ${e}`,t),""}},F=e=>{const t=e.match(/\b\w+\b/g);return t?t.filter((e=>e in H)):[]};Object.entries(l).forEach((([e,t])=>{g(e,t)}));const q={beforeCreate:[],created:[],beforeMount:[],mounted:[],beforeUpdate:[],updated:[],beforeUnmount:[],unmounted:[]},D=(e,t)=>{q[e]&&q[e].push(t)},W=e=>{q[e]?.forEach((e=>e.call(H)))},P=e=>{e.data&&Object.assign(H,e.data()),e.methods&&Object.assign(r,e.methods),e.computed&&Object.assign(t,e.computed),e.watch&&Object.entries(e.watch).forEach((([e,t])=>{(n[e]??=[]).push(t)})),e.mounted&&D("mounted",e.mounted)};u.forEach(P);window.addEventListener("error",(e=>{console.error("Global error:",e)}));const I={beforeEnter:e=>{e.style.opacity="0",e.style.transform="translateY(-20px)",e.style.display=""},enter:(e,t)=>{const r=1e3*parseFloat(getComputedStyle(e).transitionDuration);requestAnimationFrame((()=>{e.style.opacity="1",e.style.transform="translateY(0)",setTimeout(t,r)}))},afterEnter:e=>{e.style.opacity="",e.style.transform=""},enterCancelled:e=>{e.style.opacity="",e.style.transform=""},beforeLeave:e=>{e.style.opacity="1",e.style.transform="translateY(0)"},leave:(e,t)=>{const r=1e3*parseFloat(getComputedStyle(e).transitionDuration);requestAnimationFrame((()=>{e.style.opacity="0",e.style.transform="translateY(-20px)",setTimeout(t,r)}))},afterLeave:e=>{e.style.display="none",e.style.opacity="",e.style.transform=""},leaveCancelled:e=>{e.style.opacity="",e.style.transform=""}},B=e=>{if(!(e instanceof HTMLElement))return;const t=e.getAttribute("i-show");if(!t)return;let r=null;const n=async()=>{try{const n=new Function("state","helpers",`with(state) { with(helpers) { return ${t} } }`)(H,Y);e._transitionShow&&e._transitionHide?(r&&(await r,r=null),r=n?e._transitionShow():e._transitionHide(),await r):e.style.display=n?"":"none"}catch(e){console.error("Error evaluating i-show directive:",e)}};n(),(h[t]??=[]).push({element:e,update:n}),e.removeAttribute("i-show")},U=e=>{if(!(e instanceof HTMLElement))return;const t=e.getAttribute("i-for");if(!t)return;const r=t.match(/(\w+)\s+in\s+(\w+)/);if(!r)return void console.error("Invalid i-for expression:",t);const[,n,o]=r,a=e.parentNode,i=document.createComment(`i-for: ${t}`);a?.insertBefore(i,e);const c=e.cloneNode(!0);c.removeAttribute("i-for");const s=()=>{try{const e=H[o];if(!Array.isArray(e))return void console.error(`Collection ${o} is not an array`);const t=document.createDocumentFragment();let r=i.nextSibling;for(;r&&r.hasAttribute?.("data-i-for-id");){const e=r;r=r.nextSibling,e.remove()}e.forEach(((e,r)=>{const a=c.cloneNode(!0);a.setAttribute("data-i-for-id",`${o}-${r}`);const i=t=>{if(t.nodeType===Node.ELEMENT_NODE)t=(t=>{if(t.nodeType===Node.ELEMENT_NODE){const r=t.tagName.toLowerCase();if(v.has(r)){const o=v.get(r),a=Array.from(t.attributes).reduce(((t,r)=>{const o=r.value.replace(/\{(.*?)\}/g,((t,o)=>{try{const t={[n]:e};return new Function("scope","state","helpers",`with(scope) { with(state) { with(helpers) { return ${o} } } }`)(t,H,Y)}catch(e){return console.error(`Error evaluating prop expression: ${o}`,e),r.value}}));return{...t,[r.name]:o}}),{}),i=o(a),c=document.createElement("div");c.innerHTML=i.template||i;const s=c.firstElementChild;if(s)return Array.from(t.attributes).forEach((e=>{a[e.name]||s.setAttribute(e.name,e.value)})),t.parentNode?.replaceChild(s,t),s}}return t})(t),Array.from(t.childNodes).forEach(i);else if(t.nodeType===Node.TEXT_NODE){const r=t.textContent;r.includes("{")&&r.includes("}")&&(t.textContent=r.replace(/\{(.*?)\}/g,((t,r)=>{try{const t={[n]:e};return new Function("scope","state","helpers",`with(scope) { with(state) { with(helpers) { return ${r} } } }`)(t,H,Y)}catch(e){return console.error(`Error evaluating expression: ${r}`,e),""}})))}};Array.from(a.childNodes).forEach(i),t.appendChild(a)})),a.insertBefore(t,i.nextSibling)}catch(e){console.error("Error in i-for directive:",e)}};s(),(h[o]??=[]).push({update:s}),e.remove()},Y={};new WeakMap;return{mount:x((function(e){if(f=document.querySelector(e),!f)throw new Error(`Element with selector "${e}" not found.`);var t;W("beforeCreate"),W("created"),a&&a.call(H),W("beforeMount"),s.forEach((e=>{"function"==typeof e&&e({createPlugin:A,state:H,bindings:h})})),(()=>{const e=f.querySelector("template"),t=e?e.innerHTML.trim():"string"==typeof c?c.trim():c instanceof HTMLElement?c.innerHTML:f.innerHTML.trim();if(!t)throw new Error("No template provided and container is empty");f.innerHTML="";const r=document.createElement("template");r.innerHTML=t;const n=r.content,o=e=>{if(e.nodeType===Node.ELEMENT_NODE){const t=e.tagName.toLowerCase();if(v.has(t)){const r=v.get(t),n=Array.from(e.attributes).reduce(((e,t)=>({...e,[t.name]:t.value})),{}),a=r(n),i=document.createElement("div");i.innerHTML=a.template||a;const c=i.firstElementChild;if(c)return Array.from(e.attributes).forEach((e=>{n[e.name]||c.setAttribute(e.name,e.value)})),Array.from(c.children).forEach((e=>{o(e)})),void e.parentNode?.replaceChild(c,e)}Array.from(e.children).forEach((e=>{o(e)}))}};Array.from(n.children).forEach((e=>{o(e)})),k(n),f.appendChild(n)})(),f.querySelectorAll("*").forEach((e=>{Array.from(e.attributes).forEach((t=>{if(t.name.startsWith("@")){const[n,...o]=t.name.slice(1).split("."),a=t.value.trim(),i={capture:o.includes("capture"),once:o.includes("once"),passive:o.includes("passive")},c=t=>{try{if(o.includes("stop")&&t.stopPropagation(),o.includes("prevent")&&t.preventDefault(),o.includes("self")&&t.target!==e)return;if(t instanceof KeyboardEvent){const e=o.filter((e=>["ctrl","alt","shift","meta","Tab","ArrowUp","ArrowDown","ArrowLeft","ArrowRight"].includes(e))),r=e.every((e=>t[`${e}Key`]));if(e.length>0&&!r)return;const n=o.find((e=>/^[0-9]+$/.test(e)));if(n&&t.keyCode!==parseInt(n))return;const a=o.find((t=>!e.includes(t)&&!/^[0-9]+$/.test(t)));if(a&&t.key.toLowerCase()!==a.toLowerCase())return}if(t instanceof MouseEvent){const e={left:0,middle:1,right:2},r=o.find((t=>Object.keys(e).includes(t)));if(r&&t.button!==e[r])return}r&&r[a]?r[a].call(H,t):new Function("state","event",`with(state) { ${a} }`).call(H,H,t),$()}catch(e){console.error(`Error executing event handler: ${a}`,e)}};let s=c;if(o.includes("debounce")){const e=parseInt(o[o.indexOf("debounce")+1])||300;s=debounce(c,e)}if(o.includes("throttle")){const e=parseInt(o[o.indexOf("throttle")+1])||300;s=throttle(c,e)}e.addEventListener(n,s,i),e.removeAttribute(t.name)}}))})),f.querySelectorAll("[\\i-ref]").forEach((e=>{if(!(e instanceof HTMLElement))return;const t=e.getAttribute("i-ref");t&&(y[t]=e,e.removeAttribute("i-ref"))})),S(),f.querySelectorAll("[\\i-html]").forEach((e=>{if(!(e instanceof HTMLElement))return;const t=e.getAttribute("i-html");if(!t)return;const r=()=>{try{let r=new Function("state","helpers",`with(state) { with(helpers) { return ${t} } }`)(H,Y);r=r.replace(/\{(.*?)\}/g,((e,t)=>new Function("state",`with(state) { return ${t} }`)(H))),e.innerHTML=r,e.querySelectorAll("*").forEach((e=>{e instanceof HTMLElement&&n(e)}))}catch(e){console.error("Error applying i-html directive:",e)}},n=e=>{Array.from(e.childNodes).forEach((e=>{e.nodeType===Node.TEXT_NODE&&o(e)})),Array.from(e.attributes).forEach((t=>{t.value.includes("{")&&t.value.includes("}")&&a(e,t)}))},o=e=>{const t=e.textContent||"";if(t.includes("{")&&t.includes("}")){const r=t.split(/(\{.*?\})/),n=document.createDocumentFragment();r.forEach((e=>{if(e.startsWith("{")&&e.endsWith("}")){const t=e.slice(1,-1).trim(),r=document.createTextNode("");n.appendChild(r);const o=()=>{r.textContent=_(t)};o(),Object.keys(H).forEach((e=>{(h[e]??=[]).push({update:o})}))}else n.appendChild(document.createTextNode(e))})),e.parentNode.replaceChild(n,e)}},a=(e,t)=>{const r=t.value,n=()=>{const n=r.replace(/\{(.*?)\}/g,((e,t)=>new Function("state",`with(state) { return ${t} }`)(H)));e.setAttribute(t.name,n)};n(),Object.keys(H).forEach((e=>{(h[e]??=[]).push({update:n})}))};r(),Object.keys(H).forEach((e=>{(h[e]??=[]).push({update:r})})),e.removeAttribute("i-html")})),f.querySelectorAll("[i-transition]").forEach((e=>{if(!(e instanceof HTMLElement))return;const t=e.getAttribute("i-transition");if(!t)return;const[r,n,o]=t.split(",").map((e=>e.trim())),a=n?`${n}ms`:"300ms",i=o||"ease";e.style.transition=`opacity ${a} ${i}, transform ${a} ${i}`;const c=(t,r)=>new Promise((n=>{let o=!1;return t.before(e),t.during(e,(()=>{o||(t.after(e),r&&r(),n())})),()=>{o=!0,t.cancelled(e),n()}}));e._transitionShow=async t=>{e.style.display="",await c({before:I.beforeEnter,during:I.enter,after:I.afterEnter,cancelled:I.enterCancelled},t)},e._transitionHide=async e=>{await c({before:I.beforeLeave,during:I.leave,after:I.afterLeave,cancelled:I.leaveCancelled},e)},e.style.display="none",e.removeAttribute("i-transition")})),f.querySelectorAll("*").forEach((e=>{e instanceof HTMLElement&&Array.from(e.attributes).forEach((t=>{const r=t.name.match(/^(?:i-bind:|:)(.+)$/);if(!r)return;const[,n]=r,o=t.value,a=()=>{try{let t=new Function("state","helpers",`with(state) { with(helpers) { return ${o} } }`)(H,Y);"class"===n?"object"==typeof t&&null!==t?Object.entries(t).forEach((([t,r])=>{e.classList.toggle(t,!!r)})):e.className=t:"style"===n?"object"==typeof t&&null!==t?Object.entries(t).forEach((([t,r])=>{e.style[t]=r})):e.setAttribute("style",t):!1===t?e.removeAttribute(n):e.setAttribute(n,!0===t?"":t)}catch(e){console.error(`Error applying bind directive for ${n}:`,e)}};a(),(h[o]??=[]).push({update:a}),e.removeAttribute(t.name)}))})),Object.entries(O).forEach((([e,r])=>{r instanceof Set&&r.has(t)&&(delete p[e],M(e))})),f.querySelectorAll("[\\i-show]").forEach((e=>{e instanceof HTMLElement&&B(e)})),o&&o.call(H),W("mounted"),Object.keys(H).forEach((e=>M(e)))}),"Error mounting application"),onUpdated:e=>{if("function"==typeof e){const t=x(e,"Error in onUpdated callback");(m.__updated__??=[]).push({callback:t})}},createPlugin:A,emit:(e,t)=>{(b.get(e)??[]).forEach((e=>e(t)))},on:(e,t)=>(b.has(e)||b.set(e,[]),b.get(e).push(t),()=>{const r=b.get(e),n=r.indexOf(t);-1!==n&&r.splice(n,1)}),addLifecycleHook:D,applyMixin:P,component:g,render:e=>{const t=document.createElement("template");return t.innerHTML=e.trim(),t.content},power:e=>{Object.entries(e).forEach((([e,t])=>{Y[e]="function"==typeof t?(...r)=>{try{return t(...r.map((e=>"string"==typeof e&&e.includes("{")&&e.includes("}")?new Function("state","helpers",`with(state) { with(helpers) { return ${e.slice(1,-1)} } }`)(H,Y):e)))}catch(t){return console.error(`Error in helper function '${e}':`,t),""}}:t}))}}};export const debounce=(e,t)=>{let r;return function(...n){clearTimeout(r),r=setTimeout((()=>{clearTimeout(r),e(...n)}),t)}};export const throttle=(e,t)=>{let r;return function(...n){r||(e(...n),r=!0,setTimeout((()=>r=!1),t))}};export{createApp};
1
+ /**
2
+ * @license
3
+ * Olova Framework v2.0.0
4
+ * (c) 2025 Olova
5
+ * This source code is licensed under the MIT license
6
+ *
7
+ * Author: Nazmul Hossain
8
+ * Made in Bangladesh
9
+ */
10
+
11
+ /** @jsx Olova.createElement */
12
+
13
+ const Olova = {};
14
+ let currentComponent = null,
15
+ currentHook = 0;
16
+ const states = new WeakMap(),
17
+ effects = new WeakMap(),
18
+ memos = new WeakMap(),
19
+ refs = new WeakMap();
20
+ let isBatchingUpdates = !1;
21
+ const effectComponentIds = new Set(),
22
+ customHookComponentIds = new Set();
23
+ Olova.createHook = (e) => {
24
+ if ("function" != typeof e)
25
+ throw new Error("createHook: Hook implementation must be a function");
26
+ return (...t) => {
27
+ if (!currentComponent)
28
+ throw new Error(
29
+ "Custom hooks can only be called inside component render"
30
+ );
31
+ const o = currentHook++,
32
+ r = currentComponent;
33
+ customHooks.has(r) ||
34
+ (customHooks.set(r, new Map()), customHookComponentIds.add(r));
35
+ const n = customHooks.get(r);
36
+ n.has(o) || n.set(o, { state: void 0, cleanup: void 0 });
37
+ const a = {
38
+ useState: Olova.State,
39
+ useEffect: Olova.Effect,
40
+ useMemo: Olova.Memo,
41
+ useRef: Olova.Ref,
42
+ getHookState: () => n.get(o).state,
43
+ setHookState: (e) => {
44
+ n.get(o).state = e;
45
+ },
46
+ setCleanup: (e) => {
47
+ "function" == typeof e && (n.get(o).cleanup = e);
48
+ },
49
+ };
50
+ return e(a, ...t);
51
+ };
52
+ };
53
+ const customHooks = new WeakMap();
54
+ Olova.State = (e) => {
55
+ const t = currentComponent,
56
+ o = currentHook++;
57
+ states.has(t) || states.set(t, []);
58
+ const r = states.get(t);
59
+ void 0 === r[o] && (r[o] = e);
60
+ return [
61
+ r[o],
62
+ (e) => {
63
+ const t = "function" == typeof e ? e(r[o]) : e;
64
+ queueUpdate(() => {
65
+ (r[o] = t), rerender();
66
+ });
67
+ },
68
+ ];
69
+ };
70
+ const flattenChildren = (e) =>
71
+ e.reduce(
72
+ (e, t) =>
73
+ null == t || "boolean" == typeof t
74
+ ? e
75
+ : Array.isArray(t)
76
+ ? e.concat(flattenChildren(t))
77
+ : e.concat("object" == typeof t ? t : createTextElement(t)),
78
+ []
79
+ );
80
+ Olova.createElement = (e, t, ...o) =>
81
+ e === Olova.Fragment
82
+ ? { type: "FRAGMENT", props: { children: flattenChildren(o) } }
83
+ : { type: e, props: { ...t, children: flattenChildren(o) } };
84
+ const createTextElement = (e) => ({
85
+ type: "TEXT_ELEMENT",
86
+ props: { nodeValue: e, children: [] },
87
+ }),
88
+ createDom = (e) => {
89
+ const t =
90
+ "TEXT_ELEMENT" === e.type
91
+ ? document.createTextNode("")
92
+ : document.createElement(e.type),
93
+ o = sanitizeProps(e.props);
94
+ return updateDom(t, {}, o), t;
95
+ },
96
+ updateDom = (e, t, o) => {
97
+ t.style &&
98
+ Object.keys(t.style).forEach((r) => {
99
+ (o.style && t.style[r] === o.style[r]) || (e.style[r] = "");
100
+ });
101
+ const r = new Map();
102
+ Object.keys(t || {}).forEach((e) => {
103
+ "children" === e || e in o || r.set(e, null);
104
+ }),
105
+ Object.keys(o || {}).forEach((e) => {
106
+ "children" !== e && t[e] !== o[e] && r.set(e, o[e]);
107
+ }),
108
+ r.forEach((o, r) => {
109
+ if (r.startsWith("on")) {
110
+ const n = r.slice(2).toLowerCase();
111
+ t[r] && e.removeEventListener(n, t[r]), o && e.addEventListener(n, o);
112
+ } else
113
+ "style" === r && "object" == typeof o
114
+ ? Object.assign(e.style, o)
115
+ : "className" === r
116
+ ? e.setAttribute("class", o || "")
117
+ : "boolean" == typeof o
118
+ ? o
119
+ ? e.setAttribute(r, "")
120
+ : e.removeAttribute(r)
121
+ : (e[r] = o ?? "");
122
+ });
123
+ };
124
+ let rootElement = null,
125
+ currentRoot = null;
126
+ Olova.render = (e, t) => {
127
+ (rootElement = t),
128
+ (currentRoot = { dom: t, props: { children: [e] } }),
129
+ rerender();
130
+ };
131
+ const rerender = () => {
132
+ if (rootElement && currentRoot) {
133
+ for (
134
+ effectComponentIds.forEach((e) => {
135
+ const t = effects.get(e);
136
+ t &&
137
+ t.forEach((e) => {
138
+ e && e.cleanup && e.cleanup();
139
+ });
140
+ }),
141
+ customHookComponentIds.forEach((e) => {
142
+ const t = customHooks.get(e);
143
+ t &&
144
+ t.forEach((e) => {
145
+ e.cleanup && e.cleanup();
146
+ });
147
+ });
148
+ rootElement.firstChild;
149
+
150
+ )
151
+ rootElement.removeChild(rootElement.firstChild);
152
+ renderElement(currentRoot.props.children[0], rootElement);
153
+ }
154
+ },
155
+ cleanupEffects = () => {
156
+ effects.forEach((e, t) => {
157
+ e.forEach((e) => {
158
+ e && e.cleanup && e.cleanup();
159
+ });
160
+ });
161
+ },
162
+ cleanupCustomHooks = () => {
163
+ customHooks.forEach((e, t) => {
164
+ e.forEach((e) => {
165
+ e.cleanup && e.cleanup();
166
+ });
167
+ });
168
+ },
169
+ contexts = new Map();
170
+ let contextIndex = 0;
171
+ (Olova.createContext = (e) => {
172
+ const t = contextIndex++;
173
+ return (
174
+ contexts.set(t, { defaultValue: e, value: e }),
175
+ {
176
+ Provider: ({ value: e, children: o }) => (
177
+ (contexts.get(t).value = e), o[0]
178
+ ),
179
+ Consumer: ({ children: e }) => e[0](contexts.get(t).value),
180
+ _contextId: t,
181
+ }
182
+ );
183
+ }),
184
+ (Olova.Context = (e) => {
185
+ if (!e || "number" != typeof e._contextId)
186
+ throw new Error(
187
+ "Context: Invalid context object. Make sure you're passing a context created by createContext()"
188
+ );
189
+ return currentHook++, contexts.get(e._contextId).value;
190
+ });
191
+ const renderElement = (e, t) => {
192
+ if (!t || !(t instanceof Element || t instanceof DocumentFragment))
193
+ throw new Error("Invalid container element provided to render");
194
+ if (!e && 0 !== e && "" !== e) return;
195
+ if ("FRAGMENT" === e.type) {
196
+ const o = document.createDocumentFragment();
197
+ return (
198
+ e.props.children.forEach((e) => renderElement(e, o)),
199
+ void t.appendChild(o)
200
+ );
201
+ }
202
+ if ("object" == typeof e.type && e.type.Consumer) {
203
+ const o = contexts.get(e.type._contextId).value,
204
+ r = e.props.children[0](o);
205
+ return void renderElement(r, t);
206
+ }
207
+ if ("object" == typeof e.type && e.type.Provider) {
208
+ const o = e.props.children[0];
209
+ return void renderElement(o, t);
210
+ }
211
+ if ("function" == typeof e.type) {
212
+ (currentComponent = e.type), (currentHook = 0);
213
+ const o = e.type(e.props);
214
+ return void renderElement(o, t);
215
+ }
216
+ const o = createDom(e);
217
+ e.props.children.forEach((e) => renderElement(e, o)), t.appendChild(o);
218
+ };
219
+ (Olova.Effect = (e, t) => {
220
+ if ("function" != typeof e)
221
+ throw new Error("Effect: First argument must be a function");
222
+ if (void 0 !== t && !Array.isArray(t))
223
+ throw new Error("Effect: Second argument must be an array or undefined");
224
+ const o = currentComponent,
225
+ r = currentHook++;
226
+ effects.has(o) || (effects.set(o, []), effectComponentIds.add(o));
227
+ const n = effects.get(o),
228
+ a = n[r];
229
+ if (!a || !t || t.some((e, t) => !Object.is(e, a.deps[t]))) {
230
+ a && a.cleanup && a.cleanup();
231
+ const o = e();
232
+ n[r] = { deps: t, cleanup: "function" == typeof o ? o : void 0 };
233
+ }
234
+ }),
235
+ (Olova.Reducer = (e, t, o) => {
236
+ const r = currentComponent,
237
+ n = currentHook++;
238
+ states.has(r) || states.set(r, []);
239
+ const a = states.get(r);
240
+ void 0 === a[n] && (a[n] = o ? o(t) : t);
241
+ return [
242
+ a[n],
243
+ (t) => {
244
+ (a[n] = e(a[n], t)), rerender();
245
+ },
246
+ ];
247
+ }),
248
+ (Olova.Callback = (e, t) => Olova.Memo(() => e, t)),
249
+ (Olova.Memo = (e, t) => {
250
+ const o = currentComponent,
251
+ r = currentHook++;
252
+ memos.has(o) || memos.set(o, []);
253
+ const n = memos.get(o),
254
+ a = n[r];
255
+ if (
256
+ !a ||
257
+ !t ||
258
+ t.length !== a.deps.length ||
259
+ t.some(
260
+ (e, t) =>
261
+ !Object.is(e, a.deps[t]) &&
262
+ ("object" != typeof e ||
263
+ null === e ||
264
+ JSON.stringify(e) !== JSON.stringify(a.deps[t]))
265
+ )
266
+ ) {
267
+ const o = e();
268
+ return (n[r] = { value: o, deps: t }), o;
269
+ }
270
+ return a.value;
271
+ }),
272
+ (Olova.Ref = (e) => {
273
+ const t = currentComponent,
274
+ o = currentHook++;
275
+ refs.has(t) || refs.set(t, []);
276
+ const r = refs.get(t);
277
+ return void 0 === r[o] && (r[o] = { current: e }), r[o];
278
+ }),
279
+ (Olova.LayoutEffect = (e, t) => {
280
+ Olova.Effect(e, t);
281
+ }),
282
+ (Olova.ImperativeHandle = (e, t, o) => {
283
+ Olova.LayoutEffect(() => {
284
+ e && (e.current = t());
285
+ }, o);
286
+ }),
287
+ (Olova.Fragment = Symbol("Fragment"));
288
+ let nextUnitOfWork = null,
289
+ wipRoot = null;
290
+ function createFiber(e, t, o = null) {
291
+ return {
292
+ type: e,
293
+ props: t,
294
+ key: o,
295
+ dom: null,
296
+ parent: null,
297
+ child: null,
298
+ sibling: null,
299
+ alternate: null,
300
+ effectTag: null,
301
+ lastProps: null,
302
+ shouldUpdate: !0,
303
+ dependencies: new Set(),
304
+ memoizedState: null,
305
+ };
306
+ }
307
+ const schedulerPriorities = {
308
+ ImmediatePriority: 1,
309
+ UserBlockingPriority: 2,
310
+ NormalPriority: 3,
311
+ LowPriority: 4,
312
+ IdlePriority: 5,
313
+ },
314
+ objectPool = {
315
+ fibers: [],
316
+ effects: [],
317
+ acquireFiber() {
318
+ return this.fibers.pop() || createFiber();
319
+ },
320
+ releaseFiber(e) {
321
+ Object.keys(e).forEach((t) => {
322
+ e[t] = null;
323
+ }),
324
+ this.fibers.push(e);
325
+ },
326
+ },
327
+ workLoop = (e) => {
328
+ let t = !1;
329
+ for (; nextUnitOfWork && !t; ) {
330
+ const o = nextUnitOfWork;
331
+ if (
332
+ (o.priorityLevel || schedulerPriorities.NormalPriority) >
333
+ schedulerPriorities.ImmediatePriority &&
334
+ e.timeRemaining() < 500
335
+ ) {
336
+ t = !0;
337
+ break;
338
+ }
339
+ nextUnitOfWork = performUnitOfWork(o);
340
+ }
341
+ !nextUnitOfWork && wipRoot && commitRoot(), requestIdleCallback(workLoop);
342
+ };
343
+ function performUnitOfWork(e) {
344
+ if (
345
+ ("function" == typeof e.type
346
+ ? updateFunctionComponent(e)
347
+ : updateHostComponent(e),
348
+ e.child)
349
+ )
350
+ return e.child;
351
+ let t = e;
352
+ for (; t; ) {
353
+ if (t.sibling) return t.sibling;
354
+ t = t.parent;
355
+ }
356
+ }
357
+ function updateFunctionComponent(e) {
358
+ (currentComponent = e), (currentHook = 0), (e.hooks = []);
359
+ try {
360
+ const t = [e.type(e.props)];
361
+ reconcileChildren(e, t);
362
+ } catch (t) {
363
+ handleWorkInProgressError(e, t);
364
+ }
365
+ }
366
+ function updateHostComponent(e) {
367
+ e.dom || (e.dom = createDom(e)), reconcileChildren(e, e.props.children);
368
+ }
369
+ function reconcileChildren(e, t, o) {
370
+ let r = null,
371
+ n = null;
372
+ const a = new Map();
373
+ let s = t;
374
+ for (; s; ) {
375
+ const e = s.key || s.index;
376
+ a.set(e, s), (s = s.sibling);
377
+ }
378
+ for (let t = 0; t < o.length; t++) {
379
+ const s = o[t],
380
+ c = s.key || t,
381
+ l = a.get(c);
382
+ l && l.type === s.type
383
+ ? (n = {
384
+ ...l,
385
+ props: s.props,
386
+ alternate: l,
387
+ effectTag: "UPDATE",
388
+ shouldUpdate: !shallowEqual(l.props, s.props),
389
+ })
390
+ : ((n = createFiber(s.type, s.props, c)),
391
+ (n.effectTag = "PLACEMENT"),
392
+ (n.shouldUpdate = !0),
393
+ l && ((l.effectTag = "DELETION"), deletions.push(l))),
394
+ null === r ? (e.child = n) : (r.sibling = n),
395
+ (r = n),
396
+ a.delete(c);
397
+ }
398
+ a.forEach((e) => {
399
+ (e.effectTag = "DELETION"), deletions.push(e);
400
+ });
401
+ }
402
+ function shallowEqual(e, t) {
403
+ if (Object.is(e, t)) return !0;
404
+ if (!e || !t) return !1;
405
+ const o = Object.keys(e),
406
+ r = Object.keys(t);
407
+ if (o.length !== r.length) return !1;
408
+ for (let r = 0; r < o.length; r++) {
409
+ const n = o[r];
410
+ if ("children" !== n && !Object.is(e[n], t[n])) return !1;
411
+ }
412
+ return !0;
413
+ }
414
+ function handleWorkInProgressError(e, t) {
415
+ let o = null,
416
+ r = e;
417
+ for (; r; ) {
418
+ if (r.type?.prototype instanceof Olova.ErrorBoundary) {
419
+ o = r;
420
+ break;
421
+ }
422
+ r = r.parent;
423
+ }
424
+ if (!o) throw t;
425
+ {
426
+ const r = {
427
+ componentStack: getComponentStack(e),
428
+ error: t,
429
+ errorBoundary: o,
430
+ };
431
+ (o.updateQueue = o.updateQueue || []),
432
+ o.updateQueue.push({ action: "ERROR", error: r }),
433
+ scheduleWork(o, schedulerPriorities.ImmediatePriority);
434
+ }
435
+ }
436
+ function commitRoot() {
437
+ deletions.forEach(commitWork),
438
+ commitWork(wipRoot.child),
439
+ (currentRoot = wipRoot),
440
+ (wipRoot = null);
441
+ }
442
+ const commitWork = (e) => {
443
+ if (e) {
444
+ if (e.shouldUpdate)
445
+ switch (e.effectTag) {
446
+ case "PLACEMENT":
447
+ if (e.dom) {
448
+ const t = getParentFiber(e);
449
+ t && t.dom.appendChild(e.dom);
450
+ }
451
+ break;
452
+ case "UPDATE":
453
+ e.dom && updateDom(e.dom, e.alternate.props, e.props);
454
+ break;
455
+ case "DELETION":
456
+ commitDeletion(e);
457
+ }
458
+ commitWork(e.child), commitWork(e.sibling);
459
+ }
460
+ };
461
+ function getParentFiber(e) {
462
+ let t = e.parent;
463
+ for (; t && !t.dom; ) t = t.parent;
464
+ return t;
465
+ }
466
+ (Olova.createStore = (e, t) => {
467
+ if ("function" != typeof e)
468
+ throw new Error("createStore: Reducer must be a function");
469
+ let o = t,
470
+ r = new Set();
471
+ const n = (t) => {
472
+ (o = e(o, t)), r.forEach((e) => e());
473
+ };
474
+ return (
475
+ n({ type: "@@INIT" }),
476
+ {
477
+ getState: () => o,
478
+ dispatch: n,
479
+ subscribe: (e) => (r.add(e), () => r.delete(e)),
480
+ }
481
+ );
482
+ }),
483
+ (Olova.Provider = ({ store: e, children: t }) => {
484
+ if (
485
+ !e ||
486
+ "function" != typeof e.getState ||
487
+ "function" != typeof e.dispatch
488
+ )
489
+ throw new Error(
490
+ "Provider: Invalid store object. Make sure you're passing a store created by createStore()"
491
+ );
492
+ if (!t) throw new Error("Provider: Must include children elements");
493
+ const o = Olova.createContext(null),
494
+ r = () => o.Provider({ value: e, children: [t] });
495
+ return (r.Context = o), r();
496
+ }),
497
+ (Olova.Selector = (e) => {
498
+ if ("function" != typeof e)
499
+ throw new Error("Selector: Selector must be a function");
500
+ const t = Olova.Context(Olova.Provider.Context);
501
+ if (!t) throw new Error("Selector must be used within a Provider");
502
+ const [, o] = Olova.State({});
503
+ Olova.Effect(
504
+ () =>
505
+ t.subscribe(() => {
506
+ const n = e(t.getState());
507
+ r !== n && o({});
508
+ }),
509
+ [t, e]
510
+ );
511
+ const r = e(t.getState());
512
+ return r;
513
+ }),
514
+ (Olova.Dispatch = () => {
515
+ const e = Olova.Context(Olova.Provider.Context);
516
+ if (!e) throw new Error("Dispatch must be used within a Provider");
517
+ return e.dispatch;
518
+ }),
519
+ (Olova.combineReducers =
520
+ (e) =>
521
+ (t = {}, o) => {
522
+ const r = {};
523
+ let n = !1;
524
+ return (
525
+ Object.entries(e).forEach(([e, a]) => {
526
+ const s = t[e],
527
+ c = a(s, o);
528
+ (r[e] = c), (n = n || c !== s);
529
+ }),
530
+ n ? r : t
531
+ );
532
+ }),
533
+ (Olova.createAction = (e) => {
534
+ const t = (t) => ({ type: e, payload: t });
535
+ return (t.toString = () => e), t;
536
+ }),
537
+ (Olova.applyMiddleware =
538
+ (...e) =>
539
+ (t) =>
540
+ (o, r) => {
541
+ const n = t(o, r);
542
+ let a = n.dispatch;
543
+ const s = { getState: n.getState, dispatch: (e) => a(e) },
544
+ c = e.map((e) => e(s));
545
+ return (a = c.reduce((e, t) => t(e))(n.dispatch)), { ...n, dispatch: a };
546
+ }),
547
+ (Olova.Suspense = ({ fallback: e, children: t }) => {
548
+ const [o, r] = Olova.State(!1),
549
+ [n, a] = Olova.State(null);
550
+ try {
551
+ return Olova.createElement(
552
+ SuspenseProvider,
553
+ { value: { isPending: o, setPending: r, setError: a } },
554
+ t
555
+ );
556
+ } catch (t) {
557
+ if (t instanceof Promise) return t.then(() => r(!1)), r(!0), e;
558
+ throw t;
559
+ }
560
+ }),
561
+ (Olova.ErrorBoundary = class {
562
+ constructor(e) {
563
+ (this.state = { hasError: !1, error: null }),
564
+ (this.fallback = e.fallback);
565
+ }
566
+ static getDerivedStateFromError(e) {
567
+ return { hasError: !0, error: e };
568
+ }
569
+ componentDidCatch(e, t) {
570
+ console.error("Error caught by ErrorBoundary:", e, t),
571
+ this.props.onError && this.props.onError(e, t);
572
+ }
573
+ render() {
574
+ return this.state.hasError
575
+ ? "function" == typeof this.fallback
576
+ ? this.fallback(this.state.error)
577
+ : this.fallback
578
+ : this.props.children;
579
+ }
580
+ });
581
+ const createVirtualDom = (e) => ({
582
+ type: e.type,
583
+ key: e.key || null,
584
+ ref: e.ref || null,
585
+ props: {
586
+ ...e.props,
587
+ children: Array.isArray(e.props.children)
588
+ ? e.props.children.map((e) =>
589
+ "object" == typeof e ? createVirtualDom(e) : e
590
+ )
591
+ : e.props.children,
592
+ },
593
+ _owner: currentComponent,
594
+ _store: { validated: !1 },
595
+ _self: null,
596
+ _source:
597
+ "production" !== process.env.NODE_ENV
598
+ ? {
599
+ fileName: e._source?.fileName || "unknown",
600
+ lineNumber: e._source?.lineNumber || 0,
601
+ }
602
+ : null,
603
+ }),
604
+ reconcileChildrenArray = (e, t, o) => {
605
+ let r = t,
606
+ n = null,
607
+ a = null,
608
+ s = 0,
609
+ c = null;
610
+ const l = new Map();
611
+ let i = t;
612
+ for (; i; ) {
613
+ const e = i.key || s;
614
+ l.set(e, i), (i = i.sibling);
615
+ }
616
+ for (; r && s < o.length; s++) {
617
+ c = r.sibling;
618
+ const t = o[s],
619
+ l = t.key || s;
620
+ if (l !== (r.key || s)) {
621
+ r = c;
622
+ break;
623
+ }
624
+ (a = {
625
+ type: t.type,
626
+ key: l,
627
+ props: t.props,
628
+ dom: r.dom,
629
+ parent: e,
630
+ alternate: r,
631
+ effectTag: "UPDATE",
632
+ lanes: 0,
633
+ childLanes: 0,
634
+ }),
635
+ null === n ? (e.child = a) : (n.sibling = a),
636
+ (n = a),
637
+ (r = c);
638
+ }
639
+ for (; s < o.length; ) {
640
+ const t = o[s];
641
+ (a = {
642
+ type: t.type,
643
+ key: t.key || s,
644
+ props: t.props,
645
+ dom: null,
646
+ parent: e,
647
+ alternate: null,
648
+ effectTag: "PLACEMENT",
649
+ lanes: 0,
650
+ childLanes: 0,
651
+ }),
652
+ null === n ? (e.child = a) : (n.sibling = a),
653
+ (n = a),
654
+ s++;
655
+ }
656
+ for (; r; ) (r.effectTag = "DELETION"), deletions.push(r), (r = r.sibling);
657
+ return e.child;
658
+ },
659
+ memoizedDiff = (() => {
660
+ const e = new WeakMap();
661
+ return (t, o) => {
662
+ const r = `${t?.type}-${o?.type}`;
663
+ e.has(t) || e.set(t, new Map());
664
+ const n = e.get(t);
665
+ if (n.has(r)) return n.get(r);
666
+ const a = [];
667
+ if (t?.type !== o?.type)
668
+ return a.push({ type: "REPLACE", newNode: o }), n.set(r, a), a;
669
+ if ("object" != typeof o)
670
+ return t !== o && a.push({ type: "TEXT", content: o }), n.set(r, a), a;
671
+ const s = diffProps(t.props, o.props);
672
+ return (
673
+ s && a.push({ type: "PROPS", patches: s }),
674
+ o.props.skipChildrenDiff ||
675
+ diffChildren(t.props.children, o.props.children, a),
676
+ n.set(r, a),
677
+ a
678
+ );
679
+ };
680
+ })(),
681
+ diffProps = (e, t) => {
682
+ const o = {};
683
+ let r = !1;
684
+ for (const n in e) "children" === n || n in t || ((r = !0), (o[n] = null));
685
+ for (const n in t)
686
+ "children" !== n && e[n] !== t[n] && ((r = !0), (o[n] = t[n]));
687
+ return r ? o : null;
688
+ },
689
+ diffChildren = (e, t, o) => {
690
+ const r = Array.isArray(e) ? e : [e],
691
+ n = Array.isArray(t) ? t : [t],
692
+ a = new Map();
693
+ r.forEach((e, t) => {
694
+ const o = e?.key || `index:${t}`;
695
+ a.set(o, { child: e, index: t });
696
+ });
697
+ const s = [];
698
+ let c = 0;
699
+ n.forEach((e, t) => {
700
+ const o = e?.key || `index:${t}`,
701
+ r = a.get(o);
702
+ if (r) {
703
+ const t = r.child,
704
+ n = r.index;
705
+ n !== c && s.push({ type: "REORDER", from: n, to: c });
706
+ const l = memoizedDiff(t, e);
707
+ l.length > 0 && s.push({ type: "UPDATE", index: c, patches: l }),
708
+ a.delete(o);
709
+ } else s.push({ type: "INSERT", index: c, node: e });
710
+ c++;
711
+ }),
712
+ a.forEach(({ index: e }) => {
713
+ s.push({ type: "REMOVE", index: e });
714
+ }),
715
+ s.length > 0 && o.push({ type: "CHILDREN", patches: s });
716
+ },
717
+ applyPatches = (e, t) => {
718
+ t.forEach((t) => {
719
+ switch (t.type) {
720
+ case "REPLACE":
721
+ const o = createDom(t.newNode);
722
+ e.parentNode.replaceChild(o, e);
723
+ break;
724
+ case "TEXT":
725
+ e.textContent = t.content;
726
+ break;
727
+ case "PROPS":
728
+ updateDomProperties(e, t.patches);
729
+ break;
730
+ case "CHILDREN":
731
+ applyChildrenPatches(e, t.patches);
732
+ }
733
+ });
734
+ },
735
+ updateDomProperties = (e, t) => {
736
+ Object.entries(t).forEach(([t, o]) => {
737
+ if (t.startsWith("on")) {
738
+ const r = t.toLowerCase().substring(2);
739
+ e._listeners &&
740
+ e._listeners[r] &&
741
+ e.removeEventListener(r, e._listeners[r]),
742
+ o &&
743
+ (e._listeners || (e._listeners = {}),
744
+ (e._listeners[r] = o),
745
+ e.addEventListener(r, o));
746
+ } else
747
+ "style" === t && "object" == typeof o
748
+ ? Object.assign(e.style, o)
749
+ : "className" === t
750
+ ? e.setAttribute("class", o)
751
+ : "boolean" == typeof o
752
+ ? o
753
+ ? e.setAttribute(t, "")
754
+ : e.removeAttribute(t)
755
+ : null === o
756
+ ? e.removeAttribute(t)
757
+ : e.setAttribute(t, o);
758
+ });
759
+ },
760
+ applyChildrenPatches = (e, t) => {
761
+ const o = Array.from(e.childNodes),
762
+ r = [];
763
+ t.forEach((e) => {
764
+ switch (e.type) {
765
+ case "REORDER":
766
+ r.push({ type: "MOVE", from: e.from, to: e.to, node: o[e.from] });
767
+ break;
768
+ case "REMOVE":
769
+ r.push({ type: "REMOVE", index: e.index, node: o[e.index] });
770
+ break;
771
+ case "INSERT":
772
+ r.push({ type: "INSERT", index: e.index, node: createDom(e.node) });
773
+ break;
774
+ case "UPDATE":
775
+ applyPatches(o[e.index], e.patches);
776
+ }
777
+ }),
778
+ r
779
+ .sort((e, t) =>
780
+ "REMOVE" === e.type ? -1 : "REMOVE" === t.type ? 1 : e.index - t.index
781
+ )
782
+ .forEach((t) => {
783
+ switch (t.type) {
784
+ case "MOVE":
785
+ e.insertBefore(t.node, e.childNodes[t.to] || null);
786
+ break;
787
+ case "REMOVE":
788
+ e.removeChild(t.node);
789
+ break;
790
+ case "INSERT":
791
+ e.insertBefore(t.node, e.childNodes[t.index] || null);
792
+ }
793
+ });
794
+ },
795
+ priorityLevels = {
796
+ IMMEDIATE: 1,
797
+ USER_BLOCKING: 2,
798
+ NORMAL: 3,
799
+ LOW: 4,
800
+ IDLE: 5,
801
+ },
802
+ scheduleWork = (e, t) => {
803
+ new Map().set(t, e);
804
+ };
805
+ let batchQueue = new Set(),
806
+ isProcessingBatch = !1;
807
+ const batchedUpdates = (e) => {
808
+ const t = isBatchingUpdates;
809
+ isBatchingUpdates = !0;
810
+ try {
811
+ return e();
812
+ } finally {
813
+ (isBatchingUpdates = t), isBatchingUpdates || flushBatchQueue();
814
+ }
815
+ },
816
+ flushBatchQueue = () => {
817
+ if (!isProcessingBatch) {
818
+ isProcessingBatch = !0;
819
+ try {
820
+ batchQueue.forEach((e) => {
821
+ e();
822
+ });
823
+ } finally {
824
+ (isProcessingBatch = !1), batchQueue.clear();
825
+ }
826
+ performSyncWork();
827
+ }
828
+ },
829
+ queueUpdate = (e) => {
830
+ batchQueue.add(e), isBatchingUpdates || flushBatchQueue();
831
+ },
832
+ performSyncWork = () => {
833
+ rerender();
834
+ };
835
+ (Olova.Transition = () => {
836
+ const [e, t] = Olova.State(!1);
837
+ return [
838
+ e,
839
+ Olova.Callback((e) => {
840
+ t(!0),
841
+ queueMicrotask(() => {
842
+ try {
843
+ e();
844
+ } finally {
845
+ t(!1);
846
+ }
847
+ });
848
+ }, []),
849
+ ];
850
+ }),
851
+ (Olova.DeferredValue = (e, t) => {
852
+ const [o, r] = Olova.State(e);
853
+ return (
854
+ Olova.Effect(() => {
855
+ const o = setTimeout(() => {
856
+ r(e);
857
+ }, t?.timeoutMs || 2e3);
858
+ return () => clearTimeout(o);
859
+ }, [e, t?.timeoutMs]),
860
+ o
861
+ );
862
+ }),
863
+ (Olova.renderToString = (e) => {
864
+ let t = "";
865
+ var o;
866
+ return "string" != typeof (o = e) || (t += o), t;
867
+ });
868
+ const SyntheticEvent = {
869
+ preventDefault() {},
870
+ stopPropagation() {},
871
+ persist() {},
872
+ isPersistent() {},
873
+ nativeEvent: null,
874
+ target: null,
875
+ currentTarget: null,
876
+ type: null,
877
+ };
878
+ Olova.lazy = (e) => {
879
+ let t = null,
880
+ o = null;
881
+ return (r) => {
882
+ if (
883
+ (t ||
884
+ o ||
885
+ (o = e()
886
+ .then((e) => {
887
+ t = e.default || e;
888
+ })
889
+ .catch((e) => {
890
+ throw e;
891
+ })),
892
+ t)
893
+ )
894
+ return Olova.createElement(t, r);
895
+ throw o;
896
+ };
897
+ };
898
+ export const {
899
+ State: State,
900
+ createContext: createContext,
901
+ Context: Context,
902
+ Effect: Effect,
903
+ Reducer: Reducer,
904
+ Callback: Callback,
905
+ Memo: Memo,
906
+ Ref: Ref,
907
+ LayoutEffect: LayoutEffect,
908
+ ImperativeHandle: ImperativeHandle,
909
+ Fragment: Fragment,
910
+ createStore: createStore,
911
+ Provider: Provider,
912
+ Selector: Selector,
913
+ Dispatch: Dispatch,
914
+ combineReducers: combineReducers,
915
+ createAction: createAction,
916
+ applyMiddleware: applyMiddleware,
917
+ Suspense: Suspense,
918
+ ErrorBoundary: ErrorBoundary,
919
+ Transition: Transition,
920
+ DeferredValue: DeferredValue,
921
+ renderToString: renderToString,
922
+ lazy: lazy,
923
+ StrictMode: StrictMode,
924
+ Profiler: Profiler,
925
+ DebugValue: DebugValue,
926
+ Id: Id,
927
+ InsertionEffect: InsertionEffect,
928
+ Optimistic: Optimistic,
929
+ SyncExternalStore: SyncExternalStore,
930
+ ActionState: ActionState,
931
+ } = Olova;
932
+ export default Olova;
933
+ (Olova.StrictMode = ({ children: e }) => {
934
+ const t = (e) => {
935
+ if ("function" == typeof e.type) {
936
+ Object.getOwnPropertyNames(e.type.prototype).forEach((t) => {
937
+ t.startsWith("UNSAFE_") &&
938
+ console.warn(
939
+ `StrictMode: Detected deprecated method ${t} in component ${e.type.name}`
940
+ );
941
+ }),
942
+ e.props && e.props.children && e.props.children.forEach(t);
943
+ }
944
+ };
945
+ return e.forEach(t), e[0];
946
+ }),
947
+ (Olova.Profiler = ({ id: e, onRender: t, children: o }) => {
948
+ if ("function" != typeof t)
949
+ return console.warn("Profiler requires an onRender callback"), o;
950
+ const r = performance.now();
951
+ return (
952
+ Olova.Effect(() => {
953
+ const o = performance.now(),
954
+ n = o - r;
955
+ t({
956
+ id: e,
957
+ actualDuration: n,
958
+ baseDuration: n,
959
+ startTime: r,
960
+ commitTime: o,
961
+ interactions: new Set(),
962
+ phase: "mount",
963
+ });
964
+ }, []),
965
+ o
966
+ );
967
+ }),
968
+ "production" !== process.env.NODE_ENV &&
969
+ (Olova.__DEV__ = {
970
+ componentStack: [],
971
+ markComponentRender: (e) => {
972
+ Olova.__DEV__.componentStack.push(e),
973
+ console.log(`Component rendered: ${e.name || "Anonymous"}`);
974
+ },
975
+ clearComponentStack: () => {
976
+ Olova.__DEV__.componentStack = [];
977
+ },
978
+ });
979
+ const handleError = (e, t) => {
980
+ console.error("Error in Olova application:", e),
981
+ console.error("Component stack:", t);
982
+ let o = null,
983
+ r = t[t.length - 1];
984
+ for (; r && !o; )
985
+ r.type && r.type.prototype instanceof Olova.ErrorBoundary && (o = r),
986
+ (r = r.parent);
987
+ if (!o) throw e;
988
+ o.setState({ hasError: !0, error: e });
989
+ },
990
+ cleanupComponent = (e) => {
991
+ effects.has(e) &&
992
+ (effects.get(e).forEach((e) => {
993
+ e.cleanup && e.cleanup();
994
+ }),
995
+ effects.delete(e)),
996
+ states.has(e) && states.delete(e),
997
+ memos.has(e) && memos.delete(e),
998
+ refs.has(e) && refs.delete(e);
999
+ },
1000
+ sanitizeProps = (e) => {
1001
+ if (e.dangerouslySetInnerHTML) {
1002
+ const t = e.dangerouslySetInnerHTML.__html.replace(
1003
+ /<script[^>]*>([\S\s]*?)<\/script>/gi,
1004
+ ""
1005
+ );
1006
+ e.dangerouslySetInnerHTML.__html = t;
1007
+ }
1008
+ return e;
1009
+ };
1010
+ (Olova.DebugValue = (e, t) => {
1011
+ if ("production" !== process.env.NODE_ENV) {
1012
+ const o = t ? t(e) : e;
1013
+ console.log("Debug value:", o);
1014
+ }
1015
+ }),
1016
+ (Olova.Id = () => {
1017
+ const [e] = Olova.State(
1018
+ () => `olova-${Math.random().toString(36).slice(2)}`
1019
+ );
1020
+ return e;
1021
+ }),
1022
+ (Olova.InsertionEffect = (e, t) => {
1023
+ Olova.LayoutEffect(e, t);
1024
+ }),
1025
+ (Olova.SyncExternalStore = (e, t, o) => {
1026
+ const [r, n] = Olova.State(t);
1027
+ return (
1028
+ Olova.Effect(
1029
+ () => (
1030
+ n(t()),
1031
+ e(() => {
1032
+ n(t());
1033
+ })
1034
+ ),
1035
+ [e, t]
1036
+ ),
1037
+ r
1038
+ );
1039
+ }),
1040
+ (Olova.Optimistic = (e, t) => {
1041
+ const [o, r] = Olova.State(e),
1042
+ [n, a] = Olova.Transition();
1043
+ return [
1044
+ o,
1045
+ (e) => {
1046
+ a(() => {
1047
+ const n = t(o, e);
1048
+ r(n);
1049
+ });
1050
+ },
1051
+ ];
1052
+ }),
1053
+ (Olova.ActionState = (e, t) => {
1054
+ const [o, r] = Olova.State(e),
1055
+ [n, a] = Olova.State(null),
1056
+ [s, c] = Olova.State(null);
1057
+ return [
1058
+ o,
1059
+ async (e) => {
1060
+ try {
1061
+ a(o);
1062
+ const n = await t(o, e);
1063
+ r(n), a(null), c(null);
1064
+ } catch (e) {
1065
+ c(e), a(null);
1066
+ }
1067
+ },
1068
+ { pending: n, error: s },
1069
+ ];
1070
+ });
1071
+ const diffCache = new WeakMap(),
1072
+ memoizedCreateVirtualDom = (e) => {
1073
+ if (diffCache.has(e)) return diffCache.get(e);
1074
+ const t = createVirtualDom(e);
1075
+ return diffCache.set(e, t), t;
1076
+ };
1077
+ class UpdateQueue {
1078
+ constructor() {
1079
+ this.updates = new Map();
1080
+ }
1081
+ enqueue(e, t) {
1082
+ this.updates.has(e) || this.updates.set(e, new Set()),
1083
+ this.updates.get(e).add(t);
1084
+ }
1085
+ dequeue() {
1086
+ const e = Array.from(this.updates.keys()).sort();
1087
+ for (const t of e) {
1088
+ const e = this.updates.get(t);
1089
+ if (e.size > 0) {
1090
+ const o = e.values().next().value;
1091
+ return e.delete(o), 0 === e.size && this.updates.delete(t), o;
1092
+ }
1093
+ }
1094
+ return null;
1095
+ }
1096
+ }
1097
+ const updateQueue = new UpdateQueue(),
1098
+ componentCache = new WeakMap(),
1099
+ getCachedComponent = (e, t) => {
1100
+ const o = JSON.stringify(t);
1101
+ componentCache.has(e) || componentCache.set(e, new Map());
1102
+ const r = componentCache.get(e);
1103
+ return r.has(o) || r.set(o, new e(t)), r.get(o);
1104
+ },
1105
+ batchDomOperations = (e) => {
1106
+ const t = document.createDocumentFragment();
1107
+ return (
1108
+ e.forEach((e) => {
1109
+ if ("INSERT" === e.type) t.appendChild(e.node);
1110
+ }),
1111
+ t
1112
+ );
1113
+ },
1114
+ eventDelegator = {
1115
+ handlers: new Map(),
1116
+ delegate(e, t) {
1117
+ this.handlers.has(e) ||
1118
+ (this.handlers.set(e, new Set()),
1119
+ document.addEventListener(e, this.handleEvent.bind(this))),
1120
+ this.handlers.get(e).add(t);
1121
+ },
1122
+ handleEvent(e) {
1123
+ const t = this.handlers.get(e.type);
1124
+ t && t.forEach((t) => t(e));
1125
+ },
1126
+ },
1127
+ createImmutableState = (e) => ({
1128
+ value: e,
1129
+ set(e) {
1130
+ return !Object.is(this.value, e) && ((this.value = e), !0);
1131
+ },
1132
+ });
1133
+ let renderThrottleTimeout = null;
1134
+ const throttledRerender = () => {
1135
+ renderThrottleTimeout ||
1136
+ (renderThrottleTimeout = setTimeout(() => {
1137
+ rerender(), (renderThrottleTimeout = null);
1138
+ }, 16));
1139
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "olova",
3
- "version": "1.0.23",
3
+ "version": "2.0.1",
4
4
  "description": "A lightweight JavaScript framework for building reactive applications.",
5
5
  "main": "dist/olova.js",
6
6
  "keywords": [