@unsetsoft/ryunixjs 1.1.7 → 1.1.9

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/README.md CHANGED
@@ -14,4 +14,6 @@ Like React, NextJS, Preact, Vite. Ryunix allows you to build static websites fro
14
14
 
15
15
  ### Do you want to contribute?
16
16
 
17
- Fork a send a pull request!
17
+ You can make any change as long as it does not affect the `canary` branches. Make changes that are important, necessary or to add something new if you see it necessary, include your proposal before in an issue and then create a PR referencing that issue.
18
+
19
+ To be able to work more comfortably you should create a branch with this name `gh/[user]/[branch name]`, all changes should always go to the canary version. Once the changes are applied and no problems are detected, they will become part of the nightly version for further testing and finally the final version will be released. make each change with a simple descriptive message, and remember not to change the version of the mono repo or packages, such changes are made manually when a new update is about to be made.
package/dist/Ryunix.js CHANGED
@@ -18,14 +18,16 @@
18
18
  const reg = /[A-Z]/g;
19
19
 
20
20
  const RYUNIX_TYPES = Object.freeze({
21
- TEXT_ELEMENT: Symbol('text.element'),
22
- Ryunix_ELEMENT: Symbol('ryunix.element'),
23
- RYUNIX_EFFECT: Symbol('ryunix.effect'),
24
- RYUNIX_MEMO: Symbol('ryunix.memo'),
25
- RYUNIX_URL_QUERY: Symbol('ryunix.urlQuery'),
26
- RYUNIX_REF: Symbol('ryunix.ref'),
27
- RYUNIX_STORE: Symbol('ryunix.store'),
28
- RYUNIX_REDUCE: Symbol('ryunix.reduce'),
21
+ TEXT_ELEMENT: Symbol('text.element').toString(),
22
+ Ryunix_ELEMENT: Symbol('ryunix.element').toString(),
23
+ RYUNIX_EFFECT: Symbol('ryunix.effect').toString(),
24
+ RYUNIX_MEMO: Symbol('ryunix.memo').toString(),
25
+ RYUNIX_URL_QUERY: Symbol('ryunix.urlQuery').toString(),
26
+ RYUNIX_REF: Symbol('ryunix.ref').toString(),
27
+ RYUNIX_STORE: Symbol('ryunix.store').toString(),
28
+ RYUNIX_REDUCE: Symbol('ryunix.reduce').toString(),
29
+ RYUNIX_FRAGMENT: Symbol('ryunix.fragment').toString(),
30
+ RYUNIX_CONTEXT: Symbol('ryunix.context').toString(),
29
31
  });
30
32
 
31
33
  const STRINGS = Object.freeze({
@@ -47,28 +49,9 @@
47
49
  PLACEMENT: Symbol('ryunix.reconciler.status.placement').toString(),
48
50
  UPDATE: Symbol('ryunix.reconciler.status.update').toString(),
49
51
  DELETION: Symbol('ryunix.reconciler.status.deletion').toString(),
52
+ NO_EFFECT: Symbol('ryunix.reconciler.status.no_efect').toString(),
50
53
  });
51
54
 
52
- const generateHash = (prefix) => {
53
- return `${prefix}-${Math.random().toString(36).substring(2, 9)}`
54
- };
55
-
56
- const Fragment = (props) => {
57
- return props.children
58
- };
59
-
60
- const childArray = (children, out) => {
61
- out = out || [];
62
- if (children == undefined || typeof children == STRINGS.boolean) ; else if (Array.isArray(children)) {
63
- children.some((child) => {
64
- childArray(child, out);
65
- });
66
- } else {
67
- out.push(children);
68
- }
69
- return out
70
- };
71
-
72
55
  /**
73
56
  * The function creates a new element with the given type, props, and children.
74
57
  * @param type - The type of the element to be created, such as "div", "span", "h1", etc.
@@ -87,20 +70,15 @@
87
70
  */
88
71
 
89
72
  const createElement = (type, props, ...children) => {
90
- children = childArray(children, []);
91
- const key =
92
- props && props.key
93
- ? generateHash(props.key)
94
- : generateHash(RYUNIX_TYPES.Ryunix_ELEMENT.toString());
95
-
96
73
  return {
97
74
  type,
98
75
  props: {
99
76
  ...props,
100
- key,
101
- children: children.map((child) =>
102
- typeof child === STRINGS.object ? child : createTextElement(child),
103
- ),
77
+ children: children
78
+ .flat()
79
+ .map((child) =>
80
+ typeof child === STRINGS.object ? child : createTextElement(child),
81
+ ),
104
82
  },
105
83
  }
106
84
  };
@@ -122,6 +100,13 @@
122
100
  }
123
101
  };
124
102
 
103
+ const Fragment = (props) => {
104
+ const children = Array.isArray(props.children)
105
+ ? props.children
106
+ : [props.children];
107
+ return createElement(RYUNIX_TYPES.RYUNIX_FRAGMENT, {}, ...children)
108
+ };
109
+
125
110
  const isEvent = (key) => key.startsWith('on');
126
111
  const isProperty = (key) => key !== STRINGS.children && !isEvent(key);
