Skip to content

Add missing JSX DOM event bindings - #9075

Merged
cknitt merged 1 commit into
rescript-lang:masterfrom
glennsl:add-dom-event-bindings
Oct 28, 2026
Merged

cknitt merged 1 commit into
rescript-lang:masterfrom
glennsl:add-dom-event-bindings

Conversation

@glennsl

@glennsl glennsl commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Add missing handlers and capture variants through React DOM 19.3.1, including dialog, fullscreen, toggle, auxiliary-click, resize, scroll-end, and transition lifecycle events.

Add JsxEvent.Toggle with typed oldState, newState, and optional source accessors. Include JSX regression coverage and updated editor-completion snapshots.

Sources:

@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Changelog

💅 Polish

  • Add missing JSX DOM event handlers and capture variants through React 19.3, including dialog, fullscreen, toggle, scroll-end, and transition events, with typed toggle states and source.

Semantic Diff

1 commit · Full page

✏️ Add missing JSX DOM event bindings

3f55f1e · glennsl · Oct 27, 2026, 12:39 UTC · edited

Why

React DOM event handlers are missing from JsxDOM.domProps, forcing local extensions for dialogs, popovers, fullscreen, and capture-phase events. Match the event registrations and toggle fields in React DOM 19.3.1.

Typing modified (JsxDOM.domProps)

rescript · Before: Representative existing handlers · After: Existing handlers remain; missing handlers and capture variants are added

+onCancel?: JsxEvent.Synthetic.t => unit,
+onCancelCapture?: JsxEvent.Synthetic.t => unit,
+onClose?: JsxEvent.Synthetic.t => unit,
+onCloseCapture?: JsxEvent.Synthetic.t => unit,
+onFullscreenChange?: JsxEvent.Synthetic.t => unit,
+onFullscreenChangeCapture?: JsxEvent.Synthetic.t => unit,
+onFullscreenError?: JsxEvent.Synthetic.t => unit,
+onFullscreenErrorCapture?: JsxEvent.Synthetic.t => unit,
+onBeforeToggle?: JsxEvent.Toggle.t => unit,
+onBeforeToggleCapture?: JsxEvent.Toggle.t => unit,
+onToggle?: JsxEvent.Toggle.t => unit,
+onToggleCapture?: JsxEvent.Toggle.t => unit,
 onClick?: JsxEvent.Mouse.t => unit,
+onClickCapture?: JsxEvent.Mouse.t => unit,
 onScroll?: JsxEvent.UI.t => unit,
+onScrollCapture?: JsxEvent.UI.t => unit,
+onScrollEnd?: JsxEvent.UI.t => unit,
+onScrollEndCapture?: JsxEvent.UI.t => unit,
 onTransitionEnd?: JsxEvent.Transition.t => unit,
+onTransitionEndCapture?: JsxEvent.Transition.t => unit,
+… auxiliary-click, resize, transition cancel/run/start, and remaining capture handlers

Typing added (JsxEvent.Toggle)

rescript · After

