frontend-hamroun 1.2.79 → 1.2.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +129 -1513
  3. package/bin/cli.js +505 -144
  4. package/dist/index.cjs +2 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.client.cjs +2 -0
  7. package/dist/index.client.cjs.map +1 -0
  8. package/dist/index.client.js +26 -0
  9. package/dist/index.client.js.map +1 -0
  10. package/dist/index.js +298 -1
  11. package/dist/index.js.map +1 -0
  12. package/dist/jsx-runtime.cjs +2 -0
  13. package/dist/jsx-runtime.cjs.map +1 -0
  14. package/dist/jsx-runtime.js +93 -1
  15. package/dist/jsx-runtime.js.map +1 -0
  16. package/dist/renderer-Bo9zkUZ_.js +52 -0
  17. package/dist/renderer-Bo9zkUZ_.js.map +1 -0
  18. package/dist/renderer-Din1y3YM.cjs +2 -0
  19. package/dist/renderer-Din1y3YM.cjs.map +1 -0
  20. package/dist/server-renderer-CqIpQ-od.cjs +2 -0
  21. package/dist/server-renderer-CqIpQ-od.cjs.map +1 -0
  22. package/dist/server-renderer-QHt45Ip2.js +255 -0
  23. package/dist/server-renderer-QHt45Ip2.js.map +1 -0
  24. package/dist/server-renderer.cjs +2 -0
  25. package/dist/server-renderer.cjs.map +1 -0
  26. package/dist/server-renderer.js +5 -1
  27. package/dist/server-renderer.js.map +1 -0
  28. package/package.json +77 -120
  29. package/templates/basic-app/build.js +22 -0
  30. package/templates/basic-app/bun.lock +196 -0
  31. package/templates/basic-app/dev.js +27 -0
  32. package/templates/basic-app/docs/rapport_pfe.aux +27 -27
  33. package/templates/basic-app/docs/rapport_pfe.out +10 -10
  34. package/templates/basic-app/docs/rapport_pfe.toc +14 -14
  35. package/templates/basic-app/esbuild.config.js +28 -0
  36. package/templates/basic-app/index.html +1 -1
  37. package/templates/{fullstack-app → basic-app}/package-lock.json +4185 -5094
  38. package/templates/basic-app/package.json +29 -28
  39. package/templates/basic-app/server.js +24 -0
  40. package/templates/basic-app/src/App.tsx +26 -0
  41. package/templates/basic-app/src/client.tsx +11 -0
  42. package/templates/basic-app/src/components/Counter.tsx +18 -0
  43. package/templates/basic-app/src/jsx-shim.ts +4 -0
  44. package/templates/basic-app/src/main.tsx +0 -1
  45. package/templates/basic-app/src/server.ts +52 -0
  46. package/templates/basic-app/tsconfig.server.json +11 -0
  47. package/templates/fullstack-app/build/main.css +874 -874
  48. package/templates/fullstack-app/build/main.css.map +7 -7
  49. package/templates/fullstack-app/build/main.js +967 -967
  50. package/templates/fullstack-app/build/main.js.map +7 -7
  51. package/templates/fullstack-app/public/styles.css +768 -768
  52. package/templates/go/example.go +99 -154
  53. package/templates/go-wasm-app/babel.config.js +2 -8
  54. package/templates/go-wasm-app/package.json +12 -21
  55. package/templates/go-wasm-app/public/wasm/wasm_exec.js +561 -561
  56. package/templates/go-wasm-app/public/wasm/wasm_exec_node.js +39 -39
  57. package/templates/go-wasm-app/server.js +510 -59
  58. package/templates/go-wasm-app/src/app.js +2 -22
  59. package/templates/go-wasm-app/src/wasm/example.go +75 -75
  60. package/templates/go-wasm-app/vite.config.js +5 -16
  61. package/templates/ssr-template/server.js +2 -2
  62. package/templates/ssr-template/vite.config.js +5 -16
  63. package/dist/Counter.d.ts +0 -0
  64. package/dist/batch/package.json +0 -16
  65. package/dist/client-router/package.json +0 -16
  66. package/dist/component/package.json +0 -16
  67. package/dist/context/package.json +0 -16
  68. package/dist/event-bus/package.json +0 -16
  69. package/dist/forms/package.json +0 -16
  70. package/dist/hooks/package.json +0 -16
  71. package/dist/hooks-0728361a.cjs +0 -1
  72. package/dist/hooks-b58f947c.js +0 -133
  73. package/dist/hooks.js +0 -1
  74. package/dist/hooks.mjs +0 -13
  75. package/dist/index.mjs +0 -137
  76. package/dist/jsx-runtime/package.json +0 -16
  77. package/dist/jsx-runtime.mjs +0 -64
  78. package/dist/lifecycle-events/package.json +0 -16
  79. package/dist/package.json +0 -71
  80. package/dist/render-component/package.json +0 -16
  81. package/dist/renderer/package.json +0 -16
  82. package/dist/renderer.js +0 -1
  83. package/dist/renderer.mjs +0 -27
  84. package/dist/router/package.json +0 -16
  85. package/dist/server/package.json +0 -17
  86. package/dist/server/src/batch.d.ts +0 -3
  87. package/dist/server/src/batch.js +0 -23
  88. package/dist/server/src/batch.js.map +0 -1
  89. package/dist/server/src/client-router.d.ts +0 -60
  90. package/dist/server/src/client-router.js +0 -210
  91. package/dist/server/src/client-router.js.map +0 -1
  92. package/dist/server/src/component.d.ts +0 -14
  93. package/dist/server/src/component.js +0 -106
  94. package/dist/server/src/component.js.map +0 -1
  95. package/dist/server/src/context.d.ts +0 -13
  96. package/dist/server/src/context.js +0 -21
  97. package/dist/server/src/context.js.map +0 -1
  98. package/dist/server/src/event-bus.d.ts +0 -23
  99. package/dist/server/src/event-bus.js +0 -75
  100. package/dist/server/src/event-bus.js.map +0 -1
  101. package/dist/server/src/forms.d.ts +0 -40
  102. package/dist/server/src/forms.js +0 -148
  103. package/dist/server/src/forms.js.map +0 -1
  104. package/dist/server/src/hooks.d.ts +0 -12
  105. package/dist/server/src/hooks.js +0 -170
  106. package/dist/server/src/hooks.js.map +0 -1
  107. package/dist/server/src/index.client.d.ts +0 -12
  108. package/dist/server/src/index.client.js +0 -14
  109. package/dist/server/src/index.client.js.map +0 -1
  110. package/dist/server/src/index.d.ts +0 -88
  111. package/dist/server/src/index.js +0 -79
  112. package/dist/server/src/index.js.map +0 -1
  113. package/dist/server/src/jsx-runtime/jsx-dev-runtime.d.ts +0 -1
  114. package/dist/server/src/jsx-runtime/jsx-dev-runtime.js +0 -2
  115. package/dist/server/src/jsx-runtime/jsx-dev-runtime.js.map +0 -1
  116. package/dist/server/src/jsx-runtime/jsx-runtime.d.ts +0 -4
  117. package/dist/server/src/jsx-runtime/jsx-runtime.js +0 -41
  118. package/dist/server/src/jsx-runtime/jsx-runtime.js.map +0 -1
  119. package/dist/server/src/jsx-runtime.d.ts +0 -20
  120. package/dist/server/src/jsx-runtime.js +0 -105
  121. package/dist/server/src/jsx-runtime.js.map +0 -1
  122. package/dist/server/src/lifecycle-events.d.ts +0 -108
  123. package/dist/server/src/lifecycle-events.js +0 -177
  124. package/dist/server/src/lifecycle-events.js.map +0 -1
  125. package/dist/server/src/renderComponent.d.ts +0 -13
  126. package/dist/server/src/renderComponent.js +0 -30
  127. package/dist/server/src/renderComponent.js.map +0 -1
  128. package/dist/server/src/renderer.d.ts +0 -2
  129. package/dist/server/src/renderer.js +0 -31
  130. package/dist/server/src/renderer.js.map +0 -1
  131. package/dist/server/src/router.d.ts +0 -55
  132. package/dist/server/src/router.js +0 -166
  133. package/dist/server/src/router.js.map +0 -1
  134. package/dist/server/src/server/api-router.d.ts +0 -15
  135. package/dist/server/src/server/api-router.js +0 -111
  136. package/dist/server/src/server/api-router.js.map +0 -1
  137. package/dist/server/src/server/auth.d.ts +0 -32
  138. package/dist/server/src/server/auth.js +0 -80
  139. package/dist/server/src/server/auth.js.map +0 -1
  140. package/dist/server/src/server/database.d.ts +0 -24
  141. package/dist/server/src/server/database.js +0 -135
  142. package/dist/server/src/server/database.js.map +0 -1
  143. package/dist/server/src/server/index.d.ts +0 -116
  144. package/dist/server/src/server/index.js +0 -508
  145. package/dist/server/src/server/index.js.map +0 -1
  146. package/dist/server/src/server/middleware.d.ts +0 -11
  147. package/dist/server/src/server/middleware.js +0 -46
  148. package/dist/server/src/server/middleware.js.map +0 -1
  149. package/dist/server/src/server/server.d.ts +0 -9
  150. package/dist/server/src/server/server.js +0 -87
  151. package/dist/server/src/server/server.js.map +0 -1
  152. package/dist/server/src/server/templates.d.ts +0 -30
  153. package/dist/server/src/server/templates.js +0 -208
  154. package/dist/server/src/server/templates.js.map +0 -1
  155. package/dist/server/src/server/types.d.ts +0 -38
  156. package/dist/server/src/server/types.js +0 -4
  157. package/dist/server/src/server/types.js.map +0 -1
  158. package/dist/server/src/server/utils.d.ts +0 -70
  159. package/dist/server/src/server/utils.js +0 -156
  160. package/dist/server/src/server/utils.js.map +0 -1
  161. package/dist/server/src/server/wasm.d.ts +0 -9
  162. package/dist/server/src/server/wasm.js +0 -117
  163. package/dist/server/src/server/wasm.js.map +0 -1
  164. package/dist/server/src/server-renderer.d.ts +0 -5
  165. package/dist/server/src/server-renderer.js +0 -106
  166. package/dist/server/src/server-renderer.js.map +0 -1
  167. package/dist/server/src/server-types.d.ts +0 -42
  168. package/dist/server/src/server-types.js +0 -6
  169. package/dist/server/src/server-types.js.map +0 -1
  170. package/dist/server/src/store.d.ts +0 -41
  171. package/dist/server/src/store.js +0 -99
  172. package/dist/server/src/store.js.map +0 -1
  173. package/dist/server/src/types.d.ts +0 -19
  174. package/dist/server/src/types.js +0 -2
  175. package/dist/server/src/types.js.map +0 -1
  176. package/dist/server/src/utils.d.ts +0 -46
  177. package/dist/server/src/utils.js +0 -144
  178. package/dist/server/src/utils.js.map +0 -1
  179. package/dist/server/src/vdom.d.ts +0 -8
  180. package/dist/server/src/vdom.js +0 -22
  181. package/dist/server/src/vdom.js.map +0 -1
  182. package/dist/server/src/wasm.d.ts +0 -36
  183. package/dist/server/src/wasm.js +0 -159
  184. package/dist/server/src/wasm.js.map +0 -1
  185. package/dist/server/tsconfig.server.tsbuildinfo +0 -1
  186. package/dist/server-renderer/package.json +0 -16
  187. package/dist/server-renderer.mjs +0 -64
  188. package/dist/store/package.json +0 -16
  189. package/dist/types/package.json +0 -16
  190. package/dist/utils/package.json +0 -16
  191. package/dist/vdom/package.json +0 -16
  192. package/dist/wasm/package.json +0 -16
  193. package/dist/wasm.js +0 -1
  194. package/dist/wasm.mjs +0 -103
  195. package/templates/basic-app/docs/rapport_pfe.log +0 -399
  196. package/templates/complete-app/client.js +0 -58
  197. package/templates/complete-app/package-lock.json +0 -2536
  198. package/templates/complete-app/package.json +0 -17
  199. package/templates/complete-app/pages/about.js +0 -119
  200. package/templates/complete-app/pages/index.js +0 -157
  201. package/templates/complete-app/pages/wasm-demo.js +0 -290
  202. package/templates/complete-app/public/client.js +0 -80
  203. package/templates/complete-app/public/index.html +0 -47
  204. package/templates/complete-app/public/styles.css +0 -579
  205. package/templates/complete-app/readme.md +0 -188
  206. package/templates/complete-app/server.js +0 -417
  207. package/templates/complete-app/server.ts +0 -275
  208. package/templates/complete-app/src/App.tsx +0 -59
  209. package/templates/complete-app/src/client.ts +0 -61
  210. package/templates/complete-app/src/client.tsx +0 -18
  211. package/templates/complete-app/src/pages/index.tsx +0 -51
  212. package/templates/complete-app/src/server.ts +0 -218
  213. package/templates/complete-app/tsconfig.json +0 -22
  214. package/templates/complete-app/tsconfig.server.json +0 -19
  215. package/templates/complete-app/vite.config.js +0 -57
  216. package/templates/complete-app/vite.config.ts +0 -30
  217. package/templates/go-wasm-app/build.config.js +0 -62
  218. package/templates/go-wasm-app/build.js +0 -218
  219. package/templates/go-wasm-app/package-lock.json +0 -3732
@@ -1,17 +0,0 @@
1
- {
2
- "name": "ssr-app",
3
- "version": "0.1.0",
4
- "type": "module",
5
- "scripts": {
6
- "dev": "node server.js",
7
- "start": "node server.js",
8
- "build": "echo 'No build step required for this template'"
9
- },
10
- "dependencies": {
11
- "compression": "^1.8.0",
12
- "dotenv": "^16.0.3",
13
- "express": "^4.18.2",
14
- "frontend-hamroun": "latest",
15
- "node-fetch": "^3.3.1"
16
- }
17
- }
@@ -1,119 +0,0 @@
1
- import { jsx, useState, useEffect } from 'frontend-hamroun';
2
-
3
- // Simple animation component to demonstrate useEffect
4
- function FadeIn({ children, delay = 0 }) {
5
- const [opacity, setOpacity] = useState(0);
6
-
7
- useEffect(() => {
8
- const timer = setTimeout(() => {
9
- setOpacity(1);
10
- }, delay);
11
-
12
- return () => clearTimeout(timer);
13
- }, [delay]);
14
-
15
- return jsx('div', {
16
- style: `opacity: ${opacity}; transition: opacity 0.5s ease-in-out;`
17
- }, children);
18
- }
19
-
20
- // Main about page component
21
- export default function AboutPage(props) {
22
- const [activeSection, setActiveSection] = useState('overview');
23
-
24
- return jsx('div', { className: 'container' }, [
25
- jsx('header', { className: 'header' }, [
26
- jsx('h1', {}, 'About Frontend Hamroun'),
27
- jsx('a', { href: '/', className: 'back-link' }, '← Back to Home')
28
- ]),
29
-
30
- jsx('main', {}, [
31
- jsx('div', { className: 'about-nav' }, [
32
- jsx('button', {
33
- className: activeSection === 'overview' ? 'active' : '',
34
- onClick: () => setActiveSection('overview')
35
- }, 'Overview'),
36
- jsx('button', {
37
- className: activeSection === 'features' ? 'active' : '',
38
- onClick: () => setActiveSection('features')
39
- }, 'Features'),
40
- jsx('button', {
41
- className: activeSection === 'team' ? 'active' : '',
42
- onClick: () => setActiveSection('team')
43
- }, 'Team')
44
- ]),
45
-
46
- // Overview section
47
- activeSection === 'overview' && jsx(FadeIn, {}, [
48
- jsx('section', { className: 'about-section' }, [
49
- jsx('h2', {}, 'Framework Overview'),
50
- jsx('p', {}, 'Frontend Hamroun is a lightweight JavaScript framework for building modern web applications with server-side rendering and client-side hydration.'),
51
- jsx('p', {}, 'Inspired by React and other modern frameworks, it provides a simple yet powerful component model with hooks for state management and side effects.'),
52
- jsx('p', {}, `This page was rendered on the server at ${props.api?.serverTime} and then hydrated on the client to provide interactivity.`)
53
- ])
54
- ]),
55
-
56
- // Features section
57
- activeSection === 'features' && jsx(FadeIn, {}, [
58
- jsx('section', { className: 'about-section' }, [
59
- jsx('h2', {}, 'Key Features'),
60
- jsx('ul', { className: 'feature-list expanded' }, [
61
- jsx('li', {}, [
62
- jsx('strong', {}, 'Server-Side Rendering (SSR):'),
63
- jsx('p', {}, 'Render pages on the server for faster initial load and improved SEO.')
64
- ]),
65
- jsx('li', {}, [
66
- jsx('strong', {}, 'Client-Side Hydration:'),
67
- jsx('p', {}, 'Add interactivity to server-rendered HTML without rebuilding the DOM.')
68
- ]),
69
- jsx('li', {}, [
70
- jsx('strong', {}, 'React-like Hooks:'),
71
- jsx('p', {}, 'Use useState, useEffect, useMemo, and useRef for managing component state and lifecycle.')
72
- ]),
73
- jsx('li', {}, [
74
- jsx('strong', {}, 'Context API:'),
75
- jsx('p', {}, 'Share state between components without prop drilling using createContext and useContext.')
76
- ]),
77
- jsx('li', {}, [
78
- jsx('strong', {}, 'WebAssembly Integration:'),
79
- jsx('p', {}, 'Leverage high-performance Go code compiled to WebAssembly for computationally intensive tasks.')
80
- ]),
81
- jsx('li', {}, [
82
- jsx('strong', {}, 'Automatic Route Handling:'),
83
- jsx('p', {}, 'File-based routing system similar to Next.js for intuitive page organization.')
84
- ])
85
- ])
86
- ])
87
- ]),
88
-
89
- // Team section
90
- activeSection === 'team' && jsx(FadeIn, {}, [
91
- jsx('section', { className: 'about-section' }, [
92
- jsx('h2', {}, 'The Team'),
93
- jsx('div', { className: 'team-grid' }, [
94
- jsx('div', { className: 'team-member' }, [
95
- jsx('div', { className: 'avatar' }, 'MH'),
96
- jsx('h3', {}, 'Mohamed Hamroun'),
97
- jsx('p', { className: 'title' }, 'Lead Framework Developer'),
98
- jsx('p', { className: 'bio' }, 'Creator of Frontend Hamroun and full-stack JavaScript enthusiast.')
99
- ]),
100
- jsx('div', { className: 'team-member' }, [
101
- jsx('div', { className: 'avatar' }, 'AI'),
102
- jsx('h3', {}, 'AI Assistant'),
103
- jsx('p', { className: 'title' }, 'Documentation & Support'),
104
- jsx('p', { className: 'bio' }, 'Helps with documentation, examples, and framework support.')
105
- ])
106
- ])
107
- ])
108
- ])
109
- ]),
110
-
111
- jsx('footer', {}, [
112
- jsx('p', {}, '© 2025 Frontend Hamroun Framework')
113
- ])
114
- ]);
115
- }
116
-
117
- // Static metadata for SEO
118
- AboutPage.getTitle = () => 'About - Frontend Hamroun Framework';
119
- AboutPage.getDescription = () => 'Learn about the Frontend Hamroun framework, its features, and the team behind it.';
@@ -1,157 +0,0 @@
1
- import { jsx, useState, useEffect, useMemo, useRef, useContext, createContext } from 'frontend-hamroun';
2
-
3
- // Create a context for theme
4
- const ThemeContext = createContext({ theme: 'light', toggleTheme: () => {} });
5
-
6
- // Demo counter component using hooks
7
- function Counter({ initialCount = 0 }) {
8
- const [count, setCount] = useState(initialCount);
9
- const countRef = useRef(count);
10
- const { theme } = useContext(ThemeContext);
11
-
12
- // Update ref when count changes
13
- useEffect(() => {
14
- countRef.current = count;
15
- console.log('Count updated to:', count);
16
- }, [count]);
17
-
18
- // Use memoization for expensive calculation
19
- const isEven = useMemo(() => {
20
- console.log('Computing isEven...');
21
- return count % 2 === 0;
22
- }, [count]);
23
-
24
- const themeClass = theme === 'dark' ? 'dark-theme' : 'light-theme';
25
-
26
- return jsx('div', { className: `counter ${themeClass}` }, [
27
- jsx('h3', {}, 'Interactive Counter'),
28
- jsx('p', {}, [
29
- jsx('span', {}, `Current count: ${count} `),
30
- jsx('span', { className: 'badge' }, isEven ? 'even' : 'odd')
31
- ]),
32
- jsx('div', { className: 'button-group' }, [
33
- jsx('button', {
34
- onClick: () => setCount(c => c - 1),
35
- className: 'btn'
36
- }, 'Decrease'),
37
- jsx('button', {
38
- onClick: () => setCount(c => c + 1),
39
- className: 'btn primary'
40
- }, 'Increase'),
41
- jsx('button', {
42
- onClick: () => setCount(initialCount),
43
- className: 'btn secondary'
44
- }, 'Reset')
45
- ])
46
- ]);
47
- }
48
-
49
- // ServerInfo component to show server time
50
- function ServerInfo({ serverTime }) {
51
- const [clientTime, setClientTime] = useState(new Date().toISOString());
52
- const [timeVisible, setTimeVisible] = useState(true);
53
-
54
- // Update client time every second
55
- useEffect(() => {
56
- if (!timeVisible) return;
57
-
58
- const interval = setInterval(() => {
59
- setClientTime(new Date().toISOString());
60
- }, 1000);
61
-
62
- return () => clearInterval(interval);
63
- }, [timeVisible]);
64
-
65
- return jsx('div', { className: 'server-info card' }, [
66
- jsx('h3', {}, 'Server/Client Time'),
67
- jsx('button', {
68
- onClick: () => setTimeVisible(!timeVisible),
69
- className: 'btn small'
70
- }, timeVisible ? 'Hide Times' : 'Show Times'),
71
- timeVisible && jsx('div', { className: 'time-container' }, [
72
- jsx('p', {}, [
73
- jsx('strong', {}, 'Server Time: '),
74
- jsx('span', {}, serverTime)
75
- ]),
76
- jsx('p', {}, [
77
- jsx('strong', {}, 'Client Time: '),
78
- jsx('span', {}, clientTime)
79
- ]),
80
- jsx('p', { className: 'note' }, 'The client time updates every second to demonstrate client-side effects.')
81
- ])
82
- ]);
83
- }
84
-
85
- // Main page component
86
- export default function HomePage(props) {
87
- const [theme, setTheme] = useState('light');
88
- const toggleTheme = () => setTheme(theme === 'light' ? 'dark' : 'light');
89
-
90
- const themeValue = useMemo(() => ({ theme, toggleTheme }), [theme]);
91
-
92
- return jsx(ThemeContext.Provider, { value: themeValue }, [
93
- jsx('div', { className: `container ${theme}-theme` }, [
94
- jsx('header', { className: 'header' }, [
95
- jsx('div', { className: 'logo' }, [
96
- jsx('h1', {}, 'Frontend Hamroun'),
97
- jsx('span', { className: 'version' }, 'v1.2')
98
- ]),
99
- jsx('button', {
100
- onClick: toggleTheme,
101
- className: 'theme-toggle'
102
- }, theme === 'light' ? '🌙 Dark Mode' : '☀️ Light Mode')
103
- ]),
104
-
105
- jsx('main', {}, [
106
- jsx('section', { className: 'hero' }, [
107
- jsx('h2', {}, 'Welcome to the Complete Server-Side Rendered App'),
108
- jsx('p', {}, 'This demo showcases the power of Frontend Hamroun framework with server-side rendering and hydration.')
109
- ]),
110
-
111
- jsx('div', { className: 'grid' }, [
112
- jsx('div', { className: 'card' }, [
113
- jsx('h3', {}, 'Framework Features'),
114
- jsx('ul', { className: 'feature-list' }, [
115
- jsx('li', {}, 'Server-Side Rendering'),
116
- jsx('li', {}, 'Client-Side Hydration'),
117
- jsx('li', {}, 'React-like Hooks (useState, useEffect, useMemo, useRef)'),
118
- jsx('li', {}, 'Context API for State Management'),
119
- jsx('li', {}, 'WebAssembly Integration'),
120
- jsx('li', {}, 'SEO Optimization')
121
- ])
122
- ]),
123
-
124
- jsx('div', { className: 'card' }, [
125
- jsx(Counter, { initialCount: props.params.count ? parseInt(props.params.count) : 0 })
126
- ]),
127
-
128
- jsx('div', { className: 'card' }, [
129
- jsx(ServerInfo, { serverTime: props.api?.serverTime || 'Not available' })
130
- ]),
131
-
132
- jsx('div', { className: 'card' }, [
133
- jsx('h3', {}, 'Navigation'),
134
- jsx('nav', { className: 'nav-links' }, [
135
- jsx('a', { href: '/', className: 'active' }, 'Home'),
136
- jsx('a', { href: '/about', className: '' }, 'About'),
137
- jsx('a', { href: '/users', className: '' }, 'Users'),
138
- jsx('a', { href: '/wasm-demo', className: '' }, 'WebAssembly Demo')
139
- ])
140
- ])
141
- ])
142
- ]),
143
-
144
- jsx('footer', {}, [
145
- jsx('p', {}, [
146
- '© ',
147
- jsx('span', {}, new Date().getFullYear()),
148
- ' Frontend Hamroun Framework. Built with 💙 using SSR and hydration.'
149
- ])
150
- ])
151
- ])
152
- ]);
153
- }
154
-
155
- // Static metadata for SEO
156
- HomePage.getTitle = (props) => 'Frontend Hamroun - Modern JavaScript Framework';
157
- HomePage.getDescription = (props) => 'A server-side rendered demo of the Frontend Hamroun framework with React-like hooks and component architecture.';
@@ -1,290 +0,0 @@
1
- import { jsx, useState, useEffect } from 'frontend-hamroun';
2
- import { loadGoWasm } from 'frontend-hamroun/wasm';
3
-
4
- export default function WasmDemo(props) {
5
- // State for WASM loading
6
- const [wasm, setWasm] = useState(null);
7
- const [loading, setLoading] = useState(true);
8
- const [error, setError] = useState(null);
9
-
10
- // State for math demo
11
- const [num1, setNum1] = useState(5);
12
- const [num2, setNum2] = useState(3);
13
- const [operation, setOperation] = useState('add');
14
- const [result, setResult] = useState(null);
15
-
16
- // State for string operations
17
- const [inputText, setInputText] = useState('Hello WebAssembly!');
18
- const [processedText, setProcessedText] = useState('');
19
-
20
- // State for array processing
21
- const [arrayInput, setArrayInput] = useState('apple, banana, orange');
22
- const [arrayResult, setArrayResult] = useState('');
23
-
24
- // Load WASM module on client-side only
25
- useEffect(() => {
26
- async function loadWasmModule() {
27
- setLoading(true);
28
- try {
29
- const wasmModule = await loadGoWasm('/wasm/example.wasm', {
30
- debug: true
31
- });
32
- setWasm(wasmModule);
33
- setError(null);
34
- console.log('WASM module loaded:', wasmModule);
35
- } catch (err) {
36
- console.error('Failed to load WASM:', err);
37
- setError(`Error loading WASM: ${err.message}`);
38
- } finally {
39
- setLoading(false);
40
- }
41
- }
42
-
43
- loadWasmModule();
44
- }, []);
45
-
46
- // Update result when inputs or operation change
47
- useEffect(() => {
48
- if (!wasm || !wasm.functions) return;
49
-
50
- try {
51
- let calculatedResult;
52
- switch (operation) {
53
- case 'add':
54
- calculatedResult = wasm.functions.goAdd(num1.toString(), num2.toString());
55
- break;
56
- case 'subtract':
57
- calculatedResult = wasm.functions.goSubtract(num1.toString(), num2.toString());
58
- break;
59
- case 'multiply':
60
- calculatedResult = wasm.functions.goMultiply(num1.toString(), num2.toString());
61
- break;
62
- case 'divide':
63
- calculatedResult = wasm.functions.goDivide(num1.toString(), num2.toString());
64
- break;
65
- default:
66
- calculatedResult = 'Unknown operation';
67
- }
68
-
69
- setResult(calculatedResult);
70
- } catch (err) {
71
- setResult(`Error: ${err.message}`);
72
- }
73
- }, [wasm, num1, num2, operation]);
74
-
75
- // Handle text processing
76
- const handleProcessText = () => {
77
- if (!wasm || !wasm.functions) return;
78
-
79
- try {
80
- // Process the text with the WASM module's goReverseString function
81
- const reversed = wasm.functions.goReverseString(inputText);
82
- setProcessedText(reversed);
83
- } catch (err) {
84
- setProcessedText(`Error: ${err.message}`);
85
- }
86
- };
87
-
88
- // Handle array processing
89
- const handleProcessArray = () => {
90
- if (!wasm || !wasm.functions) return;
91
-
92
- try {
93
- // Process the array with the WASM module's goProcessArray function
94
- const processed = wasm.functions.goProcessArray(arrayInput);
95
- setArrayResult(processed);
96
- } catch (err) {
97
- setArrayResult(`Error: ${err.message}`);
98
- }
99
- };
100
-
101
- // Handle factorial calculation
102
- const [factorialInput, setFactorialInput] = useState(5);
103
- const [factorialResult, setFactorialResult] = useState(null);
104
-
105
- const calculateFactorial = () => {
106
- if (!wasm || !wasm.functions) return;
107
-
108
- try {
109
- const result = wasm.functions.goCalculateFactorial(factorialInput.toString());
110
- setFactorialResult(result);
111
- } catch (err) {
112
- setFactorialResult(`Error: ${err.message}`);
113
- }
114
- };
115
-
116
- if (loading) {
117
- return jsx('div', { className: 'container loading-container' }, [
118
- jsx('h1', {}, 'WebAssembly Demo'),
119
- jsx('div', { className: 'loading' }, [
120
- jsx('div', { className: 'spinner' }),
121
- jsx('p', {}, 'Loading WebAssembly module...')
122
- ])
123
- ]);
124
- }
125
-
126
- if (error) {
127
- return jsx('div', { className: 'container error-container' }, [
128
- jsx('h1', {}, 'WebAssembly Demo'),
129
- jsx('div', { className: 'error-box' }, [
130
- jsx('h3', {}, 'Error Loading WebAssembly'),
131
- jsx('p', {}, error),
132
- jsx('p', {}, 'Make sure your browser supports WebAssembly and that the WASM file is correctly built and accessible.')
133
- ]),
134
- jsx('a', { href: '/', className: 'button' }, 'Back to Home')
135
- ]);
136
- }
137
-
138
- return jsx('div', { className: 'container' }, [
139
- jsx('header', { className: 'header' }, [
140
- jsx('h1', {}, 'WebAssembly Integration Demo'),
141
- jsx('a', { href: '/', className: 'back-link' }, '← Back to Home')
142
- ]),
143
-
144
- jsx('main', { className: 'wasm-demo' }, [
145
- jsx('section', { className: 'intro-section' }, [
146
- jsx('h2', {}, 'Go + WebAssembly Integration'),
147
- jsx('p', {}, 'This page demonstrates how Frontend Hamroun integrates with WebAssembly modules compiled from Go. The following examples show different operations performed by Go code running in your browser.')
148
- ]),
149
-
150
- jsx('div', { className: 'demo-grid' }, [
151
- // Math Operations Demo
152
- jsx('section', { className: 'card' }, [
153
- jsx('h3', {}, 'Math Operations'),
154
-
155
- jsx('div', { className: 'form-grid' }, [
156
- jsx('div', { className: 'form-group' }, [
157
- jsx('label', { htmlFor: 'num1' }, 'First Number'),
158
- jsx('input', {
159
- id: 'num1',
160
- type: 'number',
161
- value: num1,
162
- onChange: (e) => setNum1(parseInt(e.target.value))
163
- })
164
- ]),
165
-
166
- jsx('div', { className: 'form-group' }, [
167
- jsx('label', { htmlFor: 'num2' }, 'Second Number'),
168
- jsx('input', {
169
- id: 'num2',
170
- type: 'number',
171
- value: num2,
172
- onChange: (e) => setNum2(parseInt(e.target.value))
173
- })
174
- ]),
175
-
176
- jsx('div', { className: 'form-group' }, [
177
- jsx('label', { htmlFor: 'operation' }, 'Operation'),
178
- jsx('select', {
179
- id: 'operation',
180
- value: operation,
181
- onChange: (e) => setOperation(e.target.value)
182
- }, [
183
- jsx('option', { value: 'add' }, 'Addition'),
184
- jsx('option', { value: 'subtract' }, 'Subtraction'),
185
- jsx('option', { value: 'multiply' }, 'Multiplication'),
186
- jsx('option', { value: 'divide' }, 'Division')
187
- ])
188
- ])
189
- ]),
190
-
191
- jsx('div', { className: 'result-box' }, [
192
- jsx('div', { className: 'result-label' }, 'Result:'),
193
- jsx('div', { className: 'result-value' }, result !== null ? result : 'Calculating...')
194
- ])
195
- ]),
196
-
197
- // String Operations Demo
198
- jsx('section', { className: 'card' }, [
199
- jsx('h3', {}, 'String Reversal'),
200
-
201
- jsx('div', { className: 'form-group' }, [
202
- jsx('label', { htmlFor: 'inputText' }, 'Input Text'),
203
- jsx('input', {
204
- id: 'inputText',
205
- type: 'text',
206
- value: inputText,
207
- onChange: (e) => setInputText(e.target.value)
208
- })
209
- ]),
210
-
211
- jsx('button', {
212
- onClick: handleProcessText,
213
- className: 'btn primary'
214
- }, 'Reverse Text'),
215
-
216
- jsx('div', { className: 'result-box' }, [
217
- jsx('div', { className: 'result-label' }, 'Reversed Text:'),
218
- jsx('div', { className: 'result-value' }, processedText || 'Click button to process')
219
- ])
220
- ]),
221
-
222
- // Factorial Calculation Demo
223
- jsx('section', { className: 'card' }, [
224
- jsx('h3', {}, 'Factorial Calculation'),
225
-
226
- jsx('div', { className: 'form-group' }, [
227
- jsx('label', { htmlFor: 'factorialInput' }, 'Number (0-20)'),
228
- jsx('input', {
229
- id: 'factorialInput',
230
- type: 'number',
231
- min: '0',
232
- max: '20',
233
- value: factorialInput,
234
- onChange: (e) => setFactorialInput(parseInt(e.target.value))
235
- })
236
- ]),
237
-
238
- jsx('button', {
239
- onClick: calculateFactorial,
240
- className: 'btn primary'
241
- }, 'Calculate Factorial'),
242
-
243
- jsx('div', { className: 'result-box' }, [
244
- jsx('div', { className: 'result-label' }, `Factorial of ${factorialInput}:`),
245
- jsx('div', { className: 'result-value' }, factorialResult || 'Click button to calculate')
246
- ])
247
- ]),
248
-
249
- // Array Processing Demo
250
- jsx('section', { className: 'card' }, [
251
- jsx('h3', {}, 'Array Processing'),
252
-
253
- jsx('div', { className: 'form-group' }, [
254
- jsx('label', { htmlFor: 'arrayInput' }, 'Comma-separated values'),
255
- jsx('input', {
256
- id: 'arrayInput',
257
- type: 'text',
258
- value: arrayInput,
259
- onChange: (e) => setArrayInput(e.target.value)
260
- })
261
- ]),
262
-
263
- jsx('button', {
264
- onClick: handleProcessArray,
265
- className: 'btn primary'
266
- }, 'Process Array'),
267
-
268
- jsx('div', { className: 'result-box' }, [
269
- jsx('div', { className: 'result-label' }, 'Processed Array (uppercase):'),
270
- jsx('div', { className: 'result-value array-result' }, arrayResult || 'Click button to process')
271
- ])
272
- ])
273
- ]),
274
-
275
- jsx('section', { className: 'info-section' }, [
276
- jsx('h3', {}, 'How It Works'),
277
- jsx('p', {}, 'The computations on this page are performed by Go code compiled to WebAssembly. The WebAssembly binary is loaded by Frontend Hamroun\'s WASM utility and executed in your browser.'),
278
- jsx('p', {}, 'This demonstrates how you can leverage the performance and type safety of Go while maintaining the interactivity of a JavaScript application.')
279
- ])
280
- ]),
281
-
282
- jsx('footer', {}, [
283
- jsx('p', {}, '© 2025 Frontend Hamroun Framework - WebAssembly Demo')
284
- ])
285
- ]);
286
- }
287
-
288
- // Static metadata for SEO
289
- WasmDemo.getTitle = () => 'WebAssembly Demo - Frontend Hamroun';
290
- WasmDemo.getDescription = () => 'Interactive demonstration of WebAssembly integration with Go in the Frontend Hamroun framework.';
@@ -1,80 +0,0 @@
1
- import { hydrate, jsx, useState, useEffect, useMemo, useRef, useContext, batchUpdates, createContext } from 'frontend-hamroun';
2
-
3
- // Immediately invoked function to handle hydration
4
- (async function() {
5
- try {
6
- // Get the app container
7
- const appRoot = document.getElementById('app');
8
- if (!appRoot) {
9
- console.error('App root element not found');
10
- return;
11
- }
12
-
13
- // Get initial data from the server
14
- let initialData = {};
15
- try {
16
- const dataElement = document.getElementById('__APP_DATA__');
17
- if (dataElement && dataElement.textContent) {
18
- initialData = JSON.parse(dataElement.textContent);
19
- console.log('Initial data loaded:', initialData);
20
- }
21
- } catch (err) {
22
- console.error('Error parsing initial data:', err);
23
- }
24
-
25
- // Path for component loading
26
- const path = initialData.path || window.location.pathname;
27
- const normalizedPath = path === '/' ? '/index' : path;
28
-
29
- try {
30
- // Import the component for the current path
31
- console.log(`Importing component for path: ${normalizedPath}`);
32
- // First attempt to load the page component
33
- const module = await import(`/pages${normalizedPath}.js`).catch(() =>
34
- import(`/pages${normalizedPath}/index.js`));
35
-
36
- if (!module || !module.default) {
37
- throw new Error(`No default export found for ${normalizedPath}`);
38
- }
39
-
40
- // Get the component
41
- const PageComponent = module.default;
42
-
43
- // Use batchUpdates for better performance during hydration
44
- batchUpdates(() => {
45
- console.log('Hydrating app with props:', initialData);
46
- // Hydrate the component
47
- hydrate(jsx(PageComponent, initialData), appRoot);
48
- console.log('Hydration complete for', normalizedPath);
49
- });
50
-
51
- } catch (err) {
52
- console.error(`Error loading or hydrating component: ${err.message}`);
53
-
54
- // Fallback to a simple component that shows the error
55
- const ErrorComponent = (props) => {
56
- const [showDetails, setShowDetails] = useState(false);
57
-
58
- return jsx('div', { className: 'error-container' }, [
59
- jsx('h1', {}, 'Error Loading Page'),
60
- jsx('p', {}, `Failed to load: ${normalizedPath}`),
61
- jsx('button', {
62
- onClick: () => setShowDetails(!showDetails),
63
- className: 'btn'
64
- }, showDetails ? 'Hide Details' : 'Show Details'),
65
- showDetails && jsx('pre', { className: 'error-details' },
66
- `${err.message}\n${err.stack || ''}`
67
- ),
68
- jsx('a', { href: '/', className: 'button' }, 'Go Home')
69
- ]);
70
- };
71
-
72
- hydrate(jsx(ErrorComponent, initialData), appRoot);
73
- }
74
- } catch (err) {
75
- console.error('Hydration failed:', err);
76
- }
77
- })();
78
-
79
- // Make jsx globally available
80
- window.jsx = jsx;