@unsetsoft/ryunixjs 1.1.17 → 1.1.19-canary.2

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
@@ -124,6 +124,7 @@
124
124
  fiber.hooks
125
125
  .filter((hook) => hook.tag === RYUNIX_TYPES.RYUNIX_EFFECT && hook.cancel)
126
126
  .forEach((effectHook) => {
127
+ console.log('[cancelEffects]: ', effectHook);
127
128
  effectHook.cancel();
128
129
  });
129
130
  }
@@ -141,6 +142,8 @@
141
142
  fiber.hooks
142
143
  .filter((hook) => hook.tag === RYUNIX_TYPES.RYUNIX_EFFECT && hook.effect)
143
144
  .forEach((effectHook) => {
145
+ console.log('[runEffects]: ', effectHook);
146
+
144
147
  effectHook.cancel = effectHook.effect();
145
148
  });
146
149
  }
@@ -207,16 +210,22 @@
207
210
  }
208
211
 
209
212
  prevProps['ryunix-class'] &&
210
- dom.classList.remove(...prevProps['ryunix-class'].split(/\s+/));
211
- dom.classList.add(...nextProps['ryunix-class'].split(/\s+/));
213
+ dom.classList.remove(
214
+ ...(prevProps['ryunix-class'].split(/\s+/).filter(Boolean) || []),
215
+ );
216
+ dom.classList.add(
217
+ ...nextProps['ryunix-class'].split(/\s+/).filter(Boolean),
218
+ );
212
219
  } else if (name === OLD_STRINGS.className) {
213
220
  if (nextProps.className === '') {
214
221
  throw new Error('className cannot be empty.')
215
222
  }
216
223
 
217
224
  prevProps.className &&
218
- dom.classList.remove(...prevProps.className.split(/\s+/));
219
- dom.classList.add(...nextProps.className.split(/\s+/));
225
+ dom.classList.remove(
226
+ ...(prevProps.className.split(/\s+/).filter(Boolean) || []),
227
+ );
228
+ dom.classList.add(...nextProps.className.split(/\s+/).filter(Boolean));
220
229
  } else {
221
230
  dom[name] = nextProps[name];
222
231
  }
@@ -595,6 +604,22 @@
595
604
  return useReducer(reducer, initialState, init)
596
605
  };
597
606
 
607
+ /**
608
+ * The `useReducer` function in JavaScript is used to manage state updates based on actions dispatched
609
+ * to a reducer function.
610
+ * @param reducer - The `reducer` parameter in the `useReducer` function is a function that takes the
611
+ * current state and an action as arguments, and returns the new state based on the action. It is used
612
+ * to update the state in response to different actions dispatched by the `dispatch` function.
613
+ * @param initialState - The `initialState` parameter in the `useReducer` function represents the
614
+ * initial state of the reducer. It is the state that will be used when the reducer is first
615
+ * initialized or reset. This initial state can be any value or object that the reducer will operate on
616
+ * and update based on the dispatched actions
617
+ * @param init - The `init` parameter in the `useReducer` function is an optional function that can be
618
+ * used to initialize the state. If provided, it will be called with the `initialState` as its argument
619
+ * and the return value will be used as the initial state value. If `init` is not
620
+ * @returns The `useReducer` function is returning an array with two elements: the current state and a
621
+ * dispatch function.
622
+ */
598
623
  const useReducer = (reducer, initialState, init) => {
599
624
  const oldHook =
600
625
  vars.wipFiber.alternate &&
@@ -602,6 +627,7 @@
602
627
  vars.wipFiber.alternate.hooks[vars.hookIndex];
603
628
 
604
629
  const hook = {
630
+ type: RYUNIX_TYPES.RYUNIX_STORE,
605
631
  state: oldHook ? oldHook.state : init ? init(initialState) : initialState,
606
632
  queue: oldHook && Array.isArray(oldHook.queue) ? oldHook.queue.slice() : [],
607
633
  };
@@ -613,7 +639,9 @@
613
639
  }
614
640
 
