baraqex 1.0.58 → 1.0.59
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/dist/index.js +27 -3
- package/dist/index.js.map +3 -3
- package/package.json +9 -15
- package/templates/basic-app/package-lock.json +6832 -4234
- package/templates/basic-app/package.json +29 -36
- package/templates/basic-app/src/main.tsx +189 -228
- package/templates/basic-app/vite.config.ts +13 -78
|
@@ -1,36 +1,29 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"type": "module",
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"buffer": "^6.0.3",
|
|
31
|
-
"stream-browserify": "^3.0.0",
|
|
32
|
-
"util": "^0.12.5",
|
|
33
|
-
"events": "^3.3.0",
|
|
34
|
-
"querystring-es3": "^0.2.1"
|
|
35
|
-
}
|
|
36
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "finall",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "tsc && vite build",
|
|
9
|
+
"preview": "vite preview",
|
|
10
|
+
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
11
|
+
"lint:fix": "eslint src --ext ts,tsx --fix"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"baraqex": "^1.0.58",
|
|
15
|
+
"frontend-hamroun": "^1.2.35"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
19
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
20
|
+
"autoprefixer": "^10.4.14",
|
|
21
|
+
"eslint": "^8.45.0",
|
|
22
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
23
|
+
"eslint-plugin-react-refresh": "^0.4.3",
|
|
24
|
+
"postcss": "^8.4.27",
|
|
25
|
+
"tailwindcss": "^3.3.3",
|
|
26
|
+
"typescript": "^5.0.0",
|
|
27
|
+
"vite": "^4.4.9"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx, render, useState, useEffect, useMemo, useRef, useErrorBoundary, createContext, useContext } from 'baraqex/browser';
|
|
1
|
+
import { render, useState, useEffect, useMemo, useRef, useErrorBoundary, createContext, useContext } from 'baraqex';
|
|
3
2
|
import './main.css';
|
|
4
3
|
|
|
5
4
|
// JSX type declarations
|
|
@@ -11,224 +10,10 @@ declare global {
|
|
|
11
10
|
}
|
|
12
11
|
}
|
|
13
12
|
|
|
14
|
-
// Create a theme context
|
|
13
|
+
// Create a theme context with proper typing
|
|
15
14
|
const ThemeContext = createContext<'light' | 'dark'>('light');
|
|
16
15
|
|
|
17
|
-
//
|
|
18
|
-
function Counter() {
|
|
19
|
-
const [count, setCount] = useState(0);
|
|
20
|
-
const renderCount = useRef(0);
|
|
21
|
-
|
|
22
|
-
useEffect(() => {
|
|
23
|
-
renderCount.current += 1;
|
|
24
|
-
}, [count]);
|
|
25
|
-
|
|
26
|
-
const doubled = useMemo(() => count * 2, [count]);
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<div className="card max-w-sm mx-auto">
|
|
30
|
-
<h2 className="text-2xl font-bold text-gray-800 mb-4 text-center">
|
|
31
|
-
Counter Example
|
|
32
|
-
</h2>
|
|
33
|
-
<div className="text-center">
|
|
34
|
-
<div className="text-4xl font-bold text-primary-600 mb-6">
|
|
35
|
-
{count}
|
|
36
|
-
</div>
|
|
37
|
-
<div className="mb-4">
|
|
38
|
-
<p className="text-sm text-gray-600 mb-2">Doubled: {doubled}</p>
|
|
39
|
-
<p className="text-sm text-gray-600">Renders: {renderCount.current}</p>
|
|
40
|
-
</div>
|
|
41
|
-
<div className="space-x-2">
|
|
42
|
-
<button
|
|
43
|
-
onClick={() => setCount(count + 1)}
|
|
44
|
-
className="btn btn-primary"
|
|
45
|
-
>
|
|
46
|
-
Increment
|
|
47
|
-
</button>
|
|
48
|
-
<button
|
|
49
|
-
onClick={() => setCount(count - 1)}
|
|
50
|
-
className="btn btn-secondary"
|
|
51
|
-
>
|
|
52
|
-
Decrement
|
|
53
|
-
</button>
|
|
54
|
-
<button
|
|
55
|
-
onClick={() => setCount(0)}
|
|
56
|
-
className="btn btn-danger"
|
|
57
|
-
>
|
|
58
|
-
Reset
|
|
59
|
-
</button>
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Todo Item Component
|
|
67
|
-
function TodoItem({ todo, onToggle, onDelete }: {
|
|
68
|
-
todo: { id: number; text: string; completed: boolean };
|
|
69
|
-
onToggle: (id: number) => void;
|
|
70
|
-
onDelete: (id: number) => void;
|
|
71
|
-
}) {
|
|
72
|
-
return (
|
|
73
|
-
<div className={`flex items-center justify-between p-3 rounded-md border transition-colors ${
|
|
74
|
-
todo.completed ? 'bg-green-50 border-green-200' : 'bg-gray-50 border-gray-200'
|
|
75
|
-
}`}>
|
|
76
|
-
<div className="flex items-center space-x-3">
|
|
77
|
-
<button
|
|
78
|
-
onClick={() => onToggle(todo.id)}
|
|
79
|
-
className={`w-5 h-5 rounded border-2 flex items-center justify-center transition-colors ${
|
|
80
|
-
todo.completed
|
|
81
|
-
? 'bg-green-500 border-green-500 text-white'
|
|
82
|
-
: 'border-gray-300 hover:border-green-500'
|
|
83
|
-
}`}
|
|
84
|
-
>
|
|
85
|
-
{todo.completed && '✓'}
|
|
86
|
-
</button>
|
|
87
|
-
<span className={`transition-colors ${todo.completed ? 'line-through text-gray-500' : 'text-gray-800'}`}>
|
|
88
|
-
{todo.text}
|
|
89
|
-
</span>
|
|
90
|
-
</div>
|
|
91
|
-
<button
|
|
92
|
-
onClick={() => onDelete(todo.id)}
|
|
93
|
-
className="text-red-500 hover:text-red-700 px-2 py-1 rounded transition-colors"
|
|
94
|
-
>
|
|
95
|
-
Delete
|
|
96
|
-
</button>
|
|
97
|
-
</div>
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Todo List Component
|
|
102
|
-
function TodoList() {
|
|
103
|
-
const [todos, setTodos] = useState<{ id: number; text: string; completed: boolean }[]>([
|
|
104
|
-
{ id: 1, text: 'Learn Baraqex Framework', completed: false },
|
|
105
|
-
{ id: 2, text: 'Build something awesome', completed: false },
|
|
106
|
-
{ id: 3, text: 'Deploy to production', completed: false }
|
|
107
|
-
]);
|
|
108
|
-
const [newTodo, setNewTodo] = useState('');
|
|
109
|
-
|
|
110
|
-
const addTodo = () => {
|
|
111
|
-
if (newTodo.trim()) {
|
|
112
|
-
setTodos([...todos, {
|
|
113
|
-
id: Date.now(),
|
|
114
|
-
text: newTodo.trim(),
|
|
115
|
-
completed: false
|
|
116
|
-
}]);
|
|
117
|
-
setNewTodo('');
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
const toggleTodo = (id: number) => {
|
|
122
|
-
setTodos(todos.map((todo: { id: number; completed: any; }) =>
|
|
123
|
-
todo.id === id ? { ...todo, completed: !todo.completed } : todo
|
|
124
|
-
));
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
const deleteTodo = (id: number) => {
|
|
128
|
-
setTodos(todos.filter((todo: { id: number; }) => todo.id !== id));
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const completedCount = todos.filter((todo: { completed: any; }) => todo.completed).length;
|
|
132
|
-
const totalCount = todos.length;
|
|
133
|
-
|
|
134
|
-
return (
|
|
135
|
-
<div className="card max-w-md mx-auto">
|
|
136
|
-
<h2 className="text-2xl font-bold text-gray-800 mb-4 text-center">
|
|
137
|
-
Todo List
|
|
138
|
-
</h2>
|
|
139
|
-
|
|
140
|
-
<div className="mb-4">
|
|
141
|
-
<div className="flex space-x-2 mb-2">
|
|
142
|
-
<input
|
|
143
|
-
type="text"
|
|
144
|
-
value={newTodo}
|
|
145
|
-
onChange={(e: { target: { value: any; }; }) => setNewTodo(e.target.value)}
|
|
146
|
-
onKeyPress={(e: { key: string; }) => e.key === 'Enter' && addTodo()}
|
|
147
|
-
placeholder="Add a new todo..."
|
|
148
|
-
className="input flex-1"
|
|
149
|
-
/>
|
|
150
|
-
<button
|
|
151
|
-
onClick={addTodo}
|
|
152
|
-
className="btn btn-primary"
|
|
153
|
-
>
|
|
154
|
-
Add
|
|
155
|
-
</button>
|
|
156
|
-
</div>
|
|
157
|
-
<div className="text-sm text-gray-600 text-center">
|
|
158
|
-
{completedCount} of {totalCount} completed
|
|
159
|
-
</div>
|
|
160
|
-
</div>
|
|
161
|
-
|
|
162
|
-
<div className="space-y-2">
|
|
163
|
-
{todos.map((todo: { id: Number; text?: string; completed?: boolean; }) => (
|
|
164
|
-
<TodoItem
|
|
165
|
-
key={todo.id}
|
|
166
|
-
todo={todo}
|
|
167
|
-
onToggle={toggleTodo}
|
|
168
|
-
onDelete={deleteTodo}
|
|
169
|
-
/>
|
|
170
|
-
))}
|
|
171
|
-
</div>
|
|
172
|
-
|
|
173
|
-
{todos.length === 0 && (
|
|
174
|
-
<p className="text-gray-500 text-center py-4">
|
|
175
|
-
No todos yet. Add one above!
|
|
176
|
-
</p>
|
|
177
|
-
)}
|
|
178
|
-
</div>
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Error boundary test component
|
|
183
|
-
function BuggyComponent() {
|
|
184
|
-
const [shouldError, setShouldError] = useState(false);
|
|
185
|
-
|
|
186
|
-
if (shouldError) {
|
|
187
|
-
throw new Error("Test error from BuggyComponent");
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return (
|
|
191
|
-
<div className="card max-w-sm mx-auto">
|
|
192
|
-
<h3 className="text-lg font-semibold text-gray-800 mb-4 text-center">
|
|
193
|
-
Error Boundary Test
|
|
194
|
-
</h3>
|
|
195
|
-
<p className="text-sm text-gray-600 mb-4 text-center">
|
|
196
|
-
Click the button below to test error handling
|
|
197
|
-
</p>
|
|
198
|
-
<div className="text-center">
|
|
199
|
-
<button
|
|
200
|
-
onClick={() => setShouldError(true)}
|
|
201
|
-
className="btn btn-danger"
|
|
202
|
-
>
|
|
203
|
-
Trigger Error
|
|
204
|
-
</button>
|
|
205
|
-
</div>
|
|
206
|
-
</div>
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Context test component
|
|
211
|
-
function ContextConsumer() {
|
|
212
|
-
const theme = useContext(ThemeContext);
|
|
213
|
-
|
|
214
|
-
return (
|
|
215
|
-
<div className="card max-w-sm mx-auto">
|
|
216
|
-
<h3 className="text-lg font-semibold text-gray-800 mb-4 text-center">
|
|
217
|
-
Context API Test
|
|
218
|
-
</h3>
|
|
219
|
-
<div className={`p-4 rounded-md border text-center ${
|
|
220
|
-
theme === 'dark' ? 'border-gray-600 bg-gray-700 text-white' : 'border-gray-300 bg-gray-50'
|
|
221
|
-
}`}>
|
|
222
|
-
<p className="text-sm mb-2">Current theme: <strong>{theme}</strong></p>
|
|
223
|
-
<p className="text-xs text-gray-500">
|
|
224
|
-
Theme is provided by Context API
|
|
225
|
-
</p>
|
|
226
|
-
</div>
|
|
227
|
-
</div>
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Main App Component
|
|
16
|
+
// Main App Component - Fix the tab rendering logic
|
|
232
17
|
function App() {
|
|
233
18
|
const [activeTab, setActiveTab] = useState('counter');
|
|
234
19
|
const [theme, setTheme] = useState<'light' | 'dark'>('light');
|
|
@@ -238,6 +23,16 @@ function App() {
|
|
|
238
23
|
document.title = `Baraqex Demo - ${activeTab.charAt(0).toUpperCase() + activeTab.slice(1)}`;
|
|
239
24
|
}, [activeTab]);
|
|
240
25
|
|
|
26
|
+
// Add debug logging for theme changes
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
console.log('Theme changed to:', theme);
|
|
29
|
+
}, [theme]);
|
|
30
|
+
|
|
31
|
+
// Add debug logging for tab changes
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
console.log('Active tab changed to:', activeTab);
|
|
34
|
+
}, [activeTab]);
|
|
35
|
+
|
|
241
36
|
if (error) {
|
|
242
37
|
return (
|
|
243
38
|
<div className="min-h-screen bg-gradient-to-br from-red-50 to-red-100 flex items-center justify-center">
|
|
@@ -258,6 +53,26 @@ function App() {
|
|
|
258
53
|
);
|
|
259
54
|
}
|
|
260
55
|
|
|
56
|
+
// Function to render the current tab content
|
|
57
|
+
const renderTabContent = () => {
|
|
58
|
+
console.log('Rendering tab content for:', activeTab);
|
|
59
|
+
|
|
60
|
+
switch (activeTab) {
|
|
61
|
+
case 'counter':
|
|
62
|
+
console.log('Rendering Counter component');
|
|
63
|
+
return <Counter />;
|
|
64
|
+
case 'error':
|
|
65
|
+
console.log('Rendering BuggyComponent');
|
|
66
|
+
return <BuggyComponent />;
|
|
67
|
+
case 'context':
|
|
68
|
+
console.log('Rendering ContextConsumer component');
|
|
69
|
+
return <ContextConsumer />;
|
|
70
|
+
default:
|
|
71
|
+
console.log('Unknown tab, rendering Counter as fallback');
|
|
72
|
+
return <Counter />;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
261
76
|
return (
|
|
262
77
|
<ThemeContext.Provider value={theme}>
|
|
263
78
|
<div className={`min-h-screen transition-colors ${
|
|
@@ -341,7 +156,11 @@ function App() {
|
|
|
341
156
|
|
|
342
157
|
<div className="mt-8 text-center">
|
|
343
158
|
<button
|
|
344
|
-
onClick={() =>
|
|
159
|
+
onClick={() => {
|
|
160
|
+
const newTheme = theme === 'light' ? 'dark' : 'light';
|
|
161
|
+
console.log('Theme toggle clicked, changing from', theme, 'to', newTheme);
|
|
162
|
+
setTheme(newTheme);
|
|
163
|
+
}}
|
|
345
164
|
className={`btn ${theme === 'dark' ? 'bg-yellow-400 text-gray-900 hover:bg-yellow-300' : 'bg-gray-800 text-white hover:bg-gray-700'}`}
|
|
346
165
|
>
|
|
347
166
|
🌙 Toggle {theme === 'light' ? 'Dark' : 'Light'} Mode
|
|
@@ -355,13 +174,15 @@ function App() {
|
|
|
355
174
|
<div className="bg-white rounded-lg shadow-sm p-1 flex space-x-1 overflow-x-auto">
|
|
356
175
|
{[
|
|
357
176
|
{ id: 'counter', label: 'Counter', icon: '🔢' },
|
|
358
|
-
{ id: 'todos', label: 'Todo List', icon: '✅' },
|
|
359
177
|
{ id: 'error', label: 'Error Test', icon: '🚨' },
|
|
360
178
|
{ id: 'context', label: 'Context', icon: '🔄' }
|
|
361
179
|
].map(tab => (
|
|
362
180
|
<button
|
|
363
181
|
key={tab.id}
|
|
364
|
-
onClick={() =>
|
|
182
|
+
onClick={() => {
|
|
183
|
+
console.log('Tab clicked:', tab.id, 'current activeTab:', activeTab);
|
|
184
|
+
setActiveTab(tab.id);
|
|
185
|
+
}}
|
|
365
186
|
className={`px-4 py-2 rounded-md transition-colors whitespace-nowrap ${
|
|
366
187
|
activeTab === tab.id
|
|
367
188
|
? 'bg-primary-500 text-white'
|
|
@@ -375,12 +196,9 @@ function App() {
|
|
|
375
196
|
</div>
|
|
376
197
|
</div>
|
|
377
198
|
|
|
378
|
-
{/* Tab Content */}
|
|
199
|
+
{/* Tab Content - Use the function to render content */}
|
|
379
200
|
<div className="flex justify-center mb-12">
|
|
380
|
-
{
|
|
381
|
-
{activeTab === 'todos' && <TodoList />}
|
|
382
|
-
{activeTab === 'error' && <BuggyComponent />}
|
|
383
|
-
{activeTab === 'context' && <ContextConsumer />}
|
|
201
|
+
{renderTabContent()}
|
|
384
202
|
</div>
|
|
385
203
|
|
|
386
204
|
{/* Footer */}
|
|
@@ -462,5 +280,148 @@ function App() {
|
|
|
462
280
|
);
|
|
463
281
|
}
|
|
464
282
|
|
|
465
|
-
//
|
|
466
|
-
|
|
283
|
+
// Simple Counter Component with Tailwind styles - Fixed hooks
|
|
284
|
+
function Counter() {
|
|
285
|
+
// Initialize with proper values and ensure hooks work correctly
|
|
286
|
+
const [count, setCount] = useState(0);
|
|
287
|
+
const renderCount = useRef(0);
|
|
288
|
+
|
|
289
|
+
useEffect(() => {
|
|
290
|
+
renderCount.current = (renderCount.current || 0) + 1;
|
|
291
|
+
console.log('Counter effect running, count:', count, 'renders:', renderCount.current);
|
|
292
|
+
}, [count]);
|
|
293
|
+
|
|
294
|
+
// Ensure count is a number before calculation
|
|
295
|
+
const doubled = useMemo(() => {
|
|
296
|
+
const numCount = typeof count === 'number' ? count : 0;
|
|
297
|
+
console.log('Calculating doubled for count:', numCount);
|
|
298
|
+
return numCount * 2;
|
|
299
|
+
}, [count]);
|
|
300
|
+
|
|
301
|
+
// Add debug logging
|
|
302
|
+
console.log('Counter render - count:', count, 'doubled:', doubled, 'renders:', renderCount.current);
|
|
303
|
+
|
|
304
|
+
return (
|
|
305
|
+
<div className="card max-w-sm mx-auto">
|
|
306
|
+
<h2 className="text-2xl font-bold text-gray-800 mb-4 text-center">
|
|
307
|
+
Counter Example
|
|
308
|
+
</h2>
|
|
309
|
+
<div className="text-center">
|
|
310
|
+
<div className="text-4xl font-bold text-primary-600 mb-6">
|
|
311
|
+
{typeof count === 'number' ? count : 0}
|
|
312
|
+
</div>
|
|
313
|
+
<div className="mb-4">
|
|
314
|
+
<p className="text-sm text-gray-600 mb-2">
|
|
315
|
+
Doubled: {typeof doubled === 'number' ? doubled : 'Error'}
|
|
316
|
+
</p>
|
|
317
|
+
<p className="text-sm text-gray-600">
|
|
318
|
+
Renders: {renderCount.current || 0}
|
|
319
|
+
</p>
|
|
320
|
+
</div>
|
|
321
|
+
<div className="space-x-2">
|
|
322
|
+
<button
|
|
323
|
+
onClick={() => {
|
|
324
|
+
console.log('Increment clicked, current count:', count);
|
|
325
|
+
const newCount = (typeof count === 'number' ? count : 0) + 1;
|
|
326
|
+
console.log('Setting new count:', newCount);
|
|
327
|
+
setCount(newCount);
|
|
328
|
+
}}
|
|
329
|
+
className="btn btn-primary"
|
|
330
|
+
>
|
|
331
|
+
Increment
|
|
332
|
+
</button>
|
|
333
|
+
<button
|
|
334
|
+
onClick={() => {
|
|
335
|
+
console.log('Decrement clicked, current count:', count);
|
|
336
|
+
const newCount = (typeof count === 'number' ? count : 0) - 1;
|
|
337
|
+
console.log('Setting new count:', newCount);
|
|
338
|
+
setCount(newCount);
|
|
339
|
+
}}
|
|
340
|
+
className="btn btn-secondary"
|
|
341
|
+
>
|
|
342
|
+
Decrement
|
|
343
|
+
</button>
|
|
344
|
+
<button
|
|
345
|
+
onClick={() => {
|
|
346
|
+
console.log('Reset clicked');
|
|
347
|
+
setCount(0);
|
|
348
|
+
}}
|
|
349
|
+
className="btn btn-danger"
|
|
350
|
+
>
|
|
351
|
+
Reset
|
|
352
|
+
</button>
|
|
353
|
+
</div>
|
|
354
|
+
</div>
|
|
355
|
+
</div>
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Error boundary test component with debugging
|
|
360
|
+
function BuggyComponent() {
|
|
361
|
+
console.log('BuggyComponent rendering...');
|
|
362
|
+
|
|
363
|
+
const [shouldError, setShouldError] = useState(false);
|
|
364
|
+
|
|
365
|
+
if (shouldError) {
|
|
366
|
+
throw new Error("Test error from BuggyComponent");
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return (
|
|
370
|
+
<div className="card max-w-sm mx-auto">
|
|
371
|
+
<h3 className="text-lg font-semibold text-gray-800 mb-4 text-center">
|
|
372
|
+
Error Boundary Test
|
|
373
|
+
</h3>
|
|
374
|
+
<p className="text-sm text-gray-600 mb-4 text-center">
|
|
375
|
+
Click the button below to test error handling
|
|
376
|
+
</p>
|
|
377
|
+
<div className="text-center">
|
|
378
|
+
<button
|
|
379
|
+
onClick={() => {
|
|
380
|
+
console.log('Triggering error...');
|
|
381
|
+
setShouldError(true);
|
|
382
|
+
}}
|
|
383
|
+
className="btn btn-danger"
|
|
384
|
+
>
|
|
385
|
+
Trigger Error
|
|
386
|
+
</button>
|
|
387
|
+
</div>
|
|
388
|
+
</div>
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Context test component - fixed to properly extract theme value
|
|
393
|
+
function ContextConsumer() {
|
|
394
|
+
const theme = useContext(ThemeContext);
|
|
395
|
+
|
|
396
|
+
// Extract the actual theme value - handle both direct values and wrapped objects
|
|
397
|
+
const actualTheme = typeof theme === 'object' && theme !== null
|
|
398
|
+
? (theme as any).value || 'light'
|
|
399
|
+
: (typeof theme === 'string' ? theme : 'light');
|
|
400
|
+
|
|
401
|
+
console.log('Context consumer - raw theme:', theme, 'actual theme:', actualTheme);
|
|
402
|
+
|
|
403
|
+
return (
|
|
404
|
+
<div className="card max-w-sm mx-auto">
|
|
405
|
+
<h3 className="text-lg font-semibold text-gray-800 mb-4 text-center">
|
|
406
|
+
Context API Test
|
|
407
|
+
</h3>
|
|
408
|
+
<div className={`p-4 rounded-md border text-center ${
|
|
409
|
+
actualTheme === 'dark' ? 'border-gray-600 bg-gray-700 text-white' : 'border-gray-300 bg-gray-50'
|
|
410
|
+
}`}>
|
|
411
|
+
<p className="text-sm mb-2">Current theme: <strong>{actualTheme}</strong></p>
|
|
412
|
+
<p className="text-xs text-gray-500">
|
|
413
|
+
Theme is provided by Context API
|
|
414
|
+
</p>
|
|
415
|
+
</div>
|
|
416
|
+
</div>
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Mount the app with null check and debug logging
|
|
421
|
+
const rootElement = document.getElementById('root');
|
|
422
|
+
if (rootElement) {
|
|
423
|
+
console.log('Mounting app to root element');
|
|
424
|
+
render(<App />, rootElement);
|
|
425
|
+
} else {
|
|
426
|
+
console.error('Root element not found');
|
|
427
|
+
}
|
|
@@ -3,119 +3,54 @@ import { defineConfig } from 'vite';
|
|
|
3
3
|
export default defineConfig({
|
|
4
4
|
esbuild: {
|
|
5
5
|
jsxFactory: 'jsx',
|
|
6
|
-
jsxFragment: 'Fragment'
|
|
6
|
+
jsxFragment: 'Fragment',
|
|
7
|
+
jsxInject: `import { jsx } from 'baraqex'`
|
|
7
8
|
},
|
|
8
9
|
define: {
|
|
9
10
|
// Ensure we're in browser mode
|
|
10
11
|
'process.env.NODE_ENV': JSON.stringify('development'),
|
|
11
12
|
'typeof window': '"object"',
|
|
12
|
-
'typeof process': '"undefined"',
|
|
13
13
|
'global': 'globalThis'
|
|
14
14
|
},
|
|
15
15
|
optimizeDeps: {
|
|
16
16
|
// Exclude ALL server-only dependencies from browser bundle
|
|
17
17
|
exclude: [
|
|
18
|
+
// Only exclude actual server modules that would cause issues
|
|
18
19
|
'express',
|
|
19
20
|
'mysql2',
|
|
20
|
-
'mysql2/promise',
|
|
21
21
|
'mongodb',
|
|
22
22
|
'pg',
|
|
23
23
|
'bcryptjs',
|
|
24
24
|
'jsonwebtoken',
|
|
25
|
-
'cors'
|
|
26
|
-
'fs',
|
|
27
|
-
'path',
|
|
28
|
-
'crypto',
|
|
29
|
-
'http',
|
|
30
|
-
'url',
|
|
31
|
-
'fs/promises',
|
|
32
|
-
'child_process',
|
|
33
|
-
'os',
|
|
34
|
-
'stream',
|
|
35
|
-
'util',
|
|
36
|
-
'events',
|
|
37
|
-
'buffer',
|
|
38
|
-
'querystring',
|
|
39
|
-
'https',
|
|
40
|
-
'net',
|
|
41
|
-
'tls',
|
|
42
|
-
'zlib'
|
|
25
|
+
'cors'
|
|
43
26
|
],
|
|
44
27
|
// Force include browser-safe modules
|
|
45
28
|
include: [
|
|
46
29
|
'frontend-hamroun'
|
|
47
30
|
]
|
|
48
31
|
},
|
|
49
|
-
build: {
|
|
50
|
-
rollupOptions: {
|
|
51
|
-
external: [
|
|
52
|
-
// Mark ALL server-only modules as external
|
|
53
|
-
'express',
|
|
54
|
-
'mysql2',
|
|
55
|
-
'mysql2/promise',
|
|
56
|
-
'mongodb',
|
|
57
|
-
'pg',
|
|
58
|
-
'bcryptjs',
|
|
59
|
-
'jsonwebtoken',
|
|
60
|
-
'cors',
|
|
61
|
-
'fs',
|
|
62
|
-
'path',
|
|
63
|
-
'crypto',
|
|
64
|
-
'http',
|
|
65
|
-
'url',
|
|
66
|
-
'fs/promises',
|
|
67
|
-
'child_process',
|
|
68
|
-
'os',
|
|
69
|
-
'stream',
|
|
70
|
-
'util',
|
|
71
|
-
'events',
|
|
72
|
-
'buffer',
|
|
73
|
-
'querystring',
|
|
74
|
-
'https',
|
|
75
|
-
'net',
|
|
76
|
-
'tls',
|
|
77
|
-
'zlib'
|
|
78
|
-
]
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
32
|
resolve: {
|
|
82
33
|
alias: {
|
|
83
|
-
//
|
|
84
|
-
'crypto': 'crypto-browserify',
|
|
85
|
-
'path': 'path-browserify',
|
|
86
|
-
'buffer': 'buffer',
|
|
87
|
-
'stream': 'stream-browserify',
|
|
88
|
-
'util': 'util',
|
|
89
|
-
'events': 'events',
|
|
90
|
-
'querystring': 'querystring-es3',
|
|
91
|
-
// Block server modules completely
|
|
34
|
+
// Only alias problematic Node.js built-ins, not everything
|
|
92
35
|
'fs': false,
|
|
36
|
+
'path': false,
|
|
93
37
|
'http': false,
|
|
94
38
|
'https': false,
|
|
95
39
|
'url': false,
|
|
96
|
-
'fs/promises': false,
|
|
97
|
-
'child_process': false,
|
|
98
40
|
'os': false,
|
|
99
|
-
'
|
|
100
|
-
'tls': false,
|
|
101
|
-
'zlib': false,
|
|
102
|
-
// Prevent any server modules from being loaded
|
|
103
|
-
'express': false,
|
|
104
|
-
'mysql2': false,
|
|
105
|
-
'mysql2/promise': false,
|
|
106
|
-
'mongodb': false,
|
|
107
|
-
'pg': false,
|
|
108
|
-
'bcryptjs': false,
|
|
109
|
-
'jsonwebtoken': false,
|
|
110
|
-
'cors': false
|
|
41
|
+
'crypto': false
|
|
111
42
|
},
|
|
112
43
|
// Only use browser-compatible fields
|
|
113
|
-
mainFields: ['browser', 'module', 'main']
|
|
114
|
-
conditions: ['browser']
|
|
44
|
+
mainFields: ['browser', 'module', 'main']
|
|
115
45
|
},
|
|
116
46
|
server: {
|
|
117
47
|
hmr: {
|
|
118
48
|
overlay: true
|
|
49
|
+
},
|
|
50
|
+
fs: {
|
|
51
|
+
// Allow serving files from the project root
|
|
52
|
+
allow: ['..']
|
|
119
53
|
}
|
|
120
54
|
}
|
|
55
|
+
|
|
121
56
|
});
|