@mulanjs/mulanjs 1.0.1-dev.20260220155535 → 1.0.1-dev.20260222103836
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/core/hooks.js +142 -0
- package/dist/mulan.esm.js +149 -1
- package/dist/mulan.esm.js.map +1 -1
- package/dist/mulan.js +149 -1
- package/dist/mulan.js.map +1 -1
- package/dist/types/core/hooks.d.ts +37 -0
- package/dist/types/index.d.ts +16 -0
- package/package.json +1 -1
package/dist/core/hooks.js
CHANGED
|
@@ -227,3 +227,145 @@ export function muPulse() {
|
|
|
227
227
|
export function muVault(key, initial, options = {}) {
|
|
228
228
|
return persistent(key, initial, Object.assign(Object.assign({}, options), { onCleanup: (fn) => onMuDestroy(fn) }));
|
|
229
229
|
}
|
|
230
|
+
// --- Next-Gen MulanJS Hooks ---
|
|
231
|
+
/**
|
|
232
|
+
* muSuspense - The Asynchronous Barrier.
|
|
233
|
+
* Natively handles async state (loading/data/error) without wrapper components.
|
|
234
|
+
*/
|
|
235
|
+
export function muSuspense(promiseFn) {
|
|
236
|
+
const state = muState({
|
|
237
|
+
loading: true,
|
|
238
|
+
data: null,
|
|
239
|
+
error: null
|
|
240
|
+
});
|
|
241
|
+
// Execute immediately safely
|
|
242
|
+
promiseFn()
|
|
243
|
+
.then(res => {
|
|
244
|
+
state.data = res;
|
|
245
|
+
state.loading = false;
|
|
246
|
+
})
|
|
247
|
+
.catch(err => {
|
|
248
|
+
state.error = err;
|
|
249
|
+
state.loading = false;
|
|
250
|
+
});
|
|
251
|
+
return state;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* onMuVisibility - The Intersection Observer Hook.
|
|
255
|
+
* Triggers when the component enters/leaves the viewport.
|
|
256
|
+
*/
|
|
257
|
+
export function onMuVisibility(callback, options = { threshold: 0.1 }) {
|
|
258
|
+
const instance = getCurrentInstance();
|
|
259
|
+
// We defer observation to mount phase to ensure DOM exists
|
|
260
|
+
onMuMount(() => {
|
|
261
|
+
if (!instance || !instance.container)
|
|
262
|
+
return;
|
|
263
|
+
const observer = new IntersectionObserver((entries) => {
|
|
264
|
+
entries.forEach(entry => {
|
|
265
|
+
callback(entry.isIntersecting);
|
|
266
|
+
});
|
|
267
|
+
}, options);
|
|
268
|
+
observer.observe(instance.container);
|
|
269
|
+
onMuDestroy(() => {
|
|
270
|
+
observer.disconnect();
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* muDebounced - High-performance debouncing built directly into a reactive signal.
|
|
276
|
+
*/
|
|
277
|
+
export function muDebounced(initialValue, delayMs) {
|
|
278
|
+
const state = muState(initialValue);
|
|
279
|
+
let timeoutId;
|
|
280
|
+
return {
|
|
281
|
+
get value() {
|
|
282
|
+
return state.value;
|
|
283
|
+
},
|
|
284
|
+
set value(newVal) {
|
|
285
|
+
clearTimeout(timeoutId);
|
|
286
|
+
timeoutId = setTimeout(() => {
|
|
287
|
+
state.value = newVal;
|
|
288
|
+
}, delayMs);
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* muThrottled - High-performance throttling built directly into a reactive signal.
|
|
294
|
+
*/
|
|
295
|
+
export function muThrottled(initialValue, delayMs) {
|
|
296
|
+
const state = muState(initialValue);
|
|
297
|
+
let lastRan = 0;
|
|
298
|
+
return {
|
|
299
|
+
get value() {
|
|
300
|
+
return state.value;
|
|
301
|
+
},
|
|
302
|
+
set value(newVal) {
|
|
303
|
+
const now = Date.now();
|
|
304
|
+
if (now - lastRan >= delayMs) {
|
|
305
|
+
state.value = newVal;
|
|
306
|
+
lastRan = now;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* onMuPanic - The Iron Fortress Error Boundary.
|
|
313
|
+
* Catches unhandled exceptions within the component scope.
|
|
314
|
+
*/
|
|
315
|
+
export function onMuPanic(fallbackFn) {
|
|
316
|
+
const instance = getCurrentInstance();
|
|
317
|
+
const handler = (event) => {
|
|
318
|
+
// Broad catch - in a full implementation, we'd inspect the stack trace
|
|
319
|
+
// to isolate if it originated from `instance` specifically.
|
|
320
|
+
// For Mulan 2.0 MVP, we execute the fallback.
|
|
321
|
+
const error = event instanceof ErrorEvent ? event.error : event.reason;
|
|
322
|
+
console.error(`[Iron Fortress] Component ${(instance === null || instance === void 0 ? void 0 : instance.$uid) || 'Unknown'} Panic:`, error);
|
|
323
|
+
fallbackFn(error);
|
|
324
|
+
// Prevent default browser crash if handled
|
|
325
|
+
event.preventDefault();
|
|
326
|
+
};
|
|
327
|
+
window.addEventListener('error', handler);
|
|
328
|
+
window.addEventListener('unhandledrejection', handler);
|
|
329
|
+
onMuDestroy(() => {
|
|
330
|
+
window.removeEventListener('error', handler);
|
|
331
|
+
window.removeEventListener('unhandledrejection', handler);
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* muHistory - State with built-in Undo/Redo tracking.
|
|
336
|
+
*/
|
|
337
|
+
export function muHistory(initialValue) {
|
|
338
|
+
const state = muState(initialValue);
|
|
339
|
+
// Explicit wrapper object because muState treats bare arrays dynamically
|
|
340
|
+
const historyTracker = muState({ log: [initialValue] });
|
|
341
|
+
const pointer = muState(0);
|
|
342
|
+
const updateValue = (newVal) => {
|
|
343
|
+
// If we are back in history and make a NEW change, we drop the 'future'
|
|
344
|
+
if (pointer.value < historyTracker.log.length - 1) {
|
|
345
|
+
historyTracker.log = historyTracker.log.slice(0, pointer.value + 1);
|
|
346
|
+
}
|
|
347
|
+
historyTracker.log.push(newVal);
|
|
348
|
+
pointer.value = historyTracker.log.length - 1;
|
|
349
|
+
state.value = newVal;
|
|
350
|
+
};
|
|
351
|
+
const undo = () => {
|
|
352
|
+
if (pointer.value > 0) {
|
|
353
|
+
pointer.value--;
|
|
354
|
+
state.value = historyTracker.log[pointer.value];
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
const redo = () => {
|
|
358
|
+
if (pointer.value < historyTracker.log.length - 1) {
|
|
359
|
+
pointer.value++;
|
|
360
|
+
state.value = historyTracker.log[pointer.value];
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
return {
|
|
364
|
+
get value() { return state.value; },
|
|
365
|
+
set value(newVal) { updateValue(newVal); },
|
|
366
|
+
undo,
|
|
367
|
+
redo,
|
|
368
|
+
get past() { return historyTracker.log.slice(0, pointer.value); },
|
|
369
|
+
get future() { return historyTracker.log.slice(pointer.value + 1); }
|
|
370
|
+
};
|
|
371
|
+
}
|
package/dist/mulan.esm.js
CHANGED
|
@@ -38,18 +38,24 @@ var hooks_namespaceObject = {};
|
|
|
38
38
|
__webpack_require__.r(hooks_namespaceObject);
|
|
39
39
|
__webpack_require__.d(hooks_namespaceObject, {
|
|
40
40
|
getCurrentInstance: () => (getCurrentInstance),
|
|
41
|
+
muDebounced: () => (muDebounced),
|
|
41
42
|
muEffect: () => (muEffect),
|
|
42
43
|
muGeom: () => (muGeom),
|
|
44
|
+
muHistory: () => (muHistory),
|
|
43
45
|
muMemo: () => (muMemo),
|
|
44
46
|
muPulse: () => (muPulse),
|
|
45
47
|
muState: () => (muState),
|
|
48
|
+
muSuspense: () => (muSuspense),
|
|
49
|
+
muThrottled: () => (muThrottled),
|
|
46
50
|
muVault: () => (muVault),
|
|
47
51
|
onMuDestroy: () => (onMuDestroy),
|
|
48
52
|
onMuIdle: () => (onMuIdle),
|
|
49
53
|
onMuInit: () => (onMuInit),
|
|
50
54
|
onMuMount: () => (onMuMount),
|
|
55
|
+
onMuPanic: () => (onMuPanic),
|
|
51
56
|
onMuResume: () => (onMuResume),
|
|
52
57
|
onMuShake: () => (onMuShake),
|
|
58
|
+
onMuVisibility: () => (onMuVisibility),
|
|
53
59
|
onMuVoice: () => (onMuVoice),
|
|
54
60
|
setCurrentInstance: () => (setCurrentInstance)
|
|
55
61
|
});
|
|
@@ -601,6 +607,148 @@ function muPulse() {
|
|
|
601
607
|
function muVault(key, initial, options = {}) {
|
|
602
608
|
return persistent(key, initial, Object.assign(Object.assign({}, options), { onCleanup: (fn) => onMuDestroy(fn) }));
|
|
603
609
|
}
|
|
610
|
+
// --- Next-Gen MulanJS Hooks ---
|
|
611
|
+
/**
|
|
612
|
+
* muSuspense - The Asynchronous Barrier.
|
|
613
|
+
* Natively handles async state (loading/data/error) without wrapper components.
|
|
614
|
+
*/
|
|
615
|
+
function muSuspense(promiseFn) {
|
|
616
|
+
const state = muState({
|
|
617
|
+
loading: true,
|
|
618
|
+
data: null,
|
|
619
|
+
error: null
|
|
620
|
+
});
|
|
621
|
+
// Execute immediately safely
|
|
622
|
+
promiseFn()
|
|
623
|
+
.then(res => {
|
|
624
|
+
state.data = res;
|
|
625
|
+
state.loading = false;
|
|
626
|
+
})
|
|
627
|
+
.catch(err => {
|
|
628
|
+
state.error = err;
|
|
629
|
+
state.loading = false;
|
|
630
|
+
});
|
|
631
|
+
return state;
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* onMuVisibility - The Intersection Observer Hook.
|
|
635
|
+
* Triggers when the component enters/leaves the viewport.
|
|
636
|
+
*/
|
|
637
|
+
function onMuVisibility(callback, options = { threshold: 0.1 }) {
|
|
638
|
+
const instance = getCurrentInstance();
|
|
639
|
+
// We defer observation to mount phase to ensure DOM exists
|
|
640
|
+
onMuMount(() => {
|
|
641
|
+
if (!instance || !instance.container)
|
|
642
|
+
return;
|
|
643
|
+
const observer = new IntersectionObserver((entries) => {
|
|
644
|
+
entries.forEach(entry => {
|
|
645
|
+
callback(entry.isIntersecting);
|
|
646
|
+
});
|
|
647
|
+
}, options);
|
|
648
|
+
observer.observe(instance.container);
|
|
649
|
+
onMuDestroy(() => {
|
|
650
|
+
observer.disconnect();
|
|
651
|
+
});
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* muDebounced - High-performance debouncing built directly into a reactive signal.
|
|
656
|
+
*/
|
|
657
|
+
function muDebounced(initialValue, delayMs) {
|
|
658
|
+
const state = muState(initialValue);
|
|
659
|
+
let timeoutId;
|
|
660
|
+
return {
|
|
661
|
+
get value() {
|
|
662
|
+
return state.value;
|
|
663
|
+
},
|
|
664
|
+
set value(newVal) {
|
|
665
|
+
clearTimeout(timeoutId);
|
|
666
|
+
timeoutId = setTimeout(() => {
|
|
667
|
+
state.value = newVal;
|
|
668
|
+
}, delayMs);
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* muThrottled - High-performance throttling built directly into a reactive signal.
|
|
674
|
+
*/
|
|
675
|
+
function muThrottled(initialValue, delayMs) {
|
|
676
|
+
const state = muState(initialValue);
|
|
677
|
+
let lastRan = 0;
|
|
678
|
+
return {
|
|
679
|
+
get value() {
|
|
680
|
+
return state.value;
|
|
681
|
+
},
|
|
682
|
+
set value(newVal) {
|
|
683
|
+
const now = Date.now();
|
|
684
|
+
if (now - lastRan >= delayMs) {
|
|
685
|
+
state.value = newVal;
|
|
686
|
+
lastRan = now;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* onMuPanic - The Iron Fortress Error Boundary.
|
|
693
|
+
* Catches unhandled exceptions within the component scope.
|
|
694
|
+
*/
|
|
695
|
+
function onMuPanic(fallbackFn) {
|
|
696
|
+
const instance = getCurrentInstance();
|
|
697
|
+
const handler = (event) => {
|
|
698
|
+
// Broad catch - in a full implementation, we'd inspect the stack trace
|
|
699
|
+
// to isolate if it originated from `instance` specifically.
|
|
700
|
+
// For Mulan 2.0 MVP, we execute the fallback.
|
|
701
|
+
const error = event instanceof ErrorEvent ? event.error : event.reason;
|
|
702
|
+
console.error(`[Iron Fortress] Component ${(instance === null || instance === void 0 ? void 0 : instance.$uid) || 'Unknown'} Panic:`, error);
|
|
703
|
+
fallbackFn(error);
|
|
704
|
+
// Prevent default browser crash if handled
|
|
705
|
+
event.preventDefault();
|
|
706
|
+
};
|
|
707
|
+
window.addEventListener('error', handler);
|
|
708
|
+
window.addEventListener('unhandledrejection', handler);
|
|
709
|
+
onMuDestroy(() => {
|
|
710
|
+
window.removeEventListener('error', handler);
|
|
711
|
+
window.removeEventListener('unhandledrejection', handler);
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* muHistory - State with built-in Undo/Redo tracking.
|
|
716
|
+
*/
|
|
717
|
+
function muHistory(initialValue) {
|
|
718
|
+
const state = muState(initialValue);
|
|
719
|
+
// Explicit wrapper object because muState treats bare arrays dynamically
|
|
720
|
+
const historyTracker = muState({ log: [initialValue] });
|
|
721
|
+
const pointer = muState(0);
|
|
722
|
+
const updateValue = (newVal) => {
|
|
723
|
+
// If we are back in history and make a NEW change, we drop the 'future'
|
|
724
|
+
if (pointer.value < historyTracker.log.length - 1) {
|
|
725
|
+
historyTracker.log = historyTracker.log.slice(0, pointer.value + 1);
|
|
726
|
+
}
|
|
727
|
+
historyTracker.log.push(newVal);
|
|
728
|
+
pointer.value = historyTracker.log.length - 1;
|
|
729
|
+
state.value = newVal;
|
|
730
|
+
};
|
|
731
|
+
const undo = () => {
|
|
732
|
+
if (pointer.value > 0) {
|
|
733
|
+
pointer.value--;
|
|
734
|
+
state.value = historyTracker.log[pointer.value];
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
const redo = () => {
|
|
738
|
+
if (pointer.value < historyTracker.log.length - 1) {
|
|
739
|
+
pointer.value++;
|
|
740
|
+
state.value = historyTracker.log[pointer.value];
|
|
741
|
+
}
|
|
742
|
+
};
|
|
743
|
+
return {
|
|
744
|
+
get value() { return state.value; },
|
|
745
|
+
set value(newVal) { updateValue(newVal); },
|
|
746
|
+
undo,
|
|
747
|
+
redo,
|
|
748
|
+
get past() { return historyTracker.log.slice(0, pointer.value); },
|
|
749
|
+
get future() { return historyTracker.log.slice(pointer.value + 1); }
|
|
750
|
+
};
|
|
751
|
+
}
|
|
604
752
|
|
|
605
753
|
;// ./src/core/component.ts
|
|
606
754
|
|
|
@@ -2059,6 +2207,6 @@ if (typeof window !== 'undefined') {
|
|
|
2059
2207
|
}
|
|
2060
2208
|
/* harmony default export */ const src = (Mulan);
|
|
2061
2209
|
|
|
2062
|
-
export { MuComponent as Component, MuBlochSphereElement, MuComponent, MuInfinity, MuRouter, MuStore, MuRouter as Router, Security, Signal, activeControls, src as default, defineComponent, effect, getCurrentInstance, hydrate, muBurst, muControl, muEffect, muEntangle, muGate, muGeom, muMeasure, muMemo, muParallel, muPulse, muQubit, muRegister, muSearch, muState, muSurge, muSwitch, muTeleport, muVault, onMuDestroy, onMuIdle, onMuInit, onMuMount, onMuResume, onMuShake, onMuVoice, persistent, reactive, ref, render, renderToString, sanitize, setCurrentInstance, useMutation, useQuery };
|
|
2210
|
+
export { MuComponent as Component, MuBlochSphereElement, MuComponent, MuInfinity, MuRouter, MuStore, MuRouter as Router, Security, Signal, activeControls, src as default, defineComponent, effect, getCurrentInstance, hydrate, muBurst, muControl, muDebounced, muEffect, muEntangle, muGate, muGeom, muHistory, muMeasure, muMemo, muParallel, muPulse, muQubit, muRegister, muSearch, muState, muSurge, muSuspense, muSwitch, muTeleport, muThrottled, muVault, onMuDestroy, onMuIdle, onMuInit, onMuMount, onMuPanic, onMuResume, onMuShake, onMuVisibility, onMuVoice, persistent, reactive, ref, render, renderToString, sanitize, setCurrentInstance, useMutation, useQuery };
|
|
2063
2211
|
|
|
2064
2212
|
//# sourceMappingURL=mulan.esm.js.map
|