sibujs 3.2.0 → 3.2.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/plugins.cjs CHANGED
@@ -2801,8 +2801,7 @@ function Route() {
2801
2801
  let currentNode = null;
2802
2802
  let loadingNode = null;
2803
2803
  let errorNode = null;
2804
- let isUpdating = false;
2805
- let currentPath = "";
2804
+ let navSeq = 0;
2806
2805
  let currentTopRoute = null;
2807
2806
  const cleanupNodes = () => {
2808
2807
  [currentNode, loadingNode, errorNode].forEach((node) => {
@@ -2880,30 +2879,21 @@ function Route() {
2880
2879
  errorNode.appendChild(retryButton);
2881
2880
  anchor.parentNode.insertBefore(errorNode, anchor.nextSibling);
2882
2881
  };
2883
- let pendingUpdate = false;
2884
2882
  const update = async () => {
2885
2883
  if (!globalRouter) return;
2886
- if (isUpdating) {
2887
- pendingUpdate = true;
2888
- return;
2889
- }
2884
+ const seq = ++navSeq;
2890
2885
  const route2 = globalRouter.currentRoute;
2891
2886
  try {
2892
2887
  const match = globalRouter["matcher"].match(route2.path);
2893
2888
  if (!match) {
2894
- currentPath = route2.path;
2895
2889
  currentTopRoute = null;
2896
2890
  cleanupNodes();
2897
2891
  return;
2898
2892
  }
2899
2893
  const routeDef = match.matched[0] || match.route;
2900
2894
  if (routeDef === currentTopRoute && currentNode) {
2901
- currentPath = route2.path;
2902
2895
  return;
2903
2896
  }
2904
- isUpdating = true;
2905
- currentPath = route2.path;
2906
- currentTopRoute = routeDef;
2907
2897
  if ("redirect" in routeDef) {
2908
2898
  const redirectPath = typeof routeDef.redirect === "function" ? routeDef.redirect(route2) : routeDef.redirect;
2909
2899
  queueMicrotask(() => {
@@ -2920,27 +2910,25 @@ function Route() {
2920
2910
  showLoading();
2921
2911
  }
2922
2912
  const component = await globalRouter.loadComponent(routeDef, route2.path);
2913
+ if (seq !== navSeq) return;
2923
2914
  const node = component();
2924
- if (node && anchor.parentNode && route2.path === currentPath) {
2915
+ if (node && anchor.parentNode) {
2916
+ currentTopRoute = routeDef;
2925
2917
  cleanupNodes();
2926
2918
  anchor.parentNode.insertBefore(node, anchor.nextSibling);
2927
2919
  currentNode = node;
2928
2920
  }
2929
2921
  } catch (error) {
2922
+ if (seq !== navSeq) return;
2930
2923
  hideLoading();
2931
2924
  console.error("[Route] Component error:", error);
2932
2925
  showError(error instanceof Error ? error : new Error(String(error)), routeDef);
2933
2926
  }
2934
2927
  }
2935
2928
  } catch (error) {
2929
+ if (seq !== navSeq) return;
2936
2930
  console.error("[Route] Update failed:", error);
2937
2931
  showError(error instanceof Error ? error : new Error(String(error)));
2938
- } finally {
2939
- isUpdating = false;
2940
- if (pendingUpdate) {
2941
- pendingUpdate = false;
2942
- update();
2943
- }
2944
2932
  }
2945
2933
  };
2946
2934
  let routeInitialized = false;
@@ -3287,24 +3275,43 @@ function __removeRouterPagehideHandler() {
3287
3275
  function Outlet() {
3288
3276
  const anchor = document.createComment("route-outlet-nested");
3289
3277
  let currentNode = null;
3278
+ let currentChild = null;
3279
+ let navSeq = 0;
3280
+ const clearCurrent = () => {
3281
+ if (currentNode) {
3282
+ dispose(currentNode);
3283
+ if (currentNode.parentNode) currentNode.parentNode.removeChild(currentNode);
3284
+ currentNode = null;
3285
+ }
3286
+ currentChild = null;
3287
+ };
3290
3288
  const update = async () => {
3291
3289
  if (!globalRouter) return;
3290
+ const seq = ++navSeq;
3292
3291
  const route2 = globalRouter.currentRoute;
3293
- if (route2.matched.length < 2) return;
3292
+ if (route2.matched.length < 2) {
3293
+ clearCurrent();
3294
+ return;
3295
+ }
3294
3296
  const childRoute = route2.matched[route2.matched.length - 1];
3295
- if (!childRoute || !("component" in childRoute)) return;
3297
+ if (!childRoute || !("component" in childRoute)) {
3298
+ clearCurrent();
3299
+ return;
3300
+ }
3301
+ if (childRoute === currentChild && currentNode) return;
3296
3302
  try {
3297
3303
  const cacheKey = `${route2.path}\0${childRoute.path}`;
3298
3304
  const component = await globalRouter.loadComponent(childRoute, cacheKey);
3305
+ if (seq !== navSeq) return;
3299
3306
  const node = component();
3300
3307
  if (node && anchor.parentNode) {
3301
- if (currentNode?.parentNode) {
3302
- currentNode.parentNode.removeChild(currentNode);
3303
- }
3308
+ clearCurrent();
3304
3309
  anchor.parentNode.insertBefore(node, anchor.nextSibling);
3305
3310
  currentNode = node;
3311
+ currentChild = childRoute;
3306
3312
  }
3307
3313
  } catch (error) {
3314
+ if (seq !== navSeq) return;
3308
3315
  console.error("[Outlet] Failed to render child route:", error);
3309
3316
  }
3310
3317
  };
package/dist/plugins.js CHANGED
@@ -964,8 +964,7 @@ function Route() {
964
964
  let currentNode = null;
965
965
  let loadingNode = null;
966
966
  let errorNode = null;
967
- let isUpdating = false;
968
- let currentPath = "";
967
+ let navSeq = 0;
969
968
  let currentTopRoute = null;
970
969
  const cleanupNodes = () => {
971
970
  [currentNode, loadingNode, errorNode].forEach((node) => {
@@ -1043,30 +1042,21 @@ function Route() {
1043
1042
  errorNode.appendChild(retryButton);
1044
1043
  anchor.parentNode.insertBefore(errorNode, anchor.nextSibling);
1045
1044
  };
1046
- let pendingUpdate = false;
1047
1045
  const update = async () => {
1048
1046
  if (!globalRouter) return;
1049
- if (isUpdating) {
1050
- pendingUpdate = true;
1051
- return;
1052
- }
1047
+ const seq = ++navSeq;
1053
1048
  const route2 = globalRouter.currentRoute;
1054
1049
  try {
1055
1050
  const match = globalRouter["matcher"].match(route2.path);
1056
1051
  if (!match) {
1057
- currentPath = route2.path;
1058
1052
  currentTopRoute = null;
1059
1053
  cleanupNodes();
1060
1054
  return;
1061
1055
  }
1062
1056
  const routeDef = match.matched[0] || match.route;
1063
1057
  if (routeDef === currentTopRoute && currentNode) {
1064
- currentPath = route2.path;
1065
1058
  return;
1066
1059
  }
1067
- isUpdating = true;
1068
- currentPath = route2.path;
1069
- currentTopRoute = routeDef;
1070
1060
  if ("redirect" in routeDef) {
1071
1061
  const redirectPath = typeof routeDef.redirect === "function" ? routeDef.redirect(route2) : routeDef.redirect;
1072
1062
  queueMicrotask(() => {
@@ -1083,27 +1073,25 @@ function Route() {
1083
1073
  showLoading();
1084
1074
  }
1085
1075
  const component = await globalRouter.loadComponent(routeDef, route2.path);
1076
+ if (seq !== navSeq) return;
1086
1077
  const node = component();
1087
- if (node && anchor.parentNode && route2.path === currentPath) {
1078
+ if (node && anchor.parentNode) {
1079
+ currentTopRoute = routeDef;
1088
1080
  cleanupNodes();
1089
1081
  anchor.parentNode.insertBefore(node, anchor.nextSibling);
1090
1082
  currentNode = node;
1091
1083
  }
1092
1084
  } catch (error) {
1085
+ if (seq !== navSeq) return;
1093
1086
  hideLoading();
1094
1087
  console.error("[Route] Component error:", error);
1095
1088
  showError(error instanceof Error ? error : new Error(String(error)), routeDef);
1096
1089
  }
1097
1090
  }
1098
1091
  } catch (error) {
1092
+ if (seq !== navSeq) return;
1099
1093
  console.error("[Route] Update failed:", error);
1100
1094
  showError(error instanceof Error ? error : new Error(String(error)));
1101
- } finally {
1102
- isUpdating = false;
1103
- if (pendingUpdate) {
1104
- pendingUpdate = false;
1105
- update();
1106
- }
1107
1095
  }
1108
1096
  };
1109
1097
  let routeInitialized = false;
@@ -1450,24 +1438,43 @@ function __removeRouterPagehideHandler() {
1450
1438
  function Outlet() {
1451
1439
  const anchor = document.createComment("route-outlet-nested");
1452
1440
  let currentNode = null;
1441
+ let currentChild = null;
1442
+ let navSeq = 0;
1443
+ const clearCurrent = () => {
1444
+ if (currentNode) {
1445
+ dispose(currentNode);
1446
+ if (currentNode.parentNode) currentNode.parentNode.removeChild(currentNode);
1447
+ currentNode = null;
1448
+ }
1449
+ currentChild = null;
1450
+ };
1453
1451
  const update = async () => {
1454
1452
  if (!globalRouter) return;
1453
+ const seq = ++navSeq;
1455
1454
  const route2 = globalRouter.currentRoute;
1456
- if (route2.matched.length < 2) return;
1455
+ if (route2.matched.length < 2) {
1456
+ clearCurrent();
1457
+ return;
1458
+ }
1457
1459
  const childRoute = route2.matched[route2.matched.length - 1];
1458
- if (!childRoute || !("component" in childRoute)) return;
1460
+ if (!childRoute || !("component" in childRoute)) {
1461
+ clearCurrent();
1462
+ return;
1463
+ }
1464
+ if (childRoute === currentChild && currentNode) return;
1459
1465
  try {
1460
1466
  const cacheKey = `${route2.path}\0${childRoute.path}`;
1461
1467
  const component = await globalRouter.loadComponent(childRoute, cacheKey);
1468
+ if (seq !== navSeq) return;
1462
1469
  const node = component();
1463
1470
  if (node && anchor.parentNode) {
1464
- if (currentNode?.parentNode) {
1465
- currentNode.parentNode.removeChild(currentNode);
1466
- }
1471
+ clearCurrent();
1467
1472
  anchor.parentNode.insertBefore(node, anchor.nextSibling);
1468
1473
  currentNode = node;
1474
+ currentChild = childRoute;
1469
1475
  }
1470
1476
  } catch (error) {
1477
+ if (seq !== navSeq) return;
1471
1478
  console.error("[Outlet] Failed to render child route:", error);
1472
1479
  }
1473
1480
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sibujs",
3
- "version": "3.2.0",
3
+ "version": "3.2.2",
4
4
  "description": "A lightweight, function-based frontend framework that combines the best of React, Svelte, and Vue — with zero VDOM and maximum simplicity. Designed for developers who want fine-grained reactivity and full control without compilation or magic.",
5
5
  "keywords": [
6
6
  "frontend",