@unsetsoft/ryunixjs 1.2.3-canary.10 → 1.2.3-canary.11
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/Ryunix.esm.js +438 -364
- package/dist/Ryunix.esm.js.map +1 -1
- package/dist/Ryunix.umd.js +442 -363
- package/dist/Ryunix.umd.js.map +1 -1
- package/dist/Ryunix.umd.min.js +1 -1
- package/dist/Ryunix.umd.min.js.map +1 -1
- package/package.json +1 -1
package/dist/Ryunix.umd.js
CHANGED
|
@@ -593,34 +593,6 @@
|
|
|
593
593
|
});
|
|
594
594
|
};
|
|
595
595
|
|
|
596
|
-
const updateFunctionComponent = (fiber) => {
|
|
597
|
-
const state = getState();
|
|
598
|
-
state.wipFiber = fiber;
|
|
599
|
-
state.hookIndex = 0;
|
|
600
|
-
state.wipFiber.hooks = [];
|
|
601
|
-
|
|
602
|
-
const children = [fiber.type(fiber.props)];
|
|
603
|
-
|
|
604
|
-
if (fiber.type._contextId && fiber.props.value !== undefined) {
|
|
605
|
-
fiber._contextId = fiber.type._contextId;
|
|
606
|
-
fiber._contextValue = fiber.props.value;
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
reconcileChildren(fiber, children);
|
|
610
|
-
};
|
|
611
|
-
|
|
612
|
-
const updateHostComponent = (fiber) => {
|
|
613
|
-
if (!fiber.dom) {
|
|
614
|
-
fiber.dom = createDom(fiber);
|
|
615
|
-
}
|
|
616
|
-
const children = fiber.props?.children || [];
|
|
617
|
-
reconcileChildren(fiber, children);
|
|
618
|
-
};
|
|
619
|
-
|
|
620
|
-
const Image = ({ src, ...props }) => {
|
|
621
|
-
return createElement('img', { ...props, src })
|
|
622
|
-
};
|
|
623
|
-
|
|
624
596
|
/**
|
|
625
597
|
* Priority levels for updates
|
|
626
598
|
*/
|
|
@@ -634,371 +606,130 @@
|
|
|
634
606
|
|
|
635
607
|
Priority.NORMAL;
|
|
636
608
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
this.measures = new Map();
|
|
644
|
-
this.renderTimes = [];
|
|
645
|
-
this.maxSamples = 100;
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
startMeasure(name) {
|
|
649
|
-
if (!this.enabled) return
|
|
650
|
-
this.measures.set(name, performance.now());
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
endMeasure(name) {
|
|
654
|
-
if (!this.enabled) return
|
|
655
|
-
const start = this.measures.get(name);
|
|
656
|
-
if (!start) return
|
|
657
|
-
|
|
658
|
-
const duration = performance.now() - start;
|
|
659
|
-
this.measures.delete(name);
|
|
660
|
-
|
|
661
|
-
return duration
|
|
609
|
+
const validateHookCall = () => {
|
|
610
|
+
const state = getState();
|
|
611
|
+
if (!state.wipFiber) {
|
|
612
|
+
throw new Error(
|
|
613
|
+
'Hooks can only be called inside the body of a function component.',
|
|
614
|
+
)
|
|
662
615
|
}
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
if (!this.enabled) return
|
|
666
|
-
|
|
667
|
-
this.renderTimes.push({
|
|
668
|
-
component: componentName,
|
|
669
|
-
duration,
|
|
670
|
-
timestamp: Date.now(),
|
|
671
|
-
});
|
|
672
|
-
|
|
673
|
-
if (this.renderTimes.length > this.maxSamples) {
|
|
674
|
-
this.renderTimes.shift();
|
|
675
|
-
}
|
|
616
|
+
if (!Array.isArray(state.wipFiber.hooks)) {
|
|
617
|
+
state.wipFiber.hooks = [];
|
|
676
618
|
}
|
|
619
|
+
};
|
|
677
620
|
|
|
678
|
-
|
|
679
|
-
|
|
621
|
+
const haveDepsChanged = (oldDeps, newDeps) => {
|
|
622
|
+
if (!oldDeps || !newDeps) return true
|
|
623
|
+
if (oldDeps.length !== newDeps.length) return true
|
|
624
|
+
return oldDeps.some((dep, i) => !Object.is(dep, newDeps[i]))
|
|
625
|
+
};
|
|
680
626
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
627
|
+
const useStore = (initialState) => {
|
|
628
|
+
const reducer = (state, action) =>
|
|
629
|
+
is.function(action) ? action(state) : action;
|
|
630
|
+
return useReducer(reducer, initialState)
|
|
631
|
+
};
|
|
685
632
|
|
|
686
|
-
|
|
687
|
-
|
|
633
|
+
const useReducer = (reducer, initialState, init) => {
|
|
634
|
+
validateHookCall();
|
|
688
635
|
|
|
689
|
-
|
|
690
|
-
|
|
636
|
+
const state = getState();
|
|
637
|
+
const { wipFiber, hookIndex } = state;
|
|
638
|
+
const oldHook = wipFiber.alternate?.hooks?.[hookIndex];
|
|
691
639
|
|
|
692
|
-
|
|
640
|
+
const hook = {
|
|
641
|
+
hookID: hookIndex,
|
|
642
|
+
type: RYUNIX_TYPES.RYUNIX_STORE,
|
|
643
|
+
state: oldHook ? oldHook.state : init ? init(initialState) : initialState,
|
|
644
|
+
queue: [], // Siempre nueva cola vacía
|
|
645
|
+
};
|
|
693
646
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
647
|
+
// Procesar acciones del render anterior
|
|
648
|
+
if (oldHook?.queue) {
|
|
649
|
+
oldHook.queue.forEach((action) => {
|
|
650
|
+
try {
|
|
651
|
+
hook.state = reducer(hook.state, action);
|
|
652
|
+
} catch (error) {
|
|
653
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
654
|
+
console.error('Error in reducer:', error);
|
|
655
|
+
}
|
|
697
656
|
}
|
|
698
|
-
const stats = byComponent.get(component);
|
|
699
|
-
stats.total += duration;
|
|
700
|
-
stats.count++;
|
|
701
|
-
stats.max = Math.max(stats.max, duration);
|
|
702
657
|
});
|
|
703
|
-
|
|
704
|
-
return Array.from(byComponent.entries())
|
|
705
|
-
.map(([name, stats]) => ({
|
|
706
|
-
name,
|
|
707
|
-
avg: stats.total / stats.count,
|
|
708
|
-
max: stats.max,
|
|
709
|
-
count: stats.count,
|
|
710
|
-
}))
|
|
711
|
-
.sort((a, b) => b.avg - a.avg)
|
|
712
|
-
.slice(0, limit)
|
|
713
658
|
}
|
|
714
659
|
|
|
715
|
-
|
|
716
|
-
if (
|
|
660
|
+
const dispatch = (action) => {
|
|
661
|
+
if (action === undefined) {
|
|
662
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
663
|
+
console.warn('dispatch called with undefined action');
|
|
664
|
+
}
|
|
665
|
+
return
|
|
666
|
+
}
|
|
717
667
|
|
|
718
|
-
|
|
719
|
-
if (!stats) return
|
|
668
|
+
hook.queue.push(action);
|
|
720
669
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
670
|
+
const currentState = getState();
|
|
671
|
+
currentState.wipRoot = {
|
|
672
|
+
dom: currentState.currentRoot.dom,
|
|
673
|
+
props: currentState.currentRoot.props,
|
|
674
|
+
alternate: currentState.currentRoot,
|
|
675
|
+
};
|
|
676
|
+
currentState.deletions = [];
|
|
677
|
+
currentState.hookIndex = 0;
|
|
678
|
+
scheduleWork(currentState.wipRoot);
|
|
679
|
+
};
|
|
727
680
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
console.log(
|
|
733
|
-
`${i + 1}. ${comp.name}: ${comp.avg.toFixed(2)}ms avg (${comp.count} renders)`,
|
|
734
|
-
);
|
|
735
|
-
});
|
|
736
|
-
}
|
|
737
|
-
console.groupEnd();
|
|
738
|
-
}
|
|
681
|
+
wipFiber.hooks[hookIndex] = hook;
|
|
682
|
+
state.hookIndex++;
|
|
683
|
+
return [hook.state, dispatch]
|
|
684
|
+
};
|
|
739
685
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
this.measures.clear();
|
|
743
|
-
}
|
|
686
|
+
const useEffect = (callback, deps) => {
|
|
687
|
+
validateHookCall();
|
|
744
688
|
|
|
745
|
-
|
|
746
|
-
|
|
689
|
+
if (!is.function(callback)) {
|
|
690
|
+
throw new Error('useEffect callback must be a function')
|
|
747
691
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
this.enabled = false;
|
|
692
|
+
if (deps !== undefined && !Array.isArray(deps)) {
|
|
693
|
+
throw new Error('useEffect dependencies must be an array or undefined')
|
|
751
694
|
}
|
|
752
|
-
}
|
|
753
695
|
|
|
754
|
-
|
|
755
|
-
|
|
696
|
+
const state = getState();
|
|
697
|
+
const { wipFiber, hookIndex } = state;
|
|
698
|
+
const oldHook = wipFiber.alternate?.hooks?.[hookIndex];
|
|
699
|
+
const hasChanged = haveDepsChanged(oldHook?.deps, deps);
|
|
756
700
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
701
|
+
const hook = {
|
|
702
|
+
hookID: hookIndex,
|
|
703
|
+
type: RYUNIX_TYPES.RYUNIX_EFFECT,
|
|
704
|
+
deps,
|
|
705
|
+
effect: hasChanged ? callback : null,
|
|
706
|
+
cancel: oldHook?.cancel,
|
|
707
|
+
};
|
|
762
708
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
profiler.recordRender(componentName, duration);
|
|
766
|
-
}
|
|
709
|
+
wipFiber.hooks[hookIndex] = hook;
|
|
710
|
+
state.hookIndex++;
|
|
767
711
|
};
|
|
768
712
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
*/
|
|
772
|
-
const withProfiler = (Component, name) => {
|
|
773
|
-
return (props) => {
|
|
774
|
-
profiler.startMeasure(name);
|
|
775
|
-
const result = Component(props);
|
|
776
|
-
const duration = profiler.endMeasure(name);
|
|
777
|
-
if (duration) profiler.recordRender(name, duration);
|
|
778
|
-
return result
|
|
779
|
-
}
|
|
780
|
-
};
|
|
713
|
+
const useRef = (initialValue) => {
|
|
714
|
+
validateHookCall();
|
|
781
715
|
|
|
782
|
-
const workLoop = (deadline) => {
|
|
783
716
|
const state = getState();
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
while (state.nextUnitOfWork && !shouldYield) {
|
|
787
|
-
state.nextUnitOfWork = performUnitOfWork(state.nextUnitOfWork);
|
|
788
|
-
shouldYield = deadline.timeRemaining() < 1;
|
|
789
|
-
}
|
|
717
|
+
const { wipFiber, hookIndex } = state;
|
|
718
|
+
const oldHook = wipFiber.alternate?.hooks?.[hookIndex];
|
|
790
719
|
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
720
|
+
const hook = {
|
|
721
|
+
hookID: hookIndex,
|
|
722
|
+
type: RYUNIX_TYPES.RYUNIX_REF,
|
|
723
|
+
value: oldHook ? oldHook.value : { current: initialValue },
|
|
724
|
+
};
|
|
794
725
|
|
|
795
|
-
|
|
726
|
+
wipFiber.hooks[hookIndex] = hook;
|
|
727
|
+
state.hookIndex++;
|
|
728
|
+
return hook.value
|
|
796
729
|
};
|
|
797
730
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
const performUnitOfWork = (fiber) => {
|
|
801
|
-
const componentName = fiber.type?.name || fiber.type?.displayName || 'Unknown';
|
|
802
|
-
|
|
803
|
-
profiler.startMeasure(componentName);
|
|
804
|
-
|
|
805
|
-
const isFunctionComponent = fiber.type instanceof Function;
|
|
806
|
-
if (isFunctionComponent) {
|
|
807
|
-
updateFunctionComponent(fiber);
|
|
808
|
-
} else {
|
|
809
|
-
updateHostComponent(fiber);
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
const duration = profiler.endMeasure(componentName);
|
|
813
|
-
if (duration) profiler.recordRender(componentName, duration);
|
|
814
|
-
|
|
815
|
-
if (fiber.child) {
|
|
816
|
-
return fiber.child
|
|
817
|
-
}
|
|
818
|
-
let nextFiber = fiber;
|
|
819
|
-
while (nextFiber) {
|
|
820
|
-
if (nextFiber.sibling) {
|
|
821
|
-
return nextFiber.sibling
|
|
822
|
-
}
|
|
823
|
-
nextFiber = nextFiber.parent;
|
|
824
|
-
}
|
|
825
|
-
};
|
|
826
|
-
|
|
827
|
-
const scheduleWork = (root, priority = Priority.NORMAL) => {
|
|
828
|
-
const state = getState();
|
|
829
|
-
state.nextUnitOfWork = root;
|
|
830
|
-
state.wipRoot = root;
|
|
831
|
-
state.deletions = [];
|
|
832
|
-
state.hookIndex = 0;
|
|
833
|
-
state.effects = [];
|
|
834
|
-
|
|
835
|
-
// Higher priority = faster scheduling
|
|
836
|
-
if (priority <= Priority.USER_BLOCKING) {
|
|
837
|
-
requestIdleCallback(workLoop);
|
|
838
|
-
} else {
|
|
839
|
-
setTimeout(() => requestIdleCallback(workLoop), 0);
|
|
840
|
-
}
|
|
841
|
-
};
|
|
842
|
-
|
|
843
|
-
const render = (element, container) => {
|
|
844
|
-
const state = getState();
|
|
845
|
-
state.wipRoot = {
|
|
846
|
-
dom: container,
|
|
847
|
-
props: {
|
|
848
|
-
children: [element],
|
|
849
|
-
},
|
|
850
|
-
alternate: state.currentRoot,
|
|
851
|
-
};
|
|
852
|
-
|
|
853
|
-
state.nextUnitOfWork = state.wipRoot;
|
|
854
|
-
state.deletions = [];
|
|
855
|
-
scheduleWork(state.wipRoot);
|
|
856
|
-
return state.wipRoot
|
|
857
|
-
};
|
|
858
|
-
|
|
859
|
-
const init = (MainElement, root = '__ryunix') => {
|
|
860
|
-
const state = getState();
|
|
861
|
-
state.containerRoot = document.getElementById(root);
|
|
862
|
-
const renderProcess = render(MainElement, state.containerRoot);
|
|
863
|
-
return renderProcess
|
|
864
|
-
};
|
|
865
|
-
|
|
866
|
-
const safeRender = (component, props, onError) => {
|
|
867
|
-
try {
|
|
868
|
-
return component(props)
|
|
869
|
-
} catch (error) {
|
|
870
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
871
|
-
console.error('Component error:', error);
|
|
872
|
-
}
|
|
873
|
-
if (onError) onError(error);
|
|
874
|
-
return null
|
|
875
|
-
}
|
|
876
|
-
};
|
|
877
|
-
|
|
878
|
-
const validateHookCall = () => {
|
|
879
|
-
const state = getState();
|
|
880
|
-
if (!state.wipFiber) {
|
|
881
|
-
throw new Error(
|
|
882
|
-
'Hooks can only be called inside the body of a function component.',
|
|
883
|
-
)
|
|
884
|
-
}
|
|
885
|
-
if (!Array.isArray(state.wipFiber.hooks)) {
|
|
886
|
-
state.wipFiber.hooks = [];
|
|
887
|
-
}
|
|
888
|
-
};
|
|
889
|
-
|
|
890
|
-
const haveDepsChanged = (oldDeps, newDeps) => {
|
|
891
|
-
if (!oldDeps || !newDeps) return true
|
|
892
|
-
if (oldDeps.length !== newDeps.length) return true
|
|
893
|
-
return oldDeps.some((dep, i) => !Object.is(dep, newDeps[i]))
|
|
894
|
-
};
|
|
895
|
-
|
|
896
|
-
const useStore = (initialState) => {
|
|
897
|
-
const reducer = (state, action) =>
|
|
898
|
-
is.function(action) ? action(state) : action;
|
|
899
|
-
return useReducer(reducer, initialState)
|
|
900
|
-
};
|
|
901
|
-
|
|
902
|
-
const useReducer = (reducer, initialState, init) => {
|
|
903
|
-
validateHookCall();
|
|
904
|
-
|
|
905
|
-
const state = getState();
|
|
906
|
-
const { wipFiber, hookIndex } = state;
|
|
907
|
-
const oldHook = wipFiber.alternate?.hooks?.[hookIndex];
|
|
908
|
-
|
|
909
|
-
const hook = {
|
|
910
|
-
hookID: hookIndex,
|
|
911
|
-
type: RYUNIX_TYPES.RYUNIX_STORE,
|
|
912
|
-
state: oldHook ? oldHook.state : init ? init(initialState) : initialState,
|
|
913
|
-
queue: [], // Siempre nueva cola vacía
|
|
914
|
-
};
|
|
915
|
-
|
|
916
|
-
// Procesar acciones del render anterior
|
|
917
|
-
if (oldHook?.queue) {
|
|
918
|
-
oldHook.queue.forEach((action) => {
|
|
919
|
-
try {
|
|
920
|
-
hook.state = reducer(hook.state, action);
|
|
921
|
-
} catch (error) {
|
|
922
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
923
|
-
console.error('Error in reducer:', error);
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
});
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
const dispatch = (action) => {
|
|
930
|
-
if (action === undefined) {
|
|
931
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
932
|
-
console.warn('dispatch called with undefined action');
|
|
933
|
-
}
|
|
934
|
-
return
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
hook.queue.push(action);
|
|
938
|
-
|
|
939
|
-
const currentState = getState();
|
|
940
|
-
currentState.wipRoot = {
|
|
941
|
-
dom: currentState.currentRoot.dom,
|
|
942
|
-
props: currentState.currentRoot.props,
|
|
943
|
-
alternate: currentState.currentRoot,
|
|
944
|
-
};
|
|
945
|
-
currentState.deletions = [];
|
|
946
|
-
currentState.hookIndex = 0;
|
|
947
|
-
scheduleWork(currentState.wipRoot);
|
|
948
|
-
};
|
|
949
|
-
|
|
950
|
-
wipFiber.hooks[hookIndex] = hook;
|
|
951
|
-
state.hookIndex++;
|
|
952
|
-
return [hook.state, dispatch]
|
|
953
|
-
};
|
|
954
|
-
|
|
955
|
-
const useEffect = (callback, deps) => {
|
|
956
|
-
validateHookCall();
|
|
957
|
-
|
|
958
|
-
if (!is.function(callback)) {
|
|
959
|
-
throw new Error('useEffect callback must be a function')
|
|
960
|
-
}
|
|
961
|
-
if (deps !== undefined && !Array.isArray(deps)) {
|
|
962
|
-
throw new Error('useEffect dependencies must be an array or undefined')
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
const state = getState();
|
|
966
|
-
const { wipFiber, hookIndex } = state;
|
|
967
|
-
const oldHook = wipFiber.alternate?.hooks?.[hookIndex];
|
|
968
|
-
const hasChanged = haveDepsChanged(oldHook?.deps, deps);
|
|
969
|
-
|
|
970
|
-
const hook = {
|
|
971
|
-
hookID: hookIndex,
|
|
972
|
-
type: RYUNIX_TYPES.RYUNIX_EFFECT,
|
|
973
|
-
deps,
|
|
974
|
-
effect: hasChanged ? callback : null,
|
|
975
|
-
cancel: oldHook?.cancel,
|
|
976
|
-
};
|
|
977
|
-
|
|
978
|
-
wipFiber.hooks[hookIndex] = hook;
|
|
979
|
-
state.hookIndex++;
|
|
980
|
-
};
|
|
981
|
-
|
|
982
|
-
const useRef = (initialValue) => {
|
|
983
|
-
validateHookCall();
|
|
984
|
-
|
|
985
|
-
const state = getState();
|
|
986
|
-
const { wipFiber, hookIndex } = state;
|
|
987
|
-
const oldHook = wipFiber.alternate?.hooks?.[hookIndex];
|
|
988
|
-
|
|
989
|
-
const hook = {
|
|
990
|
-
hookID: hookIndex,
|
|
991
|
-
type: RYUNIX_TYPES.RYUNIX_REF,
|
|
992
|
-
value: oldHook ? oldHook.value : { current: initialValue },
|
|
993
|
-
};
|
|
994
|
-
|
|
995
|
-
wipFiber.hooks[hookIndex] = hook;
|
|
996
|
-
state.hookIndex++;
|
|
997
|
-
return hook.value
|
|
998
|
-
};
|
|
999
|
-
|
|
1000
|
-
const useMemo = (compute, deps) => {
|
|
1001
|
-
validateHookCall();
|
|
731
|
+
const useMemo = (compute, deps) => {
|
|
732
|
+
validateHookCall();
|
|
1002
733
|
|
|
1003
734
|
if (!is.function(compute)) {
|
|
1004
735
|
throw new Error('useMemo callback must be a function')
|
|
@@ -1367,6 +1098,349 @@
|
|
|
1367
1098
|
useTransition: useTransition
|
|
1368
1099
|
});
|
|
1369
1100
|
|
|
1101
|
+
const updateFunctionComponent = (fiber) => {
|
|
1102
|
+
const state = getState();
|
|
1103
|
+
state.wipFiber = fiber;
|
|
1104
|
+
state.hookIndex = 0;
|
|
1105
|
+
state.wipFiber.hooks = [];
|
|
1106
|
+
|
|
1107
|
+
const children = [fiber.type(fiber.props)];
|
|
1108
|
+
|
|
1109
|
+
if (fiber.type._contextId && fiber.props.value !== undefined) {
|
|
1110
|
+
fiber._contextId = fiber.type._contextId;
|
|
1111
|
+
fiber._contextValue = fiber.props.value;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
reconcileChildren(fiber, children);
|
|
1115
|
+
};
|
|
1116
|
+
|
|
1117
|
+
const updateHostComponent = (fiber) => {
|
|
1118
|
+
if (!fiber.dom) {
|
|
1119
|
+
fiber.dom = createDom(fiber);
|
|
1120
|
+
}
|
|
1121
|
+
const children = fiber.props?.children || [];
|
|
1122
|
+
reconcileChildren(fiber, children);
|
|
1123
|
+
};
|
|
1124
|
+
|
|
1125
|
+
/* Image component */
|
|
1126
|
+
const Image = ({ src, ...props }) => {
|
|
1127
|
+
return createElement('img', { ...props, src })
|
|
1128
|
+
};
|
|
1129
|
+
|
|
1130
|
+
const { Provider: MDXProvider, useContext: useMDXComponents } = createContext(
|
|
1131
|
+
'ryunix.mdx',
|
|
1132
|
+
{},
|
|
1133
|
+
);
|
|
1134
|
+
|
|
1135
|
+
/**
|
|
1136
|
+
* Get merged MDX components from context and provided components
|
|
1137
|
+
* @param {Object} components - Additional components to merge
|
|
1138
|
+
* @returns {Object} Merged components object
|
|
1139
|
+
*/
|
|
1140
|
+
const getMDXComponents = (components) => {
|
|
1141
|
+
const contextComponents = useMDXComponents();
|
|
1142
|
+
return {
|
|
1143
|
+
...contextComponents,
|
|
1144
|
+
...components,
|
|
1145
|
+
}
|
|
1146
|
+
};
|
|
1147
|
+
|
|
1148
|
+
/**
|
|
1149
|
+
* Default MDX components with Ryunix-optimized rendering
|
|
1150
|
+
*/
|
|
1151
|
+
const defaultComponents = {
|
|
1152
|
+
// Headings
|
|
1153
|
+
h1: (props) => createElement('h1', { ...props }),
|
|
1154
|
+
h2: (props) => createElement('h2', { ...props }),
|
|
1155
|
+
h3: (props) => createElement('h3', { ...props }),
|
|
1156
|
+
h4: (props) => createElement('h4', { ...props }),
|
|
1157
|
+
h5: (props) => createElement('h5', { ...props }),
|
|
1158
|
+
h6: (props) => createElement('h6', { ...props }),
|
|
1159
|
+
|
|
1160
|
+
// Text
|
|
1161
|
+
p: (props) => createElement('p', { ...props }),
|
|
1162
|
+
a: (props) => createElement('a', { ...props }),
|
|
1163
|
+
strong: (props) => createElement('strong', { ...props }),
|
|
1164
|
+
em: (props) => createElement('em', { ...props }),
|
|
1165
|
+
code: (props) => createElement('code', { ...props }),
|
|
1166
|
+
|
|
1167
|
+
// Lists
|
|
1168
|
+
ul: (props) => createElement('ul', { ...props }),
|
|
1169
|
+
ol: (props) => createElement('ol', { ...props }),
|
|
1170
|
+
li: (props) => createElement('li', { ...props }),
|
|
1171
|
+
|
|
1172
|
+
// Blocks
|
|
1173
|
+
blockquote: (props) => createElement('blockquote', { ...props }),
|
|
1174
|
+
pre: (props) => createElement('pre', { ...props }),
|
|
1175
|
+
hr: (props) => createElement('hr', { ...props }),
|
|
1176
|
+
|
|
1177
|
+
// Tables
|
|
1178
|
+
table: (props) => createElement('table', { ...props }),
|
|
1179
|
+
thead: (props) => createElement('thead', { ...props }),
|
|
1180
|
+
tbody: (props) => createElement('tbody', { ...props }),
|
|
1181
|
+
tr: (props) => createElement('tr', { ...props }),
|
|
1182
|
+
th: (props) => createElement('th', { ...props }),
|
|
1183
|
+
td: (props) => createElement('td', { ...props }),
|
|
1184
|
+
|
|
1185
|
+
// Media
|
|
1186
|
+
img: (props) => createElement('img', { ...props }),
|
|
1187
|
+
};
|
|
1188
|
+
|
|
1189
|
+
/**
|
|
1190
|
+
* MDX Wrapper component
|
|
1191
|
+
* Provides default styling and components for MDX content
|
|
1192
|
+
*/
|
|
1193
|
+
const MDXContent = ({ children, components = {} }) => {
|
|
1194
|
+
const mergedComponents = getMDXComponents(components);
|
|
1195
|
+
|
|
1196
|
+
return createElement(
|
|
1197
|
+
MDXProvider,
|
|
1198
|
+
{ value: mergedComponents },
|
|
1199
|
+
createElement('div', null, children),
|
|
1200
|
+
)
|
|
1201
|
+
};
|
|
1202
|
+
|
|
1203
|
+
/**
|
|
1204
|
+
* Performance profiler for Ryunix
|
|
1205
|
+
*/
|
|
1206
|
+
class Profiler {
|
|
1207
|
+
constructor() {
|
|
1208
|
+
this.enabled = process.env.NODE_ENV !== 'production';
|
|
1209
|
+
this.measures = new Map();
|
|
1210
|
+
this.renderTimes = [];
|
|
1211
|
+
this.maxSamples = 100;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
startMeasure(name) {
|
|
1215
|
+
if (!this.enabled) return
|
|
1216
|
+
this.measures.set(name, performance.now());
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
endMeasure(name) {
|
|
1220
|
+
if (!this.enabled) return
|
|
1221
|
+
const start = this.measures.get(name);
|
|
1222
|
+
if (!start) return
|
|
1223
|
+
|
|
1224
|
+
const duration = performance.now() - start;
|
|
1225
|
+
this.measures.delete(name);
|
|
1226
|
+
|
|
1227
|
+
return duration
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
recordRender(componentName, duration) {
|
|
1231
|
+
if (!this.enabled) return
|
|
1232
|
+
|
|
1233
|
+
this.renderTimes.push({
|
|
1234
|
+
component: componentName,
|
|
1235
|
+
duration,
|
|
1236
|
+
timestamp: Date.now(),
|
|
1237
|
+
});
|
|
1238
|
+
|
|
1239
|
+
if (this.renderTimes.length > this.maxSamples) {
|
|
1240
|
+
this.renderTimes.shift();
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
getStats() {
|
|
1245
|
+
if (!this.enabled) return null
|
|
1246
|
+
|
|
1247
|
+
const total = this.renderTimes.reduce((sum, r) => sum + r.duration, 0);
|
|
1248
|
+
const avg = total / this.renderTimes.length;
|
|
1249
|
+
const max = Math.max(...this.renderTimes.map((r) => r.duration));
|
|
1250
|
+
const min = Math.min(...this.renderTimes.map((r) => r.duration));
|
|
1251
|
+
|
|
1252
|
+
return { total, avg, max, min, count: this.renderTimes.length }
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
getSlowestComponents(limit = 10) {
|
|
1256
|
+
if (!this.enabled) return []
|
|
1257
|
+
|
|
1258
|
+
const byComponent = new Map();
|
|
1259
|
+
|
|
1260
|
+
this.renderTimes.forEach(({ component, duration }) => {
|
|
1261
|
+
if (!byComponent.has(component)) {
|
|
1262
|
+
byComponent.set(component, { total: 0, count: 0, max: 0 });
|
|
1263
|
+
}
|
|
1264
|
+
const stats = byComponent.get(component);
|
|
1265
|
+
stats.total += duration;
|
|
1266
|
+
stats.count++;
|
|
1267
|
+
stats.max = Math.max(stats.max, duration);
|
|
1268
|
+
});
|
|
1269
|
+
|
|
1270
|
+
return Array.from(byComponent.entries())
|
|
1271
|
+
.map(([name, stats]) => ({
|
|
1272
|
+
name,
|
|
1273
|
+
avg: stats.total / stats.count,
|
|
1274
|
+
max: stats.max,
|
|
1275
|
+
count: stats.count,
|
|
1276
|
+
}))
|
|
1277
|
+
.sort((a, b) => b.avg - a.avg)
|
|
1278
|
+
.slice(0, limit)
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
logStats() {
|
|
1282
|
+
if (!this.enabled) return
|
|
1283
|
+
|
|
1284
|
+
const stats = this.getStats();
|
|
1285
|
+
if (!stats) return
|
|
1286
|
+
|
|
1287
|
+
console.group('🔍 Ryunix Performance Stats');
|
|
1288
|
+
console.log(`Total renders: ${stats.count}`);
|
|
1289
|
+
console.log(`Avg render time: ${stats.avg.toFixed(2)}ms`);
|
|
1290
|
+
console.log(
|
|
1291
|
+
`Min: ${stats.min.toFixed(2)}ms | Max: ${stats.max.toFixed(2)}ms`,
|
|
1292
|
+
);
|
|
1293
|
+
|
|
1294
|
+
const slowest = this.getSlowestComponents(5);
|
|
1295
|
+
if (slowest.length > 0) {
|
|
1296
|
+
console.log('\n⚠️ Slowest components:');
|
|
1297
|
+
slowest.forEach((comp, i) => {
|
|
1298
|
+
console.log(
|
|
1299
|
+
`${i + 1}. ${comp.name}: ${comp.avg.toFixed(2)}ms avg (${comp.count} renders)`,
|
|
1300
|
+
);
|
|
1301
|
+
});
|
|
1302
|
+
}
|
|
1303
|
+
console.groupEnd();
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
clear() {
|
|
1307
|
+
this.renderTimes = [];
|
|
1308
|
+
this.measures.clear();
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
enable() {
|
|
1312
|
+
this.enabled = true;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
disable() {
|
|
1316
|
+
this.enabled = false;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
// Global profiler instance
|
|
1321
|
+
const profiler = new Profiler();
|
|
1322
|
+
|
|
1323
|
+
/**
|
|
1324
|
+
* Hook to profile component render
|
|
1325
|
+
*/
|
|
1326
|
+
const useProfiler = (componentName) => {
|
|
1327
|
+
const startTime = performance.now();
|
|
1328
|
+
|
|
1329
|
+
return () => {
|
|
1330
|
+
const duration = performance.now() - startTime;
|
|
1331
|
+
profiler.recordRender(componentName, duration);
|
|
1332
|
+
}
|
|
1333
|
+
};
|
|
1334
|
+
|
|
1335
|
+
/**
|
|
1336
|
+
* HOC to profile component
|
|
1337
|
+
*/
|
|
1338
|
+
const withProfiler = (Component, name) => {
|
|
1339
|
+
return (props) => {
|
|
1340
|
+
profiler.startMeasure(name);
|
|
1341
|
+
const result = Component(props);
|
|
1342
|
+
const duration = profiler.endMeasure(name);
|
|
1343
|
+
if (duration) profiler.recordRender(name, duration);
|
|
1344
|
+
return result
|
|
1345
|
+
}
|
|
1346
|
+
};
|
|
1347
|
+
|
|
1348
|
+
const workLoop = (deadline) => {
|
|
1349
|
+
const state = getState();
|
|
1350
|
+
let shouldYield = false;
|
|
1351
|
+
|
|
1352
|
+
while (state.nextUnitOfWork && !shouldYield) {
|
|
1353
|
+
state.nextUnitOfWork = performUnitOfWork(state.nextUnitOfWork);
|
|
1354
|
+
shouldYield = deadline.timeRemaining() < 1;
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
if (!state.nextUnitOfWork && state.wipRoot) {
|
|
1358
|
+
commitRoot();
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
requestIdleCallback(workLoop);
|
|
1362
|
+
};
|
|
1363
|
+
|
|
1364
|
+
requestIdleCallback(workLoop);
|
|
1365
|
+
|
|
1366
|
+
const performUnitOfWork = (fiber) => {
|
|
1367
|
+
const componentName = fiber.type?.name || fiber.type?.displayName || 'Unknown';
|
|
1368
|
+
|
|
1369
|
+
profiler.startMeasure(componentName);
|
|
1370
|
+
|
|
1371
|
+
const isFunctionComponent = fiber.type instanceof Function;
|
|
1372
|
+
if (isFunctionComponent) {
|
|
1373
|
+
updateFunctionComponent(fiber);
|
|
1374
|
+
} else {
|
|
1375
|
+
updateHostComponent(fiber);
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
const duration = profiler.endMeasure(componentName);
|
|
1379
|
+
if (duration) profiler.recordRender(componentName, duration);
|
|
1380
|
+
|
|
1381
|
+
if (fiber.child) {
|
|
1382
|
+
return fiber.child
|
|
1383
|
+
}
|
|
1384
|
+
let nextFiber = fiber;
|
|
1385
|
+
while (nextFiber) {
|
|
1386
|
+
if (nextFiber.sibling) {
|
|
1387
|
+
return nextFiber.sibling
|
|
1388
|
+
}
|
|
1389
|
+
nextFiber = nextFiber.parent;
|
|
1390
|
+
}
|
|
1391
|
+
};
|
|
1392
|
+
|
|
1393
|
+
const scheduleWork = (root, priority = Priority.NORMAL) => {
|
|
1394
|
+
const state = getState();
|
|
1395
|
+
state.nextUnitOfWork = root;
|
|
1396
|
+
state.wipRoot = root;
|
|
1397
|
+
state.deletions = [];
|
|
1398
|
+
state.hookIndex = 0;
|
|
1399
|
+
state.effects = [];
|
|
1400
|
+
|
|
1401
|
+
// Higher priority = faster scheduling
|
|
1402
|
+
if (priority <= Priority.USER_BLOCKING) {
|
|
1403
|
+
requestIdleCallback(workLoop);
|
|
1404
|
+
} else {
|
|
1405
|
+
setTimeout(() => requestIdleCallback(workLoop), 0);
|
|
1406
|
+
}
|
|
1407
|
+
};
|
|
1408
|
+
|
|
1409
|
+
const render = (element, container) => {
|
|
1410
|
+
const state = getState();
|
|
1411
|
+
state.wipRoot = {
|
|
1412
|
+
dom: container,
|
|
1413
|
+
props: {
|
|
1414
|
+
children: [element],
|
|
1415
|
+
},
|
|
1416
|
+
alternate: state.currentRoot,
|
|
1417
|
+
};
|
|
1418
|
+
|
|
1419
|
+
state.nextUnitOfWork = state.wipRoot;
|
|
1420
|
+
state.deletions = [];
|
|
1421
|
+
scheduleWork(state.wipRoot);
|
|
1422
|
+
return state.wipRoot
|
|
1423
|
+
};
|
|
1424
|
+
|
|
1425
|
+
const init = (MainElement, root = '__ryunix') => {
|
|
1426
|
+
const state = getState();
|
|
1427
|
+
state.containerRoot = document.getElementById(root);
|
|
1428
|
+
const renderProcess = render(MainElement, state.containerRoot);
|
|
1429
|
+
return renderProcess
|
|
1430
|
+
};
|
|
1431
|
+
|
|
1432
|
+
const safeRender = (component, props, onError) => {
|
|
1433
|
+
try {
|
|
1434
|
+
return component(props)
|
|
1435
|
+
} catch (error) {
|
|
1436
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
1437
|
+
console.error('Component error:', error);
|
|
1438
|
+
}
|
|
1439
|
+
if (onError) onError(error);
|
|
1440
|
+
return null
|
|
1441
|
+
}
|
|
1442
|
+
};
|
|
1443
|
+
|
|
1370
1444
|
/**
|
|
1371
1445
|
* memo - Memoize component to prevent unnecessary re-renders
|
|
1372
1446
|
*/
|
|
@@ -1508,6 +1582,8 @@
|
|
|
1508
1582
|
exports.Fragment = Fragment;
|
|
1509
1583
|
exports.Hooks = hooks;
|
|
1510
1584
|
exports.Image = Image;
|
|
1585
|
+
exports.MDXContent = MDXContent;
|
|
1586
|
+
exports.MDXProvider = MDXProvider;
|
|
1511
1587
|
exports.NavLink = NavLink;
|
|
1512
1588
|
exports.Priority = Priority;
|
|
1513
1589
|
exports.RouterProvider = RouterProvider;
|
|
@@ -1516,6 +1592,8 @@
|
|
|
1516
1592
|
exports.createContext = createContext;
|
|
1517
1593
|
exports.createElement = createElement;
|
|
1518
1594
|
exports.default = Ryunix;
|
|
1595
|
+
exports.defaultComponents = defaultComponents;
|
|
1596
|
+
exports.getMDXComponents = getMDXComponents;
|
|
1519
1597
|
exports.init = init;
|
|
1520
1598
|
exports.lazy = lazy;
|
|
1521
1599
|
exports.memo = memo;
|
|
@@ -1526,6 +1604,7 @@
|
|
|
1526
1604
|
exports.useDeferredValue = useDeferredValue;
|
|
1527
1605
|
exports.useEffect = useEffect;
|
|
1528
1606
|
exports.useHash = useHash;
|
|
1607
|
+
exports.useMDXComponents = useMDXComponents;
|
|
1529
1608
|
exports.useMemo = useMemo;
|
|
1530
1609
|
exports.useMetadata = useMetadata;
|
|
1531
1610
|
exports.useProfiler = useProfiler;
|