frontend-hamroun 1.1.46 → 1.1.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,240 +1,167 @@
1
- # Your Package Name
1
+ # Frontend Hamroun
2
2
 
3
- A lightweight Virtual DOM and hooks implementation with JSX support.
3
+ A lightweight, modern frontend framework with hooks, virtual DOM, and server-side rendering capabilities.
4
4
 
5
- ## Installation
5
+ ## Features
6
6
 
7
- ```bash
8
- npm install your-package-name
9
- ```
7
+ - 🚀 Fast Virtual DOM implementation
8
+ - 🎯 Hooks-based state management
9
+ - 🌐 Server-side rendering
10
+ - 📱 Router with dynamic routes
11
+ - 🔄 Context API
12
+ - 🛠️ TypeScript support
13
+ - 📦 Small bundle size (~12KB gzipped)
14
+ - ⚡ Code splitting support
10
15
 
11
- ## Quick Start
12
-
13
- Create a new project using:
16
+ ## Installation
14
17
 
15
18
  ```bash
16
- npx create-frontend-app my-app
19
+ npm install frontend-hamroun
17
20
  # or
18
- npm create frontend-app@latest my-app
19
- ```
20
- Then:
21
-
22
- ```bash
23
- cd my-app
24
- npm install
25
- npm run dev
21
+ yarn add frontend-hamroun
26
22
  ```
27
23
 
28
- ## Usage
24
+ ## Quick Start
29
25
 
30
- ```jsx
31
- import { render, useState } from 'your-package-name';
26
+ ```tsx
27
+ import { render, useState } from 'frontend-hamroun';
32
28
 
