@moku-labs/web 2.1.0 → 2.1.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/browser.mjs CHANGED
@@ -4156,6 +4156,27 @@ function createSpaKernel(state, config, emit, deps) {
4156
4156
  if (signal?.aborted) return;
4157
4157
  await performNavigation(pathname, handlers, signal);
4158
4158
  };
4159
+ /**
4160
+ * Programmatic navigation entry (`app.spa.navigate` / `ctx.navigate`). A link click or the
4161
+ * Navigation API commits the address bar before the interceptor calls {@link navigate}; a
4162
+ * programmatic call does NOT, so it must commit the URL itself first — otherwise the content
4163
+ * swaps but the address bar (and the back button / refresh / deep link) stays on the old URL.
4164
+ * `history.pushState` updates the URL WITHOUT firing a `navigate` event, so it can't
4165
+ * double-trigger the interceptor. The current scroll is saved first so a later back restores it.
4166
+ *
4167
+ * @param path - The destination path (pathname + optional search).
4168
+ * @param scroll - The optional per-call scroll override.
4169
+ * @example
4170
+ * navigateProgrammatic("/board/abc/issue/1", "preserve");
4171
+ */
4172
+ const navigateProgrammatic = (path, scroll) => {
4173
+ if (typeof document === "undefined") return;
4174
+ if (path !== currentLocationUrl()) {
4175
+ saveScrollPosition(currentLocationUrl());
4176
+ history.pushState({}, "", path);
4177
+ }
4178
+ navigate(path, true, void 0, scroll).catch(() => {});
4179
+ };
4159
4180
  return {
4160
4181
  /**
4161
4182
  * Register config islands and seed currentUrl from the document.
@@ -4167,8 +4188,7 @@ function createSpaKernel(state, config, emit, deps) {
4167
4188
  for (const island of resolved.islands) registerIsland(state, island);
4168
4189
  state.currentUrl = currentLocationUrl();
4169
4190
  state.navigate = (path, options) => {
4170
- if (typeof document === "undefined") return;
4171
- navigate(path, true, void 0, options?.scroll).catch(() => {});
4191
+ navigateProgrammatic(path, options?.scroll);
4172
4192
  };
4173
4193
  },
4174
4194
  /**
@@ -4209,8 +4229,7 @@ function createSpaKernel(state, config, emit, deps) {
4209
4229
  * kernel.processNav("/about");
4210
4230
  */
4211
4231
  processNav(path, options) {
4212
- if (typeof document === "undefined") return;
4213
- navigate(path, true, void 0, options?.scroll).catch(() => {});
4232
+ navigateProgrammatic(path, options?.scroll);
4214
4233
  },
4215
4234
  /**
4216
4235
  * Scan the swap region and mount islands for matching elements.
package/dist/index.cjs CHANGED
@@ -10862,6 +10862,27 @@ function createSpaKernel(state, config, emit, deps) {
10862
10862
  if (signal?.aborted) return;
10863
10863
  await performNavigation(pathname, handlers, signal);
10864
10864
  };
10865
+ /**
10866
+ * Programmatic navigation entry (`app.spa.navigate` / `ctx.navigate`). A link click or the
10867
+ * Navigation API commits the address bar before the interceptor calls {@link navigate}; a
10868
+ * programmatic call does NOT, so it must commit the URL itself first — otherwise the content
10869
+ * swaps but the address bar (and the back button / refresh / deep link) stays on the old URL.
10870
+ * `history.pushState` updates the URL WITHOUT firing a `navigate` event, so it can't
10871
+ * double-trigger the interceptor. The current scroll is saved first so a later back restores it.
10872
+ *
10873
+ * @param path - The destination path (pathname + optional search).
10874
+ * @param scroll - The optional per-call scroll override.
10875
+ * @example
10876
+ * navigateProgrammatic("/board/abc/issue/1", "preserve");
10877
+ */
10878
+ const navigateProgrammatic = (path, scroll) => {
10879
+ if (typeof document === "undefined") return;
10880
+ if (path !== currentLocationUrl()) {
10881
+ saveScrollPosition(currentLocationUrl());
10882
+ history.pushState({}, "", path);
10883
+ }
10884
+ navigate(path, true, void 0, scroll).catch(() => {});
10885
+ };
10865
10886
  return {
10866
10887
  /**
10867
10888
  * Register config islands and seed currentUrl from the document.
@@ -10873,8 +10894,7 @@ function createSpaKernel(state, config, emit, deps) {
10873
10894
  for (const island of resolved.islands) registerIsland(state, island);
10874
10895
  state.currentUrl = currentLocationUrl();
10875
10896
  state.navigate = (path, options) => {
10876
- if (typeof document === "undefined") return;
10877
- navigate(path, true, void 0, options?.scroll).catch(() => {});
10897
+ navigateProgrammatic(path, options?.scroll);
10878
10898
  };
10879
10899
  },
10880
10900
  /**
@@ -10915,8 +10935,7 @@ function createSpaKernel(state, config, emit, deps) {
10915
10935
  * kernel.processNav("/about");
10916
10936
  */
10917
10937
  processNav(path, options) {
10918
- if (typeof document === "undefined") return;
10919
- navigate(path, true, void 0, options?.scroll).catch(() => {});
10938
+ navigateProgrammatic(path, options?.scroll);
10920
10939
  },
10921
10940
  /**
10922
10941
  * Scan the swap region and mount islands for matching elements.
package/dist/index.mjs CHANGED
@@ -10849,6 +10849,27 @@ function createSpaKernel(state, config, emit, deps) {
10849
10849
  if (signal?.aborted) return;
10850
10850
  await performNavigation(pathname, handlers, signal);
10851
10851
  };
10852
+ /**
10853
+ * Programmatic navigation entry (`app.spa.navigate` / `ctx.navigate`). A link click or the
10854
+ * Navigation API commits the address bar before the interceptor calls {@link navigate}; a
10855
+ * programmatic call does NOT, so it must commit the URL itself first — otherwise the content
10856
+ * swaps but the address bar (and the back button / refresh / deep link) stays on the old URL.
10857
+ * `history.pushState` updates the URL WITHOUT firing a `navigate` event, so it can't
10858
+ * double-trigger the interceptor. The current scroll is saved first so a later back restores it.
10859
+ *
10860
+ * @param path - The destination path (pathname + optional search).
10861
+ * @param scroll - The optional per-call scroll override.
10862
+ * @example
10863
+ * navigateProgrammatic("/board/abc/issue/1", "preserve");
10864
+ */
10865
+ const navigateProgrammatic = (path, scroll) => {
10866
+ if (typeof document === "undefined") return;
10867
+ if (path !== currentLocationUrl()) {
10868
+ saveScrollPosition(currentLocationUrl());
10869
+ history.pushState({}, "", path);
10870
+ }
10871
+ navigate(path, true, void 0, scroll).catch(() => {});
10872
+ };
10852
10873
  return {
10853
10874
  /**
10854
10875
  * Register config islands and seed currentUrl from the document.
@@ -10860,8 +10881,7 @@ function createSpaKernel(state, config, emit, deps) {
10860
10881
  for (const island of resolved.islands) registerIsland(state, island);
10861
10882
  state.currentUrl = currentLocationUrl();
10862
10883
  state.navigate = (path, options) => {
10863
- if (typeof document === "undefined") return;
10864
- navigate(path, true, void 0, options?.scroll).catch(() => {});
10884
+ navigateProgrammatic(path, options?.scroll);
10865
10885
  };
10866
10886
  },
10867
10887
  /**
@@ -10902,8 +10922,7 @@ function createSpaKernel(state, config, emit, deps) {
10902
10922
  * kernel.processNav("/about");
10903
10923
  */
10904
10924
  processNav(path, options) {
10905
- if (typeof document === "undefined") return;
10906
- navigate(path, true, void 0, options?.scroll).catch(() => {});
10925
+ navigateProgrammatic(path, options?.scroll);
10907
10926
  },
10908
10927
  /**
10909
10928
  * Scan the swap region and mount islands for matching elements.
package/package.json CHANGED
@@ -132,5 +132,5 @@
132
132
  "test:build-e2e": "bun test src/plugins/build/__tests__/e2e/",
133
133
  "test:coverage": "vitest run --project unit --project integration --coverage"
134
134
  },
135
- "version": "2.1.0"
135
+ "version": "2.1.1"
136
136
  }