127
112
  const isNew = (prev, next) => (key) => prev[key] !== next[key];
@@ -172,6 +157,9 @@
172
157
  * properties of the newly created
173
158
  */
174
159
  const createDom = (fiber) => {
160
+ if (fiber.type === RYUNIX_TYPES.RYUNIX_FRAGMENT) {
161
+ return null // Los fragmentos no crean nodos DOM reales
162
+ }
175
163
  const dom =
176
164
  fiber.type == RYUNIX_TYPES.TEXT_ELEMENT
177
165
  ? document.createTextNode('')
@@ -258,18 +246,8 @@
258
246
  */
259
247
  const commitRoot = () => {
260
248
  vars.deletions.forEach(commitWork);
261
- if (vars.wipRoot && vars.wipRoot.child) {
262
- commitWork(vars.wipRoot.child);
263
- vars.currentRoot = vars.wipRoot;
264
- }
265
- vars.effects.forEach((effect) => {
266
- try {
267
- effect();
268
- } catch (err) {
269
- console.error('Error in effect:', err);
270
- }
271
- });
272
- vars.effects = [];
249
+ commitWork(vars.wipRoot.child);
250
+ vars.currentRoot = vars.wipRoot;
273
251
  vars.wipRoot = null;
274
252
  };
275
253
 
@@ -281,7 +259,9 @@
281
259
  * @returns The function does not return anything, it performs side effects by manipulating the DOM.
282
260
  */
283
261
  const commitWork = (fiber) => {
284
- if (!fiber) return
262
+ if (!fiber) {
263
+ return
264
+ }
285
265
 
286
266
  let domParentFiber = fiber.parent;
287
267
  while (!domParentFiber.dom) {
@@ -289,20 +269,23 @@
289
269
  }
290
270
  const domParent = domParentFiber.dom;
291
271
 
292
- if (fiber.effectTag === EFFECT_TAGS.PLACEMENT && fiber.dom != null) {
293
- domParent.appendChild(fiber.dom);
272
+ if (fiber.effectTag === EFFECT_TAGS.PLACEMENT) {
273
+ if (fiber.dom != null) {
274
+ domParent.appendChild(fiber.dom);
275
+ }
294
276
  runEffects(fiber);
295
- } else if (fiber.effectTag === EFFECT_TAGS.UPDATE && fiber.dom != null) {
277
+ } else if (fiber.effectTag === EFFECT_TAGS.UPDATE) {
296
278
  cancelEffects(fiber);
297
- updateDom(fiber.dom, fiber.alternate.props, fiber.props);
279
+ if (fiber.dom != null) {
280
+ updateDom(fiber.dom, fiber.alternate.props, fiber.props);
281
+ }
298
282
  runEffects(fiber);
299
283
  } else if (fiber.effectTag === EFFECT_TAGS.DELETION) {
300
- commitDeletion(fiber, domParent);
301
284
  cancelEffects(fiber);
285
+ commitDeletion(fiber, domParent);
302
286
  return
303
287
  }
304
288
 
305
- // Recorre los "fibers" hijos y hermanos
306
289
  commitWork(fiber.child);
307
290
  commitWork(fiber.sibling);
308
291
  };
@@ -318,7 +301,11 @@
318
301
  if (fiber.dom) {
319
302
  domParent.removeChild(fiber.dom);
320
303
  } else {
321
- commitDeletion(fiber.child, domParent);
304
+ let child = fiber.child;
305
+ while (child) {
306
+ commitDeletion(child, domParent);
307
+ child = child.sibling;
308
+ }
322
309
  }
323
310
  };
324
311
 
@@ -331,53 +318,28 @@
331
318
  * @param elements - an array of elements representing the new children to be rendered in the current
332
319
  * fiber's subtree
333
320
  */
334
- const shouldComponentUpdate = (oldProps, newProps) => {
335
- // Comparar las propiedades antiguas y nuevas
336
- return (
337
- !oldProps ||
338
- !newProps ||
339
- Object.keys(oldProps).length !== Object.keys(newProps).length ||
340
- Object.keys(newProps).some((key) => oldProps[key] !== newProps[key])
341
- )
342
- };
343
-
344
- const recycleFiber = (oldFiber, newProps) => {
345
- return {
346
- ...oldFiber,
347
- props: newProps,
348
- alternate: oldFiber,
349
- effectTag: EFFECT_TAGS.UPDATE,
350
- }
351
- };
352
-
353
321
  const reconcileChildren = (wipFiber, elements) => {
354
322
  let index = 0;
355
323
  let oldFiber = wipFiber.alternate && wipFiber.alternate.child;
356
- let prevSibling = null;
357
-
358
- const oldFibersMap = new Map();
359
- while (oldFiber) {
360
- const oldKey = oldFiber.props.key || oldFiber.type;
361
- oldFibersMap.set(oldKey, oldFiber);
362
- oldFiber = oldFiber.sibling;
363
- }
324
+ let prevSibling;
364
325
 
365
- while (index < elements.length) {
326
+ while (index < elements.length || oldFiber != null) {
366
327
  const element = elements[index];
367
- const key = element.props.key || element.type;
368
- const oldFiber = oldFibersMap.get(key);
369
-
370
328
  let newFiber;
371
- const sameType = oldFiber && element && element.type === oldFiber.type;
372
329
 
373
- if (sameType && !shouldComponentUpdate(oldFiber.props, element.props)) {
374
- // Reutilizar fibra existente si no hay cambios
375
- newFiber = recycleFiber(oldFiber, element.props);
376
- oldFibersMap.delete(key);
377
- }
330
+ const sameType = oldFiber && element && element.type == oldFiber.type;
378
331
 
332
+ if (sameType) {
333
+ newFiber = {
334
+ type: oldFiber.type,
335
+ props: element.props,
336
+ dom: oldFiber.dom,
337
+ parent: wipFiber,
338
+ alternate: oldFiber,
339
+ effectTag: EFFECT_TAGS.UPDATE,
340
+ };
341
+ }
379
342
  if (element && !sameType) {
380
- // Crear nueva fibra
381
343
  newFiber = {
382
344
  type: element.type,
383
345
  props: element.props,
@@ -387,28 +349,24 @@
387
349
  effectTag: EFFECT_TAGS.PLACEMENT,
388
350
  };
389
351
  }
390
-
391
352
  if (oldFiber && !sameType) {
392
353
  oldFiber.effectTag = EFFECT_TAGS.DELETION;
393
- wipFiber.effects = wipFiber.effects || [];
394
- wipFiber.effects.push(oldFiber);
354
+ vars.deletions.push(oldFiber);
355
+ }
356
+
357
+ if (oldFiber) {
358
+ oldFiber = oldFiber.sibling;
395
359
  }
396
360
 
397
361
  if (index === 0) {
398
362
  wipFiber.child = newFiber;
399
- } else if (prevSibling) {
363
+ } else if (element) {
400
364
  prevSibling.sibling = newFiber;
401
365
  }
402
366
 
403
367
  prevSibling = newFiber;
404
-
405
368
  index++;
406
369
  }
407
-
408
- oldFibersMap.forEach((oldFiber) => {
409
- oldFiber.effectTag = EFFECT_TAGS.DELETION;
410
- vars.deletions.push(oldFiber);
411
- });
412
370
  };
413
371
 
414
372
  /**
@@ -422,11 +380,15 @@
422
380
  vars.wipFiber = fiber;
423
381
  vars.hookIndex = 0;
424
382
  vars.wipFiber.hooks = [];
383
+ const children = [fiber.type(fiber.props)];
425
384
 
426
- const children = fiber.type(fiber.props);
427
- let childArr = Array.isArray(children) ? children : [children];
385
+ // Aquí detectamos si es Provider para guardar contexto y valor en fiber
386
+ if (fiber.type._contextId && fiber.props.value !== undefined) {
387
+ fiber._contextId = fiber.type._contextId;
388
+ fiber._contextValue = fiber.props.value;
389
+ }
428
390
 
429
- reconcileChildren(fiber, childArr);
391
+ reconcileChildren(fiber, children);
430
392
  };
431
393
 
432
394
  /**
@@ -436,10 +398,18 @@
436
398
  * fibers in the tree.
437
399
  */
438
400
  const updateHostComponent = (fiber) => {
439
- if (!fiber.dom) {
440
- fiber.dom = createDom(fiber);
401
+ const children = Array.isArray(fiber.props.children)
402
+ ? fiber.props.children.flat()
403
+ : [fiber.props.children];
404
+
405
+ if (fiber.type === RYUNIX_TYPES.RYUNIX_FRAGMENT) {
406
+ reconcileChildren(fiber, children);
407
+ } else {
408
+ if (!fiber.dom) {
409
+ fiber.dom = createDom(fiber);
410
+ }
411
+ reconcileChildren(fiber, children);
441
412
  }
442
- reconcileChildren(fiber, fiber.props.children);
443
413
  };
444
414
 
445
415
  /* Internal components*/
@@ -528,7 +498,7 @@
528
498
  requestIdleCallback(workLoop);
529
499
  };
530
500
 
531
- //requestIdleCallback(workLoop)
501
+ requestIdleCallback(workLoop);
532
502
 
533
503
  /**
534
504
  * The function performs a unit of work by updating either a function component or a host component and
@@ -540,7 +510,7 @@
540
510
  * @returns The function `performUnitOfWork` returns the next fiber to be processed. If the current
541
511
  * fiber has a child, it returns the child. Otherwise, it looks for the next sibling of the current
542
512
  * fiber. If there are no more siblings, it goes up the tree to the parent and looks for the next
543
- * sibling of the parent. The function returns `undefined` if there are no more fibers to process.
513
+ * sibling of the parent. The function returns `null` if there are no more fibers to process.
544
514
  */
545
515
  const performUnitOfWork = (fiber) => {
546
516
  const isFunctionComponent = fiber.type instanceof Function;
@@ -559,7 +529,6 @@
559
529
  }
560
530
  nextFiber = nextFiber.parent;
561
531
  }
562
- return undefined
563
532
  };
