@unsetsoft/ryunixjs 1.1.17 → 1.1.19

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
@@ -207,16 +207,22 @@
207
207
  }
208
208
 
209
209
  prevProps['ryunix-class'] &&
210
- dom.classList.remove(...prevProps['ryunix-class'].split(/\s+/));
211
- dom.classList.add(...nextProps['ryunix-class'].split(/\s+/));
210
+ dom.classList.remove(
211
+ ...(prevProps['ryunix-class'].split(/\s+/).filter(Boolean) || []),
212
+ );
213
+ dom.classList.add(
214
+ ...nextProps['ryunix-class'].split(/\s+/).filter(Boolean),
215
+ );
212
216
  } else if (name === OLD_STRINGS.className) {
213
217
  if (nextProps.className === '') {
214
218
  throw new Error('className cannot be empty.')
215
219
  }
216
220
 
217
221
  prevProps.className &&
218
- dom.classList.remove(...prevProps.className.split(/\s+/));
219
- dom.classList.add(...nextProps.className.split(/\s+/));
222
+ dom.classList.remove(
223
+ ...(prevProps.className.split(/\s+/).filter(Boolean) || []),
224
+ );
225
+ dom.classList.add(...nextProps.className.split(/\s+/).filter(Boolean));
220
226
  } else {
221
227
  dom[name] = nextProps[name];
222
228
  }
@@ -613,7 +619,9 @@
613
619
  }
614
620
 
