frontend-hamroun 1.2.85 → 1.2.88
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/batch.d.ts +4 -0
- package/dist/batch.d.ts.map +1 -0
- package/dist/batch.js +22 -0
- package/dist/client-router.d.ts +61 -0
- package/dist/client-router.d.ts.map +1 -0
- package/dist/client-router.js +209 -0
- package/dist/component.d.ts +15 -0
- package/dist/component.d.ts.map +1 -0
- package/dist/component.js +84 -0
- package/dist/components/Counter.d.ts +1 -0
- package/dist/components/Counter.d.ts.map +1 -0
- package/dist/components/Counter.js +2 -0
- package/dist/context.d.ts +5 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +23 -0
- package/dist/event-bus.d.ts +24 -0
- package/dist/event-bus.d.ts.map +1 -0
- package/dist/event-bus.js +74 -0
- package/dist/forms.d.ts +41 -0
- package/dist/forms.d.ts.map +1 -0
- package/dist/forms.js +147 -0
- package/dist/hooks.d.ts +12 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +142 -0
- package/dist/index.cjs +1118 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.client.d.ts +13 -0
- package/dist/index.client.d.ts.map +1 -0
- package/dist/index.client.js +12 -25
- package/dist/index.d.ts +65 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1040 -264
- package/dist/index.js.map +1 -1
- package/dist/jsx-dev-runtime.cjs +102 -0
- package/dist/jsx-dev-runtime.cjs.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +3 -0
- package/dist/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/jsx-dev-runtime.js +96 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime/jsx-runtime.d.ts +5 -0
- package/dist/jsx-runtime/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime/jsx-runtime.js +40 -0
- package/dist/jsx-runtime.cjs +112 -1
- package/dist/jsx-runtime.cjs.map +1 -1
- package/dist/jsx-runtime.d.ts +18 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +90 -79
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/lifecycle-events.d.ts +109 -0
- package/dist/lifecycle-events.d.ts.map +1 -0
- package/dist/lifecycle-events.js +176 -0
- package/dist/renderComponent.d.ts +14 -0
- package/dist/renderComponent.d.ts.map +1 -0
- package/dist/renderComponent.js +29 -0
- package/dist/renderer.d.ts +4 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +49 -0
- package/dist/router.d.ts +56 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +165 -0
- package/dist/server-renderer.d.ts +2 -0
- package/dist/server-renderer.d.ts.map +1 -0
- package/dist/server-renderer.js +111 -5
- package/dist/server-types.d.ts +43 -0
- package/dist/server-types.d.ts.map +1 -0
- package/dist/server-types.js +5 -0
- package/dist/store.d.ts +42 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +98 -0
- package/dist/types.d.ts +272 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/utils.d.ts +47 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +143 -0
- package/dist/vdom.d.ts +9 -0
- package/dist/vdom.d.ts.map +1 -0
- package/dist/vdom.js +21 -0
- package/dist/wasm.d.ts +37 -0
- package/dist/wasm.d.ts.map +1 -0
- package/dist/wasm.js +158 -0
- package/package.json +54 -83
- package/dist/index.client.cjs +0 -2
- package/dist/index.client.cjs.map +0 -1
- package/dist/index.client.js.map +0 -1
- package/dist/renderer-DaVfBeVi.cjs +0 -2
- package/dist/renderer-DaVfBeVi.cjs.map +0 -1
- package/dist/renderer-nfT7XSpo.js +0 -61
- package/dist/renderer-nfT7XSpo.js.map +0 -1
- package/dist/server-renderer-B5b0Q0ck.cjs +0 -2
- package/dist/server-renderer-B5b0Q0ck.cjs.map +0 -1
- package/dist/server-renderer-C4MB-jAp.js +0 -248
- package/dist/server-renderer-C4MB-jAp.js.map +0 -1
- package/dist/server-renderer.cjs +0 -2
- package/dist/server-renderer.cjs.map +0 -1
- package/dist/server-renderer.js.map +0 -1
package/dist/index.cjs
CHANGED
@@ -1,2 +1,1119 @@
|
|
1
|
-
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
4
|
+
|
5
|
+
function jsx(type, props) {
|
6
|
+
console.log('JSX Transform:', { type, props });
|
7
|
+
const processedProps = { ...props };
|
8
|
+
// Handle children properly
|
9
|
+
if (arguments.length > 2) {
|
10
|
+
processedProps.children = Array.prototype.slice.call(arguments, 2);
|
11
|
+
}
|
12
|
+
return { type, props: processedProps };
|
13
|
+
}
|
14
|
+
const Fragment = ({ children }) => children;
|
15
|
+
async function createElement(vnode) {
|
16
|
+
console.log('Creating element from:', vnode);
|
17
|
+
// Handle primitives and null
|
18
|
+
if (vnode == null) {
|
19
|
+
return document.createTextNode('');
|
20
|
+
}
|
21
|
+
if (typeof vnode === 'boolean') {
|
22
|
+
return document.createTextNode('');
|
23
|
+
}
|
24
|
+
if (typeof vnode === 'number' || typeof vnode === 'string') {
|
25
|
+
return document.createTextNode(String(vnode));
|
26
|
+
}
|
27
|
+
// Handle arrays
|
28
|
+
if (Array.isArray(vnode)) {
|
29
|
+
const fragment = document.createDocumentFragment();
|
30
|
+
for (const child of vnode) {
|
31
|
+
const node = await createElement(child);
|
32
|
+
fragment.appendChild(node);
|
33
|
+
}
|
34
|
+
return fragment;
|
35
|
+
}
|
36
|
+
// Handle VNode
|
37
|
+
if ('type' in vnode && vnode.props !== undefined) {
|
38
|
+
const { type, props } = vnode;
|
39
|
+
// Handle function components
|
40
|
+
if (typeof type === 'function') {
|
41
|
+
try {
|
42
|
+
const result = await type(props || {});
|
43
|
+
const node = await createElement(result);
|
44
|
+
if (node instanceof Element) {
|
45
|
+
node.setAttribute('data-component-id', type.name || type.toString());
|
46
|
+
}
|
47
|
+
return node;
|
48
|
+
}
|
49
|
+
catch (error) {
|
50
|
+
console.error('Error rendering component:', error);
|
51
|
+
return document.createTextNode('');
|
52
|
+
}
|
53
|
+
}
|
54
|
+
// Create DOM element
|
55
|
+
const element = document.createElement(type);
|
56
|
+
// Handle props
|
57
|
+
for (const [key, value] of Object.entries(props || {})) {
|
58
|
+
if (key === 'children')
|
59
|
+
continue;
|
60
|
+
if (key.startsWith('on') && typeof value === 'function') {
|
61
|
+
const eventName = key.toLowerCase().slice(2);
|
62
|
+
// Remove existing event listener if any
|
63
|
+
const existingHandler = element.__events?.[eventName];
|
64
|
+
if (existingHandler) {
|
65
|
+
element.removeEventListener(eventName, existingHandler);
|
66
|
+
}
|
67
|
+
// Add new event listener
|
68
|
+
element.addEventListener(eventName, value);
|
69
|
+
if (!element.__events) {
|
70
|
+
element.__events = {};
|
71
|
+
}
|
72
|
+
element.__events[eventName] = value;
|
73
|
+
}
|
74
|
+
else if (key === 'style' && typeof value === 'object') {
|
75
|
+
Object.assign(element.style, value);
|
76
|
+
}
|
77
|
+
else if (key === 'className') {
|
78
|
+
element.setAttribute('class', String(value));
|
79
|
+
}
|
80
|
+
else if (key !== 'key' && key !== 'ref') {
|
81
|
+
element.setAttribute(key, String(value));
|
82
|
+
}
|
83
|
+
}
|
84
|
+
// Handle children
|
85
|
+
const children = props?.children;
|
86
|
+
if (children != null) {
|
87
|
+
const childArray = Array.isArray(children) ? children.flat() : [children];
|
88
|
+
for (const child of childArray) {
|
89
|
+
const childNode = await createElement(child);
|
90
|
+
element.appendChild(childNode);
|
91
|
+
}
|
92
|
+
}
|
93
|
+
return element;
|
94
|
+
}
|
95
|
+
// Handle other objects by converting to string
|
96
|
+
return document.createTextNode(String(vnode));
|
97
|
+
}
|
98
|
+
|
99
|
+
let isBatching = false;
|
100
|
+
const queue = [];
|
101
|
+
function batchUpdates(fn) {
|
102
|
+
if (isBatching) {
|
103
|
+
queue.push(fn);
|
104
|
+
return;
|
105
|
+
}
|
106
|
+
isBatching = true;
|
107
|
+
try {
|
108
|
+
fn();
|
109
|
+
while (queue.length > 0) {
|
110
|
+
const nextFn = queue.shift();
|
111
|
+
nextFn?.();
|
112
|
+
}
|
113
|
+
}
|
114
|
+
finally {
|
115
|
+
isBatching = false;
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
const contexts = new Map();
|
120
|
+
function createContext(defaultValue) {
|
121
|
+
const contextId = Symbol('context');
|
122
|
+
const Provider = ({ value, children }) => {
|
123
|
+
contexts.set(contextId, value);
|
124
|
+
return children;
|
125
|
+
};
|
126
|
+
const Consumer = ({ children }) => {
|
127
|
+
const value = contexts.get(contextId) ?? defaultValue;
|
128
|
+
return children(value);
|
129
|
+
};
|
130
|
+
const context = {
|
131
|
+
Provider,
|
132
|
+
Consumer,
|
133
|
+
displayName: 'Context'
|
134
|
+
};
|
135
|
+
return context;
|
136
|
+
}
|
137
|
+
function useContext(context) {
|
138
|
+
// In a real implementation, this would access the context value from the component tree
|
139
|
+
// For now, returning a default value to satisfy TypeScript
|
140
|
+
return {};
|
141
|
+
}
|
142
|
+
|
143
|
+
// Current render ID counter
|
144
|
+
let currentRender = 0;
|
145
|
+
// State storage
|
146
|
+
const states = new Map();
|
147
|
+
const stateIndices = new Map();
|
148
|
+
const effects = new Map();
|
149
|
+
const memos = new Map();
|
150
|
+
const refs = new Map();
|
151
|
+
// Rendering callbacks
|
152
|
+
let globalRenderCallback = null;
|
153
|
+
let globalContainer = null;
|
154
|
+
let currentElement = null;
|
155
|
+
function setRenderCallback(callback, element, container) {
|
156
|
+
globalRenderCallback = callback;
|
157
|
+
globalContainer = container;
|
158
|
+
currentElement = element;
|
159
|
+
}
|
160
|
+
function prepareRender(component = null) {
|
161
|
+
currentRender++;
|
162
|
+
stateIndices.set(currentRender, 0);
|
163
|
+
return currentRender;
|
164
|
+
}
|
165
|
+
function finishRender() {
|
166
|
+
currentRender = 0;
|
167
|
+
}
|
168
|
+
function useState(initial) {
|
169
|
+
if (!currentRender) {
|
170
|
+
throw new Error("useState must be called within a render");
|
171
|
+
}
|
172
|
+
if (!states.has(currentRender)) {
|
173
|
+
states.set(currentRender, []);
|
174
|
+
}
|
175
|
+
const componentStates = states.get(currentRender);
|
176
|
+
const index = stateIndices.get(currentRender) || 0;
|
177
|
+
if (index >= componentStates.length) {
|
178
|
+
componentStates.push(initial);
|
179
|
+
}
|
180
|
+
const state = componentStates[index];
|
181
|
+
const setState = (newValue) => {
|
182
|
+
const nextValue = typeof newValue === 'function'
|
183
|
+
? newValue(componentStates[index])
|
184
|
+
: newValue;
|
185
|
+
if (componentStates[index] === nextValue)
|
186
|
+
return;
|
187
|
+
componentStates[index] = nextValue;
|
188
|
+
if (isBatching) {
|
189
|
+
batchUpdates(() => rerender(currentRender));
|
190
|
+
}
|
191
|
+
else {
|
192
|
+
rerender(currentRender);
|
193
|
+
}
|
194
|
+
};
|
195
|
+
stateIndices.set(currentRender, index + 1);
|
196
|
+
return [state, setState];
|
197
|
+
}
|
198
|
+
function useEffect(callback, deps) {
|
199
|
+
if (!currentRender)
|
200
|
+
throw new Error("useEffect must be called within a render");
|
201
|
+
const effectIndex = stateIndices.get(currentRender) || 0;
|
202
|
+
if (!effects.has(currentRender)) {
|
203
|
+
effects.set(currentRender, []);
|
204
|
+
}
|
205
|
+
const componentEffects = effects.get(currentRender);
|
206
|
+
const prevEffect = componentEffects[effectIndex];
|
207
|
+
if (!prevEffect || !deps || !prevEffect.deps || deps.some((dep, i) => dep !== prevEffect.deps[i])) {
|
208
|
+
if (prevEffect?.cleanup) {
|
209
|
+
prevEffect.cleanup();
|
210
|
+
}
|
211
|
+
// Schedule effect execution after render is complete
|
212
|
+
queueMicrotask(() => {
|
213
|
+
const cleanup = callback() || undefined;
|
214
|
+
componentEffects[effectIndex] = { cleanup, deps: deps || [] };
|
215
|
+
});
|
216
|
+
}
|
217
|
+
stateIndices.set(currentRender, effectIndex + 1);
|
218
|
+
}
|
219
|
+
function useMemo(factory, deps) {
|
220
|
+
if (!currentRender)
|
221
|
+
throw new Error("useMemo must be called within a render");
|
222
|
+
const memoIndex = stateIndices.get(currentRender) || 0;
|
223
|
+
if (!memos.has(currentRender)) {
|
224
|
+
memos.set(currentRender, []);
|
225
|
+
}
|
226
|
+
const componentMemos = memos.get(currentRender);
|
227
|
+
const prevMemo = componentMemos[memoIndex];
|
228
|
+
if (!prevMemo || (deps && deps.some((dep, i) => !Object.is(dep, prevMemo.deps[i])))) {
|
229
|
+
const value = factory();
|
230
|
+
componentMemos[memoIndex] = { value, deps: deps || [] };
|
231
|
+
stateIndices.set(currentRender, memoIndex + 1);
|
232
|
+
return value;
|
233
|
+
}
|
234
|
+
stateIndices.set(currentRender, memoIndex + 1);
|
235
|
+
return prevMemo.value;
|
236
|
+
}
|
237
|
+
function useRef(initial) {
|
238
|
+
if (!currentRender)
|
239
|
+
throw new Error("useRef must be called within a render");
|
240
|
+
const refIndex = stateIndices.get(currentRender) || 0;
|
241
|
+
if (!refs.has(currentRender)) {
|
242
|
+
refs.set(currentRender, []);
|
243
|
+
}
|
244
|
+
const componentRefs = refs.get(currentRender);
|
245
|
+
if (refIndex >= componentRefs.length) {
|
246
|
+
const ref = { current: initial };
|
247
|
+
componentRefs.push(ref);
|
248
|
+
stateIndices.set(currentRender, refIndex + 1);
|
249
|
+
return ref;
|
250
|
+
}
|
251
|
+
const ref = componentRefs[refIndex];
|
252
|
+
stateIndices.set(currentRender, refIndex + 1);
|
253
|
+
return ref;
|
254
|
+
}
|
255
|
+
async function rerender(rendererId) {
|
256
|
+
try {
|
257
|
+
// Clean up effects
|
258
|
+
const componentEffects = effects.get(rendererId);
|
259
|
+
if (componentEffects) {
|
260
|
+
componentEffects.forEach(effect => {
|
261
|
+
if (effect.cleanup)
|
262
|
+
effect.cleanup();
|
263
|
+
});
|
264
|
+
effects.set(rendererId, []);
|
265
|
+
}
|
266
|
+
// Trigger re-render
|
267
|
+
if (globalRenderCallback && globalContainer && currentElement) {
|
268
|
+
await globalRenderCallback(currentElement, globalContainer);
|
269
|
+
}
|
270
|
+
}
|
271
|
+
catch (error) {
|
272
|
+
console.error('Error during rerender:', error);
|
273
|
+
}
|
274
|
+
}
|
275
|
+
function useErrorBoundary() {
|
276
|
+
const [error, setError] = useState(null);
|
277
|
+
return [error, () => setError(null)];
|
278
|
+
}
|
279
|
+
|
280
|
+
// Render function for client-side rendering
|
281
|
+
async function render(element, container) {
|
282
|
+
try {
|
283
|
+
// Set up render callback for state updates
|
284
|
+
setRenderCallback(render, element, container);
|
285
|
+
// Prepare render context
|
286
|
+
const renderId = prepareRender(element);
|
287
|
+
// Create DOM nodes from virtual elements
|
288
|
+
const domNode = await createElement(element);
|
289
|
+
// Clear container and append new content
|
290
|
+
// Handle both Element and DocumentFragment cases
|
291
|
+
if (container instanceof Element) {
|
292
|
+
container.innerHTML = '';
|
293
|
+
}
|
294
|
+
else {
|
295
|
+
// For DocumentFragment, clear all children
|
296
|
+
while (container.firstChild) {
|
297
|
+
container.removeChild(container.firstChild);
|
298
|
+
}
|
299
|
+
}
|
300
|
+
container.appendChild(domNode);
|
301
|
+
// Finish render
|
302
|
+
finishRender();
|
303
|
+
console.log('Render completed successfully');
|
304
|
+
}
|
305
|
+
catch (error) {
|
306
|
+
console.error('Error during render:', error);
|
307
|
+
// Clean up render context on error
|
308
|
+
finishRender();
|
309
|
+
throw error;
|
310
|
+
}
|
311
|
+
}
|
312
|
+
// Hydrate function for client-side hydration of SSR content
|
313
|
+
async function hydrate(element, container) {
|
314
|
+
try {
|
315
|
+
console.log('Starting hydration...');
|
316
|
+
// For now, hydrate works the same as render
|
317
|
+
// In a more advanced implementation, this would preserve existing DOM
|
318
|
+
// and only attach event listeners and initialize state
|
319
|
+
await render(element, container);
|
320
|
+
console.log('Hydration completed successfully');
|
321
|
+
}
|
322
|
+
catch (error) {
|
323
|
+
console.error('Error during hydration:', error);
|
324
|
+
throw error;
|
325
|
+
}
|
326
|
+
}
|
327
|
+
|
328
|
+
function arePropsEqual(oldProps, newProps) {
|
329
|
+
const oldKeys = Object.keys(oldProps).filter(k => k !== 'children');
|
330
|
+
const newKeys = Object.keys(newProps).filter(k => k !== 'children');
|
331
|
+
if (oldKeys.length !== newKeys.length)
|
332
|
+
return false;
|
333
|
+
return oldKeys.every(key => oldProps[key] === newProps[key]);
|
334
|
+
}
|
335
|
+
function diff(oldNode, newNode) {
|
336
|
+
if (oldNode == null || newNode == null)
|
337
|
+
return oldNode !== newNode;
|
338
|
+
if (typeof oldNode !== typeof newNode)
|
339
|
+
return true;
|
340
|
+
if (typeof newNode === 'string' || typeof newNode === 'number')
|
341
|
+
return oldNode !== newNode;
|
342
|
+
if (newNode.type !== oldNode.type)
|
343
|
+
return true;
|
344
|
+
return !arePropsEqual(oldNode.props, newNode.props);
|
345
|
+
}
|
346
|
+
function shouldComponentUpdate(oldProps, newProps) {
|
347
|
+
return !arePropsEqual(oldProps, newProps);
|
348
|
+
}
|
349
|
+
|
350
|
+
class Component {
|
351
|
+
constructor(props = {}) {
|
352
|
+
this.state = {};
|
353
|
+
this.element = null;
|
354
|
+
this._mounted = false;
|
355
|
+
this.props = props;
|
356
|
+
}
|
357
|
+
componentDidMount() {
|
358
|
+
// Hook for after component is mounted
|
359
|
+
}
|
360
|
+
async setState(newState) {
|
361
|
+
const prevState = { ...this.state };
|
362
|
+
this.state = { ...prevState, ...newState };
|
363
|
+
console.log(`${this.constructor.name} state updated:`, {
|
364
|
+
prev: prevState,
|
365
|
+
next: this.state
|
366
|
+
});
|
367
|
+
await Promise.resolve(); // Ensure state is updated before re-render
|
368
|
+
if (this._mounted) {
|
369
|
+
await this.update();
|
370
|
+
}
|
371
|
+
else {
|
372
|
+
await this.update();
|
373
|
+
}
|
374
|
+
}
|
375
|
+
_replayEvents(oldElement, newElement) {
|
376
|
+
const oldEvents = oldElement.__events || {};
|
377
|
+
Object.entries(oldEvents).forEach(([event, handler]) => {
|
378
|
+
newElement.addEventListener(event, handler);
|
379
|
+
});
|
380
|
+
newElement.__events = oldEvents;
|
381
|
+
}
|
382
|
+
_deepCloneWithEvents(node) {
|
383
|
+
const clone = node.cloneNode(false);
|
384
|
+
// Copy events from original element
|
385
|
+
const events = node.__events || {};
|
386
|
+
clone.__events = events;
|
387
|
+
Object.entries(events).forEach(([event, handler]) => {
|
388
|
+
clone.addEventListener(event, handler);
|
389
|
+
});
|
390
|
+
// Clone children
|
391
|
+
Array.from(node.childNodes).forEach(child => {
|
392
|
+
if (child instanceof HTMLElement) {
|
393
|
+
clone.appendChild(this._deepCloneWithEvents(child));
|
394
|
+
}
|
395
|
+
else {
|
396
|
+
clone.appendChild(child.cloneNode(true));
|
397
|
+
}
|
398
|
+
});
|
399
|
+
return clone;
|
400
|
+
}
|
401
|
+
async update() {
|
402
|
+
const vdom = this.render();
|
403
|
+
if (!vdom)
|
404
|
+
return document.createTextNode('');
|
405
|
+
const rendered = await createElement(vdom);
|
406
|
+
if (rendered instanceof HTMLElement) {
|
407
|
+
return this._updateElement(rendered);
|
408
|
+
}
|
409
|
+
const wrapper = document.createElement('div');
|
410
|
+
wrapper.appendChild(rendered);
|
411
|
+
return this._updateElement(wrapper);
|
412
|
+
}
|
413
|
+
async _updateElement(rendered) {
|
414
|
+
const newElement = this._deepCloneWithEvents(rendered);
|
415
|
+
newElement.__instance = this;
|
416
|
+
if (!this.element) {
|
417
|
+
this.element = newElement;
|
418
|
+
if (!this._mounted) {
|
419
|
+
this._mounted = true;
|
420
|
+
queueMicrotask(() => this.componentDidMount());
|
421
|
+
}
|
422
|
+
}
|
423
|
+
else if (this.element.parentNode) {
|
424
|
+
this.element.parentNode.replaceChild(newElement, this.element);
|
425
|
+
this.element = newElement;
|
426
|
+
}
|
427
|
+
return this.element;
|
428
|
+
}
|
429
|
+
render() {
|
430
|
+
throw new Error('Component must implement render() method');
|
431
|
+
}
|
432
|
+
}
|
433
|
+
|
434
|
+
/**
|
435
|
+
* Client-side router for single-page applications
|
436
|
+
*/
|
437
|
+
// Create context for router
|
438
|
+
const RouterContext = createContext({
|
439
|
+
location: {
|
440
|
+
pathname: '/',
|
441
|
+
search: '',
|
442
|
+
hash: ''
|
443
|
+
},
|
444
|
+
params: {},
|
445
|
+
navigate: () => { },
|
446
|
+
match: () => false
|
447
|
+
});
|
448
|
+
// Parse path pattern into regex
|
449
|
+
function parsePath(path) {
|
450
|
+
// Convert :param syntax to capture groups
|
451
|
+
const pattern = path
|
452
|
+
.replace(/\/+$/, '') // Remove trailing slashes
|
453
|
+
.replace(/^\/+/, '/') // Ensure leading slash
|
454
|
+
.replace(/\/:([^/]+)/g, '/([^/]+)');
|
455
|
+
// Get param names
|
456
|
+
const paramNames = [];
|
457
|
+
path.replace(/\/:([^/]+)/g, (_, paramName) => {
|
458
|
+
paramNames.push(paramName);
|
459
|
+
return '';
|
460
|
+
});
|
461
|
+
return { pattern, paramNames };
|
462
|
+
}
|
463
|
+
// Match a path against a pattern
|
464
|
+
function matchPath(pathname, route) {
|
465
|
+
const { path, exact = false } = route;
|
466
|
+
const { pattern, paramNames } = parsePath(path);
|
467
|
+
// Create regex with or without exact matching
|
468
|
+
const regex = new RegExp(`^${pattern}${exact ? '$' : ''}`);
|
469
|
+
const match = pathname.match(regex);
|
470
|
+
if (!match)
|
471
|
+
return null;
|
472
|
+
// Extract params
|
473
|
+
const params = {};
|
474
|
+
paramNames.forEach((name, index) => {
|
475
|
+
params[name] = match[index + 1];
|
476
|
+
});
|
477
|
+
return params;
|
478
|
+
}
|
479
|
+
// Router Provider component
|
480
|
+
function RouterProvider({ routes, children }) {
|
481
|
+
// Get initial location from window if available
|
482
|
+
const getInitialLocation = () => {
|
483
|
+
if (typeof window === 'undefined') {
|
484
|
+
return { pathname: '/', search: '', hash: '' };
|
485
|
+
}
|
486
|
+
return {
|
487
|
+
pathname: window.location.pathname,
|
488
|
+
search: window.location.search,
|
489
|
+
hash: window.location.hash
|
490
|
+
};
|
491
|
+
};
|
492
|
+
// Fix: Call the function to get the initial value instead of passing the function itself
|
493
|
+
const [location, setLocation] = useState(getInitialLocation());
|
494
|
+
const [params, setParams] = useState({});
|
495
|
+
// Update params when location changes
|
496
|
+
useEffect(() => {
|
497
|
+
for (const route of routes) {
|
498
|
+
const matchedParams = matchPath(location.pathname, route);
|
499
|
+
if (matchedParams) {
|
500
|
+
setParams(matchedParams);
|
501
|
+
break;
|
502
|
+
}
|
503
|
+
}
|
504
|
+
}, [location, routes]);
|
505
|
+
// Listen for popstate events
|
506
|
+
useEffect(() => {
|
507
|
+
if (typeof window === 'undefined')
|
508
|
+
return;
|
509
|
+
const handlePopState = () => {
|
510
|
+
setLocation({
|
511
|
+
pathname: window.location.pathname,
|
512
|
+
search: window.location.search,
|
513
|
+
hash: window.location.hash
|
514
|
+
});
|
515
|
+
};
|
516
|
+
window.addEventListener('popstate', handlePopState);
|
517
|
+
return () => window.removeEventListener('popstate', handlePopState);
|
518
|
+
}, []);
|
519
|
+
// Navigation function
|
520
|
+
const navigate = (to, options = {}) => {
|
521
|
+
if (typeof window === 'undefined')
|
522
|
+
return;
|
523
|
+
const { replace = false, state = null } = options;
|
524
|
+
if (replace) {
|
525
|
+
window.history.replaceState(state, '', to);
|
526
|
+
}
|
527
|
+
else {
|
528
|
+
window.history.pushState(state, '', to);
|
529
|
+
}
|
530
|
+
// Update location
|
531
|
+
setLocation({
|
532
|
+
pathname: window.location.pathname,
|
533
|
+
search: window.location.search,
|
534
|
+
hash: window.location.hash
|
535
|
+
});
|
536
|
+
};
|
537
|
+
// Match function to test if a path matches the current location
|
538
|
+
const match = (path) => {
|
539
|
+
const { pattern } = parsePath(path);
|
540
|
+
const regex = new RegExp(`^${pattern}`);
|
541
|
+
return regex.test(location.pathname);
|
542
|
+
};
|
543
|
+
// Router context value
|
544
|
+
const routerValue = {
|
545
|
+
location: {
|
546
|
+
pathname: location.pathname,
|
547
|
+
search: location.search,
|
548
|
+
hash: location.hash
|
549
|
+
},
|
550
|
+
params,
|
551
|
+
navigate,
|
552
|
+
match
|
553
|
+
};
|
554
|
+
return jsx(RouterContext.Provider, { value: routerValue, children });
|
555
|
+
}
|
556
|
+
// Route component
|
557
|
+
function Route({ path, component: Component, props = {} }) {
|
558
|
+
const context = useContext();
|
559
|
+
const params = context.params;
|
560
|
+
const locationPathname = context.location.pathname;
|
561
|
+
const routeToMatch = { path, component: Component };
|
562
|
+
const match = matchPath(locationPathname, routeToMatch);
|
563
|
+
if (!match)
|
564
|
+
return null;
|
565
|
+
return jsx(Component, { ...props, params });
|
566
|
+
}
|
567
|
+
// Switch component
|
568
|
+
function Switch({ children }) {
|
569
|
+
const context = useContext();
|
570
|
+
const locationPathname = context.location.pathname;
|
571
|
+
// Find the first matching route
|
572
|
+
const child = Array.isArray(children)
|
573
|
+
? children.find(child => {
|
574
|
+
if (!child || typeof child.type !== 'function' || !child.props.path)
|
575
|
+
return false;
|
576
|
+
const routeObj = {
|
577
|
+
path: child.props.path,
|
578
|
+
component: child.type,
|
579
|
+
exact: child.props.exact || false
|
580
|
+
};
|
581
|
+
return matchPath(locationPathname, routeObj);
|
582
|
+
})
|
583
|
+
: children;
|
584
|
+
return child || null;
|
585
|
+
}
|
586
|
+
// Link component
|
587
|
+
function Link({ to, replace = false, state = null, className = '', activeClassName = '', children, ...rest }) {
|
588
|
+
const context = useContext();
|
589
|
+
const navigate = context.navigate;
|
590
|
+
const match = context.match;
|
591
|
+
const handleClick = (e) => {
|
592
|
+
e.preventDefault();
|
593
|
+
navigate(to, { replace, state });
|
594
|
+
};
|
595
|
+
const isActive = match(to);
|
596
|
+
const classes = [
|
597
|
+
className,
|
598
|
+
isActive ? activeClassName : ''
|
599
|
+
].filter(Boolean).join(' ');
|
600
|
+
return jsx('a', {
|
601
|
+
href: to,
|
602
|
+
className: classes || undefined,
|
603
|
+
onClick: handleClick,
|
604
|
+
...rest,
|
605
|
+
children
|
606
|
+
});
|
607
|
+
}
|
608
|
+
// Redirect component
|
609
|
+
function Redirect({ to, replace = true }) {
|
610
|
+
const context = useContext();
|
611
|
+
const navigate = context.navigate;
|
612
|
+
useEffect(() => {
|
613
|
+
navigate(to, { replace });
|
614
|
+
}, [to]);
|
615
|
+
return null;
|
616
|
+
}
|
617
|
+
// Hooks
|
618
|
+
function useLocation() {
|
619
|
+
const context = useContext();
|
620
|
+
return context.location;
|
621
|
+
}
|
622
|
+
function useParams() {
|
623
|
+
const context = useContext();
|
624
|
+
return context.params;
|
625
|
+
}
|
626
|
+
function useNavigate() {
|
627
|
+
const context = useContext();
|
628
|
+
return context.navigate;
|
629
|
+
}
|
630
|
+
|
631
|
+
/**
|
632
|
+
* Form handling utilities for the framework
|
633
|
+
*/
|
634
|
+
function useForm(options) {
|
635
|
+
const { initialValues, validate, onSubmit } = options;
|
636
|
+
const [values, setValues] = useState(initialValues);
|
637
|
+
const [errors, setErrors] = useState({});
|
638
|
+
const [touched, setTouched] = useState({});
|
639
|
+
const [dirty, setDirty] = useState({});
|
640
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
641
|
+
const [submitCount, setSubmitCount] = useState(0);
|
642
|
+
// Track form validity and dirty state
|
643
|
+
const isValid = Object.keys(errors).length === 0;
|
644
|
+
const isDirty = Object.values(dirty).some(Boolean);
|
645
|
+
// Validate form when values or validate function changes
|
646
|
+
useEffect(() => {
|
647
|
+
if (validate) {
|
648
|
+
const validationErrors = validate(values);
|
649
|
+
setErrors(validationErrors || {});
|
650
|
+
}
|
651
|
+
}, [values, validate]);
|
652
|
+
// Handle form input changes
|
653
|
+
const handleChange = (e) => {
|
654
|
+
const { name, value, type, checked } = e.target;
|
655
|
+
const fieldValue = type === 'checkbox' ? checked : value;
|
656
|
+
setValues(prev => ({
|
657
|
+
...prev,
|
658
|
+
[name]: fieldValue
|
659
|
+
}));
|
660
|
+
setDirty(prev => ({
|
661
|
+
...prev,
|
662
|
+
[name]: true
|
663
|
+
}));
|
664
|
+
};
|
665
|
+
// Handle field blur
|
666
|
+
const handleBlur = (e) => {
|
667
|
+
const { name } = e.target;
|
668
|
+
setTouched(prev => ({
|
669
|
+
...prev,
|
670
|
+
[name]: true
|
671
|
+
}));
|
672
|
+
};
|
673
|
+
// Set field value programmatically
|
674
|
+
const setFieldValue = (field, value) => {
|
675
|
+
setValues(prev => ({
|
676
|
+
...prev,
|
677
|
+
[field]: value
|
678
|
+
}));
|
679
|
+
setDirty(prev => ({
|
680
|
+
...prev,
|
681
|
+
[field]: true
|
682
|
+
}));
|
683
|
+
};
|
684
|
+
// Set field error programmatically
|
685
|
+
const setFieldError = (field, error) => {
|
686
|
+
setErrors(prev => ({
|
687
|
+
...prev,
|
688
|
+
[field]: error
|
689
|
+
}));
|
690
|
+
};
|
691
|
+
// Update multiple values at once
|
692
|
+
const updateValues = (newValues) => {
|
693
|
+
setValues(prev => ({
|
694
|
+
...prev,
|
695
|
+
...newValues
|
696
|
+
}));
|
697
|
+
// Mark changed fields as dirty
|
698
|
+
const dirtyFields = {};
|
699
|
+
Object.keys(newValues).forEach(key => {
|
700
|
+
dirtyFields[key] = true;
|
701
|
+
});
|
702
|
+
setDirty(prev => ({
|
703
|
+
...prev,
|
704
|
+
...dirtyFields
|
705
|
+
}));
|
706
|
+
};
|
707
|
+
// Reset form to initial state
|
708
|
+
const resetForm = () => {
|
709
|
+
setValues(initialValues);
|
710
|
+
setErrors({});
|
711
|
+
setTouched({});
|
712
|
+
setDirty({});
|
713
|
+
setIsSubmitting(false);
|
714
|
+
};
|
715
|
+
// Handle form submission
|
716
|
+
const handleSubmit = async (e) => {
|
717
|
+
e.preventDefault();
|
718
|
+
// Mark all fields as touched
|
719
|
+
const allTouched = {};
|
720
|
+
Object.keys(values).forEach(key => {
|
721
|
+
allTouched[key] = true;
|
722
|
+
});
|
723
|
+
setTouched(allTouched);
|
724
|
+
// Validate before submission
|
725
|
+
let validationErrors = {};
|
726
|
+
if (validate) {
|
727
|
+
validationErrors = validate(values);
|
728
|
+
setErrors(validationErrors || {});
|
729
|
+
}
|
730
|
+
// Only proceed if valid
|
731
|
+
if (Object.keys(validationErrors).length === 0 && onSubmit) {
|
732
|
+
setIsSubmitting(true);
|
733
|
+
setSubmitCount(count => count + 1);
|
734
|
+
try {
|
735
|
+
await onSubmit(values, {
|
736
|
+
fields: Object.keys(values).reduce((acc, key) => {
|
737
|
+
acc[key] = {
|
738
|
+
value: values[key],
|
739
|
+
error: errors[key],
|
740
|
+
touched: touched[key] || false,
|
741
|
+
dirty: dirty[key] || false
|
742
|
+
};
|
743
|
+
return acc;
|
744
|
+
}, {}),
|
745
|
+
isValid,
|
746
|
+
isDirty,
|
747
|
+
isSubmitting: true,
|
748
|
+
submitCount: submitCount + 1
|
749
|
+
});
|
750
|
+
}
|
751
|
+
finally {
|
752
|
+
setIsSubmitting(false);
|
753
|
+
}
|
754
|
+
}
|
755
|
+
};
|
756
|
+
return {
|
757
|
+
values,
|
758
|
+
errors,
|
759
|
+
touched,
|
760
|
+
dirty,
|
761
|
+
isValid,
|
762
|
+
isDirty,
|
763
|
+
isSubmitting,
|
764
|
+
submitCount,
|
765
|
+
handleChange,
|
766
|
+
handleBlur,
|
767
|
+
handleSubmit,
|
768
|
+
setFieldValue,
|
769
|
+
setFieldError,
|
770
|
+
setValues: updateValues,
|
771
|
+
resetForm
|
772
|
+
};
|
773
|
+
}
|
774
|
+
|
775
|
+
function createEventBus() {
|
776
|
+
const events = new Map();
|
777
|
+
const onceHandlers = new WeakMap();
|
778
|
+
const on = (event, handler) => {
|
779
|
+
if (!events.has(event)) {
|
780
|
+
events.set(event, new Set());
|
781
|
+
}
|
782
|
+
events.get(event).add(handler);
|
783
|
+
// Return a function to remove this handler
|
784
|
+
return () => off(event, handler);
|
785
|
+
};
|
786
|
+
const once = (event, handler) => {
|
787
|
+
// Create a wrapper that will call the handler and remove itself
|
788
|
+
const onceWrapper = (...args) => {
|
789
|
+
off(event, onceWrapper);
|
790
|
+
handler(...args);
|
791
|
+
};
|
792
|
+
// Store the mapping between the original handler and the wrapper
|
793
|
+
onceHandlers.set(handler, onceWrapper);
|
794
|
+
// Register the wrapper
|
795
|
+
return on(event, onceWrapper);
|
796
|
+
};
|
797
|
+
const off = (event, handler) => {
|
798
|
+
// If no handler is provided, remove all handlers for the event
|
799
|
+
if (!handler) {
|
800
|
+
events.delete(event);
|
801
|
+
return;
|
802
|
+
}
|
803
|
+
// Check if it's a once handler wrapper
|
804
|
+
const wrappedHandler = onceHandlers.get(handler);
|
805
|
+
const handlerToRemove = wrappedHandler || handler;
|
806
|
+
if (events.has(event)) {
|
807
|
+
events.get(event).delete(handlerToRemove);
|
808
|
+
// Clean up empty event sets
|
809
|
+
if (events.get(event).size === 0) {
|
810
|
+
events.delete(event);
|
811
|
+
}
|
812
|
+
}
|
813
|
+
};
|
814
|
+
const emit = (event, ...args) => {
|
815
|
+
if (!events.has(event)) {
|
816
|
+
return;
|
817
|
+
}
|
818
|
+
// Create a copy of the handlers to avoid issues if handlers modify the set
|
819
|
+
const handlers = Array.from(events.get(event));
|
820
|
+
// Call each handler with the arguments
|
821
|
+
for (const handler of handlers) {
|
822
|
+
handler(...args);
|
823
|
+
}
|
824
|
+
};
|
825
|
+
const clear = (event) => {
|
826
|
+
if (event) {
|
827
|
+
events.delete(event);
|
828
|
+
}
|
829
|
+
else {
|
830
|
+
events.clear();
|
831
|
+
}
|
832
|
+
};
|
833
|
+
return { on, once, off, emit, clear };
|
834
|
+
}
|
835
|
+
// Create a global event bus instance
|
836
|
+
const globalEventBus = createEventBus();
|
837
|
+
// Hook to use the event bus in components
|
838
|
+
function useEvent(event, handler, options = {}) {
|
839
|
+
return options.once
|
840
|
+
? globalEventBus.once(event, handler)
|
841
|
+
: globalEventBus.on(event, handler);
|
842
|
+
}
|
843
|
+
|
844
|
+
/**
|
845
|
+
* Global state management solution similar to Redux
|
846
|
+
*/
|
847
|
+
function createStore(reducer, initialState, middlewares = []) {
|
848
|
+
let state = initialState;
|
849
|
+
let listeners = [];
|
850
|
+
// Apply middlewares
|
851
|
+
let dispatch = (action) => {
|
852
|
+
state = reducer(state, action);
|
853
|
+
listeners.forEach(listener => listener());
|
854
|
+
return action;
|
855
|
+
};
|
856
|
+
// Chain middlewares
|
857
|
+
if (middlewares.length > 0) {
|
858
|
+
const middlewareAPI = {
|
859
|
+
getState: () => state,
|
860
|
+
dispatch: (action) => dispatch(action),
|
861
|
+
subscribe: (listener) => subscribe(listener)
|
862
|
+
};
|
863
|
+
const chain = middlewares.map(middleware => middleware(middlewareAPI));
|
864
|
+
dispatch = chain.reduce((a, b) => (next) => a(b(next)))(dispatch);
|
865
|
+
}
|
866
|
+
// Subscribe to store changes
|
867
|
+
function subscribe(listener) {
|
868
|
+
listeners.push(listener);
|
869
|
+
return function unsubscribe() {
|
870
|
+
listeners = listeners.filter(l => l !== listener);
|
871
|
+
};
|
872
|
+
}
|
873
|
+
// Initialize store with default state
|
874
|
+
dispatch({ type: '@@INIT' });
|
875
|
+
return {
|
876
|
+
getState: () => state,
|
877
|
+
dispatch,
|
878
|
+
subscribe
|
879
|
+
};
|
880
|
+
}
|
881
|
+
const StoreContext = createContext({
|
882
|
+
store: {
|
883
|
+
getState: () => ({}),
|
884
|
+
dispatch: () => { },
|
885
|
+
subscribe: () => () => { }
|
886
|
+
},
|
887
|
+
state: {}
|
888
|
+
});
|
889
|
+
function StoreProvider({ store, children }) {
|
890
|
+
const [state, setState] = useState(store.getState());
|
891
|
+
useEffect(() => {
|
892
|
+
const unsubscribe = store.subscribe(() => {
|
893
|
+
setState(store.getState());
|
894
|
+
});
|
895
|
+
return unsubscribe;
|
896
|
+
}, [store]);
|
897
|
+
return jsx(StoreContext.Provider, {
|
898
|
+
value: { store, state },
|
899
|
+
children
|
900
|
+
});
|
901
|
+
}
|
902
|
+
function useSelector(selector) {
|
903
|
+
const context = useContext();
|
904
|
+
return selector(context.state);
|
905
|
+
}
|
906
|
+
function useDispatch() {
|
907
|
+
const context = useContext();
|
908
|
+
return context.store.dispatch;
|
909
|
+
}
|
910
|
+
function useStore() {
|
911
|
+
const context = useContext();
|
912
|
+
return context.store;
|
913
|
+
}
|
914
|
+
// Common middlewares
|
915
|
+
const logger = (store) => (next) => (action) => {
|
916
|
+
console.group(action.type);
|
917
|
+
console.log('Previous state:', store.getState());
|
918
|
+
console.log('Action:', action);
|
919
|
+
const result = next(action);
|
920
|
+
console.log('Next state:', store.getState());
|
921
|
+
console.groupEnd();
|
922
|
+
return result;
|
923
|
+
};
|
924
|
+
const thunk = (store) => (next) => (action) => {
|
925
|
+
if (typeof action === 'function') {
|
926
|
+
return action(store.dispatch, store.getState);
|
927
|
+
}
|
928
|
+
return next(action);
|
929
|
+
};
|
930
|
+
|
931
|
+
/**
|
932
|
+
* Lifecycle events for components and application
|
933
|
+
*/
|
934
|
+
exports.LifecycleEvents = void 0;
|
935
|
+
(function (LifecycleEvents) {
|
936
|
+
LifecycleEvents["APP_INIT"] = "app:init";
|
937
|
+
LifecycleEvents["APP_MOUNTED"] = "app:mounted";
|
938
|
+
LifecycleEvents["APP_UPDATED"] = "app:updated";
|
939
|
+
LifecycleEvents["APP_ERROR"] = "app:error";
|
940
|
+
LifecycleEvents["APP_DESTROYED"] = "app:destroyed";
|
941
|
+
LifecycleEvents["COMPONENT_CREATED"] = "component:created";
|
942
|
+
LifecycleEvents["COMPONENT_MOUNTED"] = "component:mounted";
|
943
|
+
LifecycleEvents["COMPONENT_UPDATED"] = "component:updated";
|
944
|
+
LifecycleEvents["COMPONENT_ERROR"] = "component:error";
|
945
|
+
LifecycleEvents["COMPONENT_UNMOUNTED"] = "component:unmounted";
|
946
|
+
LifecycleEvents["ROUTER_BEFORE_CHANGE"] = "router:before-change";
|
947
|
+
LifecycleEvents["ROUTER_AFTER_CHANGE"] = "router:after-change";
|
948
|
+
LifecycleEvents["ROUTER_ERROR"] = "router:error";
|
949
|
+
LifecycleEvents["STORE_INITIALIZED"] = "store:initialized";
|
950
|
+
LifecycleEvents["STORE_BEFORE_ACTION"] = "store:before-action";
|
951
|
+
LifecycleEvents["STORE_AFTER_ACTION"] = "store:after-action";
|
952
|
+
LifecycleEvents["STORE_ERROR"] = "store:error";
|
953
|
+
})(exports.LifecycleEvents || (exports.LifecycleEvents = {}));
|
954
|
+
// Event emitters
|
955
|
+
function emitAppInit(data) {
|
956
|
+
globalEventBus.emit(exports.LifecycleEvents.APP_INIT, data);
|
957
|
+
}
|
958
|
+
function emitAppMounted(rootElement) {
|
959
|
+
globalEventBus.emit(exports.LifecycleEvents.APP_MOUNTED, rootElement);
|
960
|
+
}
|
961
|
+
function emitAppUpdated() {
|
962
|
+
globalEventBus.emit(exports.LifecycleEvents.APP_UPDATED);
|
963
|
+
}
|
964
|
+
function emitAppError(error) {
|
965
|
+
globalEventBus.emit(exports.LifecycleEvents.APP_ERROR, error);
|
966
|
+
}
|
967
|
+
function emitAppDestroyed() {
|
968
|
+
globalEventBus.emit(exports.LifecycleEvents.APP_DESTROYED);
|
969
|
+
}
|
970
|
+
function emitComponentCreated(info) {
|
971
|
+
globalEventBus.emit(exports.LifecycleEvents.COMPONENT_CREATED, info);
|
972
|
+
}
|
973
|
+
function emitComponentMounted(info, element) {
|
974
|
+
globalEventBus.emit(exports.LifecycleEvents.COMPONENT_MOUNTED, info, element);
|
975
|
+
}
|
976
|
+
function emitComponentUpdated(info, prevProps, newProps) {
|
977
|
+
globalEventBus.emit(exports.LifecycleEvents.COMPONENT_UPDATED, info, prevProps, newProps);
|
978
|
+
}
|
979
|
+
function emitComponentError(info, error) {
|
980
|
+
globalEventBus.emit(exports.LifecycleEvents.COMPONENT_ERROR, info, error);
|
981
|
+
}
|
982
|
+
function emitComponentUnmounted(info) {
|
983
|
+
globalEventBus.emit(exports.LifecycleEvents.COMPONENT_UNMOUNTED, info);
|
984
|
+
}
|
985
|
+
// Event listeners
|
986
|
+
function onAppInit(handler) {
|
987
|
+
return globalEventBus.on(exports.LifecycleEvents.APP_INIT, handler);
|
988
|
+
}
|
989
|
+
function onAppMounted(handler) {
|
990
|
+
return globalEventBus.on(exports.LifecycleEvents.APP_MOUNTED, handler);
|
991
|
+
}
|
992
|
+
function onAppUpdated(handler) {
|
993
|
+
return globalEventBus.on(exports.LifecycleEvents.APP_UPDATED, handler);
|
994
|
+
}
|
995
|
+
function onAppError(handler) {
|
996
|
+
return globalEventBus.on(exports.LifecycleEvents.APP_ERROR, handler);
|
997
|
+
}
|
998
|
+
function onAppDestroyed(handler) {
|
999
|
+
return globalEventBus.on(exports.LifecycleEvents.APP_DESTROYED, handler);
|
1000
|
+
}
|
1001
|
+
function onComponentCreated(handler) {
|
1002
|
+
return globalEventBus.on(exports.LifecycleEvents.COMPONENT_CREATED, handler);
|
1003
|
+
}
|
1004
|
+
function onComponentMounted(handler) {
|
1005
|
+
return globalEventBus.on(exports.LifecycleEvents.COMPONENT_MOUNTED, handler);
|
1006
|
+
}
|
1007
|
+
function onComponentUpdated(handler) {
|
1008
|
+
return globalEventBus.on(exports.LifecycleEvents.COMPONENT_UPDATED, handler);
|
1009
|
+
}
|
1010
|
+
function onComponentError(handler) {
|
1011
|
+
return globalEventBus.on(exports.LifecycleEvents.COMPONENT_ERROR, handler);
|
1012
|
+
}
|
1013
|
+
function onComponentUnmounted(handler) {
|
1014
|
+
return globalEventBus.on(exports.LifecycleEvents.COMPONENT_UNMOUNTED, handler);
|
1015
|
+
}
|
1016
|
+
|
1017
|
+
// Core JSX and rendering functions
|
1018
|
+
// Default export object for compatibility
|
1019
|
+
const frontendHamroun = {
|
1020
|
+
// JSX
|
1021
|
+
jsx,
|
1022
|
+
jsxs: jsx,
|
1023
|
+
jsxDEV: jsx,
|
1024
|
+
Fragment,
|
1025
|
+
createElement,
|
1026
|
+
// Rendering
|
1027
|
+
render,
|
1028
|
+
hydrate,
|
1029
|
+
// Hooks
|
1030
|
+
useState,
|
1031
|
+
useEffect,
|
1032
|
+
useMemo,
|
1033
|
+
useRef,
|
1034
|
+
useContext,
|
1035
|
+
useErrorBoundary,
|
1036
|
+
// Context
|
1037
|
+
createContext,
|
1038
|
+
// Utilities
|
1039
|
+
batchUpdates,
|
1040
|
+
diff,
|
1041
|
+
shouldComponentUpdate,
|
1042
|
+
// Component class
|
1043
|
+
Component,
|
1044
|
+
// Router
|
1045
|
+
RouterProvider,
|
1046
|
+
Route,
|
1047
|
+
Switch,
|
1048
|
+
Link,
|
1049
|
+
Redirect,
|
1050
|
+
useLocation,
|
1051
|
+
useParams,
|
1052
|
+
useNavigate,
|
1053
|
+
// Forms
|
1054
|
+
useForm,
|
1055
|
+
// Event bus
|
1056
|
+
createEventBus,
|
1057
|
+
useEvent,
|
1058
|
+
eventBus: globalEventBus
|
1059
|
+
};
|
1060
|
+
|
1061
|
+
exports.Component = Component;
|
1062
|
+
exports.Fragment = Fragment;
|
1063
|
+
exports.Link = Link;
|
1064
|
+
exports.Redirect = Redirect;
|
1065
|
+
exports.Route = Route;
|
1066
|
+
exports.RouterProvider = RouterProvider;
|
1067
|
+
exports.StoreProvider = StoreProvider;
|
1068
|
+
exports.Switch = Switch;
|
1069
|
+
exports.batchUpdates = batchUpdates;
|
1070
|
+
exports.createContext = createContext;
|
1071
|
+
exports.createElement = createElement;
|
1072
|
+
exports.createEventBus = createEventBus;
|
1073
|
+
exports.createStore = createStore;
|
1074
|
+
exports.default = frontendHamroun;
|
1075
|
+
exports.diff = diff;
|
1076
|
+
exports.emitAppDestroyed = emitAppDestroyed;
|
1077
|
+
exports.emitAppError = emitAppError;
|
1078
|
+
exports.emitAppInit = emitAppInit;
|
1079
|
+
exports.emitAppMounted = emitAppMounted;
|
1080
|
+
exports.emitAppUpdated = emitAppUpdated;
|
1081
|
+
exports.emitComponentCreated = emitComponentCreated;
|
1082
|
+
exports.emitComponentError = emitComponentError;
|
1083
|
+
exports.emitComponentMounted = emitComponentMounted;
|
1084
|
+
exports.emitComponentUnmounted = emitComponentUnmounted;
|
1085
|
+
exports.emitComponentUpdated = emitComponentUpdated;
|
1086
|
+
exports.eventBus = globalEventBus;
|
1087
|
+
exports.hydrate = hydrate;
|
1088
|
+
exports.jsx = jsx;
|
1089
|
+
exports.jsxDEV = jsx;
|
1090
|
+
exports.jsxs = jsx;
|
1091
|
+
exports.logger = logger;
|
1092
|
+
exports.onAppDestroyed = onAppDestroyed;
|
1093
|
+
exports.onAppError = onAppError;
|
1094
|
+
exports.onAppInit = onAppInit;
|
1095
|
+
exports.onAppMounted = onAppMounted;
|
1096
|
+
exports.onAppUpdated = onAppUpdated;
|
1097
|
+
exports.onComponentCreated = onComponentCreated;
|
1098
|
+
exports.onComponentError = onComponentError;
|
1099
|
+
exports.onComponentMounted = onComponentMounted;
|
1100
|
+
exports.onComponentUnmounted = onComponentUnmounted;
|
1101
|
+
exports.onComponentUpdated = onComponentUpdated;
|
1102
|
+
exports.render = render;
|
1103
|
+
exports.shouldComponentUpdate = shouldComponentUpdate;
|
1104
|
+
exports.thunk = thunk;
|
1105
|
+
exports.useContext = useContext;
|
1106
|
+
exports.useDispatch = useDispatch;
|
1107
|
+
exports.useEffect = useEffect;
|
1108
|
+
exports.useErrorBoundary = useErrorBoundary;
|
1109
|
+
exports.useEvent = useEvent;
|
1110
|
+
exports.useForm = useForm;
|
1111
|
+
exports.useLocation = useLocation;
|
1112
|
+
exports.useMemo = useMemo;
|
1113
|
+
exports.useNavigate = useNavigate;
|
1114
|
+
exports.useParams = useParams;
|
1115
|
+
exports.useRef = useRef;
|
1116
|
+
exports.useSelector = useSelector;
|
1117
|
+
exports.useState = useState;
|
1118
|
+
exports.useStore = useStore;
|
2
1119
|
//# sourceMappingURL=index.cjs.map
|