@ashley-shrok/viewmodel-shell 0.7.0 → 0.7.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.
Files changed (2) hide show
  1. package/dist/browser.js +18 -1
  2. package/package.json +1 -1
package/dist/browser.js CHANGED
@@ -25,6 +25,15 @@ export class BrowserAdapter {
25
25
  const focusId = active?.id || null;
26
26
  const selStart = active?.selectionStart ?? null;
27
27
  const selEnd = active?.selectionEnd ?? null;
28
+ // 0.7.1 (#7) — snapshot the WINDOW scroll position alongside element-level
29
+ // scroll. Without this, an action-driven re-render rebuilds the entire
30
+ // subtree and the viewport jumps (to top, or wherever HTMLElement.focus()
31
+ // scrolled the restored-focus element into view). Same preservation
32
+ // contract as element scroll: preserve unless the server explicitly
33
+ // navigates (a redirect IS a navigation, so it correctly does NOT
34
+ // round-trip through render — it goes through navigate()).
35
+ const winScrollX = window.scrollX;
36
+ const winScrollY = window.scrollY;
28
37
  const scrollMap = new Map();
29
38
  this.container.querySelectorAll("[id]").forEach(el => {
30
39
  if (el.scrollTop !== 0 || el.scrollLeft !== 0)
@@ -44,7 +53,11 @@ export class BrowserAdapter {
44
53
  if (focusId) {
45
54
  const el = this.container.querySelector(`#${CSS.escape(focusId)}`);
46
55
  if (el) {
47
- el.focus();
56
+ // 0.7.1 (#7) — preventScroll stops focus() from yanking the viewport
57
+ // to the focused element. The window-scroll restore below still
58
+ // overrides any scroll that snuck in, but preventing the scroll in
59
+ // the first place is the cleaner contract.
60
+ el.focus({ preventScroll: true });
48
61
  if (selStart !== null && selEnd !== null) {
49
62
  try {
50
63
  el.setSelectionRange(selStart, selEnd);
@@ -60,6 +73,10 @@ export class BrowserAdapter {
60
73
  el.scrollLeft = left;
61
74
  }
62
75
  });
76
+ // 0.7.1 (#7) — restore the window scroll LAST so any defensive
77
+ // browser behavior earlier in this method (e.g. a future element
78
+ // bringing itself into view) gets overridden by the snapshot.
79
+ window.scrollTo(winScrollX, winScrollY);
63
80
  }
64
81
  navigate(url) {
65
82
  window.location.href = url;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ashley-shrok/viewmodel-shell",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "A server-driven UI framework where the wire format is structured enough that agents can build full-stack apps without ever opening a browser and all UI tests are pure unit tests with no browser runtime. Server returns a JSON tree of typed nodes; a thin TypeScript adapter renders it to DOM. Backend-agnostic — a .NET reference backend ships with the repo, but any language can produce the JSON contract.",
5
5
  "type": "module",
6
6
  "license": "MIT",