615
641
  const dispatch = (action) => {
616
- hook.queue.push(action);
642
+ hook.queue.push(
643
+ typeof action === STRINGS.function ? action : (prev) => action,
644
+ );
617
645
 
618
646
  vars.wipRoot = {
619
647
  dom: vars.currentRoot.dom,
@@ -654,27 +682,12 @@
654
682
  const hook = {
655
683
  type: RYUNIX_TYPES.RYUNIX_EFFECT,
656
684
  deps,
657
- cleanup: oldHook?.cleanup,
685
+ cancel: oldHook?.cancel,
686
+ effect: callback,
658
687
  };
659
688
 
660
- const hasChanged = !oldHook || !lodash.isEqual(oldHook.deps, deps);
661
-
662
- if (hasChanged) {
663
- vars.effects.push(() => {
664
- // Llama al cleanup anterior si existe
665
- if (typeof hook.cleanup === 'function') {
666
- hook.cleanup();
667
- }
668
-
669
- // Ejecuta el nuevo efecto y guarda el nuevo cleanup
670
- const result = callback();
671
- if (typeof result === 'function') {
672
- hook.cleanup = result;
673
- }
674
- });
675
- }
676
-
677
689
  vars.wipFiber.hooks[vars.hookIndex] = hook;
690
+ console.log('[useEffect]: ', vars.wipFiber.hooks[vars.hookIndex]);
678
691
  vars.hookIndex++;
679
692
  };
680
693
 
@@ -759,24 +772,11 @@
759
772
  return useMemo(() => callback, deps)
760
773
  };
