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.
- package/LICENSE +21 -0
- package/README.md +129 -1513
- package/bin/cli.js +505 -144
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.client.cjs +2 -0
- package/dist/index.client.cjs.map +1 -0
- package/dist/index.client.js +26 -0
- package/dist/index.client.js.map +1 -0
- package/dist/index.js +298 -1
- package/dist/index.js.map +1 -0
- package/dist/jsx-runtime.cjs +2 -0
- package/dist/jsx-runtime.cjs.map +1 -0
- package/dist/jsx-runtime.js +93 -1
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/renderer-Bo9zkUZ_.js +52 -0
- package/dist/renderer-Bo9zkUZ_.js.map +1 -0
- package/dist/renderer-Din1y3YM.cjs +2 -0
- package/dist/renderer-Din1y3YM.cjs.map +1 -0
- package/dist/server-renderer-CqIpQ-od.cjs +2 -0
- package/dist/server-renderer-CqIpQ-od.cjs.map +1 -0
- package/dist/server-renderer-QHt45Ip2.js +255 -0
- package/dist/server-renderer-QHt45Ip2.js.map +1 -0
- package/dist/server-renderer.cjs +2 -0
- package/dist/server-renderer.cjs.map +1 -0
- package/dist/server-renderer.js +5 -1
- package/dist/server-renderer.js.map +1 -0
- package/package.json +77 -120
- package/templates/basic-app/build.js +22 -0
- package/templates/basic-app/bun.lock +196 -0
- package/templates/basic-app/dev.js +27 -0
- package/templates/basic-app/docs/rapport_pfe.aux +27 -27
- package/templates/basic-app/docs/rapport_pfe.out +10 -10
- package/templates/basic-app/docs/rapport_pfe.toc +14 -14
- package/templates/basic-app/esbuild.config.js +28 -0
- package/templates/basic-app/index.html +1 -1
- package/templates/{fullstack-app → basic-app}/package-lock.json +4185 -5094
- package/templates/basic-app/package.json +29 -28
- package/templates/basic-app/server.js +24 -0
- package/templates/basic-app/src/App.tsx +26 -0
- package/templates/basic-app/src/client.tsx +11 -0
- package/templates/basic-app/src/components/Counter.tsx +18 -0
- package/templates/basic-app/src/jsx-shim.ts +4 -0
- package/templates/basic-app/src/main.tsx +0 -1
- package/templates/basic-app/src/server.ts +52 -0
- package/templates/basic-app/tsconfig.server.json +11 -0
- package/templates/fullstack-app/build/main.css +874 -874
- package/templates/fullstack-app/build/main.css.map +7 -7
- package/templates/fullstack-app/build/main.js +967 -967
- package/templates/fullstack-app/build/main.js.map +7 -7
- package/templates/fullstack-app/public/styles.css +768 -768
- package/templates/go/example.go +99 -154
- package/templates/go-wasm-app/babel.config.js +2 -8
- package/templates/go-wasm-app/package.json +12 -21
- package/templates/go-wasm-app/public/wasm/wasm_exec.js +561 -561
- package/templates/go-wasm-app/public/wasm/wasm_exec_node.js +39 -39
- package/templates/go-wasm-app/server.js +510 -59
- package/templates/go-wasm-app/src/app.js +2 -22
- package/templates/go-wasm-app/src/wasm/example.go +75 -75
- package/templates/go-wasm-app/vite.config.js +5 -16
- package/templates/ssr-template/server.js +2 -2
- package/templates/ssr-template/vite.config.js +5 -16
- package/dist/Counter.d.ts +0 -0
- package/dist/batch/package.json +0 -16
- package/dist/client-router/package.json +0 -16
- package/dist/component/package.json +0 -16
- package/dist/context/package.json +0 -16
- package/dist/event-bus/package.json +0 -16
- package/dist/forms/package.json +0 -16
- package/dist/hooks/package.json +0 -16
- package/dist/hooks-0728361a.cjs +0 -1
- package/dist/hooks-b58f947c.js +0 -133
- package/dist/hooks.js +0 -1
- package/dist/hooks.mjs +0 -13
- package/dist/index.mjs +0 -137
- package/dist/jsx-runtime/package.json +0 -16
- package/dist/jsx-runtime.mjs +0 -64
- package/dist/lifecycle-events/package.json +0 -16
- package/dist/package.json +0 -71
- package/dist/render-component/package.json +0 -16
- package/dist/renderer/package.json +0 -16
- package/dist/renderer.js +0 -1
- package/dist/renderer.mjs +0 -27
- package/dist/router/package.json +0 -16
- package/dist/server/package.json +0 -17
- package/dist/server/src/batch.d.ts +0 -3
- package/dist/server/src/batch.js +0 -23
- package/dist/server/src/batch.js.map +0 -1
- package/dist/server/src/client-router.d.ts +0 -60
- package/dist/server/src/client-router.js +0 -210
- package/dist/server/src/client-router.js.map +0 -1
- package/dist/server/src/component.d.ts +0 -14
- package/dist/server/src/component.js +0 -106
- package/dist/server/src/component.js.map +0 -1
- package/dist/server/src/context.d.ts +0 -13
- package/dist/server/src/context.js +0 -21
- package/dist/server/src/context.js.map +0 -1
- package/dist/server/src/event-bus.d.ts +0 -23
- package/dist/server/src/event-bus.js +0 -75
- package/dist/server/src/event-bus.js.map +0 -1
- package/dist/server/src/forms.d.ts +0 -40
- package/dist/server/src/forms.js +0 -148
- package/dist/server/src/forms.js.map +0 -1
- package/dist/server/src/hooks.d.ts +0 -12
- package/dist/server/src/hooks.js +0 -170
- package/dist/server/src/hooks.js.map +0 -1
- package/dist/server/src/index.client.d.ts +0 -12
- package/dist/server/src/index.client.js +0 -14
- package/dist/server/src/index.client.js.map +0 -1
- package/dist/server/src/index.d.ts +0 -88
- package/dist/server/src/index.js +0 -79
- package/dist/server/src/index.js.map +0 -1
- package/dist/server/src/jsx-runtime/jsx-dev-runtime.d.ts +0 -1
- package/dist/server/src/jsx-runtime/jsx-dev-runtime.js +0 -2
- package/dist/server/src/jsx-runtime/jsx-dev-runtime.js.map +0 -1
- package/dist/server/src/jsx-runtime/jsx-runtime.d.ts +0 -4
- package/dist/server/src/jsx-runtime/jsx-runtime.js +0 -41
- package/dist/server/src/jsx-runtime/jsx-runtime.js.map +0 -1
- package/dist/server/src/jsx-runtime.d.ts +0 -20
- package/dist/server/src/jsx-runtime.js +0 -105
- package/dist/server/src/jsx-runtime.js.map +0 -1
- package/dist/server/src/lifecycle-events.d.ts +0 -108
- package/dist/server/src/lifecycle-events.js +0 -177
- package/dist/server/src/lifecycle-events.js.map +0 -1
- package/dist/server/src/renderComponent.d.ts +0 -13
- package/dist/server/src/renderComponent.js +0 -30
- package/dist/server/src/renderComponent.js.map +0 -1
- package/dist/server/src/renderer.d.ts +0 -2
- package/dist/server/src/renderer.js +0 -31
- package/dist/server/src/renderer.js.map +0 -1
- package/dist/server/src/router.d.ts +0 -55
- package/dist/server/src/router.js +0 -166
- package/dist/server/src/router.js.map +0 -1
- package/dist/server/src/server/api-router.d.ts +0 -15
- package/dist/server/src/server/api-router.js +0 -111
- package/dist/server/src/server/api-router.js.map +0 -1
- package/dist/server/src/server/auth.d.ts +0 -32
- package/dist/server/src/server/auth.js +0 -80
- package/dist/server/src/server/auth.js.map +0 -1
- package/dist/server/src/server/database.d.ts +0 -24
- package/dist/server/src/server/database.js +0 -135
- package/dist/server/src/server/database.js.map +0 -1
- package/dist/server/src/server/index.d.ts +0 -116
- package/dist/server/src/server/index.js +0 -508
- package/dist/server/src/server/index.js.map +0 -1
- package/dist/server/src/server/middleware.d.ts +0 -11
- package/dist/server/src/server/middleware.js +0 -46
- package/dist/server/src/server/middleware.js.map +0 -1
- package/dist/server/src/server/server.d.ts +0 -9
- package/dist/server/src/server/server.js +0 -87
- package/dist/server/src/server/server.js.map +0 -1
- package/dist/server/src/server/templates.d.ts +0 -30
- package/dist/server/src/server/templates.js +0 -208
- package/dist/server/src/server/templates.js.map +0 -1
- package/dist/server/src/server/types.d.ts +0 -38
- package/dist/server/src/server/types.js +0 -4
- package/dist/server/src/server/types.js.map +0 -1
- package/dist/server/src/server/utils.d.ts +0 -70
- package/dist/server/src/server/utils.js +0 -156
- package/dist/server/src/server/utils.js.map +0 -1
- package/dist/server/src/server/wasm.d.ts +0 -9
- package/dist/server/src/server/wasm.js +0 -117
- package/dist/server/src/server/wasm.js.map +0 -1
- package/dist/server/src/server-renderer.d.ts +0 -5
- package/dist/server/src/server-renderer.js +0 -106
- package/dist/server/src/server-renderer.js.map +0 -1
- package/dist/server/src/server-types.d.ts +0 -42
- package/dist/server/src/server-types.js +0 -6
- package/dist/server/src/server-types.js.map +0 -1
- package/dist/server/src/store.d.ts +0 -41
- package/dist/server/src/store.js +0 -99
- package/dist/server/src/store.js.map +0 -1
- package/dist/server/src/types.d.ts +0 -19
- package/dist/server/src/types.js +0 -2
- package/dist/server/src/types.js.map +0 -1
- package/dist/server/src/utils.d.ts +0 -46
- package/dist/server/src/utils.js +0 -144
- package/dist/server/src/utils.js.map +0 -1
- package/dist/server/src/vdom.d.ts +0 -8
- package/dist/server/src/vdom.js +0 -22
- package/dist/server/src/vdom.js.map +0 -1
- package/dist/server/src/wasm.d.ts +0 -36
- package/dist/server/src/wasm.js +0 -159
- package/dist/server/src/wasm.js.map +0 -1
- package/dist/server/tsconfig.server.tsbuildinfo +0 -1
- package/dist/server-renderer/package.json +0 -16
- package/dist/server-renderer.mjs +0 -64
- package/dist/store/package.json +0 -16
- package/dist/types/package.json +0 -16
- package/dist/utils/package.json +0 -16
- package/dist/vdom/package.json +0 -16
- package/dist/wasm/package.json +0 -16
- package/dist/wasm.js +0 -1
- package/dist/wasm.mjs +0 -103
- package/templates/basic-app/docs/rapport_pfe.log +0 -399
- package/templates/complete-app/client.js +0 -58
- package/templates/complete-app/package-lock.json +0 -2536
- package/templates/complete-app/package.json +0 -17
- package/templates/complete-app/pages/about.js +0 -119
- package/templates/complete-app/pages/index.js +0 -157
- package/templates/complete-app/pages/wasm-demo.js +0 -290
- package/templates/complete-app/public/client.js +0 -80
- package/templates/complete-app/public/index.html +0 -47
- package/templates/complete-app/public/styles.css +0 -579
- package/templates/complete-app/readme.md +0 -188
- package/templates/complete-app/server.js +0 -417
- package/templates/complete-app/server.ts +0 -275
- package/templates/complete-app/src/App.tsx +0 -59
- package/templates/complete-app/src/client.ts +0 -61
- package/templates/complete-app/src/client.tsx +0 -18
- package/templates/complete-app/src/pages/index.tsx +0 -51
- package/templates/complete-app/src/server.ts +0 -218
- package/templates/complete-app/tsconfig.json +0 -22
- package/templates/complete-app/tsconfig.server.json +0 -19
- package/templates/complete-app/vite.config.js +0 -57
- package/templates/complete-app/vite.config.ts +0 -30
- package/templates/go-wasm-app/build.config.js +0 -62
- package/templates/go-wasm-app/build.js +0 -218
- 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
|