@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.
- package/dist/browser.js +18 -1
- 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
|
-
|
|
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.
|
|
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",
|