Skip to content

Commit 29d9d31

Browse files
authored
[DOM] Copy source onto the synthetic toggle event (react#37389)
`ToggleEvent` carries a `source` property pointing at the control that opened or closed a popover, but `ToggleEventInterface` only lists `newState` and `oldState`, so the synthetic event never copies it. An `onToggle` handler reads `event.source` as `undefined` even when the native event has it. Adding `source` to the interface copies it off the native event the same way `newState` and `oldState` are copied.
1 parent 269bd40 commit 29d9d31

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

packages/react-dom-bindings/src/events/SyntheticEvent.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,7 @@ const ToggleEventInterface: EventInterfaceType = {
609609
...EventInterface,
610610
newState: 0,
611611
oldState: 0,
612+
source: 0,
612613
};
613614
export const SyntheticToggleEvent: $FlowFixMe =
614615
createSyntheticEvent(ToggleEventInterface);

packages/react-dom/src/events/plugins/__tests__/SimpleEventPlugin-test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class ToggleEvent extends Event {
1515
super(type, eventInit);
1616
this.newState = eventInit.newState;
1717
this.oldState = eventInit.oldState;
18+
this.source = eventInit.source;
1819
}
1920
}
2021

@@ -623,4 +624,39 @@ describe('SimpleEventPlugin', function () {
623624
const event = onSubmit.mock.calls[0][0];
624625
expect(event.submitter).toBe(submitter);
625626
});
627+
628+
it('includes the source in toggle events', async function () {
629+
container = document.createElement('div');
630+
631+
const onToggle = jest.fn();
632+
const root = ReactDOMClient.createRoot(container);
633+
await act(() => {
634+
root.render(
635+
<>
636+
<button popoverTarget="popover">Toggle popover</button>
637+
<div id="popover" popover="" onToggle={onToggle}>
638+
popover content
639+
</div>
640+
</>,
641+
);
642+
});
643+
644+
const source = container.querySelector('button');
645+
const target = container.querySelector('#popover');
646+
await act(() => {
647+
target.dispatchEvent(
648+
new ToggleEvent('toggle', {
649+
bubbles: false,
650+
cancelable: true,
651+
oldState: 'closed',
652+
newState: 'open',
653+
source: source,
654+
}),
655+
);
656+
});
657+
658+
expect(onToggle).toHaveBeenCalledTimes(1);
659+
const event = onToggle.mock.calls[0][0];
660+
expect(event.source).toBe(source);
661+
});
626662
});

0 commit comments

Comments
 (0)