frontend-hamroun 1.1.54 → 1.1.56

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,420 +1,240 @@
1
- # Frontend Hamroun
1
+ # Your Package Name
2
2
 
3
- A lightweight, modern frontend framework with hooks, virtual DOM, and server-side rendering capabilities.
3
+ A lightweight Virtual DOM and hooks implementation with JSX support.
4
4
 
5
- ## Features
5
+ ## Installation
6
6
 
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
7
+ ```bash
8
+ npm install your-package-name
9
+ ```
15
10
 
16
- ## Installation
11
+ ## Quick Start
12
+
13
+ Create a new project using:
17
14
 
18
15
  ```bash
19
- npm install frontend-hamroun
16
+ npx create-frontend-app my-app
20
17
  # or
21
- yarn add frontend-hamroun
18
+ npm create frontend-app@latest my-app
22
19
  ```
20
+ Then:
23
21
 
24
- ## Quick Start
22
+ ```bash
23
+ cd my-app
24
+ npm install
25
+ npm run dev
26
+ ```
25
27
 
26
- ```tsx
27
- import { render, useState } from 'frontend-hamroun';
28
+ ## Usage
29
+
30
+ ```jsx
31
+ import { render, useState } from 'your-package-name';
28
32
 
29
- function Counter() {
33
+ function App() {
30
34
  const [count, setCount] = useState(0);
31
-
32
35
  return (
33
- <button onClick={() => setCount(count + 1)}>
34
- Count: {count}
35
- </button>
36
+ <div>
37
+ <h1>Count: {count}</h1>
38
+ <button onClick={() => setCount(count + 1)}>Increment</button>
39
+ </div>
36
40
  );
37
41
  }
38
42
 
39
- render(<Counter />, document.getElementById('root'));
43
+ render(<App />, document.getElementById('root'));
40
44
  ```
41
45
 
42
- ## Core Features
46
+ ## Features
43
47
 
44
- ### Hooks
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.
45
58
 
46
59
  ```tsx
47
- import { useState, useEffect, useMemo, useContext } from 'frontend-hamroun';
60
+ const [state, setState] = useState(initialValue);
61
+ ```
48
62
 
49
- // State Management
50
- const [state, setState] = useState(initialState);
63
+ ### useEffect
64
+ Handles side effects in components.
51
65
 
52
- // Side Effects
66
+ ```tsx
53
67
  useEffect(() => {
54
68
  // Effect code
55
69
  return () => {
56
70
  // Cleanup code
57
71
  };
58
72
  }, [dependencies]);
59
-
60
- // Memoization
61
- const memoizedValue = useMemo(() => computeExpensiveValue(deps), [deps]);
62
73
  ```
63
74
 
64
- ### Routing
75
+ ### useMemo
76
+ Memoizes expensive computations.
65
77
 
66
78
  ```tsx
67
- import { Link, useRouter } from 'frontend-hamroun';
68
-
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
- }
79
+ const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
83
80
  ```
84
81
 
85
- ### Context API
82
+ ### useRef
83
+ Creates a mutable reference.
86
84
 
87
85
  ```tsx
88
- import { createContext, useContext } from 'frontend-hamroun';
89
-
90
- const ThemeContext = createContext('light');
91
-
92
- function ThemedButton() {
93
- const theme = useContext(ThemeContext);
94
- return <button className={theme}>Click me</button>;
95
- }
86
+ const ref = useRef(initialValue);
96
87
  ```
97
88
 
98
- ## Server-Side Rendering
89
+ ### useErrorBoundary
90
+ Handles component errors.
99
91
 
100
- ### Quick Start
101
92
  ```tsx
