frontend-hamroun 1.1.54 → 1.1.55
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/README.md +149 -329
- package/dist/hooks.d.ts +0 -10
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +87 -199
- package/dist/index.mjs.map +1 -1
- package/dist/server-renderer.d.ts +1 -2
- package/dist/templates/default.d.ts +1 -7
- package/dist/types.d.ts +6 -3
- package/package.json +1 -2
- package/templates/basic-app/src/main.tsx +6 -9
- package/templates/ssr-template/package.json +5 -6
- package/templates/ssr-template/src/App.tsx +20 -116
- package/templates/ssr-template/src/client.tsx +2 -32
- package/templates/ssr-template/src/server.ts +33 -73
- package/templates/ssr-template/tsconfig.json +4 -6
- package/templates/ssr-template/vite.config.ts +8 -9
- package/templates/ssr-template/public/styles.css +0 -49
package/README.md
CHANGED
@@ -1,420 +1,240 @@
|
|
1
|
-
#
|
1
|
+
# Your Package Name
|
2
2
|
|
3
|
-
A lightweight
|
3
|
+
A lightweight Virtual DOM and hooks implementation with JSX support.
|
4
4
|
|
5
|
-
##
|
5
|
+
## Installation
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
- 📱 Router with dynamic routes
|
11
|
-
- 🔄 Context API
|
12
|
-
- 🛠️ TypeScript support
|
13
|
-
- 📦 Small bundle size (~12KB gzipped)
|
14
|
-
- ⚡ Code splitting support
|
7
|
+
```bash
|
8
|
+
npm install your-package-name
|
9
|
+
```
|
15
10
|
|
16
|
-
##
|
11
|
+
## Quick Start
|
12
|
+
|
13
|
+
Create a new project using:
|
17
14
|
|
18
15
|
```bash
|
19
|
-
|
16
|
+
npx create-frontend-app my-app
|
20
17
|
# or
|
21
|
-
|
18
|
+
npm create frontend-app@latest my-app
|
22
19
|
```
|
20
|
+
Then:
|
23
21
|
|
24
|
-
|
22
|
+
```bash
|
23
|
+
cd my-app
|
24
|
+
npm install
|
25
|
+
npm run dev
|
26
|
+
```
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
```jsx
|
31
|
+
import { render, useState } from 'your-package-name';
|
28
32
|
|
29
|
-
function
|
33
|
+
function App() {
|
30
34
|
const [count, setCount] = useState(0);
|
31
|
-
|
32
35
|
return (
|
33
|
-
<
|
34
|
-
Count: {count}
|
35
|
-
|
36
|
+
<div>
|
37
|
+
<h1>Count: {count}</h1>
|
38
|
+
<button onClick={() => setCount(count + 1)}>Increment</button>
|
39
|
+
</div>
|
36
40
|
);
|
37
41
|
}
|
38
42
|
|
39
|
-
render(<
|
43
|
+
render(<App />, document.getElementById('root'));
|
40
44
|
```
|
41
45
|
|
42
|
-
##
|
46
|
+
## Features
|
43
47
|
|
44
|
-
|
48
|
+
- Virtual DOM with efficient diffing
|
49
|
+
- Hooks (useState, useEffect, useMemo, useRef)
|
50
|
+
- Context API
|
51
|
+
- Batch updates
|
52
|
+
- Hydration support
|
53
|
+
|
54
|
+
## Hooks
|
55
|
+
|
56
|
+
### useState
|
57
|
+
Manages component state.
|
45
58
|
|
46
59
|
```tsx
|
47
|
-
|
60
|
+
const [state, setState] = useState(initialValue);
|
61
|
+
```
|
48
62
|
|
49
|
-
|
50
|
-
|
63
|
+
### useEffect
|
64
|
+
Handles side effects in components.
|
51
65
|
|
52
|
-
|
66
|
+
```tsx
|
53
67
|
useEffect(() => {
|
54
68
|
// Effect code
|
55
69
|
return () => {
|
56
70
|
// Cleanup code
|
57
71
|
};
|
58
72
|
}, [dependencies]);
|
59
|
-
|
60
|
-
// Memoization
|
61
|
-
const memoizedValue = useMemo(() => computeExpensiveValue(deps), [deps]);
|
62
73
|
```
|
63
74
|
|
64
|
-
###
|
75
|
+
### useMemo
|
76
|
+
Memoizes expensive computations.
|
65
77
|
|
66
78
|
```tsx
|
67
|
-
|
68
|
-
|
69
|
-
function App() {
|
70
|
-
const router = useRouter();
|
71
|
-
|
72
|
-
return (
|
73
|
-
<div>
|
74
|
-
<nav>
|
75
|
-
<Link href="/">Home</Link>
|
76
|
-
<Link href="/about">About</Link>
|
77
|
-
</nav>
|
78
|
-
{router.pathname === '/' && <Home />}
|
79
|
-
{router.pathname === '/about' && <About />}
|
80
|
-
</div>
|
81
|
-
);
|
82
|
-
}
|
79
|
+
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
|
83
80
|
```
|
84
81
|
|
85
|
-
###
|
82
|
+
### useRef
|
83
|
+
Creates a mutable reference.
|
86
84
|
|
87
85
|
```tsx
|
88
|
-
|
89
|
-
|
90
|
-
const ThemeContext = createContext('light');
|
91
|
-
|
92
|
-
function ThemedButton() {
|
93
|
-
const theme = useContext(ThemeContext);
|
94
|
-
return <button className={theme}>Click me</button>;
|
95
|
-
}
|
86
|
+
const ref = useRef(initialValue);
|
96
87
|
```
|
97
88
|
|
98
|
-
|
89
|
+
### useErrorBoundary
|
90
|
+
Handles component errors.
|
99
91
|
|
100
|
-
### Quick Start
|
101
92
|
```tsx
|
102
|
-
|
103
|
-
import { renderToString } from 'frontend-hamroun';
|
104
|
-
|
105
|
-
const html = await renderToString(<App />, {
|
106
|
-
title: 'My SSR App',
|
107
|
-
description: 'A server-rendered application',
|
108
|
-
scripts: ['/client.js'],
|
109
|
-
initialState: {
|
110
|
-
user: { id: 1, name: 'John' }
|
111
|
-
}
|
112
|
-
});
|
93
|
+
const [error, resetError] = useErrorBoundary();
|
113
94
|
```
|
114
95
|
|
115
|
-
|
116
|
-
|
117
|
-
1. Server Setup:
|
118
|
-
```typescript
|
119
|
-
// server.ts
|
120
|
-
import express from 'express';
|
121
|
-
import { renderToString } from 'frontend-hamroun';
|
122
|
-
|
123
|
-
const app = express();
|
124
|
-
|
125
|
-
app.get('*', async (req, res) => {
|
126
|
-
try {
|
127
|
-
const html = await renderToString(<App />, {
|
128
|
-
title: 'My App',
|
129
|
-
description: 'Server-rendered app',
|
130
|
-
scripts: ['/client.js'],
|
131
|
-
styles: ['/styles.css'],
|
132
|
-
meta: {
|
133
|
-
'og:title': 'My App',
|
134
|
-
'theme-color': '#ffffff'
|
135
|
-
},
|
136
|
-
initialState: {
|
137
|
-
url: req.url,
|
138
|
-
user: req.user
|
139
|
-
},
|
140
|
-
bodyAttrs: { class: 'app-root' },
|
141
|
-
htmlAttrs: { lang: 'en' }
|
142
|
-
});
|
143
|
-
|
144
|
-
res.send(html);
|
145
|
-
} catch (error) {
|
146
|
-
res.status(500).send('Server Error');
|
147
|
-
}
|
148
|
-
});
|
149
|
-
```
|
96
|
+
## Context API
|
150
97
|
|
151
|
-
|
152
|
-
```typescript
|
153
|
-
// client.tsx
|
154
|
-
import { hydrate } from 'frontend-hamroun';
|
155
|
-
|
156
|
-
// Type-safe state access
|
157
|
-
declare global {
|
158
|
-
interface Window {
|
159
|
-
__INITIAL_STATE__: {
|
160
|
-
url: string;
|
161
|
-
user?: { id: number; name: string };
|
162
|
-
}
|
163
|
-
}
|
164
|
-
}
|
165
|
-
|
166
|
-
const { url, user } = window.__INITIAL_STATE__;
|
98
|
+
Create and use shared state across components.
|
167
99
|
|
168
|
-
|
169
|
-
|
100
|
+
```tsx
|
101
|
+
const ThemeContext = createContext('light');
|
170
102
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
scripts?: string[];
|
178
|
-
styles?: string[];
|
179
|
-
meta?: Record<string, string>;
|
180
|
-
initialState?: any;
|
181
|
-
bodyAttrs?: Record<string, string>;
|
182
|
-
htmlAttrs?: Record<string, string>;
|
103
|
+
function App() {
|
104
|
+
return (
|
105
|
+
<ThemeContext.Provider value="dark">
|
106
|
+
<Child />
|
107
|
+
</ThemeContext.Provider>
|
108
|
+
);
|
183
109
|
}
|
184
|
-
```
|
185
110
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
- 🎨 Customizable templates
|
191
|
-
- 📱 Meta tags for SEO
|
192
|
-
- 🛡️ XSS protection
|
193
|
-
- 🚀 Streaming support
|
194
|
-
- 📦 Asset optimization
|
195
|
-
- 🔍 Error handling
|
196
|
-
|
197
|
-
### Best Practices
|
198
|
-
|
199
|
-
1. State Management:
|
200
|
-
```typescript
|
201
|
-
// Shared types between server and client
|
202
|
-
interface AppState {
|
203
|
-
url: string;
|
204
|
-
user?: UserData;
|
205
|
-
settings: AppSettings;
|
111
|
+
function Child() {
|
112
|
+
const theme = useContext(ThemeContext);
|
113
|
+
// Or use selector for performance
|
114
|
+
const isDark = ThemeContext.useSelector(theme => theme === 'dark');
|
206
115
|
}
|
207
|
-
|
208
|
-
// Server
|
209
|
-
const state: AppState = {
|
210
|
-
url: req.url,
|
211
|
-
user: await getUser(req),
|
212
|
-
settings: await getSettings()
|
213
|
-
};
|
214
|
-
|
215
|
-
// Client
|
216
|
-
const { url, user, settings } = window.__INITIAL_STATE__ as AppState;
|
217
116
|
```
|
218
117
|
|
219
|
-
|
220
|
-
```typescript
|
221
|
-
// Server-side error boundary
|
222
|
-
try {
|
223
|
-
const html = await renderToString(<App />, options);
|
224
|
-
res.send(html);
|
225
|
-
} catch (error) {
|
226
|
-
const errorHtml = await renderToString(
|
227
|
-
<ErrorPage error={error} />,
|
228
|
-
{ title: 'Error' }
|
229
|
-
);
|
230
|
-
res.status(500).send(errorHtml);
|
231
|
-
}
|
232
|
-
```
|
118
|
+
## Performance Optimization
|
233
119
|
|
234
|
-
|
235
|
-
|
236
|
-
// Caching
|
237
|
-
const cached = await cache.get(cacheKey);
|
238
|
-
if (cached) return cached;
|
239
|
-
|
240
|
-
const html = await renderToString(<App />, {
|
241
|
-
...options,
|
242
|
-
scripts: [
|
243
|
-
{ src: '/client.js', async: true, defer: true }
|
244
|
-
]
|
245
|
-
});
|
120
|
+
### Batch Updates
|
121
|
+
Group multiple state updates together.
|
246
122
|
|
247
|
-
|
248
|
-
|
123
|
+
```tsx
|
124
|
+
import { batchUpdates } from 'your-package-name';
|
249
125
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
// Server-side rendering with customization
|
254
|
-
const html = await renderToString(<App />, {
|
255
|
-
title: 'My App',
|
256
|
-
description: 'Server-rendered application',
|
257
|
-
scripts: ['/assets/client.js'],
|
258
|
-
styles: ['/assets/styles.css'],
|
259
|
-
meta: {
|
260
|
-
'theme-color': '#ffffff',
|
261
|
-
'og:title': 'My App',
|
262
|
-
'og:description': 'My awesome app'
|
263
|
-
},
|
264
|
-
initialState: {
|
265
|
-
user: { name: 'John' }
|
266
|
-
},
|
267
|
-
bodyAttrs: { class: 'dark-mode' },
|
268
|
-
htmlAttrs: { lang: 'en', dir: 'ltr' }
|
126
|
+
batchUpdates(() => {
|
127
|
+
setValue1(newValue1);
|
128
|
+
setValue2(newValue2);
|
269
129
|
});
|
270
130
|
```
|
271
131
|
|
272
|
-
###
|
273
|
-
|
274
|
-
```typescript
|
275
|
-
import express from 'express';
|
276
|
-
import { renderToString } from 'frontend-hamroun';
|
277
|
-
|
278
|
-
const app = express();
|
279
|
-
|
280
|
-
app.get('*', async (req, res) => {
|
281
|
-
const initialState = {
|
282
|
-
url: req.url,
|
283
|
-
user: req.user // From your auth middleware
|
284
|
-
};
|
285
|
-
|
286
|
-
const html = await renderToString(<App />, {
|
287
|
-
title: 'My App',
|
288
|
-
scripts: ['/client.js'],
|
289
|
-
initialState
|
290
|
-
});
|
132
|
+
### Component Memoization
|
133
|
+
Prevent unnecessary re-renders.
|
291
134
|
|
292
|
-
|
293
|
-
|
135
|
+
```tsx
|
136
|
+
const MemoizedComponent = useMemo(() => (
|
137
|
+
<ExpensiveComponent prop={value} />
|
138
|
+
), [value]);
|
294
139
|
```
|
295
140
|
|
296
|
-
|
297
|
-
|
298
|
-
```typescript
|
299
|
-
import { hydrate } from 'frontend-hamroun';
|
300
|
-
|
301
|
-
// Access the server-provided state
|
302
|
-
declare global {
|
303
|
-
interface Window {
|
304
|
-
__INITIAL_STATE__: any;
|
305
|
-
}
|
306
|
-
}
|
141
|
+
## Server-Side Rendering
|
307
142
|
|
308
|
-
|
143
|
+
```tsx
|
144
|
+
import { hydrate } from 'your-package-name';
|
309
145
|
|
310
|
-
|
311
|
-
|
312
|
-
document.getElementById('root')!
|
313
|
-
);
|
146
|
+
// On the client
|
147
|
+
hydrate(<App />, document.getElementById('root'));
|
314
148
|
```
|
315
149
|
|
316
|
-
##
|
317
|
-
|
318
|
-
Create a new project:
|
150
|
+
## Event Handling
|
319
151
|
|
320
|
-
```
|
321
|
-
|
152
|
+
```tsx
|
153
|
+
function Button() {
|
154
|
+
return (
|
155
|
+
<button
|
156
|
+
onClick={(e) => handleClick(e)}
|
157
|
+
onMouseOver={(e) => handleHover(e)}
|
158
|
+
>
|
159
|
+
Click me
|
160
|
+
</button>
|
161
|
+
);
|
162
|
+
}
|
322
163
|
```
|
323
164
|
|
324
|
-
##
|
325
|
-
|
326
|
-
- Initial bundle: 12KB gzipped
|
327
|
-
- Dynamic imports for code splitting
|
328
|
-
- Automatic batching for state updates
|
329
|
-
- Efficient virtual DOM diffing
|
330
|
-
|
331
|
-
## Security
|
332
|
-
|
333
|
-
- XSS protection
|
334
|
-
- Content Security Policy support
|
335
|
-
- Type-safe props
|
336
|
-
- Secure by default
|
165
|
+
## Styling
|
337
166
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
- Hot Module Replacement
|
349
|
-
- Developer tools extension
|
350
|
-
- Error boundaries
|
351
|
-
- Performance monitoring
|
352
|
-
|
353
|
-
## Advanced Features
|
354
|
-
|
355
|
-
### Template Customization
|
356
|
-
```typescript
|
357
|
-
interface TemplateOptions {
|
358
|
-
title: string;
|
359
|
-
description?: string;
|
360
|
-
scripts?: string[];
|
361
|
-
styles?: string[];
|
362
|
-
meta?: Record<string, string>;
|
363
|
-
initialState?: any;
|
364
|
-
bodyAttrs?: Record<string, string>;
|
365
|
-
htmlAttrs?: Record<string, string>;
|
167
|
+
```tsx
|
168
|
+
function StyledComponent() {
|
169
|
+
return (
|
170
|
+
<div style={{
|
171
|
+
color: 'blue',
|
172
|
+
padding: '20px'
|
173
|
+
}}>
|
174
|
+
Styled content
|
175
|
+
</div>
|
176
|
+
);
|
366
177
|
}
|
367
|
-
|
368
|
-
// Usage with custom template
|
369
|
-
const html = await renderToString(<App />, {
|
370
|
-
title: 'Custom Template',
|
371
|
-
styles: ['/styles.css'],
|
372
|
-
bodyAttrs: { 'data-theme': 'dark' }
|
373
|
-
});
|
374
178
|
```
|
375
179
|
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
function ErrorBoundary(
|
180
|
+
## Error Handling
|
181
|
+
|
182
|
+
```tsx
|
183
|
+
function ErrorBoundary() {
|
380
184
|
const [error, resetError] = useErrorBoundary();
|
381
185
|
|
382
186
|
if (error) {
|
383
187
|
return (
|
384
|
-
<div
|
385
|
-
<
|
386
|
-
<pre>{error.message}</pre>
|
188
|
+
<div>
|
189
|
+
<h1>Something went wrong!</h1>
|
387
190
|
<button onClick={resetError}>Try again</button>
|
388
191
|
</div>
|
389
192
|
);
|
390
193
|
}
|
391
194
|
|
392
|
-
return
|
195
|
+
return <ComponentThatMightError />;
|
393
196
|
}
|
394
197
|
```
|
395
198
|
|
396
|
-
##
|
397
|
-
|
398
|
-
1. Fork the repository
|
399
|
-
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
400
|
-
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
401
|
-
4. Push to the branch (`git push origin feature/amazing-feature`)
|
402
|
-
5. Open a Pull Request
|
199
|
+
## Best Practices
|
403
200
|
|
404
|
-
|
201
|
+
1. Use batch updates for multiple state changes
|
202
|
+
2. Implement error boundaries for error handling
|
203
|
+
3. Use context selectors for better performance
|
204
|
+
4. Memoize expensive computations
|
205
|
+
5. Clean up effects when components unmount
|
206
|
+
6. Keep components small and focused
|
207
|
+
7. Use proper TypeScript types for better development experience
|
405
208
|
|
406
|
-
|
209
|
+
## API Reference
|
407
210
|
|
408
|
-
|
211
|
+
### Core
|
212
|
+
- `render(element, container)`
|
213
|
+
- `hydrate(element, container)`
|
214
|
+
- `createElement(vnode)`
|
409
215
|
|
410
|
-
|
411
|
-
-
|
412
|
-
-
|
216
|
+
### Hooks
|
217
|
+
- `useState<T>(initial: T)`
|
218
|
+
- `useEffect(callback, deps?)`
|
219
|
+
- `useMemo(factory, deps)`
|
220
|
+
- `useRef(initial)`
|
221
|
+
- `useErrorBoundary()`
|
222
|
+
|
223
|
+
### Context
|
224
|
+
- `createContext(defaultValue)`
|
225
|
+
- `useContext(Context)`
|
226
|
+
- `Context.Provider`
|
227
|
+
- `Context.Consumer`
|
228
|
+
- `Context.useSelector`
|
229
|
+
|
230
|
+
### Performance
|
231
|
+
- `batchUpdates(callback)`
|
413
232
|
|
414
|
-
##
|
233
|
+
## License
|
415
234
|
|
416
|
-
|
235
|
+
MIT License - feel free to use in any project.
|
417
236
|
|
418
|
-
##
|
237
|
+
## Contributing
|
419
238
|
|
420
|
-
|
239
|
+
Contributions are welcome! Please read our contributing guidelines and submit pull requests.
|
240
|
+
`````
|
package/dist/hooks.d.ts
CHANGED
@@ -6,13 +6,3 @@ export declare function useEffect(callback: () => (() => void) | void, deps?: an
|
|
6
6
|
export declare function useMemo<T>(factory: () => T, deps: any[]): T;
|
7
7
|
export declare function useRef<T>(initial: T): any;
|
8
8
|
export declare function useErrorBoundary(): [Error | null, () => void];
|
9
|
-
export declare function useRouter(): {
|
10
|
-
push: () => void;
|
11
|
-
replace: () => void;
|
12
|
-
back: () => void;
|
13
|
-
forward: () => void;
|
14
|
-
pathname: string;
|
15
|
-
search: string;
|
16
|
-
hash: string;
|
17
|
-
params: Record<string, string>;
|
18
|
-
} | undefined;
|
package/dist/index.d.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
export { useState, useEffect, useMemo, useRef, useErrorBoundary } from './hooks';
|
2
|
-
export { createElement } from './jsx-runtime';
|
3
2
|
export { createContext, useContext } from './context';
|
4
3
|
export { batchUpdates } from './batch';
|
5
4
|
export { jsx, jsxs, Fragment } from './jsx-runtime';
|
package/dist/index.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let e=!1;const t=[];function n(n){if(e)t.push(n);else{e=!0;try{for(n();t.length>0;){const e=t.shift();null==e||e()}}finally{e=!1}}}let r=0;const o=new Map,s=new Map,
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let e=!1;const t=[];function n(n){if(e)t.push(n);else{e=!0;try{for(n();t.length>0;){const e=t.shift();null==e||e()}}finally{e=!1}}}let r=0;const o=new Map,s=new Map,a=new Map,i=new Map,c=new Map;let l=null,u=null,p=null;const d="undefined"==typeof window,f=new Map;function h(e,t,n){l=e,u=n,p=t}function w(){return r++,s.set(r,0),r}function y(){d&&f.delete(r),r=0}function m(t){if(!r)throw new Error("useState must be called within a render");if(d){f.has(r)||f.set(r,new Map);const e=f.get(r),n=s.get(r)||0;e.has(n)||e.set(n,t);const o=e.get(n),a=e=>{};return s.set(r,n+1),[o,a]}o.has(r)||o.set(r,[]);const a=o.get(r),i=s.get(r);i>=a.length&&a.push(t);const c=a[i];return s.set(r,i+1),[c,t=>{const o="function"==typeof t?t(a[i]):t;a[i]!==o&&(a[i]=o,e?n((()=>b(r))):b(r))}]}function g(e,t){if(!r)throw new Error("useEffect must be called within a render");const n=s.get(r);a.has(r)||a.set(r,[]);const o=a.get(r),i=o[n];i&&t&&i.deps&&!t.some(((e,t)=>e!==i.deps[t]))||((null==i?void 0:i.cleanup)&&i.cleanup(),queueMicrotask((()=>{const r=e()||void 0;o[n]={cleanup:r,deps:t}}))),s.set(r,n+1)}async function b(e){try{const t=a.get(e);t&&(t.forEach((e=>{e.cleanup&&e.cleanup()})),a.set(e,[])),l&&u&&p&&await l(p,u)}catch(t){console.error("Error during rerender:",t)}}function v(e,t){console.log("JSX Transform:",{type:e,props:t});const n={...t};return arguments.length>2&&(n.children=Array.prototype.slice.call(arguments,2)),{type:e,props:n}}async function x(e){var t;if(console.log("Creating element from:",e),null==e)return document.createTextNode("");if("boolean"==typeof e)return document.createTextNode("");if("number"==typeof e||"string"==typeof e)return document.createTextNode(String(e));if(Array.isArray(e)){const t=document.createDocumentFragment();for(const n of e){const e=await x(n);t.appendChild(e)}return t}if("type"in e&&void 0!==e.props){const{type:r,props:o}=e;if("function"==typeof r)try{const e=await r(o||{}),t=await x(e);return t instanceof Element&&t.setAttribute("data-component-id",r.name||r.toString()),t}catch(n){return console.error("Error rendering component:",n),document.createTextNode("")}const s=document.createElement(r);for(const[e,n]of Object.entries(o||{}))if("children"!==e)if(e.startsWith("on")&&"function"==typeof n){const r=e.toLowerCase().slice(2),o=null==(t=s.__events)?void 0:t[r];o&&s.removeEventListener(r,o),s.addEventListener(r,n),s.__events||(s.__events={}),s.__events[r]=n}else"style"===e&&"object"==typeof n?Object.assign(s.style,n):"className"===e?s.setAttribute("class",String(n)):"key"!==e&&"ref"!==e&&s.setAttribute(e,String(n));const a=null==o?void 0:o.children;if(null!=a){const e=Array.isArray(a)?a.flat():[a];for(const t of e){const e=await x(t);s.appendChild(e)}}return s}return document.createTextNode(String(e))}let S=!1;async function E(e,t){console.log("Rendering to:",t.id),n((async()=>{w();try{h(E,e,t);const n=await x(e);S||(t.innerHTML=""),t.appendChild(n)}finally{y()}}))}function j(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}let A={pathname:"undefined"!=typeof window?window.location.pathname:"/",search:"undefined"!=typeof window?window.location.search:"",hash:"undefined"!=typeof window?window.location.hash:"",params:{}};const M=new Set;function C(e,t={}){"undefined"!=typeof window&&function(e,t={}){const n=new URL(e,window.location.origin),r={pathname:n.pathname,search:n.search,hash:n.hash,params:{}};t.replace?window.history.replaceState(r,"",n.toString()):window.history.pushState(r,"",n.toString()),A=r,M.forEach((e=>e(r))),t.scroll&&window.scrollTo(0,0)}(e,t)}exports.Fragment=({children:e})=>e,exports.Link=function({href:e,children:t,replace:n=!1,className:r,style:o,...s}){return{type:"a",props:{href:e,onClick:t=>{t.preventDefault(),C(e,{replace:n})},className:r,style:o,...s,children:t}}},exports.batchUpdates=n,exports.createContext=function(e){return{Provider:({value:e,children:t})=>t,Consumer:({children:t})=>t(e),_id:Symbol(),useSelector:t=>t(e)}},exports.hydrate=async function(e,t){S=!0;try{await E(e,t)}finally{S=!1}},exports.jsx=v,exports.jsxs=v,exports.render=E,exports.renderToString=async function e(t){w(),h((()=>{}),t,null);try{if(null==t)return"";if("boolean"==typeof t)return"";if("number"==typeof t||"string"==typeof t)return j(String(t));if(Array.isArray(t)){return(await Promise.all(t.map(e))).join("")}if("type"in t&&void 0!==t.props){const{type:o,props:s}=t;if("function"==typeof o)try{w();const t=await o(s||{}),n=await e(t);return y(),n}catch(r){return console.error("Error rendering component:",r),""}let a=`<${o}`;for(const[e,t]of Object.entries(s||{}))"children"!==e&&("className"===e?a+=` class="${j(String(t))}"`:"style"===e&&"object"==typeof t?a+=` style="${n=t||{},Object.entries(n).map((([e,t])=>{return`${n=e,n.replace(/[A-Z]/g,(e=>"-"+e.toLowerCase()))}:${t}`;var n})).join(";")}"`:e.startsWith("on")||(a+=` ${e}="${j(String(t))}"`));if(new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]).has(o))return a+"/>";if(a+=">",null==s?void 0:s.children){const t=Array.isArray(s.children)?s.children:[s.children];a+=(await Promise.all(t.map(e))).join("")}return a+`</${o}>`}return j(String(t))}finally{y()}var n},exports.useContext=function(e){return e},exports.useEffect=g,exports.useErrorBoundary=function(){const[e,t]=m(null);return[e,()=>t(null)]},exports.useMemo=function(e,t){if(!r)throw new Error("useMemo must be called within a render");const n=s.get(r);i.has(r)||i.set(r,[]);const o=i.get(r),a=o[n];if(!a||t&&t.some(((e,t)=>!Object.is(e,a.deps[t])))){const a=e();return o[n]={value:a,deps:t},s.set(r,n+1),a}return s.set(r,n+1),a.value},exports.useRef=function(e){if(!r)throw new Error("useRef must be called within a render");const t=s.get(r);c.has(r)||c.set(r,[]);const n=c.get(r);if(t>=n.length){const o={current:e};return n.push(o),s.set(r,t+1),o}const o=n[t];return s.set(r,t+1),o},exports.useRouter=function(){const[e,t]=m(A);return g((()=>{const e=e=>{t(e)},n=()=>{A={pathname:window.location.pathname,search:window.location.search,hash:window.location.hash,params:{}},t(A)};return M.add(e),window.addEventListener("popstate",n),()=>{M.delete(e),window.removeEventListener("popstate",n)}}),[]),{...e,push:(e,t)=>C(e,t),replace:(e,t)=>C(e,{...t,replace:!0}),back:()=>window.history.back(),forward:()=>window.history.forward()}},exports.useState=m;
|
2
2
|
//# sourceMappingURL=index.js.map
|