@jskit-ai/shell-web 0.1.250 → 0.1.252

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.
Files changed (47) hide show
  1. package/fixtures/adaptive-shell/src/main.js +6 -3
  2. package/package.json +2 -2
  3. package/patterns/application-shell/PATTERN.md +18 -4
  4. package/patterns/application-shell/example/src/pages/home/index.vue +15 -5
  5. package/patterns/application-shell/example/tests/e2e/adaptive-shell.spec.ts +1 -1
  6. package/src/architecture/inspectVueArchitecture.js +1092 -336
  7. package/src/client/asyncModuleRecovery/runtime.js +116 -0
  8. package/src/client/components/ShellLayout.vue +18 -288
  9. package/src/client/components/ShellMenuLinkItem.vue +3 -21
  10. package/src/client/components/ShellOutlet.vue +2 -24
  11. package/src/client/components/ShellRouteTransition.vue +16 -114
  12. package/src/client/components/ShellSurfaceAwareMenuLinkItem.vue +5 -100
  13. package/src/client/components/ShellTabLinkItem.vue +5 -101
  14. package/src/client/composables/useShellNavigationLink.js +85 -0
  15. package/src/client/composables/useShellPullToRefresh.js +260 -0
  16. package/src/client/error/index.js +1 -1
  17. package/src/client/error/inject.js +4 -1
  18. package/src/client/error/policy.js +4 -13
  19. package/src/client/error/presenters.js +4 -9
  20. package/src/client/error/store.js +1 -1
  21. package/src/client/navigation/linkResolver.js +5 -27
  22. package/src/client/navigation/usePaths.js +1 -21
  23. package/src/client/placement/index.js +2 -0
  24. package/src/client/placement/inject.js +4 -1
  25. package/src/client/placement/runtime.js +2 -4
  26. package/src/client/placement/surfaceContext.js +11 -8
  27. package/src/client/placement/validators.js +18 -65
  28. package/src/client/providers/ShellWebClientProvider.js +100 -356
  29. package/src/client/requestRecovery/runtime.js +29 -77
  30. package/src/client/runtime/bootstrapRuntime.js +5 -4
  31. package/src/client/runtime/refreshRuntime.js +122 -0
  32. package/src/client/support/gestureTargets.js +26 -0
  33. package/src/client/support/menuLinkTarget.js +35 -19
  34. package/src/client/support/routeParams.js +26 -0
  35. package/src/client/support/routeSwipeGesture.js +88 -0
  36. package/src/client/support/routeTransitionKey.js +1 -3
  37. package/src/client/support/shellLayoutClass.js +32 -0
  38. package/test/bootstrapRuntime.test.js +98 -0
  39. package/test/errorActions.test.js +2 -1
  40. package/test/errorRuntime.test.js +30 -0
  41. package/test/linkResolver.test.js +23 -1
  42. package/test/menuLinkTarget.test.js +77 -0
  43. package/test/routeSwipeGesture.test.js +49 -0
  44. package/test/settingsPlacementContract.test.js +16 -6
  45. package/test/shellGestureSupport.test.js +46 -0
  46. package/test/surfaceContext.test.js +53 -0
  47. package/test/useShellPullToRefresh.test.js +123 -0
@@ -13,6 +13,9 @@ import ShellSurfaceAwareMenuLinkItem from "@jskit-ai/shell-web/client/components
13
13
  import ShellTabLinkItem from "@jskit-ai/shell-web/client/components/ShellTabLinkItem";
14
14
  import { useShellLayoutStore } from "../../../src/client/stores/useShellLayoutStore.js";
15
15
  import { createWebPlacementRuntime } from "../../../src/client/placement/runtime.js";
16
+ import { SHELL_WEB_PLACEMENT_RUNTIME_KEY } from "../../../src/client/placement/inject.js";
17
+ import { SHELL_WEB_ERROR_RUNTIME_KEY } from "../../../src/client/error/inject.js";
18
+ import { SHELL_WEB_REFRESH_RUNTIME_KEY } from "../../../src/client/runtime/refreshRuntime.js";
16
19
  import { createErrorRuntime } from "../../../src/client/error/runtime.js";
17
20
  import { createDefaultMaterialErrorPresenters } from "../../../src/client/error/presenters.js";
18
21
  import { createErrorPresentationStore } from "../../../src/client/error/store.js";
@@ -183,21 +186,21 @@ const app = createApp(App);
183
186
  app.use(pinia);
184
187
  app.use(router);
185
188
  app.use(vuetify);
186
- app.provide("jskit.shell-web.runtime.web-placement.client", placementRuntime);
189
+ app.provide(SHELL_WEB_PLACEMENT_RUNTIME_KEY, placementRuntime);
187
190
  const errorStore = createErrorPresentationStore();
188
191
  const errorRuntime = createErrorRuntime({
189
192
  presenters: createDefaultMaterialErrorPresenters({ store: errorStore }),
190
193
  defaultPresenterId: "material.snackbar"
191
194
  });
192
195
  useShellErrorPresentationStore(pinia).attachRuntimeStore(errorStore);
193
- app.provide("jskit.shell-web.runtime.web-error.client", errorRuntime);
196
+ app.provide(SHELL_WEB_ERROR_RUNTIME_KEY, errorRuntime);
194
197
  window.__shellFixtureReportBanner = (message) => errorRuntime.report({
195
198
  source: "shell-web.fixture",
196
199
  message,
197
200
  severity: "error",
198
201
  channel: "banner"
199
202
  });
