Fix front component pointer/mouse event coordinates (#21117)

Fixes https://github.com/twentyhq/twenty/issues/21000

Front-component event handlers read standard event fields
(event.clientX, event.offsetX, …), but these were always undefined. On
the remote side, serialized event data was passed only as the
CustomEvent's detail — and CustomEvent ignores every constructor option
except detail, so the values lived at event.detail.clientX and never on
the event object itself.

- Added `applySerializedEventProperties`, to copy a curated allowlist of
event-level keys onto the event. Element/target state (value, checked,
files, scroll, media props) stays in
`applySerializedEventTargetProperties`, applied to this (the dispatch
element = event.target).
- Added x/y to `SerializedEventData` and to host-side serialization in
`createHtmlHostWrapper`.
- Added an `svg-pointer `story + `createHtmlTagPointerStory`

Note: Also pinned @types/react to v18 so the renderer stops dragging in
React 19 types and breaking typecheck.
This commit is contained in:
Raphaël Bosi
2026-06-02 17:04:11 +02:00
committed by GitHub
parent 1642be86f5
commit 1833fa84a5
13 changed files with 326 additions and 125 deletions
@@ -129,11 +129,22 @@ const generateCommonEventsType = (
});
writer.writeLine(');');
writer.blankLine();
writer.writeLine('return new CustomEvent(eventType, {');
writer.writeLine('const event = new CustomEvent(eventType, {');
writer.indent(() => {
writer.writeLine('detail: eventData,');
});
writer.writeLine('}) as RemoteEvent<SerializedEventData>;');
writer.blankLine();
writer.writeLine('applySerializedEventProperties(');
writer.indent(() => {
writer.writeLine(
'event as unknown as Record<string, unknown>,',
);
writer.writeLine('eventData,');
});
writer.writeLine(');');
writer.blankLine();
writer.writeLine('return event;');
});
writer.writeLine('},');
});
@@ -400,11 +411,18 @@ export const generateRemoteElements = (
});
sourceFile.addImportDeclaration({
moduleSpecifier: '@/constants/SerializedEventData',
namedImports: [
'applySerializedEventTargetProperties',
{ name: 'SerializedEventData', isTypeOnly: true },
],
moduleSpecifier: '@/constants/applySerializedEventProperties',
namedImports: ['applySerializedEventProperties'],
});
sourceFile.addImportDeclaration({
moduleSpecifier: '@/constants/applySerializedEventTargetProperties',
namedImports: ['applySerializedEventTargetProperties'],
});
sourceFile.addImportDeclaration({
moduleSpecifier: '@/types/SerializedEventData',
namedImports: [{ name: 'SerializedEventData', isTypeOnly: true }],
});
const commonPropertyNames = new Set(Object.keys(commonProperties));