@unsetsoft/ryunixjs 1.1.7-canary.63 → 1.1.7-canary.65
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.js +204 -293
- package/dist/Ryunix.min.js +1 -1
- package/package.json +1 -1
package/dist/Ryunix.js
CHANGED
|
@@ -51,35 +51,6 @@
|
|
|
51
51
|
NO_EFFECT: Symbol('ryunix.reconciler.status.no_efect').toString(),
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
const matchPath = (pattern, path) => {
|
|
55
|
-
const patternSegments = pattern.split('/').filter(Boolean);
|
|
56
|
-
const pathSegments = path.split('/').filter(Boolean);
|
|
57
|
-
|
|
58
|
-
if (pattern === '*') return {}
|
|
59
|
-
|
|
60
|
-
if (patternSegments.length !== pathSegments.length) return null
|
|
61
|
-
|
|
62
|
-
const params = {};
|
|
63
|
-
|
|
64
|
-
for (let i = 0; i < patternSegments.length; i++) {
|
|
65
|
-
const pSeg = patternSegments[i];
|
|
66
|
-
const pathSeg = pathSegments[i];
|
|
67
|
-
|
|
68
|
-
if (pSeg.startsWith(':')) {
|
|
69
|
-
params[pSeg.slice(1)] = decodeURIComponent(pathSeg);
|
|
70
|
-
} else if (pSeg !== pathSeg) {
|
|
71
|
-
return null
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return params
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const parseQuery = (search) => {
|
|
79
|
-
if (!search) return {}
|
|
80
|
-
return Object.fromEntries(new URLSearchParams(search))
|
|
81
|
-
};
|
|
82
|
-
|
|
83
54
|
/**
|
|
84
55
|
* The function creates a new element with the given type, props, and children.
|
|
85
56
|
* @param type - The type of the element to be created, such as "div", "span", "h1", etc.
|
|
@@ -128,7 +99,8 @@
|
|
|
128
99
|
}
|
|
129
100
|
};
|
|
130
101
|
|
|
131
|
-
const
|
|
102
|
+
const Fragment = (props) =>
|
|
103
|
+
createElement(RYUNIX_TYPES.RYUNIX_FRAGMENT, {}, ...props.children);
|
|
132
104
|
|
|
133
105
|
const isEvent = (key) => key.startsWith('on');
|
|
134
106
|
const isProperty = (key) => key !== STRINGS.children && !isEvent(key);
|
|
@@ -385,6 +357,207 @@
|
|
|
385
357
|
}
|
|
386
358
|
};
|
|
387
359
|
|
|
360
|
+
/**
|
|
361
|
+
* This function updates a function component by setting up a work-in-progress fiber, resetting the
|
|
362
|
+
* hook index, creating an empty hooks array, rendering the component, and reconciling its children.
|
|
363
|
+
* @param fiber - The fiber parameter is an object that represents a node in the fiber tree. It
|
|
364
|
+
* contains information about the component, its props, state, and children. In this function, it is
|
|
365
|
+
* used to update the state of the component and its children.
|
|
366
|
+
*/
|
|
367
|
+
const updateFunctionComponent = (fiber) => {
|
|
368
|
+
vars.wipFiber = fiber;
|
|
369
|
+
vars.hookIndex = 0;
|
|
370
|
+
vars.wipFiber.hooks = [];
|
|
371
|
+
const children = [fiber.type(fiber.props)];
|
|
372
|
+
reconcileChildren(fiber, children);
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* This function updates a host component's DOM element and reconciles its children.
|
|
377
|
+
* @param fiber - A fiber is a unit of work in Ryunix that represents a component and its state. It
|
|
378
|
+
* contains information about the component's type, props, and children, as well as pointers to other
|
|
379
|
+
* fibers in the tree.
|
|
380
|
+
*/
|
|
381
|
+
const updateHostComponent = (fiber) => {
|
|
382
|
+
if (fiber.type === RYUNIX_TYPES.RYUNIX_FRAGMENT) {
|
|
383
|
+
reconcileChildren(fiber, fiber.props.children.flat());
|
|
384
|
+
} else {
|
|
385
|
+
if (!fiber.dom) {
|
|
386
|
+
fiber.dom = createDom(fiber);
|
|
387
|
+
}
|
|
388
|
+
reconcileChildren(fiber, fiber.props.children.flat());
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
/* Internal components*/
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* The function `optimizationImageApi` optimizes image URLs by adding query parameters for width,
|
|
396
|
+
* height, quality, and extension, and handles local and remote image sources.
|
|
397
|
+
* @returns The function `optimizationImageApi` returns either the original `src` if it is a local
|
|
398
|
+
* image and the page is being run on localhost, or it returns a modified image URL with optimization
|
|
399
|
+
* parameters added if the `src` is not local.
|
|
400
|
+
*/
|
|
401
|
+
const optimizationImageApi = ({ src, props }) => {
|
|
402
|
+
const query = new URLSearchParams();
|
|
403
|
+
const apiEndpoint = 'https://image.unsetsoft.com';
|
|
404
|
+
|
|
405
|
+
const isLocal = !src.startsWith('http') || !src.startsWith('https');
|
|
406
|
+
|
|
407
|
+
if (props.width) query.set('width', props.width);
|
|
408
|
+
if (props.height) query.set('width', props.height);
|
|
409
|
+
if (props.quality) query.set('quality', props.quality);
|
|
410
|
+
|
|
411
|
+
const extension = props.extension ? `@${props.extension}` : '';
|
|
412
|
+
|
|
413
|
+
const localhost =
|
|
414
|
+
window.location.origin === 'http://localhost:3000' ||
|
|
415
|
+
window.location.origin === 'http://localhost:5173' ||
|
|
416
|
+
window.location.origin === 'http://localhost:4173';
|
|
417
|
+
|
|
418
|
+
if (isLocal) {
|
|
419
|
+
if (localhost) {
|
|
420
|
+
console.warn(
|
|
421
|
+
'Image optimizations only work with full links and must not contain localhost.',
|
|
422
|
+
);
|
|
423
|
+
return src
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return `${window.location.origin}/${src}`
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
return `${apiEndpoint}/image/${src}${extension}?${query.toString()}`
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* The `Image` function in JavaScript optimizes image loading based on a specified optimization flag.
|
|
434
|
+
* @returns An `<img>` element is being returned with the specified `src` and other props passed to the
|
|
435
|
+
* `Image` component. The `src` is either the original `src` value or the result of calling
|
|
436
|
+
* `optimizationImageApi` function with `src` and `props` if `optimization` is set to 'true'.
|
|
437
|
+
*/
|
|
438
|
+
const Image = ({ src, ...props }) => {
|
|
439
|
+
const optimization = props.optimization === 'true' ? true : false;
|
|
440
|
+
|
|
441
|
+
const url = optimization
|
|
442
|
+
? optimizationImageApi({
|
|
443
|
+
src,
|
|
444
|
+
props,
|
|
445
|
+
})
|
|
446
|
+
: src;
|
|
447
|
+
|
|
448
|
+
const ImageProps = {
|
|
449
|
+
src: url,
|
|
450
|
+
props,
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
return createElement('img', ImageProps, null)
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* This function uses requestIdleCallback to perform work on a fiber tree until it is complete or the
|
|
458
|
+
* browser needs to yield to other tasks.
|
|
459
|
+
* @param deadline - The `deadline` parameter is an object that represents the amount of time the
|
|
460
|
+
* browser has to perform work before it needs to handle other tasks. It has a `timeRemaining()` method
|
|
461
|
+
* that returns the amount of time remaining before the deadline is reached. The `shouldYield` variable
|
|
462
|
+
* is used to determine
|
|
463
|
+
*/
|
|
464
|
+
const workLoop = (deadline) => {
|
|
465
|
+
let shouldYield = false;
|
|
466
|
+
while (vars.nextUnitOfWork && !shouldYield) {
|
|
467
|
+
vars.nextUnitOfWork = performUnitOfWork(vars.nextUnitOfWork);
|
|
468
|
+
shouldYield = deadline.timeRemaining() < 1;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (!vars.nextUnitOfWork && vars.wipRoot) {
|
|
472
|
+
commitRoot();
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
requestIdleCallback(workLoop);
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
requestIdleCallback(workLoop);
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* The function performs a unit of work by updating either a function component or a host component and
|
|
482
|
+
* returns the next fiber to be processed.
|
|
483
|
+
* @param fiber - A fiber is a unit of work in Ryunix that represents a component and its state. It
|
|
484
|
+
* contains information about the component's type, props, and children, as well as pointers to its
|
|
485
|
+
* parent, child, and sibling fibers. The `performUnitOfWork` function takes a fiber as a parameter and
|
|
486
|
+
* performs work
|
|
487
|
+
* @returns The function `performUnitOfWork` returns the next fiber to be processed. If the current
|
|
488
|
+
* fiber has a child, it returns the child. Otherwise, it looks for the next sibling of the current
|
|
489
|
+
* fiber. If there are no more siblings, it goes up the tree to the parent and looks for the next
|
|
490
|
+
* sibling of the parent. The function returns `null` if there are no more fibers to process.
|
|
491
|
+
*/
|
|
492
|
+
const performUnitOfWork = (fiber) => {
|
|
493
|
+
const isFunctionComponent = fiber.type instanceof Function;
|
|
494
|
+
if (isFunctionComponent) {
|
|
495
|
+
updateFunctionComponent(fiber);
|
|
496
|
+
} else {
|
|
497
|
+
updateHostComponent(fiber);
|
|
498
|
+
}
|
|
499
|
+
if (fiber.child) {
|
|
500
|
+
return fiber.child
|
|
501
|
+
}
|
|
502
|
+
let nextFiber = fiber;
|
|
503
|
+
while (nextFiber) {
|
|
504
|
+
if (nextFiber.sibling) {
|
|
505
|
+
return nextFiber.sibling
|
|
506
|
+
}
|
|
507
|
+
nextFiber = nextFiber.parent;
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
const scheduleWork = (root) => {
|
|
512
|
+
vars.nextUnitOfWork = root;
|
|
513
|
+
vars.wipRoot = root;
|
|
514
|
+
vars.deletions = [];
|
|
515
|
+
|
|
516
|
+
vars.hookIndex = 0;
|
|
517
|
+
vars.effects = [];
|
|
518
|
+
requestIdleCallback(workLoop);
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Renders an element into a container using a work-in-progress (WIP) root.
|
|
523
|
+
* @function render
|
|
524
|
+
* @param {Object|HTMLElement} element - The element to be rendered in the container. It can be a Ryunix component (custom element) or a standard DOM element.
|
|
525
|
+
* @param {HTMLElement} container - The container where the element will be rendered. This parameter is optional if `createRoot()` is used beforehand to set up the container.
|
|
526
|
+
* @description The function assigns the `container` to a work-in-progress root and sets up properties for reconciliation, including children and the reference to the current root.
|
|
527
|
+
* It also clears any scheduled deletions and establishes the next unit of work for incremental rendering.
|
|
528
|
+
*/
|
|
529
|
+
const render = (element, container) => {
|
|
530
|
+
vars.wipRoot = {
|
|
531
|
+
dom: container,
|
|
532
|
+
props: {
|
|
533
|
+
children: [element],
|
|
534
|
+
},
|
|
535
|
+
alternate: vars.currentRoot,
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
vars.nextUnitOfWork = vars.wipRoot;
|
|
539
|
+
vars.deletions = [];
|
|
540
|
+
scheduleWork(vars.wipRoot);
|
|
541
|
+
return vars.wipRoot
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Initializes the application by creating a reference to a DOM element with the specified ID and rendering the main component.
|
|
546
|
+
* @function init
|
|
547
|
+
* @param {Object} MainElement - The main component to render, typically the root component of the application.
|
|
548
|
+
* @param {string} [root='__ryunix'] - The ID of the HTML element that serves as the container for the root element. Defaults to `'__ryunix'` if not provided.
|
|
549
|
+
* @example
|
|
550
|
+
* Ryunix.init(App, "__ryunix"); // Initializes and renders the App component into the <div id="__ryunix"></div> element.
|
|
551
|
+
* @description This function retrieves the container element by its ID and invokes the `render` function to render the main component into it.
|
|
552
|
+
*/
|
|
553
|
+
const init = (MainElement, root = '__ryunix') => {
|
|
554
|
+
vars.containerRoot = document.getElementById(root);
|
|
555
|
+
|
|
556
|
+
const renderProcess = render(MainElement, vars.containerRoot);
|
|
557
|
+
|
|
558
|
+
return renderProcess
|
|
559
|
+
};
|
|
560
|
+
|
|
388
561
|
/**
|
|
389
562
|
* @description The function creates a state.
|
|
390
563
|
* @param initial - The initial value of the state for the hook.
|
|
@@ -725,279 +898,17 @@
|
|
|
725
898
|
useStore: useStore
|
|
726
899
|
});
|
|
727
900
|
|
|
728
|
-
/**
|
|
729
|
-
* This function updates a function component by setting up a work-in-progress fiber, resetting the
|
|
730
|
-
* hook index, creating an empty hooks array, rendering the component, and reconciling its children.
|
|
731
|
-
* @param fiber - The fiber parameter is an object that represents a node in the fiber tree. It
|
|
732
|
-
* contains information about the component, its props, state, and children. In this function, it is
|
|
733
|
-
* used to update the state of the component and its children.
|
|
734
|
-
*/
|
|
735
|
-
const updateFunctionComponent = (fiber) => {
|
|
736
|
-
vars.wipFiber = fiber;
|
|
737
|
-
vars.hookIndex = 0;
|
|
738
|
-
vars.wipFiber.hooks = [];
|
|
739
|
-
const children = [fiber.type(fiber.props)];
|
|
740
|
-
reconcileChildren(fiber, children);
|
|
741
|
-
};
|
|
742
|
-
|
|
743
|
-
/**
|
|
744
|
-
* This function updates a host component's DOM element and reconciles its children.
|
|
745
|
-
* @param fiber - A fiber is a unit of work in Ryunix that represents a component and its state. It
|
|
746
|
-
* contains information about the component's type, props, and children, as well as pointers to other
|
|
747
|
-
* fibers in the tree.
|
|
748
|
-
*/
|
|
749
|
-
const updateHostComponent = (fiber) => {
|
|
750
|
-
if (!fiber.dom) {
|
|
751
|
-
fiber.dom = createDom(fiber);
|
|
752
|
-
}
|
|
753
|
-
reconcileChildren(fiber, fiber.props.children.flat());
|
|
754
|
-
};
|
|
755
|
-
|
|
756
|
-
/* Built-in components */
|
|
757
|
-
|
|
758
|
-
/**
|
|
759
|
-
* The function `optimizationImageApi` optimizes image URLs by adding query parameters for width,
|
|
760
|
-
* height, quality, and extension, and handles local and remote image sources.
|
|
761
|
-
* @returns The function `optimizationImageApi` returns either the original `src` if it is a local
|
|
762
|
-
* image and the page is being run on localhost, or it returns a modified image URL with optimization
|
|
763
|
-
* parameters added if the `src` is not local.
|
|
764
|
-
*/
|
|
765
|
-
const optimizationImageApi = ({ src, props }) => {
|
|
766
|
-
const query = new URLSearchParams();
|
|
767
|
-
const apiEndpoint = 'https://image.unsetsoft.com';
|
|
768
|
-
|
|
769
|
-
const isLocal = !src.startsWith('http') || !src.startsWith('https');
|
|
770
|
-
|
|
771
|
-
if (props.width) query.set('width', props.width);
|
|
772
|
-
if (props.height) query.set('width', props.height);
|
|
773
|
-
if (props.quality) query.set('quality', props.quality);
|
|
774
|
-
|
|
775
|
-
const extension = props.extension ? `@${props.extension}` : '';
|
|
776
|
-
|
|
777
|
-
const localhost =
|
|
778
|
-
window.location.origin === 'http://localhost:3000' ||
|
|
779
|
-
window.location.origin === 'http://localhost:5173' ||
|
|
780
|
-
window.location.origin === 'http://localhost:4173';
|
|
781
|
-
|
|
782
|
-
if (isLocal) {
|
|
783
|
-
if (localhost) {
|
|
784
|
-
console.warn(
|
|
785
|
-
'Image optimizations only work with full links and must not contain localhost.',
|
|
786
|
-
);
|
|
787
|
-
return src
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
return `${window.location.origin}/${src}`
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
return `${apiEndpoint}/image/${src}${extension}?${query.toString()}`
|
|
794
|
-
};
|
|
795
|
-
|
|
796
|
-
/**
|
|
797
|
-
* The `Image` function in JavaScript optimizes image loading based on a specified optimization flag.
|
|
798
|
-
* @returns An `<img>` element is being returned with the specified `src` and other props passed to the
|
|
799
|
-
* `Image` component. The `src` is either the original `src` value or the result of calling
|
|
800
|
-
* `optimizationImageApi` function with `src` and `props` if `optimization` is set to 'true'.
|
|
801
|
-
*/
|
|
802
|
-
const Image = ({ src, ...props }) => {
|
|
803
|
-
const optimization = props.optimization === 'true' ? true : false;
|
|
804
|
-
|
|
805
|
-
const url = optimization
|
|
806
|
-
? optimizationImageApi({
|
|
807
|
-
src,
|
|
808
|
-
props,
|
|
809
|
-
})
|
|
810
|
-
: src;
|
|
811
|
-
|
|
812
|
-
const ImageProps = {
|
|
813
|
-
src: url,
|
|
814
|
-
props,
|
|
815
|
-
};
|
|
816
|
-
|
|
817
|
-
return createElement('img', ImageProps, null)
|
|
818
|
-
};
|
|
819
|
-
|
|
820
|
-
const Router = ({ children }) => {
|
|
821
|
-
const [location, setLocation] = useStore({
|
|
822
|
-
pathname: window.location.pathname,
|
|
823
|
-
search: window.location.search,
|
|
824
|
-
});
|
|
825
|
-
|
|
826
|
-
const navigate = (to) => {
|
|
827
|
-
if (to === location.pathname + location.search) return
|
|
828
|
-
window.history.pushState({}, '', to);
|
|
829
|
-
setLocation({
|
|
830
|
-
pathname: window.location.pathname,
|
|
831
|
-
search: window.location.search,
|
|
832
|
-
});
|
|
833
|
-
};
|
|
834
|
-
|
|
835
|
-
useEffect(() => {
|
|
836
|
-
const onPopState = () => {
|
|
837
|
-
setLocation({
|
|
838
|
-
pathname: window.location.pathname,
|
|
839
|
-
search: window.location.search,
|
|
840
|
-
});
|
|
841
|
-
};
|
|
842
|
-
window.addEventListener('popstate', onPopState);
|
|
843
|
-
return () => window.removeEventListener('popstate', onPopState)
|
|
844
|
-
}, []);
|
|
845
|
-
|
|
846
|
-
return children({
|
|
847
|
-
pathname: location.pathname,
|
|
848
|
-
query: parseQuery(location.search),
|
|
849
|
-
navigate,
|
|
850
|
-
})
|
|
851
|
-
};
|
|
852
|
-
|
|
853
|
-
const Route = ({ path, element, pathname, query, navigate }) => {
|
|
854
|
-
const params = matchPath(path, pathname);
|
|
855
|
-
if (!params) return null
|
|
856
|
-
return createElement(element, { params, query, navigate })
|
|
857
|
-
};
|
|
858
|
-
|
|
859
|
-
const Routes = ({ routes, pathname, query, navigate }) => {
|
|
860
|
-
for (const route of routes) {
|
|
861
|
-
const params = matchPath(route.path, pathname);
|
|
862
|
-
if (params !== null) {
|
|
863
|
-
return createElement(route.element, { params, query, navigate })
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
return null
|
|
867
|
-
};
|
|
868
|
-
|
|
869
|
-
const Link = ({ to, children, navigate, ...props }) => {
|
|
870
|
-
const handleClick = (e) => {
|
|
871
|
-
e.preventDefault();
|
|
872
|
-
navigate(to);
|
|
873
|
-
};
|
|
874
|
-
return createElement(
|
|
875
|
-
'a',
|
|
876
|
-
{ href: to, onClick: handleClick, ...props },
|
|
877
|
-
children,
|
|
878
|
-
)
|
|
879
|
-
};
|
|
880
|
-
|
|
881
|
-
/**
|
|
882
|
-
* This function uses requestIdleCallback to perform work on a fiber tree until it is complete or the
|
|
883
|
-
* browser needs to yield to other tasks.
|
|
884
|
-
* @param deadline - The `deadline` parameter is an object that represents the amount of time the
|
|
885
|
-
* browser has to perform work before it needs to handle other tasks. It has a `timeRemaining()` method
|
|
886
|
-
* that returns the amount of time remaining before the deadline is reached. The `shouldYield` variable
|
|
887
|
-
* is used to determine
|
|
888
|
-
*/
|
|
889
|
-
const workLoop = (deadline) => {
|
|
890
|
-
let shouldYield = false;
|
|
891
|
-
while (vars.nextUnitOfWork && !shouldYield) {
|
|
892
|
-
vars.nextUnitOfWork = performUnitOfWork(vars.nextUnitOfWork);
|
|
893
|
-
shouldYield = deadline.timeRemaining() < 1;
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
if (!vars.nextUnitOfWork && vars.wipRoot) {
|
|
897
|
-
commitRoot();
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
requestIdleCallback(workLoop);
|
|
901
|
-
};
|
|
902
|
-
|
|
903
|
-
requestIdleCallback(workLoop);
|
|
904
|
-
|
|
905
|
-
/**
|
|
906
|
-
* The function performs a unit of work by updating either a function component or a host component and
|
|
907
|
-
* returns the next fiber to be processed.
|
|
908
|
-
* @param fiber - A fiber is a unit of work in Ryunix that represents a component and its state. It
|
|
909
|
-
* contains information about the component's type, props, and children, as well as pointers to its
|
|
910
|
-
* parent, child, and sibling fibers. The `performUnitOfWork` function takes a fiber as a parameter and
|
|
911
|
-
* performs work
|
|
912
|
-
* @returns The function `performUnitOfWork` returns the next fiber to be processed. If the current
|
|
913
|
-
* fiber has a child, it returns the child. Otherwise, it looks for the next sibling of the current
|
|
914
|
-
* fiber. If there are no more siblings, it goes up the tree to the parent and looks for the next
|
|
915
|
-
* sibling of the parent. The function returns `null` if there are no more fibers to process.
|
|
916
|
-
*/
|
|
917
|
-
const performUnitOfWork = (fiber) => {
|
|
918
|
-
const isFunctionComponent = fiber.type instanceof Function;
|
|
919
|
-
if (isFunctionComponent) {
|
|
920
|
-
updateFunctionComponent(fiber);
|
|
921
|
-
} else {
|
|
922
|
-
updateHostComponent(fiber);
|
|
923
|
-
}
|
|
924
|
-
if (fiber.child) {
|
|
925
|
-
return fiber.child
|
|
926
|
-
}
|
|
927
|
-
let nextFiber = fiber;
|
|
928
|
-
while (nextFiber) {
|
|
929
|
-
if (nextFiber.sibling) {
|
|
930
|
-
return nextFiber.sibling
|
|
931
|
-
}
|
|
932
|
-
nextFiber = nextFiber.parent;
|
|
933
|
-
}
|
|
934
|
-
};
|
|
935
|
-
|
|
936
|
-
const scheduleWork = (root) => {
|
|
937
|
-
vars.nextUnitOfWork = root;
|
|
938
|
-
vars.wipRoot = root;
|
|
939
|
-
vars.deletions = [];
|
|
940
|
-
|
|
941
|
-
vars.hookIndex = 0;
|
|
942
|
-
vars.effects = [];
|
|
943
|
-
requestIdleCallback(workLoop);
|
|
944
|
-
};
|
|
945
|
-
|
|
946
|
-
/**
|
|
947
|
-
* Renders an element into a container using a work-in-progress (WIP) root.
|
|
948
|
-
* @function render
|
|
949
|
-
* @param {Object|HTMLElement} element - The element to be rendered in the container. It can be a Ryunix component (custom element) or a standard DOM element.
|
|
950
|
-
* @param {HTMLElement} container - The container where the element will be rendered. This parameter is optional if `createRoot()` is used beforehand to set up the container.
|
|
951
|
-
* @description The function assigns the `container` to a work-in-progress root and sets up properties for reconciliation, including children and the reference to the current root.
|
|
952
|
-
* It also clears any scheduled deletions and establishes the next unit of work for incremental rendering.
|
|
953
|
-
*/
|
|
954
|
-
const render = (element, container) => {
|
|
955
|
-
vars.wipRoot = {
|
|
956
|
-
dom: container,
|
|
957
|
-
props: {
|
|
958
|
-
children: [element],
|
|
959
|
-
},
|
|
960
|
-
alternate: vars.currentRoot,
|
|
961
|
-
};
|
|
962
|
-
|
|
963
|
-
vars.nextUnitOfWork = vars.wipRoot;
|
|
964
|
-
vars.deletions = [];
|
|
965
|
-
scheduleWork(vars.wipRoot);
|
|
966
|
-
return vars.wipRoot
|
|
967
|
-
};
|
|
968
|
-
|
|
969
|
-
/**
|
|
970
|
-
* Initializes the application by creating a reference to a DOM element with the specified ID and rendering the main component.
|
|
971
|
-
* @function init
|
|
972
|
-
* @param {Object} MainElement - The main component to render, typically the root component of the application.
|
|
973
|
-
* @param {string} [root='__ryunix'] - The ID of the HTML element that serves as the container for the root element. Defaults to `'__ryunix'` if not provided.
|
|
974
|
-
* @example
|
|
975
|
-
* Ryunix.init(App, "__ryunix"); // Initializes and renders the App component into the <div id="__ryunix"></div> element.
|
|
976
|
-
* @description This function retrieves the container element by its ID and invokes the `render` function to render the main component into it.
|
|
977
|
-
*/
|
|
978
|
-
const init = (MainElement, root = '__ryunix') => {
|
|
979
|
-
vars.containerRoot = document.getElementById(root);
|
|
980
|
-
|
|
981
|
-
const renderProcess = render(MainElement, vars.containerRoot);
|
|
982
|
-
|
|
983
|
-
return renderProcess
|
|
984
|
-
};
|
|
985
|
-
|
|
986
901
|
var Ryunix = {
|
|
987
902
|
createElement,
|
|
988
903
|
render,
|
|
989
904
|
init,
|
|
990
|
-
|
|
905
|
+
Fragment,
|
|
991
906
|
Hooks,
|
|
992
907
|
};
|
|
993
908
|
|
|
994
909
|
window.Ryunix = Ryunix;
|
|
995
910
|
|
|
996
911
|
exports.Image = Image;
|
|
997
|
-
exports.Link = Link;
|
|
998
|
-
exports.Route = Route;
|
|
999
|
-
exports.Router = Router;
|
|
1000
|
-
exports.Routes = Routes;
|
|
1001
912
|
exports.default = Ryunix;
|
|
1002
913
|
exports.useCallback = useCallback;
|
|
1003
914
|
exports.useEffect = useEffect;
|
package/dist/Ryunix.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("lodash")):"function"==typeof define&&define.amd?define(["exports","lodash"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Ryunix={},e.lodash)}(this,(function(e,t){"use strict";let o={containerRoot:null,nextUnitOfWork:null,currentRoot:null,wipRoot:null,deletions:null,wipFiber:null,hookIndex:null,effects:null};const n=/[A-Z]/g,r=Object.freeze({TEXT_ELEMENT:Symbol("text.element").toString(),Ryunix_ELEMENT:Symbol("ryunix.element").toString(),RYUNIX_EFFECT:Symbol("ryunix.effect").toString(),RYUNIX_MEMO:Symbol("ryunix.memo").toString(),RYUNIX_URL_QUERY:Symbol("ryunix.urlQuery").toString(),RYUNIX_REF:Symbol("ryunix.ref").toString(),RYUNIX_STORE:Symbol("ryunix.store").toString(),RYUNIX_REDUCE:Symbol("ryunix.reduce").toString(),RYUNIX_FRAGMENT:Symbol("ryunix.fragment").toString()}),i=Object.freeze({object:"object",function:"function",style:"ryunix-style",className:"ryunix-class",children:"children",boolean:"boolean",string:"string"}),s=Object.freeze({style:"style",className:"className"}),
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("lodash")):"function"==typeof define&&define.amd?define(["exports","lodash"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Ryunix={},e.lodash)}(this,(function(e,t){"use strict";let o={containerRoot:null,nextUnitOfWork:null,currentRoot:null,wipRoot:null,deletions:null,wipFiber:null,hookIndex:null,effects:null};const n=/[A-Z]/g,r=Object.freeze({TEXT_ELEMENT:Symbol("text.element").toString(),Ryunix_ELEMENT:Symbol("ryunix.element").toString(),RYUNIX_EFFECT:Symbol("ryunix.effect").toString(),RYUNIX_MEMO:Symbol("ryunix.memo").toString(),RYUNIX_URL_QUERY:Symbol("ryunix.urlQuery").toString(),RYUNIX_REF:Symbol("ryunix.ref").toString(),RYUNIX_STORE:Symbol("ryunix.store").toString(),RYUNIX_REDUCE:Symbol("ryunix.reduce").toString(),RYUNIX_FRAGMENT:Symbol("ryunix.fragment").toString()}),i=Object.freeze({object:"object",function:"function",style:"ryunix-style",className:"ryunix-class",children:"children",boolean:"boolean",string:"string"}),s=Object.freeze({style:"style",className:"className"}),l=Object.freeze({PLACEMENT:Symbol("ryunix.reconciler.status.placement").toString(),UPDATE:Symbol("ryunix.reconciler.status.update").toString(),DELETION:Symbol("ryunix.reconciler.status.deletion").toString(),NO_EFFECT:Symbol("ryunix.reconciler.status.no_efect").toString()}),a=(e,t,...o)=>({type:e,props:{...t,children:o.flat().map((e=>typeof e===i.object?e:c(e)))}}),c=e=>({type:r.TEXT_ELEMENT,props:{nodeValue:e,children:[]}}),u=e=>e.startsWith("on"),p=e=>e!==i.children&&!u(e),d=(e,t)=>o=>e[o]!==t[o],f=e=>t=>!(t in e),h=e=>{e.hooks&&e.hooks.filter((e=>e.tag===r.RYUNIX_EFFECT&&e.cancel)).forEach((e=>{e.cancel()}))},y=e=>{e.hooks&&e.hooks.filter((e=>e.tag===r.RYUNIX_EFFECT&&e.effect)).forEach((e=>{e.cancel=e.effect()}))},m=(e,t,o)=>{Object.keys(t).filter(u).filter((e=>f(o)(e)||d(t,o)(e))).forEach((o=>{const n=o.toLowerCase().substring(2);e.removeEventListener(n,t[o])})),Object.keys(t).filter(p).filter(f(o)).forEach((t=>{e[t]=""})),Object.keys(o).filter(p).filter(d(t,o)).forEach((n=>{if(n===i.style)w(e,o["ryunix-style"]);else if(n===s.style)w(e,o.style);else if(n===i.className){if(""===o["ryunix-class"])throw new Error("data-class cannot be empty.");t["ryunix-class"]&&e.classList.remove(...t["ryunix-class"].split(/\s+/)),e.classList.add(...o["ryunix-class"].split(/\s+/))}else if(n===s.className){if(""===o.className)throw new Error("className cannot be empty.");t.className&&e.classList.remove(...t.className.split(/\s+/)),e.classList.add(...o.className.split(/\s+/))}else e[n]=o[n]})),Object.keys(o).filter(u).filter(d(t,o)).forEach((t=>{const n=t.toLowerCase().substring(2);e.addEventListener(n,o[t])}))},w=(e,t)=>{e.style=Object.keys(t).reduce(((e,o)=>e+=`${o.replace(n,(function(e){return"-"+e.toLowerCase()}))}: ${t[o]};`),"")},E=e=>{if(!e)return;let t=e.parent;for(;!t.dom;)t=t.parent;const o=t.dom;if(e.effectTag===l.PLACEMENT)null!=e.dom&&o.appendChild(e.dom),y(e);else if(e.effectTag===l.UPDATE)h(e),null!=e.dom&&m(e.dom,e.alternate.props,e.props),y(e);else if(e.effectTag===l.DELETION)return h(e),void b(e,o);E(e.child),E(e.sibling)},b=(e,t)=>{e.dom?t.removeChild(e.dom):b(e.child,t)},R=(e,t)=>{let n,r=0,i=e.alternate&&e.alternate.child;for(;r<t.length||null!=i;){const s=t[r];let a;const c=i&&s&&s.type==i.type;c&&(a={type:i.type,props:s.props,dom:i.dom,parent:e,alternate:i,effectTag:l.UPDATE}),s&&!c&&(a={type:s.type,props:s.props,dom:null,parent:e,alternate:null,effectTag:l.PLACEMENT}),i&&!c&&(i.effectTag=l.DELETION,o.deletions.push(i)),i&&(i=i.sibling),0===r?e.child=a:s&&(n.sibling=a),n=a,r++}},k=e=>{e.type===r.RYUNIX_FRAGMENT||e.dom||(e.dom=(e=>{const t=e.type==r.TEXT_ELEMENT?document.createTextNode(""):document.createElement(e.type);return m(t,{},e.props),t})(e)),R(e,e.props.children.flat())},g=e=>{let t=!1;for(;o.nextUnitOfWork&&!t;)o.nextUnitOfWork=x(o.nextUnitOfWork),t=e.timeRemaining()<1;!o.nextUnitOfWork&&o.wipRoot&&(o.deletions.forEach(E),E(o.wipRoot.child),o.currentRoot=o.wipRoot,o.wipRoot=null),requestIdleCallback(g)};requestIdleCallback(g);const x=e=>{if(e.type instanceof Function?(e=>{o.wipFiber=e,o.hookIndex=0,o.wipFiber.hooks=[];const t=[e.type(e.props)];R(e,t)})(e):k(e),e.child)return e.child;let t=e;for(;t;){if(t.sibling)return t.sibling;t=t.parent}},N=e=>{o.nextUnitOfWork=e,o.wipRoot=e,o.deletions=[],o.hookIndex=0,o.effects=[],requestIdleCallback(g)},F=(e,t)=>(o.wipRoot={dom:t,props:{children:[e]},alternate:o.currentRoot},o.nextUnitOfWork=o.wipRoot,o.deletions=[],N(o.wipRoot),o.wipRoot),I=(e,t)=>T(((e,t)=>"function"==typeof t?t(e):t),e,t),T=(e,t,n)=>{const r=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],i={state:r?r.state:n?n(t):t,queue:r&&Array.isArray(r.queue)?r.queue.slice():[]};r&&Array.isArray(r.queue)&&r.queue.forEach((t=>{i.state=e(i.state,t)}));return i.queue.forEach((t=>{i.state=e(i.state,t)})),o.wipFiber.hooks[o.hookIndex]=i,o.hookIndex++,[i.state,e=>{i.queue.push(e),o.wipRoot={dom:o.currentRoot.dom,props:o.currentRoot.props,alternate:o.currentRoot},o.deletions=[],o.hookIndex=0,N(o.wipRoot)}]},S=(e,n)=>{const i=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],s={type:r.RYUNIX_EFFECT,deps:n,cleanup:i?.cleanup};(!i||!t.isEqual(i.deps,n))&&o.effects.push((()=>{"function"==typeof s.cleanup&&s.cleanup();const t=e();"function"==typeof t&&(s.cleanup=t)})),o.wipFiber.hooks[o.hookIndex]=s,o.hookIndex++},U=e=>{const t=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],n={type:r.RYUNIX_REF,value:t?t.value:{current:e}};return o.wipFiber.hooks[o.hookIndex]=n,o.hookIndex++,n.value},_=(e,n)=>{const i=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],s={type:r.RYUNIX_MEMO,value:null,deps:n};return i&&t.isEqual(i.deps,s.deps)?s.value=i.value:s.value=e(),o.wipFiber.hooks[o.hookIndex]=s,o.hookIndex++,s.value},O=(e,t)=>_((()=>e),t),v=()=>{const e=new URLSearchParams(window.location.search),t={};for(let[o,n]of e.entries())t[o]=n;return t},L=e=>{const[t,n]=I(window.location.pathname),r=(e,t)=>{const o=t.split("?")[0],n=e.find((e=>e.NotFound)),i=n?{route:{component:n.NotFound},params:{}}:{route:{component:null},params:{}};for(const n of e){if(n.subRoutes){const e=r(n.subRoutes,t);if(e)return e}if("*"===n.path)return i;if(!n.path||"string"!=typeof n.path){console.warn("Invalid route detected:",n),console.info("if you are using { NotFound: NotFound } please add { path: '*', NotFound: NotFound }");continue}const e=[],s=new RegExp(`^${n.path.replace(/:\w+/g,(t=>(e.push(t.substring(1)),"([^/]+)")))}$`),l=o.match(s);if(l){return{route:n,params:e.reduce(((e,t,o)=>(e[t]=l[o+1],e)),{})}}}return i},s=e=>{window.history.pushState({},"",e),o.wipRoot={dom:o.currentRoot.dom,props:o.currentRoot.props,alternate:o.currentRoot},o.nextUnitOfWork=o.wipRoot,o.deletions=[],l(e)},l=e=>{const t=e.split("?")[0];n(t)};S((()=>{const e=()=>l(window.location.pathname);return window.addEventListener("popstate",e),()=>window.removeEventListener("popstate",e)}),[]);const c=r(e,t)||{};return{Children:()=>{const e=v(),{route:o}=c;return o&&o.component&&typeof o.component===i.function?o.component({key:t,params:c.params||{},query:e}):(console.error("Component not found for current path or the component is not a valid function:",c),null)},NavLink:({to:e,...t})=>a("a",{href:e,onClick:t=>{t.preventDefault(),s(e)},...t},t.children),navigate:s}};var C={createElement:a,render:F,init:(e,t="__ryunix")=>{o.containerRoot=document.getElementById(t);return F(e,o.containerRoot)},Fragment:e=>a(r.RYUNIX_FRAGMENT,{},...e.children),Hooks:Object.freeze({__proto__:null,useCallback:O,useEffect:S,useMemo:_,useQuery:v,useRef:U,useRouter:L,useStore:I})};window.Ryunix=C,e.Image=({src:e,...t})=>{const o="true"===t.optimization?(({src:e,props:t})=>{const o=new URLSearchParams,n=!e.startsWith("http")||!e.startsWith("https");t.width&&o.set("width",t.width),t.height&&o.set("width",t.height),t.quality&&o.set("quality",t.quality);const r=t.extension?`@${t.extension}`:"",i="http://localhost:3000"===window.location.origin||"http://localhost:5173"===window.location.origin||"http://localhost:4173"===window.location.origin;return n?i?(console.warn("Image optimizations only work with full links and must not contain localhost."),e):`${window.location.origin}/${e}`:`https://image.unsetsoft.com/image/${e}${r}?${o.toString()}`})({src:e,props:t}):e;return a("img",{src:o,props:t},null)},e.default=C,e.useCallback=O,e.useEffect=S,e.useMemo=_,e.useQuery=v,e.useRef=U,e.useRouter=L,e.useStore=I,Object.defineProperty(e,"__esModule",{value:!0})}));
|