761
774
 
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 }) => {
775
+ const createContext = (
776
+ contextId = RYUNIX_TYPES.RYUNIX_CONTEXT,
777
+ defaultValue = {},
778
+ ) => {
779
+ const Provider = ({ children }) => {
780
780
  return Fragment({
781
781
  children: children,
782
782
  })
@@ -784,10 +784,10 @@
784
784
 
785
785
  Provider._contextId = contextId;
786
786
 
787
- const useContext = () => {
787
+ const useContext = (ctxID = RYUNIX_TYPES.RYUNIX_CONTEXT) => {
788
788
  let fiber = vars.wipFiber;
789
789
  while (fiber) {
790
- if (fiber.type && fiber.type._contextId === contextId) {
790
+ if (fiber.type && fiber.type._contextId === ctxID) {
791
791
  if (fiber.props && 'value' in fiber.props) {
792
792
  return fiber.props.value
793
793
  }
@@ -804,175 +804,28 @@
804
804
  }
805
805
  };
806
806
 
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({
807
+ const useQuery = () => {
808
+ const searchParams = new URLSearchParams(window.location.search);
809
+ const query = {};
810
+ for (let [key, value] of searchParams.entries()) {
811
+ query[key] = value;
812
+ }
813
+ return query
814
+ };
815
+
816
+ const useHash = () => {
817
+ const [hash, setHash] = useStore(window.location.hash);
818
+ useEffect(() => {
819
+ const onHashChange = () => {
820
+ setHash(window.location.hash);
821
+ };
822
+ window.addEventListener('hashchange', onHashChange);
823
+ return () => window.removeEventListener('hashchange', onHashChange)
824
+ }, []);
825
+ return hash
826
+ };
827
+
828
+ const RouterContext = createContext('ryunix.navigation', {
976
829
  location: '/',
977
830
  params: {},
978
831
  query: {},
@@ -981,7 +834,7 @@
981
834
  });
982
835
 
983
836
  const findRoute = (routes, path) => {
984
- const pathname = path.split('?')[0];
837
+ const pathname = path.split('?')[0].split('#')[0];
985
838
 
986
839
  const notFoundRoute = routes.find((route) => route.NotFound);
987
840
  const notFound = notFoundRoute
@@ -1032,17 +885,22 @@
1032
885
  const [location, setLocation] = useStore(window.location.pathname);
1033
886
 
1034
887
  useEffect(() => {
1035
- const onPopState = () => setLocation(window.location.pathname);
1036
- window.addEventListener('popstate', onPopState);
1037
- return () => window.removeEventListener('popstate', onPopState)
888
+ const update = () => setLocation(window.location.pathname);
889
+
890
+ window.addEventListener('popstate', update);
891
+ window.addEventListener('hashchange', update);
892
+ return () => {
893
+ window.removeEventListener('popstate', update);
894
+ window.removeEventListener('hashchange', update);
895
+ }
1038
896
  }, []);
1039
897
 
1040
898
  const navigate = (path) => {
1041
899
  window.history.pushState({}, '', path);
1042
- setLocation(path);
900
+ setLocation(window.location.pathname);
1043
901
  };
1044
902
 
1045
- const currentRouteData = findRoute(routes, location) || {};
903
+ const currentRouteData = findRoute(routes, window.location.pathname) || {};
1046
904
  const query = useQuery();
1047
905
 
1048
906
  const contextValue = {
@@ -1063,15 +921,28 @@
1063
921
  };
1064
922
 
1065
923
  const useRouter = () => {
1066
- return RouterContext.useContext()
924
+ return RouterContext.useContext('ryunix.navigation')
1067
925
  };
1068
926
 
1069
927
  const Children = () => {
1070
928
  const { route, params, query, location } = useRouter();
1071
-
1072
929
  if (!route || !route.component) return null
930
+ const hash = useHash();
1073
931
 
1074
- return createElement(route.component, { key: location, params, query })
932
+ useEffect(() => {
933
+ if (hash) {
934
+ const id = hash.slice(1);
935
+ const el = document.getElementById(id);
936
+ if (el) el.scrollIntoView({ block: 'start', behavior: 'smooth' });
937
+ }
938
+ }, [hash]);
939
+
940
+ return createElement(route.component, {
941
+ key: location,
942
+ params,
943
+ query,
944
+ hash,
945
+ })
1075
946
  };
1076
947
 
1077
948
  // Componente NavLink para navegación interna
@@ -1098,6 +969,7 @@
1098
969
  createContext: createContext,
1099
970
  useCallback: useCallback,
1100
971
  useEffect: useEffect,
972
+ useHash: useHash,
1101
973
  useMemo: useMemo,
1102
974
  useQuery: useQuery,
1103
975
  useRef: useRef,
@@ -1123,6 +995,7 @@
1123
995
  exports.default = Ryunix;
1124
996
  exports.useCallback = useCallback;
1125
997
  exports.useEffect = useEffect;
998
+ exports.useHash = useHash;
1126
999
  exports.useMemo = useMemo;
1127
1000
  exports.useQuery = useQuery;
1128
1001
  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=>{console.log("[cancelEffects]: ",e),e.cancel()}))},m=e=>{e.hooks&&e.hooks.filter((e=>e.tag===r.RYUNIX_EFFECT&&e.effect)).forEach((e=>{console.log("[runEffects]: ",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 s=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],a={type:r.RYUNIX_STORE,state:s?s.state:n?n(t):t,queue:s&&Array.isArray(s.queue)?s.queue.slice():[]};s&&Array.isArray(s.queue)&&s.queue.forEach((t=>{a.state=e(a.state,t)}));return a.queue.forEach((t=>{a.state=e(a.state,t)})),o.wipFiber.hooks[o.hookIndex]=a,o.hookIndex++,[a.state,e=>{a.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,t)=>{const n=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],i={type:r.RYUNIX_EFFECT,deps:t,cancel:n?.cancel,effect:e};o.wipFiber.hooks[o.hookIndex]=i,console.log("[useEffect]: ",o.wipFiber.hooks[o.hookIndex]),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},Y=()=>{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},q=O("ryunix.navigation",{location:"/",params:{},query:{},navigate:e=>{},route:null}),A=(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=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]=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=A(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(q.Provider,{value:s},u({children:t}))},j=()=>q.useContext("ryunix.navigation"),P=()=>{const{route:e,params:t,query:o,location:n}=j();if(!e||!e.component)return null;const r=Y();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:Y,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=Y,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-canary.2",
4
4
  "license": "MIT",
5
5
  "main": "./dist/Ryunix.min.js",
6
6
  "types": "./dist/Ryunix.d.ts",
@@ -12,7 +12,6 @@
12
12
  "build:js": "rollup ./src/main.js --file ./dist/Ryunix.min.js --format umd --name Ryunix --plugin @rollup/plugin-terser",
13
13
  "build": "rollup ./src/main.js --file ./dist/Ryunix.js --format umd --name Ryunix",
14
14
  "prepublishOnly": "npm run build:js | npm run build",
15
- "nightly:release": "npm publish --tag nightly",
16
15
  "canary:release": "npm publish --tag canary",
17
16
  "release": "npm publish",
18
17
  "lint": "eslint . --ext .ts --fix --max-warnings=0 --config .eslintrc.js --no-eslintrc",