564
533
 
565
534
  const scheduleWork = (root) => {
@@ -708,6 +677,15 @@
708
677
  vars.hookIndex++;
709
678
  };
710
679
 
680
+ /**
681
+ * The useRef function in JavaScript is used to create a reference object that persists between renders
682
+ * in a functional component.
683
+ * @param initial - The `initial` parameter in the `useRef` function represents the initial value that
684
+ * will be assigned to the `current` property of the reference object. This initial value will be used
685
+ * if there is no previous value stored in the hook.
686
+ * @returns The `useRef` function is returning the `current` property of the `hook.value` object. This
687
+ * property contains the current value of the reference being managed by the `useRef` hook.
688
+ */
711
689
  const useRef = (initial) => {
712
690
  const oldHook =
713
691
  vars.wipFiber.alternate &&
@@ -725,6 +703,19 @@
725
703
  return hook.value
726
704
  };
727
705
 
706
+ /**
707
+ * The useMemo function in JavaScript is used to memoize the result of a computation based on the
708
+ * dependencies provided.
709
+ * @param comp - The `comp` parameter in the `useMemo` function is a function that represents the
710
+ * computation that needs to be memoized. This function will be executed to calculate the memoized
711
+ * value based on the dependencies provided.
712
+ * @param deps - The `deps` parameter in the `useMemo` function stands for dependencies. It is an array
713
+ * of values that the function depends on. The `useMemo` function will only recompute the memoized
714
+ * value when one of the dependencies has changed.
715
+ * @returns The `useMemo` function returns the `value` property of the `hook` object, which is either
716
+ * the memoized value from the previous render if the dependencies have not changed, or the result of
717
+ * calling the `comp` function if the dependencies have changed.
718
+ */
728
719
  const useMemo = (comp, deps) => {
729
720
  const oldHook =
730
721
  vars.wipFiber.alternate &&
@@ -753,6 +744,16 @@
753
744
  return hook.value
754
745
  };
