frontend-hamroun 1.2.83 → 1.2.84

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,26 +1,404 @@
1
- import { useState } from 'frontend-hamroun';
1
+ import {
2
+ jsx,
3
+ useState,
4
+ useEffect,
5
+ useMemo,
6
+ useErrorBoundary,
7
+ useForm
8
+ } from 'frontend-hamroun';
2
9
 
3
- export function App() {
4
- // Initialize with a default state that works on both server and client
5
- const [count, setCount] = useState(0);
6
-
10
+ // Todo item interface
11
+ interface Todo {
12
+ id: number;
13
+ text: string;
14
+ completed: boolean;
15
+ priority: 'high' | 'medium' | 'low';
16
+ }
17
+
18
+ // Component prop interfaces
19
+ interface TodoItemProps {
20
+ todo: Todo;
21
+ onToggle: (id: number) => void;
22
+ onDelete: (id: number) => void;
23
+ }
24
+
25
+ interface ThemeToggleButtonProps {
26
+ theme: string;
27
+ onToggle: () => void;
28
+ }
29
+
30
+ interface AppFooterProps {
31
+ theme: string;
32
+ }
33
+
34
+ // Todo Item Component
35
+ function TodoItem({ todo, onToggle, onDelete }: TodoItemProps) {
7
36
  return (
8
- <div>
9
- <h1>Server-Side Rendered App</h1>
10
- <div>
37
+ <div className={`todo-item ${todo.completed ? 'completed' : ''}`}>
38
+ <input
39
+ type="checkbox"
40
+ checked={todo.completed}
41
+ onChange={() => onToggle(todo.id)}
42
+ className="todo-checkbox"
43
+ />
44
+ <span className="todo-text">{todo.text}</span>
45
+ <span className={`todo-priority priority-${todo.priority}`}>
46
+ {todo.priority === 'high' && '🔴'}
47
+ {todo.priority === 'medium' && '🟡'}
48
+ {todo.priority === 'low' && '🟢'}
49
+ {todo.priority}
50
+ </span>
51
+ <div className="todo-actions">
11
52
  <button
12
- onClick={() => setCount(count - 1)}
13
- data-action="decrement"
14
- >-</button>
15
- <span style={{ margin: '0 10px' }}>{count}</span>
16
- <button
17
- onClick={() => setCount(count + 1)}
18
- data-action="increment"
19
- >+</button>
53
+ onClick={() => onDelete(todo.id)}
54
+ className="btn btn-sm btn-danger"
55
+ title="Delete todo"
56
+ >
57
+ 🗑️
58
+ </button>
59
+ </div>
60
+ </div>
61
+ );
62
+ }
63
+
64
+ // Theme Toggle Button Component
65
+ function ThemeToggleButton({ theme, onToggle }: ThemeToggleButtonProps) {
66
+ return (
67
+ <button
68
+ onClick={onToggle}
69
+ className="btn btn-secondary theme-toggle"
70
+ title="Toggle theme"
71
+ >
72
+ {theme === 'light' ? '🌙' : '☀️'}
73
+ </button>
74
+ );
75
+ }
76
+
77
+ // App Footer Component
78
+ function AppFooter({ theme }: AppFooterProps) {
79
+ return (
80
+ <footer className="app-footer">
81
+ <div className="container">
82
+ <p>Built with Frontend Hamroun • Hooks: useState, useEffect, useMemo, useErrorBoundary, useForm</p>
83
+ <p>Theme: <strong>{theme}</strong> • Environment: <strong>Client</strong></p>
84
+ </div>
85
+ </footer>
86
+ );
87
+ }
88
+
89
+ export function App() {
90
+ // State hooks with proper typing
91
+ const [todos, setTodos] = useState<Todo[]>([
92
+ { id: 1, text: 'Learn Frontend Hamroun hooks', completed: false, priority: 'high' },
93
+ { id: 2, text: 'Build a todo app', completed: false, priority: 'medium' },
94
+ { id: 3, text: 'Master client-side concepts', completed: true, priority: 'low' }
95
+ ]);
96
+ const [theme, setTheme] = useState<string>('light');
97
+ const [taskFilter, setTaskFilter] = useState<string>('all');
98
+
99
+ // Error boundary hook
100
+ const [error, resetError] = useErrorBoundary();
101
+
102
+ // Form hook for adding new todos
103
+ const addTodoForm = useForm({
104
+ initialValues: {
105
+ text: '',
106
+ priority: 'medium' as 'high' | 'medium' | 'low'
107
+ },
108
+ validate: (values) => {
109
+ const errors: Record<string, string> = {};
110
+ if (!values.text.trim()) {
111
+ errors.text = 'Todo text is required';
112
+ }
113
+ return errors;
114
+ },
115
+ onSubmit: (values) => {
116
+ const newTodo: Todo = {
117
+ id: Date.now(),
118
+ text: values.text.trim(),
119
+ completed: false,
120
+ priority: values.priority
121
+ };
122
+ setTodos(prev => [...prev, newTodo]);
123
+ addTodoForm.resetForm();
124
+ }
125
+ });
126
+
127
+ // Mount effect
128
+ useEffect(() => {
129
+ console.log('Todo App mounted');
130
+
131
+ // Load saved todos from localStorage
132
+ const savedTodos = localStorage.getItem('todos');
133
+ const savedTheme = localStorage.getItem('theme');
134
+
135
+ if (savedTodos) {
136
+ try {
137
+ setTodos(JSON.parse(savedTodos));
138
+ } catch (e) {
139
+ console.error('Failed to load saved todos');
140
+ }
141
+ }
142
+
143
+ if (savedTheme) {
144
+ setTheme(savedTheme);
145
+ }
146
+
147
+ return () => {
148
+ console.log('Todo App unmounting');
149
+ };
150
+ }, []);
151
+
152
+ // Theme effect
153
+ useEffect(() => {
154
+ document.body.className = `theme-${theme}`;
155
+ document.documentElement.setAttribute('data-theme', theme);
156
+ localStorage.setItem('theme', theme);
157
+ }, [theme]);
158
+
159
+ // Save todos effect
160
+ useEffect(() => {
161
+ if (todos.length === 0) return;
162
+ localStorage.setItem('todos', JSON.stringify(todos));
163
+ }, [todos]);
164
+
165
+ // Memoized filtered todos
166
+ const filteredTodos = useMemo(() => {
167
+ console.log('Filtering todos - memoized computation');
168
+ return todos.filter(todo => {
169
+ if (taskFilter === 'completed') return todo.completed;
170
+ if (taskFilter === 'active') return !todo.completed;
171
+ if (taskFilter === 'high') return todo.priority === 'high';
172
+ if (taskFilter === 'medium') return todo.priority === 'medium';
173
+ if (taskFilter === 'low') return todo.priority === 'low';
174
+ return true;
175
+ });
176
+ }, [todos, taskFilter]);
177
+
178
+ // Memoized todo stats
179
+ const todoStats = useMemo(() => {
180
+ const total = todos.length;
181
+ const completed = todos.filter(t => t.completed).length;
182
+ const active = total - completed;
183
+ const highPriority = todos.filter(t => t.priority === 'high' && !t.completed).length;
184
+
185
+ return { total, completed, active, highPriority };
186
+ }, [todos]);
187
+
188
+ // Todo action handlers
189
+ const handleToggleTodo = (id: number) => {
190
+ console.log('Toggling todo:', id);
191
+ setTodos(prev => prev.map(todo =>
192
+ todo.id === id ? { ...todo, completed: !todo.completed } : todo
193
+ ));
194
+ };
195
+
196
+ const handleDeleteTodo = (id: number) => {
197
+ console.log('Deleting todo:', id);
198
+ setTodos(prev => prev.filter(todo => todo.id !== id));
199
+ };
200
+
201
+ // Event handlers
202
+ const clearCompleted = () => {
203
+ setTodos(prev => prev.filter(todo => !todo.completed));
204
+ };
205
+
206
+ const markAllComplete = () => {
207
+ setTodos(prev => prev.map(todo => ({ ...todo, completed: true })));
208
+ };
209
+
210
+ const toggleTheme = () => {
211
+ setTheme(prev => prev === 'light' ? 'dark' : 'light');
212
+ };
213
+
214
+ const simulateError = () => {
215
+ throw new Error('Simulated error for testing error boundary');
216
+ };
217
+
218
+ if (error) {
219
+ return (
220
+ <div className="error-container">
221
+ <h2>Something went wrong!</h2>
222
+ <p>{(error as Error).message}</p>
223
+ <button onClick={resetError} className="btn btn-primary">
224
+ Try Again
225
+ </button>
20
226
  </div>
21
- <script dangerouslySetInnerHTML={{
22
- __html: `window.__INITIAL_STATE__ = ${JSON.stringify({ count: 0 })};`
23
- }} />
227
+ );
228
+ }
229
+
230
+ return (
231
+ <div className={`app theme-${theme}`}>
232
+
233
+ {/* Header */}
234
+ <header className="app-header">
235
+ <div className="container">
236
+ <h1 className="app-title">
237
+ 📝 Todo App
238
+ <span className="subtitle">Built with Frontend Hamroun</span>
239
+ </h1>
240
+
241
+ <div className="header-controls">
242
+ <ThemeToggleButton theme={theme} onToggle={toggleTheme} />
243
+ <div className="stats">
244
+ <span className="stat">
245
+ Total: <strong>{todoStats.total}</strong>
246
+ </span>
247
+ <span className="stat">
248
+ Active: <strong>{todoStats.active}</strong>
249
+ </span>
250
+ <span className="stat">
251
+ Done: <strong>{todoStats.completed}</strong>
252
+ </span>
253
+ </div>
254
+ </div>
255
+ </div>
256
+ </header>
257
+
258
+ <main className="main-content">
259
+ <div className="container">
260
+
261
+ {/* Add Todo Section */}
262
+ <section className="card add-todo-section">
263
+ <h2>➕ Add New Todo</h2>
264
+
265
+ <form onSubmit={addTodoForm.handleSubmit} className="add-todo-form">
266
+ <input
267
+ type="text"
268
+ name="text"
269
+ value={addTodoForm.values.text}
270
+ onChange={addTodoForm.handleChange}
271
+ onBlur={addTodoForm.handleBlur}
272
+ placeholder="What needs to be done?"
273
+ className={`input todo-input ${addTodoForm.errors.text && addTodoForm.touched.text ? 'error' : ''}`}
274
+ />
275
+
276
+ <select
277
+ name="priority"
278
+ value={addTodoForm.values.priority}
279
+ onChange={addTodoForm.handleChange}
280
+ className="select priority-select"
281
+ >
282
+ <option value="low">🟢 Low Priority</option>
283
+ <option value="medium">🟡 Medium Priority</option>
284
+ <option value="high">🔴 High Priority</option>
285
+ </select>
286
+
287
+ <button
288
+ type="submit"
289
+ className={`btn btn-primary add-btn ${addTodoForm.isSubmitting ? 'loading' : ''}`}
290
+ disabled={addTodoForm.isSubmitting || !addTodoForm.values.text.trim()}
291
+ >
292
+ {addTodoForm.isSubmitting ? '⏳ Adding...' : '➕ Add Todo'}
293
+ </button>
294
+ </form>
295
+
296
+ {addTodoForm.errors.text && addTodoForm.touched.text && (
297
+ <div className="error-message">{addTodoForm.errors.text}</div>
298
+ )}
299
+ </section>
300
+
301
+ {/* Filters Section */}
302
+ <section className="card filters-section">
303
+ <h2>🔍 Filter Todos</h2>
304
+
305
+ <div className="filters">
306
+ {(['all', 'active', 'completed', 'high', 'medium', 'low'] as const).map(filterType => (
307
+ <button
308
+ key={filterType}
309
+ onClick={() => setTaskFilter(filterType)}
310
+ className={`btn btn-sm filter-btn ${taskFilter === filterType ? 'btn-primary' : 'btn-outline'}`}
311
+ >
312
+ {filterType === 'all' && '📋 All'}
313
+ {filterType === 'active' && '⏳ Active'}
314
+ {filterType === 'completed' && '✅ Completed'}
315
+ {filterType === 'high' && '🔴 High Priority'}
316
+ {filterType === 'medium' && '🟡 Medium Priority'}
317
+ {filterType === 'low' && '🟢 Low Priority'}
318
+ </button>
319
+ ))}
320
+ </div>
321
+
322
+ <div className="bulk-actions">
323
+ <button
324
+ onClick={markAllComplete}
325
+ className="btn btn-success btn-sm"
326
+ disabled={todoStats.active === 0}
327
+ >
328
+ ✅ Mark All Complete
329
+ </button>
330
+ <button
331
+ onClick={clearCompleted}
332
+ className="btn btn-warning btn-sm"
333
+ disabled={todoStats.completed === 0}
334
+ >
335
+ 🗑️ Clear Completed
336
+ </button>
337
+ </div>
338
+ </section>
339
+
340
+ {/* Todos List Section */}
341
+ <section className="card todos-section">
342
+ <div className="section-header">
343
+ <h2>📋 Todo List</h2>
344
+ <div className="filter-info">
345
+ Showing <strong>{filteredTodos.length}</strong> of <strong>{todoStats.total}</strong> todos
346
+ {taskFilter !== 'all' && <span className="filter-badge">{taskFilter}</span>}
347
+ </div>
348
+ </div>
349
+
350
+ <div className="todos-list">
351
+ {filteredTodos.length > 0 ? (
352
+ filteredTodos.map(todo => (
353
+ <TodoItem
354
+ key={todo.id}
355
+ todo={todo}
356
+ onToggle={handleToggleTodo}
357
+ onDelete={handleDeleteTodo}
358
+ />
359
+ ))
360
+ ) : (
361
+ <div className="empty-state">
362
+ <p>
363
+ {taskFilter === 'all' ? '🎉 No todos yet. Add one above!' :
364
+ taskFilter === 'completed' ? '📝 No completed todos yet.' :
365
+ taskFilter === 'active' ? '🎯 No active todos. Great job!' :
366
+ `🔍 No ${taskFilter} priority todos found.`}
367
+ </p>
368
+ </div>
369
+ )}
370
+ </div>
371
+ </section>
372
+
373
+ {/* Actions Section */}
374
+ <section className="card actions-section">
375
+ <h2>⚙️ Actions</h2>
376
+ <div className="action-buttons">
377
+ <button onClick={simulateError} className="btn btn-danger">
378
+ 💥 Test Error Boundary
379
+ </button>
380
+ </div>
381
+ </section>
382
+
383
+ </div>
384
+ </main>
385
+
386
+ {/* Footer */}
387
+ <AppFooter theme={theme} />
388
+
389
+ {/* Styles */}
390
+ <style>{`
391
+ /* ...existing styles... */
392
+ .error-message {
393
+ color: #e74c3c;
394
+ font-size: 0.875rem;
395
+ margin-top: 0.5rem;
396
+ }
397
+
398
+ .input.error {
399
+ border-color: #e74c3c;
400
+ }
401
+ `}</style>
24
402
  </div>
25
403
  );
26
404
  }
@@ -6,8 +6,33 @@ import {
6
6
  useErrorBoundary
7
7
  } from 'frontend-hamroun';
8
8
 
9
+ // Todo item interface
10
+ interface Todo {
11
+ id: number;
12
+ text: string;
13
+ completed: boolean;
14
+ priority: 'high' | 'medium' | 'low';
15
+ }
16
+
17
+ // Component prop interfaces
18
+ interface TodoItemProps {
19
+ todo: Todo;
20
+ onToggle: (id: number) => void;
21
+ onDelete: (id: number) => void;
22
+ }
23
+
24
+ interface ThemeToggleButtonProps {
25
+ theme: string;
26
+ onToggle: () => void;
27
+ }
28
+
29
+ interface AppFooterProps {
30
+ theme: string;
31
+ isBrowser: boolean;
32
+ }
33
+
9
34
  // Todo Item Component - simple props-based component
10
- function TodoItem({ todo, onToggle, onDelete }) {
35
+ function TodoItem({ todo, onToggle, onDelete }: TodoItemProps) {
11
36
  return (
12
37
  <div className={`todo-item ${todo.completed ? 'completed' : ''}`}>
13
38
  <input
@@ -37,7 +62,7 @@ function TodoItem({ todo, onToggle, onDelete }) {
37
62
  }
38
63
 
39
64
  // Theme Toggle Button Component
40
- function ThemeToggleButton({ theme, onToggle }) {
65
+ function ThemeToggleButton({ theme, onToggle }: ThemeToggleButtonProps) {
41
66
  return (
42
67
  <button
43
68
  onClick={onToggle}
@@ -50,7 +75,7 @@ function ThemeToggleButton({ theme, onToggle }) {
50
75
  }
51
76
 
52
77
  // App Footer Component
53
- function AppFooter({ theme, isBrowser }) {
78
+ function AppFooter({ theme, isBrowser }: AppFooterProps) {
54
79
  return (
55
80
  <footer className="app-footer">
56
81
  <div className="container">
@@ -62,17 +87,17 @@ function AppFooter({ theme, isBrowser }) {
62
87
  }
63
88
 
64
89
  export function App() {
65
- // State hooks
66
- const [todos, setTodos] = useState([
90
+ // State hooks with proper typing
91
+ const [todos, setTodos] = useState<Todo[]>([
67
92
  { id: 1, text: 'Learn Frontend Hamroun hooks', completed: false, priority: 'high' },
68
93
  { id: 2, text: 'Build a todo app', completed: false, priority: 'medium' },
69
94
  { id: 3, text: 'Master SSR concepts', completed: true, priority: 'low' }
70
95
  ]);
71
- const [newTask, setNewTask] = useState('');
72
- const [taskFilter, setTaskFilter] = useState('all');
73
- const [taskPriority, setTaskPriority] = useState('medium');
74
- const [theme, setTheme] = useState('light');
75
- const [isLoading, setIsLoading] = useState(false);
96
+ const [newTask, setNewTask] = useState<string>('');
97
+ const [taskFilter, setTaskFilter] = useState<string>('all');
98
+ const [taskPriority, setTaskPriority] = useState<'high' | 'medium' | 'low'>('medium');
99
+ const [theme, setTheme] = useState<string>('light');
100
+ const [isLoading, setIsLoading] = useState<boolean>(false);
76
101
 
77
102
  // Error boundary hook
78
103
  const [error, resetError] = useErrorBoundary();
@@ -147,22 +172,22 @@ export function App() {
147
172
  }, [todos]);
148
173
 
149
174
  // Todo action handlers
150
- const handleToggleTodo = (id) => {
175
+ const handleToggleTodo = (id: number) => {
151
176
  console.log('Toggling todo:', id);
152
177
  setTodos(prev => prev.map(todo =>
153
178
  todo.id === id ? { ...todo, completed: !todo.completed } : todo
154
179
  ));
155
180
  };
156
181
 
157
- const handleDeleteTodo = (id) => {
182
+ const handleDeleteTodo = (id: number) => {
158
183
  console.log('Deleting todo:', id);
159
184
  setTodos(prev => prev.filter(todo => todo.id !== id));
160
185
  };
161
186
 
162
- const handleAddTodo = (text, priority) => {
187
+ const handleAddTodo = (text: string, priority: 'high' | 'medium' | 'low') => {
163
188
  if (!text || !text.trim()) return;
164
189
 
165
- const newTodo = {
190
+ const newTodo: Todo = {
166
191
  id: Date.now(),
167
192
  text: text.trim(),
168
193
  completed: false,
@@ -185,7 +210,7 @@ export function App() {
185
210
  }
186
211
  };
187
212
 
188
- const handleKeyPress = (e) => {
213
+ const handleKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
189
214
  if (e.key === 'Enter') {
190
215
  addTask();
191
216
  }
@@ -211,7 +236,7 @@ export function App() {
211
236
  return (
212
237
  <div className="error-container">
213
238
  <h2>Something went wrong!</h2>
214
- <p>{error.message}</p>
239
+ <p>{(error as Error).message}</p>
215
240
  <button onClick={resetError} className="btn btn-primary">
216
241
  Try Again
217
242
  </button>
@@ -267,7 +292,7 @@ export function App() {
267
292
 
268
293
  <select
269
294
  value={taskPriority}
270
- onChange={(e) => setTaskPriority(e.target.value)}
295
+ onChange={(e) => setTaskPriority(e.target.value as 'high' | 'medium' | 'low')}
271
296
  className="select priority-select"
272
297
  disabled={isLoading}
273
298
  >
@@ -291,7 +316,7 @@ export function App() {
291
316
  <h2>🔍 Filter Todos</h2>
292
317
 
293
318
  <div className="filters">
294
- {['all', 'active', 'completed', 'high', 'medium', 'low'].map(filterType => (
319
+ {(['all', 'active', 'completed', 'high', 'medium', 'low'] as const).map(filterType => (
295
320
  <button
296
321
  key={filterType}
297
322
  onClick={() => setTaskFilter(filterType)}
@@ -1,2 +0,0 @@
1
- "use strict";const e=require("./jsx-runtime.cjs"),r=require("./server-renderer-Chs-nmJm.cjs");let n=!1;async function t(i,s){console.log("Rendering to:",s.id),r.batchUpdates((async()=>{r.prepareRender();try{r.setRenderCallback(t,i,s);const c=await e.createElement(i);n||(s.innerHTML=""),s.appendChild(c)}finally{r.finishRender()}}))}exports.createContext=function(e){return{Provider:({value:e,children:r})=>r,Consumer:({children:r})=>r(e),_id:Symbol(),useSelector:r=>r(e)}},exports.hydrate=async function(e,r){n=!0;try{await t(e,r)}finally{n=!1}},exports.render=t,exports.useContext=function(e){return e};
2
- //# sourceMappingURL=renderer-BL3gq8cW.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"renderer-BL3gq8cW.cjs","sources":["../src/renderer.ts","../src/context.ts"],"sourcesContent":["import { createElement } from './jsx-runtime.js';\r\nimport { prepareRender, finishRender, setRenderCallback } from './hooks.js';\r\nimport { batchUpdates } from './batch.js';\r\n\r\nlet isHydrating = false;\r\n\r\nexport async function hydrate(element: any, container: HTMLElement) {\r\n isHydrating = true;\r\n try {\r\n await render(element, container);\r\n } finally {\r\n isHydrating = false;\r\n }\r\n}\r\n\r\nexport async function render(element: any, container: HTMLElement) {\r\n console.log('Rendering to:', container.id);\r\n \r\n batchUpdates(async () => {\r\n const rendererId = prepareRender();\r\n try {\r\n setRenderCallback(render, element, container);\r\n const domNode = await createElement(element);\r\n \r\n if (!isHydrating) {\r\n container.innerHTML = '';\r\n }\r\n container.appendChild(domNode);\r\n \r\n } finally {\r\n finishRender();\r\n }\r\n });\r\n}\r\n","\r\n\r\nconst contexts = new Map<symbol, any>();\r\nlet currentRender: Function | null = null;\r\n\r\nexport interface Context<T> {\r\n Provider: (props: { value: T; children?: any }) => any;\r\n Consumer: (props: { children: (value: T) => any }) => any;\r\n _id: symbol;\r\n useSelector: <S>(selector: (state: T) => S) => S;\r\n}\r\n\r\nexport function createContext<T>(defaultValue: T): Context<T> {\r\n const context = {\r\n Provider: ({ value, children }: { value: T, children?: any }) => {\r\n return children;\r\n },\r\n Consumer: ({ children }: { children: (value: T) => any }) => {\r\n return children(defaultValue);\r\n },\r\n _id: Symbol(),\r\n useSelector: <S>(selector: (state: T) => S) => {\r\n return selector(defaultValue);\r\n }\r\n };\r\n\r\n return context;\r\n}\r\n\r\nexport function useContext<T>(context: any): T {\r\n return context;\r\n}\r\n"],"names":["isHydrating","async","render","element","container","console","log","id","batchUpdates","prepareRender","domNode","createElement","innerHTML","appendChild","finishRender","defaultValue","Provider","value","children","Consumer","_id","Symbol","useSelector","selector","context"],"mappings":"8FAIA,IAAIA,GAAc,EAWIC,eAAAC,EAAOC,EAAcC,GACjCC,QAAAC,IAAI,gBAAiBF,EAAUG,IAEvCC,EAAAA,cAAaP,UACQQ,EAAAA,gBACf,wBACgBP,EAAQC,EAASC,GAC7B,MAAAM,QAAgBC,EAAAA,cAAcR,GAE/BH,IACHI,EAAUQ,UAAY,IAExBR,EAAUS,YAAYH,EAAO,CAE7B,QACaI,gBAAA,IAGnB,uBCrBO,SAA0BC,GAcxB,MAbS,CACdC,SAAU,EAAGC,QAAOC,cACXA,EAETC,SAAU,EAAGD,cACJA,EAASH,GAElBK,IAAKC,SACLC,YAAiBC,GACRA,EAASR,GAKtB,kBDrBsBd,eAAQE,EAAcC,GAC5BJ,GAAA,EACV,UACIE,EAAOC,EAASC,EAAS,CAC/B,QACcJ,GAAA,CAAA,CAElB,sCCgBO,SAAuBwB,GACrB,OAAAA,CACT"}
@@ -1,52 +0,0 @@
1
- import { createElement } from "./jsx-runtime.js";
2
- import { b as batchUpdates, p as prepareRender, s as setRenderCallback, f as finishRender } from "./server-renderer-C1WXH-zV.js";
3
- function createContext(defaultValue) {
4
- const context = {
5
- Provider: ({ value, children }) => {
6
- return children;
7
- },
8
- Consumer: ({ children }) => {
9
- return children(defaultValue);
10
- },
11
- _id: Symbol(),
12
- useSelector: (selector) => {
13
- return selector(defaultValue);
14
- }
15
- };
16
- return context;
17
- }
18
- function useContext(context) {
19
- return context;
20
- }
21
- let isHydrating = false;
22
- async function hydrate(element, container) {
23
- isHydrating = true;
24
- try {
25
- await render(element, container);
26
- } finally {
27
- isHydrating = false;
28
- }
29
- }
30
- async function render(element, container) {
31
- console.log("Rendering to:", container.id);
32
- batchUpdates(async () => {
33
- const rendererId = prepareRender();
34
- try {
35
- setRenderCallback(render, element, container);
36
- const domNode = await createElement(element);
37
- if (!isHydrating) {
38
- container.innerHTML = "";
39
- }
40
- container.appendChild(domNode);
41
- } finally {
42
- finishRender();
43
- }
44
- });
45
- }
46
- export {
47
- createContext as c,
48
- hydrate as h,
49
- render as r,
50
- useContext as u
51
- };
52
- //# sourceMappingURL=renderer-Dyy-o05F.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"renderer-Dyy-o05F.js","sources":["../src/context.ts","../src/renderer.ts"],"sourcesContent":["\r\n\r\nconst contexts = new Map<symbol, any>();\r\nlet currentRender: Function | null = null;\r\n\r\nexport interface Context<T> {\r\n Provider: (props: { value: T; children?: any }) => any;\r\n Consumer: (props: { children: (value: T) => any }) => any;\r\n _id: symbol;\r\n useSelector: <S>(selector: (state: T) => S) => S;\r\n}\r\n\r\nexport function createContext<T>(defaultValue: T): Context<T> {\r\n const context = {\r\n Provider: ({ value, children }: { value: T, children?: any }) => {\r\n return children;\r\n },\r\n Consumer: ({ children }: { children: (value: T) => any }) => {\r\n return children(defaultValue);\r\n },\r\n _id: Symbol(),\r\n useSelector: <S>(selector: (state: T) => S) => {\r\n return selector(defaultValue);\r\n }\r\n };\r\n\r\n return context;\r\n}\r\n\r\nexport function useContext<T>(context: any): T {\r\n return context;\r\n}\r\n","import { createElement } from './jsx-runtime.js';\r\nimport { prepareRender, finishRender, setRenderCallback } from './hooks.js';\r\nimport { batchUpdates } from './batch.js';\r\n\r\nlet isHydrating = false;\r\n\r\nexport async function hydrate(element: any, container: HTMLElement) {\r\n isHydrating = true;\r\n try {\r\n await render(element, container);\r\n } finally {\r\n isHydrating = false;\r\n }\r\n}\r\n\r\nexport async function render(element: any, container: HTMLElement) {\r\n console.log('Rendering to:', container.id);\r\n \r\n batchUpdates(async () => {\r\n const rendererId = prepareRender();\r\n try {\r\n setRenderCallback(render, element, container);\r\n const domNode = await createElement(element);\r\n \r\n if (!isHydrating) {\r\n container.innerHTML = '';\r\n }\r\n container.appendChild(domNode);\r\n \r\n } finally {\r\n finishRender();\r\n }\r\n });\r\n}\r\n"],"names":[],"mappings":";;AAYO,SAAS,cAAiB,cAA6B;AAC5D,QAAM,UAAU;AAAA,IACd,UAAU,CAAC,EAAE,OAAO,eAA6C;AACxD,aAAA;AAAA,IACT;AAAA,IACA,UAAU,CAAC,EAAE,eAAgD;AAC3D,aAAO,SAAS,YAAY;AAAA,IAC9B;AAAA,IACA,KAAK,OAAO;AAAA,IACZ,aAAa,CAAI,aAA8B;AAC7C,aAAO,SAAS,YAAY;AAAA,IAAA;AAAA,EAEhC;AAEO,SAAA;AACT;AAEO,SAAS,WAAc,SAAiB;AACtC,SAAA;AACT;AC3BA,IAAI,cAAc;AAEI,eAAA,QAAQ,SAAc,WAAwB;AACpD,gBAAA;AACV,MAAA;AACI,UAAA,OAAO,SAAS,SAAS;AAAA,EAAA,UAC/B;AACc,kBAAA;AAAA,EAAA;AAElB;AAEsB,eAAA,OAAO,SAAc,WAAwB;AACzD,UAAA,IAAI,iBAAiB,UAAU,EAAE;AAEzC,eAAa,YAAY;AACvB,UAAM,aAAa,cAAc;AAC7B,QAAA;AACgB,wBAAA,QAAQ,SAAS,SAAS;AACtC,YAAA,UAAU,MAAM,cAAc,OAAO;AAE3C,UAAI,CAAC,aAAa;AAChB,kBAAU,YAAY;AAAA,MAAA;AAExB,gBAAU,YAAY,OAAO;AAAA,IAAA,UAE7B;AACa,mBAAA;AAAA,IAAA;AAAA,EACf,CACD;AACH;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"server-renderer-C1WXH-zV.js","sources":["../src/batch.ts","../src/hooks.ts","../src/server-renderer.ts"],"sourcesContent":["export let isBatching = false;\r\nconst queue: Function[] = [];\r\n\r\nexport function batchUpdates(fn: Function) {\r\n if (isBatching) {\r\n queue.push(fn);\r\n return;\r\n }\r\n\r\n isBatching = true;\r\n try {\r\n fn();\r\n while (queue.length > 0) {\r\n const nextFn = queue.shift();\r\n nextFn?.();\r\n }\r\n } finally {\r\n isBatching = false;\r\n }\r\n}\r\n\r\nexport function getIsBatching() {\r\n return isBatching;\r\n}\r\n","import { createElement } from './jsx-runtime.js';\r\nimport { batchUpdates, isBatching } from './batch.js';\r\nimport { diff } from './vdom.js';\r\nimport { createContext, useContext } from './context.js';\r\n\r\n// Current render ID counter\r\nlet currentRender = 0;\r\nlet isServerRender = false;\r\n\r\n// State storage\r\nconst states = new Map<number, any[]>();\r\nconst stateIndices = new Map<number, number>();\r\nconst effects = new Map<number, any[]>();\r\nconst memos = new Map<number, any[]>();\r\nconst refs = new Map<number, any[]>();\r\n\r\n// Server-side rendering detection\r\nconst isServer = typeof window === 'undefined';\r\nconst serverStates = new Map<number, Map<number, any>>();\r\n\r\n// Rendering callbacks\r\nlet globalRenderCallback: any = null;\r\nlet globalContainer: any = null;\r\nlet currentElement: any = null;\r\n\r\nexport function setRenderCallback(callback: any, element: any, container: any): void {\r\n globalRenderCallback = callback;\r\n globalContainer = container;\r\n currentElement = element;\r\n}\r\n\r\nexport function prepareRender(isSSR: boolean = false): number {\r\n currentRender++;\r\n isServerRender = isSSR;\r\n stateIndices.set(currentRender, 0);\r\n return currentRender;\r\n}\r\n\r\nexport function finishRender(): void {\r\n if (isServer || isServerRender) {\r\n serverStates.delete(currentRender);\r\n }\r\n isServerRender = false;\r\n currentRender = 0;\r\n}\r\n\r\nexport function useState<T>(initial: T): [T, (newValue: T | ((prev: T) => T)) => void] {\r\n if (!currentRender && !isServerRender) {\r\n throw new Error(\"useState must be called within a render\");\r\n }\r\n\r\n // Handle server-side rendering separately\r\n if (isServer || isServerRender) {\r\n if (!serverStates.has(currentRender)) {\r\n serverStates.set(currentRender, new Map());\r\n }\r\n const componentState = serverStates.get(currentRender)!;\r\n const index = stateIndices.get(currentRender) || 0;\r\n \r\n if (!componentState.has(index)) {\r\n componentState.set(index, initial);\r\n }\r\n \r\n const state = componentState.get(index);\r\n // In SSR, setState is a no-op\r\n const setState = (_newValue: T | ((prev: T) => T)) => {};\r\n \r\n stateIndices.set(currentRender, index + 1);\r\n return [state, setState];\r\n }\r\n\r\n // Client-side implementation\r\n if (!states.has(currentRender)) {\r\n states.set(currentRender, []);\r\n }\r\n \r\n const componentStates = states.get(currentRender)!;\r\n const index = stateIndices.get(currentRender) || 0;\r\n \r\n if (index >= componentStates.length) {\r\n componentStates.push(initial);\r\n }\r\n \r\n const state = componentStates[index];\r\n \r\n const setState = (newValue: T | ((prev: T) => T)) => {\r\n const nextValue = typeof newValue === 'function'\r\n ? (newValue as ((prev: T) => T))(componentStates[index])\r\n : newValue;\r\n \r\n if (componentStates[index] === nextValue) return;\r\n \r\n componentStates[index] = nextValue;\r\n \r\n if (isBatching) {\r\n batchUpdates(() => rerender(currentRender));\r\n } else {\r\n rerender(currentRender);\r\n }\r\n };\r\n \r\n stateIndices.set(currentRender, index + 1);\r\n return [state, setState];\r\n}\r\n\r\nexport function useEffect(callback: () => void | (() => void), deps?: any[]): void {\r\n if (!currentRender && !isServerRender) throw new Error(\"useEffect must be called within a render\");\r\n\r\n // Skip effects on server\r\n if (isServer || isServerRender) {\r\n const effectIndex = stateIndices.get(currentRender) || 0;\r\n stateIndices.set(currentRender, effectIndex + 1);\r\n return;\r\n }\r\n\r\n const effectIndex = stateIndices.get(currentRender) || 0;\r\n \r\n if (!effects.has(currentRender)) {\r\n effects.set(currentRender, []);\r\n }\r\n \r\n const componentEffects = effects.get(currentRender)!;\r\n const prevEffect = componentEffects[effectIndex];\r\n \r\n if (!prevEffect || !deps || !prevEffect.deps || deps.some((dep, i) => dep !== prevEffect.deps[i])) {\r\n if (prevEffect?.cleanup) {\r\n prevEffect.cleanup();\r\n }\r\n \r\n // Schedule effect execution after render is complete\r\n queueMicrotask(() => {\r\n const cleanup = callback() || undefined;\r\n componentEffects[effectIndex] = { cleanup, deps: deps || [] };\r\n });\r\n }\r\n \r\n stateIndices.set(currentRender, effectIndex + 1);\r\n}\r\n\r\nexport function useMemo<T>(factory: () => T, deps?: any[]): T {\r\n if (!currentRender && !isServerRender) throw new Error(\"useMemo must be called within a render\");\r\n \r\n const memoIndex = stateIndices.get(currentRender) || 0;\r\n \r\n if (!memos.has(currentRender)) {\r\n memos.set(currentRender, []);\r\n }\r\n \r\n const componentMemos = memos.get(currentRender)!;\r\n const prevMemo = componentMemos[memoIndex];\r\n \r\n if (!prevMemo || (deps && deps.some((dep, i) => !Object.is(dep, prevMemo.deps[i])))) {\r\n const value = factory();\r\n componentMemos[memoIndex] = { value, deps: deps || [] };\r\n stateIndices.set(currentRender, memoIndex + 1);\r\n return value;\r\n }\r\n \r\n stateIndices.set(currentRender, memoIndex + 1);\r\n return prevMemo.value;\r\n}\r\n\r\nexport function useRef<T>(initial: T): { current: T } {\r\n if (!currentRender && !isServerRender) throw new Error(\"useRef must be called within a render\");\r\n \r\n const refIndex = stateIndices.get(currentRender) || 0;\r\n \r\n if (!refs.has(currentRender)) {\r\n refs.set(currentRender, []);\r\n }\r\n \r\n const componentRefs = refs.get(currentRender)!;\r\n \r\n if (refIndex >= componentRefs.length) {\r\n const ref = { current: initial };\r\n componentRefs.push(ref);\r\n stateIndices.set(currentRender, refIndex + 1);\r\n return ref;\r\n }\r\n \r\n const ref = componentRefs[refIndex];\r\n stateIndices.set(currentRender, refIndex + 1);\r\n return ref;\r\n}\r\n\r\nasync function rerender(rendererId: number): Promise<void> {\r\n try {\r\n // Clean up effects\r\n const componentEffects = effects.get(rendererId);\r\n if (componentEffects) {\r\n componentEffects.forEach(effect => {\r\n if (effect.cleanup) effect.cleanup();\r\n });\r\n effects.set(rendererId, []);\r\n }\r\n \r\n // Trigger re-render\r\n if (globalRenderCallback && globalContainer && currentElement) {\r\n await globalRenderCallback(currentElement, globalContainer);\r\n }\r\n } catch (error) {\r\n console.error('Error during rerender:', error);\r\n }\r\n}\r\n\r\nexport function useErrorBoundary() {\r\n const [error, setError] = useState(null);\r\n return [error, () => setError(null)];\r\n}\r\n\r\n// Re-export from context to match index.js\r\nexport { createContext, useContext };\r\n","import { VNode } from './types.js';\r\nimport { prepareRender, finishRender } from './hooks.js';\r\n\r\nexport async function renderToString(element: any): Promise<string> {\r\n const renderId = prepareRender(true); // Mark as SSR\r\n \r\n try {\r\n const html = await renderNodeToString(element);\r\n return html;\r\n } finally {\r\n finishRender();\r\n }\r\n}\r\n\r\nasync function renderNodeToString(node: any): Promise<string> {\r\n // Handle null, undefined, boolean\r\n if (node == null || typeof node === 'boolean') {\r\n return '';\r\n }\r\n\r\n // Handle primitives\r\n if (typeof node === 'string' || typeof node === 'number') {\r\n return escapeHtml(String(node));\r\n }\r\n\r\n // Handle arrays\r\n if (Array.isArray(node)) {\r\n const results = await Promise.all(node.map(child => renderNodeToString(child)));\r\n return results.join('');\r\n }\r\n\r\n // Handle objects with type and props (React-like elements)\r\n if (node && typeof node === 'object' && 'type' in node) {\r\n const { type, props = {} } = node;\r\n\r\n // Handle function components\r\n if (typeof type === 'function') {\r\n try {\r\n const result = await type(props);\r\n return await renderNodeToString(result);\r\n } catch (error:any) {\r\n console.error('Error rendering component:', error);\r\n return `<!-- Error rendering component: ${error.message} -->`;\r\n }\r\n }\r\n\r\n // Handle DOM elements\r\n if (typeof type === 'string') {\r\n return await renderDOMElement(type, props);\r\n }\r\n }\r\n\r\n // Fallback for other objects\r\n if (typeof node === 'object') {\r\n return escapeHtml(JSON.stringify(node));\r\n }\r\n\r\n return escapeHtml(String(node));\r\n}\r\n\r\nasync function renderDOMElement(tagName: string, props: any): Promise<string> {\r\n const { children, ...attrs } = props;\r\n \r\n // Self-closing tags\r\n const voidElements = new Set([\r\n 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',\r\n 'link', 'meta', 'param', 'source', 'track', 'wbr'\r\n ]);\r\n\r\n // Build attributes string\r\n const attributeString = Object.entries(attrs)\r\n .filter(([key, value]) => {\r\n // Filter out React-specific props and event handlers\r\n if (key.startsWith('on') || key === 'key' || key === 'ref') return false;\r\n if (value == null || value === false) return false;\r\n return true;\r\n })\r\n .map(([key, value]) => {\r\n // Handle className -> class\r\n if (key === 'className') key = 'class';\r\n \r\n // Handle boolean attributes\r\n if (value === true) return key;\r\n \r\n // Handle style objects\r\n if (key === 'style' && typeof value === 'object' && value !== null) {\r\n const styleString = Object.entries(value)\r\n .map(([prop, val]) => `${kebabCase(prop)}:${val}`)\r\n .join(';');\r\n return `style=\"${escapeHtml(styleString)}\"`;\r\n }\r\n \r\n return `${key}=\"${escapeHtml(String(value))}\"`;\r\n })\r\n .join(' ');\r\n\r\n const openTag = `<${tagName}${attributeString ? ' ' + attributeString : ''}>`;\r\n \r\n // Self-closing elements\r\n if (voidElements.has(tagName)) {\r\n return openTag.slice(0, -1) + '/>';\r\n }\r\n\r\n // Elements with children\r\n const closeTag = `</${tagName}>`;\r\n \r\n if (children != null) {\r\n const childrenString = await renderNodeToString(children);\r\n return openTag + childrenString + closeTag;\r\n }\r\n \r\n return openTag + closeTag;\r\n}\r\n\r\nfunction escapeHtml(text: string): string {\r\n const htmlEscapes: Record<string, string> = {\r\n '&': '&amp;',\r\n '<': '&lt;',\r\n '>': '&gt;',\r\n '\"': '&quot;',\r\n \"'\": '&#x27;',\r\n '/': '&#x2F;'\r\n };\r\n \r\n return text.replace(/[&<>\"'/]/g, (match) => htmlEscapes[match]);\r\n}\r\n\r\nfunction kebabCase(str: string): string {\r\n return str.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);\r\n}\r\n"],"names":["index","state","setState","effectIndex","ref"],"mappings":"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"}