102
- // server.ts
103
- import { renderToString } from 'frontend-hamroun';
104
-
105
- const html = await renderToString(<App />, {
106
- title: 'My SSR App',
107
- description: 'A server-rendered application',
108
- scripts: ['/client.js'],
109
- initialState: {
110
- user: { id: 1, name: 'John' }
111
- }
112
- });
93
+ const [error, resetError] = useErrorBoundary();
113
94
  ```
114
95
 
115
- ### Complete SSR Setup
116
-
117
- 1. Server Setup:
118
- ```typescript
119
- // server.ts
120
- import express from 'express';
121
- import { renderToString } from 'frontend-hamroun';
122
-
123
- const app = express();
124
-
125
- app.get('*', async (req, res) => {
126
- try {
127
- const html = await renderToString(<App />, {
128
- title: 'My App',
129
- description: 'Server-rendered app',
130
- scripts: ['/client.js'],
131
- styles: ['/styles.css'],
132
- meta: {
133
- 'og:title': 'My App',
134
- 'theme-color': '#ffffff'
135
- },
136
- initialState: {
137
- url: req.url,
138
- user: req.user
139
- },
140
- bodyAttrs: { class: 'app-root' },
141
- htmlAttrs: { lang: 'en' }
142
- });
143
-
144
- res.send(html);
145
- } catch (error) {
146
- res.status(500).send('Server Error');
147
- }
148
- });
149
- ```
96
+ ## Context API
150
97
 
151
- 2. Client Hydration:
152
- ```typescript
153
- // client.tsx
154
- import { hydrate } from 'frontend-hamroun';
155
-
156
- // Type-safe state access
157
- declare global {
158
- interface Window {
159
- __INITIAL_STATE__: {
160
- url: string;
161
- user?: { id: number; name: string };
162
- }
163
- }
164
- }
165
-
166
- const { url, user } = window.__INITIAL_STATE__;
98
+ Create and use shared state across components.
167
99
 
168
- hydrate(<App url={url} user={user} />, document.getElementById('root')!);
169
- ```
100
+ ```tsx
101
+ const ThemeContext = createContext('light');
170
102
 
171
- 3. Template Customization:
172
- ```typescript
173
- // Custom template options
174
- interface TemplateOptions {
175
- title: string;
176
- description?: string;
177
- scripts?: string[];
178
- styles?: string[];
179
- meta?: Record<string, string>;
180
- initialState?: any;
181
- bodyAttrs?: Record<string, string>;
182
- htmlAttrs?: Record<string, string>;
103
+ function App() {
104
+ return (
105
+ <ThemeContext.Provider value="dark">
106
+ <Child />
107
+ </ThemeContext.Provider>
108
+ );
183
109
  }
184
- ```
185
110
 
186
- ### SSR Features
187
-
188
- - Full HTML document generation
189
- - 🔄 Automatic state hydration
190
- - 🎨 Customizable templates
191
- - 📱 Meta tags for SEO
192
- - 🛡️ XSS protection
193
- - 🚀 Streaming support
194
- - 📦 Asset optimization
195
- - 🔍 Error handling
196
-
197
- ### Best Practices
198
-
199
- 1. State Management:
200
- ```typescript
201
- // Shared types between server and client
202
- interface AppState {
203
- url: string;
204
- user?: UserData;
205
- settings: AppSettings;
111
+ function Child() {
112
+ const theme = useContext(ThemeContext);
113
+ // Or use selector for performance
114
+ const isDark = ThemeContext.useSelector(theme => theme === 'dark');
206
115
  }
207
-
208
- // Server
209
- const state: AppState = {
210
- url: req.url,
211
- user: await getUser(req),
212
- settings: await getSettings()
213
- };
214
-
215
- // Client
216
- const { url, user, settings } = window.__INITIAL_STATE__ as AppState;
217
116
  ```
218
117
 
219
- 2. Error Handling:
220
- ```typescript
221
- // Server-side error boundary
222
- try {
223
- const html = await renderToString(<App />, options);
224
- res.send(html);
225
- } catch (error) {
226
- const errorHtml = await renderToString(
227
- <ErrorPage error={error} />,
228
- { title: 'Error' }
229
- );
230
- res.status(500).send(errorHtml);
231
- }
232
- ```
118
+ ## Performance Optimization
233
119
 