200
- app.provide("jskit.shell-web.runtime.web-refresh.client", {
203
+ app.provide(SHELL_WEB_REFRESH_RUNTIME_KEY, {
201
204
  async refresh() {
202
205
  await fetch("/api/bootstrap?reason=pull-to-refresh");
203
206
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/shell-web",
3
- "version": "0.1.250",
3
+ "version": "0.1.252",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "test": "node --test --test-concurrency=1"
@@ -34,7 +34,7 @@
34
34
  "@vue/compiler-sfc": "3.5.44"
35
35
  },
36
36
  "peerDependencies": {
37
- "@jskit-ai/kernel": "0.1.245",
37
+ "@jskit-ai/kernel": "0.1.246",
38
38
  "pinia": "^4.0.3",
39
39
  "vue": "^3.5.44",
40
40
  "vue-router": "^5.3.1",
@@ -43,10 +43,24 @@ placement registry, topology, and adaptive smoke helper exported by
43
43
  above the content so they never cover it. A full-viewport fixed screen on
44
44
  such a surface starts at `var(--shell-error-banners-inline-height, 0px)`, as
45
45
  `@jskit-ai/auth-web`'s login and reset views do.
46
- - Restyle shell chrome through its `--shell-chrome-*`, `--shell-app-bar-*`,
47
- `--shell-navigation-*` and `--shell-bottom-navigation-*` custom properties,
48
- not by overriding Vuetify internals; a Material 3 restyle removes the dividers
49
- and separates surfaces tonally.
46
+ - Restyle shell chrome through its custom properties, not by overriding
47
+ Vuetify internals: `--shell-chrome-border-width` and
48
+ `--shell-chrome-border-color` for the shared dividers,
49
+ `--shell-app-bar-border-width`, `--shell-navigation-border-width` and
50
+ `--shell-bottom-navigation-border-width` per edge, and
51
+ `--shell-app-bar-background`, `--shell-navigation-background` and
52
+ `--shell-bottom-navigation-background` for the surfaces. The defaults keep
53
+ one thin divider on each separating edge, because Vuetify's default themes
54
+ define no Material 3 surface-container roles. A Material 3 restyle sets the
55
+ border widths to `0` and gives navigation a tonal surface, for example
56
+ `rgb(var(--v-theme-surface-container-low))` when the theme defines it.
57
+ - `createShellRouter()` from `@jskit-ai/kernel/client` installs
58
+ `shellScrollBehavior`: a new screen opens at the top (or its hash target),
59
+ Back/Forward restore the saved position, and query, hash, tab or sub-view
60
+ changes within the same page keep it. A tab or sub-view is the same page when
61
+ both locations share a parent page record below the surface root. Pass
62
+ `scrollBehavior` to replace it, or `scrollBehavior: false` to disable it; do
63
+ not wrap the router or reset scroll in page components.
50
64
  - The adaptive browser check closes navigation through its public close control.
51
65
 
52
66
  ## Example files
@@ -15,16 +15,16 @@ const healthQuery = useQuery({
15
15
  });
16
16
 
17
17
  const health = computed(() => {
18
- if (healthQuery.isPending.value || healthQuery.isFetching.value) {
19
- return "loading...";
20
- }
21
-
22
18
  if (healthQuery.error.value) {
23
19
  return "unreachable";
24
20
  }
25
21
 
26
22
  return healthQuery.data.value?.ok ? "ok" : "unhealthy";
27
23
  });
24
+
25
+ const healthPending = computed(
26
+ () => healthQuery.isPending.value || healthQuery.isFetching.value
27
+ );
28
28
  </script>
29
29
 
30
30
  <template>
@@ -36,7 +36,13 @@ const health = computed(() => {
36
36
  <v-sheet rounded="lg" border class="home-surface-screen__panel">
37
37
  <div class="home-surface-screen__status">
38
38
  <span class="text-caption text-medium-emphasis">Service health</span>
39
- <strong>{{ health }}</strong>
39
+ <v-skeleton-loader
40
+ v-if="healthPending"
41
+ aria-label="Loading service health"
42
+ class="home-surface-screen__health-skeleton"
43
+ type="text"
44
+ />
45
+ <strong v-else>{{ health }}</strong>
40
46
  </div>
41
47
  <v-divider vertical class="d-none d-sm-block" />
42
48
  <div class="home-surface-screen__status">
@@ -71,6 +77,10 @@ const health = computed(() => {
71
77
  min-width: 9rem;
72
78
  }
73
79
 
80
+ .home-surface-screen__health-skeleton {
81
+ max-width: 5rem;
82
+ }
83
+
74
84
  @media (max-width: 640px) {
75
85
  .home-surface-screen__actions :deep(.v-btn) {
76
86
  min-height: 48px;
@@ -1,7 +1,7 @@
1
1
  import { expect, test } from "@playwright/test";
2
2
  import { DEFAULT_VIEWPORTS, runAdaptiveShellSmokeCase } from "@jskit-ai/shell-web/test/adaptiveShellSmoke";
3
3
 
4
- test.describe("generated adaptive shell smoke", () => {
4
+ test.describe("adaptive shell smoke", () => {
5
5
  for (const viewport of DEFAULT_VIEWPORTS) {
6
6
  test(`${viewport.name} layout has reachable navigation and no horizontal overflow`, async ({ page }) => {
7
7
  await runAdaptiveShellSmokeCase({ page, expect, viewport });