755
746
 
747
+ /**
748
+ * The useCallback function in JavaScript returns a memoized version of the callback function that only
749
+ * changes if one of the dependencies has changed.
750
+ * @param callback - The `callback` parameter is a function that you want to memoize using
751
+ * `useCallback`. This function will only be re-created if any of the dependencies specified in the
752
+ * `deps` array change.
753
+ * @param deps - Dependencies array that the callback function depends on.
754
+ * @returns The useCallback function is returning a memoized version of the callback function. It is
755
+ * using the useMemo hook to memoize the callback function based on the provided dependencies (deps).
756
+ */
756
757
  const useCallback = (callback, deps) => {
757
758
  return useMemo(() => callback, deps)
758
759
  };
@@ -771,6 +772,37 @@
771
772
  return query
772
773
  };
773
774
 
775
+ const createContext = (defaultValue) => {
776
+ const contextId = RYUNIX_TYPES.RYUNIX_CONTEXT;
777
+
778
+ const Provider = ({ value, children }) => {
779
+ return Fragment({
780
+ children: children,
781
+ })
782
+ };
783
+
784
+ Provider._contextId = contextId;
785
+
786
+ const useContext = () => {
787
+ let fiber = vars.wipFiber;
788
+ while (fiber) {
789
+ if (fiber.type && fiber.type._contextId === contextId) {
790
+ if (fiber.props && 'value' in fiber.props) {
791
+ return fiber.props.value
792
+ }
793
+ return undefined
794
+ }
795
+ fiber = fiber.parent;
796
+ }
797
+ return defaultValue
798
+ };
799
+
800
+ return {
801
+ Provider,
802
+ useContext,
803
+ }
804
+ };
805
+
774
806
  /**
775
807
  * `useRouter` is a routing function to manage navigation, nested routes, and route pre-loading.
776
808
  *
@@ -826,115 +858,243 @@
826
858
  * </>
827
859
  * );
828
860
  */
