baraqex 1.0.42 → 1.0.44

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.
@@ -1,23 +1,29 @@
1
1
  {
2
- "name": "ssr-version",
3
- "private": true,
4
- "version": "0.0.0",
2
+ "name": "ssr-template",
3
+ "version": "1.0.0",
4
+ "description": "Frontend Hamroun SSR Template",
5
5
  "type": "module",
6
+ "main": "dist/server.js",
6
7
  "scripts": {
7
- "build:client": "esbuild src/client.tsx --bundle --outfile=dist/client.js --platform=browser --format=esm",
8
- "build:server": "esbuild src/server.ts --bundle --outfile=dist/server.js --platform=node --format=esm --external:frontend-hamroun --packages=external",
9
- "build": "node esbuild.config.js",
10
- "start": "node dist/server.js"
8
+ "dev": "concurrently \"npm run build:watch\" \"npm run serve:dev\"",
9
+ "build": "npm run build:client && npm run build:server",
10
+ "build:client": "node esbuild.config.js",
11
+ "build:server": "node esbuild.config.js",
12
+ "build:watch": "node esbuild.config.js --watch",
13
+ "serve": "node dist/server.js",
14
+ "serve:dev": "nodemon dist/server.js",
15
+ "start": "npm run build && npm run serve",
16
+ "clean": "rimraf dist"
11
17
  },
12
18
  "dependencies": {
13
- "baraqex": "^1.0.40",
14
- "express": "^4.18.2",
15
- "frontend-hamroun": "latest"
19
+ "baraqex": "file:../..",
20
+ "express": "^4.18.0",
21
+ "frontend-hamroun": "^1.2.35"
16
22
  },
17
23
  "devDependencies": {
18
- "@types/express": "^4.17.17",
19
- "@types/node": "^20.5.0",
20
- "esbuild": "^0.19.12",
21
- "typescript": "^5.0.0"
24
+ "concurrently": "^8.0.0",
25
+ "esbuild": "^0.19.0",
26
+ "nodemon": "^3.0.0",
27
+ "rimraf": "^5.0.0"
22
28
  }
23
29
  }
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, useRef, useMemo } from 'baraqex/browser';
1
+ import { useState, useEffect, useRef, useMemo } from 'frontend-hamroun';
2
2
 
3
3
  // Custom hooks for better code organization
