-
Notifications
You must be signed in to change notification settings - Fork 21
feat(ScrollView): conditional wheel event preventDefault for nested scrolling #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
myers
wants to merge
7
commits into
alibaba:main
Choose a base branch
from
myers:feat/scrollview-wheel
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,026
−168
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…actory
Separate frame scheduling concerns from canvas creation for better
architectural clarity and simpler custom integrations (e.g., WebXR).
Changes:
- Split IPlatformAdapter into two focused interfaces:
* IFrameScheduler - Frame scheduling (scheduleFrame, onFrame)
* ICanvasFactory - Canvas creation and management
- Update RenderCanvas to depend only on IFrameScheduler
* Rename parameter from platformAdapter to frameScheduler
* RenderCanvas no longer depends on canvas creation methods
- Update createElement factory to accept IFrameScheduler
- Keep IPlatformAdapter as union of both for backward compatibility
Benefits:
- Single Responsibility Principle - each interface has one concern
- RenderCanvas only depends on what it needs (frame scheduling)
- WebXR/custom renderers can provide simple IFrameScheduler without
implementing unused canvas creation methods
- No breaking changes - IPlatformAdapter still works as before
- Better foundation for testing and exotic platforms
Example WebXR usage:
class XRFrameScheduler implements IFrameScheduler {
scheduleFrame() { xrSession.requestAnimationFrame(...) }
onFrame(cb) { ... }
}
new RenderCanvas(new XRFrameScheduler(xrSession))
Fix pointerenter and pointerleave events to fire on entire element hierarchy, not just the direct target. Previously, these events only fired at the primary target element, which was incorrect. They should fire for all elements that are entered or left during pointer movement. Now properly tracks which elements were entered (in new path but not old) and which were left (in old path but not new), firing appropriate events for each.
This commit adds support for injecting custom event bindings into RenderCanvas and introduces BridgeEventBinding for programmatic event injection. Changes: - Add binding parameter to RenderCanvas constructor (defaults to DOMEventBinding) - Add binding parameter to createElement factory function - Implement BridgeEventBinding for programmatic event injection - Add NativeEventBinding.el property for element binding - Add comprehensive test suite for BridgeEventBinding (12 tests) Benefits: - Enables WebXR controller event injection - Clean interface using property setter pattern
This commit enables passing any canvas element (HTMLCanvasElement or OffscreenCanvas) to RenderCanvas via constructor injection, following the established dependency injection pattern (frameScheduler, binding). Changes: - Add canvas parameter to RenderCanvas constructor and createElement factory - Expand el property type to accept both HTMLCanvasElement and OffscreenCanvas - Update CanvasSurface to accept both HTMLCanvasElement and OffscreenCanvas - Rename createOrUpdateEl → ensureCanvasSize (reflects actual behavior) - Guard cursor management with instanceof check for HTMLCanvasElement - Make drawFrame public for manual rendering control - Add JSDoc documentation for constructor and drawFrame Benefits: - Clean dependency injection pattern consistent with other constructor parameters - Manual frame control via public drawFrame method - Cursor management gracefully degrades for OffscreenCanvas - Backwards compatible (canvas parameter is optional)
This commit adds HeadlessCanvas, a React component for rendering Canvas UI to OffscreenCanvas without mounting to the DOM. Changes: - Add HeadlessCanvas component with event injection API - Accept user-provided OffscreenCanvas and custom frameScheduler - Provide injectEvent and injectWheelEvent helpers via onReady callback - Support onFrameEnd callback for texture copying - Export HeadlessCanvas and related types from @canvas-ui/react Benefits: - Enables WebXR layer rendering (XRWebGLLayer texture targets) - Manual frame control with custom schedulers - Programmatic event injection for XR controllers - No DOM coupling for headless environments Use cases: - WebXR UI panels rendered to quad layers - Custom render loop integration
getBoundingClientRect() only exists on HTMLCanvasElement, not OffscreenCanvas. Skip popup positioning for OffscreenCanvas since it has no DOM position.
…crolling Implement proper wheel event bubbling behavior in RenderScrollView to enable nested scrolling scenarios where parent scrollers can handle events when the inner scroller reaches its scroll bounds. Changes: - RenderScrollView: only call preventDefault() when scroll actually occurs (when _setScrollOffset() returns true), allowing events to bubble to parent when at scroll bounds (top/bottom for vertical, left/right for horizontal) - Add 6 comprehensive integration tests covering preventDefault behavior at all scroll bounds and nested ScrollView scenarios - BridgeEventBinding: add preventDefault/stopPropagation mocks to wheel events for test support, plus stub pointer capture methods for compatibility Tests verify: - preventDefault called when scrolling within bounds - preventDefault NOT called when at top/bottom/left/right bounds - Nested ScrollViews: inner at bounds allows outer to scroll All tests passing (10 passed: 4 existing + 6 new)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Hello! 您好
This PR builds on the work in #35 (HeadlessCanvas). It depends on BridgeEventBinding from #32 for test infrastructure.
When scrolling through examples in storybook, it was annoying that when I scrolled while the pointer was over a canvas-ui element, it did nothing. This is the fix I came up with after digging into it.
This PR implements proper wheel event bubbling behavior in RenderScrollView to enable nested scrolling scenarios where parent scrollers can handle events when the inner scroller reaches its scroll bounds.
Changes:
Tests verify: