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,967 +1,967 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropNames = Object.getOwnPropertyNames;
3
- var __glob = (map) => (path) => {
4
- var fn = map[path];
5
- if (fn)
6
- return fn();
7
- throw new Error("Module not found in bundle: " + path);
8
- };
9
- var __esm = (fn, res) => function __init() {
10
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
- };
12
- var __export = (target, all) => {
13
- for (var name in all)
14
- __defProp(target, name, { get: all[name], enumerable: true });
15
- };
16
-
17
- // node_modules/frontend-hamroun/dist/index.mjs
18
- function batchUpdates(fn) {
19
- if (isBatching) {
20
- queue.push(fn);
21
- return;
22
- }
23
- isBatching = true;
24
- try {
25
- fn();
26
- while (queue.length > 0) {
27
- const nextFn = queue.shift();
28
- nextFn == null ? void 0 : nextFn();
29
- }
30
- } finally {
31
- isBatching = false;
32
- }
33
- }
34
- function setRenderCallback(callback, element, container) {
35
- globalRenderCallback = callback;
36
- globalContainer = container;
37
- currentElement = element;
38
- }
39
- function prepareRender() {
40
- currentRender++;
41
- stateIndices.set(currentRender, 0);
42
- return currentRender;
43
- }
44
- function finishRender() {
45
- if (isServer) {
46
- serverStates.delete(currentRender);
47
- }
48
- currentRender = 0;
49
- }
50
- function useState(initial) {
51
- if (!currentRender) {
52
- throw new Error("useState must be called within a render");
53
- }
54
- if (isServer) {
55
- if (!serverStates.has(currentRender)) {
56
- serverStates.set(currentRender, /* @__PURE__ */ new Map());
57
- }
58
- const componentState = serverStates.get(currentRender);
59
- const index2 = stateIndices.get(currentRender) || 0;
60
- if (!componentState.has(index2)) {
61
- componentState.set(index2, initial);
62
- }
63
- const state2 = componentState.get(index2);
64
- const setState2 = (newValue) => {
65
- };
66
- stateIndices.set(currentRender, index2 + 1);
67
- return [state2, setState2];
68
- }
69
- if (!states.has(currentRender)) {
70
- states.set(currentRender, []);
71
- }
72
- const componentStates = states.get(currentRender);
73
- const index = stateIndices.get(currentRender);
74
- if (index >= componentStates.length) {
75
- componentStates.push(initial);
76
- }
77
- const state = componentStates[index];
78
- const setState = (newValue) => {
79
- const nextValue = typeof newValue === "function" ? newValue(componentStates[index]) : newValue;
80
- if (componentStates[index] === nextValue)
81
- return;
82
- componentStates[index] = nextValue;
83
- if (isBatching) {
84
- batchUpdates(() => rerender(currentRender));
85
- } else {
86
- rerender(currentRender);
87
- }
88
- };
89
- stateIndices.set(currentRender, index + 1);
90
- return [state, setState];
91
- }
92
- function useEffect(callback, deps) {
93
- if (!currentRender)
94
- throw new Error("useEffect must be called within a render");
95
- const effectIndex = stateIndices.get(currentRender);
96
- if (!effects.has(currentRender)) {
97
- effects.set(currentRender, []);
98
- }
99
- const componentEffects = effects.get(currentRender);
100
- const prevEffect = componentEffects[effectIndex];
101
- if (!prevEffect || !deps || !prevEffect.deps || deps.some((dep, i) => dep !== prevEffect.deps[i])) {
102
- if (prevEffect == null ? void 0 : prevEffect.cleanup) {
103
- prevEffect.cleanup();
104
- }
105
- queueMicrotask(() => {
106
- const cleanup = callback() || void 0;
107
- componentEffects[effectIndex] = { cleanup, deps };
108
- });
109
- }
110
- stateIndices.set(currentRender, effectIndex + 1);
111
- }
112
- function useMemo(factory, deps) {
113
- if (!currentRender)
114
- throw new Error("useMemo must be called within a render");
115
- const memoIndex = stateIndices.get(currentRender);
116
- if (!memos.has(currentRender)) {
117
- memos.set(currentRender, []);
118
- }
119
- const componentMemos = memos.get(currentRender);
120
- const prevMemo = componentMemos[memoIndex];
121
- if (!prevMemo || deps && deps.some((dep, i) => !Object.is(dep, prevMemo.deps[i]))) {
122
- const value = factory();
123
- componentMemos[memoIndex] = { value, deps };
124
- stateIndices.set(currentRender, memoIndex + 1);
125
- return value;
126
- }
127
- stateIndices.set(currentRender, memoIndex + 1);
128
- return prevMemo.value;
129
- }
130
- async function rerender(rendererId) {
131
- try {
132
- const componentEffects = effects.get(rendererId);
133
- if (componentEffects) {
134
- componentEffects.forEach((effect) => {
135
- if (effect.cleanup)
136
- effect.cleanup();
137
- });
138
- effects.set(rendererId, []);
139
- }
140
- if (globalRenderCallback && globalContainer && currentElement) {
141
- await globalRenderCallback(currentElement, globalContainer);
142
- }
143
- } catch (error) {
144
- console.error("Error during rerender:", error);
145
- }
146
- }
147
- function useErrorBoundary() {
148
- const [error, setError] = useState(null);
149
- return [error, () => setError(null)];
150
- }
151
- function jsx(type, props) {
152
- console.log("JSX Transform:", { type, props });
153
- const processedProps = { ...props };
154
- if (arguments.length > 2) {
155
- processedProps.children = Array.prototype.slice.call(arguments, 2);
156
- }
157
- return { type, props: processedProps };
158
- }
159
- async function createElement(vnode) {
160
- var _a;
161
- console.log("Creating element from:", vnode);
162
- if (vnode == null) {
163
- return document.createTextNode("");
164
- }
165
- if (typeof vnode === "boolean") {
166
- return document.createTextNode("");
167
- }
168
- if (typeof vnode === "number" || typeof vnode === "string") {
169
- return document.createTextNode(String(vnode));
170
- }
171
- if (Array.isArray(vnode)) {
172
- const fragment = document.createDocumentFragment();
173
- for (const child of vnode) {
174
- const node = await createElement(child);
175
- fragment.appendChild(node);
176
- }
177
- return fragment;
178
- }
179
- if ("type" in vnode && vnode.props !== void 0) {
180
- const { type, props } = vnode;
181
- if (typeof type === "function") {
182
- try {
183
- const result = await type(props || {});
184
- const node = await createElement(result);
185
- if (node instanceof Element) {
186
- node.setAttribute("data-component-id", type.name || type.toString());
187
- }
188
- return node;
189
- } catch (error) {
190
- console.error("Error rendering component:", error);
191
- return document.createTextNode("");
192
- }
193
- }
194
- const element = document.createElement(type);
195
- for (const [key, value] of Object.entries(props || {})) {
196
- if (key === "children")
197
- continue;
198
- if (key.startsWith("on") && typeof value === "function") {
199
- const eventName = key.toLowerCase().slice(2);
200
- const existingHandler = (_a = element.__events) == null ? void 0 : _a[eventName];
201
- if (existingHandler) {
202
- element.removeEventListener(eventName, existingHandler);
203
- }
204
- element.addEventListener(eventName, value);
205
- if (!element.__events) {
206
- element.__events = {};
207
- }
208
- element.__events[eventName] = value;
209
- } else if (key === "style" && typeof value === "object") {
210
- Object.assign(element.style, value);
211
- } else if (key === "className") {
212
- element.setAttribute("class", String(value));
213
- } else if (key !== "key" && key !== "ref") {
214
- element.setAttribute(key, String(value));
215
- }
216
- }
217
- const children = props == null ? void 0 : props.children;
218
- if (children != null) {
219
- const childArray = Array.isArray(children) ? children.flat() : [children];
220
- for (const child of childArray) {
221
- const childNode = await createElement(child);
222
- element.appendChild(childNode);
223
- }
224
- }
225
- return element;
226
- }
227
- return document.createTextNode(String(vnode));
228
- }
229
- async function hydrate(element, container) {
230
- isHydrating = true;
231
- try {
232
- await render(element, container);
233
- } finally {
234
- isHydrating = false;
235
- }
236
- }
237
- async function render(element, container) {
238
- console.log("Rendering to:", container.id);
239
- batchUpdates(async () => {
240
- const rendererId = prepareRender();
241
- try {
242
- setRenderCallback(render, element, container);
243
- const domNode = await createElement(element);
244
- if (!isHydrating) {
245
- container.innerHTML = "";
246
- }
247
- container.appendChild(domNode);
248
- } finally {
249
- finishRender();
250
- }
251
- });
252
- }
253
- var isBatching, queue, currentRender, states, stateIndices, effects, memos, globalRenderCallback, globalContainer, currentElement, isServer, serverStates, isHydrating;
254
- var init_dist = __esm({
255
- "node_modules/frontend-hamroun/dist/index.mjs"() {
256
- isBatching = false;
257
- queue = [];
258
- currentRender = 0;
259
- states = /* @__PURE__ */ new Map();
260
- stateIndices = /* @__PURE__ */ new Map();
261
- effects = /* @__PURE__ */ new Map();
262
- memos = /* @__PURE__ */ new Map();
263
- globalRenderCallback = null;
264
- globalContainer = null;
265
- currentElement = null;
266
- isServer = typeof window === "undefined";
267
- serverStates = /* @__PURE__ */ new Map();
268
- isHydrating = false;
269
- }
270
- });
271
-
272
- // src/pages/404.tsx
273
- var __exports = {};
274
- __export(__exports, {
275
- default: () => NotFound
276
- });
277
- function NotFound({ initialState: initialState2 }) {
278
- return /* @__PURE__ */ jsx("div", { className: "not-found-container max-w-4xl mx-auto p-6" }, /* @__PURE__ */ jsx("div", { className: "bg-gray-50 border border-gray-200 rounded-lg p-8 shadow-sm" }, /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold text-gray-700 mb-4" }, "Page Not Found"), /* @__PURE__ */ jsx("p", { className: "text-lg text-gray-600 mb-4" }, "The page you are looking for does not exist or has been moved."), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-6" }, "Path: ", /* @__PURE__ */ jsx("code", { className: "bg-gray-100 px-2 py-1 rounded" }, initialState2?.route || "unknown")), /* @__PURE__ */ jsx("div", { className: "mt-6" }, /* @__PURE__ */ jsx(
279
- "a",
280
- {
281
- href: "/",
282
- className: "inline-block px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
283
- },
284
- "Back to Home"
285
- ))));
286
- }
287
- var init__ = __esm({
288
- "src/pages/404.tsx"() {
289
- "use strict";
290
- init_dist();
291
- }
292
- });
293
-
294
- // src/pages/[id].tsx
295
- var id_exports = {};
296
- var init_id = __esm({
297
- "src/pages/[id].tsx"() {
298
- "use strict";
299
- }
300
- });
301
-
302
- // src/components/Layout.tsx
303
- function Layout({ children, title = "Frontend Hamroun App" }) {
304
- return /* @__PURE__ */ jsx("div", { className: "min-h-screen flex flex-col bg-gray-50" }, /* @__PURE__ */ jsx("header", { className: "bg-blue-600 text-white" }, /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-4 flex justify-between items-center" }, /* @__PURE__ */ jsx("h1", { className: "text-xl font-bold" }, /* @__PURE__ */ jsx("a", { href: "/", className: "hover:text-blue-100" }, title)), /* @__PURE__ */ jsx("nav", null, /* @__PURE__ */ jsx("ul", { className: "flex space-x-6" }, /* @__PURE__ */ jsx("li", null, /* @__PURE__ */ jsx("a", { href: "/", className: "hover:text-blue-100" }, "Home")), /* @__PURE__ */ jsx("li", null, /* @__PURE__ */ jsx("a", { href: "/about", className: "hover:text-blue-100" }, "About")))))), /* @__PURE__ */ jsx("main", { className: "flex-grow container mx-auto px-4 py-8" }, children), /* @__PURE__ */ jsx("footer", { className: "bg-gray-800 text-white" }, /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-6" }, /* @__PURE__ */ jsx("p", { className: "text-center text-gray-400" }, "\xA9 ", (/* @__PURE__ */ new Date()).getFullYear(), " Frontend Hamroun App. All rights reserved."))));
305
- }
306
- var init_Layout = __esm({
307
- "src/components/Layout.tsx"() {
308
- "use strict";
309
- init_dist();
310
- }
311
- });
312
-
313
- // src/pages/_app.tsx
314
- var app_exports = {};
315
- __export(app_exports, {
316
- default: () => App
317
- });
318
- function App({ Component, pageProps, initialState: initialState2 }) {
319
- return /* @__PURE__ */ jsx(Layout, null, /* @__PURE__ */ jsx(Component, { ...pageProps, initialState: initialState2 }));
320
- }
321
- var init_app = __esm({
322
- "src/pages/_app.tsx"() {
323
- "use strict";
324
- init_dist();
325
- init_Layout();
326
- }
327
- });
328
-
329
- // src/pages/_document.tsx
330
- var document_exports = {};
331
- __export(document_exports, {
332
- default: () => Document
333
- });
334
- function Document({
335
- title = "Frontend Hamroun App",
336
- headContent,
337
- bodyContent,
338
- scripts
339
- }) {
340
- return /* @__PURE__ */ jsx("html", { lang: "en" }, /* @__PURE__ */ jsx("head", null, /* @__PURE__ */ jsx("meta", { charSet: "UTF-8" }), /* @__PURE__ */ jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }), /* @__PURE__ */ jsx("title", null, title), /* @__PURE__ */ jsx("link", { rel: "stylesheet", href: "/styles.css" }), headContent), /* @__PURE__ */ jsx("body", null, /* @__PURE__ */ jsx("div", { id: "root" }, bodyContent), /* @__PURE__ */ jsx("script", { src: "/build/main.js", type: "module" }), scripts));
341
- }
342
- var init_document = __esm({
343
- "src/pages/_document.tsx"() {
344
- "use strict";
345
- init_dist();
346
- }
347
- });
348
-
349
- // src/pages/_error.tsx
350
- var error_exports = {};
351
- __export(error_exports, {
352
- default: () => ErrorPage
353
- });
354
- function ErrorPage({ initialState: initialState2 }) {
355
- const { error } = initialState2 || {};
356
- const [showDetails, setShowDetails] = useState(false);
357
- const isDev = true;
358
- return /* @__PURE__ */ jsx("div", { className: "error-page-container max-w-4xl mx-auto p-6" }, /* @__PURE__ */ jsx("div", { className: "bg-red-50 border border-red-200 rounded-lg p-8 shadow-sm" }, /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold text-red-700 mb-4" }, "Something went wrong"), /* @__PURE__ */ jsx("p", { className: "text-lg text-red-600 mb-4" }, error?.message || "An unexpected error occurred"), isDev && error?.stack && /* @__PURE__ */ jsx("div", { className: "mt-6" }, /* @__PURE__ */ jsx(
359
- "button",
360
- {
361
- className: "text-blue-600 underline mb-2",
362
- onClick: () => setShowDetails(!showDetails)
363
- },
364
- showDetails ? "Hide" : "Show",
365
- " technical details"
366
- ), showDetails && /* @__PURE__ */ jsx("pre", { className: "bg-gray-100 p-4 rounded-md text-sm overflow-auto max-h-96 text-gray-800" }, error.stack)), /* @__PURE__ */ jsx("div", { className: "mt-6" }, /* @__PURE__ */ jsx(
367
- "a",
368
- {
369
- href: "/",
370
- className: "inline-block px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
371
- },
372
- "Back to Home"
373
- ))));
374
- }
375
- var init_error = __esm({
376
- "src/pages/_error.tsx"() {
377
- "use strict";
378
- init_dist();
379
- }
380
- });
381
-
382
- // src/pages/about.tsx
383
- var about_exports = {};
384
- __export(about_exports, {
385
- default: () => AboutPage,
386
- getServerSideProps: () => getServerSideProps
387
- });
388
- function AboutPage({ initialState: initialState2 }) {
389
- return /* @__PURE__ */ jsx(Layout, { title: "About - Frontend Hamroun" }, /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto" }, /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold text-blue-600 mb-6" }, "About Frontend Hamroun"), /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-8 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "What is Frontend Hamroun?"), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-4" }, "Frontend Hamroun is a lightweight JavaScript framework for building modern web applications. It provides a familiar component-based architecture with hooks, JSX support, and server-side rendering capabilities."), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-4" }, "This framework is designed to be simple yet powerful, offering the essential features needed for web application development without the complexity of larger frameworks."), /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium text-gray-700 mt-6 mb-2" }, "Key Features:"), /* @__PURE__ */ jsx("ul", { className: "list-disc pl-6 text-gray-600 space-y-2" }, /* @__PURE__ */ jsx("li", null, "Component-based architecture"), /* @__PURE__ */ jsx("li", null, "JSX support"), /* @__PURE__ */ jsx("li", null, "Hooks for state and effects"), /* @__PURE__ */ jsx("li", null, "Server-side rendering"), /* @__PURE__ */ jsx("li", null, "Minimal API surface"), /* @__PURE__ */ jsx("li", null, "File-based routing"), /* @__PURE__ */ jsx("li", null, "Built-in API routes"))), /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "Getting Started"), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-4" }, "This application was created using the Frontend Hamroun fullstack template, which provides a complete setup for building applications with server-side rendering, API routes, and client-side navigation."), /* @__PURE__ */ jsx("div", { className: "bg-gray-50 p-4 rounded-md mt-4" }, /* @__PURE__ */ jsx("h3", { className: "text-md font-medium text-gray-700 mb-2" }, "Quick Start:"), /* @__PURE__ */ jsx("pre", { className: "bg-gray-800 text-gray-100 p-4 rounded overflow-x-auto" }, /* @__PURE__ */ jsx("code", null, `# Create a new application
390
- npx frontend-hamroun create my-app
391
-
392
- # Change directory
393
- cd my-app
394
-
395
- # Start the development server
396
- npm run dev`))))));
397
- }
398
- async function getServerSideProps() {
399
- return {
400
- props: {
401
- pageTitle: "About Frontend Hamroun",
402
- description: "Learn more about the Frontend Hamroun framework"
403
- }
404
- };
405
- }
406
- var init_about = __esm({
407
- "src/pages/about.tsx"() {
408
- "use strict";
409
- init_dist();
410
- init_Layout();
411
- }
412
- });
413
-
414
- // src/pages/about/index.tsx
415
- var about_exports2 = {};
416
- __export(about_exports2, {
417
- default: () => about_default
418
- });
419
- var AboutPage2, about_default;
420
- var init_about2 = __esm({
421
- "src/pages/about/index.tsx"() {
422
- "use strict";
423
- init_dist();
424
- init_Layout();
425
- AboutPage2 = ({ initialState: initialState2 }) => {
426
- return /* @__PURE__ */ jsx(Layout, { title: "About This App" }, /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto bg-white shadow-lg rounded-lg overflow-hidden" }, /* @__PURE__ */ jsx("div", { className: "p-8" }, /* @__PURE__ */ jsx("p", { className: "text-lg text-gray-700 mb-6" }, "This is a frontend application built with Frontend Hamroun framework and styled with Tailwind CSS."), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-8" }, "It features server-side rendering, client-side navigation, and websocket-based live reloading during development."), /* @__PURE__ */ jsx("div", { className: "bg-gray-50 p-6 rounded-lg border border-gray-200 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "Key Features"), /* @__PURE__ */ jsx("ul", { className: "space-y-2 text-gray-700" }, /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Server-side rendering"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Client-side navigation"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Component-based architecture"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Integrated API backend"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Live reload during development"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Tailwind CSS for styling"))), /* @__PURE__ */ jsx("a", { href: "/", className: "inline-block px-6 py-3 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 transition-colors" }, "Back to Home"))));
427
- };
428
- about_default = AboutPage2;
429
- }
430
- });
431
-
432
- // src/components/UserList.tsx
433
- function UserList({ users }) {
434
- if (!users || users.length === 0) {
435
- return /* @__PURE__ */ jsx("div", { className: "empty-state p-4 text-center bg-gray-50 rounded" }, /* @__PURE__ */ jsx("p", { className: "text-gray-500" }, "No users available"));
436
- }
437
- return /* @__PURE__ */ jsx("div", { className: "user-list" }, /* @__PURE__ */ jsx("ul", { className: "divide-y divide-gray-100" }, users.map((user) => /* @__PURE__ */ jsx("li", { key: user.id, className: "py-3" }, /* @__PURE__ */ jsx("div", { className: "flex justify-between" }, /* @__PURE__ */ jsx("div", null, /* @__PURE__ */ jsx("p", { className: "font-medium text-gray-900" }, user.name), /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500" }, user.email)), /* @__PURE__ */ jsx(
438
- "a",
439
- {
440
- href: `/users/${user.id}`,
441
- className: "text-blue-600 hover:underline text-sm self-center"
442
- },
443
- "View Profile"
444
- ))))));
445
- }
446
- var init_UserList = __esm({
447
- "src/components/UserList.tsx"() {
448
- "use strict";
449
- init_dist();
450
- }
451
- });
452
-
453
- // src/components/StateDemo.tsx
454
- function StateDemo() {
455
- const [state, setState] = useState({
456
- count: 0,
457
- lastUpdated: null,
458
- history: []
459
- });
460
- const [isLoading, setIsLoading] = useState(false);
461
- const [showHistory, setShowHistory] = useState(false);
462
- const isSSR = typeof window === "undefined";
463
- const stats = useMemo(() => {
464
- if (isSSR || !state || !state.history || state.history.length === 0) {
465
- return { avg: 0, max: 0, min: 0 };
466
- }
467
- try {
468
- const sum = state.history.reduce((a, b) => a + b, 0);
469
- return {
470
- avg: parseFloat((sum / state.history.length).toFixed(1)),
471
- max: Math.max(...state.history),
472
- min: Math.min(...state.history)
473
- };
474
- } catch (error) {
475
- console.error("Error calculating stats:", error);
476
- return { avg: 0, max: 0, min: 0 };
477
- }
478
- }, [state?.history]);
479
- const increment = () => {
480
- if (isSSR)
481
- return;
482
- setIsLoading(true);
483
- setTimeout(() => {
484
- setState((prevState) => ({
485
- count: prevState.count + 1,
486
- lastUpdated: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
487
- history: [...prevState.history || [], prevState.count + 1]
488
- }));
489
- setIsLoading(false);
490
- }, 300);
491
- };
492
- const decrement = () => {
493
- if (isSSR)
494
- return;
495
- setIsLoading(true);
496
- setTimeout(() => {
497
- setState((prevState) => ({
498
- count: Math.max(0, prevState.count - 1),
499
- lastUpdated: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
500
- history: prevState.count > 0 ? [...prevState.history || [], prevState.count - 1] : prevState.history || []
501
- }));
502
- setIsLoading(false);
503
- }, 300);
504
- };
505
- const reset = () => {
506
- if (isSSR)
507
- return;
508
- setState({
509
- count: 0,
510
- lastUpdated: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
511
- history: []
512
- });
513
- };
514
- const toggleHistory = () => {
515
- if (isSSR)
516
- return;
517
- setShowHistory((prev) => !prev);
518
- };
519
- if (isSSR) {
520
- return /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "State Management Demo"), /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ jsx("button", { className: "px-4 py-2 bg-gray-200 text-gray-800 rounded-lg" }, "-"), /* @__PURE__ */ jsx("span", { className: "text-2xl font-bold mx-4" }, "0"), /* @__PURE__ */ jsx("button", { className: "px-4 py-2 bg-blue-600 text-white rounded-lg" }, "+")), /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500" }, "Interactive counter (client-side only)"));
521
- }
522
- return /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "State Management Demo"), /* @__PURE__ */ jsx("div", { className: "mb-6" }, /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ jsx(
523
- "button",
524
- {
525
- onClick: decrement,
526
- className: "px-4 py-2 bg-gray-200 text-gray-800 rounded-lg hover:bg-gray-300 disabled:opacity-50",
527
- disabled: state.count === 0 || isLoading
528
- },
529
- isLoading ? "..." : "-"
530
- ), /* @__PURE__ */ jsx("span", { className: "text-2xl font-bold mx-4" }, state.count), /* @__PURE__ */ jsx(
531
- "button",
532
- {
533
- onClick: increment,
534
- className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50",
535
- disabled: isLoading
536
- },
537
- isLoading ? "..." : "+"
538
- )), /* @__PURE__ */ jsx(
539
- "button",
540
- {
541
- onClick: reset,
542
- className: "text-sm text-gray-600 hover:text-red-600",
543
- disabled: state.count === 0 && (!state.history || state.history.length === 0)
544
- },
545
- "Reset Counter"
546
- )), state.lastUpdated && /* @__PURE__ */ jsx("div", { className: "mb-4" }, /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500" }, "Last updated: ", state.lastUpdated)), state.history && state.history.length > 0 && /* @__PURE__ */ jsx("div", { className: "border-t pt-4 mt-4" }, /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ jsx("h3", { className: "text-md font-medium text-gray-700" }, "Statistics"), /* @__PURE__ */ jsx(
547
- "button",
548
- {
549
- onClick: toggleHistory,
550
- className: "text-sm text-blue-600 hover:underline"
551
- },
552
- showHistory ? "Hide History" : "Show History"
553
- )), /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-2 mb-3" }, /* @__PURE__ */ jsx("div", { className: "bg-blue-50 p-2 rounded text-center" }, /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500" }, "Average"), /* @__PURE__ */ jsx("div", { className: "font-bold" }, stats.avg)), /* @__PURE__ */ jsx("div", { className: "bg-green-50 p-2 rounded text-center" }, /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500" }, "Maximum"), /* @__PURE__ */ jsx("div", { className: "font-bold" }, stats.max)), /* @__PURE__ */ jsx("div", { className: "bg-red-50 p-2 rounded text-center" }, /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500" }, "Minimum"), /* @__PURE__ */ jsx("div", { className: "font-bold" }, stats.min))), showHistory && /* @__PURE__ */ jsx("div", { className: "mt-3" }, /* @__PURE__ */ jsx("h4", { className: "text-sm font-medium text-gray-600 mb-1" }, "History (", state.history.length, " events)"), /* @__PURE__ */ jsx("div", { className: "bg-gray-50 p-2 rounded max-h-24 overflow-y-auto text-xs" }, state.history.map((value, index) => /* @__PURE__ */ jsx(
554
- "span",
555
- {
556
- key: index,
557
- className: "inline-block bg-gray-200 rounded px-2 py-1 m-1"
558
- },
559
- value
560
- ))))));
561
- }
562
- var init_StateDemo = __esm({
563
- "src/components/StateDemo.tsx"() {
564
- "use strict";
565
- init_dist();
566
- }
567
- });
568
-
569
- // src/components/ErrorBoundary.tsx
570
- function ErrorBoundary({ children, fallback }) {
571
- const [error, resetError] = useErrorBoundary();
572
- if (error) {
573
- if (fallback) {
574
- return fallback(error, resetError);
575
- }
576
- return /* @__PURE__ */ jsx("div", { className: "error-boundary p-4 border border-red-500 rounded bg-red-50" }, /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium text-red-800 mb-2" }, "Something went wrong"), /* @__PURE__ */ jsx("p", { className: "text-red-600 mb-2" }, error.message), /* @__PURE__ */ jsx(
577
- "button",
578
- {
579
- onClick: resetError,
580
- className: "px-3 py-1 bg-red-600 text-white rounded hover:bg-red-700"
581
- },
582
- "Try again"
583
- ), /* @__PURE__ */ jsx("pre", { className: "mt-3 text-xs overflow-auto p-2 bg-gray-100" }, error.stack));
584
- }
585
- return children;
586
- }
587
- var init_ErrorBoundary = __esm({
588
- "src/components/ErrorBoundary.tsx"() {
589
- "use strict";
590
- init_dist();
591
- }
592
- });
593
-
594
- // src/data/api.ts
595
- var sampleUsers, samplePosts, delay, UserApi;
596
- var init_api = __esm({
597
- "src/data/api.ts"() {
598
- "use strict";
599
- init_dist();
600
- sampleUsers = [
601
- { id: 1, name: "User 1", email: "user1@example.com" },
602
- { id: 2, name: "User 2", email: "user2@example.com" },
603
- { id: 3, name: "User 3", email: "user3@example.com" }
604
- ];
605
- samplePosts = [
606
- { id: 1, title: "Post 1", content: "Content for post 1", authorId: 1 },
607
- { id: 2, title: "Post 2", content: "Content for post 2", authorId: 2 },
608
- { id: 3, title: "Post 3", content: "Content for post 3", authorId: 1 }
609
- ];
610
- delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
611
- UserApi = {
612
- // Get all users
613
- async getAll() {
614
- try {
615
- await delay(300);
616
- return [...sampleUsers];
617
- } catch (error) {
618
- console.error("Error fetching users:", error);
619
- return [];
620
- }
621
- },
622
- // Get user by ID
623
- async getById(id) {
624
- try {
625
- const userId = typeof id === "string" ? parseInt(id, 10) : id;
626
- await delay(200);
627
- const user = sampleUsers.find((u) => u.id === userId);
628
- if (!user)
629
- throw new Error("User not found");
630
- return { ...user };
631
- } catch (error) {
632
- console.error(`Error fetching user ${id}:`, error);
633
- return null;
634
- }
635
- },
636
- // Get posts (all or by author)
637
- async getPosts(authorId) {
638
- try {
639
- const userId = authorId ? typeof authorId === "string" ? parseInt(authorId, 10) : authorId : void 0;
640
- await delay(400);
641
- const posts = userId ? samplePosts.filter((p) => p.authorId === userId) : samplePosts;
642
- return [...posts];
643
- } catch (error) {
644
- console.error("Error fetching posts:", error);
645
- return [];
646
- }
647
- }
648
- };
649
- }
650
- });
651
-
652
- // src/pages/index.tsx
653
- var pages_exports = {};
654
- __export(pages_exports, {
655
- default: () => HomePage,
656
- getServerSideProps: () => getServerSideProps2
657
- });
658
- function HomePage({ users, posts, initialState: initialState2 }) {
659
- const [state, setState] = useState(initialState2 || {});
660
- const [refreshTrigger, setRefreshTrigger] = useState(0);
661
- useEffect(() => {
662
- if (refreshTrigger === 0)
663
- return;
664
- async function fetchData() {
665
- try {
666
- const [users2, posts2] = await Promise.all([
667
- UserApi.getAll(),
668
- UserApi.getPosts()
669
- ]);
670
- batchUpdates(() => {
671
- setState((prev) => ({
672
- ...prev,
673
- data: {
674
- ...prev.data,
675
- users: users2,
676
- posts: posts2
677
- },
678
- lastUpdate: (/* @__PURE__ */ new Date()).toISOString()
679
- }));
680
- });
681
- } catch (error) {
682
- console.error("Error fetching data:", error);
683
- }
684
- }
685
- fetchData();
686
- }, [refreshTrigger]);
687
- const handleRefresh = () => {
688
- setRefreshTrigger((t) => t + 1);
689
- };
690
- return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto py-8" }, /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold text-blue-600 mb-6" }, "Welcome to your Next-style Frontend Hamroun application!"), /* @__PURE__ */ jsx("div", { className: "mb-8" }, /* @__PURE__ */ jsx(
691
- "button",
692
- {
693
- className: "mb-4 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700",
694
- onClick: handleRefresh
695
- },
696
- "Refresh Data"
697
- ), /* @__PURE__ */ jsx("div", { className: "bg-blue-50 p-4 rounded-lg border border-blue-100 mb-6" }, /* @__PURE__ */ jsx("p", { className: "text-blue-700" }, "Last updated: ", state.lastUpdate || "Never"))), /* @__PURE__ */ jsx(ErrorBoundary, null, /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "User List"), /* @__PURE__ */ jsx(UserList, { users: users || state.data?.users || [] }))), /* @__PURE__ */ jsx(ErrorBoundary, null, /* @__PURE__ */ jsx(StateDemo, null)), /* @__PURE__ */ jsx("div", { className: "bg-gray-50 rounded-lg p-6 border border-gray-200 mt-8" }, /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium text-gray-700 mb-3" }, "Application State"), /* @__PURE__ */ jsx("pre", { className: "overflow-auto p-4 bg-gray-100 rounded-md text-sm text-gray-800" }, JSON.stringify({ users, posts, ...state }, null, 2))));
698
- }
699
- async function getServerSideProps2() {
700
- try {
701
- const users = await UserApi.getAll();
702
- const posts = await UserApi.getPosts();
703
- return {
704
- props: {
705
- users,
706
- posts
707
- }
708
- };
709
- } catch (error) {
710
- console.error("Error fetching initial data:", error);
711
- return {
712
- props: {
713
- users: [],
714
- posts: []
715
- }
716
- };
717
- }
718
- }
719
- var init_pages = __esm({
720
- "src/pages/index.tsx"() {
721
- "use strict";
722
- init_dist();
723
- init_UserList();
724
- init_StateDemo();
725
- init_ErrorBoundary();
726
- init_api();
727
- }
728
- });
729
-
730
- // src/pages/users.tsx
731
- var users_exports = {};
732
- __export(users_exports, {
733
- default: () => users_default
734
- });
735
- var UsersPage, users_default;
736
- var init_users = __esm({
737
- "src/pages/users.tsx"() {
738
- "use strict";
739
- init_dist();
740
- init_Layout();
741
- init_api();
742
- UsersPage = ({ initialState: initialState2 }) => {
743
- const users = initialState2.data?.users || [];
744
- return /* @__PURE__ */ jsx(Layout, { title: "User Management" }, /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto" }, /* @__PURE__ */ jsx("div", { className: "bg-blue-50 p-6 rounded-lg mb-8 border border-blue-100" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-blue-800 mb-2" }, "Data Fetching Demo"), /* @__PURE__ */ jsx("p", { className: "text-blue-700" }, "This page demonstrates dynamic data fetching with the Users API.")), /* @__PURE__ */ jsx("div", { className: "bg-white shadow-md rounded-lg overflow-hidden" }, /* @__PURE__ */ jsx("div", { className: "px-6 py-4 border-b border-gray-200" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800" }, "User List")), users.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-6 text-center text-gray-500" }, /* @__PURE__ */ jsx("p", null, "No users found.")) : /* @__PURE__ */ jsx("div", { className: "overflow-x-auto" }, /* @__PURE__ */ jsx("table", { className: "w-full" }, /* @__PURE__ */ jsx("thead", null, /* @__PURE__ */ jsx("tr", { className: "bg-gray-50" }, /* @__PURE__ */ jsx("th", { className: "text-left py-3 px-6 font-medium text-gray-600 text-sm uppercase tracking-wider border-b" }, "ID"), /* @__PURE__ */ jsx("th", { className: "text-left py-3 px-6 font-medium text-gray-600 text-sm uppercase tracking-wider border-b" }, "Name"), /* @__PURE__ */ jsx("th", { className: "text-left py-3 px-6 font-medium text-gray-600 text-sm uppercase tracking-wider border-b" }, "Email"))), /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-gray-200" }, users.map((user) => /* @__PURE__ */ jsx("tr", { key: user.id, className: "hover:bg-gray-50" }, /* @__PURE__ */ jsx("td", { className: "py-4 px-6 text-sm text-gray-900" }, user.id), /* @__PURE__ */ jsx("td", { className: "py-4 px-6 text-sm font-medium text-gray-900" }, user.name), /* @__PURE__ */ jsx("td", { className: "py-4 px-6 text-sm text-gray-500" }, user.email)))))))));
745
- };
746
- UsersPage.getInitialData = async () => {
747
- return {
748
- users: await UserApi.getAll()
749
- };
750
- };
751
- users_default = UsersPage;
752
- }
753
- });
754
-
755
- // src/pages/users/[id].tsx
756
- var id_exports2 = {};
757
- __export(id_exports2, {
758
- default: () => UserDetail,
759
- getServerSideProps: () => getServerSideProps3
760
- });
761
- function UserDetail({ user, posts, initialState: initialState2 }) {
762
- const [userData, setUserData] = useState(user);
763
- const [userPosts, setUserPosts] = useState(posts || []);
764
- const [loading, setLoading] = useState(false);
765
- const [error, setError] = useState(null);
766
- const { id } = initialState2?.params || {};
767
- useEffect(() => {
768
- if (!userData && id) {
769
- setLoading(true);
770
- Promise.all([
771
- UserApi.getById(id),
772
- UserApi.getPosts(id)
773
- ]).then(([userData2, postsData]) => {
774
- setUserData(userData2);
775
- setUserPosts(postsData);
776
- setLoading(false);
777
- }).catch((err) => {
778
- console.error("Error fetching user data:", err);
779
- setError(err.message || "Failed to load user data");
780
- setLoading(false);
781
- });
782
- }
783
- }, [userData, id]);
784
- if (loading) {
785
- return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto p-4" }, /* @__PURE__ */ jsx("div", { className: "animate-pulse rounded-md bg-gray-100 p-8" }, /* @__PURE__ */ jsx("div", { className: "h-8 bg-gray-200 rounded w-1/4 mb-4" }), /* @__PURE__ */ jsx("div", { className: "h-4 bg-gray-200 rounded w-1/2 mb-2" }), /* @__PURE__ */ jsx("div", { className: "h-4 bg-gray-200 rounded w-3/4 mb-4" }), /* @__PURE__ */ jsx("div", { className: "h-40 bg-gray-200 rounded mb-4" })));
786
- }
787
- if (error) {
788
- return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto p-4" }, /* @__PURE__ */ jsx("div", { className: "rounded-md bg-red-50 p-4 border border-red-200" }, /* @__PURE__ */ jsx("h2", { className: "text-lg font-bold text-red-700" }, "Error Loading User"), /* @__PURE__ */ jsx("p", { className: "text-red-600" }, error)));
789
- }
790
- if (!userData) {
791
- return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto p-4" }, /* @__PURE__ */ jsx("div", { className: "rounded-md bg-yellow-50 p-4 border border-yellow-200" }, /* @__PURE__ */ jsx("h2", { className: "text-lg font-bold text-yellow-700" }, "User Not Found"), /* @__PURE__ */ jsx("p", { className: "text-yellow-600" }, "Could not find user with ID: ", id), /* @__PURE__ */ jsx("a", { href: "/users", className: "text-blue-600 hover:underline mt-2 block" }, "Back to Users List")));
792
- }
793
- return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto p-4" }, /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6 mb-6" }, /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-gray-800 mb-4" }, userData.name), /* @__PURE__ */ jsx("div", { className: "user-info mb-6" }, /* @__PURE__ */ jsx("p", { className: "text-gray-600" }, /* @__PURE__ */ jsx("span", { className: "font-bold" }, "ID:"), " ", userData.id), /* @__PURE__ */ jsx("p", { className: "text-gray-600" }, /* @__PURE__ */ jsx("span", { className: "font-bold" }, "Email:"), " ", userData.email)), /* @__PURE__ */ jsx("a", { href: "/users", className: "text-blue-600 hover:underline" }, "Back to Users List")), userPosts && userPosts.length > 0 ? /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-gray-800 mb-4" }, "Posts by ", userData.name), /* @__PURE__ */ jsx("div", { className: "space-y-4" }, userPosts.map((post) => /* @__PURE__ */ jsx("div", { key: post.id, className: "border-b pb-4" }, /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold" }, post.title), /* @__PURE__ */ jsx("p", { className: "text-gray-600" }, post.content))))) : /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-gray-800 mb-4" }, "Posts by ", userData.name), /* @__PURE__ */ jsx("p", { className: "text-gray-500 italic" }, "No posts found for this user.")));
794
- }
795
- async function getServerSideProps3({ params }) {
796
- try {
797
- const userId = params.id;
798
- const [user, posts] = await Promise.all([
799
- UserApi.getById(parseInt(userId)),
800
- UserApi.getPosts(parseInt(userId))
801
- ]);
802
- if (!user) {
803
- return {
804
- notFound: true
805
- };
806
- }
807
- return {
808
- props: {
809
- user,
810
- posts
811
- }
812
- };
813
- } catch (error) {
814
- console.error(`Error fetching user ${params.id}:`, error);
815
- return {
816
- props: {
817
- error: {
818
- message: error.message,
819
- status: error.status || 500
820
- },
821
- user: null,
822
- posts: []
823
- }
824
- };
825
- }
826
- }
827
- var init_id2 = __esm({
828
- "src/pages/users/[id].tsx"() {
829
- "use strict";
830
- init_dist();
831
- init_api();
832
- }
833
- });
834
-
835
- // src/pages/wasm-demo.tsx
836
- var wasm_demo_exports = {};
837
- var init_wasm_demo = __esm({
838
- "src/pages/wasm-demo.tsx"() {
839
- "use strict";
840
- }
841
- });
842
-
843
- // src/main.tsx
844
- init_dist();
845
-
846
- // import("./pages/**/*.tsx") in src/main.tsx
847
- var globImport_pages_tsx = __glob({
848
- "./pages/404.tsx": () => Promise.resolve().then(() => (init__(), __exports)),
849
- "./pages/[id].tsx": () => Promise.resolve().then(() => (init_id(), id_exports)),
850
- "./pages/_app.tsx": () => Promise.resolve().then(() => (init_app(), app_exports)),
851
- "./pages/_document.tsx": () => Promise.resolve().then(() => (init_document(), document_exports)),
852
- "./pages/_error.tsx": () => Promise.resolve().then(() => (init_error(), error_exports)),
853
- "./pages/about.tsx": () => Promise.resolve().then(() => (init_about(), about_exports)),
854
- "./pages/about/index.tsx": () => Promise.resolve().then(() => (init_about2(), about_exports2)),
855
- "./pages/index.tsx": () => Promise.resolve().then(() => (init_pages(), pages_exports)),
856
- "./pages/users.tsx": () => Promise.resolve().then(() => (init_users(), users_exports)),
857
- "./pages/users/[id].tsx": () => Promise.resolve().then(() => (init_id2(), id_exports2)),
858
- "./pages/wasm-demo.tsx": () => Promise.resolve().then(() => (init_wasm_demo(), wasm_demo_exports))
859
- });
860
-
861
- // import("./pages/**/*/index.tsx") in src/main.tsx
862
- var globImport_pages_index_tsx = __glob({
863
- "./pages/about/index.tsx": () => Promise.resolve().then(() => (init_about2(), about_exports2))
864
- });
865
-
866
- // src/main.tsx
867
- var initialState = window.__INITIAL_STATE__ || {
868
- route: window.location.pathname,
869
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
870
- serverRendered: false,
871
- data: {
872
- users: null,
873
- posts: null
874
- }
875
- };
876
- console.log("[Client] Initial state:", initialState);
877
- var isHydrating2 = document.getElementById("root")?.innerHTML.trim() !== "";
878
- async function handleRouteChange(path, isPushState = true) {
879
- try {
880
- console.log(`[Router] Navigating to: ${path}`);
881
- if (isPushState) {
882
- window.history.pushState(null, "", path);
883
- }
884
- const normalizedPath = path === "/" ? "index" : path.replace(/^\//, "");
885
- let Page;
886
- try {
887
- const module = await globImport_pages_tsx(`./pages/${normalizedPath}.tsx`);
888
- Page = module.default;
889
- } catch (error) {
890
- console.warn(`[Router] Could not load page for ${path}, trying index file`);
891
- try {
892
- const module = await globImport_pages_index_tsx(`./pages/${normalizedPath}/index.tsx`);
893
- Page = module.default;
894
- } catch (innerError) {
895
- console.error(`[Router] Failed to load page component for ${path}`);
896
- try {
897
- const notFoundModule = await Promise.resolve().then(() => (init__(), __exports));
898
- Page = notFoundModule.default;
899
- } catch (notFoundError) {
900
- const rootElement2 = document.getElementById("root");
901
- if (rootElement2) {
902
- render(
903
- /* @__PURE__ */ jsx("div", { style: { padding: "20px", maxWidth: "800px", margin: "0 auto" } }, /* @__PURE__ */ jsx("h1", null, "Page Not Found"), /* @__PURE__ */ jsx("p", null, "The page you requested could not be found."), /* @__PURE__ */ jsx("a", { href: "/", style: { color: "#0066cc" } }, "Go to Home")),
904
- rootElement2
905
- );
906
- }
907
- return;
908
- }
909
- }
910
- }
911
- let pageProps = initialState.pageProps || {};
912
- if (Page.getServerSideProps) {
913
- try {
914
- const response = await fetch(`/api/__props${path}`);
915
- if (response.ok) {
916
- const data = await response.json();
917
- pageProps = data.props || {};
918
- }
919
- } catch (error) {
920
- console.error("[Router] Error fetching page props:", error);
921
- }
922
- }
923
- const updatedState = {
924
- ...initialState,
925
- route: path,
926
- pageProps
927
- };
928
- const rootElement = document.getElementById("root");
929
- if (!rootElement)
930
- return;
931
- if (isHydrating2 && path === initialState.route) {
932
- console.log("[Client] Hydrating server-rendered content");
933
- hydrate(/* @__PURE__ */ jsx(Page, { ...pageProps, initialState: updatedState }), rootElement);
934
- isHydrating2 = false;
935
- } else {
936
- console.log("[Client] Rendering client-side");
937
- render(/* @__PURE__ */ jsx(Page, { ...pageProps, initialState: updatedState }), rootElement);
938
- }
939
- } catch (error) {
940
- console.error("[Router] Navigation error:", error);
941
- }
942
- }
943
- handleRouteChange(window.location.pathname, false);
944
- document.addEventListener("click", (e) => {
945
- let target = e.target;
946
- while (target && target.tagName !== "A") {
947
- target = target.parentElement;
948
- if (!target)
949
- break;
950
- }
951
- if (target && target.tagName === "A" && target.getAttribute("href") && target.getAttribute("href")?.startsWith("/") && !target.getAttribute("href")?.startsWith("//") && !target.getAttribute("target")) {
952
- e.preventDefault();
953
- const href = target.getAttribute("href") || "/";
954
- handleRouteChange(href);
955
- }
956
- });
957
- window.addEventListener("popstate", () => {
958
- handleRouteChange(window.location.pathname, false);
959
- });
960
- if (typeof io !== "undefined") {
961
- const socket = io();
962
- socket.on("reload", () => {
963
- console.log("[Dev] Reloading page due to file changes");
964
- window.location.reload();
965
- });
966
- }
967
- //# sourceMappingURL=main.js.map
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __glob = (map) => (path) => {
4
+ var fn = map[path];
5
+ if (fn)
6
+ return fn();
7
+ throw new Error("Module not found in bundle: " + path);
8
+ };
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
16
+
17
+ // node_modules/frontend-hamroun/dist/index.mjs
18
+ function batchUpdates(fn) {
19
+ if (isBatching) {
20
+ queue.push(fn);
21
+ return;
22
+ }
23
+ isBatching = true;
24
+ try {
25
+ fn();
26
+ while (queue.length > 0) {
27
+ const nextFn = queue.shift();
28
+ nextFn == null ? void 0 : nextFn();
29
+ }
30
+ } finally {
31
+ isBatching = false;
32
+ }
33
+ }
34
+ function setRenderCallback(callback, element, container) {
35
+ globalRenderCallback = callback;
36
+ globalContainer = container;
37
+ currentElement = element;
38
+ }
39
+ function prepareRender() {
40
+ currentRender++;
41
+ stateIndices.set(currentRender, 0);
42
+ return currentRender;
43
+ }
44
+ function finishRender() {
45
+ if (isServer) {
46
+ serverStates.delete(currentRender);
47
+ }
48
+ currentRender = 0;
49
+ }
50
+ function useState(initial) {
51
+ if (!currentRender) {
52
+ throw new Error("useState must be called within a render");
53
+ }
54
+ if (isServer) {
55
+ if (!serverStates.has(currentRender)) {
56
+ serverStates.set(currentRender, /* @__PURE__ */ new Map());
57
+ }
58
+ const componentState = serverStates.get(currentRender);
59
+ const index2 = stateIndices.get(currentRender) || 0;
60
+ if (!componentState.has(index2)) {
61
+ componentState.set(index2, initial);
62
+ }
63
+ const state2 = componentState.get(index2);
64
+ const setState2 = (newValue) => {
65
+ };
66
+ stateIndices.set(currentRender, index2 + 1);
67
+ return [state2, setState2];
68
+ }
69
+ if (!states.has(currentRender)) {
70
+ states.set(currentRender, []);
71
+ }
72
+ const componentStates = states.get(currentRender);
73
+ const index = stateIndices.get(currentRender);
74
+ if (index >= componentStates.length) {
75
+ componentStates.push(initial);
76
+ }
77
+ const state = componentStates[index];
78
+ const setState = (newValue) => {
79
+ const nextValue = typeof newValue === "function" ? newValue(componentStates[index]) : newValue;
80
+ if (componentStates[index] === nextValue)
81
+ return;
82
+ componentStates[index] = nextValue;
83
+ if (isBatching) {
84
+ batchUpdates(() => rerender(currentRender));
85
+ } else {
86
+ rerender(currentRender);
87
+ }
88
+ };
89
+ stateIndices.set(currentRender, index + 1);
90
+ return [state, setState];
91
+ }
92
+ function useEffect(callback, deps) {
93
+ if (!currentRender)
94
+ throw new Error("useEffect must be called within a render");
95
+ const effectIndex = stateIndices.get(currentRender);
96
+ if (!effects.has(currentRender)) {
97
+ effects.set(currentRender, []);
98
+ }
99
+ const componentEffects = effects.get(currentRender);
100
+ const prevEffect = componentEffects[effectIndex];
101
+ if (!prevEffect || !deps || !prevEffect.deps || deps.some((dep, i) => dep !== prevEffect.deps[i])) {
102
+ if (prevEffect == null ? void 0 : prevEffect.cleanup) {
103
+ prevEffect.cleanup();
104
+ }
105
+ queueMicrotask(() => {
106
+ const cleanup = callback() || void 0;
107
+ componentEffects[effectIndex] = { cleanup, deps };
108
+ });
109
+ }
110
+ stateIndices.set(currentRender, effectIndex + 1);
111
+ }
112
+ function useMemo(factory, deps) {
113
+ if (!currentRender)
114
+ throw new Error("useMemo must be called within a render");
115
+ const memoIndex = stateIndices.get(currentRender);
116
+ if (!memos.has(currentRender)) {
117
+ memos.set(currentRender, []);
118
+ }
119
+ const componentMemos = memos.get(currentRender);
120
+ const prevMemo = componentMemos[memoIndex];
121
+ if (!prevMemo || deps && deps.some((dep, i) => !Object.is(dep, prevMemo.deps[i]))) {
122
+ const value = factory();
123
+ componentMemos[memoIndex] = { value, deps };
124
+ stateIndices.set(currentRender, memoIndex + 1);
125
+ return value;
126
+ }
127
+ stateIndices.set(currentRender, memoIndex + 1);
128
+ return prevMemo.value;
129
+ }
130
+ async function rerender(rendererId) {
131
+ try {
132
+ const componentEffects = effects.get(rendererId);
133
+ if (componentEffects) {
134
+ componentEffects.forEach((effect) => {
135
+ if (effect.cleanup)
136
+ effect.cleanup();
137
+ });
138
+ effects.set(rendererId, []);
139
+ }
140
+ if (globalRenderCallback && globalContainer && currentElement) {
141
+ await globalRenderCallback(currentElement, globalContainer);
142
+ }
143
+ } catch (error) {
144
+ console.error("Error during rerender:", error);
145
+ }
146
+ }
147
+ function useErrorBoundary() {
148
+ const [error, setError] = useState(null);
149
+ return [error, () => setError(null)];
150
+ }
151
+ function jsx(type, props) {
152
+ console.log("JSX Transform:", { type, props });
153
+ const processedProps = { ...props };
154
+ if (arguments.length > 2) {
155
+ processedProps.children = Array.prototype.slice.call(arguments, 2);
156
+ }
157
+ return { type, props: processedProps };
158
+ }
159
+ async function createElement(vnode) {
160
+ var _a;
161
+ console.log("Creating element from:", vnode);
162
+ if (vnode == null) {
163
+ return document.createTextNode("");
164
+ }
165
+ if (typeof vnode === "boolean") {
166
+ return document.createTextNode("");
167
+ }
168
+ if (typeof vnode === "number" || typeof vnode === "string") {
169
+ return document.createTextNode(String(vnode));
170
+ }
171
+ if (Array.isArray(vnode)) {
172
+ const fragment = document.createDocumentFragment();
173
+ for (const child of vnode) {
174
+ const node = await createElement(child);
175
+ fragment.appendChild(node);
176
+ }
177
+ return fragment;
178
+ }
179
+ if ("type" in vnode && vnode.props !== void 0) {
180
+ const { type, props } = vnode;
181
+ if (typeof type === "function") {
182
+ try {
183
+ const result = await type(props || {});
184
+ const node = await createElement(result);
185
+ if (node instanceof Element) {
186
+ node.setAttribute("data-component-id", type.name || type.toString());
187
+ }
188
+ return node;
189
+ } catch (error) {
190
+ console.error("Error rendering component:", error);
191
+ return document.createTextNode("");
192
+ }
193
+ }
194
+ const element = document.createElement(type);
195
+ for (const [key, value] of Object.entries(props || {})) {
196
+ if (key === "children")
197
+ continue;
198
+ if (key.startsWith("on") && typeof value === "function") {
199
+ const eventName = key.toLowerCase().slice(2);
200
+ const existingHandler = (_a = element.__events) == null ? void 0 : _a[eventName];
201
+ if (existingHandler) {
202
+ element.removeEventListener(eventName, existingHandler);
203
+ }
204
+ element.addEventListener(eventName, value);
205
+ if (!element.__events) {
206
+ element.__events = {};
207
+ }
208
+ element.__events[eventName] = value;
209
+ } else if (key === "style" && typeof value === "object") {
210
+ Object.assign(element.style, value);
211
+ } else if (key === "className") {
212
+ element.setAttribute("class", String(value));
213
+ } else if (key !== "key" && key !== "ref") {
214
+ element.setAttribute(key, String(value));
215
+ }
216
+ }
217
+ const children = props == null ? void 0 : props.children;
218
+ if (children != null) {
219
+ const childArray = Array.isArray(children) ? children.flat() : [children];
220
+ for (const child of childArray) {
221
+ const childNode = await createElement(child);
222
+ element.appendChild(childNode);
223
+ }
224
+ }
225
+ return element;
226
+ }
227
+ return document.createTextNode(String(vnode));
228
+ }
229
+ async function hydrate(element, container) {
230
+ isHydrating = true;
231
+ try {
232
+ await render(element, container);
233
+ } finally {
234
+ isHydrating = false;
235
+ }
236
+ }
237
+ async function render(element, container) {
238
+ console.log("Rendering to:", container.id);
239
+ batchUpdates(async () => {
240
+ const rendererId = prepareRender();
241
+ try {
242
+ setRenderCallback(render, element, container);
243
+ const domNode = await createElement(element);
244
+ if (!isHydrating) {
245
+ container.innerHTML = "";
246
+ }
247
+ container.appendChild(domNode);
248
+ } finally {
249
+ finishRender();
250
+ }
251
+ });
252
+ }
253
+ var isBatching, queue, currentRender, states, stateIndices, effects, memos, globalRenderCallback, globalContainer, currentElement, isServer, serverStates, isHydrating;
254
+ var init_dist = __esm({
255
+ "node_modules/frontend-hamroun/dist/index.mjs"() {
256
+ isBatching = false;
257
+ queue = [];
258
+ currentRender = 0;
259
+ states = /* @__PURE__ */ new Map();
260
+ stateIndices = /* @__PURE__ */ new Map();
261
+ effects = /* @__PURE__ */ new Map();
262
+ memos = /* @__PURE__ */ new Map();
263
+ globalRenderCallback = null;
264
+ globalContainer = null;
265
+ currentElement = null;
266
+ isServer = typeof window === "undefined";
267
+ serverStates = /* @__PURE__ */ new Map();
268
+ isHydrating = false;
269
+ }
270
+ });
271
+
272
+ // src/pages/404.tsx
273
+ var __exports = {};
274
+ __export(__exports, {
275
+ default: () => NotFound
276
+ });
277
+ function NotFound({ initialState: initialState2 }) {
278
+ return /* @__PURE__ */ jsx("div", { className: "not-found-container max-w-4xl mx-auto p-6" }, /* @__PURE__ */ jsx("div", { className: "bg-gray-50 border border-gray-200 rounded-lg p-8 shadow-sm" }, /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold text-gray-700 mb-4" }, "Page Not Found"), /* @__PURE__ */ jsx("p", { className: "text-lg text-gray-600 mb-4" }, "The page you are looking for does not exist or has been moved."), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-6" }, "Path: ", /* @__PURE__ */ jsx("code", { className: "bg-gray-100 px-2 py-1 rounded" }, initialState2?.route || "unknown")), /* @__PURE__ */ jsx("div", { className: "mt-6" }, /* @__PURE__ */ jsx(
279
+ "a",
280
+ {
281
+ href: "/",
282
+ className: "inline-block px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
283
+ },
284
+ "Back to Home"
285
+ ))));
286
+ }
287
+ var init__ = __esm({
288
+ "src/pages/404.tsx"() {
289
+ "use strict";
290
+ init_dist();
291
+ }
292
+ });
293
+
294
+ // src/pages/[id].tsx
295
+ var id_exports = {};
296
+ var init_id = __esm({
297
+ "src/pages/[id].tsx"() {
298
+ "use strict";
299
+ }
300
+ });
301
+
302
+ // src/components/Layout.tsx
303
+ function Layout({ children, title = "Frontend Hamroun App" }) {
304
+ return /* @__PURE__ */ jsx("div", { className: "min-h-screen flex flex-col bg-gray-50" }, /* @__PURE__ */ jsx("header", { className: "bg-blue-600 text-white" }, /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-4 flex justify-between items-center" }, /* @__PURE__ */ jsx("h1", { className: "text-xl font-bold" }, /* @__PURE__ */ jsx("a", { href: "/", className: "hover:text-blue-100" }, title)), /* @__PURE__ */ jsx("nav", null, /* @__PURE__ */ jsx("ul", { className: "flex space-x-6" }, /* @__PURE__ */ jsx("li", null, /* @__PURE__ */ jsx("a", { href: "/", className: "hover:text-blue-100" }, "Home")), /* @__PURE__ */ jsx("li", null, /* @__PURE__ */ jsx("a", { href: "/about", className: "hover:text-blue-100" }, "About")))))), /* @__PURE__ */ jsx("main", { className: "flex-grow container mx-auto px-4 py-8" }, children), /* @__PURE__ */ jsx("footer", { className: "bg-gray-800 text-white" }, /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-6" }, /* @__PURE__ */ jsx("p", { className: "text-center text-gray-400" }, "\xA9 ", (/* @__PURE__ */ new Date()).getFullYear(), " Frontend Hamroun App. All rights reserved."))));
305
+ }
306
+ var init_Layout = __esm({
307
+ "src/components/Layout.tsx"() {
308
+ "use strict";
309
+ init_dist();
310
+ }
311
+ });
312
+
313
+ // src/pages/_app.tsx
314
+ var app_exports = {};
315
+ __export(app_exports, {
316
+ default: () => App
317
+ });
318
+ function App({ Component, pageProps, initialState: initialState2 }) {
319
+ return /* @__PURE__ */ jsx(Layout, null, /* @__PURE__ */ jsx(Component, { ...pageProps, initialState: initialState2 }));
320
+ }
321
+ var init_app = __esm({
322
+ "src/pages/_app.tsx"() {
323
+ "use strict";
324
+ init_dist();
325
+ init_Layout();
326
+ }
327
+ });
328
+
329
+ // src/pages/_document.tsx
330
+ var document_exports = {};
331
+ __export(document_exports, {
332
+ default: () => Document
333
+ });
334
+ function Document({
335
+ title = "Frontend Hamroun App",
336
+ headContent,
337
+ bodyContent,
338
+ scripts
339
+ }) {
340
+ return /* @__PURE__ */ jsx("html", { lang: "en" }, /* @__PURE__ */ jsx("head", null, /* @__PURE__ */ jsx("meta", { charSet: "UTF-8" }), /* @__PURE__ */ jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }), /* @__PURE__ */ jsx("title", null, title), /* @__PURE__ */ jsx("link", { rel: "stylesheet", href: "/styles.css" }), headContent), /* @__PURE__ */ jsx("body", null, /* @__PURE__ */ jsx("div", { id: "root" }, bodyContent), /* @__PURE__ */ jsx("script", { src: "/build/main.js", type: "module" }), scripts));
341
+ }
342
+ var init_document = __esm({
343
+ "src/pages/_document.tsx"() {
344
+ "use strict";
345
+ init_dist();
346
+ }
347
+ });
348
+
349
+ // src/pages/_error.tsx
350
+ var error_exports = {};
351
+ __export(error_exports, {
352
+ default: () => ErrorPage
353
+ });
354
+ function ErrorPage({ initialState: initialState2 }) {
355
+ const { error } = initialState2 || {};
356
+ const [showDetails, setShowDetails] = useState(false);
357
+ const isDev = true;
358
+ return /* @__PURE__ */ jsx("div", { className: "error-page-container max-w-4xl mx-auto p-6" }, /* @__PURE__ */ jsx("div", { className: "bg-red-50 border border-red-200 rounded-lg p-8 shadow-sm" }, /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold text-red-700 mb-4" }, "Something went wrong"), /* @__PURE__ */ jsx("p", { className: "text-lg text-red-600 mb-4" }, error?.message || "An unexpected error occurred"), isDev && error?.stack && /* @__PURE__ */ jsx("div", { className: "mt-6" }, /* @__PURE__ */ jsx(
359
+ "button",
360
+ {
361
+ className: "text-blue-600 underline mb-2",
362
+ onClick: () => setShowDetails(!showDetails)
363
+ },
364
+ showDetails ? "Hide" : "Show",
365
+ " technical details"
366
+ ), showDetails && /* @__PURE__ */ jsx("pre", { className: "bg-gray-100 p-4 rounded-md text-sm overflow-auto max-h-96 text-gray-800" }, error.stack)), /* @__PURE__ */ jsx("div", { className: "mt-6" }, /* @__PURE__ */ jsx(
367
+ "a",
368
+ {
369
+ href: "/",
370
+ className: "inline-block px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
371
+ },
372
+ "Back to Home"
373
+ ))));
374
+ }
375
+ var init_error = __esm({
376
+ "src/pages/_error.tsx"() {
377
+ "use strict";
378
+ init_dist();
379
+ }
380
+ });
381
+
382
+ // src/pages/about.tsx
383
+ var about_exports = {};
384
+ __export(about_exports, {
385
+ default: () => AboutPage,
386
+ getServerSideProps: () => getServerSideProps
387
+ });
388
+ function AboutPage({ initialState: initialState2 }) {
389
+ return /* @__PURE__ */ jsx(Layout, { title: "About - Frontend Hamroun" }, /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto" }, /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold text-blue-600 mb-6" }, "About Frontend Hamroun"), /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-8 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "What is Frontend Hamroun?"), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-4" }, "Frontend Hamroun is a lightweight JavaScript framework for building modern web applications. It provides a familiar component-based architecture with hooks, JSX support, and server-side rendering capabilities."), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-4" }, "This framework is designed to be simple yet powerful, offering the essential features needed for web application development without the complexity of larger frameworks."), /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium text-gray-700 mt-6 mb-2" }, "Key Features:"), /* @__PURE__ */ jsx("ul", { className: "list-disc pl-6 text-gray-600 space-y-2" }, /* @__PURE__ */ jsx("li", null, "Component-based architecture"), /* @__PURE__ */ jsx("li", null, "JSX support"), /* @__PURE__ */ jsx("li", null, "Hooks for state and effects"), /* @__PURE__ */ jsx("li", null, "Server-side rendering"), /* @__PURE__ */ jsx("li", null, "Minimal API surface"), /* @__PURE__ */ jsx("li", null, "File-based routing"), /* @__PURE__ */ jsx("li", null, "Built-in API routes"))), /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "Getting Started"), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-4" }, "This application was created using the Frontend Hamroun fullstack template, which provides a complete setup for building applications with server-side rendering, API routes, and client-side navigation."), /* @__PURE__ */ jsx("div", { className: "bg-gray-50 p-4 rounded-md mt-4" }, /* @__PURE__ */ jsx("h3", { className: "text-md font-medium text-gray-700 mb-2" }, "Quick Start:"), /* @__PURE__ */ jsx("pre", { className: "bg-gray-800 text-gray-100 p-4 rounded overflow-x-auto" }, /* @__PURE__ */ jsx("code", null, `# Create a new application
390
+ npx frontend-hamroun create my-app
391
+
392
+ # Change directory
393
+ cd my-app
394
+
395
+ # Start the development server
396
+ npm run dev`))))));
397
+ }
398
+ async function getServerSideProps() {
399
+ return {
400
+ props: {
401
+ pageTitle: "About Frontend Hamroun",
402
+ description: "Learn more about the Frontend Hamroun framework"
403
+ }
404
+ };
405
+ }
406
+ var init_about = __esm({
407
+ "src/pages/about.tsx"() {
408
+ "use strict";
409
+ init_dist();
410
+ init_Layout();
411
+ }
412
+ });
413
+
414
+ // src/pages/about/index.tsx
415
+ var about_exports2 = {};
416
+ __export(about_exports2, {
417
+ default: () => about_default
418
+ });
419
+ var AboutPage2, about_default;
420
+ var init_about2 = __esm({
421
+ "src/pages/about/index.tsx"() {
422
+ "use strict";
423
+ init_dist();
424
+ init_Layout();
425
+ AboutPage2 = ({ initialState: initialState2 }) => {
426
+ return /* @__PURE__ */ jsx(Layout, { title: "About This App" }, /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto bg-white shadow-lg rounded-lg overflow-hidden" }, /* @__PURE__ */ jsx("div", { className: "p-8" }, /* @__PURE__ */ jsx("p", { className: "text-lg text-gray-700 mb-6" }, "This is a frontend application built with Frontend Hamroun framework and styled with Tailwind CSS."), /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-8" }, "It features server-side rendering, client-side navigation, and websocket-based live reloading during development."), /* @__PURE__ */ jsx("div", { className: "bg-gray-50 p-6 rounded-lg border border-gray-200 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "Key Features"), /* @__PURE__ */ jsx("ul", { className: "space-y-2 text-gray-700" }, /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Server-side rendering"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Client-side navigation"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Component-based architecture"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Integrated API backend"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Live reload during development"), /* @__PURE__ */ jsx("li", { className: "flex items-center" }, /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-green-500 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M5 13l4 4L19 7" })), "Tailwind CSS for styling"))), /* @__PURE__ */ jsx("a", { href: "/", className: "inline-block px-6 py-3 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 transition-colors" }, "Back to Home"))));
427
+ };
428
+ about_default = AboutPage2;
429
+ }
430
+ });
431
+
432
+ // src/components/UserList.tsx
433
+ function UserList({ users }) {
434
+ if (!users || users.length === 0) {
435
+ return /* @__PURE__ */ jsx("div", { className: "empty-state p-4 text-center bg-gray-50 rounded" }, /* @__PURE__ */ jsx("p", { className: "text-gray-500" }, "No users available"));
436
+ }
437
+ return /* @__PURE__ */ jsx("div", { className: "user-list" }, /* @__PURE__ */ jsx("ul", { className: "divide-y divide-gray-100" }, users.map((user) => /* @__PURE__ */ jsx("li", { key: user.id, className: "py-3" }, /* @__PURE__ */ jsx("div", { className: "flex justify-between" }, /* @__PURE__ */ jsx("div", null, /* @__PURE__ */ jsx("p", { className: "font-medium text-gray-900" }, user.name), /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500" }, user.email)), /* @__PURE__ */ jsx(
438
+ "a",
439
+ {
440
+ href: `/users/${user.id}`,
441
+ className: "text-blue-600 hover:underline text-sm self-center"
442
+ },
443
+ "View Profile"
444
+ ))))));
445
+ }
446
+ var init_UserList = __esm({
447
+ "src/components/UserList.tsx"() {
448
+ "use strict";
449
+ init_dist();
450
+ }
451
+ });
452
+
453
+ // src/components/StateDemo.tsx
454
+ function StateDemo() {
455
+ const [state, setState] = useState({
456
+ count: 0,
457
+ lastUpdated: null,
458
+ history: []
459
+ });
460
+ const [isLoading, setIsLoading] = useState(false);
461
+ const [showHistory, setShowHistory] = useState(false);
462
+ const isSSR = typeof window === "undefined";
463
+ const stats = useMemo(() => {
464
+ if (isSSR || !state || !state.history || state.history.length === 0) {
465
+ return { avg: 0, max: 0, min: 0 };
466
+ }
467
+ try {
468
+ const sum = state.history.reduce((a, b) => a + b, 0);
469
+ return {
470
+ avg: parseFloat((sum / state.history.length).toFixed(1)),
471
+ max: Math.max(...state.history),
472
+ min: Math.min(...state.history)
473
+ };
474
+ } catch (error) {
475
+ console.error("Error calculating stats:", error);
476
+ return { avg: 0, max: 0, min: 0 };
477
+ }
478
+ }, [state?.history]);
479
+ const increment = () => {
480
+ if (isSSR)
481
+ return;
482
+ setIsLoading(true);
483
+ setTimeout(() => {
484
+ setState((prevState) => ({
485
+ count: prevState.count + 1,
486
+ lastUpdated: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
487
+ history: [...prevState.history || [], prevState.count + 1]
488
+ }));
489
+ setIsLoading(false);
490
+ }, 300);
491
+ };
492
+ const decrement = () => {
493
+ if (isSSR)
494
+ return;
495
+ setIsLoading(true);
496
+ setTimeout(() => {
497
+ setState((prevState) => ({
498
+ count: Math.max(0, prevState.count - 1),
499
+ lastUpdated: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
500
+ history: prevState.count > 0 ? [...prevState.history || [], prevState.count - 1] : prevState.history || []
501
+ }));
502
+ setIsLoading(false);
503
+ }, 300);
504
+ };
505
+ const reset = () => {
506
+ if (isSSR)
507
+ return;
508
+ setState({
509
+ count: 0,
510
+ lastUpdated: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
511
+ history: []
512
+ });
513
+ };
514
+ const toggleHistory = () => {
515
+ if (isSSR)
516
+ return;
517
+ setShowHistory((prev) => !prev);
518
+ };
519
+ if (isSSR) {
520
+ return /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "State Management Demo"), /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ jsx("button", { className: "px-4 py-2 bg-gray-200 text-gray-800 rounded-lg" }, "-"), /* @__PURE__ */ jsx("span", { className: "text-2xl font-bold mx-4" }, "0"), /* @__PURE__ */ jsx("button", { className: "px-4 py-2 bg-blue-600 text-white rounded-lg" }, "+")), /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500" }, "Interactive counter (client-side only)"));
521
+ }
522
+ return /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "State Management Demo"), /* @__PURE__ */ jsx("div", { className: "mb-6" }, /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ jsx(
523
+ "button",
524
+ {
525
+ onClick: decrement,
526
+ className: "px-4 py-2 bg-gray-200 text-gray-800 rounded-lg hover:bg-gray-300 disabled:opacity-50",
527
+ disabled: state.count === 0 || isLoading
528
+ },
529
+ isLoading ? "..." : "-"
530
+ ), /* @__PURE__ */ jsx("span", { className: "text-2xl font-bold mx-4" }, state.count), /* @__PURE__ */ jsx(
531
+ "button",
532
+ {
533
+ onClick: increment,
534
+ className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50",
535
+ disabled: isLoading
536
+ },
537
+ isLoading ? "..." : "+"
538
+ )), /* @__PURE__ */ jsx(
539
+ "button",
540
+ {
541
+ onClick: reset,
542
+ className: "text-sm text-gray-600 hover:text-red-600",
543
+ disabled: state.count === 0 && (!state.history || state.history.length === 0)
544
+ },
545
+ "Reset Counter"
546
+ )), state.lastUpdated && /* @__PURE__ */ jsx("div", { className: "mb-4" }, /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500" }, "Last updated: ", state.lastUpdated)), state.history && state.history.length > 0 && /* @__PURE__ */ jsx("div", { className: "border-t pt-4 mt-4" }, /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ jsx("h3", { className: "text-md font-medium text-gray-700" }, "Statistics"), /* @__PURE__ */ jsx(
547
+ "button",
548
+ {
549
+ onClick: toggleHistory,
550
+ className: "text-sm text-blue-600 hover:underline"
551
+ },
552
+ showHistory ? "Hide History" : "Show History"
553
+ )), /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-2 mb-3" }, /* @__PURE__ */ jsx("div", { className: "bg-blue-50 p-2 rounded text-center" }, /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500" }, "Average"), /* @__PURE__ */ jsx("div", { className: "font-bold" }, stats.avg)), /* @__PURE__ */ jsx("div", { className: "bg-green-50 p-2 rounded text-center" }, /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500" }, "Maximum"), /* @__PURE__ */ jsx("div", { className: "font-bold" }, stats.max)), /* @__PURE__ */ jsx("div", { className: "bg-red-50 p-2 rounded text-center" }, /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500" }, "Minimum"), /* @__PURE__ */ jsx("div", { className: "font-bold" }, stats.min))), showHistory && /* @__PURE__ */ jsx("div", { className: "mt-3" }, /* @__PURE__ */ jsx("h4", { className: "text-sm font-medium text-gray-600 mb-1" }, "History (", state.history.length, " events)"), /* @__PURE__ */ jsx("div", { className: "bg-gray-50 p-2 rounded max-h-24 overflow-y-auto text-xs" }, state.history.map((value, index) => /* @__PURE__ */ jsx(
554
+ "span",
555
+ {
556
+ key: index,
557
+ className: "inline-block bg-gray-200 rounded px-2 py-1 m-1"
558
+ },
559
+ value
560
+ ))))));
561
+ }
562
+ var init_StateDemo = __esm({
563
+ "src/components/StateDemo.tsx"() {
564
+ "use strict";
565
+ init_dist();
566
+ }
567
+ });
568
+
569
+ // src/components/ErrorBoundary.tsx
570
+ function ErrorBoundary({ children, fallback }) {
571
+ const [error, resetError] = useErrorBoundary();
572
+ if (error) {
573
+ if (fallback) {
574
+ return fallback(error, resetError);
575
+ }
576
+ return /* @__PURE__ */ jsx("div", { className: "error-boundary p-4 border border-red-500 rounded bg-red-50" }, /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium text-red-800 mb-2" }, "Something went wrong"), /* @__PURE__ */ jsx("p", { className: "text-red-600 mb-2" }, error.message), /* @__PURE__ */ jsx(
577
+ "button",
578
+ {
579
+ onClick: resetError,
580
+ className: "px-3 py-1 bg-red-600 text-white rounded hover:bg-red-700"
581
+ },
582
+ "Try again"
583
+ ), /* @__PURE__ */ jsx("pre", { className: "mt-3 text-xs overflow-auto p-2 bg-gray-100" }, error.stack));
584
+ }
585
+ return children;
586
+ }
587
+ var init_ErrorBoundary = __esm({
588
+ "src/components/ErrorBoundary.tsx"() {
589
+ "use strict";
590
+ init_dist();
591
+ }
592
+ });
593
+
594
+ // src/data/api.ts
595
+ var sampleUsers, samplePosts, delay, UserApi;
596
+ var init_api = __esm({
597
+ "src/data/api.ts"() {
598
+ "use strict";
599
+ init_dist();
600
+ sampleUsers = [
601
+ { id: 1, name: "User 1", email: "user1@example.com" },
602
+ { id: 2, name: "User 2", email: "user2@example.com" },
603
+ { id: 3, name: "User 3", email: "user3@example.com" }
604
+ ];
605
+ samplePosts = [
606
+ { id: 1, title: "Post 1", content: "Content for post 1", authorId: 1 },
607
+ { id: 2, title: "Post 2", content: "Content for post 2", authorId: 2 },
608
+ { id: 3, title: "Post 3", content: "Content for post 3", authorId: 1 }
609
+ ];
610
+ delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
611
+ UserApi = {
612
+ // Get all users
613
+ async getAll() {
614
+ try {
615
+ await delay(300);
616
+ return [...sampleUsers];
617
+ } catch (error) {
618
+ console.error("Error fetching users:", error);
619
+ return [];
620
+ }
621
+ },
622
+ // Get user by ID
623
+ async getById(id) {
624
+ try {
625
+ const userId = typeof id === "string" ? parseInt(id, 10) : id;
626
+ await delay(200);
627
+ const user = sampleUsers.find((u) => u.id === userId);
628
+ if (!user)
629
+ throw new Error("User not found");
630
+ return { ...user };
631
+ } catch (error) {
632
+ console.error(`Error fetching user ${id}:`, error);
633
+ return null;
634
+ }
635
+ },
636
+ // Get posts (all or by author)
637
+ async getPosts(authorId) {
638
+ try {
639
+ const userId = authorId ? typeof authorId === "string" ? parseInt(authorId, 10) : authorId : void 0;
640
+ await delay(400);
641
+ const posts = userId ? samplePosts.filter((p) => p.authorId === userId) : samplePosts;
642
+ return [...posts];
643
+ } catch (error) {
644
+ console.error("Error fetching posts:", error);
645
+ return [];
646
+ }
647
+ }
648
+ };
649
+ }
650
+ });
651
+
652
+ // src/pages/index.tsx
653
+ var pages_exports = {};
654
+ __export(pages_exports, {
655
+ default: () => HomePage,
656
+ getServerSideProps: () => getServerSideProps2
657
+ });
658
+ function HomePage({ users, posts, initialState: initialState2 }) {
659
+ const [state, setState] = useState(initialState2 || {});
660
+ const [refreshTrigger, setRefreshTrigger] = useState(0);
661
+ useEffect(() => {
662
+ if (refreshTrigger === 0)
663
+ return;
664
+ async function fetchData() {
665
+ try {
666
+ const [users2, posts2] = await Promise.all([
667
+ UserApi.getAll(),
668
+ UserApi.getPosts()
669
+ ]);
670
+ batchUpdates(() => {
671
+ setState((prev) => ({
672
+ ...prev,
673
+ data: {
674
+ ...prev.data,
675
+ users: users2,
676
+ posts: posts2
677
+ },
678
+ lastUpdate: (/* @__PURE__ */ new Date()).toISOString()
679
+ }));
680
+ });
681
+ } catch (error) {
682
+ console.error("Error fetching data:", error);
683
+ }
684
+ }
685
+ fetchData();
686
+ }, [refreshTrigger]);
687
+ const handleRefresh = () => {
688
+ setRefreshTrigger((t) => t + 1);
689
+ };
690
+ return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto py-8" }, /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold text-blue-600 mb-6" }, "Welcome to your Next-style Frontend Hamroun application!"), /* @__PURE__ */ jsx("div", { className: "mb-8" }, /* @__PURE__ */ jsx(
691
+ "button",
692
+ {
693
+ className: "mb-4 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700",
694
+ onClick: handleRefresh
695
+ },
696
+ "Refresh Data"
697
+ ), /* @__PURE__ */ jsx("div", { className: "bg-blue-50 p-4 rounded-lg border border-blue-100 mb-6" }, /* @__PURE__ */ jsx("p", { className: "text-blue-700" }, "Last updated: ", state.lastUpdate || "Never"))), /* @__PURE__ */ jsx(ErrorBoundary, null, /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6 mb-8" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800 mb-4" }, "User List"), /* @__PURE__ */ jsx(UserList, { users: users || state.data?.users || [] }))), /* @__PURE__ */ jsx(ErrorBoundary, null, /* @__PURE__ */ jsx(StateDemo, null)), /* @__PURE__ */ jsx("div", { className: "bg-gray-50 rounded-lg p-6 border border-gray-200 mt-8" }, /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium text-gray-700 mb-3" }, "Application State"), /* @__PURE__ */ jsx("pre", { className: "overflow-auto p-4 bg-gray-100 rounded-md text-sm text-gray-800" }, JSON.stringify({ users, posts, ...state }, null, 2))));
698
+ }
699
+ async function getServerSideProps2() {
700
+ try {
701
+ const users = await UserApi.getAll();
702
+ const posts = await UserApi.getPosts();
703
+ return {
704
+ props: {
705
+ users,
706
+ posts
707
+ }
708
+ };
709
+ } catch (error) {
710
+ console.error("Error fetching initial data:", error);
711
+ return {
712
+ props: {
713
+ users: [],
714
+ posts: []
715
+ }
716
+ };
717
+ }
718
+ }
719
+ var init_pages = __esm({
720
+ "src/pages/index.tsx"() {
721
+ "use strict";
722
+ init_dist();
723
+ init_UserList();
724
+ init_StateDemo();
725
+ init_ErrorBoundary();
726
+ init_api();
727
+ }
728
+ });
729
+
730
+ // src/pages/users.tsx
731
+ var users_exports = {};
732
+ __export(users_exports, {
733
+ default: () => users_default
734
+ });
735
+ var UsersPage, users_default;
736
+ var init_users = __esm({
737
+ "src/pages/users.tsx"() {
738
+ "use strict";
739
+ init_dist();
740
+ init_Layout();
741
+ init_api();
742
+ UsersPage = ({ initialState: initialState2 }) => {
743
+ const users = initialState2.data?.users || [];
744
+ return /* @__PURE__ */ jsx(Layout, { title: "User Management" }, /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto" }, /* @__PURE__ */ jsx("div", { className: "bg-blue-50 p-6 rounded-lg mb-8 border border-blue-100" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-blue-800 mb-2" }, "Data Fetching Demo"), /* @__PURE__ */ jsx("p", { className: "text-blue-700" }, "This page demonstrates dynamic data fetching with the Users API.")), /* @__PURE__ */ jsx("div", { className: "bg-white shadow-md rounded-lg overflow-hidden" }, /* @__PURE__ */ jsx("div", { className: "px-6 py-4 border-b border-gray-200" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-800" }, "User List")), users.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-6 text-center text-gray-500" }, /* @__PURE__ */ jsx("p", null, "No users found.")) : /* @__PURE__ */ jsx("div", { className: "overflow-x-auto" }, /* @__PURE__ */ jsx("table", { className: "w-full" }, /* @__PURE__ */ jsx("thead", null, /* @__PURE__ */ jsx("tr", { className: "bg-gray-50" }, /* @__PURE__ */ jsx("th", { className: "text-left py-3 px-6 font-medium text-gray-600 text-sm uppercase tracking-wider border-b" }, "ID"), /* @__PURE__ */ jsx("th", { className: "text-left py-3 px-6 font-medium text-gray-600 text-sm uppercase tracking-wider border-b" }, "Name"), /* @__PURE__ */ jsx("th", { className: "text-left py-3 px-6 font-medium text-gray-600 text-sm uppercase tracking-wider border-b" }, "Email"))), /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-gray-200" }, users.map((user) => /* @__PURE__ */ jsx("tr", { key: user.id, className: "hover:bg-gray-50" }, /* @__PURE__ */ jsx("td", { className: "py-4 px-6 text-sm text-gray-900" }, user.id), /* @__PURE__ */ jsx("td", { className: "py-4 px-6 text-sm font-medium text-gray-900" }, user.name), /* @__PURE__ */ jsx("td", { className: "py-4 px-6 text-sm text-gray-500" }, user.email)))))))));
745
+ };
746
+ UsersPage.getInitialData = async () => {
747
+ return {
748
+ users: await UserApi.getAll()
749
+ };
750
+ };
751
+ users_default = UsersPage;
752
+ }
753
+ });
754
+
755
+ // src/pages/users/[id].tsx
756
+ var id_exports2 = {};
757
+ __export(id_exports2, {
758
+ default: () => UserDetail,
759
+ getServerSideProps: () => getServerSideProps3
760
+ });
761
+ function UserDetail({ user, posts, initialState: initialState2 }) {
762
+ const [userData, setUserData] = useState(user);
763
+ const [userPosts, setUserPosts] = useState(posts || []);
764
+ const [loading, setLoading] = useState(false);
765
+ const [error, setError] = useState(null);
766
+ const { id } = initialState2?.params || {};
767
+ useEffect(() => {
768
+ if (!userData && id) {
769
+ setLoading(true);
770
+ Promise.all([
771
+ UserApi.getById(id),
772
+ UserApi.getPosts(id)
773
+ ]).then(([userData2, postsData]) => {
774
+ setUserData(userData2);
775
+ setUserPosts(postsData);
776
+ setLoading(false);
777
+ }).catch((err) => {
778
+ console.error("Error fetching user data:", err);
779
+ setError(err.message || "Failed to load user data");
780
+ setLoading(false);
781
+ });
782
+ }
783
+ }, [userData, id]);
784
+ if (loading) {
785
+ return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto p-4" }, /* @__PURE__ */ jsx("div", { className: "animate-pulse rounded-md bg-gray-100 p-8" }, /* @__PURE__ */ jsx("div", { className: "h-8 bg-gray-200 rounded w-1/4 mb-4" }), /* @__PURE__ */ jsx("div", { className: "h-4 bg-gray-200 rounded w-1/2 mb-2" }), /* @__PURE__ */ jsx("div", { className: "h-4 bg-gray-200 rounded w-3/4 mb-4" }), /* @__PURE__ */ jsx("div", { className: "h-40 bg-gray-200 rounded mb-4" })));
786
+ }
787
+ if (error) {
788
+ return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto p-4" }, /* @__PURE__ */ jsx("div", { className: "rounded-md bg-red-50 p-4 border border-red-200" }, /* @__PURE__ */ jsx("h2", { className: "text-lg font-bold text-red-700" }, "Error Loading User"), /* @__PURE__ */ jsx("p", { className: "text-red-600" }, error)));
789
+ }
790
+ if (!userData) {
791
+ return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto p-4" }, /* @__PURE__ */ jsx("div", { className: "rounded-md bg-yellow-50 p-4 border border-yellow-200" }, /* @__PURE__ */ jsx("h2", { className: "text-lg font-bold text-yellow-700" }, "User Not Found"), /* @__PURE__ */ jsx("p", { className: "text-yellow-600" }, "Could not find user with ID: ", id), /* @__PURE__ */ jsx("a", { href: "/users", className: "text-blue-600 hover:underline mt-2 block" }, "Back to Users List")));
792
+ }
793
+ return /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto p-4" }, /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6 mb-6" }, /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-gray-800 mb-4" }, userData.name), /* @__PURE__ */ jsx("div", { className: "user-info mb-6" }, /* @__PURE__ */ jsx("p", { className: "text-gray-600" }, /* @__PURE__ */ jsx("span", { className: "font-bold" }, "ID:"), " ", userData.id), /* @__PURE__ */ jsx("p", { className: "text-gray-600" }, /* @__PURE__ */ jsx("span", { className: "font-bold" }, "Email:"), " ", userData.email)), /* @__PURE__ */ jsx("a", { href: "/users", className: "text-blue-600 hover:underline" }, "Back to Users List")), userPosts && userPosts.length > 0 ? /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-gray-800 mb-4" }, "Posts by ", userData.name), /* @__PURE__ */ jsx("div", { className: "space-y-4" }, userPosts.map((post) => /* @__PURE__ */ jsx("div", { key: post.id, className: "border-b pb-4" }, /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold" }, post.title), /* @__PURE__ */ jsx("p", { className: "text-gray-600" }, post.content))))) : /* @__PURE__ */ jsx("div", { className: "bg-white shadow-lg rounded-lg p-6" }, /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-gray-800 mb-4" }, "Posts by ", userData.name), /* @__PURE__ */ jsx("p", { className: "text-gray-500 italic" }, "No posts found for this user.")));
794
+ }
795
+ async function getServerSideProps3({ params }) {
796
+ try {
797
+ const userId = params.id;
798
+ const [user, posts] = await Promise.all([
799
+ UserApi.getById(parseInt(userId)),
800
+ UserApi.getPosts(parseInt(userId))
801
+ ]);
802
+ if (!user) {
803
+ return {
804
+ notFound: true
805
+ };
806
+ }
807
+ return {
808
+ props: {
809
+ user,
810
+ posts
811
+ }
812
+ };
813
+ } catch (error) {
814
+ console.error(`Error fetching user ${params.id}:`, error);
815
+ return {
816
+ props: {
817
+ error: {
818
+ message: error.message,
819
+ status: error.status || 500
820
+ },
821
+ user: null,
822
+ posts: []
823
+ }
824
+ };
825
+ }
826
+ }
827
+ var init_id2 = __esm({
828
+ "src/pages/users/[id].tsx"() {
829
+ "use strict";
830
+ init_dist();
831
+ init_api();
832
+ }
833
+ });
834
+
835
+ // src/pages/wasm-demo.tsx
836
+ var wasm_demo_exports = {};
837
+ var init_wasm_demo = __esm({
838
+ "src/pages/wasm-demo.tsx"() {
839
+ "use strict";
840
+ }
841
+ });
842
+
843
+ // src/main.tsx
844
+ init_dist();
845
+
846
+ // import("./pages/**/*.tsx") in src/main.tsx
847
+ var globImport_pages_tsx = __glob({
848
+ "./pages/404.tsx": () => Promise.resolve().then(() => (init__(), __exports)),
849
+ "./pages/[id].tsx": () => Promise.resolve().then(() => (init_id(), id_exports)),
850
+ "./pages/_app.tsx": () => Promise.resolve().then(() => (init_app(), app_exports)),
851
+ "./pages/_document.tsx": () => Promise.resolve().then(() => (init_document(), document_exports)),
852
+ "./pages/_error.tsx": () => Promise.resolve().then(() => (init_error(), error_exports)),
853
+ "./pages/about.tsx": () => Promise.resolve().then(() => (init_about(), about_exports)),
854
+ "./pages/about/index.tsx": () => Promise.resolve().then(() => (init_about2(), about_exports2)),
855
+ "./pages/index.tsx": () => Promise.resolve().then(() => (init_pages(), pages_exports)),
856
+ "./pages/users.tsx": () => Promise.resolve().then(() => (init_users(), users_exports)),
857
+ "./pages/users/[id].tsx": () => Promise.resolve().then(() => (init_id2(), id_exports2)),
858
+ "./pages/wasm-demo.tsx": () => Promise.resolve().then(() => (init_wasm_demo(), wasm_demo_exports))
859
+ });
860
+
861
+ // import("./pages/**/*/index.tsx") in src/main.tsx
862
+ var globImport_pages_index_tsx = __glob({
863
+ "./pages/about/index.tsx": () => Promise.resolve().then(() => (init_about2(), about_exports2))
864
+ });
865
+
866
+ // src/main.tsx
867
+ var initialState = window.__INITIAL_STATE__ || {
868
+ route: window.location.pathname,
869
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
870
+ serverRendered: false,
871
+ data: {
872
+ users: null,
873
+ posts: null
874
+ }
875
+ };
876
+ console.log("[Client] Initial state:", initialState);
877
+ var isHydrating2 = document.getElementById("root")?.innerHTML.trim() !== "";
878
+ async function handleRouteChange(path, isPushState = true) {
879
+ try {
880
+ console.log(`[Router] Navigating to: ${path}`);
881
+ if (isPushState) {
882
+ window.history.pushState(null, "", path);
883
+ }
884
+ const normalizedPath = path === "/" ? "index" : path.replace(/^\//, "");
885
+ let Page;
886
+ try {
887
+ const module = await globImport_pages_tsx(`./pages/${normalizedPath}.tsx`);
888
+ Page = module.default;
889
+ } catch (error) {
890
+ console.warn(`[Router] Could not load page for ${path}, trying index file`);
891
+ try {
892
+ const module = await globImport_pages_index_tsx(`./pages/${normalizedPath}/index.tsx`);
893
+ Page = module.default;
894
+ } catch (innerError) {
895
+ console.error(`[Router] Failed to load page component for ${path}`);
896
+ try {
897
+ const notFoundModule = await Promise.resolve().then(() => (init__(), __exports));
898
+ Page = notFoundModule.default;
899
+ } catch (notFoundError) {
900
+ const rootElement2 = document.getElementById("root");
901
+ if (rootElement2) {
902
+ render(
903
+ /* @__PURE__ */ jsx("div", { style: { padding: "20px", maxWidth: "800px", margin: "0 auto" } }, /* @__PURE__ */ jsx("h1", null, "Page Not Found"), /* @__PURE__ */ jsx("p", null, "The page you requested could not be found."), /* @__PURE__ */ jsx("a", { href: "/", style: { color: "#0066cc" } }, "Go to Home")),
904
+ rootElement2
905
+ );
906
+ }
907
+ return;
908
+ }
909
+ }
910
+ }
911
+ let pageProps = initialState.pageProps || {};
912
+ if (Page.getServerSideProps) {
913
+ try {
914
+ const response = await fetch(`/api/__props${path}`);
915
+ if (response.ok) {
916
+ const data = await response.json();
917
+ pageProps = data.props || {};
918
+ }
919
+ } catch (error) {
920
+ console.error("[Router] Error fetching page props:", error);
921
+ }
922
+ }
923
+ const updatedState = {
924
+ ...initialState,
925
+ route: path,
926
+ pageProps
927
+ };
928
+ const rootElement = document.getElementById("root");
929
+ if (!rootElement)
930
+ return;
931
+ if (isHydrating2 && path === initialState.route) {
932
+ console.log("[Client] Hydrating server-rendered content");
933
+ hydrate(/* @__PURE__ */ jsx(Page, { ...pageProps, initialState: updatedState }), rootElement);
934
+ isHydrating2 = false;
935
+ } else {
936
+ console.log("[Client] Rendering client-side");
937
+ render(/* @__PURE__ */ jsx(Page, { ...pageProps, initialState: updatedState }), rootElement);
938
+ }
939
+ } catch (error) {
940
+ console.error("[Router] Navigation error:", error);
941
+ }
942
+ }
943
+ handleRouteChange(window.location.pathname, false);
944
+ document.addEventListener("click", (e) => {
945
+ let target = e.target;
946
+ while (target && target.tagName !== "A") {
947
+ target = target.parentElement;
948
+ if (!target)
949
+ break;
950
+ }
951
+ if (target && target.tagName === "A" && target.getAttribute("href") && target.getAttribute("href")?.startsWith("/") && !target.getAttribute("href")?.startsWith("//") && !target.getAttribute("target")) {
952
+ e.preventDefault();
953
+ const href = target.getAttribute("href") || "/";
954
+ handleRouteChange(href);
955
+ }
956
+ });
957
+ window.addEventListener("popstate", () => {
958
+ handleRouteChange(window.location.pathname, false);
959
+ });
960
+ if (typeof io !== "undefined") {
961
+ const socket = io();
962
+ socket.on("reload", () => {
963
+ console.log("[Dev] Reloading page due to file changes");
964
+ window.location.reload();
965
+ });
966
+ }
967
+ //# sourceMappingURL=main.js.map