33
- function App() {
29
+ function Counter() {
34
30
  const [count, setCount] = useState(0);
31
+
35
32
  return (
36
- <div>
37
- <h1>Count: {count}</h1>
38
- <button onClick={() => setCount(count + 1)}>Increment</button>
39
- </div>
33
+ <button onClick={() => setCount(count + 1)}>
34
+ Count: {count}
35
+ </button>
40
36
  );
41
37
  }
42
38
 
43
- render(<App />, document.getElementById('root'));
39
+ render(<Counter />, document.getElementById('root'));
44
40
  ```
45
41
 
46
- ## Features
42
+ ## Core Features
47
43
 
48
- - Virtual DOM with efficient diffing
49
- - Hooks (useState, useEffect, useMemo, useRef)
50
- - Context API
51
- - Batch updates
52
- - Hydration support
53
-
54
- ## Hooks
55
-
56
- ### useState
57
- Manages component state.
44
+ ### Hooks
58
45
 
59
46
  ```tsx
60
- const [state, setState] = useState(initialValue);
61
- ```
47
+ import { useState, useEffect, useMemo, useContext } from 'frontend-hamroun';
62
48
 
63
- ### useEffect
64
- Handles side effects in components.
49
+ // State Management
50
+ const [state, setState] = useState(initialState);
65
51
 
66
- ```tsx
52
+ // Side Effects
67
53
  useEffect(() => {
68
54
  // Effect code
69
55
  return () => {
70
56
  // Cleanup code
71
57
  };
72
58
  }, [dependencies]);
73
- ```
74
-
75
- ### useMemo
76
- Memoizes expensive computations.
77
59
 
78
- ```tsx
79
- const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
60
+ // Memoization
61
+ const memoizedValue = useMemo(() => computeExpensiveValue(deps), [deps]);
80
62
  ```
81
63
 
82
- ### useRef
83
- Creates a mutable reference.
64
+ ### Routing
84
65
 
85
66
  ```tsx
86
- const ref = useRef(initialValue);
87
- ```
67
+ import { Link, useRouter } from 'frontend-hamroun';
88
68
 
89
- ### useErrorBoundary
90
- Handles component errors.
91
-
92
- ```tsx
93
- const [error, resetError] = useErrorBoundary();
69
+ function App() {
70
+ const router = useRouter();
71
+
72
+ return (
73
+ <div>
74
+ <nav>
75
+ <Link href="/">Home</Link>
76
+ <Link href="/about">About</Link>
77
+ </nav>
78
+ {router.pathname === '/' && <Home />}
79
+ {router.pathname === '/about' && <About />}
80
+ </div>
81
+ );
82
+ }
94
83
  ```
95
84
 
96
- ## Context API
97
-
98
- Create and use shared state across components.
85
+ ### Context API
99
86
 
100
87
  ```tsx
101
- const ThemeContext = createContext('light');
88
+ import { createContext, useContext } from 'frontend-hamroun';
102
89
 
103
- function App() {
104
- return (
105
- <ThemeContext.Provider value="dark">
106
- <Child />
107
- </ThemeContext.Provider>
108
- );
109
- }
90
+ const ThemeContext = createContext('light');
110
91
 
111
- function Child() {
92
+ function ThemedButton() {
112
93
  const theme = useContext(ThemeContext);
113
- // Or use selector for performance
114
- const isDark = ThemeContext.useSelector(theme => theme === 'dark');
94
+ return <button className={theme}>Click me</button>;
115
95
  }
116
96
  ```
117
97
 
118
- ## Performance Optimization
119
-
120
- ### Batch Updates
121
- Group multiple state updates together.
98
+ ### Server-Side Rendering
122
99
 
123
100
  ```tsx
124
- import { batchUpdates } from 'your-package-name';
101
+ import { renderToString } from 'frontend-hamroun';
125
102
 
126
- batchUpdates(() => {
127
- setValue1(newValue1);
128
- setValue2(newValue2);
129
- });
103
+ const html = await renderToString(<App />);
130
104
  ```
131
105
 
132
- ### Component Memoization
133
- Prevent unnecessary re-renders.
106
+ ## CLI Tools
134
107
 
135
- ```tsx
136
- const MemoizedComponent = useMemo(() => (
137
- <ExpensiveComponent prop={value} />
138
- ), [value]);
108
+ Create a new project:
109
+
110
+ ```bash
111
+ npx create-frontend-app my-app
139
112
  ```
140
113
 
141
- ## Server-Side Rendering
114
+ ## Performance
142
115
 
143
- ```tsx
144
- import { hydrate } from 'your-package-name';
116
+ - Initial bundle: 12KB gzipped
117
+ - Dynamic imports for code splitting
118
+ - Automatic batching for state updates
119
+ - Efficient virtual DOM diffing
145
120
 
146
- // On the client
147
- hydrate(<App />, document.getElementById('root'));
148
- ```
121
+ ## Security
149
122
 
150
- ## Event Handling
123
+ - XSS protection
124
+ - Content Security Policy support
125
+ - Type-safe props
126
+ - Secure by default
151
127
 
152
- ```tsx
153
- function Button() {
154
- return (
155
- <button
156
- onClick={(e) => handleClick(e)}
157
- onMouseOver={(e) => handleHover(e)}
158
- >
159
- Click me
160
- </button>
161
- );
162
- }
163
- ```
128
+ ## Browser Support
164
129
 
165
- ## Styling
130
+ - Chrome (latest)
131
+ - Firefox (latest)
132
+ - Safari (latest)
133
+ - Edge (latest)
166
134
 
167
- ```tsx
168
- function StyledComponent() {
169
- return (
170
- <div style={{
171
- color: 'blue',
172
- padding: '20px'
173
- }}>
174
- Styled content
175
- </div>
176
- );
177
- }
178
- ```
135
+ ## Development Tools
179
136
 
180
- ## Error Handling
137
+ - TypeScript support
138
+ - Hot Module Replacement
139
+ - Developer tools extension
140
+ - Error boundaries
141
+ - Performance monitoring
181
142
 
182
- ```tsx
183
- function ErrorBoundary() {
184
- const [error, resetError] = useErrorBoundary();
185
-
186
- if (error) {
187
- return (
188
- <div>
189
- <h1>Something went wrong!</h1>
190
- <button onClick={resetError}>Try again</button>
191
- </div>
192
- );
193
- }
194
-
195
- return <ComponentThatMightError />;
196
- }
197
- ```
143
+ ## Contributing
198
144
 
199
- ## Best Practices
145
+ 1. Fork the repository
146
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
147
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
148
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
149
+ 5. Open a Pull Request
200
150
 
201
- 1. Use batch updates for multiple state changes
202
- 2. Implement error boundaries for error handling
203
- 3. Use context selectors for better performance
204
- 4. Memoize expensive computations
205
- 5. Clean up effects when components unmount
206
- 6. Keep components small and focused
207
- 7. Use proper TypeScript types for better development experience
151
+ ## License
208
152
 
209
- ## API Reference
153
+ MIT License - see the [LICENSE](LICENSE) file for details.
210
154
 
211
- ### Core
212
- - `render(element, container)`
213
- - `hydrate(element, container)`
214
- - `createElement(vnode)`
155
+ ## Support
215
156
 
216
- ### Hooks
217
- - `useState<T>(initial: T)`
218
- - `useEffect(callback, deps?)`
219
- - `useMemo(factory, deps)`
220
- - `useRef(initial)`
221
- - `useErrorBoundary()`
222
-
223
- ### Context
224
- - `createContext(defaultValue)`
225
- - `useContext(Context)`
226
- - `Context.Provider`
227
- - `Context.Consumer`
228
- - `Context.useSelector`
229
-
230
- ### Performance
231
- - `batchUpdates(callback)`
157
+ - Documentation: [Link to docs]
158
+ - Issues: [GitHub Issues]
159
+ - Discussions: [GitHub Discussions]
232
160
 
233
- ## License
161
+ ## Team
234
162
 
235
- MIT License - feel free to use in any project.
163
+ - Hamroun - Lead Developer
236
164
 
237
- ## Contributing
165
+ ## Acknowledgments
238
166
 
239
- Contributions are welcome! Please read our contributing guidelines and submit pull requests.
240
- `````
167
+ Special thanks to the open-source community and all contributors.
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let e=!1;const t=[];function n(n){if(e)t.push(n);else{e=!0;try{for(n();t.length>0;){const e=t.shift();null==e||e()}}finally{e=!1}}}let r=0;const o=new Map,s=new Map,a=new Map,i=new Map,c=new Map;let l=null,u=null,p=null;const d="undefined"==typeof window,f=new Map;function h(e,t,n){l=e,u=n,p=t}function w(){return r++,s.set(r,0),r}function y(){d&&f.delete(r),r=0}function m(t){if(!r)throw new Error("useState must be called within a render");if(d){f.has(r)||f.set(r,new Map);const e=f.get(r),n=s.get(r)||0;e.has(n)||e.set(n,t);const o=e.get(n),a=e=>{};return s.set(r,n+1),[o,a]}o.has(r)||o.set(r,[]);const a=o.get(r),i=s.get(r);i>=a.length&&a.push(t);const c=a[i];return s.set(r,i+1),[c,t=>{const o="function"==typeof t?t(a[i]):t;a[i]!==o&&(a[i]=o,e?n((()=>b(r))):b(r))}]}function g(e,t){if(!r)throw new Error("useEffect must be called within a render");const n=s.get(r);a.has(r)||a.set(r,[]);const o=a.get(r),i=o[n];i&&t&&i.deps&&!t.some(((e,t)=>e!==i.deps[t]))||((null==i?void 0:i.cleanup)&&i.cleanup(),queueMicrotask((()=>{const r=e()||void 0;o[n]={cleanup:r,deps:t}}))),s.set(r,n+1)}async function b(e){try{const t=a.get(e);t&&(t.forEach((e=>{e.cleanup&&e.cleanup()})),a.set(e,[])),l&&u&&p&&await l(p,u)}catch(t){console.error("Error during rerender:",t)}}function v(e,t){console.log("JSX Transform:",{type:e,props:t});const n={...t};return arguments.length>2&&(n.children=Array.prototype.slice.call(arguments,2)),{type:e,props:n}}async function x(e){var t;if(console.log("Creating element from:",e),null==e)return document.createTextNode("");if("boolean"==typeof e)return document.createTextNode("");if("number"==typeof e||"string"==typeof e)return document.createTextNode(String(e));if(Array.isArray(e)){const t=document.createDocumentFragment();for(const n of e){const e=await x(n);t.appendChild(e)}return t}if("type"in e&&void 0!==e.props){const{type:r,props:o}=e;if("function"==typeof r)try{const e=await r(o||{}),t=await x(e);return t instanceof Element&&t.setAttribute("data-component-id",r.name||r.toString()),t}catch(n){return console.error("Error rendering component:",n),document.createTextNode("")}const s=document.createElement(r);for(const[e,n]of Object.entries(o||{}))if("children"!==e)if(e.startsWith("on")&&"function"==typeof n){const r=e.toLowerCase().slice(2),o=null==(t=s.__events)?void 0:t[r];o&&s.removeEventListener(r,o),s.addEventListener(r,n),s.__events||(s.__events={}),s.__events[r]=n}else"style"===e&&"object"==typeof n?Object.assign(s.style,n):"className"===e?s.setAttribute("class",String(n)):"key"!==e&&"ref"!==e&&s.setAttribute(e,String(n));const a=null==o?void 0:o.children;if(null!=a){const e=Array.isArray(a)?a.flat():[a];for(const t of e){const e=await x(t);s.appendChild(e)}}return s}return document.createTextNode(String(e))}let S=!1;async function E(e,t){console.log("Rendering to:",t.id),n((async()=>{w();try{h(E,e,t);const n=await x(e);S||(t.innerHTML=""),t.appendChild(n)}finally{y()}}))}function j(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}let A={pathname:"undefined"!=typeof window?window.location.pathname:"/",search:"undefined"!=typeof window?window.location.search:"",hash:"undefined"!=typeof window?window.location.hash:"",params:{}};const M=new Set;function C(e,t={}){"undefined"!=typeof window&&function(e,t={}){const n=new URL(e,window.location.origin),r={pathname:n.pathname,search:n.search,hash:n.hash,params:{}};t.replace?window.history.replaceState(r,"",n.toString()):window.history.pushState(r,"",n.toString()),A=r,M.forEach((e=>e(r))),t.scroll&&window.scrollTo(0,0)}(e,t)}exports.Fragment=({children:e})=>e,exports.Link=function({href:e,children:t,replace:n=!1,className:r,style:o,...s}){return{type:"a",props:{href:e,onClick:t=>{t.preventDefault(),C(e,{replace:n})},className:r,style:o,...s,children:t}}},exports.batchUpdates=n,exports.createContext=function(e){return{Provider:({value:e,children:t})=>t,Consumer:({children:t})=>t(e),_id:Symbol(),useSelector:t=>t(e)}},exports.hydrate=async function(e,t){S=!0;try{await E(e,t)}finally{S=!1}},exports.jsx=v,exports.jsxs=v,exports.render=E,exports.renderToString=async function e(t){w(),h((()=>{}),t,null);try{if(null==t)return"";if("boolean"==typeof t)return"";if("number"==typeof t||"string"==typeof t)return j(String(t));if(Array.isArray(t)){return(await Promise.all(t.map(e))).join("")}if("type"in t&&void 0!==t.props){const{type:o,props:s}=t;if("function"==typeof o)try{w();const t=await o(s||{}),n=await e(t);return y(),n}catch(r){return console.error("Error rendering component:",r),""}let a=`<${o}`;for(const[e,t]of Object.entries(s||{}))"children"!==e&&("className"===e?a+=` class="${j(String(t))}"`:"style"===e&&"object"==typeof t?a+=` style="${n=t||{},Object.entries(n).map((([e,t])=>{return`${n=e,n.replace(/[A-Z]/g,(e=>"-"+e.toLowerCase()))}:${t}`;var n})).join(";")}"`:e.startsWith("on")||(a+=` ${e}="${j(String(t))}"`));if(new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]).has(o))return a+"/>";if(a+=">",null==s?void 0:s.children){const t=Array.isArray(s.children)?s.children:[s.children];a+=(await Promise.all(t.map(e))).join("")}return a+`</${o}>`}return j(String(t))}finally{y()}var n},exports.useContext=function(e){return e},exports.useEffect=g,exports.useErrorBoundary=function(){const[e,t]=m(null);return[e,()=>t(null)]},exports.useMemo=function(e,t){if(!r)throw new Error("useMemo must be called within a render");const n=s.get(r);i.has(r)||i.set(r,[]);const o=i.get(r),a=o[n];if(!a||t&&t.some(((e,t)=>!Object.is(e,a.deps[t])))){const a=e();return o[n]={value:a,deps:t},s.set(r,n+1),a}return s.set(r,n+1),a.value},exports.useRef=function(e){if(!r)throw new Error("useRef must be called within a render");const t=s.get(r);c.has(r)||c.set(r,[]);const n=c.get(r);if(t>=n.length){const o={current:e};return n.push(o),s.set(r,t+1),o}const o=n[t];return s.set(r,t+1),o},exports.useRouter=function(){const[e,t]=m(A);return g((()=>{const e=e=>{t(e)},n=()=>{A={pathname:window.location.pathname,search:window.location.search,hash:window.location.hash,params:{}},t(A)};return M.add(e),window.addEventListener("popstate",n),()=>{M.delete(e),window.removeEventListener("popstate",n)}}),[]),{...e,push:(e,t)=>C(e,t),replace:(e,t)=>C(e,{...t,replace:!0}),back:()=>window.history.back(),forward:()=>window.history.forward()}},exports.useState=m;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let e=!1;const t=[];function n(n){if(e)t.push(n);else{e=!0;try{for(n();t.length>0;){const e=t.shift();null==e||e()}}finally{e=!1}}}let r=0;const o=new Map,s=new Map,i=new Map,a=new Map,c=new Map;let l=null,p=null,u=null;const d="undefined"==typeof window,f=new Map;function h(t){if(!r)throw new Error("useState must be called within a render");if(d){f.has(r)||f.set(r,new Map);const e=f.get(r),n=s.get(r)||0;e.has(n)||e.set(n,t);const o=e.get(n),i=e=>{};return s.set(r,n+1),[o,i]}o.has(r)||o.set(r,[]);const i=o.get(r),a=s.get(r);a>=i.length&&i.push(t);const c=i[a];return s.set(r,a+1),[c,t=>{const o="function"==typeof t?t(i[a]):t;i[a]!==o&&(i[a]=o,e?n((()=>y(r))):y(r))}]}function w(e,t){if(!r)throw new Error("useEffect must be called within a render");const n=s.get(r);i.has(r)||i.set(r,[]);const o=i.get(r),a=o[n];a&&t&&a.deps&&!t.some(((e,t)=>e!==a.deps[t]))||((null==a?void 0:a.cleanup)&&a.cleanup(),queueMicrotask((()=>{const r=e()||void 0;o[n]={cleanup:r,deps:t}}))),s.set(r,n+1)}async function y(e){try{const t=i.get(e);t&&(t.forEach((e=>{e.cleanup&&e.cleanup()})),i.set(e,[])),l&&p&&u&&await l(u,p)}catch(t){console.error("Error during rerender:",t)}}function m(e,t){console.log("JSX Transform:",{type:e,props:t});const n={...t};return arguments.length>2&&(n.children=Array.prototype.slice.call(arguments,2)),{type:e,props:n}}async function g(e){var t;if(console.log("Creating element from:",e),null==e)return document.createTextNode("");if("boolean"==typeof e)return document.createTextNode("");if("number"==typeof e||"string"==typeof e)return document.createTextNode(String(e));if(Array.isArray(e)){const t=document.createDocumentFragment();for(const n of e){const e=await g(n);t.appendChild(e)}return t}if("type"in e&&void 0!==e.props){const{type:r,props:o}=e;if("function"==typeof r)try{const e=await r(o||{}),t=await g(e);return t instanceof Element&&t.setAttribute("data-component-id",r.name||r.toString()),t}catch(n){return console.error("Error rendering component:",n),document.createTextNode("")}const s=document.createElement(r);for(const[e,n]of Object.entries(o||{}))if("children"!==e)if(e.startsWith("on")&&"function"==typeof n){const r=e.toLowerCase().slice(2),o=null==(t=s.__events)?void 0:t[r];o&&s.removeEventListener(r,o),s.addEventListener(r,n),s.__events||(s.__events={}),s.__events[r]=n}else"style"===e&&"object"==typeof n?Object.assign(s.style,n):"className"===e?s.setAttribute("class",String(n)):"key"!==e&&"ref"!==e&&s.setAttribute(e,String(n));const i=null==o?void 0:o.children;if(null!=i){const e=Array.isArray(i)?i.flat():[i];for(const t of e){const e=await g(t);s.appendChild(e)}}return s}return document.createTextNode(String(e))}let b=!1;async function v(e,t){console.log("Rendering to:",t.id),n((async()=>{r++,s.set(r,0);try{!function(e,t,n){l=e,p=n,u=t}(v,e,t);const n=await g(e);b||(t.innerHTML=""),t.appendChild(n)}finally{d&&f.delete(r),r=0}}))}async function x(e){var t,n;if(null==e||"boolean"==typeof e)return"";if("number"==typeof e||"string"==typeof e)return $(String(e));if("function"==typeof e){return x(await e({}))}if(e.type){if("function"==typeof e.type){return x(await e.type(e.props||{}))}let r=`<${e.type}`;for(const[t,o]of Object.entries(e.props||{}))"children"!==t&&"key"!==t&&"ref"!==t&&("className"===t?r+=` class="${$(String(o))}"`:"style"===t&&"object"==typeof o&&null!==o?r+=` style="${n=o,Object.entries(n).map((([e,t])=>`${e}: ${t}`)).join("; ")}"`:t.startsWith("on")||(r+=` ${t}="${$(String(o))}"`));if(r+=">",null==(t=e.props)?void 0:t.children){const t=Array.isArray(e.props.children)?e.props.children:[e.props.children];for(const e of t)r+=await x(e)}return r+=`</${e.type}>`,r}return""}function $(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}let S={pathname:"undefined"!=typeof window?window.location.pathname:"/",search:"undefined"!=typeof window?window.location.search:"",hash:"undefined"!=typeof window?window.location.hash:"",params:{}};const E=new Set;function j(e,t={}){"undefined"!=typeof window&&function(e,t={}){const n=new URL(e,window.location.origin),r={pathname:n.pathname,search:n.search,hash:n.hash,params:{}};t.replace?window.history.replaceState(r,"",n.toString()):window.history.pushState(r,"",n.toString()),S=r,E.forEach((e=>e(r))),t.scroll&&window.scrollTo(0,0)}(e,t)}exports.Fragment=({children:e})=>e,exports.Link=function({href:e,children:t,replace:n=!1,className:r,style:o,...s}){return{type:"a",props:{href:e,onClick:t=>{t.preventDefault(),j(e,{replace:n})},className:r,style:o,...s,children:t}}},exports.batchUpdates=n,exports.createContext=function(e){return{Provider:({value:e,children:t})=>t,Consumer:({children:t})=>t(e),_id:Symbol(),useSelector:t=>t(e)}},exports.hydrate=async function(e,t){b=!0;try{await v(e,t)}finally{b=!1}},exports.jsx=m,exports.jsxs=m,exports.render=v,exports.renderToString=async function(e,t={}){try{return function(e,t){const{title:n,description:r="",scripts:o=[],styles:s=[],initialState:i={},meta:a={},bodyAttrs:c={},htmlAttrs:l={lang:"en"}}=t,p=Object.entries(l).map((([e,t])=>`${e}="${t}"`)).join(" "),u=Object.entries(c).map((([e,t])=>`${e}="${t}"`)).join(" ");return`<!DOCTYPE html>\n<html ${p}>\n <head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n ${r?`<meta name="description" content="${r}">\n`:""}${Object.entries(a).map((([e,t])=>` <meta name="${e}" content="${t}">`)).join("\n")}\n <title>${n}</title>\n${s.map((e=>` <link rel="stylesheet" href="${e}">`)).join("\n")}\n <script>\n window.__INITIAL_STATE__ = ${JSON.stringify(i)};\n <\/script>\n </head>\n <body ${u}>\n <div id="root">${e}</div>\n${o.map((e=>` <script src="${e}" defer><\/script>`)).join("\n")}\n </body>\n</html>`}(await x(e),{title:"Frontend Hamroun App",...t})}catch(n){return console.error("Error during server rendering:",n),""}},exports.useContext=function(e){return e},exports.useEffect=w,exports.useErrorBoundary=function(){const[e,t]=h(null);return[e,()=>t(null)]},exports.useMemo=function(e,t){if(!r)throw new Error("useMemo must be called within a render");const n=s.get(r);a.has(r)||a.set(r,[]);const o=a.get(r),i=o[n];if(!i||t&&t.some(((e,t)=>!Object.is(e,i.deps[t])))){const i=e();return o[n]={value:i,deps:t},s.set(r,n+1),i}return s.set(r,n+1),i.value},exports.useRef=function(e){if(!r)throw new Error("useRef must be called within a render");const t=s.get(r);c.has(r)||c.set(r,[]);const n=c.get(r);if(t>=n.length){const o={current:e};return n.push(o),s.set(r,t+1),o}const o=n[t];return s.set(r,t+1),o},exports.useRouter=function(){const[e,t]=h(S);return w((()=>{const e=e=>{t(e)},n=()=>{S={pathname:window.location.pathname,search:window.location.search,hash:window.location.hash,params:{}},t(S)};return E.add(e),window.addEventListener("popstate",n),()=>{E.delete(e),window.removeEventListener("popstate",n)}}),[]),{...e,push:(e,t)=>j(e,t),replace:(e,t)=>j(e,{...t,replace:!0}),back:()=>window.history.back(),forward:()=>window.history.forward()}},exports.useState=h;
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/batch.ts","../src/hooks.ts","../src/jsx-runtime.ts","../src/renderer.ts","../src/server-renderer.ts","../src/router.ts","../src/link.tsx","../src/context.ts"],"sourcesContent":["export let isBatching = false;\r\nconst queue: Function[] = [];\r\n\r\nexport function batchUpdates(fn: Function) {\r\n if (isBatching) {\r\n queue.push(fn);\r\n return;\r\n }\r\n\r\n isBatching = true;\r\n try {\r\n fn();\r\n while (queue.length > 0) {\r\n const nextFn = queue.shift();\r\n nextFn?.();\r\n }\r\n } finally {\r\n isBatching = false;\r\n }\r\n}\r\n\r\nexport function getIsBatching() {\r\n return isBatching;\r\n}\r\n","import { createElement } from './jsx-runtime';\r\nimport { batchUpdates, isBatching } from './batch';\r\nimport { diff } from './vdom';\r\n\r\nlet currentRender: number = 0;\r\nconst states = new Map<number, any[]>();\r\nconst stateIndices = new Map<number, number>();\r\nconst effects = new Map<number, Effect[]>();\r\nconst memos = new Map<number, { value: any; deps: any[] }[]>();\r\nconst refs = new Map<number, any[]>();\r\n\r\ninterface Effect {\r\n cleanup?: () => void;\r\n deps?: any[];\r\n}\r\n\r\n// Add at the top with other declarations\r\nlet globalRenderCallback: ((element: any, container: HTMLElement) => void) | null = null;\r\nlet globalContainer: HTMLElement | null = null;\r\nlet currentElement: any = null;\r\n\r\nconst isServer = typeof window === 'undefined';\r\nconst serverStates = new Map<number, any>();\r\n\r\nexport function setRenderCallback(\r\n callback: (element: any, container: HTMLElement) => void,\r\n element: any,\r\n container: HTMLElement\r\n) {\r\n globalRenderCallback = callback;\r\n globalContainer = container;\r\n currentElement = element;\r\n}\r\n\r\nexport function prepareRender() {\r\n currentRender++;\r\n stateIndices.set(currentRender, 0);\r\n return currentRender;\r\n}\r\n\r\nexport function finishRender() {\r\n if (isServer) {\r\n serverStates.delete(currentRender);\r\n }\r\n currentRender = 0;\r\n}\r\n\r\nexport function useState<T>(initial: T): [T, (value: T | ((prev: T) => T)) => void] {\r\n if (!currentRender) {\r\n throw new Error('useState must be called within a render');\r\n }\r\n\r\n if (isServer) {\r\n // Server-side state handling\r\n if (!serverStates.has(currentRender)) {\r\n serverStates.set(currentRender, new Map());\r\n }\r\n const componentState = serverStates.get(currentRender)!;\r\n const index = stateIndices.get(currentRender) || 0;\r\n \r\n if (!componentState.has(index)) {\r\n componentState.set(index, initial);\r\n }\r\n\r\n const state = componentState.get(index);\r\n const setState = (newValue: T | ((prev: T) => T)) => {\r\n // No-op for server-side\r\n };\r\n\r\n stateIndices.set(currentRender, index + 1);\r\n return [state, setState];\r\n }\r\n\r\n if (!states.has(currentRender)) {\r\n states.set(currentRender, []);\r\n }\r\n\r\n const componentStates = states.get(currentRender)!;\r\n const index = stateIndices.get(currentRender)!;\r\n \r\n if (index >= componentStates.length) {\r\n componentStates.push(initial);\r\n }\r\n\r\n const state = componentStates[index];\r\n const setState = (newValue: T | ((prev: T) => T)) => {\r\n const nextValue = typeof newValue === 'function' \r\n ? (newValue as Function)(componentStates[index])\r\n : newValue;\r\n\r\n if (componentStates[index] === nextValue) return; // Skip if value hasn't changed\r\n \r\n componentStates[index] = nextValue;\r\n \r\n if (isBatching) {\r\n batchUpdates(() => rerender(currentRender));\r\n } else {\r\n rerender(currentRender);\r\n }\r\n };\r\n\r\n stateIndices.set(currentRender, index + 1);\r\n return [state, setState];\r\n}\r\n\r\nexport function useEffect(callback: () => (() => void) | void, deps?: any[]) {\r\n if (!currentRender) throw new Error('useEffect must be called within a render');\r\n \r\n const effectIndex = stateIndices.get(currentRender)!;\r\n \r\n if (!effects.has(currentRender)) {\r\n effects.set(currentRender, []);\r\n }\r\n\r\n const componentEffects = effects.get(currentRender)!;\r\n const prevEffect = componentEffects[effectIndex];\r\n \r\n // Run effect if deps changed\r\n if (!prevEffect || !deps || !prevEffect.deps || \r\n deps.some((dep, i) => dep !== prevEffect.deps![i])) {\r\n \r\n // Cleanup previous effect\r\n if (prevEffect?.cleanup) {\r\n prevEffect.cleanup();\r\n }\r\n\r\n // Schedule new effect\r\n queueMicrotask(() => {\r\n const cleanup = callback() || undefined;\r\n componentEffects[effectIndex] = { cleanup: cleanup, deps };\r\n });\r\n }\r\n \r\n stateIndices.set(currentRender, effectIndex + 1);\r\n}\r\n\r\nexport function useMemo<T>(factory: () => T, deps: any[]): T {\r\n if (!currentRender) throw new Error('useMemo must be called within a render');\r\n \r\n const memoIndex = stateIndices.get(currentRender)!;\r\n \r\n if (!memos.has(currentRender)) {\r\n memos.set(currentRender, []);\r\n }\r\n\r\n const componentMemos = memos.get(currentRender)!;\r\n const prevMemo = componentMemos[memoIndex];\r\n \r\n if (!prevMemo || (deps && deps.some((dep, i) => !Object.is(dep, prevMemo.deps[i])))) {\r\n const value = factory();\r\n componentMemos[memoIndex] = { value, deps };\r\n stateIndices.set(currentRender, memoIndex + 1);\r\n return value;\r\n }\r\n\r\n stateIndices.set(currentRender, memoIndex + 1);\r\n return prevMemo.value;\r\n}\r\n\r\nexport function useRef<T>(initial: T) {\r\n if (!currentRender) throw new Error('useRef must be called within a render');\r\n \r\n const refIndex = stateIndices.get(currentRender)!;\r\n \r\n if (!refs.has(currentRender)) {\r\n refs.set(currentRender, []);\r\n }\r\n\r\n const componentRefs = refs.get(currentRender)!;\r\n if (refIndex >= componentRefs.length) {\r\n // Initialize with an object that has a current property\r\n const ref = { current: initial };\r\n componentRefs.push(ref);\r\n stateIndices.set(currentRender, refIndex + 1);\r\n return ref;\r\n }\r\n\r\n const ref = componentRefs[refIndex];\r\n stateIndices.set(currentRender, refIndex + 1);\r\n return ref;\r\n}\r\n\r\n// Add a map to track component DOM nodes\r\nconst componentNodes = new Map<Function, Node>();\r\n\r\nasync function rerender(rendererId: number) {\r\n try {\r\n // Clean up effects\r\n const componentEffects = effects.get(rendererId);\r\n if (componentEffects) {\r\n componentEffects.forEach(effect => {\r\n if (effect.cleanup) effect.cleanup();\r\n });\r\n effects.set(rendererId, []);\r\n }\r\n\r\n if (globalRenderCallback && globalContainer && currentElement) {\r\n await globalRenderCallback(currentElement, globalContainer);\r\n }\r\n } catch (error) {\r\n console.error('Error during rerender:', error);\r\n }\r\n}\r\n\r\n// Add new hook for error boundaries\r\nexport function useErrorBoundary(): [Error | null, () => void] {\r\n const [error, setError] = useState<Error | null>(null);\r\n return [error, () => setError(null)];\r\n}\r\n\r\n// Remove withHooks export\r\n","import type { Component } from './component';\r\n\r\ninterface VNode {\r\n type: string | Function;\r\n props: Record<string, any>;\r\n}\r\n\r\nfunction jsx(type: string | Function, props: any): VNode {\r\n console.log('JSX Transform:', { type, props });\r\n const processedProps = { ...props };\r\n \r\n // Handle children properly\r\n if (arguments.length > 2) {\r\n processedProps.children = Array.prototype.slice.call(arguments, 2);\r\n }\r\n \r\n return { type, props: processedProps };\r\n}\r\n\r\nconst Fragment = ({ children }: { children: any }) => children;\r\n\r\nasync function createElement(vnode: VNode | any): Promise<Node> {\r\n console.log('Creating element from:', vnode);\r\n\r\n // Handle primitives and null\r\n if (vnode == null) {\r\n return document.createTextNode('');\r\n }\r\n \r\n if (typeof vnode === 'boolean') {\r\n return document.createTextNode('');\r\n }\r\n\r\n if (typeof vnode === 'number' || typeof vnode === 'string') {\r\n return document.createTextNode(String(vnode));\r\n }\r\n\r\n // Handle arrays\r\n if (Array.isArray(vnode)) {\r\n const fragment = document.createDocumentFragment();\r\n for (const child of vnode) {\r\n const node = await createElement(child);\r\n fragment.appendChild(node);\r\n }\r\n return fragment;\r\n }\r\n\r\n // Handle VNode\r\n if ('type' in vnode && vnode.props !== undefined) {\r\n const { type, props } = vnode;\r\n \r\n // Handle function components\r\n if (typeof type === 'function') {\r\n try {\r\n const result = await type(props || {});\r\n const node = await createElement(result);\r\n if (node instanceof Element) {\r\n node.setAttribute('data-component-id', type.name || type.toString());\r\n }\r\n return node;\r\n } catch (error) {\r\n console.error('Error rendering component:', error);\r\n return document.createTextNode('');\r\n }\r\n }\r\n\r\n // Create DOM element\r\n const element = document.createElement(type as string);\r\n \r\n // Handle props\r\n for (const [key, value] of Object.entries(props || {})) {\r\n if (key === 'children') continue;\r\n if (key.startsWith('on') && typeof value === 'function') {\r\n const eventName = key.toLowerCase().slice(2);\r\n // Remove existing event listener if any\r\n const existingHandler = (element as any).__events?.[eventName];\r\n if (existingHandler) {\r\n element.removeEventListener(eventName, existingHandler);\r\n }\r\n \r\n // Add new event listener\r\n element.addEventListener(eventName, value as EventListener);\r\n if (!(element as any).__events) {\r\n (element as any).__events = {};\r\n }\r\n (element as any).__events[eventName] = value;\r\n } else if (key === 'style' && typeof value === 'object') {\r\n Object.assign(element.style, value);\r\n } else if (key === 'className') {\r\n element.setAttribute('class', String(value));\r\n } else if (key !== 'key' && key !== 'ref') {\r\n element.setAttribute(key, String(value));\r\n }\r\n }\r\n\r\n // Handle children\r\n const children = props?.children;\r\n if (children != null) {\r\n const childArray = Array.isArray(children) ? children.flat() : [children];\r\n for (const child of childArray) {\r\n const childNode = await createElement(child);\r\n element.appendChild(childNode);\r\n }\r\n }\r\n\r\n return element;\r\n }\r\n\r\n // Handle other objects by converting to string\r\n return document.createTextNode(String(vnode));\r\n}\r\n\r\n// Export named functions and aliases without duplicates\r\nexport {\r\n jsx,\r\n jsx as jsxs,\r\n jsx as jsxDEV,\r\n Fragment,\r\n createElement\r\n};\r\n\r\n// Named exports object\r\nconst jsxRuntime = {\r\n jsx,\r\n jsxs: jsx,\r\n jsxDEV: jsx,\r\n Fragment,\r\n createElement\r\n};\r\n\r\nexport default jsxRuntime;\r\n","import { createElement } from './jsx-runtime';\r\nimport { prepareRender, finishRender, setRenderCallback } from './hooks';\r\nimport { batchUpdates } from './batch';\r\n\r\nlet isHydrating = false;\r\n\r\nexport async function hydrate(element: any, container: HTMLElement) {\r\n isHydrating = true;\r\n try {\r\n await render(element, container);\r\n } finally {\r\n isHydrating = false;\r\n }\r\n}\r\n\r\nexport async function render(element: any, container: HTMLElement) {\r\n console.log('Rendering to:', container.id);\r\n \r\n batchUpdates(async () => {\r\n const rendererId = prepareRender();\r\n try {\r\n setRenderCallback(render, element, container);\r\n const domNode = await createElement(element);\r\n \r\n if (!isHydrating) {\r\n container.innerHTML = '';\r\n }\r\n container.appendChild(domNode);\r\n \r\n } finally {\r\n finishRender();\r\n }\r\n });\r\n}\r\n","import { prepareRender, finishRender, setRenderCallback } from './hooks';\r\n\r\nexport async function renderToString(element: any): Promise<string> {\r\n // Setup render context\r\n const rendererId = prepareRender();\r\n setRenderCallback(() => {}, element, null as any);\r\n \r\n try {\r\n if (element == null) return '';\r\n \r\n if (typeof element === 'boolean') return '';\r\n \r\n if (typeof element === 'number' || typeof element === 'string') {\r\n return escapeHtml(String(element));\r\n }\r\n\r\n if (Array.isArray(element)) {\r\n const children = await Promise.all(element.map(renderToString));\r\n return children.join('');\r\n }\r\n\r\n if ('type' in element && element.props !== undefined) {\r\n const { type, props } = element;\r\n\r\n // Handle function components\r\n if (typeof type === 'function') {\r\n try {\r\n // Prepare new render context for the component\r\n prepareRender();\r\n const result = await type(props || {});\r\n const html = await renderToString(result);\r\n finishRender();\r\n return html;\r\n } catch (error) {\r\n console.error('Error rendering component:', error);\r\n return '';\r\n }\r\n }\r\n\r\n // Handle regular elements\r\n let html = `<${type}`;\r\n\r\n // Add attributes\r\n for (const [key, value] of Object.entries(props || {})) {\r\n if (key === 'children') continue;\r\n if (key === 'className') {\r\n html += ` class=\"${escapeHtml(String(value))}\"`;\r\n } else if (key === 'style' && typeof value === 'object') {\r\n html += ` style=\"${stringifyStyle(value || {})}\"`;\r\n } else if (!key.startsWith('on')) {\r\n html += ` ${key}=\"${escapeHtml(String(value))}\"`;\r\n }\r\n }\r\n\r\n // Handle self-closing tags\r\n const voidElements = new Set([\r\n 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',\r\n 'link', 'meta', 'param', 'source', 'track', 'wbr'\r\n ]);\r\n \r\n if (voidElements.has(type)) {\r\n return html + '/>';\r\n }\r\n\r\n html += '>';\r\n\r\n // Add children\r\n if (props?.children) {\r\n const children = Array.isArray(props.children) ? props.children : [props.children];\r\n const renderedChildren = await Promise.all(children.map(renderToString));\r\n html += renderedChildren.join('');\r\n }\r\n\r\n return html + `</${type}>`;\r\n }\r\n\r\n return escapeHtml(String(element));\r\n } finally {\r\n finishRender();\r\n }\r\n}\r\n\r\nfunction escapeHtml(str: string): string {\r\n return str\r\n .replace(/&/g, '&amp;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;')\r\n .replace(/\"/g, '&quot;')\r\n .replace(/'/g, '&#39;');\r\n}\r\n\r\nfunction stringifyStyle(style: Record<string, any>): string {\r\n return Object.entries(style)\r\n .map(([key, value]) => `${hyphenate(key)}:${value}`)\r\n .join(';');\r\n}\r\n\r\nfunction hyphenate(str: string): string {\r\n return str.replace(/[A-Z]/g, match => '-' + match.toLowerCase());\r\n}\r\n","import { useState, useEffect } from './hooks';\r\n\r\ninterface RouterState {\r\n pathname: string;\r\n search: string;\r\n hash: string;\r\n params: Record<string, string>;\r\n}\r\n\r\ninterface RouterOptions {\r\n replace?: boolean;\r\n scroll?: boolean;\r\n}\r\n\r\nlet currentState: RouterState = {\r\n pathname: typeof window !== 'undefined' ? window.location.pathname : '/',\r\n search: typeof window !== 'undefined' ? window.location.search : '',\r\n hash: typeof window !== 'undefined' ? window.location.hash : '',\r\n params: {}\r\n};\r\n\r\nconst listeners = new Set<(state: RouterState) => void>();\r\n\r\n// Parse route pattern and extract params\r\nfunction matchRoute(pattern: string, pathname: string): Record<string, string> | null {\r\n const paramNames: string[] = [];\r\n const regexPattern = pattern.replace(/:([^/]+)/g, (_, name) => {\r\n paramNames.push(name);\r\n return '([^/]+)';\r\n });\r\n\r\n const match = pathname.match(new RegExp(`^${regexPattern}$`));\r\n if (!match) return null;\r\n\r\n const params: Record<string, string> = {};\r\n paramNames.forEach((name, i) => {\r\n params[name] = match[i + 1];\r\n });\r\n\r\n return params;\r\n}\r\n\r\nfunction updateState(newPath: string, options: RouterOptions = {}) {\r\n const url = new URL(newPath, window.location.origin);\r\n const newState: RouterState = {\r\n pathname: url.pathname,\r\n search: url.search,\r\n hash: url.hash,\r\n params: {}\r\n };\r\n\r\n if (options.replace) {\r\n window.history.replaceState(newState, '', url.toString());\r\n } else {\r\n window.history.pushState(newState, '', url.toString());\r\n }\r\n\r\n currentState = newState;\r\n listeners.forEach(listener => listener(newState));\r\n\r\n if (options.scroll) {\r\n window.scrollTo(0, 0);\r\n }\r\n}\r\n\r\nexport function navigate(to: string, options: RouterOptions = {}) {\r\n if (typeof window === 'undefined') return;\r\n updateState(to, options);\r\n}\r\n\r\nexport function useRouter() {\r\n const [state, setState] = useState<RouterState>(currentState);\r\n\r\n useEffect(() => {\r\n const handleRouteChange = (newState: RouterState) => {\r\n setState(newState);\r\n };\r\n\r\n const handlePopState = () => {\r\n currentState = {\r\n pathname: window.location.pathname,\r\n search: window.location.search,\r\n hash: window.location.hash,\r\n params: {}\r\n };\r\n setState(currentState);\r\n };\r\n\r\n listeners.add(handleRouteChange);\r\n window.addEventListener('popstate', handlePopState);\r\n\r\n return () => {\r\n listeners.delete(handleRouteChange);\r\n window.removeEventListener('popstate', handlePopState);\r\n };\r\n }, []);\r\n\r\n return {\r\n ...state,\r\n push: (to: string, options?: RouterOptions) => navigate(to, options),\r\n replace: (to: string, options?: RouterOptions) => navigate(to, { ...options, replace: true }),\r\n back: () => window.history.back(),\r\n forward: () => window.history.forward()\r\n };\r\n}\r\n\r\nexport function useRoute(pattern: string) {\r\n const { pathname } = useRouter();\r\n const [params, setParams] = useState<Record<string, string>>({});\r\n const [isMatch, setIsMatch] = useState(false);\r\n\r\n useEffect(() => {\r\n const matchedParams = matchRoute(pattern, pathname);\r\n setIsMatch(!!matchedParams);\r\n setParams(matchedParams || {});\r\n }, [pattern, pathname]);\r\n\r\n return { isMatch, params };\r\n}\r\n\r\nexport function useParams<T extends Record<string, string>>() {\r\n const router = useRouter();\r\n return router.params as T;\r\n}\r\n\r\nexport function useSearchParams() {\r\n const { search } = useRouter();\r\n return new URLSearchParams(search);\r\n}\r\n","import { navigate } from './router';\r\n\r\ninterface LinkProps {\r\n href: string;\r\n children?: any;\r\n replace?: boolean;\r\n className?: string;\r\n style?: Record<string, string>;\r\n [key: string]: any;\r\n}\r\n\r\nexport function Link({ \r\n href, \r\n children, \r\n replace = false, \r\n className,\r\n style,\r\n ...rest \r\n}: LinkProps) {\r\n const handleClick = (e: MouseEvent) => {\r\n e.preventDefault();\r\n navigate(href, { replace });\r\n };\r\n\r\n return {\r\n type: 'a',\r\n props: {\r\n href,\r\n onClick: handleClick,\r\n className,\r\n style,\r\n ...rest,\r\n children\r\n }\r\n };\r\n}\r\n","\r\n\r\nconst contexts = new Map<symbol, any>();\r\nlet currentRender: Function | null = null;\r\n\r\nexport interface Context<T> {\r\n Provider: (props: { value: T; children?: any }) => any;\r\n Consumer: (props: { children: (value: T) => any }) => any;\r\n _id: symbol;\r\n useSelector: <S>(selector: (state: T) => S) => S;\r\n}\r\n\r\nexport function createContext<T>(defaultValue: T): Context<T> {\r\n const context = {\r\n Provider: ({ value, children }: { value: T, children?: any }) => {\r\n return children;\r\n },\r\n Consumer: ({ children }: { children: (value: T) => any }) => {\r\n return children(defaultValue);\r\n },\r\n _id: Symbol(),\r\n useSelector: <S>(selector: (state: T) => S) => {\r\n return selector(defaultValue);\r\n }\r\n };\r\n\r\n return context;\r\n}\r\n\r\nexport function useContext<T>(context: any): T {\r\n return context;\r\n}\r\n"],"names":["isBatching","queue","batchUpdates","fn","push","length","nextFn","shift","currentRender","states","Map","stateIndices","effects","memos","refs","globalRenderCallback","globalContainer","currentElement","isServer","window","serverStates","setRenderCallback","callback","element","container","prepareRender","set","finishRender","delete","useState","initial","Error","has","componentState","get","index","state","setState","newValue","componentStates","nextValue","rerender","useEffect","deps","effectIndex","componentEffects","prevEffect","some","dep","i","cleanup","queueMicrotask","async","rendererId","forEach","effect","error","console","jsx","type","props","log","processedProps","arguments","children","Array","prototype","slice","call","createElement","vnode","document","createTextNode","String","isArray","fragment","createDocumentFragment","child","node","appendChild","result","Element","setAttribute","name","toString","key","value","Object","entries","startsWith","eventName","toLowerCase","existingHandler","_a","__events","removeEventListener","addEventListener","assign","style","childArray","flat","childNode","isHydrating","render","id","domNode","innerHTML","escapeHtml","str","replace","currentState","pathname","location","search","hash","params","listeners","Set","navigate","to","options","newPath","url","URL","origin","newState","history","replaceState","pushState","listener","scroll","scrollTo","updateState","href","className","rest","onClick","e","preventDefault","defaultValue","Provider","Consumer","_id","Symbol","useSelector","selector","renderToString","Promise","all","map","join","html","match","context","setError","factory","memoIndex","componentMemos","prevMemo","is","refIndex","componentRefs","ref","current","handleRouteChange","handlePopState","add","back","forward"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/batch.ts","../src/hooks.ts","../src/jsx-runtime.ts","../src/renderer.ts","../src/server-renderer.ts","../src/router.ts","../src/link.tsx","../src/context.ts","../src/templates/default.ts"],"sourcesContent":["export let isBatching = false;\r\nconst queue: Function[] = [];\r\n\r\nexport function batchUpdates(fn: Function) {\r\n if (isBatching) {\r\n queue.push(fn);\r\n return;\r\n }\r\n\r\n isBatching = true;\r\n try {\r\n fn();\r\n while (queue.length > 0) {\r\n const nextFn = queue.shift();\r\n nextFn?.();\r\n }\r\n } finally {\r\n isBatching = false;\r\n }\r\n}\r\n\r\nexport function getIsBatching() {\r\n return isBatching;\r\n}\r\n","import { createElement } from './jsx-runtime';\r\nimport { batchUpdates, isBatching } from './batch';\r\nimport { diff } from './vdom';\r\n\r\nlet currentRender: number = 0;\r\nconst states = new Map<number, any[]>();\r\nconst stateIndices = new Map<number, number>();\r\nconst effects = new Map<number, Effect[]>();\r\nconst memos = new Map<number, { value: any; deps: any[] }[]>();\r\nconst refs = new Map<number, any[]>();\r\n\r\ninterface Effect {\r\n cleanup?: () => void;\r\n deps?: any[];\r\n}\r\n\r\n// Add at the top with other declarations\r\nlet globalRenderCallback: ((element: any, container: HTMLElement) => void) | null = null;\r\nlet globalContainer: HTMLElement | null = null;\r\nlet currentElement: any = null;\r\n\r\nconst isServer = typeof window === 'undefined';\r\nconst serverStates = new Map<number, any>();\r\n\r\nexport function setRenderCallback(\r\n callback: (element: any, container: HTMLElement) => void,\r\n element: any,\r\n container: HTMLElement\r\n) {\r\n globalRenderCallback = callback;\r\n globalContainer = container;\r\n currentElement = element;\r\n}\r\n\r\nexport function prepareRender() {\r\n currentRender++;\r\n stateIndices.set(currentRender, 0);\r\n return currentRender;\r\n}\r\n\r\nexport function finishRender() {\r\n if (isServer) {\r\n serverStates.delete(currentRender);\r\n }\r\n currentRender = 0;\r\n}\r\n\r\nexport function useState<T>(initial: T): [T, (value: T | ((prev: T) => T)) => void] {\r\n if (!currentRender) {\r\n throw new Error('useState must be called within a render');\r\n }\r\n\r\n if (isServer) {\r\n // Server-side state handling\r\n if (!serverStates.has(currentRender)) {\r\n serverStates.set(currentRender, new Map());\r\n }\r\n const componentState = serverStates.get(currentRender)!;\r\n const index = stateIndices.get(currentRender) || 0;\r\n \r\n if (!componentState.has(index)) {\r\n componentState.set(index, initial);\r\n }\r\n\r\n const state = componentState.get(index);\r\n const setState = (newValue: T | ((prev: T) => T)) => {\r\n // No-op for server-side\r\n };\r\n\r\n stateIndices.set(currentRender, index + 1);\r\n return [state, setState];\r\n }\r\n\r\n if (!states.has(currentRender)) {\r\n states.set(currentRender, []);\r\n }\r\n\r\n const componentStates = states.get(currentRender)!;\r\n const index = stateIndices.get(currentRender)!;\r\n \r\n if (index >= componentStates.length) {\r\n componentStates.push(initial);\r\n }\r\n\r\n const state = componentStates[index];\r\n const setState = (newValue: T | ((prev: T) => T)) => {\r\n const nextValue = typeof newValue === 'function' \r\n ? (newValue as Function)(componentStates[index])\r\n : newValue;\r\n\r\n if (componentStates[index] === nextValue) return; // Skip if value hasn't changed\r\n \r\n componentStates[index] = nextValue;\r\n \r\n if (isBatching) {\r\n batchUpdates(() => rerender(currentRender));\r\n } else {\r\n rerender(currentRender);\r\n }\r\n };\r\n\r\n stateIndices.set(currentRender, index + 1);\r\n return [state, setState];\r\n}\r\n\r\nexport function useEffect(callback: () => (() => void) | void, deps?: any[]) {\r\n if (!currentRender) throw new Error('useEffect must be called within a render');\r\n \r\n const effectIndex = stateIndices.get(currentRender)!;\r\n \r\n if (!effects.has(currentRender)) {\r\n effects.set(currentRender, []);\r\n }\r\n\r\n const componentEffects = effects.get(currentRender)!;\r\n const prevEffect = componentEffects[effectIndex];\r\n \r\n // Run effect if deps changed\r\n if (!prevEffect || !deps || !prevEffect.deps || \r\n deps.some((dep, i) => dep !== prevEffect.deps![i])) {\r\n \r\n // Cleanup previous effect\r\n if (prevEffect?.cleanup) {\r\n prevEffect.cleanup();\r\n }\r\n\r\n // Schedule new effect\r\n queueMicrotask(() => {\r\n const cleanup = callback() || undefined;\r\n componentEffects[effectIndex] = { cleanup: cleanup, deps };\r\n });\r\n }\r\n \r\n stateIndices.set(currentRender, effectIndex + 1);\r\n}\r\n\r\nexport function useMemo<T>(factory: () => T, deps: any[]): T {\r\n if (!currentRender) throw new Error('useMemo must be called within a render');\r\n \r\n const memoIndex = stateIndices.get(currentRender)!;\r\n \r\n if (!memos.has(currentRender)) {\r\n memos.set(currentRender, []);\r\n }\r\n\r\n const componentMemos = memos.get(currentRender)!;\r\n const prevMemo = componentMemos[memoIndex];\r\n \r\n if (!prevMemo || (deps && deps.some((dep, i) => !Object.is(dep, prevMemo.deps[i])))) {\r\n const value = factory();\r\n componentMemos[memoIndex] = { value, deps };\r\n stateIndices.set(currentRender, memoIndex + 1);\r\n return value;\r\n }\r\n\r\n stateIndices.set(currentRender, memoIndex + 1);\r\n return prevMemo.value;\r\n}\r\n\r\nexport function useRef<T>(initial: T) {\r\n if (!currentRender) throw new Error('useRef must be called within a render');\r\n \r\n const refIndex = stateIndices.get(currentRender)!;\r\n \r\n if (!refs.has(currentRender)) {\r\n refs.set(currentRender, []);\r\n }\r\n\r\n const componentRefs = refs.get(currentRender)!;\r\n if (refIndex >= componentRefs.length) {\r\n // Initialize with an object that has a current property\r\n const ref = { current: initial };\r\n componentRefs.push(ref);\r\n stateIndices.set(currentRender, refIndex + 1);\r\n return ref;\r\n }\r\n\r\n const ref = componentRefs[refIndex];\r\n stateIndices.set(currentRender, refIndex + 1);\r\n return ref;\r\n}\r\n\r\n// Add a map to track component DOM nodes\r\nconst componentNodes = new Map<Function, Node>();\r\n\r\nasync function rerender(rendererId: number) {\r\n try {\r\n // Clean up effects\r\n const componentEffects = effects.get(rendererId);\r\n if (componentEffects) {\r\n componentEffects.forEach(effect => {\r\n if (effect.cleanup) effect.cleanup();\r\n });\r\n effects.set(rendererId, []);\r\n }\r\n\r\n if (globalRenderCallback && globalContainer && currentElement) {\r\n await globalRenderCallback(currentElement, globalContainer);\r\n }\r\n } catch (error) {\r\n console.error('Error during rerender:', error);\r\n }\r\n}\r\n\r\n// Add new hook for error boundaries\r\nexport function useErrorBoundary(): [Error | null, () => void] {\r\n const [error, setError] = useState<Error | null>(null);\r\n return [error, () => setError(null)];\r\n}\r\n\r\n// Remove withHooks export\r\n","import type { Component } from './component';\r\n\r\ninterface VNode {\r\n type: string | Function;\r\n props: Record<string, any>;\r\n}\r\n\r\nfunction jsx(type: string | Function, props: any): VNode {\r\n console.log('JSX Transform:', { type, props });\r\n const processedProps = { ...props };\r\n \r\n // Handle children properly\r\n if (arguments.length > 2) {\r\n processedProps.children = Array.prototype.slice.call(arguments, 2);\r\n }\r\n \r\n return { type, props: processedProps };\r\n}\r\n\r\nconst Fragment = ({ children }: { children: any }) => children;\r\n\r\nasync function createElement(vnode: VNode | any): Promise<Node> {\r\n console.log('Creating element from:', vnode);\r\n\r\n // Handle primitives and null\r\n if (vnode == null) {\r\n return document.createTextNode('');\r\n }\r\n \r\n if (typeof vnode === 'boolean') {\r\n return document.createTextNode('');\r\n }\r\n\r\n if (typeof vnode === 'number' || typeof vnode === 'string') {\r\n return document.createTextNode(String(vnode));\r\n }\r\n\r\n // Handle arrays\r\n if (Array.isArray(vnode)) {\r\n const fragment = document.createDocumentFragment();\r\n for (const child of vnode) {\r\n const node = await createElement(child);\r\n fragment.appendChild(node);\r\n }\r\n return fragment;\r\n }\r\n\r\n // Handle VNode\r\n if ('type' in vnode && vnode.props !== undefined) {\r\n const { type, props } = vnode;\r\n \r\n // Handle function components\r\n if (typeof type === 'function') {\r\n try {\r\n const result = await type(props || {});\r\n const node = await createElement(result);\r\n if (node instanceof Element) {\r\n node.setAttribute('data-component-id', type.name || type.toString());\r\n }\r\n return node;\r\n } catch (error) {\r\n console.error('Error rendering component:', error);\r\n return document.createTextNode('');\r\n }\r\n }\r\n\r\n // Create DOM element\r\n const element = document.createElement(type as string);\r\n \r\n // Handle props\r\n for (const [key, value] of Object.entries(props || {})) {\r\n if (key === 'children') continue;\r\n if (key.startsWith('on') && typeof value === 'function') {\r\n const eventName = key.toLowerCase().slice(2);\r\n // Remove existing event listener if any\r\n const existingHandler = (element as any).__events?.[eventName];\r\n if (existingHandler) {\r\n element.removeEventListener(eventName, existingHandler);\r\n }\r\n \r\n // Add new event listener\r\n element.addEventListener(eventName, value as EventListener);\r\n if (!(element as any).__events) {\r\n (element as any).__events = {};\r\n }\r\n (element as any).__events[eventName] = value;\r\n } else if (key === 'style' && typeof value === 'object') {\r\n Object.assign(element.style, value);\r\n } else if (key === 'className') {\r\n element.setAttribute('class', String(value));\r\n } else if (key !== 'key' && key !== 'ref') {\r\n element.setAttribute(key, String(value));\r\n }\r\n }\r\n\r\n // Handle children\r\n const children = props?.children;\r\n if (children != null) {\r\n const childArray = Array.isArray(children) ? children.flat() : [children];\r\n for (const child of childArray) {\r\n const childNode = await createElement(child);\r\n element.appendChild(childNode);\r\n }\r\n }\r\n\r\n return element;\r\n }\r\n\r\n // Handle other objects by converting to string\r\n return document.createTextNode(String(vnode));\r\n}\r\n\r\n// Export named functions and aliases without duplicates\r\nexport {\r\n jsx,\r\n jsx as jsxs,\r\n jsx as jsxDEV,\r\n Fragment,\r\n createElement\r\n};\r\n\r\n// Named exports object\r\nconst jsxRuntime = {\r\n jsx,\r\n jsxs: jsx,\r\n jsxDEV: jsx,\r\n Fragment,\r\n createElement\r\n};\r\n\r\nexport default jsxRuntime;\r\n","import { createElement } from './jsx-runtime';\r\nimport { prepareRender, finishRender, setRenderCallback } from './hooks';\r\nimport { batchUpdates } from './batch';\r\n\r\nlet isHydrating = false;\r\n\r\nexport async function hydrate(element: any, container: HTMLElement) {\r\n isHydrating = true;\r\n try {\r\n await render(element, container);\r\n } finally {\r\n isHydrating = false;\r\n }\r\n}\r\n\r\nexport async function render(element: any, container: HTMLElement) {\r\n console.log('Rendering to:', container.id);\r\n \r\n batchUpdates(async () => {\r\n const rendererId = prepareRender();\r\n try {\r\n setRenderCallback(render, element, container);\r\n const domNode = await createElement(element);\r\n \r\n if (!isHydrating) {\r\n container.innerHTML = '';\r\n }\r\n container.appendChild(domNode);\r\n \r\n } finally {\r\n finishRender();\r\n }\r\n });\r\n}\r\n","import { VNode } from './types';\r\nimport { defaultTemplate, TemplateOptions } from './templates/default';\r\n\r\nexport async function renderToString(\r\n element: JSX.Element, \r\n options: Partial<TemplateOptions> = {}\r\n): Promise<string> {\r\n try {\r\n const content = await renderNodeToString(element);\r\n return defaultTemplate(content, {\r\n title: 'Frontend Hamroun App',\r\n ...options\r\n });\r\n } catch (error) {\r\n console.error('Error during server rendering:', error);\r\n return '';\r\n }\r\n}\r\n\r\nasync function renderNodeToString(node: VNode | any): Promise<string> {\r\n if (node == null || typeof node === 'boolean') {\r\n return '';\r\n }\r\n\r\n if (typeof node === 'number' || typeof node === 'string') {\r\n return escapeHtml(String(node));\r\n }\r\n\r\n if (typeof node === 'function') {\r\n const result = await node({ });\r\n return renderNodeToString(result);\r\n }\r\n\r\n if (node.type) {\r\n if (typeof node.type === 'function') {\r\n const result = await node.type(node.props || {});\r\n return renderNodeToString(result);\r\n }\r\n\r\n let html = `<${node.type}`;\r\n \r\n // Handle props\r\n for (const [key, value] of Object.entries(node.props || {})) {\r\n if (key === 'children' || key === 'key' || key === 'ref') continue;\r\n if (key === 'className') {\r\n html += ` class=\"${escapeHtml(String(value))}\"`;\r\n } else if (key === 'style' && typeof value === 'object' && value !== null) {\r\n html += ` style=\"${styleToString(value)}\"`;\r\n } else if (!key.startsWith('on')) {\r\n html += ` ${key}=\"${escapeHtml(String(value))}\"`;\r\n }\r\n }\r\n\r\n html += '>';\r\n\r\n // Handle children\r\n if (node.props?.children) {\r\n const children = Array.isArray(node.props.children) \r\n ? node.props.children \r\n : [node.props.children];\r\n \r\n for (const child of children) {\r\n html += await renderNodeToString(child);\r\n }\r\n }\r\n\r\n html += `</${node.type}>`;\r\n return html;\r\n }\r\n\r\n return '';\r\n}\r\n\r\nfunction escapeHtml(str: string): string {\r\n return str\r\n .replace(/&/g, '&amp;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;')\r\n .replace(/\"/g, '&quot;')\r\n .replace(/'/g, '&#039;');\r\n}\r\n\r\nfunction styleToString(style: Record<string, any>): string {\r\n return Object.entries(style)\r\n .map(([key, value]) => `${key}: ${value}`)\r\n .join('; ');\r\n}\r\n","import { useState, useEffect } from './hooks';\r\n\r\ninterface RouterState {\r\n pathname: string;\r\n search: string;\r\n hash: string;\r\n params: Record<string, string>;\r\n}\r\n\r\ninterface RouterOptions {\r\n replace?: boolean;\r\n scroll?: boolean;\r\n}\r\n\r\nlet currentState: RouterState = {\r\n pathname: typeof window !== 'undefined' ? window.location.pathname : '/',\r\n search: typeof window !== 'undefined' ? window.location.search : '',\r\n hash: typeof window !== 'undefined' ? window.location.hash : '',\r\n params: {}\r\n};\r\n\r\nconst listeners = new Set<(state: RouterState) => void>();\r\n\r\n// Parse route pattern and extract params\r\nfunction matchRoute(pattern: string, pathname: string): Record<string, string> | null {\r\n const paramNames: string[] = [];\r\n const regexPattern = pattern.replace(/:([^/]+)/g, (_, name) => {\r\n paramNames.push(name);\r\n return '([^/]+)';\r\n });\r\n\r\n const match = pathname.match(new RegExp(`^${regexPattern}$`));\r\n if (!match) return null;\r\n\r\n const params: Record<string, string> = {};\r\n paramNames.forEach((name, i) => {\r\n params[name] = match[i + 1];\r\n });\r\n\r\n return params;\r\n}\r\n\r\nfunction updateState(newPath: string, options: RouterOptions = {}) {\r\n const url = new URL(newPath, window.location.origin);\r\n const newState: RouterState = {\r\n pathname: url.pathname,\r\n search: url.search,\r\n hash: url.hash,\r\n params: {}\r\n };\r\n\r\n if (options.replace) {\r\n window.history.replaceState(newState, '', url.toString());\r\n } else {\r\n window.history.pushState(newState, '', url.toString());\r\n }\r\n\r\n currentState = newState;\r\n listeners.forEach(listener => listener(newState));\r\n\r\n if (options.scroll) {\r\n window.scrollTo(0, 0);\r\n }\r\n}\r\n\r\nexport function navigate(to: string, options: RouterOptions = {}) {\r\n if (typeof window === 'undefined') return;\r\n updateState(to, options);\r\n}\r\n\r\nexport function useRouter() {\r\n const [state, setState] = useState<RouterState>(currentState);\r\n\r\n useEffect(() => {\r\n const handleRouteChange = (newState: RouterState) => {\r\n setState(newState);\r\n };\r\n\r\n const handlePopState = () => {\r\n currentState = {\r\n pathname: window.location.pathname,\r\n search: window.location.search,\r\n hash: window.location.hash,\r\n params: {}\r\n };\r\n setState(currentState);\r\n };\r\n\r\n listeners.add(handleRouteChange);\r\n window.addEventListener('popstate', handlePopState);\r\n\r\n return () => {\r\n listeners.delete(handleRouteChange);\r\n window.removeEventListener('popstate', handlePopState);\r\n };\r\n }, []);\r\n\r\n return {\r\n ...state,\r\n push: (to: string, options?: RouterOptions) => navigate(to, options),\r\n replace: (to: string, options?: RouterOptions) => navigate(to, { ...options, replace: true }),\r\n back: () => window.history.back(),\r\n forward: () => window.history.forward()\r\n };\r\n}\r\n\r\nexport function useRoute(pattern: string) {\r\n const { pathname } = useRouter();\r\n const [params, setParams] = useState<Record<string, string>>({});\r\n const [isMatch, setIsMatch] = useState(false);\r\n\r\n useEffect(() => {\r\n const matchedParams = matchRoute(pattern, pathname);\r\n setIsMatch(!!matchedParams);\r\n setParams(matchedParams || {});\r\n }, [pattern, pathname]);\r\n\r\n return { isMatch, params };\r\n}\r\n\r\nexport function useParams<T extends Record<string, string>>() {\r\n const router = useRouter();\r\n return router.params as T;\r\n}\r\n\r\nexport function useSearchParams() {\r\n const { search } = useRouter();\r\n return new URLSearchParams(search);\r\n}\r\n","import { navigate } from './router';\r\n\r\ninterface LinkProps {\r\n href: string;\r\n children?: any;\r\n replace?: boolean;\r\n className?: string;\r\n style?: Record<string, string>;\r\n [key: string]: any;\r\n}\r\n\r\nexport function Link({ \r\n href, \r\n children, \r\n replace = false, \r\n className,\r\n style,\r\n ...rest \r\n}: LinkProps) {\r\n const handleClick = (e: MouseEvent) => {\r\n e.preventDefault();\r\n navigate(href, { replace });\r\n };\r\n\r\n return {\r\n type: 'a',\r\n props: {\r\n href,\r\n onClick: handleClick,\r\n className,\r\n style,\r\n ...rest,\r\n children\r\n }\r\n };\r\n}\r\n","\r\n\r\nconst contexts = new Map<symbol, any>();\r\nlet currentRender: Function | null = null;\r\n\r\nexport interface Context<T> {\r\n Provider: (props: { value: T; children?: any }) => any;\r\n Consumer: (props: { children: (value: T) => any }) => any;\r\n _id: symbol;\r\n useSelector: <S>(selector: (state: T) => S) => S;\r\n}\r\n\r\nexport function createContext<T>(defaultValue: T): Context<T> {\r\n const context = {\r\n Provider: ({ value, children }: { value: T, children?: any }) => {\r\n return children;\r\n },\r\n Consumer: ({ children }: { children: (value: T) => any }) => {\r\n return children(defaultValue);\r\n },\r\n _id: Symbol(),\r\n useSelector: <S>(selector: (state: T) => S) => {\r\n return selector(defaultValue);\r\n }\r\n };\r\n\r\n return context;\r\n}\r\n\r\nexport function useContext<T>(context: any): T {\r\n return context;\r\n}\r\n","export interface TemplateOptions {\r\n title: string;\r\n description?: string;\r\n scripts?: string[];\r\n styles?: string[];\r\n initialState?: any;\r\n meta?: Record<string, string>;\r\n bodyAttrs?: Record<string, string>;\r\n htmlAttrs?: Record<string, string>;\r\n}\r\n\r\nexport function defaultTemplate(content: string, options: TemplateOptions): string {\r\n const {\r\n title,\r\n description = '',\r\n scripts = [],\r\n styles = [],\r\n initialState = {},\r\n meta = {},\r\n bodyAttrs = {},\r\n htmlAttrs = { lang: 'en' }\r\n } = options;\r\n\r\n const htmlAttributes = Object.entries(htmlAttrs)\r\n .map(([key, value]) => `${key}=\"${value}\"`)\r\n .join(' ');\r\n\r\n const bodyAttributes = Object.entries(bodyAttrs)\r\n .map(([key, value]) => `${key}=\"${value}\"`)\r\n .join(' ');\r\n\r\n const metaTags = Object.entries(meta)\r\n .map(([name, content]) => ` <meta name=\"${name}\" content=\"${content}\">`)\r\n .join('\\n');\r\n\r\n return `<!DOCTYPE html>\r\n<html ${htmlAttributes}>\r\n <head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n ${description ? `<meta name=\"description\" content=\"${description}\">\\n` : ''}${metaTags}\r\n <title>${title}</title>\r\n${styles.map(href => ` <link rel=\"stylesheet\" href=\"${href}\">`).join('\\n')}\r\n <script>\r\n window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};\r\n </script>\r\n </head>\r\n <body ${bodyAttributes}>\r\n <div id=\"root\">${content}</div>\r\n${scripts.map(src => ` <script src=\"${src}\" defer></script>`).join('\\n')}\r\n </body>\r\n</html>`;\r\n}\r\n"],"names":["isBatching","queue","batchUpdates","fn","push","length","nextFn","shift","currentRender","states","Map","stateIndices","effects","memos","refs","globalRenderCallback","globalContainer","currentElement","isServer","window","serverStates","useState","initial","Error","has","set","componentState","get","index","state","setState","newValue","componentStates","nextValue","rerender","useEffect","callback","deps","effectIndex","componentEffects","prevEffect","some","dep","i","cleanup","queueMicrotask","async","rendererId","forEach","effect","error","console","jsx","type","props","log","processedProps","arguments","children","Array","prototype","slice","call","createElement","vnode","document","createTextNode","String","isArray","fragment","createDocumentFragment","child","node","appendChild","result","Element","setAttribute","name","toString","element","key","value","Object","entries","startsWith","eventName","toLowerCase","existingHandler","_a","__events","removeEventListener","addEventListener","assign","style","childArray","flat","childNode","isHydrating","render","container","id","setRenderCallback","domNode","innerHTML","delete","renderNodeToString","escapeHtml","html","map","join","str","replace","currentState","pathname","location","search","hash","params","listeners","Set","navigate","to","options","newPath","url","URL","origin","newState","history","replaceState","pushState","listener","scroll","scrollTo","updateState","href","className","rest","onClick","e","preventDefault","defaultValue","Provider","Consumer","_id","Symbol","useSelector","selector","content","title","description","scripts","styles","initialState","meta","bodyAttrs","htmlAttrs","lang","htmlAttributes","bodyAttributes","JSON","stringify","src","defaultTemplate","context","setError","factory","memoIndex","componentMemos","prevMemo","is","refIndex","componentRefs","ref","current","handleRouteChange","handlePopState","add","back","forward"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -284,88 +284,97 @@ async function render(element, container) {
284
284
  }
285
285
  });