module Toggle = {
  type tag
  type t = synthetic<tag>
  include MakeEventWithType({type t = t})
  @get external oldState: t => [#closed | #"open"] = "oldState"
  @get external newState: t => [#closed | #"open"] = "newState"
  @get @return(nullable) external source: t => option<Dom.element> = "source"
}

The JSX fixture covers the added handlers and toggle accessors. The editor completion snapshot is regenerated against the rebased compiler.

Review

  • Does this require React 19.3 for existing applications? No existing signatures change. Fullscreen handlers and the synthetic toggle source are available in React 19.3. The source accessor returns None for null or undefined, including on older React versions.
  • Are enter/leave capture handlers included? No. React's mouse and pointer enter/leave events have no capture phase.

@pkg-pr-new

pkg-pr-new Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

rescript

npm i https://pkg.pr.new/rescript@9075

@rescript/belt

npm i https://pkg.pr.new/@rescript/belt@9075

@rescript/darwin-arm64

npm i https://pkg.pr.new/@rescript/darwin-arm64@9075

@rescript/linux-arm64

npm i https://pkg.pr.new/@rescript/linux-arm64@9075

@rescript/linux-x64

npm i https://pkg.pr.new/@rescript/linux-x64@9075

@rescript/runtime

npm i https://pkg.pr.new/@rescript/runtime@9075

@rescript/win32-x64

npm i https://pkg.pr.new/@rescript/win32-x64@9075

commit: 3f55f1e

@cknitt

cknitt commented Oct 28, 2026

Copy link
Copy Markdown
Member

@glennsl Thanks a lot, this is great!

Could you rebase on latest master, and ask your agent to fill out the commit records for semantic diff using the records skill as described in AGENTS.md?

cknitt added a commit that referenced this pull request Oct 28, 2026
* Fail the Semantic Diff check for commits without a description

Commits with only a subject, like #9075's, leave their Semantic Diff
cards empty. The records format already requires a description;
`commitRecords.js --check` now enforces it after the comment is drawn,
and CONTRIBUTING.md, the PR template and AGENTS.md say so.

Diagnostic added (commit without a description):
After (text):
    A commit has no description:

      a1bc9e1 Add missing JSX DOM event bindings

    Below its subject, a commit message says why the commit is made, as a line
    or two of prose or a `Why:` section (see "Commit messages" in
    CONTRIBUTING.md). Add one with `git rebase -i`, marking these commits
    `reword`, or squash them into a commit that has one, and force-push.

Review: What counts as a description? A paragraph of prose, or a `Why:`
section with content. Object blocks, code and trailers alone don't count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kbf3gJ4f9jQinqHFuszdea
Signed-off-by: Christoph Knittel <ck@cca.io>

* Leave the check command out of the records skill

The skill already requires a description, and the failing check
explains itself, so naming the script there adds nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kbf3gJ4f9jQinqHFuszdea
Signed-off-by: Christoph Knittel <ck@cca.io>

* List the commit description before the sign-off in the PR template

The checklist now follows the order of a commit message: the
description comes before the Signed-off-by trailer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kbf3gJ4f9jQinqHFuszdea
Signed-off-by: Christoph Knittel <ck@cca.io>

---------

Signed-off-by: Christoph Knittel <ck@cca.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Why:
    React DOM event handlers are missing from JsxDOM.domProps, forcing local
    extensions for dialogs, popovers, fullscreen, and capture-phase events.
    Match the event registrations and toggle fields in React DOM 19.3.1.

Typing modified (JsxDOM.domProps):
Before (rescript): Representative existing handlers
    onClick?: JsxEvent.Mouse.t => unit,
    onScroll?: JsxEvent.UI.t => unit,
    onTransitionEnd?: JsxEvent.Transition.t => unit,
After (rescript): Existing handlers remain; missing handlers and capture variants are added
    onCancel?: JsxEvent.Synthetic.t => unit,
    onCancelCapture?: JsxEvent.Synthetic.t => unit,
    onClose?: JsxEvent.Synthetic.t => unit,
    onCloseCapture?: JsxEvent.Synthetic.t => unit,
    onFullscreenChange?: JsxEvent.Synthetic.t => unit,
    onFullscreenChangeCapture?: JsxEvent.Synthetic.t => unit,
    onFullscreenError?: JsxEvent.Synthetic.t => unit,
    onFullscreenErrorCapture?: JsxEvent.Synthetic.t => unit,
    onBeforeToggle?: JsxEvent.Toggle.t => unit,
    onBeforeToggleCapture?: JsxEvent.Toggle.t => unit,
    onToggle?: JsxEvent.Toggle.t => unit,
    onToggleCapture?: JsxEvent.Toggle.t => unit,
    onClick?: JsxEvent.Mouse.t => unit,
    onClickCapture?: JsxEvent.Mouse.t => unit,
    onScroll?: JsxEvent.UI.t => unit,
    onScrollCapture?: JsxEvent.UI.t => unit,
    onScrollEnd?: JsxEvent.UI.t => unit,
    onScrollEndCapture?: JsxEvent.UI.t => unit,
    onTransitionEnd?: JsxEvent.Transition.t => unit,
    onTransitionEndCapture?: JsxEvent.Transition.t => unit,
    … auxiliary-click, resize, transition cancel/run/start, and remaining capture handlers

Typing added (JsxEvent.Toggle):
After (rescript):
    module Toggle = {
      type tag
      type t = synthetic<tag>
      include MakeEventWithType({type t = t})
      @get external oldState: t => [#closed | #"open"] = "oldState"
      @get external newState: t => [#closed | #"open"] = "newState"
      @get @return(nullable) external source: t => option<Dom.element> = "source"
    }

Review: Does this require React 19.3 for existing applications?
    No existing signatures change. Fullscreen handlers and the synthetic
    toggle source are available in React 19.3. The source accessor returns
    None for null or undefined, including on older React versions.

Review: Are enter/leave capture handlers included?
    No. React's mouse and pointer enter/leave events have no capture phase.

The JSX fixture covers the added handlers and toggle accessors. The editor
completion snapshot is regenerated against the rebased compiler.

Signed-off-by: Glenn Slotte <glenn@slotte.net>
@glennsl
glennsl force-pushed the add-dom-event-bindings branch from a1bc9e1 to 3f55f1e Compare October 28, 2026 14:29
@cknitt
cknitt merged commit f3cf487 into rescript-lang:master Oct 28, 2026
26 checks passed
@glennsl
glennsl deleted the add-dom-event-bindings branch October 28, 2026 21:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants