@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 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 Fragments = (props) => props.children;
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
- Fragments,
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;
@@ -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"}),a=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()}),l=(e,t)=>{const o=e.split("/").filter(Boolean),n=t.split("/").filter(Boolean);if("*"===e)return{};if(o.length!==n.length)return null;const r={};for(let e=0;e<o.length;e++){const t=o[e],i=n[e];if(t.startsWith(":"))r[t.slice(1)]=decodeURIComponent(i);else if(t!==i)return null}return r},c=(e,t,...o)=>({type:e,props:{...t,children:o.flat().map((e=>typeof e===i.object?e:u(e)))}}),u=e=>({type:r.TEXT_ELEMENT,props:{nodeValue:e,children:[]}}),p=e=>e.startsWith("on"),d=e=>e!==i.children&&!p(e),f=(e,t)=>o=>e[o]!==t[o],h=e=>t=>!(t in e),m=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()}))},w=(e,t,o)=>{Object.keys(t).filter(p).filter((e=>h(o)(e)||f(t,o)(e))).forEach((o=>{const n=o.toLowerCase().substring(2);e.removeEventListener(n,t[o])})),Object.keys(t).filter(d).filter(h(o)).forEach((t=>{e[t]=""})),Object.keys(o).filter(d).filter(f(t,o)).forEach((n=>{if(n===i.style)E(e,o["ryunix-style"]);else if(n===s.style)E(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(p).filter(f(t,o)).forEach((t=>{const n=t.toLowerCase().substring(2);e.addEventListener(n,o[t])}))},E=(e,t)=>{e.style=Object.keys(t).reduce(((e,o)=>e+=`${o.replace(n,(function(e){return"-"+e.toLowerCase()}))}: ${t[o]};`),"")},b=e=>{if(!e)return;let t=e.parent;for(;!t.dom;)t=t.parent;const o=t.dom;if(e.effectTag===a.PLACEMENT)null!=e.dom&&o.appendChild(e.dom),y(e);else if(e.effectTag===a.UPDATE)m(e),null!=e.dom&&w(e.dom,e.alternate.props,e.props),y(e);else if(e.effectTag===a.DELETION)return m(e),void g(e,o);b(e.child),b(e.sibling)},g=(e,t)=>{e.dom?t.removeChild(e.dom):g(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 l;const c=i&&s&&s.type==i.type;c&&(l={type:i.type,props:s.props,dom:i.dom,parent:e,alternate:i,effectTag:a.UPDATE}),s&&!c&&(l={type:s.type,props:s.props,dom:null,parent:e,alternate:null,effectTag:a.PLACEMENT}),i&&!c&&(i.effectTag=a.DELETION,o.deletions.push(i)),i&&(i=i.sibling),0===r?e.child=l:s&&(n.sibling=l),n=l,r++}},k=(e,t)=>x(((e,t)=>"function"==typeof t?t(e):t),e,t),x=(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,C(o.wipRoot)}]},N=(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++},F=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},I=(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},v=(e,t)=>I((()=>e),t),S=()=>{const e=new URLSearchParams(window.location.search),t={};for(let[o,n]of e.entries())t[o]=n;return t},T=e=>{const[t,n]=k(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)),"([^/]+)")))}$`),a=o.match(s);if(a){return{route:n,params:e.reduce(((e,t,o)=>(e[t]=a[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=[],a(e)},a=e=>{const t=e.split("?")[0];n(t)};N((()=>{const e=()=>a(window.location.pathname);return window.addEventListener("popstate",e),()=>window.removeEventListener("popstate",e)}),[]);const l=r(e,t)||{};return{Children:()=>{const e=S(),{route:o}=l;return o&&o.component&&typeof o.component===i.function?o.component({key:t,params:l.params||{},query:e}):(console.error("Component not found for current path or the component is not a valid function:",l),null)},NavLink:({to:e,...t})=>c("a",{href:e,onClick:t=>{t.preventDefault(),s(e)},...t},t.children),navigate:s}};var U=Object.freeze({__proto__:null,useCallback:v,useEffect:N,useMemo:I,useQuery:S,useRef:F,useRouter:T,useStore:k});const L=e=>{e.dom||(e.dom=(e=>{const t=e.type==r.TEXT_ELEMENT?document.createTextNode(""):document.createElement(e.type);return w(t,{},e.props),t})(e)),R(e,e.props.children.flat())},O=e=>{let t=!1;for(;o.nextUnitOfWork&&!t;)o.nextUnitOfWork=_(o.nextUnitOfWork),t=e.timeRemaining()<1;!o.nextUnitOfWork&&o.wipRoot&&(o.deletions.forEach(b),b(o.wipRoot.child),o.currentRoot=o.wipRoot,o.wipRoot=null),requestIdleCallback(O)};requestIdleCallback(O);const _=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):L(e),e.child)return e.child;let t=e;for(;t;){if(t.sibling)return t.sibling;t=t.parent}},C=e=>{o.nextUnitOfWork=e,o.wipRoot=e,o.deletions=[],o.hookIndex=0,o.effects=[],requestIdleCallback(O)},q=(e,t)=>(o.wipRoot={dom:t,props:{children:[e]},alternate:o.currentRoot},o.nextUnitOfWork=o.wipRoot,o.deletions=[],C(o.wipRoot),o.wipRoot);var j={createElement:c,render:q,init:(e,t="__ryunix")=>{o.containerRoot=document.getElementById(t);return q(e,o.containerRoot)},Fragments:e=>e.children,Hooks:U};window.Ryunix=j,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 c("img",{src:o,props:t},null)},e.Link=({to:e,children:t,navigate:o,...n})=>c("a",{href:e,onClick:t=>{t.preventDefault(),o(e)},...n},t),e.Route=({path:e,element:t,pathname:o,query:n,navigate:r})=>{const i=l(e,o);return i?c(t,{params:i,query:n,navigate:r}):null},e.Router=({children:e})=>{const[t,o]=k({pathname:window.location.pathname,search:window.location.search});return N((()=>{const e=()=>{o({pathname:window.location.pathname,search:window.location.search})};return window.addEventListener("popstate",e),()=>window.removeEventListener("popstate",e)}),[]),e({pathname:t.pathname,query:(n=t.search,n?Object.fromEntries(new URLSearchParams(n)):{}),navigate:e=>{e!==t.pathname+t.search&&(window.history.pushState({},"",e),o({pathname:window.location.pathname,search:window.location.search}))}});var n},e.Routes=({routes:e,pathname:t,query:o,navigate:n})=>{for(const r of e){const e=l(r.path,t);if(null!==e)return c(r.element,{params:e,query:o,navigate:n})}return null},e.default=j,e.useCallback=v,e.useEffect=N,e.useMemo=I,e.useQuery=S,e.useRef=F,e.useRouter=T,e.useStore=k,Object.defineProperty(e,"__esModule",{value:!0})}));
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})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unsetsoft/ryunixjs",
3
- "version": "1.1.7-canary.63",
3
+ "version": "1.1.7-canary.65",
4
4
  "license": "MIT",
5
5
  "main": "./dist/Ryunix.min.js",
6
6
  "types": "./dist/Ryunix.d.ts",