4
4
  function useTimer(initialTime = 0) {
@@ -10,7 +10,7 @@ function useTimer(initialTime = 0) {
10
10
  if (!isRunning) {
11
11
  setIsRunning(true);
12
12
  intervalRef.current = setInterval(() => {
13
- setTime((prev: number) => prev + 1);
13
+ setTime((prev) => prev + 1);
14
14
  }, 1000);
15
15
  }
16
16
  };
@@ -50,47 +50,45 @@ function useTimer(initialTime = 0) {
50
50
  function useCounter(initialValue = 0, step = 1) {
51
51
  const [count, setCount] = useState(initialValue);
52
52
 
53
- const increment = () => setCount((prev: number) => prev + step);
54
- const decrement = () => setCount((prev: number) => prev - step);
53
+ const increment = () => setCount((prev) => prev + step);
54
+ const decrement = () => setCount((prev) => prev - step);
55
55
  const reset = () => setCount(initialValue);
56
- const setValue = (value: number | ((prev: number) => number)) => setCount(value);
56
+ const setValue = (value) => setCount(typeof value === 'function' ? value : value);
57
57
 
58
58
  return { count, increment, decrement, reset, setValue };
59
59
  }
60
60
 
61
61
  function useTodos() {
62
- // Initialize with proper default array to prevent hydration issues
63
- const [todos, setTodos] = useState([
62
+ // Initialize with stable array to prevent hydration issues
63
+ const [todos, setTodos] = useState(() => [
64
64
  { id: 1, text: 'Learn Frontend Hamroun', completed: false },
65
65
  { id: 2, text: 'Build SSR app', completed: true },
66
66
  { id: 3, text: 'Deploy to production', completed: false }
67
67
  ]);
68
68
  const [filter, setFilter] = useState('all');
69
69
 
70
- const addTodo = (text: any) => {
71
- // Ensure text is a string and handle null/undefined
72
- const textString = String(text || '');
73
- if (textString.trim()) {
74
- setTodos((prev: any) => [...prev, {
70
+ const addTodo = (text) => {
71
+ const textString = String(text || '').trim();
72
+ if (textString) {
73
+ setTodos((prev) => [...prev, {
75
74
  id: Date.now(),
76
- text: textString.trim(),
75
+ text: textString,
77
76
  completed: false
78
77
  }]);
79
78
  }
80
79
  };
81
80
 
82
- const toggleTodo = (id: number) => {
83
- setTodos((prev: any[]) => prev.map((todo: { id: number; completed: any; }) =>
81
+ const toggleTodo = (id) => {
82
+ setTodos((prev) => prev.map((todo) =>
84
83
  todo.id === id ? { ...todo, completed: !todo.completed } : todo
85
84
  ));
86
85
  };
87
86
 
88
- const deleteTodo = (id: number) => {
89
- setTodos((prev: any[]) => prev.filter((todo: { id: number; }) => todo.id !== id));
87
+ const deleteTodo = (id) => {
88
+ setTodos((prev) => prev.filter((todo) => todo.id !== id));
90
89
  };
91
90
 
92
91
  const filteredTodos = useMemo(() => {
93
- // Ensure todos is always an array to prevent hydration errors
94
92
  const todoArray = Array.isArray(todos) ? todos : [];
95
93
 
96
94
  switch (filter) {
@@ -104,7 +102,6 @@ function useTodos() {
104
102
  }, [todos, filter]);
105
103
 
106
104
  const stats = useMemo(() => {
107
- // Ensure todos is always an array to prevent hydration errors
108
105
  const todoArray = Array.isArray(todos) ? todos : [];
109
106
  const total = todoArray.length;
110
107
  const completed = todoArray.filter(todo => todo.completed).length;
@@ -127,7 +124,7 @@ function useTheme() {
127
124
  const [theme, setTheme] = useState('light');
128
125
 
129
126
  const toggleTheme = () => {
130
- setTheme((prev: string) => prev === 'light' ? 'dark' : 'light');
127
+ setTheme((prev) => prev === 'light' ? 'dark' : 'light');
131
128
  };
132
129
 
133
130
  const themeColors = useMemo(() => {
@@ -152,7 +149,17 @@ function useTheme() {
152
149
  }
153
150
 
154
151
  // Todo Item Component
155
- function TodoItem({ todo, onToggle, onDelete, ...props }:any) {
152
+ function TodoItem({ todo, onToggle, onDelete }) {
153
+ const handleToggle = (e) => {
154
+ e.preventDefault();
155
+ onToggle(todo.id);
156
+ };
157
+
158
+ const handleDelete = (e) => {
159
+ e.preventDefault();
160
+ onDelete(todo.id);
161
+ };
162
+
156
163
  return (
157
164
  <div style={{
158
165
  display: 'flex',
@@ -169,12 +176,12 @@ function TodoItem({ todo, onToggle, onDelete, ...props }:any) {
169
176
  <input
170
177
  type="checkbox"
171
178
  checked={todo.completed}
172
- onChange={() => onToggle(todo.id)}
179
+ onChange={handleToggle}
173
180
  style={{ marginRight: '0.75rem' }}
174
181
  />
175
182
  <span style={{ flex: 1 }}>{todo.text}</span>
176
183
  <button
177
- onClick={() => onDelete(todo.id)}
184
+ onClick={handleDelete}
178
185
  style={{
179
186
  background: '#e74c3c',
180
187
  color: 'white',
@@ -233,23 +240,44 @@ export function App() {
233
240
 
234
241
  const [newTodo, setNewTodo] = useState('');
235
242
  const [showAdvanced, setShowAdvanced] = useState(false);
243
+ const [step, setStep] = useState(1);
236
244
  const inputRef = useRef(null);
237
245
 
238
246
  // Handle todo form submission
239
- const handleTodoSubmit = (e: { preventDefault: () => void; }) => {
247
+ const handleTodoSubmit = (e) => {
240
248
  e.preventDefault();
241
- // Ensure newTodo is a string before passing to addTodo
242
- const todoText = String(newTodo || '');
243
- addTodo(todoText);
244
- setNewTodo('');
245
- if (inputRef.current) {
246
- inputRef.current.focus();
249
+ e.stopPropagation();
250
+
251
+ const todoText = String(newTodo || '').trim();
252
+ if (todoText) {
253
+ addTodo(todoText);
254
+ setNewTodo('');
255
+
256
+ // Focus input after state update
257
+ setTimeout(() => {
258
+ if (inputRef.current) {
259
+ inputRef.current.focus();
260
+ }
261
+ }, 0);
262
+ }
263
+ };
264
+
265
+ const handleNewTodoChange = (e) => {
266
+ setNewTodo(e.target.value);
267
+ };
268
+
269
+ const handleStepChange = (e) => {
270
+ setStep(parseInt(e.target.value) || 1);
271
+ };
272
+
273
+ const handleSetValue = (e) => {
274
+ if (e.key === 'Enter') {
275
+ const value = parseInt(e.target.value) || 0;
276
+ setValue(value);
277
+ e.target.value = '';
247
278
  }
248
279
  };
249
280
 
250
- // Dynamic step value for counter
251
- const [step, setStep] = useState(1);
252
-
253
281
  useEffect(() => {
254
282
  console.log('App mounted - Frontend Hamroun SSR working!');
255
283
  return () => console.log('App unmounted');
@@ -438,7 +466,7 @@ export function App() {
438
466
  min="1"
439
467
  max="10"
440
468
  value={step}
441
- onChange={(e: { target: { value: string; }; }) => setStep(parseInt(e.target.value))}
469
+ onChange={handleStepChange}
442
470
  style={{ width: '100%' }}
443
471
  />
444
472
  </div>
@@ -479,12 +507,7 @@ export function App() {
479
507
  background: colors.bg,
480
508
  color: colors.text
481
509
  }}
482
- onKeyPress={(e: { key: string; target: { value: string; }; }) => {
483
- if (e.key === 'Enter') {
484
- setValue(parseInt(e.target.value) || 0);
485
- e.target.value = '';
486
- }
487
- }}
510
+ onKeyPress={handleSetValue}
488
511
  />
489
512
  </div>
490
513
  <div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>
@@ -637,7 +660,7 @@ export function App() {
637
660
  ref={inputRef}
638
661
  type="text"
639
662
  value={newTodo}
640
- onChange={(e: { target: { value: string | ((prev: string) => string); }; }) => setNewTodo(e.target.value)}
663
+ onChange={handleNewTodoChange}
641
664
  placeholder="Add a new todo..."
642
665
  style={{
643
666
  flex: 1,
@@ -715,7 +738,7 @@ export function App() {
715
738
  '🎉 No completed todos yet!'}
716
739
  </div>
717
740
  ) : (
718
- todos.map((todo: { id: any; }) => (
741
+ todos.map((todo) => (
719
742
  <TodoItem
720
743
  key={todo.id}
721
744
  todo={todo}
@@ -2,4 +2,3 @@ import { hydrate, jsx, render } from 'frontend-hamroun';
2
2
  import { App } from './App.js';
3
3
 
4
4
  await hydrate(jsx(App, {}), document.getElementById('root')!);
5
- await render(jsx(App, {}), document.getElementById('root')!);