829
- const useRouter = (routes) => {
830
- const [location, setLocation] = useStore(window.location.pathname);
831
-
832
- const findRoute = (routes, path) => {
833
- const pathname = path.split('?')[0];
861
+ // const useRouter = (routes) => {
862
+ // const [location, setLocation] = useStore(window.location.pathname)
863
+
864
+ // const findRoute = (routes, path) => {
865
+ // const pathname = path.split('?')[0]
866
+
867
+ // const notFoundRoute = routes.find((route) => route.NotFound)
868
+ // const notFound = notFoundRoute
869
+ // ? { route: { component: notFoundRoute.NotFound }, params: {} }
870
+ // : { route: { component: null }, params: {} }
871
+
872
+ // for (const route of routes) {
873
+ // if (route.subRoutes) {
874
+ // const childRoute = findRoute(route.subRoutes, path)
875
+ // if (childRoute) return childRoute
876
+ // }
877
+
878
+ // if (route.path === '*') {
879
+ // return notFound
880
+ // }
881
+
882
+ // if (!route.path || typeof route.path !== 'string') {
883
+ // console.warn('Invalid route detected:', route)
884
+ // console.info(
885
+ // "if you are using { NotFound: NotFound } please add { path: '*', NotFound: NotFound }",
886
+ // )
887
+ // continue
888
+ // }
889
+
890
+ // const keys = []
891
+ // const pattern = new RegExp(
892
+ // `^${route.path.replace(/:\w+/g, (match) => {
893
+ // keys.push(match.substring(1))
894
+ // return '([^/]+)'
895
+ // })}$`,
896
+ // )
897
+
898
+ // const match = pathname.match(pattern)
899
+ // if (match) {
900
+ // const params = keys.reduce((acc, key, index) => {
901
+ // acc[key] = match[index + 1]
902
+ // return acc
903
+ // }, {})
904
+
905
+ // return { route, params }
906
+ // }
907
+ // }
908
+
909
+ // return notFound
910
+ // }
911
+
912
+ // const navigate = (path) => {
913
+ // window.history.pushState({}, '', path)
914
+
915
+ // updateRoute(path)
916
+ // }
917
+
918
+ // const updateRoute = (path) => {
919
+ // const cleanedPath = path.split('?')[0]
920
+ // setLocation(cleanedPath)
921
+ // }
922
+
923
+ // useEffect(() => {
924
+ // const onPopState = () => updateRoute(window.location.pathname)
925
+ // window.addEventListener('popstate', onPopState)
926
+
927
+ // return () => window.removeEventListener('popstate', onPopState)
928
+ // }, [])
929
+
930
+ // const currentRouteData = findRoute(routes, location) || {}
931
+
932
+ // const Children = () => {
933
+ // const query = useQuery()
934
+ // const { route } = currentRouteData
935
+
936
+ // if (
937
+ // !route ||
938
+ // !route.component ||
939
+ // typeof route.component !== STRINGS.function
940
+ // ) {
941
+ // console.error(
942
+ // 'Component not found for current path or the component is not a valid function:',
943
+ // currentRouteData,
944
+ // )
945
+ // return null
946
+ // }
947
+
948
+ // const WrappedComponent = () =>
949
+ // createElement(route.component, {
950
+ // key: location,
951
+ // params: currentRouteData.params || {},
952
+ // query,
953
+ // })
954
+
955
+ // return createElement(WrappedComponent)
956
+ // }
957
+
958
+ // const NavLink = ({ to, ...props }) => {
959
+ // const handleClick = (e) => {
960
+ // e.preventDefault()
961
+ // navigate(to)
962
+ // }
963
+ // return createElement(
964
+ // 'a',
965
+ // { href: to, onClick: handleClick, ...props },
966
+ // props.children,
967
+ // )
968
+ // }
969
+
970
+ // return { Children, NavLink, navigate }
971
+ // }
972
+
973
+ // Crear contexto para Router
974
+ const RouterContext = createContext({
975
+ location: '/',
976
+ params: {},
977
+ query: {},
978
+ navigate: (path) => {},
979
+ route: null,
980
+ });
834
981
 
835
- const notFoundRoute = routes.find((route) => route.NotFound);
836
- const notFound = notFoundRoute
837
- ? { route: { component: notFoundRoute.NotFound }, params: {} }
838
- : { route: { component: null }, params: {} };
982
+ const findRoute = (routes, path) => {
983
+ const pathname = path.split('?')[0];
839
984
 
840
- for (const route of routes) {
841
- if (route.subRoutes) {
842
- const childRoute = findRoute(route.subRoutes, path);
843
- if (childRoute) return childRoute
844
- }
985
+ const notFoundRoute = routes.find((route) => route.NotFound);
986
+ const notFound = notFoundRoute
987
+ ? { route: { component: notFoundRoute.NotFound }, params: {} }
988
+ : { route: { component: null }, params: {} };
845
989
 
846
- if (route.path === '*') {
847
- return notFound
848
- }
990
+ for (const route of routes) {
991
+ if (route.subRoutes) {
992
+ const childRoute = findRoute(route.subRoutes, path);
993
+ if (childRoute) return childRoute
994
+ }
849
995
 
850
- if (!route.path || typeof route.path !== 'string') {
851
- console.warn('Invalid route detected:', route);
852
- console.info(
853
- "if you are using { NotFound: NotFound } please add { path: '*', NotFound: NotFound }",
854
- );
855
- continue
856
- }
996
+ if (route.path === '*') {
997
+ return notFound
998
+ }
857
999
 
858
- const keys = [];
859
- const pattern = new RegExp(
860
- `^${route.path.replace(/:\w+/g, (match) => {
861
- keys.push(match.substring(1));
862
- return '([^/]+)'
863
- })}$`,
1000
+ if (!route.path || typeof route.path !== 'string') {
1001
+ console.warn('Invalid route detected:', route);
1002
+ console.info(
1003
+ "if you are using { NotFound: NotFound } please add { path: '*', NotFound: NotFound }",
864
1004
  );
1005
+ continue
1006
+ }
865
1007
 
866
- const match = pathname.match(pattern);
867
- if (match) {
868
- const params = keys.reduce((acc, key, index) => {
869
- acc[key] = match[index + 1];
870
- return acc
871
- }, {});
872
-
873
- return { route, params }
874
- }
1008
+ const keys = [];
1009
+ const pattern = new RegExp(
1010
+ `^${route.path.replace(/:\w+/g, (match) => {
1011
+ keys.push(match.substring(1));
1012
+ return '([^/]+)'
1013
+ })}$`,
1014
+ );
1015
+
1016
+ const match = pathname.match(pattern);
1017
+ if (match) {
1018
+ const params = keys.reduce((acc, key, index) => {
1019
+ acc[key] = match[index + 1];
1020
+ return acc
1021
+ }, {});
1022
+
1023
+ return { route, params }
875
1024
  }
1025
+ }
876
1026
 
877
- return notFound
878
- };
1027
+ return notFound
1028
+ };
1029
+
1030
+ const RouterProvider = ({ routes, children }) => {
1031
+ const [location, setLocation] = useStore(window.location.pathname);
1032
+
1033
+ useEffect(() => {
1034
+ const onPopState = () => setLocation(window.location.pathname);
1035
+ window.addEventListener('popstate', onPopState);
1036
+ return () => window.removeEventListener('popstate', onPopState)
1037
+ }, []);
879
1038
 
880
1039
  const navigate = (path) => {
881
1040
  window.history.pushState({}, '', path);
882
- updateRoute(path);
1041
+ setLocation(path);
883
1042
  };
884
1043
 
885
- const updateRoute = (path) => {
886
- const cleanedPath = path.split('?')[0];
887
- setLocation(cleanedPath);
1044
+ const currentRouteData = findRoute(routes, location) || {};
1045
+ const query = useQuery();
1046
+
1047
+ const contextValue = {
1048
+ location,
1049
+ params: currentRouteData.params || {},
1050
+ query,
1051
+ navigate,
1052
+ route: currentRouteData.route,
888
1053
  };
889
1054
 
890
- useEffect(() => {
891
- const onPopState = () => updateRoute(window.location.pathname);
892
- window.addEventListener('popstate', onPopState);
1055
+ return createElement(
1056
+ RouterContext.Provider,
1057
+ { value: contextValue },
1058
+ Fragment({
1059
+ children: children,
1060
+ }),
1061
+ )
1062
+ };
893
1063
 
894
- return () => window.removeEventListener('popstate', onPopState)
895
- }, []);
1064
+ const useRouter = () => {
1065
+ return RouterContext.useContext()
1066
+ };
896
1067
 
897
- const currentRouteData = findRoute(routes, location) || {};
1068
+ const Children = () => {
1069
+ const { route, params, query, location } = useRouter();
898
1070
 
899
- const Children = () => {
900
- const query = useQuery();
901
- const { route } = currentRouteData;
902
-
903
- if (
904
- !route ||
905
- !route.component ||
906
- typeof route.component !== STRINGS.function
907
- ) {
908
- console.error(
909
- 'Component not found for current path or the component is not a valid function:',
910
- currentRouteData,
911
- );
912
- return null
913
- }
1071
+ if (!route || !route.component) return null
914
1072
 
915
- return route.component({
916
- params: currentRouteData.params || {},
917
- query,
918
- })
919
- };
1073
+ return createElement(route.component, { key: location, params, query })
1074
+ };
920
1075
 
921
- const NavLink = ({ to, ...props }) => {
922
- const handleClick = (e) => {
923
- e.preventDefault();
924
- navigate(to);
925
- };
926
- return createElement(
927
- 'a',
928
- { href: to, onClick: handleClick, ...props },
929
- props.children,
930
- )
1076
+ // Componente NavLink para navegación interna
1077
+ const NavLink = ({ to, ...props }) => {
1078
+ const { navigate } = useRouter();
1079
+
1080
+ const handleClick = (e) => {
1081
+ e.preventDefault();
1082
+ navigate(to);
931
1083
  };
932
1084
 
933
- return { Children, NavLink, navigate }
1085
+ return createElement(
1086
+ 'a',
1087
+ { href: to, onClick: handleClick, ...props },
1088
+ props.children,
1089
+ )
934
1090
  };
935
1091
 
936
1092
  var Hooks = /*#__PURE__*/Object.freeze({
937
1093
  __proto__: null,
1094
+ Children: Children,
1095
+ NavLink: NavLink,
1096
+ RouterProvider: RouterProvider,
1097
+ createContext: createContext,
938
1098
  useCallback: useCallback,
939
1099
  useEffect: useEffect,
940
1100
  useMemo: useMemo,
@@ -954,7 +1114,11 @@
954
1114
 
955
1115
  window.Ryunix = Ryunix;
956
1116
 
1117
+ exports.Children = Children;
957
1118
  exports.Image = Image;
1119
+ exports.NavLink = NavLink;
1120
+ exports.RouterProvider = RouterProvider;
1121
+ exports.createContext = createContext;
958
1122
  exports.default = Ryunix;
959
1123
  exports.useCallback = useCallback;
960
1124
  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"),Ryunix_ELEMENT:Symbol("ryunix.element"),RYUNIX_EFFECT:Symbol("ryunix.effect"),RYUNIX_MEMO:Symbol("ryunix.memo"),RYUNIX_URL_QUERY:Symbol("ryunix.urlQuery"),RYUNIX_REF:Symbol("ryunix.ref"),RYUNIX_STORE:Symbol("ryunix.store"),RYUNIX_REDUCE:Symbol("ryunix.reduce")}),s=Object.freeze({object:"object",function:"function",style:"ryunix-style",className:"ryunix-class",children:"children",boolean:"boolean",string:"string"}),i=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()}),a=e=>`${e}-${Math.random().toString(36).substring(2,9)}`,c=(e,t)=>(t=t||[],null==e||typeof e==s.boolean||(Array.isArray(e)?e.some((e=>{c(e,t)})):t.push(e)),t),u=(e,t,...o)=>{o=c(o,[]);const n=t&&t.key?a(t.key):a(r.Ryunix_ELEMENT.toString());return{type:e,props:{...t,key:n,children:o.map((e=>typeof e===s.object?e:p(e)))}}},p=e=>({type:r.TEXT_ELEMENT,props:{nodeValue:e,children:[]}}),f=e=>e.startsWith("on"),d=e=>e!==s.children&&!f(e),h=(e,t)=>o=>e[o]!==t[o],y=e=>t=>!(t in e),m=e=>{e.hooks&&e.hooks.filter((e=>e.tag===r.RYUNIX_EFFECT&&e.cancel)).forEach((e=>{e.cancel()}))},E=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(f).filter((e=>y(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(y(o)).forEach((t=>{e[t]=""})),Object.keys(o).filter(d).filter(h(t,o)).forEach((n=>{if(n===s.style)b(e,o["ryunix-style"]);else if(n===i.style)b(e,o.style);else if(n===s.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===i.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(f).filter(h(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]};`),"")},k=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),E(e);else if(e.effectTag===l.UPDATE&&null!=e.dom)m(e),w(e.dom,e.alternate.props,e.props),E(e);else if(e.effectTag===l.DELETION)return R(e,o),void m(e);k(e.child),k(e.sibling)},R=(e,t)=>{e.dom?t.removeChild(e.dom):R(e.child,t)},x=(e,t)=>!e||!t||Object.keys(e).length!==Object.keys(t).length||Object.keys(t).some((o=>e[o]!==t[o])),g=(e,t)=>({...e,props:t,alternate:e,effectTag:l.UPDATE}),N=(e,t)=>{let n=0,r=e.alternate&&e.alternate.child,s=null;const i=new Map;for(;r;){const e=r.props.key||r.type;i.set(e,r),r=r.sibling}for(;n<t.length;){const o=t[n],r=o.props.key||o.type,a=i.get(r);let c;const u=a&&o&&o.type===a.type;u&&!x(a.props,o.props)&&(c=g(a,o.props),i.delete(r)),o&&!u&&(c={type:o.type,props:o.props,dom:null,parent:e,alternate:null,effectTag:l.PLACEMENT}),a&&!u&&(a.effectTag=l.DELETION,e.effects=e.effects||[],e.effects.push(a)),0===n?e.child=c:s&&(s.sibling=c),s=c,n++}i.forEach((e=>{e.effectTag=l.DELETION,o.deletions.push(e)}))},F=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)),N(e,e.props.children)},I=e=>{let t=!1;for(;o.nextUnitOfWork&&!t;)o.nextUnitOfWork=T(o.nextUnitOfWork),t=e.timeRemaining()<1;!o.nextUnitOfWork&&o.wipRoot&&(o.deletions.forEach(k),o.wipRoot&&o.wipRoot.child&&(k(o.wipRoot.child),o.currentRoot=o.wipRoot),o.effects.forEach((e=>{try{e()}catch(e){console.error("Error in effect:",e)}})),o.effects=[],o.wipRoot=null),requestIdleCallback(I)},T=e=>{if(e.type instanceof Function?(e=>{o.wipFiber=e,o.hookIndex=0,o.wipFiber.hooks=[];const t=e.type(e.props);let n=Array.isArray(t)?t:[t];N(e,n)})(e):F(e),e.child)return e.child;let t=e;for(;t;){if(t.sibling)return t.sibling;t=t.parent}},O=e=>{o.nextUnitOfWork=e,o.wipRoot=e,o.deletions=[],o.hookIndex=0,o.effects=[],requestIdleCallback(I)},L=(e,t)=>(o.wipRoot={dom:t,props:{children:[e]},alternate:o.currentRoot},o.nextUnitOfWork=o.wipRoot,o.deletions=[],O(o.wipRoot),o.wipRoot),U=(e,t)=>v(((e,t)=>"function"==typeof t?t(e):t),e,t),v=(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(e),o.wipRoot={dom:o.currentRoot.dom,props:o.currentRoot.props,alternate:o.currentRoot},o.deletions=[],o.hookIndex=0,O(o.wipRoot)}]},_=(e,n)=>{const s=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],i={type:r.RYUNIX_EFFECT,deps:n,cleanup:s?.cleanup};(!s||!t.isEqual(s.deps,n))&&o.effects.push((()=>{"function"==typeof i.cleanup&&i.cleanup();const t=e();"function"==typeof t&&(i.cleanup=t)})),o.wipFiber.hooks[o.hookIndex]=i,o.hookIndex++},S=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 s=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],i={type:r.RYUNIX_MEMO,value:null,deps:n};return s&&t.isEqual(s.deps,i.deps)?i.value=s.value:i.value=e(),o.wipFiber.hooks[o.hookIndex]=i,o.hookIndex++,i.value},j=(e,t)=>C((()=>e),t),M=()=>{const e=new URLSearchParams(window.location.search),t={};for(let[o,n]of e.entries())t[o]=n;return t},q=e=>{const[t,o]=U(window.location.pathname),n=(e,t)=>{const o=t.split("?")[0],r=e.find((e=>e.NotFound)),s=r?{route:{component:r.NotFound},params:{}}:{route:{component:null},params:{}};for(const r of e){if(r.subRoutes){const e=n(r.subRoutes,t);if(e)return e}if("*"===r.path)return s;if(!r.path||"string"!=typeof r.path){console.warn("Invalid route detected:",r),console.info("if you are using { NotFound: NotFound } please add { path: '*', NotFound: NotFound }");continue}const e=[],i=new RegExp(`^${r.path.replace(/:\w+/g,(t=>(e.push(t.substring(1)),"([^/]+)")))}$`),l=o.match(i);if(l){return{route:r,params:e.reduce(((e,t,o)=>(e[t]=l[o+1],e)),{})}}}return s},r=e=>{window.history.pushState({},"",e),i(e)},i=e=>{const t=e.split("?")[0];o(t)};_((()=>{const e=()=>i(window.location.pathname);return window.addEventListener("popstate",e),()=>window.removeEventListener("popstate",e)}),[]);const l=n(e,t)||{};return{Children:()=>{const e=M(),{route:t}=l;return t&&t.component&&typeof t.component===s.function?t.component({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})=>u("a",{href:e,onClick:t=>{t.preventDefault(),r(e)},...t},t.children),navigate:r}};var A={createElement:u,render:L,init:(e,t="__ryunix")=>{o.containerRoot=document.getElementById(t);return L(e,o.containerRoot)},Fragment:e=>e.children,Hooks:Object.freeze({__proto__:null,useCallback:j,useEffect:_,useMemo:C,useQuery:M,useRef:S,useRouter:q,useStore:U})};window.Ryunix=A,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}`:"",s="http://localhost:3000"===window.location.origin||"http://localhost:5173"===window.location.origin||"http://localhost:4173"===window.location.origin;return n?s?(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 u("img",{src:o,props:t},null)},e.default=A,e.useCallback=j,e.useEffect=_,e.useMemo=C,e.useQuery=M,e.useRef=S,e.useRouter=q,e.useStore=U,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"}),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)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(p).filter(f(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]};`),"")},b=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);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}},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=e=>{let t=!1;for(;o.nextUnitOfWork&&!t;)o.nextUnitOfWork=N(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(k)};requestIdleCallback(k);const N=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}},I=e=>{o.nextUnitOfWork=e,o.wipRoot=e,o.deletions=[],o.hookIndex=0,o.effects=[],requestIdleCallback(k)},F=(e,t)=>(o.wipRoot={dom:t,props:{children:[e]},alternate:o.currentRoot},o.nextUnitOfWork=o.wipRoot,o.deletions=[],I(o.wipRoot),o.wipRoot),T=(e,t)=>v(((e,t)=>"function"==typeof t?t(e):t),e,t),v=(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,I(o.wipRoot)}]},_=(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++},S=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},U=(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)=>U((()=>e),t),O=()=>{const e=new URLSearchParams(window.location.search),t={};for(let[o,n]of e.entries())t[o]=n;return t},L=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}}},X=L({location:"/",params:{},query:{},navigate:e=>{},route:null}),q=(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=q(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},A=({routes:e,children:t})=>{const[o,n]=T(window.location.pathname);_((()=>{const e=()=>n(window.location.pathname);return window.addEventListener("popstate",e),()=>window.removeEventListener("popstate",e)}),[]);const r=q(e,o)||{},i=O(),s={location:o,params:r.params||{},query:i,navigate:e=>{window.history.pushState({},"",e),n(e)},route:r.route};return a(X.Provider,{value:s},u({children:t}))},M=()=>X.useContext(),Y=()=>{const{route:e,params:t,query:o,location:n}=M();return e&&e.component?a(e.component,{key:n,params:t,query:o}):null},j=({to:e,...t})=>{const{navigate:o}=M();return a("a",{href:e,onClick:t=>{t.preventDefault(),o(e)},...t},t.children)};var P={createElement:a,render:F,init:(e,t="__ryunix")=>{o.containerRoot=document.getElementById(t);return F(e,o.containerRoot)},Fragment:u,Hooks:Object.freeze({__proto__:null,Children:Y,NavLink:j,RouterProvider:A,createContext:L,useCallback:C,useEffect:_,useMemo:U,useQuery:O,useRef:S,useRouter:M,useStore:T})};window.Ryunix=P,e.Children=Y,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.NavLink=j,e.RouterProvider=A,e.createContext=L,e.default=P,e.useCallback=C,e.useEffect=_,e.useMemo=U,e.useQuery=O,e.useRef=S,e.useRouter=M,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.7",
3
+ "version": "1.1.9",
4
4
  "license": "MIT",
5
5
  "main": "./dist/Ryunix.min.js",
6
6
  "types": "./dist/Ryunix.d.ts",