286
286
  }
287
- async function renderToString(element) {
288
- prepareRender();
289
- setRenderCallback(() => {
290
- }, element, null);
287
+ function defaultTemplate(content, options) {
288
+ const {
289
+ title,
290
+ description = "",
291
+ scripts = [],
292
+ styles = [],
293
+ initialState = {},
294
+ meta = {},
295
+ bodyAttrs = {},
296
+ htmlAttrs = { lang: "en" }
297
+ } = options;
298
+ const htmlAttributes = Object.entries(htmlAttrs).map(([key, value]) => `${key}="${value}"`).join(" ");
299
+ const bodyAttributes = Object.entries(bodyAttrs).map(([key, value]) => `${key}="${value}"`).join(" ");
300
+ const metaTags = Object.entries(meta).map(([name, content2]) => ` <meta name="${name}" content="${content2}">`).join("\n");
301
+ return `<!DOCTYPE html>
302
+ <html ${htmlAttributes}>
303
+ <head>
304
+ <meta charset="UTF-8">
305
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
306
+ ${description ? `<meta name="description" content="${description}">
307
+ ` : ""}${metaTags}
308
+ <title>${title}</title>
309
+ ${styles.map((href) => ` <link rel="stylesheet" href="${href}">`).join("\n")}
310
+ <script>
311
+ window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};
312
+ <\/script>
313
+ </head>
314
+ <body ${bodyAttributes}>
315
+ <div id="root">${content}</div>
316
+ ${scripts.map((src) => ` <script src="${src}" defer><\/script>`).join("\n")}
317
+ </body>
318
+ </html>`;
319
+ }
320
+ async function renderToString(element, options = {}) {
291
321
  try {
292
- if (element == null)
293
- return "";
294
- if (typeof element === "boolean")
295
- return "";
296
- if (typeof element === "number" || typeof element === "string") {
297
- return escapeHtml(String(element));
298
- }
299
- if (Array.isArray(element)) {
300
- const children = await Promise.all(element.map(renderToString));
301
- return children.join("");
322
+ const content = await renderNodeToString(element);
323
+ return defaultTemplate(content, {
324
+ title: "Frontend Hamroun App",
325
+ ...options
326
+ });
327
+ } catch (error) {
328
+ console.error("Error during server rendering:", error);
329
+ return "";
330
+ }
331
+ }
332
+ async function renderNodeToString(node) {
333
+ var _a;
334
+ if (node == null || typeof node === "boolean") {
335
+ return "";
336
+ }
337
+ if (typeof node === "number" || typeof node === "string") {
338
+ return escapeHtml(String(node));
339
+ }
340
+ if (typeof node === "function") {
341
+ const result = await node({});
342
+ return renderNodeToString(result);
343
+ }
344
+ if (node.type) {
345
+ if (typeof node.type === "function") {
346
+ const result = await node.type(node.props || {});
347
+ return renderNodeToString(result);
302
348
  }
303
- if ("type" in element && element.props !== void 0) {
304
- const { type, props } = element;
305
- if (typeof type === "function") {
306
- try {
307
- prepareRender();
308
- const result = await type(props || {});
309
- const html2 = await renderToString(result);
310
- finishRender();
311
- return html2;
312
- } catch (error) {
313
- console.error("Error rendering component:", error);
314
- return "";
315
- }
316
- }
317
- let html = `<${type}`;
318
- for (const [key, value] of Object.entries(props || {})) {
319
- if (key === "children")
320
- continue;
321
- if (key === "className") {
322
- html += ` class="${escapeHtml(String(value))}"`;
323
- } else if (key === "style" && typeof value === "object") {
324
- html += ` style="${stringifyStyle(value || {})}"`;
325
- } else if (!key.startsWith("on")) {
326
- html += ` ${key}="${escapeHtml(String(value))}"`;
327
- }
328
- }
329
- const voidElements = /* @__PURE__ */ new Set([
330
- "area",
331
- "base",
332
- "br",
333
- "col",
334
- "embed",
335
- "hr",
336
- "img",
337
- "input",
338
- "link",
339
- "meta",
340
- "param",
341
- "source",
342
- "track",
343
- "wbr"
344
- ]);
345
- if (voidElements.has(type)) {
346
- return html + "/>";
349
+ let html = `<${node.type}`;
350
+ for (const [key, value] of Object.entries(node.props || {})) {
351
+ if (key === "children" || key === "key" || key === "ref")
352
+ continue;
353
+ if (key === "className") {
354
+ html += ` class="${escapeHtml(String(value))}"`;
355
+ } else if (key === "style" && typeof value === "object" && value !== null) {
356
+ html += ` style="${styleToString(value)}"`;
357
+ } else if (!key.startsWith("on")) {
358
+ html += ` ${key}="${escapeHtml(String(value))}"`;
347
359
  }
348
- html += ">";
349
- if (props == null ? void 0 : props.children) {
350
- const children = Array.isArray(props.children) ? props.children : [props.children];
351
- const renderedChildren = await Promise.all(children.map(renderToString));
352
- html += renderedChildren.join("");
360
+ }
361
+ html += ">";
362
+ if ((_a = node.props) == null ? void 0 : _a.children) {
363
+ const children = Array.isArray(node.props.children) ? node.props.children : [node.props.children];
364
+ for (const child of children) {
365
+ html += await renderNodeToString(child);
353
366
  }
354
- return html + `</${type}>`;
355
367
  }
356
- return escapeHtml(String(element));
357
- } finally {
358
- finishRender();
368
+ html += `</${node.type}>`;
369
+ return html;
359
370
  }
371
+ return "";
360
372
  }
361
373
  function escapeHtml(str) {
362
- return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
363
- }
364
- function stringifyStyle(style) {
365
- return Object.entries(style).map(([key, value]) => `${hyphenate(key)}:${value}`).join(";");
374
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
366
375
  }
367
- function hyphenate(str) {
368
- return str.replace(/[A-Z]/g, (match) => "-" + match.toLowerCase());
376
+ function styleToString(style) {
377
+ return Object.entries(style).map(([key, value]) => `${key}: ${value}`).join("; ");
369
378
  }
370
379
  let currentState = {
371
380
  pathname: typeof window !== "undefined" ? window.location.pathname : "/",
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/batch.ts","../src/hooks.ts","../src/context.ts","../src/jsx-runtime.ts","../src/renderer.ts","../src/server-renderer.ts","../src/router.ts","../src/link.tsx"],"sourcesContent":["export let isBatching = false;\r\nconst queue: Function[] = [];\r\n\r\nexport function batchUpdates(fn: Function) {\r\n if (isBatching) {\r\n queue.push(fn);\r\n return;\r\n }\r\n\r\n isBatching = true;\r\n try {\r\n fn();\r\n while (queue.length > 0) {\r\n const nextFn = queue.shift();\r\n nextFn?.();\r\n }\r\n } finally {\r\n isBatching = false;\r\n }\r\n}\r\n\r\nexport function getIsBatching() {\r\n return isBatching;\r\n}\r\n","import { createElement } from './jsx-runtime';\r\nimport { batchUpdates, isBatching } from './batch';\r\nimport { diff } from './vdom';\r\n\r\nlet currentRender: number = 0;\r\nconst states = new Map<number, any[]>();\r\nconst stateIndices = new Map<number, number>();\r\nconst effects = new Map<number, Effect[]>();\r\nconst memos = new Map<number, { value: any; deps: any[] }[]>();\r\nconst refs = new Map<number, any[]>();\r\n\r\ninterface Effect {\r\n cleanup?: () => void;\r\n deps?: any[];\r\n}\r\n\r\n// Add at the top with other declarations\r\nlet globalRenderCallback: ((element: any, container: HTMLElement) => void) | null = null;\r\nlet globalContainer: HTMLElement | null = null;\r\nlet currentElement: any = null;\r\n\r\nconst isServer = typeof window === 'undefined';\r\nconst serverStates = new Map<number, any>();\r\n\r\nexport function setRenderCallback(\r\n callback: (element: any, container: HTMLElement) => void,\r\n element: any,\r\n container: HTMLElement\r\n) {\r\n globalRenderCallback = callback;\r\n globalContainer = container;\r\n currentElement = element;\r\n}\r\n\r\nexport function prepareRender() {\r\n currentRender++;\r\n stateIndices.set(currentRender, 0);\r\n return currentRender;\r\n}\r\n\r\nexport function finishRender() {\r\n if (isServer) {\r\n serverStates.delete(currentRender);\r\n }\r\n currentRender = 0;\r\n}\r\n\r\nexport function useState<T>(initial: T): [T, (value: T | ((prev: T) => T)) => void] {\r\n if (!currentRender) {\r\n throw new Error('useState must be called within a render');\r\n }\r\n\r\n if (isServer) {\r\n // Server-side state handling\r\n if (!serverStates.has(currentRender)) {\r\n serverStates.set(currentRender, new Map());\r\n }\r\n const componentState = serverStates.get(currentRender)!;\r\n const index = stateIndices.get(currentRender) || 0;\r\n \r\n if (!componentState.has(index)) {\r\n componentState.set(index, initial);\r\n }\r\n\r\n const state = componentState.get(index);\r\n const setState = (newValue: T | ((prev: T) => T)) => {\r\n // No-op for server-side\r\n };\r\n\r\n stateIndices.set(currentRender, index + 1);\r\n return [state, setState];\r\n }\r\n\r\n if (!states.has(currentRender)) {\r\n states.set(currentRender, []);\r\n }\r\n\r\n const componentStates = states.get(currentRender)!;\r\n const index = stateIndices.get(currentRender)!;\r\n \r\n if (index >= componentStates.length) {\r\n componentStates.push(initial);\r\n }\r\n\r\n const state = componentStates[index];\r\n const setState = (newValue: T | ((prev: T) => T)) => {\r\n const nextValue = typeof newValue === 'function' \r\n ? (newValue as Function)(componentStates[index])\r\n : newValue;\r\n\r\n if (componentStates[index] === nextValue) return; // Skip if value hasn't changed\r\n \r\n componentStates[index] = nextValue;\r\n \r\n if (isBatching) {\r\n batchUpdates(() => rerender(currentRender));\r\n } else {\r\n rerender(currentRender);\r\n }\r\n };\r\n\r\n stateIndices.set(currentRender, index + 1);\r\n return [state, setState];\r\n}\r\n\r\nexport function useEffect(callback: () => (() => void) | void, deps?: any[]) {\r\n if (!currentRender) throw new Error('useEffect must be called within a render');\r\n \r\n const effectIndex = stateIndices.get(currentRender)!;\r\n \r\n if (!effects.has(currentRender)) {\r\n effects.set(currentRender, []);\r\n }\r\n\r\n const componentEffects = effects.get(currentRender)!;\r\n const prevEffect = componentEffects[effectIndex];\r\n \r\n // Run effect if deps changed\r\n if (!prevEffect || !deps || !prevEffect.deps || \r\n deps.some((dep, i) => dep !== prevEffect.deps![i])) {\r\n \r\n // Cleanup previous effect\r\n if (prevEffect?.cleanup) {\r\n prevEffect.cleanup();\r\n }\r\n\r\n // Schedule new effect\r\n queueMicrotask(() => {\r\n const cleanup = callback() || undefined;\r\n componentEffects[effectIndex] = { cleanup: cleanup, deps };\r\n });\r\n }\r\n \r\n stateIndices.set(currentRender, effectIndex + 1);\r\n}\r\n\r\nexport function useMemo<T>(factory: () => T, deps: any[]): T {\r\n if (!currentRender) throw new Error('useMemo must be called within a render');\r\n \r\n const memoIndex = stateIndices.get(currentRender)!;\r\n \r\n if (!memos.has(currentRender)) {\r\n memos.set(currentRender, []);\r\n }\r\n\r\n const componentMemos = memos.get(currentRender)!;\r\n const prevMemo = componentMemos[memoIndex];\r\n \r\n if (!prevMemo || (deps && deps.some((dep, i) => !Object.is(dep, prevMemo.deps[i])))) {\r\n const value = factory();\r\n componentMemos[memoIndex] = { value, deps };\r\n stateIndices.set(currentRender, memoIndex + 1);\r\n return value;\r\n }\r\n\r\n stateIndices.set(currentRender, memoIndex + 1);\r\n return prevMemo.value;\r\n}\r\n\r\nexport function useRef<T>(initial: T) {\r\n if (!currentRender) throw new Error('useRef must be called within a render');\r\n \r\n const refIndex = stateIndices.get(currentRender)!;\r\n \r\n if (!refs.has(currentRender)) {\r\n refs.set(currentRender, []);\r\n }\r\n\r\n const componentRefs = refs.get(currentRender)!;\r\n if (refIndex >= componentRefs.length) {\r\n // Initialize with an object that has a current property\r\n const ref = { current: initial };\r\n componentRefs.push(ref);\r\n stateIndices.set(currentRender, refIndex + 1);\r\n return ref;\r\n }\r\n\r\n const ref = componentRefs[refIndex];\r\n stateIndices.set(currentRender, refIndex + 1);\r\n return ref;\r\n}\r\n\r\n// Add a map to track component DOM nodes\r\nconst componentNodes = new Map<Function, Node>();\r\n\r\nasync function rerender(rendererId: number) {\r\n try {\r\n // Clean up effects\r\n const componentEffects = effects.get(rendererId);\r\n if (componentEffects) {\r\n componentEffects.forEach(effect => {\r\n if (effect.cleanup) effect.cleanup();\r\n });\r\n effects.set(rendererId, []);\r\n }\r\n\r\n if (globalRenderCallback && globalContainer && currentElement) {\r\n await globalRenderCallback(currentElement, globalContainer);\r\n }\r\n } catch (error) {\r\n console.error('Error during rerender:', error);\r\n }\r\n}\r\n\r\n// Add new hook for error boundaries\r\nexport function useErrorBoundary(): [Error | null, () => void] {\r\n const [error, setError] = useState<Error | null>(null);\r\n return [error, () => setError(null)];\r\n}\r\n\r\n// Remove withHooks export\r\n","\r\n\r\nconst contexts = new Map<symbol, any>();\r\nlet currentRender: Function | null = null;\r\n\r\nexport interface Context<T> {\r\n Provider: (props: { value: T; children?: any }) => any;\r\n Consumer: (props: { children: (value: T) => any }) => any;\r\n _id: symbol;\r\n useSelector: <S>(selector: (state: T) => S) => S;\r\n}\r\n\r\nexport function createContext<T>(defaultValue: T): Context<T> {\r\n const context = {\r\n Provider: ({ value, children }: { value: T, children?: any }) => {\r\n return children;\r\n },\r\n Consumer: ({ children }: { children: (value: T) => any }) => {\r\n return children(defaultValue);\r\n },\r\n _id: Symbol(),\r\n useSelector: <S>(selector: (state: T) => S) => {\r\n return selector(defaultValue);\r\n }\r\n };\r\n\r\n return context;\r\n}\r\n\r\nexport function useContext<T>(context: any): T {\r\n return context;\r\n}\r\n","import type { Component } from './component';\r\n\r\ninterface VNode {\r\n type: string | Function;\r\n props: Record<string, any>;\r\n}\r\n\r\nfunction jsx(type: string | Function, props: any): VNode {\r\n console.log('JSX Transform:', { type, props });\r\n const processedProps = { ...props };\r\n \r\n // Handle children properly\r\n if (arguments.length > 2) {\r\n processedProps.children = Array.prototype.slice.call(arguments, 2);\r\n }\r\n \r\n return { type, props: processedProps };\r\n}\r\n\r\nconst Fragment = ({ children }: { children: any }) => children;\r\n\r\nasync function createElement(vnode: VNode | any): Promise<Node> {\r\n console.log('Creating element from:', vnode);\r\n\r\n // Handle primitives and null\r\n if (vnode == null) {\r\n return document.createTextNode('');\r\n }\r\n \r\n if (typeof vnode === 'boolean') {\r\n return document.createTextNode('');\r\n }\r\n\r\n if (typeof vnode === 'number' || typeof vnode === 'string') {\r\n return document.createTextNode(String(vnode));\r\n }\r\n\r\n // Handle arrays\r\n if (Array.isArray(vnode)) {\r\n const fragment = document.createDocumentFragment();\r\n for (const child of vnode) {\r\n const node = await createElement(child);\r\n fragment.appendChild(node);\r\n }\r\n return fragment;\r\n }\r\n\r\n // Handle VNode\r\n if ('type' in vnode && vnode.props !== undefined) {\r\n const { type, props } = vnode;\r\n \r\n // Handle function components\r\n if (typeof type === 'function') {\r\n try {\r\n const result = await type(props || {});\r\n const node = await createElement(result);\r\n if (node instanceof Element) {\r\n node.setAttribute('data-component-id', type.name || type.toString());\r\n }\r\n return node;\r\n } catch (error) {\r\n console.error('Error rendering component:', error);\r\n return document.createTextNode('');\r\n }\r\n }\r\n\r\n // Create DOM element\r\n const element = document.createElement(type as string);\r\n \r\n // Handle props\r\n for (const [key, value] of Object.entries(props || {})) {\r\n if (key === 'children') continue;\r\n if (key.startsWith('on') && typeof value === 'function') {\r\n const eventName = key.toLowerCase().slice(2);\r\n // Remove existing event listener if any\r\n const existingHandler = (element as any).__events?.[eventName];\r\n if (existingHandler) {\r\n element.removeEventListener(eventName, existingHandler);\r\n }\r\n \r\n // Add new event listener\r\n element.addEventListener(eventName, value as EventListener);\r\n if (!(element as any).__events) {\r\n (element as any).__events = {};\r\n }\r\n (element as any).__events[eventName] = value;\r\n } else if (key === 'style' && typeof value === 'object') {\r\n Object.assign(element.style, value);\r\n } else if (key === 'className') {\r\n element.setAttribute('class', String(value));\r\n } else if (key !== 'key' && key !== 'ref') {\r\n element.setAttribute(key, String(value));\r\n }\r\n }\r\n\r\n // Handle children\r\n const children = props?.children;\r\n if (children != null) {\r\n const childArray = Array.isArray(children) ? children.flat() : [children];\r\n for (const child of childArray) {\r\n const childNode = await createElement(child);\r\n element.appendChild(childNode);\r\n }\r\n }\r\n\r\n return element;\r\n }\r\n\r\n // Handle other objects by converting to string\r\n return document.createTextNode(String(vnode));\r\n}\r\n\r\n// Export named functions and aliases without duplicates\r\nexport {\r\n jsx,\r\n jsx as jsxs,\r\n jsx as jsxDEV,\r\n Fragment,\r\n createElement\r\n};\r\n\r\n// Named exports object\r\nconst jsxRuntime = {\r\n jsx,\r\n jsxs: jsx,\r\n jsxDEV: jsx,\r\n Fragment,\r\n createElement\r\n};\r\n\r\nexport default jsxRuntime;\r\n","import { createElement } from './jsx-runtime';\r\nimport { prepareRender, finishRender, setRenderCallback } from './hooks';\r\nimport { batchUpdates } from './batch';\r\n\r\nlet isHydrating = false;\r\n\r\nexport async function hydrate(element: any, container: HTMLElement) {\r\n isHydrating = true;\r\n try {\r\n await render(element, container);\r\n } finally {\r\n isHydrating = false;\r\n }\r\n}\r\n\r\nexport async function render(element: any, container: HTMLElement) {\r\n console.log('Rendering to:', container.id);\r\n \r\n batchUpdates(async () => {\r\n const rendererId = prepareRender();\r\n try {\r\n setRenderCallback(render, element, container);\r\n const domNode = await createElement(element);\r\n \r\n if (!isHydrating) {\r\n container.innerHTML = '';\r\n }\r\n container.appendChild(domNode);\r\n \r\n } finally {\r\n finishRender();\r\n }\r\n });\r\n}\r\n","import { prepareRender, finishRender, setRenderCallback } from './hooks';\r\n\r\nexport async function renderToString(element: any): Promise<string> {\r\n // Setup render context\r\n const rendererId = prepareRender();\r\n setRenderCallback(() => {}, element, null as any);\r\n \r\n try {\r\n if (element == null) return '';\r\n \r\n if (typeof element === 'boolean') return '';\r\n \r\n if (typeof element === 'number' || typeof element === 'string') {\r\n return escapeHtml(String(element));\r\n }\r\n\r\n if (Array.isArray(element)) {\r\n const children = await Promise.all(element.map(renderToString));\r\n return children.join('');\r\n }\r\n\r\n if ('type' in element && element.props !== undefined) {\r\n const { type, props } = element;\r\n\r\n // Handle function components\r\n if (typeof type === 'function') {\r\n try {\r\n // Prepare new render context for the component\r\n prepareRender();\r\n const result = await type(props || {});\r\n const html = await renderToString(result);\r\n finishRender();\r\n return html;\r\n } catch (error) {\r\n console.error('Error rendering component:', error);\r\n return '';\r\n }\r\n }\r\n\r\n // Handle regular elements\r\n let html = `<${type}`;\r\n\r\n // Add attributes\r\n for (const [key, value] of Object.entries(props || {})) {\r\n if (key === 'children') continue;\r\n if (key === 'className') {\r\n html += ` class=\"${escapeHtml(String(value))}\"`;\r\n } else if (key === 'style' && typeof value === 'object') {\r\n html += ` style=\"${stringifyStyle(value || {})}\"`;\r\n } else if (!key.startsWith('on')) {\r\n html += ` ${key}=\"${escapeHtml(String(value))}\"`;\r\n }\r\n }\r\n\r\n // Handle self-closing tags\r\n const voidElements = new Set([\r\n 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',\r\n 'link', 'meta', 'param', 'source', 'track', 'wbr'\r\n ]);\r\n \r\n if (voidElements.has(type)) {\r\n return html + '/>';\r\n }\r\n\r\n html += '>';\r\n\r\n // Add children\r\n if (props?.children) {\r\n const children = Array.isArray(props.children) ? props.children : [props.children];\r\n const renderedChildren = await Promise.all(children.map(renderToString));\r\n html += renderedChildren.join('');\r\n }\r\n\r\n return html + `</${type}>`;\r\n }\r\n\r\n return escapeHtml(String(element));\r\n } finally {\r\n finishRender();\r\n }\r\n}\r\n\r\nfunction escapeHtml(str: string): string {\r\n return str\r\n .replace(/&/g, '&amp;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;')\r\n .replace(/\"/g, '&quot;')\r\n .replace(/'/g, '&#39;');\r\n}\r\n\r\nfunction stringifyStyle(style: Record<string, any>): string {\r\n return Object.entries(style)\r\n .map(([key, value]) => `${hyphenate(key)}:${value}`)\r\n .join(';');\r\n}\r\n\r\nfunction hyphenate(str: string): string {\r\n return str.replace(/[A-Z]/g, match => '-' + match.toLowerCase());\r\n}\r\n","import { useState, useEffect } from './hooks';\r\n\r\ninterface RouterState {\r\n pathname: string;\r\n search: string;\r\n hash: string;\r\n params: Record<string, string>;\r\n}\r\n\r\ninterface RouterOptions {\r\n replace?: boolean;\r\n scroll?: boolean;\r\n}\r\n\r\nlet currentState: RouterState = {\r\n pathname: typeof window !== 'undefined' ? window.location.pathname : '/',\r\n search: typeof window !== 'undefined' ? window.location.search : '',\r\n hash: typeof window !== 'undefined' ? window.location.hash : '',\r\n params: {}\r\n};\r\n\r\nconst listeners = new Set<(state: RouterState) => void>();\r\n\r\n// Parse route pattern and extract params\r\nfunction matchRoute(pattern: string, pathname: string): Record<string, string> | null {\r\n const paramNames: string[] = [];\r\n const regexPattern = pattern.replace(/:([^/]+)/g, (_, name) => {\r\n paramNames.push(name);\r\n return '([^/]+)';\r\n });\r\n\r\n const match = pathname.match(new RegExp(`^${regexPattern}$`));\r\n if (!match) return null;\r\n\r\n const params: Record<string, string> = {};\r\n paramNames.forEach((name, i) => {\r\n params[name] = match[i + 1];\r\n });\r\n\r\n return params;\r\n}\r\n\r\nfunction updateState(newPath: string, options: RouterOptions = {}) {\r\n const url = new URL(newPath, window.location.origin);\r\n const newState: RouterState = {\r\n pathname: url.pathname,\r\n search: url.search,\r\n hash: url.hash,\r\n params: {}\r\n };\r\n\r\n if (options.replace) {\r\n window.history.replaceState(newState, '', url.toString());\r\n } else {\r\n window.history.pushState(newState, '', url.toString());\r\n }\r\n\r\n currentState = newState;\r\n listeners.forEach(listener => listener(newState));\r\n\r\n if (options.scroll) {\r\n window.scrollTo(0, 0);\r\n }\r\n}\r\n\r\nexport function navigate(to: string, options: RouterOptions = {}) {\r\n if (typeof window === 'undefined') return;\r\n updateState(to, options);\r\n}\r\n\r\nexport function useRouter() {\r\n const [state, setState] = useState<RouterState>(currentState);\r\n\r\n useEffect(() => {\r\n const handleRouteChange = (newState: RouterState) => {\r\n setState(newState);\r\n };\r\n\r\n const handlePopState = () => {\r\n currentState = {\r\n pathname: window.location.pathname,\r\n search: window.location.search,\r\n hash: window.location.hash,\r\n params: {}\r\n };\r\n setState(currentState);\r\n };\r\n\r\n listeners.add(handleRouteChange);\r\n window.addEventListener('popstate', handlePopState);\r\n\r\n return () => {\r\n listeners.delete(handleRouteChange);\r\n window.removeEventListener('popstate', handlePopState);\r\n };\r\n }, []);\r\n\r\n return {\r\n ...state,\r\n push: (to: string, options?: RouterOptions) => navigate(to, options),\r\n replace: (to: string, options?: RouterOptions) => navigate(to, { ...options, replace: true }),\r\n back: () => window.history.back(),\r\n forward: () => window.history.forward()\r\n };\r\n}\r\n\r\nexport function useRoute(pattern: string) {\r\n const { pathname } = useRouter();\r\n const [params, setParams] = useState<Record<string, string>>({});\r\n const [isMatch, setIsMatch] = useState(false);\r\n\r\n useEffect(() => {\r\n const matchedParams = matchRoute(pattern, pathname);\r\n setIsMatch(!!matchedParams);\r\n setParams(matchedParams || {});\r\n }, [pattern, pathname]);\r\n\r\n return { isMatch, params };\r\n}\r\n\r\nexport function useParams<T extends Record<string, string>>() {\r\n const router = useRouter();\r\n return router.params as T;\r\n}\r\n\r\nexport function useSearchParams() {\r\n const { search } = useRouter();\r\n return new URLSearchParams(search);\r\n}\r\n","import { navigate } from './router';\r\n\r\ninterface LinkProps {\r\n href: string;\r\n children?: any;\r\n replace?: boolean;\r\n className?: string;\r\n style?: Record<string, string>;\r\n [key: string]: any;\r\n}\r\n\r\nexport function Link({ \r\n href, \r\n children, \r\n replace = false, \r\n className,\r\n style,\r\n ...rest \r\n}: LinkProps) {\r\n const handleClick = (e: MouseEvent) => {\r\n e.preventDefault();\r\n navigate(href, { replace });\r\n };\r\n\r\n return {\r\n type: 'a',\r\n props: {\r\n href,\r\n onClick: handleClick,\r\n className,\r\n style,\r\n ...rest,\r\n children\r\n }\r\n };\r\n}\r\n"],"names":["index","state","setState","ref","html"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/batch.ts","../src/hooks.ts","../src/context.ts","../src/jsx-runtime.ts","../src/renderer.ts","../src/templates/default.ts","../src/server-renderer.ts","../src/router.ts","../src/link.tsx"],"sourcesContent":["export let isBatching = false;\r\nconst queue: Function[] = [];\r\n\r\nexport function batchUpdates(fn: Function) {\r\n if (isBatching) {\r\n queue.push(fn);\r\n return;\r\n }\r\n\r\n isBatching = true;\r\n try {\r\n fn();\r\n while (queue.length > 0) {\r\n const nextFn = queue.shift();\r\n nextFn?.();\r\n }\r\n } finally {\r\n isBatching = false;\r\n }\r\n}\r\n\r\nexport function getIsBatching() {\r\n return isBatching;\r\n}\r\n","import { createElement } from './jsx-runtime';\r\nimport { batchUpdates, isBatching } from './batch';\r\nimport { diff } from './vdom';\r\n\r\nlet currentRender: number = 0;\r\nconst states = new Map<number, any[]>();\r\nconst stateIndices = new Map<number, number>();\r\nconst effects = new Map<number, Effect[]>();\r\nconst memos = new Map<number, { value: any; deps: any[] }[]>();\r\nconst refs = new Map<number, any[]>();\r\n\r\ninterface Effect {\r\n cleanup?: () => void;\r\n deps?: any[];\r\n}\r\n\r\n// Add at the top with other declarations\r\nlet globalRenderCallback: ((element: any, container: HTMLElement) => void) | null = null;\r\nlet globalContainer: HTMLElement | null = null;\r\nlet currentElement: any = null;\r\n\r\nconst isServer = typeof window === 'undefined';\r\nconst serverStates = new Map<number, any>();\r\n\r\nexport function setRenderCallback(\r\n callback: (element: any, container: HTMLElement) => void,\r\n element: any,\r\n container: HTMLElement\r\n) {\r\n globalRenderCallback = callback;\r\n globalContainer = container;\r\n currentElement = element;\r\n}\r\n\r\nexport function prepareRender() {\r\n currentRender++;\r\n stateIndices.set(currentRender, 0);\r\n return currentRender;\r\n}\r\n\r\nexport function finishRender() {\r\n if (isServer) {\r\n serverStates.delete(currentRender);\r\n }\r\n currentRender = 0;\r\n}\r\n\r\nexport function useState<T>(initial: T): [T, (value: T | ((prev: T) => T)) => void] {\r\n if (!currentRender) {\r\n throw new Error('useState must be called within a render');\r\n }\r\n\r\n if (isServer) {\r\n // Server-side state handling\r\n if (!serverStates.has(currentRender)) {\r\n serverStates.set(currentRender, new Map());\r\n }\r\n const componentState = serverStates.get(currentRender)!;\r\n const index = stateIndices.get(currentRender) || 0;\r\n \r\n if (!componentState.has(index)) {\r\n componentState.set(index, initial);\r\n }\r\n\r\n const state = componentState.get(index);\r\n const setState = (newValue: T | ((prev: T) => T)) => {\r\n // No-op for server-side\r\n };\r\n\r\n stateIndices.set(currentRender, index + 1);\r\n return [state, setState];\r\n }\r\n\r\n if (!states.has(currentRender)) {\r\n states.set(currentRender, []);\r\n }\r\n\r\n const componentStates = states.get(currentRender)!;\r\n const index = stateIndices.get(currentRender)!;\r\n \r\n if (index >= componentStates.length) {\r\n componentStates.push(initial);\r\n }\r\n\r\n const state = componentStates[index];\r\n const setState = (newValue: T | ((prev: T) => T)) => {\r\n const nextValue = typeof newValue === 'function' \r\n ? (newValue as Function)(componentStates[index])\r\n : newValue;\r\n\r\n if (componentStates[index] === nextValue) return; // Skip if value hasn't changed\r\n \r\n componentStates[index] = nextValue;\r\n \r\n if (isBatching) {\r\n batchUpdates(() => rerender(currentRender));\r\n } else {\r\n rerender(currentRender);\r\n }\r\n };\r\n\r\n stateIndices.set(currentRender, index + 1);\r\n return [state, setState];\r\n}\r\n\r\nexport function useEffect(callback: () => (() => void) | void, deps?: any[]) {\r\n if (!currentRender) throw new Error('useEffect must be called within a render');\r\n \r\n const effectIndex = stateIndices.get(currentRender)!;\r\n \r\n if (!effects.has(currentRender)) {\r\n effects.set(currentRender, []);\r\n }\r\n\r\n const componentEffects = effects.get(currentRender)!;\r\n const prevEffect = componentEffects[effectIndex];\r\n \r\n // Run effect if deps changed\r\n if (!prevEffect || !deps || !prevEffect.deps || \r\n deps.some((dep, i) => dep !== prevEffect.deps![i])) {\r\n \r\n // Cleanup previous effect\r\n if (prevEffect?.cleanup) {\r\n prevEffect.cleanup();\r\n }\r\n\r\n // Schedule new effect\r\n queueMicrotask(() => {\r\n const cleanup = callback() || undefined;\r\n componentEffects[effectIndex] = { cleanup: cleanup, deps };\r\n });\r\n }\r\n \r\n stateIndices.set(currentRender, effectIndex + 1);\r\n}\r\n\r\nexport function useMemo<T>(factory: () => T, deps: any[]): T {\r\n if (!currentRender) throw new Error('useMemo must be called within a render');\r\n \r\n const memoIndex = stateIndices.get(currentRender)!;\r\n \r\n if (!memos.has(currentRender)) {\r\n memos.set(currentRender, []);\r\n }\r\n\r\n const componentMemos = memos.get(currentRender)!;\r\n const prevMemo = componentMemos[memoIndex];\r\n \r\n if (!prevMemo || (deps && deps.some((dep, i) => !Object.is(dep, prevMemo.deps[i])))) {\r\n const value = factory();\r\n componentMemos[memoIndex] = { value, deps };\r\n stateIndices.set(currentRender, memoIndex + 1);\r\n return value;\r\n }\r\n\r\n stateIndices.set(currentRender, memoIndex + 1);\r\n return prevMemo.value;\r\n}\r\n\r\nexport function useRef<T>(initial: T) {\r\n if (!currentRender) throw new Error('useRef must be called within a render');\r\n \r\n const refIndex = stateIndices.get(currentRender)!;\r\n \r\n if (!refs.has(currentRender)) {\r\n refs.set(currentRender, []);\r\n }\r\n\r\n const componentRefs = refs.get(currentRender)!;\r\n if (refIndex >= componentRefs.length) {\r\n // Initialize with an object that has a current property\r\n const ref = { current: initial };\r\n componentRefs.push(ref);\r\n stateIndices.set(currentRender, refIndex + 1);\r\n return ref;\r\n }\r\n\r\n const ref = componentRefs[refIndex];\r\n stateIndices.set(currentRender, refIndex + 1);\r\n return ref;\r\n}\r\n\r\n// Add a map to track component DOM nodes\r\nconst componentNodes = new Map<Function, Node>();\r\n\r\nasync function rerender(rendererId: number) {\r\n try {\r\n // Clean up effects\r\n const componentEffects = effects.get(rendererId);\r\n if (componentEffects) {\r\n componentEffects.forEach(effect => {\r\n if (effect.cleanup) effect.cleanup();\r\n });\r\n effects.set(rendererId, []);\r\n }\r\n\r\n if (globalRenderCallback && globalContainer && currentElement) {\r\n await globalRenderCallback(currentElement, globalContainer);\r\n }\r\n } catch (error) {\r\n console.error('Error during rerender:', error);\r\n }\r\n}\r\n\r\n// Add new hook for error boundaries\r\nexport function useErrorBoundary(): [Error | null, () => void] {\r\n const [error, setError] = useState<Error | null>(null);\r\n return [error, () => setError(null)];\r\n}\r\n\r\n// Remove withHooks export\r\n","\r\n\r\nconst contexts = new Map<symbol, any>();\r\nlet currentRender: Function | null = null;\r\n\r\nexport interface Context<T> {\r\n Provider: (props: { value: T; children?: any }) => any;\r\n Consumer: (props: { children: (value: T) => any }) => any;\r\n _id: symbol;\r\n useSelector: <S>(selector: (state: T) => S) => S;\r\n}\r\n\r\nexport function createContext<T>(defaultValue: T): Context<T> {\r\n const context = {\r\n Provider: ({ value, children }: { value: T, children?: any }) => {\r\n return children;\r\n },\r\n Consumer: ({ children }: { children: (value: T) => any }) => {\r\n return children(defaultValue);\r\n },\r\n _id: Symbol(),\r\n useSelector: <S>(selector: (state: T) => S) => {\r\n return selector(defaultValue);\r\n }\r\n };\r\n\r\n return context;\r\n}\r\n\r\nexport function useContext<T>(context: any): T {\r\n return context;\r\n}\r\n","import type { Component } from './component';\r\n\r\ninterface VNode {\r\n type: string | Function;\r\n props: Record<string, any>;\r\n}\r\n\r\nfunction jsx(type: string | Function, props: any): VNode {\r\n console.log('JSX Transform:', { type, props });\r\n const processedProps = { ...props };\r\n \r\n // Handle children properly\r\n if (arguments.length > 2) {\r\n processedProps.children = Array.prototype.slice.call(arguments, 2);\r\n }\r\n \r\n return { type, props: processedProps };\r\n}\r\n\r\nconst Fragment = ({ children }: { children: any }) => children;\r\n\r\nasync function createElement(vnode: VNode | any): Promise<Node> {\r\n console.log('Creating element from:', vnode);\r\n\r\n // Handle primitives and null\r\n if (vnode == null) {\r\n return document.createTextNode('');\r\n }\r\n \r\n if (typeof vnode === 'boolean') {\r\n return document.createTextNode('');\r\n }\r\n\r\n if (typeof vnode === 'number' || typeof vnode === 'string') {\r\n return document.createTextNode(String(vnode));\r\n }\r\n\r\n // Handle arrays\r\n if (Array.isArray(vnode)) {\r\n const fragment = document.createDocumentFragment();\r\n for (const child of vnode) {\r\n const node = await createElement(child);\r\n fragment.appendChild(node);\r\n }\r\n return fragment;\r\n }\r\n\r\n // Handle VNode\r\n if ('type' in vnode && vnode.props !== undefined) {\r\n const { type, props } = vnode;\r\n \r\n // Handle function components\r\n if (typeof type === 'function') {\r\n try {\r\n const result = await type(props || {});\r\n const node = await createElement(result);\r\n if (node instanceof Element) {\r\n node.setAttribute('data-component-id', type.name || type.toString());\r\n }\r\n return node;\r\n } catch (error) {\r\n console.error('Error rendering component:', error);\r\n return document.createTextNode('');\r\n }\r\n }\r\n\r\n // Create DOM element\r\n const element = document.createElement(type as string);\r\n \r\n // Handle props\r\n for (const [key, value] of Object.entries(props || {})) {\r\n if (key === 'children') continue;\r\n if (key.startsWith('on') && typeof value === 'function') {\r\n const eventName = key.toLowerCase().slice(2);\r\n // Remove existing event listener if any\r\n const existingHandler = (element as any).__events?.[eventName];\r\n if (existingHandler) {\r\n element.removeEventListener(eventName, existingHandler);\r\n }\r\n \r\n // Add new event listener\r\n element.addEventListener(eventName, value as EventListener);\r\n if (!(element as any).__events) {\r\n (element as any).__events = {};\r\n }\r\n (element as any).__events[eventName] = value;\r\n } else if (key === 'style' && typeof value === 'object') {\r\n Object.assign(element.style, value);\r\n } else if (key === 'className') {\r\n element.setAttribute('class', String(value));\r\n } else if (key !== 'key' && key !== 'ref') {\r\n element.setAttribute(key, String(value));\r\n }\r\n }\r\n\r\n // Handle children\r\n const children = props?.children;\r\n if (children != null) {\r\n const childArray = Array.isArray(children) ? children.flat() : [children];\r\n for (const child of childArray) {\r\n const childNode = await createElement(child);\r\n element.appendChild(childNode);\r\n }\r\n }\r\n\r\n return element;\r\n }\r\n\r\n // Handle other objects by converting to string\r\n return document.createTextNode(String(vnode));\r\n}\r\n\r\n// Export named functions and aliases without duplicates\r\nexport {\r\n jsx,\r\n jsx as jsxs,\r\n jsx as jsxDEV,\r\n Fragment,\r\n createElement\r\n};\r\n\r\n// Named exports object\r\nconst jsxRuntime = {\r\n jsx,\r\n jsxs: jsx,\r\n jsxDEV: jsx,\r\n Fragment,\r\n createElement\r\n};\r\n\r\nexport default jsxRuntime;\r\n","import { createElement } from './jsx-runtime';\r\nimport { prepareRender, finishRender, setRenderCallback } from './hooks';\r\nimport { batchUpdates } from './batch';\r\n\r\nlet isHydrating = false;\r\n\r\nexport async function hydrate(element: any, container: HTMLElement) {\r\n isHydrating = true;\r\n try {\r\n await render(element, container);\r\n } finally {\r\n isHydrating = false;\r\n }\r\n}\r\n\r\nexport async function render(element: any, container: HTMLElement) {\r\n console.log('Rendering to:', container.id);\r\n \r\n batchUpdates(async () => {\r\n const rendererId = prepareRender();\r\n try {\r\n setRenderCallback(render, element, container);\r\n const domNode = await createElement(element);\r\n \r\n if (!isHydrating) {\r\n container.innerHTML = '';\r\n }\r\n container.appendChild(domNode);\r\n \r\n } finally {\r\n finishRender();\r\n }\r\n });\r\n}\r\n","export interface TemplateOptions {\r\n title: string;\r\n description?: string;\r\n scripts?: string[];\r\n styles?: string[];\r\n initialState?: any;\r\n meta?: Record<string, string>;\r\n bodyAttrs?: Record<string, string>;\r\n htmlAttrs?: Record<string, string>;\r\n}\r\n\r\nexport function defaultTemplate(content: string, options: TemplateOptions): string {\r\n const {\r\n title,\r\n description = '',\r\n scripts = [],\r\n styles = [],\r\n initialState = {},\r\n meta = {},\r\n bodyAttrs = {},\r\n htmlAttrs = { lang: 'en' }\r\n } = options;\r\n\r\n const htmlAttributes = Object.entries(htmlAttrs)\r\n .map(([key, value]) => `${key}=\"${value}\"`)\r\n .join(' ');\r\n\r\n const bodyAttributes = Object.entries(bodyAttrs)\r\n .map(([key, value]) => `${key}=\"${value}\"`)\r\n .join(' ');\r\n\r\n const metaTags = Object.entries(meta)\r\n .map(([name, content]) => ` <meta name=\"${name}\" content=\"${content}\">`)\r\n .join('\\n');\r\n\r\n return `<!DOCTYPE html>\r\n<html ${htmlAttributes}>\r\n <head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n ${description ? `<meta name=\"description\" content=\"${description}\">\\n` : ''}${metaTags}\r\n <title>${title}</title>\r\n${styles.map(href => ` <link rel=\"stylesheet\" href=\"${href}\">`).join('\\n')}\r\n <script>\r\n window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};\r\n </script>\r\n </head>\r\n <body ${bodyAttributes}>\r\n <div id=\"root\">${content}</div>\r\n${scripts.map(src => ` <script src=\"${src}\" defer></script>`).join('\\n')}\r\n </body>\r\n</html>`;\r\n}\r\n","import { VNode } from './types';\r\nimport { defaultTemplate, TemplateOptions } from './templates/default';\r\n\r\nexport async function renderToString(\r\n element: JSX.Element, \r\n options: Partial<TemplateOptions> = {}\r\n): Promise<string> {\r\n try {\r\n const content = await renderNodeToString(element);\r\n return defaultTemplate(content, {\r\n title: 'Frontend Hamroun App',\r\n ...options\r\n });\r\n } catch (error) {\r\n console.error('Error during server rendering:', error);\r\n return '';\r\n }\r\n}\r\n\r\nasync function renderNodeToString(node: VNode | any): Promise<string> {\r\n if (node == null || typeof node === 'boolean') {\r\n return '';\r\n }\r\n\r\n if (typeof node === 'number' || typeof node === 'string') {\r\n return escapeHtml(String(node));\r\n }\r\n\r\n if (typeof node === 'function') {\r\n const result = await node({ });\r\n return renderNodeToString(result);\r\n }\r\n\r\n if (node.type) {\r\n if (typeof node.type === 'function') {\r\n const result = await node.type(node.props || {});\r\n return renderNodeToString(result);\r\n }\r\n\r\n let html = `<${node.type}`;\r\n \r\n // Handle props\r\n for (const [key, value] of Object.entries(node.props || {})) {\r\n if (key === 'children' || key === 'key' || key === 'ref') continue;\r\n if (key === 'className') {\r\n html += ` class=\"${escapeHtml(String(value))}\"`;\r\n } else if (key === 'style' && typeof value === 'object' && value !== null) {\r\n html += ` style=\"${styleToString(value)}\"`;\r\n } else if (!key.startsWith('on')) {\r\n html += ` ${key}=\"${escapeHtml(String(value))}\"`;\r\n }\r\n }\r\n\r\n html += '>';\r\n\r\n // Handle children\r\n if (node.props?.children) {\r\n const children = Array.isArray(node.props.children) \r\n ? node.props.children \r\n : [node.props.children];\r\n \r\n for (const child of children) {\r\n html += await renderNodeToString(child);\r\n }\r\n }\r\n\r\n html += `</${node.type}>`;\r\n return html;\r\n }\r\n\r\n return '';\r\n}\r\n\r\nfunction escapeHtml(str: string): string {\r\n return str\r\n .replace(/&/g, '&amp;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;')\r\n .replace(/\"/g, '&quot;')\r\n .replace(/'/g, '&#039;');\r\n}\r\n\r\nfunction styleToString(style: Record<string, any>): string {\r\n return Object.entries(style)\r\n .map(([key, value]) => `${key}: ${value}`)\r\n .join('; ');\r\n}\r\n","import { useState, useEffect } from './hooks';\r\n\r\ninterface RouterState {\r\n pathname: string;\r\n search: string;\r\n hash: string;\r\n params: Record<string, string>;\r\n}\r\n\r\ninterface RouterOptions {\r\n replace?: boolean;\r\n scroll?: boolean;\r\n}\r\n\r\nlet currentState: RouterState = {\r\n pathname: typeof window !== 'undefined' ? window.location.pathname : '/',\r\n search: typeof window !== 'undefined' ? window.location.search : '',\r\n hash: typeof window !== 'undefined' ? window.location.hash : '',\r\n params: {}\r\n};\r\n\r\nconst listeners = new Set<(state: RouterState) => void>();\r\n\r\n// Parse route pattern and extract params\r\nfunction matchRoute(pattern: string, pathname: string): Record<string, string> | null {\r\n const paramNames: string[] = [];\r\n const regexPattern = pattern.replace(/:([^/]+)/g, (_, name) => {\r\n paramNames.push(name);\r\n return '([^/]+)';\r\n });\r\n\r\n const match = pathname.match(new RegExp(`^${regexPattern}$`));\r\n if (!match) return null;\r\n\r\n const params: Record<string, string> = {};\r\n paramNames.forEach((name, i) => {\r\n params[name] = match[i + 1];\r\n });\r\n\r\n return params;\r\n}\r\n\r\nfunction updateState(newPath: string, options: RouterOptions = {}) {\r\n const url = new URL(newPath, window.location.origin);\r\n const newState: RouterState = {\r\n pathname: url.pathname,\r\n search: url.search,\r\n hash: url.hash,\r\n params: {}\r\n };\r\n\r\n if (options.replace) {\r\n window.history.replaceState(newState, '', url.toString());\r\n } else {\r\n window.history.pushState(newState, '', url.toString());\r\n }\r\n\r\n currentState = newState;\r\n listeners.forEach(listener => listener(newState));\r\n\r\n if (options.scroll) {\r\n window.scrollTo(0, 0);\r\n }\r\n}\r\n\r\nexport function navigate(to: string, options: RouterOptions = {}) {\r\n if (typeof window === 'undefined') return;\r\n updateState(to, options);\r\n}\r\n\r\nexport function useRouter() {\r\n const [state, setState] = useState<RouterState>(currentState);\r\n\r\n useEffect(() => {\r\n const handleRouteChange = (newState: RouterState) => {\r\n setState(newState);\r\n };\r\n\r\n const handlePopState = () => {\r\n currentState = {\r\n pathname: window.location.pathname,\r\n search: window.location.search,\r\n hash: window.location.hash,\r\n params: {}\r\n };\r\n setState(currentState);\r\n };\r\n\r\n listeners.add(handleRouteChange);\r\n window.addEventListener('popstate', handlePopState);\r\n\r\n return () => {\r\n listeners.delete(handleRouteChange);\r\n window.removeEventListener('popstate', handlePopState);\r\n };\r\n }, []);\r\n\r\n return {\r\n ...state,\r\n push: (to: string, options?: RouterOptions) => navigate(to, options),\r\n replace: (to: string, options?: RouterOptions) => navigate(to, { ...options, replace: true }),\r\n back: () => window.history.back(),\r\n forward: () => window.history.forward()\r\n };\r\n}\r\n\r\nexport function useRoute(pattern: string) {\r\n const { pathname } = useRouter();\r\n const [params, setParams] = useState<Record<string, string>>({});\r\n const [isMatch, setIsMatch] = useState(false);\r\n\r\n useEffect(() => {\r\n const matchedParams = matchRoute(pattern, pathname);\r\n setIsMatch(!!matchedParams);\r\n setParams(matchedParams || {});\r\n }, [pattern, pathname]);\r\n\r\n return { isMatch, params };\r\n}\r\n\r\nexport function useParams<T extends Record<string, string>>() {\r\n const router = useRouter();\r\n return router.params as T;\r\n}\r\n\r\nexport function useSearchParams() {\r\n const { search } = useRouter();\r\n return new URLSearchParams(search);\r\n}\r\n","import { navigate } from './router';\r\n\r\ninterface LinkProps {\r\n href: string;\r\n children?: any;\r\n replace?: boolean;\r\n className?: string;\r\n style?: Record<string, string>;\r\n [key: string]: any;\r\n}\r\n\r\nexport function Link({ \r\n href, \r\n children, \r\n replace = false, \r\n className,\r\n style,\r\n ...rest \r\n}: LinkProps) {\r\n const handleClick = (e: MouseEvent) => {\r\n e.preventDefault();\r\n navigate(href, { replace });\r\n };\r\n\r\n return {\r\n type: 'a',\r\n props: {\r\n href,\r\n onClick: handleClick,\r\n className,\r\n style,\r\n ...rest,\r\n children\r\n }\r\n };\r\n}\r\n"],"names":["index","state","setState","ref","content"],"mappings":"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"}
@@ -1 +1,2 @@
1
- export declare function renderToString(element: any): Promise<string>;
1
+ import { TemplateOptions } from './templates/default';
2
+ export declare function renderToString(element: JSX.Element, options?: Partial<TemplateOptions>): Promise<string>;
@@ -0,0 +1,11 @@
1
+ export interface TemplateOptions {
2
+ title: string;
3
+ description?: string;
4
+ scripts?: string[];
5
+ styles?: string[];
6
+ initialState?: any;
7
+ meta?: Record<string, string>;
8
+ bodyAttrs?: Record<string, string>;
9
+ htmlAttrs?: Record<string, string>;
10
+ }
11
+ export declare function defaultTemplate(content: string, options: TemplateOptions): string;
package/dist/types.d.ts CHANGED
@@ -1,15 +1,12 @@
1
1
  export type { Context } from './context';
2
2
  export interface VNode {
3
- type: string | Function;
3
+ type: string | Function | ((props: any) => any);
4
4
  props: Record<string, any>;
5
- key?: string | number;
5
+ key?: string | null;
6
6
  }
7
7
  declare global {
8
8
  namespace JSX {
9
- interface Element {
10
- type: string | Function;
11
- props: Record<string, any>;
12
- key?: string | number;
9
+ interface Element extends VNode {
13
10
  }
14
11
  interface IntrinsicElements {
15
12
  [elemName: string]: any;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontend-hamroun",
3
- "version": "1.1.46",
3
+ "version": "1.1.47",
4
4
  "description": "A lightweight frontend framework with hooks and virtual DOM",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -4,41 +4,48 @@ import { fileURLToPath } from 'url';
4
4
  import { renderToString, jsx } from 'frontend-hamroun';
5
5
  import { App } from './App.js';
6
6
  import fs from 'fs';
7
+ import { title } from 'process';
7
8
 
8
9
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
10
  const app = express();
10
11
  const port = 3000;
11
12
 
12
13
  // Find the client entry file
13
- const getClientEntry = () => {
14
+ function getClientEntry(): string {
14
15
  const assetsDir = path.join(__dirname, './');
15
16
  const files = fs.readdirSync(assetsDir);
16
- return files.find(file => file.startsWith("client")&& file.endsWith('.js'));
17
- };
17
+ const entry = files.find(file => file.startsWith("client") && file.endsWith('.js'));
18
+ if (!entry) {
19
+ throw new Error('Client entry file not found');
20
+ }
21
+ return entry;
22
+ }
18
23
 
19
- // Serve static files from dist/assets
24
+ // Static file serving
20
25
  app.use('/assets', express.static(path.join(__dirname, './')));
21
-
22
- // Serve static files from dist
23
26
  app.use(express.static(path.join(__dirname, 'dist')));
24
27
 
25
- app.get('/', async (_req: any, res: { send: (arg0: string) => void; }) => {
26
- const clientEntry = getClientEntry();
27
- const html = await renderToString(jsx(App, null
28
- ));
29
-
30
- res.send(`
31
- <!DOCTYPE html>
32
- <html>
33
- <head>
34
- <title>SSR App</title>
35
- </head>
36
- <body>
37
- <div id="root">${html}</div>
38
- <script type="module" src="/assets/${clientEntry}"></script>
39
- </body>
40
- </html>
41
- `);
28
+ // Main route handler
29
+ app.get('/', async (_req: any, res: { send: (arg0: string) => void; status: (arg0: number) => { (): any; new(): any; send: { (arg0: string): void; new(): any; }; }; }) => {
30
+ try {
31
+ const clientEntry = getClientEntry();
32
+ const html = await renderToString({
33
+ element: jsx(App, null),
34
+ title: 'SSR App',
35
+ scripts: [`/assets/${clientEntry}`],
36
+ initialState: {
37
+ // Add any initial state here
38
+ },
39
+ meta: {
40
+ 'viewport': 'width=device-width, initial-scale=1.0',
41
+ }
42
+ });
43
+
44
+ res.send(html);
45
+ } catch (error) {
46
+ console.error('Rendering error:', error);
47
+ res.status(500).send('Server Error');
48
+ }
42
49
  });
43
50
 
44
51
  app.listen(port, () => {