234
- 3. Performance Optimization:
235
- ```typescript
236
- // Caching
237
- const cached = await cache.get(cacheKey);
238
- if (cached) return cached;
239
-
240
- const html = await renderToString(<App />, {
241
- ...options,
242
- scripts: [
243
- { src: '/client.js', async: true, defer: true }
244
- ]
245
- });
120
+ ### Batch Updates
121
+ Group multiple state updates together.
246
122
 
247
- await cache.set(cacheKey, html, '1h');
248
- ```
123
+ ```tsx
124
+ import { batchUpdates } from 'your-package-name';
249
125
 
250
- ### Basic SSR Setup
251
-
252
- ```typescript
253
- // Server-side rendering with customization
254
- const html = await renderToString(<App />, {
255
- title: 'My App',
256
- description: 'Server-rendered application',
257
- scripts: ['/assets/client.js'],
258
- styles: ['/assets/styles.css'],
259
- meta: {
260
- 'theme-color': '#ffffff',
261
- 'og:title': 'My App',
262
- 'og:description': 'My awesome app'
263
- },
264
- initialState: {
265
- user: { name: 'John' }
266
- },
267
- bodyAttrs: { class: 'dark-mode' },
268
- htmlAttrs: { lang: 'en', dir: 'ltr' }
126
+ batchUpdates(() => {
127
+ setValue1(newValue1);
128
+ setValue2(newValue2);
269
129
  });
270
130
  ```
271
131
 
272
- ### Express Server Integration
273
-
274
- ```typescript
275
- import express from 'express';
276
- import { renderToString } from 'frontend-hamroun';
277
-
278
- const app = express();
279
-
280
- app.get('*', async (req, res) => {
281
- const initialState = {
282
- url: req.url,
283
- user: req.user // From your auth middleware
284
- };
285
-
286
- const html = await renderToString(<App />, {
287
- title: 'My App',
288
- scripts: ['/client.js'],
289
- initialState
290
- });
132
+ ### Component Memoization
133
+ Prevent unnecessary re-renders.
291
134
 
292
- res.send(html);
293
- });
135
+ ```tsx
136
+ const MemoizedComponent = useMemo(() => (
137
+ <ExpensiveComponent prop={value} />
138
+ ), [value]);
294
139
  ```
295
140
 
296
- ### Client-Side Hydration
297
-
298
- ```typescript
299
- import { hydrate } from 'frontend-hamroun';
300
-
301
- // Access the server-provided state
302
- declare global {
303
- interface Window {
304
- __INITIAL_STATE__: any;
305
- }
306
- }
141
+ ## Server-Side Rendering
307
142
 
308
- const initialState = window.__INITIAL_STATE__;
143
+ ```tsx
144
+ import { hydrate } from 'your-package-name';
309
145
 
310
- hydrate(
311
- <App initialState={initialState} />,
312
- document.getElementById('root')!
313
- );
146
+ // On the client
147
+ hydrate(<App />, document.getElementById('root'));
314
148
  ```
315
149
 
316
- ## CLI Tools
317
-
318
- Create a new project:
150
+ ## Event Handling
319
151
 
320
- ```bash
321
- npx create-frontend-app my-app
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
+ }
322
163
  ```
323
164
 
324
- ## Performance
325
-
326
- - Initial bundle: 12KB gzipped
327
- - Dynamic imports for code splitting
328
- - Automatic batching for state updates
329
- - Efficient virtual DOM diffing
330
-
331
- ## Security
332
-
333
- - XSS protection
334
- - Content Security Policy support
335
- - Type-safe props
336
- - Secure by default
165
+ ## Styling
337
166
 
338
- ## Browser Support
339
-
340
- - Chrome (latest)
341
- - Firefox (latest)
342
- - Safari (latest)
343
- - Edge (latest)
344
-
345
- ## Development Tools
346
-
347
- - TypeScript support
348
- - Hot Module Replacement
349
- - Developer tools extension
350
- - Error boundaries
351
- - Performance monitoring
352
-
353
- ## Advanced Features
354
-
355
- ### Template Customization
356
- ```typescript
357
- interface TemplateOptions {
358
- title: string;
359
- description?: string;
360
- scripts?: string[];
361
- styles?: string[];
362
- meta?: Record<string, string>;
363
- initialState?: any;
364
- bodyAttrs?: Record<string, string>;
365
- htmlAttrs?: Record<string, string>;
167
+ ```tsx
168
+ function StyledComponent() {
169
+ return (
170
+ <div style={{
171
+ color: 'blue',
172
+ padding: '20px'
173
+ }}>
174
+ Styled content
175
+ </div>
176
+ );
366
177
  }
367
-
368
- // Usage with custom template
369
- const html = await renderToString(<App />, {
370
- title: 'Custom Template',
371
- styles: ['/styles.css'],
372
- bodyAttrs: { 'data-theme': 'dark' }
373
- });
374
178
  ```
375
179
 
376
- ### Error Handling
377
- ```typescript
378
- // Error boundary component
379
- function ErrorBoundary({ children }) {
180
+ ## Error Handling
181
+
182
+ ```tsx
183
+ function ErrorBoundary() {
380
184
  const [error, resetError] = useErrorBoundary();
381
185
 
382
186
  if (error) {
383
187
  return (
384
- <div role="alert">
385
- <h2>Something went wrong</h2>
386
- <pre>{error.message}</pre>
188
+ <div>
189
+ <h1>Something went wrong!</h1>
387
190
  <button onClick={resetError}>Try again</button>
388
191
  </div>
389
192
  );
390
193
  }
391
194
 
392
- return children;
195
+ return <ComponentThatMightError />;
393
196
  }
394
197
  ```
395
198
 
396
- ## Contributing
397
-
398
- 1. Fork the repository
399
- 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
400
- 3. Commit your changes (`git commit -m 'Add amazing feature'`)
401
- 4. Push to the branch (`git push origin feature/amazing-feature`)
402
- 5. Open a Pull Request
199
+ ## Best Practices
403
200
 
404
- ## License
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
405
208
 
406
- MIT License - see the [LICENSE](LICENSE) file for details.
209
+ ## API Reference
407
210
 
408
- ## Support
211
+ ### Core
212
+ - `render(element, container)`
213
+ - `hydrate(element, container)`
214
+ - `createElement(vnode)`
409
215
 
410
- - Documentation: [Link to docs]
411
- - Issues: [GitHub Issues]
412
- - Discussions: [GitHub Discussions]
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)`
413
232
 
414
- ## Team
233
+ ## License
415
234
 
416
- - Hamroun - Lead Developer
235
+ MIT License - feel free to use in any project.
417
236
 
418
- ## Acknowledgments
237
+ ## Contributing
419
238
 
420
- Special thanks to the open-source community and all contributors.
239
+ Contributions are welcome! Please read our contributing guidelines and submit pull requests.
240
+ `````
package/dist/hooks.d.ts CHANGED
@@ -6,13 +6,3 @@ export declare function useEffect(callback: () => (() => void) | void, deps?: an
6
6
  export declare function useMemo<T>(factory: () => T, deps: any[]): T;
7
7
  export declare function useRef<T>(initial: T): any;
8
8
  export declare function useErrorBoundary(): [Error | null, () => void];
9
- export declare function useRouter(): {
10
- push: () => void;
11
- replace: () => void;
12
- back: () => void;
13
- forward: () => void;
14
- pathname: string;
15
- search: string;
16
- hash: string;
17
- params: Record<string, string>;
18
- } | undefined;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export { useState, useEffect, useMemo, useRef, useErrorBoundary } from './hooks';
2
- export { createElement } from './jsx-runtime';
3
2
  export { createContext, useContext } from './context';
4
3
  export { batchUpdates } from './batch';
5
4
  export { jsx, jsxs, Fragment } from './jsx-runtime';
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,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((()=>w(r))):w(r))}]}function y(e,t){if(!r)throw new Error("useEffect must be called within a render");if(d){const e=s.get(r);return void s.set(r,e+1)}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 w(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 $(e){var t;if(null==e||"boolean"==typeof e)return"";if(e&&"object"==typeof e&&"function"==typeof e.render)try{return $(await e.render())}catch(n){return console.error("Error rendering component instance:",n),""}if("number"==typeof e||"string"==typeof e)return S(String(e));if(Array.isArray(e)){return(await Promise.all(e.map((e=>$(e))))).join("")}if("function"==typeof e){e.name;try{return $(await e({}))}finally{}}if(e.type){if("function"==typeof e.type){e.type.name,e.props;try{return $(await e.type(e.props||{}))}finally{}}let n=`<${e.type}`;e.props&&(n+=function(e){let t="";for(const[n,r]of Object.entries(e))"children"!==n&&"key"!==n&&"ref"!==n&&("className"!==n?"style"!==n||"object"!=typeof r||null===r?n.startsWith("on")||("boolean"!=typeof r?null!=r&&(t+=` ${n}="${S(String(r))}"`):r&&(t+=` ${n}`)):t+=` style="${x(r)}"`:r&&(t+=` class="${S(String(r))}"`));return t}(e.props));if(new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]).has(e.type))return n+"/>";if(n+=">",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)n+=await $(e)}return n+`</${e.type}>`}return""}function S(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}function x(e){return Object.entries(e).map((([e,t])=>{return`${n=e,n.replace(/[A-Z]/g,(e=>"-"+e.toLowerCase()))}: ${t}`;var n})).join("; ")}let E={pathname:"undefined"!=typeof window?window.location.pathname:"/",search:"undefined"!=typeof window?window.location.search:"",hash:"undefined"!=typeof window?window.location.hash:"",params:{}};const j=new Set;function A(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()),E=r,j.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(),A(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.createElement=g,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={}){var n;try{let r;if("function"==typeof e){const t=await e({});r=await $(t)}else r=await $(e);const o=null==(n=t.scripts)?void 0:n.map((e=>"string"==typeof e?{src:e,defer:!0}:{...e,defer:e.defer??!0}));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(" "),d=Object.entries(a).map((([e,t])=>` <meta name="${e}" content="${t}">`)).join("\n"),f=o.map((e=>{if("string"==typeof e)return` <script src="${e}" defer><\/script>`;const{src:t,defer:n=!0,async:r=!1,type:o}=e;return` <script src="${t}"${n?" defer":""}${r?" async":""}${o?` type="${o}"`:""}><\/script>`})).join("\n");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`:""}${d}\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${f}\n </body>\n</html>`}(r,{title:"Frontend Hamroun App",...t,scripts:o})}catch(r){if(console.error("Server rendering error:",r),"development"===process.env.NODE_ENV){return`\n <!DOCTYPE html>\n <html>\n <head><title>Rendering Error</title></head>\n <body>\n <h1>Server Rendering Error</h1>\n <pre>${S(r instanceof Error?r.stack||r.message:String(r))}</pre>\n </body>\n </html>\n `}return""}},exports.useContext=function(e){return e},exports.useEffect=y,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(E);return y((()=>{const e=e=>{t(e)},n=()=>{E={pathname:window.location.pathname,search:window.location.search,hash:window.location.hash,params:{}},t(E)};return j.add(e),window.addEventListener("popstate",n),()=>{j.delete(e),window.removeEventListener("popstate",n)}}),[]),{...e,push:(e,t)=>A(e,t),replace:(e,t)=>A(e,{...t,replace:!0}),back:()=>window.history.back(),forward:()=>window.history.forward()}},exports.useState=h;
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;
2
2
  //# sourceMappingURL=index.js.map