frontend-hamroun 1.1.46 → 1.1.48

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,420 @@
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
6
-
7
- ```bash
8
- npm install your-package-name
9
- ```
5
+ ## Features
10
6
 
11
- ## Quick Start
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
12
15
 
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
47
-
48
- - Virtual DOM with efficient diffing
49
- - Hooks (useState, useEffect, useMemo, useRef)
50
- - Context API
51
- - Batch updates
52
- - Hydration support
53
-
54
- ## Hooks
42
+ ## Core Features
55
43
 
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]);
59
+
60
+ // Memoization
61
+ const memoizedValue = useMemo(() => computeExpensiveValue(deps), [deps]);
73
62
  ```
74
63
 
75
- ### useMemo
76
- Memoizes expensive computations.
64
+ ### Routing
77
65
 
78
66
  ```tsx
79
- const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
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
+ }
80
83
  ```
81
84
 
82
- ### useRef
83
- Creates a mutable reference.
85
+ ### Context API
84
86
 
85
87
  ```tsx
86
- const ref = useRef(initialValue);
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
+ }
87
96
  ```
88
97
 
89
- ### useErrorBoundary
90
- Handles component errors.
98
+ ## Server-Side Rendering
91
99
 
100
+ ### Quick Start
92
101
  ```tsx
93
- const [error, resetError] = useErrorBoundary();
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
+ });
94
113
  ```
95
114
 
96
- ## Context API
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
+ ```
97
150
 
98
- Create and use shared state across components.
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
+ }
99
165
 
100
- ```tsx
101
- const ThemeContext = createContext('light');
166
+ const { url, user } = window.__INITIAL_STATE__;
102
167
 
103
- function App() {
104
- return (
105
- <ThemeContext.Provider value="dark">
106
- <Child />
107
- </ThemeContext.Provider>
108
- );
168
+ hydrate(<App url={url} user={user} />, document.getElementById('root')!);
169
+ ```
170
+
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>;
109
183
  }
184
+ ```
110
185
 
111
- function Child() {
112
- const theme = useContext(ThemeContext);
113
- // Or use selector for performance
114
- const isDark = ThemeContext.useSelector(theme => theme === 'dark');
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;
115
206
  }
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;
116
217
  ```
117
218
 
118
- ## Performance Optimization
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
+ ```
119
233
 
120
- ### Batch Updates
121
- Group multiple state updates together.
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
+ });
122
246
 
123
- ```tsx
124
- import { batchUpdates } from 'your-package-name';
247
+ await cache.set(cacheKey, html, '1h');
248
+ ```
125
249
 
126
- batchUpdates(() => {
127
- setValue1(newValue1);
128
- setValue2(newValue2);
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' }
129
269
  });
130
270
  ```
131
271
 
132
- ### Component Memoization
133
- Prevent unnecessary re-renders.
272
+ ### Express Server Integration
134
273
 
135
- ```tsx
136
- const MemoizedComponent = useMemo(() => (
137
- <ExpensiveComponent prop={value} />
138
- ), [value]);
139
- ```
274
+ ```typescript
275
+ import express from 'express';
276
+ import { renderToString } from 'frontend-hamroun';
140
277
 
141
- ## Server-Side Rendering
278
+ const app = express();
142
279
 
143
- ```tsx
144
- import { hydrate } from 'your-package-name';
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
+ });
145
291
 
146
- // On the client
147
- hydrate(<App />, document.getElementById('root'));
292
+ res.send(html);
293
+ });
148
294
  ```
149
295
 
150
- ## Event Handling
296
+ ### Client-Side Hydration
151
297
 
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
- );
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
+ }
162
306
  }
307
+
308
+ const initialState = window.__INITIAL_STATE__;
309
+
310
+ hydrate(
311
+ <App initialState={initialState} />,
312
+ document.getElementById('root')!
313
+ );
163
314
  ```
164
315
 
165
- ## Styling
316
+ ## CLI Tools
166
317
 
167
- ```tsx
168
- function StyledComponent() {
169
- return (
170
- <div style={{
171
- color: 'blue',
172
- padding: '20px'
173
- }}>
174
- Styled content
175
- </div>
176
- );
177
- }
318
+ Create a new project:
319
+
320
+ ```bash
321
+ npx create-frontend-app my-app
178
322
  ```
179
323
 
180
- ## Error Handling
324
+ ## Performance
181
325
 
182
- ```tsx
183
- function ErrorBoundary() {
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
337
+
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>;
366
+ }
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
+ ```
375
+
376
+ ### Error Handling
377
+ ```typescript
378
+ // Error boundary component
379
+ function ErrorBoundary({ children }) {
184
380
  const [error, resetError] = useErrorBoundary();
185
381
 
186
382
  if (error) {
187
383
  return (
188
- <div>
189
- <h1>Something went wrong!</h1>
384
+ <div role="alert">
385
+ <h2>Something went wrong</h2>
386
+ <pre>{error.message}</pre>
190
387
  <button onClick={resetError}>Try again</button>
191
388
  </div>
192
389
  );
193
390
  }
194
391
 
195
- return <ComponentThatMightError />;
392
+ return children;
196
393
  }
197
394
  ```
198
395
 
199
- ## Best Practices
396
+ ## Contributing
200
397
 
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
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
208
403
 
209
- ## API Reference
404
+ ## License
210
405
 
211
- ### Core
212
- - `render(element, container)`
213
- - `hydrate(element, container)`
214
- - `createElement(vnode)`
406
+ MIT License - see the [LICENSE](LICENSE) file for details.
215
407
 
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)`
408
+ ## Support
232
409
 
233
- ## License
410
+ - Documentation: [Link to docs]
411
+ - Issues: [GitHub Issues]
412
+ - Discussions: [GitHub Discussions]
234
413
 
235
- MIT License - feel free to use in any project.
414
+ ## Team
236
415
 
237
- ## Contributing
416
+ - Hamroun - Lead Developer
417
+
418
+ ## Acknowledgments
238
419
 
239
- Contributions are welcome! Please read our contributing guidelines and submit pull requests.
240
- `````
420
+ 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