@hai3/framework 0.2.0-alpha.0 → 0.2.0-alpha.1

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 CHANGED
@@ -972,22 +972,53 @@ function layout() {
972
972
  // src/plugins/navigation.ts
973
973
  var import_state13 = require("@hai3/state");
974
974
  var import_i18n = require("@hai3/i18n");
975
+
976
+ // src/utils/basePath.ts
977
+ function normalizeBase(base) {
978
+ if (!base) {
979
+ return "/";
980
+ }
981
+ let normalized = base.startsWith("/") ? base : `/${base}`;
982
+ if (normalized !== "/" && normalized.endsWith("/")) {
983
+ normalized = normalized.slice(0, -1);
984
+ }
985
+ return normalized;
986
+ }
987
+ function stripBase(pathname, base) {
988
+ if (base === "/") {
989
+ return pathname;
990
+ }
991
+ if (!pathname.startsWith(base)) {
992
+ return null;
993
+ }
994
+ const nextChar = pathname.charAt(base.length);
995
+ if (nextChar && nextChar !== "/") {
996
+ return null;
997
+ }
998
+ return pathname.slice(base.length) || "/";
999
+ }
1000
+ function prependBase(path, base) {
1001
+ if (base === "/") {
1002
+ return path;
1003
+ }
1004
+ const cleanPath = path.startsWith("/") ? path : `/${path}`;
1005
+ return `${base}${cleanPath}`;
1006
+ }
1007
+ function resolveBase(pluginConfig, appConfig) {
1008
+ const rawBase = pluginConfig?.base ?? appConfig?.base ?? "/";
1009
+ return normalizeBase(rawBase);
1010
+ }
1011
+
1012
+ // src/plugins/navigation.ts
975
1013
  var screenActions4 = screenActions;
976
1014
  var menuActions3 = menuActions;
977
- function buildMenuItems(screenset) {
978
- return screenset.menu.map((item) => ({
979
- id: item.menuItem.screenId ?? item.menuItem.id,
980
- label: item.menuItem.label,
981
- icon: item.menuItem.icon
982
- }));
983
- }
984
1015
  function navigateToScreen2(payload) {
985
1016
  import_state13.eventBus.emit("navigation/screen/navigated", payload);
986
1017
  }
987
1018
  function navigateToScreenset(payload) {
988
1019
  import_state13.eventBus.emit("navigation/screenset/navigated", payload);
989
1020
  }
990
- function navigation() {
1021
+ function navigation(config) {
991
1022
  return {
992
1023
  name: "navigation",
993
1024
  dependencies: ["screensets"],
@@ -999,33 +1030,66 @@ function navigation() {
999
1030
  },
1000
1031
  onInit(app) {
1001
1032
  const dispatch = app.store.dispatch;
1033
+ const base = resolveBase(config, app.config);
1002
1034
  let currentScreensetId = null;
1003
- async function loadScreensetTranslations(screensetId, language) {
1004
- await import_i18n.i18nRegistry.loadScreensetTranslations(screensetId, language);
1005
- }
1006
- function updateMenuForScreenset(screensetId) {
1007
- if (screensetId === currentScreensetId) return;
1035
+ const loadScreensetTranslations = async (screensetId, language) => {
1036
+ await import_i18n.i18nRegistry.loadScreensetTranslations(
1037
+ screensetId,
1038
+ language
1039
+ );
1040
+ };
1041
+ const updateScreensetMenu = (screenset) => {
1042
+ const menuItems = screenset.menu.map((item) => ({
1043
+ id: item.menuItem.screenId ?? item.menuItem.id,
1044
+ label: item.menuItem.label,
1045
+ icon: item.menuItem.icon
1046
+ }));
1047
+ dispatch(menuActions3.setMenuItems(menuItems));
1048
+ };
1049
+ const activateScreenset = (screensetId) => {
1050
+ if (screensetId === currentScreensetId) {
1051
+ return;
1052
+ }
1008
1053
  const screenset = app.screensetRegistry.get(screensetId);
1009
- if (!screenset) return;
1054
+ if (!screenset) {
1055
+ return;
1056
+ }
1010
1057
  currentScreensetId = screensetId;
1011
1058
  loadScreensetTranslations(screensetId).catch((err) => {
1012
1059
  console.warn(`[HAI3] Failed to load translations for screenset ${screensetId}:`, err);
1013
1060
  });
1014
- const menuItems = buildMenuItems(screenset);
1015
- dispatch(menuActions3.setMenuItems(menuItems));
1016
- }
1061
+ updateScreensetMenu(screenset);
1062
+ };
1063
+ const extractScreenId = () => {
1064
+ const internalPath = stripBase(window.location.pathname, base);
1065
+ if (!internalPath) {
1066
+ return null;
1067
+ }
1068
+ const parts = internalPath.split("/").filter(Boolean);
1069
+ return parts[0] || null;
1070
+ };
1071
+ const activateScreen = (screenId) => {
1072
+ const screensetId = app.routeRegistry?.getScreensetForScreen(screenId);
1073
+ if (!screensetId) {
1074
+ return;
1075
+ }
1076
+ activateScreenset(screensetId);
1077
+ dispatch(screenActions4.navigateTo(screenId));
1078
+ };
1017
1079
  import_state13.eventBus.on("navigation/screen/navigated", (payload) => {
1018
- if (app.routeRegistry && !app.routeRegistry.hasScreen(payload.screensetId, payload.screenId)) {
1080
+ if (!app.routeRegistry?.hasScreen(payload.screensetId, payload.screenId)) {
1019
1081
  console.warn(
1020
1082
  `Screen "${payload.screenId}" in screenset "${payload.screensetId}" not found.`
1021
1083
  );
1022
1084
  return;
1023
1085
  }
1024
- updateMenuForScreenset(payload.screensetId);
1086
+ activateScreenset(payload.screensetId);
1025
1087
  dispatch(screenActions4.navigateTo(payload.screenId));
1026
1088
  if (typeof window !== "undefined") {
1027
- const url = `/${payload.screenId}`;
1028
- window.history.pushState(null, "", url);
1089
+ const url = prependBase(`/${payload.screenId}`, base);
1090
+ if (window.location.pathname !== url) {
1091
+ window.history.pushState(null, "", url);
1092
+ }
1029
1093
  }
1030
1094
  });
1031
1095
  import_state13.eventBus.on("navigation/screenset/navigated", (payload) => {
@@ -1042,15 +1106,18 @@ function navigation() {
1042
1106
  let lastLoadedLanguage = null;
1043
1107
  import_i18n.i18nRegistry.subscribe(() => {
1044
1108
  const currentLanguage = import_i18n.i18nRegistry.getLanguage();
1045
- if (!currentLanguage || currentLanguage === lastLoadedLanguage) return;
1046
- if (!currentScreensetId) return;
1109
+ if (!currentLanguage || currentLanguage === lastLoadedLanguage) {
1110
+ return;
1111
+ }
1112
+ if (!currentScreensetId) {
1113
+ return;
1114
+ }
1047
1115
  const screenset = app.screensetRegistry.get(currentScreensetId);
1048
- if (!screenset) return;
1116
+ if (!screenset) {
1117
+ return;
1118
+ }
1049
1119
  lastLoadedLanguage = currentLanguage;
1050
- loadScreensetTranslations(currentScreensetId, currentLanguage).then(() => {
1051
- const menuItems = buildMenuItems(screenset);
1052
- dispatch(menuActions3.setMenuItems(menuItems));
1053
- }).catch((err) => {
1120
+ loadScreensetTranslations(currentScreensetId, currentLanguage).then(() => updateScreensetMenu(screenset)).catch((err) => {
1054
1121
  console.warn(
1055
1122
  `[HAI3] Failed to reload translations for screenset ${currentScreensetId}:`,
1056
1123
  err
@@ -1059,31 +1126,15 @@ function navigation() {
1059
1126
  });
1060
1127
  if (typeof window !== "undefined") {
1061
1128
  window.addEventListener("popstate", () => {
1062
- const path2 = window.location.pathname;
1063
- const parts2 = path2.split("/").filter(Boolean);
1064
- if (parts2.length >= 1) {
1065
- const screenId = parts2[0];
1066
- const screensetId = app.routeRegistry?.getScreensetForScreen(screenId);
1067
- if (screensetId) {
1068
- updateMenuForScreenset(screensetId);
1069
- dispatch(screenActions4.navigateTo(screenId));
1070
- }
1129
+ const screenId2 = extractScreenId();
1130
+ if (screenId2) {
1131
+ activateScreen(screenId2);
1071
1132
  }
1072
1133
  });
1073
- const path = window.location.pathname;
1074
- const parts = path.split("/").filter(Boolean);
1134
+ const screenId = extractScreenId();
1075
1135
  const autoNavigate = app.config.autoNavigate !== false;
1076
- if (parts.length >= 1) {
1077
- const screenId = parts[0];
1078
- const screensetId = app.routeRegistry?.getScreensetForScreen(screenId);
1079
- if (screensetId) {
1080
- navigateToScreen2({ screensetId, screenId });
1081
- } else if (autoNavigate) {
1082
- const screensets2 = app.screensetRegistry.getAll();
1083
- if (screensets2.length > 0) {
1084
- navigateToScreenset({ screensetId: screensets2[0].id });
1085
- }
1086
- }
1136
+ if (screenId) {
1137
+ activateScreen(screenId);
1087
1138
  } else if (autoNavigate) {
1088
1139
  const screensets2 = app.screensetRegistry.getAll();
1089
1140
  if (screensets2.length > 0) {