615
621
  const dispatch = (action) => {
616
- hook.queue.push(action);
622
+ hook.queue.push(
623
+ typeof action === STRINGS.function ? action : (prev) => action,
624
+ );
617
625
 
618
626
  vars.wipRoot = {
619
627
  dom: vars.currentRoot.dom,
@@ -759,24 +767,11 @@
759
767
  return useMemo(() => callback, deps)
760
768
  };
761
769
 
762
- /**
763
- * The `useQuery` function parses the query parameters from the URL and returns them as an object.
764
- * @returns An object containing key-value pairs of the query parameters from the URLSearchParams in
765
- * the current window's URL is being returned.
766
- */
767
- const useQuery = () => {
768
- const searchParams = new URLSearchParams(window.location.search);
769
- const query = {};
770
- for (let [key, value] of searchParams.entries()) {
771
- query[key] = value;
772
- }
773
- return query
774
- };
775
-
776
- const createContext = (defaultValue) => {
777
- const contextId = RYUNIX_TYPES.RYUNIX_CONTEXT;
778
-
779
- const Provider = ({ value, children }) => {
770
+ const createContext = (
771
+ contextId = RYUNIX_TYPES.RYUNIX_CONTEXT,
772
+ defaultValue = {},
773
+ ) => {
774
+ const Provider = ({ children }) => {
780
775
  return Fragment({
781
776
  children: children,
782
777
  })
@@ -784,10 +779,10 @@
784
779
 
785
780
  Provider._contextId = contextId;
786
781
 
787
- const useContext = () => {
782
+ const useContext = (ctxID = RYUNIX_TYPES.RYUNIX_CONTEXT) => {
788
783
  let fiber = vars.wipFiber;
789
784
  while (fiber) {
790
- if (fiber.type && fiber.type._contextId === contextId) {
785
+ if (fiber.type && fiber.type._contextId === ctxID) {
791
786
  if (fiber.props && 'value' in fiber.props) {
792
787
  return fiber.props.value
793
788
  }
@@ -804,175 +799,28 @@
804
799
  }
805
800
  };
806
801
 
807
- /**
808
- * `useRouter` is a routing function to manage navigation, nested routes, and route pre-loading.
809
- *
810
- * This function handles client-side routing, URL updates, and component rendering based on defined routes. It supports:
811
- * - Dynamic routes (e.g., "/user/:id").
812
- * - Optional nested routes with an `subRoutes` property in route objects.
813
- * - Default pre-loading of all routes except the current active route.
814
- *
815
- * @param {Array} routes - An array of route objects, each containing:
816
- * - `path` (string): The URL path to match (supports dynamic segments like "/user/:id").
817
- * - `component` (function): The component to render when the route matches.
818
- * - `subRoutes` (optional array): An optional array of nested route objects, defining sub-routes for this route.
819
- * - `NotFound` (optional function): Component to render for unmatched routes (default 404 behavior).
820
- *
821
- * @returns {Object} - An object with:
822
- * - `Children` (function): Returns the component that matches the current route, passing route parameters and query parameters as props.
823
- * - `NavLink` (component): A link component to navigate within the application without refreshing the page.
824
- * - `navigate` (function): Allows programmatically navigating to a specific path.
825
- *
826
- * @example
827
- * // Define nested routes
828
- * const routes = [
829
- * {
830
- * path: "/",
831
- * component: HomePage,
832
- * subRoutes: [
833
- * {
834
- * path: "/settings",
835
- * component: SettingsPage,
836
- * },
837
- * ],
838
- * },
839
- * {
840
- * path: "/user/:id",
841
- * component: UserProfile,
842
- * },
843
- * {
844
- * path: "*",
845
- * NotFound: NotFoundPage,
846
- * },
847
- * ];
848
- *
849
- * // Use the routing function
850
- * const { Children, NavLink } = useRouter(routes);
851
- *
852
- * // Render the matched component
853
- * const App = () => (
854
- * <>
855
- * <NavLink to="/">Home</NavLink>
856
- * <NavLink to="/settings">Settings</NavLink>
857
- * <NavLink to="/user/123">User Profile</NavLink>
858
- * <Children />
859
- * </>
860
- * );
861
- */
862
- // const useRouter = (routes) => {
863
- // const [location, setLocation] = useStore(window.location.pathname)
864
-
865
- // const findRoute = (routes, path) => {
866
- // const pathname = path.split('?')[0]
867
-
868
- // const notFoundRoute = routes.find((route) => route.NotFound)
869
- // const notFound = notFoundRoute
870
- // ? { route: { component: notFoundRoute.NotFound }, params: {} }
871
- // : { route: { component: null }, params: {} }
872
-
873
- // for (const route of routes) {
874
- // if (route.subRoutes) {
875
- // const childRoute = findRoute(route.subRoutes, path)
876
- // if (childRoute) return childRoute
877
- // }
878
-
879
- // if (route.path === '*') {
880
- // return notFound
881
- // }
882
-
883
- // if (!route.path || typeof route.path !== 'string') {
884
- // console.warn('Invalid route detected:', route)
885
- // console.info(
886
- // "if you are using { NotFound: NotFound } please add { path: '*', NotFound: NotFound }",
887
- // )
888
- // continue
889
- // }
890
-
891
- // const keys = []
892
- // const pattern = new RegExp(
893
- // `^${route.path.replace(/:\w+/g, (match) => {
894
- // keys.push(match.substring(1))
895
- // return '([^/]+)'
896
- // })}$`,
897
- // )
898
-
899
- // const match = pathname.match(pattern)
900
- // if (match) {
901
- // const params = keys.reduce((acc, key, index) => {
902
- // acc[key] = match[index + 1]
903
- // return acc
904
- // }, {})
905
-
906
- // return { route, params }
907
- // }
908
- // }
909
-
910
- // return notFound
911
- // }
912
-
913
- // const navigate = (path) => {
914
- // window.history.pushState({}, '', path)
915
-
916
- // updateRoute(path)
917
- // }
918
-
919
- // const updateRoute = (path) => {
920
- // const cleanedPath = path.split('?')[0]
921
- // setLocation(cleanedPath)
922
- // }
923
-
924
- // useEffect(() => {
925
- // const onPopState = () => updateRoute(window.location.pathname)
926
- // window.addEventListener('popstate', onPopState)
927
-
928
- // return () => window.removeEventListener('popstate', onPopState)
929
- // }, [])
930
-
931
- // const currentRouteData = findRoute(routes, location) || {}
932
-
933
- // const Children = () => {
934
- // const query = useQuery()
935
- // const { route } = currentRouteData
936
-
937
- // if (
938
- // !route ||
939
- // !route.component ||
940
- // typeof route.component !== STRINGS.function
941
- // ) {
942
- // console.error(
943
- // 'Component not found for current path or the component is not a valid function:',
944
- // currentRouteData,
945
- // )
946
- // return null
947
- // }
948
-
949
- // const WrappedComponent = () =>
950
- // createElement(route.component, {
951
- // key: location,
952
- // params: currentRouteData.params || {},
953
- // query,
954
- // })
955
-
956
- // return createElement(WrappedComponent)
957
- // }
958
-
959
- // const NavLink = ({ to, ...props }) => {
960
- // const handleClick = (e) => {
961
- // e.preventDefault()
962
- // navigate(to)
963
- // }
964
- // return createElement(
965
- // 'a',
966
- // { href: to, onClick: handleClick, ...props },
967
- // props.children,
968
- // )
969
- // }
970
-
971
- // return { Children, NavLink, navigate }
972
- // }
973
-
974
- // Crear contexto para Router
975
- const RouterContext = createContext({
802
+ const useQuery = () => {
803
+ const searchParams = new URLSearchParams(window.location.search);
804
+ const query = {};
805
+ for (let [key, value] of searchParams.entries()) {
806
+ query[key] = value;
807
+ }
808
+ return query
809
+ };
810
+
811
+ const useHash = () => {
812
+ const [hash, setHash] = useStore(window.location.hash);
813
+ useEffect(() => {
814
+ const onHashChange = () => {
815
+ setHash(window.location.hash);
816
+ };
817
+ window.addEventListener('hashchange', onHashChange);
818
+ return () => window.removeEventListener('hashchange', onHashChange)
819
+ }, []);
820
+ return hash
821
+ };
822
+
823
+ const RouterContext = createContext('ryunix.navigation', {
976
824
  location: '/',
977
825
  params: {},
978
826
  query: {},
@@ -981,7 +829,7 @@
981
829
  });
982
830
 
983
831
  const findRoute = (routes, path) => {
984
- const pathname = path.split('?')[0];
832
+ const pathname = path.split('?')[0].split('#')[0];
985
833
 
986
834
  const notFoundRoute = routes.find((route) => route.NotFound);
987
835
  const notFound = notFoundRoute
@@ -1032,17 +880,22 @@
1032
880
  const [location, setLocation] = useStore(window.location.pathname);
1033
881
 
1034
882
  useEffect(() => {
1035
- const onPopState = () => setLocation(window.location.pathname);
1036
- window.addEventListener('popstate', onPopState);
1037
- return () => window.removeEventListener('popstate', onPopState)
883
+ const update = () => setLocation(window.location.pathname);
884
+
885
+ window.addEventListener('popstate', update);
886
+ window.addEventListener('hashchange', update);
887
+ return () => {
888
+ window.removeEventListener('popstate', update);
889
+ window.removeEventListener('hashchange', update);
890
+ }
1038
891
  }, []);
1039
892
 
1040
893
  const navigate = (path) => {
1041
894
  window.history.pushState({}, '', path);
1042
- setLocation(path);
895
+ setLocation(window.location.pathname);
1043
896
  };
1044
897
 
1045
- const currentRouteData = findRoute(routes, location) || {};
898
+ const currentRouteData = findRoute(routes, window.location.pathname) || {};
1046
899
  const query = useQuery();
1047
900
 
1048
901
  const contextValue = {
@@ -1063,15 +916,28 @@
1063
916
  };
1064
917
 
1065
918
  const useRouter = () => {
1066
- return RouterContext.useContext()
919
+ return RouterContext.useContext('ryunix.navigation')
1067
920
  };
1068
921
 
1069
922
  const Children = () => {
1070
923
  const { route, params, query, location } = useRouter();
1071
-
1072
924
  if (!route || !route.component) return null
925
+ const hash = useHash();
1073
926
 
1074
- return createElement(route.component, { key: location, params, query })
927
+ useEffect(() => {
928
+ if (hash) {
929
+ const id = hash.slice(1);
930
+ const el = document.getElementById(id);
931
+ if (el) el.scrollIntoView({ block: 'start', behavior: 'smooth' });
932
+ }
933
+ }, [hash]);
934
+
935
+ return createElement(route.component, {
936
+ key: location,
937
+ params,
938
+ query,
939
+ hash,
940
+ })
1075
941
  };
1076
942
 
1077
943
  // Componente NavLink para navegación interna
@@ -1098,6 +964,7 @@
1098
964
  createContext: createContext,
1099
965
  useCallback: useCallback,
1100
966
  useEffect: useEffect,
967
+ useHash: useHash,
1101
968
  useMemo: useMemo,
1102
969
  useQuery: useQuery,
1103
970
  useRef: useRef,
@@ -1123,6 +990,7 @@
1123
990
  exports.default = Ryunix;
1124
991
  exports.useCallback = useCallback;
1125
992
  exports.useEffect = useEffect;
993
+ exports.useHash = useHash;
1126
994
  exports.useMemo = useMemo;
1127
995
  exports.useQuery = useQuery;
1128
996
  exports.useRef = useRef;
@@ -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(),RYUNIX_CONTEXT:Symbol("ryunix.context").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=>{const t=Array.isArray(e.children)?e.children:[e.children];return a(r.RYUNIX_FRAGMENT,{},...t)},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),y=e=>{e.hooks&&e.hooks.filter((e=>e.tag===r.RYUNIX_EFFECT&&e.cancel)).forEach((e=>{e.cancel()}))},m=e=>{e.hooks&&e.hooks.filter((e=>e.tag===r.RYUNIX_EFFECT&&e.effect)).forEach((e=>{e.cancel=e.effect()}))},E=(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)b(e,o["ryunix-style"]);else if(n===s.style)b(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])}))},b=(e,t)=>{e.style=Object.keys(t).reduce(((e,o)=>e+=`${o.replace(n,(function(e){return"-"+e.toLowerCase()}))}: ${t[o]};`),"")},w=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),m(e);else if(e.effectTag===l.UPDATE)y(e),null!=e.dom&&E(e.dom,e.alternate.props,e.props),m(e);else if(e.effectTag===l.DELETION)return y(e),void x(e,o);w(e.child),w(e.sibling)},x=(e,t)=>{if(e.dom)t.removeChild(e.dom);else{let o=e.child;for(;o;)x(o,t),o=o.sibling}},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++}},g=e=>{const t=Array.isArray(e.props.children)?e.props.children.flat():[e.props.children];e.type===r.RYUNIX_FRAGMENT||e.dom||(e.dom=(e=>{if(e.type===r.RYUNIX_FRAGMENT)return null;const t=e.type==r.TEXT_ELEMENT?document.createTextNode(""):document.createElement(e.type);return E(t,{},e.props),t})(e)),R(e,t)},k=({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("height",t.height),t.quality&&o.set("quality",t.quality);const r=t.extension?`@${t.extension}`:"";return n?(()=>{const{hostname:e}=window.location;return"localhost"===e||"127.0.0.1"===e})()?(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()}`},N=e=>{let t=!1;for(;o.nextUnitOfWork&&!t;)o.nextUnitOfWork=I(o.nextUnitOfWork),t=e.timeRemaining()<1;!o.nextUnitOfWork&&o.wipRoot&&(o.deletions.forEach(w),w(o.wipRoot.child),o.currentRoot=o.wipRoot,o.wipRoot=null),requestIdleCallback(N)};requestIdleCallback(N);const I=e=>{if(e.type instanceof Function?(e=>{o.wipFiber=e,o.hookIndex=0,o.wipFiber.hooks=[];const t=[e.type(e.props)];e.type._contextId&&void 0!==e.props.value&&(e._contextId=e.type._contextId,e._contextValue=e.props.value),R(e,t)})(e):g(e),e.child)return e.child;let t=e;for(;t;){if(t.sibling)return t.sibling;t=t.parent}},F=e=>{o.nextUnitOfWork=e,o.wipRoot=e,o.deletions=[],o.hookIndex=0,o.effects=[],requestIdleCallback(N)},T=(e,t)=>(o.wipRoot={dom:t,props:{children:[e]},alternate:o.currentRoot},o.nextUnitOfWork=o.wipRoot,o.deletions=[],F(o.wipRoot),o.wipRoot),v=(e,t)=>_(((e,t)=>"function"==typeof t?t(e):t),e,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,F(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},C=(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)=>C((()=>e),t),L=()=>{const e=new URLSearchParams(window.location.search),t={};for(let[o,n]of e.entries())t[o]=n;return t},X=e=>{const t=r.RYUNIX_CONTEXT,n=({value:e,children:t})=>u({children:t});n._contextId=t;return{Provider:n,useContext:()=>{let n=o.wipFiber;for(;n;){if(n.type&&n.type._contextId===t)return n.props&&"value"in n.props?n.props.value:void 0;n=n.parent}return e}}},q=X({location:"/",params:{},query:{},navigate:e=>{},route:null}),A=(e,t)=>{const o=t.split("?")[0],n=e.find((e=>e.NotFound)),r=n?{route:{component:n.NotFound},params:{}}:{route:{component:null},params:{}};for(const n of e){if(n.subRoutes){const e=A(n.subRoutes,t);if(e)return e}if("*"===n.path)return r;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=[],i=new RegExp(`^${n.path.replace(/:\w+/g,(t=>(e.push(t.substring(1)),"([^/]+)")))}$`),s=o.match(i);if(s){return{route:n,params:e.reduce(((e,t,o)=>(e[t]=s[o+1],e)),{})}}}return r},M=({routes:e,children:t})=>{const[o,n]=v(window.location.pathname);S((()=>{const e=()=>n(window.location.pathname);return window.addEventListener("popstate",e),()=>window.removeEventListener("popstate",e)}),[]);const r=A(e,o)||{},i=L(),s={location:o,params:r.params||{},query:i,navigate:e=>{window.history.pushState({},"",e),n(e)},route:r.route};return a(q.Provider,{value:s},u({children:t}))},Y=()=>q.useContext(),j=()=>{const{route:e,params:t,query:o,location:n}=Y();return e&&e.component?a(e.component,{key:n,params:t,query:o}):null},P=({to:e,...t})=>{const{navigate:o}=Y();return a("a",{href:e,onClick:t=>{t.preventDefault(),o(e)},...t},t.children)};var W={createElement:a,render:T,init:(e,t="__ryunix")=>{o.containerRoot=document.getElementById(t);return T(e,o.containerRoot)},Fragment:u,Hooks:Object.freeze({__proto__:null,Children:j,NavLink:P,RouterProvider:M,createContext:X,useCallback:O,useEffect:S,useMemo:C,useQuery:L,useRef:U,useRouter:Y,useStore:v})};window.Ryunix=W,e.Children=j,e.Image=({src:e,...t})=>{const o={src:"true"===t.optimization?k({src:e,props:t}):e,...t};return a("img",o,null)},e.NavLink=P,e.RouterProvider=M,e.createContext=X,e.default=W,e.useCallback=O,e.useEffect=S,e.useMemo=C,e.useQuery=L,e.useRef=U,e.useRouter=Y,e.useStore=v,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(),RYUNIX_CONTEXT:Symbol("ryunix.context").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,...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=>{const t=Array.isArray(e.children)?e.children:[e.children];return l(r.RYUNIX_FRAGMENT,{},...t)},p=e=>e.startsWith("on"),d=e=>e!==i.children&&!p(e),h=(e,t)=>o=>e[o]!==t[o],f=e=>t=>!(t in e),y=e=>{e.hooks&&e.hooks.filter((e=>e.tag===r.RYUNIX_EFFECT&&e.cancel)).forEach((e=>{e.cancel()}))},m=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=>f(o)(e)||h(t,o)(e))).forEach((o=>{const n=o.toLowerCase().substring(2);e.removeEventListener(n,t[o])})),Object.keys(t).filter(d).filter(f(o)).forEach((t=>{e[t]=""})),Object.keys(o).filter(d).filter(h(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+/).filter(Boolean)||[]),e.classList.add(...o["ryunix-class"].split(/\s+/).filter(Boolean))}else if(n===s.className){if(""===o.className)throw new Error("className cannot be empty.");t.className&&e.classList.remove(...t.className.split(/\s+/).filter(Boolean)||[]),e.classList.add(...o.className.split(/\s+/).filter(Boolean))}else e[n]=o[n]})),Object.keys(o).filter(p).filter(h(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),m(e);else if(e.effectTag===a.UPDATE)y(e),null!=e.dom&&w(e.dom,e.alternate.props,e.props),m(e);else if(e.effectTag===a.DELETION)return y(e),void x(e,o);b(e.child),b(e.sibling)},x=(e,t)=>{if(e.dom)t.removeChild(e.dom);else{let o=e.child;for(;o;)x(o,t),o=o.sibling}},g=(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++}},R=e=>{const t=Array.isArray(e.props.children)?e.props.children.flat():[e.props.children];e.type===r.RYUNIX_FRAGMENT||e.dom||(e.dom=(e=>{if(e.type===r.RYUNIX_FRAGMENT)return null;const t=e.type==r.TEXT_ELEMENT?document.createTextNode(""):document.createElement(e.type);return w(t,{},e.props),t})(e)),g(e,t)},k=({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("height",t.height),t.quality&&o.set("quality",t.quality);const r=t.extension?`@${t.extension}`:"";return n?(()=>{const{hostname:e}=window.location;return"localhost"===e||"127.0.0.1"===e})()?(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()}`},N=e=>{let t=!1;for(;o.nextUnitOfWork&&!t;)o.nextUnitOfWork=I(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(N)};requestIdleCallback(N);const I=e=>{if(e.type instanceof Function?(e=>{o.wipFiber=e,o.hookIndex=0,o.wipFiber.hooks=[];const t=[e.type(e.props)];e.type._contextId&&void 0!==e.props.value&&(e._contextId=e.type._contextId,e._contextValue=e.props.value),g(e,t)})(e):R(e),e.child)return e.child;let t=e;for(;t;){if(t.sibling)return t.sibling;t=t.parent}},v=e=>{o.nextUnitOfWork=e,o.wipRoot=e,o.deletions=[],o.hookIndex=0,o.effects=[],requestIdleCallback(N)},F=(e,t)=>(o.wipRoot={dom:t,props:{children:[e]},alternate:o.currentRoot},o.nextUnitOfWork=o.wipRoot,o.deletions=[],v(o.wipRoot),o.wipRoot),T=(e,t)=>_(((e,t)=>"function"==typeof t?t(e):t),e,t),_=(e,t,n)=>{const r=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],s={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=>{s.state=e(s.state,t)}));return s.queue.forEach((t=>{s.state=e(s.state,t)})),o.wipFiber.hooks[o.hookIndex]=s,o.hookIndex++,[s.state,e=>{s.queue.push(typeof e===i.function?e:t=>e),o.wipRoot={dom:o.currentRoot.dom,props:o.currentRoot.props,alternate:o.currentRoot},o.deletions=[],o.hookIndex=0,v(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},L=(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},C=(e,t)=>L((()=>e),t),O=(e=r.RYUNIX_CONTEXT,t={})=>{const n=({children:e})=>u({children:e});n._contextId=e;return{Provider:n,useContext:(e=r.RYUNIX_CONTEXT)=>{let n=o.wipFiber;for(;n;){if(n.type&&n.type._contextId===e)return n.props&&"value"in n.props?n.props.value:void 0;n=n.parent}return t}}},X=()=>{const e=new URLSearchParams(window.location.search),t={};for(let[o,n]of e.entries())t[o]=n;return t},q=()=>{const[e,t]=T(window.location.hash);return S((()=>{const e=()=>{t(window.location.hash)};return window.addEventListener("hashchange",e),()=>window.removeEventListener("hashchange",e)}),[]),e},A=O("ryunix.navigation",{location:"/",params:{},query:{},navigate:e=>{},route:null}),Y=(e,t)=>{const o=t.split("?")[0].split("#")[0],n=e.find((e=>e.NotFound)),r=n?{route:{component:n.NotFound},params:{}}:{route:{component:null},params:{}};for(const n of e){if(n.subRoutes){const e=Y(n.subRoutes,t);if(e)return e}if("*"===n.path)return r;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=[],i=new RegExp(`^${n.path.replace(/:\w+/g,(t=>(e.push(t.substring(1)),"([^/]+)")))}$`),s=o.match(i);if(s){return{route:n,params:e.reduce(((e,t,o)=>(e[t]=s[o+1],e)),{})}}}return r},M=({routes:e,children:t})=>{const[o,n]=T(window.location.pathname);S((()=>{const e=()=>n(window.location.pathname);return window.addEventListener("popstate",e),window.addEventListener("hashchange",e),()=>{window.removeEventListener("popstate",e),window.removeEventListener("hashchange",e)}}),[]);const r=Y(e,window.location.pathname)||{},i=X(),s={location:o,params:r.params||{},query:i,navigate:e=>{window.history.pushState({},"",e),n(window.location.pathname)},route:r.route};return l(A.Provider,{value:s},u({children:t}))},j=()=>A.useContext("ryunix.navigation"),P=()=>{const{route:e,params:t,query:o,location:n}=j();if(!e||!e.component)return null;const r=q();return S((()=>{if(r){const e=r.slice(1),t=document.getElementById(e);t&&t.scrollIntoView({block:"start",behavior:"smooth"})}}),[r]),l(e.component,{key:n,params:t,query:o,hash:r})},W=({to:e,...t})=>{const{navigate:o}=j();return l("a",{href:e,onClick:t=>{t.preventDefault(),o(e)},...t},t.children)};var $={createElement:l,render:F,init:(e,t="__ryunix")=>{o.containerRoot=document.getElementById(t);return F(e,o.containerRoot)},Fragment:u,Hooks:Object.freeze({__proto__:null,Children:P,NavLink:W,RouterProvider:M,createContext:O,useCallback:C,useEffect:S,useHash:q,useMemo:L,useQuery:X,useRef:U,useRouter:j,useStore:T})};window.Ryunix=$,e.Children=P,e.Image=({src:e,...t})=>{const o={src:"true"===t.optimization?k({src:e,props:t}):e,...t};return l("img",o,null)},e.NavLink=W,e.RouterProvider=M,e.createContext=O,e.default=$,e.useCallback=C,e.useEffect=S,e.useHash=q,e.useMemo=L,e.useQuery=X,e.useRef=U,e.useRouter=j,e.useStore=T,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.17",
3
+ "version": "1.1.19",
4
4
  "license": "MIT",
5
5
  "main": "./dist/Ryunix.min.js",
6
6
  "types": "./dist/Ryunix.d.ts",