@inventure71/paddockjs 4.3.0 → 4.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 7b608b9: Release Grid Walk drag capture when window focus, document visibility or pressed-button state is lost, so interrupted gestures cannot resume panning. Add focused Firefox input and cross-tab scrolling regression coverage.
8
+
3
9
  ## 4.3.0
4
10
 
5
11
  ### Minor Changes
@@ -176,6 +176,7 @@ For a fresh checkout or linked worktree, run `npm ci` in the package before the
176
176
  - `npm run consumer:bundle-boundaries` packs the package, installs the tarball into a fresh temporary Vite app, and verifies the root browser import remains the CSS/asset-owning simulator bundle while `/placeholder`, `/data`, and `/environment` stay CSS-free or lightweight according to their documented roles.
177
177
  - `npm run site:install` installs the single website; `npm run site:dev` starts its Demo, Guide, Labs and Reference sections on one URL. `npm run site:ci` installs and builds it once, including public-feature inventory validation. Existing `demo:*` and `showcase:*` install/dev/build/ci commands are compatibility aliases to these same commands.
178
178
  - `npm run browser:smoke` builds `site`, starts its local preview server, and checks desktop/mobile canvas rendering, overflow constraints, API buttons, and visual policy-runner stepping in Chromium. Use `npm run browser:smoke:quick` for the smaller local browser pass and `npm run browser:smoke:full` for the full matrix.
179
+ - `npm run browser:smoke:firefox` builds the site and runs focused Gecko input checks for wheel ownership, page/cross-tab scrolling, Grid Walk boundary handoff and interrupted dragging. Install its isolated browser once with `npx playwright install firefox`; append `-- --skip-build` to reuse a current site build. This optional check complements the Chromium gates and does not reproduce native macOS trackpad momentum or validate a user's Zen profile.
179
180
  - `npm run changeset` records the next version bump and changelog note.
180
181
  - `npm run version-packages` applies pending Changesets locally.
181
182
  - `.github/workflows/ci.yml` verifies the package on push and pull request.
package/docs/grid_walk.md CHANGED
@@ -67,6 +67,8 @@ There is no motion button. Hosts can set `ambientMotion: false` for a static pre
67
67
 
68
68
  Very small containers retain the package's minimum-size limits. Provide at least 320 px width and enough height for the scene and controls. Browser checks exercise 320 × 460, 390 × 360, 390 × 760, 640 × 640, 720 × 460, 1120 × 620 and 1400 × 400 hosts. In short containers the shared banner bounds its height and allows its own content to scroll. The project banner retains the race component's text truncation and compact layout.
69
69
 
70
+ Dragging releases pointer capture when its window loses focus, its document becomes hidden, or a subsequent pointer move reports no pressed buttons. Returning to the tab never resumes an interrupted drag; a fresh press begins a new gesture.
71
+
70
72
  ## Startup, failure and recovery
71
73
 
72
74
  A successful `restart()` completes loading for any newly created Grid Walk surfaces before rendering the replacement session. Restarted project banners must show their entry content rather than stale startup placeholders.
@@ -77,4 +79,6 @@ Hosts must restore Retry in a `finally` block and explicitly call their mount/st
77
79
 
78
80
  ## Verification surface
79
81
 
82
+ For focused Gecko input coverage, install the isolated test browser with `npx playwright install firefox`, then run `npm run browser:smoke:firefox` (or append `-- --skip-build` after a current site build). This checks native wheel ownership outside the simulator and across an independent control tab, Grid Walk boundary handoff, interrupted dragging, and scrolling after switching to Race. It does not run the full Chromium layout/touch matrix. Automated wheel events do not reproduce macOS trackpad momentum phases or establish acceptance in a user's Zen profile.
83
+
80
84
  Run `npm run site:dev` and open `/guide/grid-walk.html`, or use Grid Walk in the main demo at `/`. The main demo uses the single Start/Stop button; the Guide retains the default two-button switch. Host size controls change actual component dimensions without replacing the simulation. Normal and full browser gates exercise keyboard focus, canvas mouse/touch selection and dragging, diagonal wheel and cross-axis keyboard input, label overlap and selection continuity, opaque light surfaces, every entry, live resizing, state preservation, reduced motion, shared banner content/links and destroy/remount with cached assets. Focused tests cover deterministic progress equivalence, display-only staging and camera hysteresis.
