Integrate motion, pointer, gel, and package validation#39
Conversation
Greptile SummaryThis PR integrates DeviceOrientation permission/calibration/idle-reset, pointer and scroll physics, the Confidence Score: 5/5Safe to merge; no P0 or P1 findings — only two P2 style/documentation concerns No critical or blocking bugs found. Previous P1 threads are addressed. Two P2 findings (DEFAULT_BLOB_PHYSICS_CONFIG export inconsistency and scroll decay restart semantics change) are non-blocking style/documentation concerns that do not affect correctness. src/core/BlobPhysics.ts (DEFAULT_BLOB_PHYSICS_CONFIG export gap) and src/motion/ScrollHandler.ts (decay restart semantics change) Important Files Changed
Sequence DiagramsequenceDiagram
participant Host as Host App
participant TV as TinyVectors.svelte
participant DM as DeviceMotion
participant PP as PointerPhysicsController
participant SH as ScrollHandler
participant BP as BlobPhysics
participant IF as InteractionField
Host->>TV: mount (enableDeviceMotion, enableScrollPhysics, enablePointerPhysics)
TV->>BP: new BlobPhysics(blobCount, physicsConfig)
TV->>BP: init()
BP-->>TV: ready
TV->>DM: new DeviceMotion(callback, opts)
TV->>DM: initialize()
DM->>DM: observeReducedMotion()
DM->>DM: startListening() / return 'prompt'
TV->>SH: new ScrollHandler()
TV->>PP: createPointerPhysicsController({target: window})
loop Animation Frame
TV->>BP: tick(dt)
BP->>IF: gravityField (pre-cached via setGravity)
BP-->>TV: getBlobs()
end
Note over DM,BP: On device orientation event
DM->>DM: handleOrientation → calibrate / filter / deadZone
DM->>TV: callback(MotionVector)
TV->>BP: setGravity(x * strength, y * strength)
TV->>BP: setTilt(motionData)
BP->>IF: directionalBiasField(gravity, strength, maxForce)
Note over PP,BP: On pointer move
PP->>PP: getCoalescedEvents → rAF-batch
PP->>BP: updateMousePosition(x, y)
Note over SH,BP: On wheel event
SH->>SH: handleScroll → stickiness / pullForces
TV->>BP: setScrollStickiness(stickiness * 0.12)
Host->>TV: unmount
TV->>DM: cleanup()
TV->>PP: dispose()
TV->>SH: dispose()
TV->>BP: dispose()
Reviews (29): Last reviewed commit: "fix(physics): compute pointer velocity f..." | Re-trigger Greptile |
Summary
Integrates the current v0.3 cleanup work into
v0.3.0-develas reviewable slices:check:bundle-sizeso tracked runtime field modules are reported when they enter the{ TinyVectors }consumer bundleReview Follow-up
--disable-dev-shm-usageto the Chrome/CDP probe for container stability.DeviceMotionduring async component init so cleanup owns the active listener.>=5.20.0for current Svelte runtime assumptions.prefers-reduced-motionchanges from reduce to no-preference.test:browser:motion.requestDeviceMotionPermission()on mounted physics so stale handles cannot create post-unmount listeners.enableDeviceMotionin setup so live prop toggles follow the same cleanup path as scroll and pointer toggles.docs/physics-feel-contract.md, internalInteractionFieldhelpers, and the first gravity/device-orientation runtime route through that field contract.@propertyregistration back to--tv-blob-intensity.dist/core/InteractionField.jsnow that gravity routing imports it.DeviceMotionidle reset,deviceMotionIdleResetMs, browser idle-reset coverage, and explicit pointer IO capability detection.pointerout/mouseout/blurreset so scroll/pointer state cannot preserve stale pointer location after viewport exit.getDeviceMotionStatus()on the TinyVectors handle so host apps can inspect support, permission, and active listener state.prefers-reduced-motionchanges to reduce, with unit coverage.pointercancel, with public type exports, package-consumer coverage, browser listener lifecycle coverage, and docs.prefers-reduced-motion: reduceneutralizes motion, removes the orientation listener, and restores exactly one listener onno-preference.addListener/removeListenermedia query APIs for device-motion gating and cleanup.ScrollHandler's existingmaxForcesconfig so scroll pull-force retention can be capped or disabled without changing defaults.ScrollHandlerConfigfrom both package root and motion entrypoints.InteractionFieldas a bounded directional field, cached the resulting force outside the per-blob hot path, inlined the directional clamp for bundle recovery, and updated bundle-size reporting.Issue Map
Refs #24, #25, #26, #27, #28, #40.
Linear mapping:
Validation
pnpm run checkpnpm run test(180 tests)pnpm run buildpnpm run check:release-metadatapnpm run check:packagepnpm run check:bundle-size(10.90 KiBgzip,0.10 KiBtarget headroom; reportsInteractionFieldis included for gravity routing)pnpm run test:browser:motion(disabled-IO clean start, synthetic orientation, CDP orientation, directional motion signs, motion status, idle reset, reduced-motion listener lifecycle, pointer cancel/listener lifecycle, listener cleanup)nix develop . --command bazel build //:pkg //:package_consumer_check //:bundle_size_check //:typecheck //:test --verbose_failurespnpm run check:package-consumernpm pack --dry-run ./bazel-bin/pkgnpm publish --dry-run --ignore-scripts --access public ./bazel-bin/pkgNotes
The browser probe confirms synthetic
deviceorientationand CDP orientation overrides change blob paths, reports device-motion status as enabled/supported/granted/active in Chrome, and verifies device-orientation silence returns motion to neutral. Raw CDP accelerometer override remains informational because the runtime intentionally uses DeviceOrientation/TiltSource rather than raw accelerometer events.InteractionFieldnow has its first runtime consumer: gravity/device-orientation is routed through a bounded directional field. Pointer and scroll routing remain future slices so the restored demo feel stays reviewable.