@hai3/framework 0.2.0-alpha.2 → 0.2.0-alpha.4
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/index.cjs +157 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +157 -30
- package/dist/index.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +56 -1
- package/dist/types.d.ts +56 -1
- package/package.json +4 -2
package/dist/index.cjs
CHANGED
|
@@ -935,6 +935,44 @@ function resolveBase(pluginConfig, appConfig) {
|
|
|
935
935
|
return normalizeBase(rawBase);
|
|
936
936
|
}
|
|
937
937
|
|
|
938
|
+
// src/utils/routeMatcher.ts
|
|
939
|
+
var import_path_to_regexp = require("path-to-regexp");
|
|
940
|
+
function compileRoute(pattern, screensetId, screenId) {
|
|
941
|
+
return {
|
|
942
|
+
pattern,
|
|
943
|
+
screensetId,
|
|
944
|
+
screenId,
|
|
945
|
+
matcher: (0, import_path_to_regexp.match)(pattern, { decode: decodeURIComponent }),
|
|
946
|
+
toPath: (0, import_path_to_regexp.compile)(pattern, { encode: encodeURIComponent })
|
|
947
|
+
};
|
|
948
|
+
}
|
|
949
|
+
function matchPath(path, routes) {
|
|
950
|
+
for (const route of routes) {
|
|
951
|
+
const result = route.matcher(path);
|
|
952
|
+
if (result) {
|
|
953
|
+
return {
|
|
954
|
+
screensetId: route.screensetId,
|
|
955
|
+
screenId: route.screenId,
|
|
956
|
+
params: result.params
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
return void 0;
|
|
961
|
+
}
|
|
962
|
+
function generatePath(route, params) {
|
|
963
|
+
return route.toPath(params);
|
|
964
|
+
}
|
|
965
|
+
function extractRequiredParams(pattern) {
|
|
966
|
+
const params = [];
|
|
967
|
+
const matches = pattern.match(/:([^/]+)/g);
|
|
968
|
+
if (matches) {
|
|
969
|
+
for (const match2 of matches) {
|
|
970
|
+
params.push(match2.slice(1));
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
return params;
|
|
974
|
+
}
|
|
975
|
+
|
|
938
976
|
// src/plugins/navigation.ts
|
|
939
977
|
var screenActions3 = screenActions;
|
|
940
978
|
var menuActions3 = menuActions;
|
|
@@ -957,7 +995,39 @@ function navigation(config) {
|
|
|
957
995
|
onInit(app) {
|
|
958
996
|
const dispatch = app.store.dispatch;
|
|
959
997
|
const base = resolveBase(config, app.config);
|
|
998
|
+
const routerMode = app.config.routerMode ?? "browser";
|
|
960
999
|
let currentScreensetId = null;
|
|
1000
|
+
const getCurrentPath = () => {
|
|
1001
|
+
if (typeof window === "undefined") return "/";
|
|
1002
|
+
switch (routerMode) {
|
|
1003
|
+
case "hash":
|
|
1004
|
+
return window.location.hash.slice(1) || "/";
|
|
1005
|
+
case "memory":
|
|
1006
|
+
return "/";
|
|
1007
|
+
case "browser":
|
|
1008
|
+
default:
|
|
1009
|
+
return window.location.pathname;
|
|
1010
|
+
}
|
|
1011
|
+
};
|
|
1012
|
+
const updateURL = (path) => {
|
|
1013
|
+
if (typeof window === "undefined" || routerMode === "memory") {
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
const url = prependBase(path, base);
|
|
1017
|
+
switch (routerMode) {
|
|
1018
|
+
case "hash":
|
|
1019
|
+
if (window.location.hash !== `#${url}`) {
|
|
1020
|
+
window.location.hash = url;
|
|
1021
|
+
}
|
|
1022
|
+
break;
|
|
1023
|
+
case "browser":
|
|
1024
|
+
default:
|
|
1025
|
+
if (window.location.pathname !== url) {
|
|
1026
|
+
window.history.pushState(null, "", url);
|
|
1027
|
+
}
|
|
1028
|
+
break;
|
|
1029
|
+
}
|
|
1030
|
+
};
|
|
961
1031
|
const loadScreensetTranslations = async (screensetId, language) => {
|
|
962
1032
|
await import_i18n.i18nRegistry.loadScreensetTranslations(
|
|
963
1033
|
screensetId,
|
|
@@ -986,21 +1056,17 @@ function navigation(config) {
|
|
|
986
1056
|
});
|
|
987
1057
|
updateScreensetMenu(screenset);
|
|
988
1058
|
};
|
|
989
|
-
const
|
|
990
|
-
const
|
|
991
|
-
|
|
992
|
-
return null;
|
|
993
|
-
}
|
|
994
|
-
const parts = internalPath.split("/").filter(Boolean);
|
|
995
|
-
return parts[0] || null;
|
|
1059
|
+
const extractInternalPath = () => {
|
|
1060
|
+
const currentPath = getCurrentPath();
|
|
1061
|
+
return stripBase(currentPath, base) || "/";
|
|
996
1062
|
};
|
|
997
|
-
const
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1063
|
+
const activateFromRouteMatch = (match2) => {
|
|
1064
|
+
activateScreenset(match2.screensetId);
|
|
1065
|
+
dispatch(screenActions3.navigateTo(match2.screenId));
|
|
1066
|
+
};
|
|
1067
|
+
const matchCurrentPath = () => {
|
|
1068
|
+
const path = extractInternalPath();
|
|
1069
|
+
return app.routeRegistry?.matchRoute(path);
|
|
1004
1070
|
};
|
|
1005
1071
|
import_state13.eventBus.on("navigation/screen/navigated", (payload) => {
|
|
1006
1072
|
if (!app.routeRegistry?.hasScreen(payload.screensetId, payload.screenId)) {
|
|
@@ -1009,14 +1075,22 @@ function navigation(config) {
|
|
|
1009
1075
|
);
|
|
1010
1076
|
return;
|
|
1011
1077
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
const
|
|
1016
|
-
|
|
1017
|
-
|
|
1078
|
+
const pattern = app.routeRegistry?.getRoutePattern(payload.screenId);
|
|
1079
|
+
if (pattern) {
|
|
1080
|
+
const requiredParams = extractRequiredParams(pattern);
|
|
1081
|
+
const providedParams = payload.params || {};
|
|
1082
|
+
const missingParams = requiredParams.filter((param) => !(param in providedParams));
|
|
1083
|
+
if (missingParams.length > 0) {
|
|
1084
|
+
console.warn(
|
|
1085
|
+
`Screen "${payload.screenId}" requires route params [${requiredParams.join(", ")}] but missing: [${missingParams.join(", ")}]`
|
|
1086
|
+
);
|
|
1087
|
+
return;
|
|
1018
1088
|
}
|
|
1019
1089
|
}
|
|
1090
|
+
activateScreenset(payload.screensetId);
|
|
1091
|
+
dispatch(screenActions3.navigateTo(payload.screenId));
|
|
1092
|
+
const path = app.routeRegistry?.generatePath(payload.screenId, payload.params) ?? `/${payload.screenId}`;
|
|
1093
|
+
updateURL(path);
|
|
1020
1094
|
});
|
|
1021
1095
|
import_state13.eventBus.on("navigation/screenset/navigated", (payload) => {
|
|
1022
1096
|
const screenset = app.screensetRegistry.get(payload.screensetId);
|
|
@@ -1050,23 +1124,36 @@ function navigation(config) {
|
|
|
1050
1124
|
);
|
|
1051
1125
|
});
|
|
1052
1126
|
});
|
|
1053
|
-
if (typeof window !== "undefined") {
|
|
1054
|
-
|
|
1055
|
-
const
|
|
1056
|
-
if (
|
|
1057
|
-
|
|
1127
|
+
if (typeof window !== "undefined" && routerMode !== "memory") {
|
|
1128
|
+
const handleURLChange = () => {
|
|
1129
|
+
const match3 = matchCurrentPath();
|
|
1130
|
+
if (match3) {
|
|
1131
|
+
activateFromRouteMatch(match3);
|
|
1058
1132
|
}
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1133
|
+
};
|
|
1134
|
+
if (routerMode === "hash") {
|
|
1135
|
+
window.addEventListener("hashchange", handleURLChange);
|
|
1136
|
+
} else {
|
|
1137
|
+
window.addEventListener("popstate", handleURLChange);
|
|
1138
|
+
}
|
|
1139
|
+
const match2 = matchCurrentPath();
|
|
1061
1140
|
const autoNavigate = app.config.autoNavigate !== false;
|
|
1062
|
-
if (
|
|
1063
|
-
|
|
1141
|
+
if (match2) {
|
|
1142
|
+
activateFromRouteMatch(match2);
|
|
1064
1143
|
} else if (autoNavigate) {
|
|
1065
1144
|
const screensets2 = app.screensetRegistry.getAll();
|
|
1066
1145
|
if (screensets2.length > 0) {
|
|
1067
1146
|
navigateToScreenset({ screensetId: screensets2[0].id });
|
|
1068
1147
|
}
|
|
1069
1148
|
}
|
|
1149
|
+
} else if (routerMode === "memory") {
|
|
1150
|
+
const autoNavigate = app.config.autoNavigate !== false;
|
|
1151
|
+
if (autoNavigate) {
|
|
1152
|
+
const screensets2 = app.screensetRegistry.getAll();
|
|
1153
|
+
if (screensets2.length > 0) {
|
|
1154
|
+
navigateToScreenset({ screensetId: screensets2[0].id });
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1070
1157
|
}
|
|
1071
1158
|
}
|
|
1072
1159
|
};
|
|
@@ -1085,14 +1172,25 @@ function createRouteRegistry(screensetRegistry3) {
|
|
|
1085
1172
|
screenset.menu.forEach((menuScreenItem) => {
|
|
1086
1173
|
const screenId = menuScreenItem.menuItem.screenId ?? menuScreenItem.menuItem.id;
|
|
1087
1174
|
if (screenId && menuScreenItem.screen) {
|
|
1175
|
+
const pattern = menuScreenItem.menuItem.path ?? `/${screenId}`;
|
|
1176
|
+
const compiledRoute = compileRoute(pattern, screenset.id, screenId);
|
|
1088
1177
|
routes.push({
|
|
1089
1178
|
screensetId: screenset.id,
|
|
1090
1179
|
screenId,
|
|
1091
|
-
loader: menuScreenItem.screen
|
|
1180
|
+
loader: menuScreenItem.screen,
|
|
1181
|
+
pattern,
|
|
1182
|
+
compiledRoute
|
|
1092
1183
|
});
|
|
1093
1184
|
}
|
|
1094
1185
|
});
|
|
1095
1186
|
});
|
|
1187
|
+
routes.sort((a, b) => {
|
|
1188
|
+
const aHasParams = a.pattern.includes(":");
|
|
1189
|
+
const bHasParams = b.pattern.includes(":");
|
|
1190
|
+
if (!aHasParams && bHasParams) return -1;
|
|
1191
|
+
if (aHasParams && !bHasParams) return 1;
|
|
1192
|
+
return 0;
|
|
1193
|
+
});
|
|
1096
1194
|
return routes;
|
|
1097
1195
|
}
|
|
1098
1196
|
return {
|
|
@@ -1148,6 +1246,35 @@ function createRouteRegistry(screensetRegistry3) {
|
|
|
1148
1246
|
screensetId,
|
|
1149
1247
|
screenId
|
|
1150
1248
|
}));
|
|
1249
|
+
},
|
|
1250
|
+
/**
|
|
1251
|
+
* Match a URL path against registered routes, extracting params.
|
|
1252
|
+
* Returns the first matching route with extracted params, or undefined if no match.
|
|
1253
|
+
*/
|
|
1254
|
+
matchRoute(path) {
|
|
1255
|
+
const allRoutes = buildRoutes();
|
|
1256
|
+
const compiledRoutes = allRoutes.map((r) => r.compiledRoute);
|
|
1257
|
+
return matchPath(path, compiledRoutes);
|
|
1258
|
+
},
|
|
1259
|
+
/**
|
|
1260
|
+
* Generate a URL path for a screen with given params.
|
|
1261
|
+
*/
|
|
1262
|
+
generatePath(screenId, params = {}) {
|
|
1263
|
+
const allRoutes = buildRoutes();
|
|
1264
|
+
const route = allRoutes.find((r) => r.screenId === screenId);
|
|
1265
|
+
if (!route) {
|
|
1266
|
+
console.warn(`Route not found for screen: ${screenId}`);
|
|
1267
|
+
return `/${screenId}`;
|
|
1268
|
+
}
|
|
1269
|
+
return generatePath(route.compiledRoute, params);
|
|
1270
|
+
},
|
|
1271
|
+
/**
|
|
1272
|
+
* Get the route pattern for a screen.
|
|
1273
|
+
*/
|
|
1274
|
+
getRoutePattern(screenId) {
|
|
1275
|
+
const allRoutes = buildRoutes();
|
|
1276
|
+
const route = allRoutes.find((r) => r.screenId === screenId);
|
|
1277
|
+
return route?.pattern;
|
|
1151
1278
|
}
|
|
1152
1279
|
};
|
|
1153
1280
|
}
|