@@ -16,6 +16,8 @@ Opt-in [Grid Walk](grid_walk.md) is package-owned presentation around normal bro
16
16
 
17
17
  The package-styled Grid Walk / Race switch mounts outside the scene through `mountViewControls()`, with automatic composition above the all-in-one shell and race telemetry drawer. A standalone canvas requires an explicitly mounted switch or host controls calling `setView()`. `ui.viewControls` defaults to `'switch'` and accepts `'toggle'` for a single green Start race / red Stop race action using semantic green/red flag colors; unknown values use `'switch'`. Stop pauses exact race progress and shows the original display grid, while Start resumes it. Both variants share runtime state, enable when ready, hide when Grid Walk is disabled and update after restart. Wheel browsing yields to page scrolling at the grid limits; Ctrl/Meta wheel retains browser zoom, and Race zoom is excluded while Grid Walk owns input. Varied groups of two to five mechanics and continuously distributed walking visitors respect reduced motion and host ambient-motion settings, with no motion toggle in the overlay. Expert mode is excluded; existing consumer defaults are preserved.
18
18
 
19
+ Grid Walk releases drag capture on window blur, document hiding and a pointer move with no pressed buttons. Interrupted gestures do not resume when focus returns; subsequent presses start normally. These lifecycle listeners belong to the canvas host's document/window and are removed with the runtime.
20
+
19
21
  ## Public API
20
22
 
21
23
  Main import:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inventure71/paddockjs",
3
- "version": "4.3.0",
3
+ "version": "4.3.1",
4
4
  "type": "module",
5
5
  "description": "A data-driven browser F1 simulator component for host websites.",
6
6
  "license": "Apache-2.0",
@@ -98,6 +98,7 @@
98
98
  "browser:smoke": "node smoke/browser-smoke.mjs",
99
99
  "browser:smoke:quick": "node smoke/browser-smoke.mjs --quick",
100
100
  "browser:smoke:full": "node smoke/browser-smoke.mjs --full",
101
+ "browser:smoke:firefox": "node smoke/firefox-input-smoke.mjs",
101
102
  "benchmark:runtime": "node scripts/benchmark-runtime-efficiency.mjs",
102
103
  "showcase:install": "npm run site:install",
103
104
  "showcase:dev": "npm run site:dev",
@@ -21,6 +21,8 @@ export class GridWalkNavigation {
21
21
  surface.addEventListener('pointermove', (event) => {
22
22
  const gesture = this.gesture;
23
23
  if (!gesture || gesture.id !== event.pointerId) return;
24
+ // Native pointerup/cancel can be missed when a drag leaves the window.
25
+ if (!this.enabled || event.buttons === 0) { this.cancel(); return; }
24
26
  const delta = this.horizontal ? event.clientX - gesture.x : event.clientY - gesture.y;
25
27
  if (!gesture.moved && Math.abs(delta) < 6) return;
26
28
  if (!delta) return;
@@ -45,6 +47,11 @@ export class GridWalkNavigation {
45
47
  event.stopImmediatePropagation();
46
48
  }, options);
47
49
  for (const name of ['pointercancel', 'lostpointercapture']) surface.addEventListener(name, () => this.cancel(), options);
50
+ const document = host.ownerDocument;
51
+ document?.defaultView?.addEventListener('blur', () => this.cancel(), { signal });
52
+ document?.addEventListener('visibilitychange', () => {
53
+ if (document.visibilityState === 'hidden') this.cancel();
54
+ }, { signal });
48
55
  surface.addEventListener('wheel', (event) => {
49
56
  if (!this.enabled || !isSceneTarget(event) || !event.cancelable || event.defaultPrevented || event.ctrlKey || event.metaKey) return;
50
57
  const unit = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? (this.horizontal ? host.clientWidth : host.clientHeight) : 1;