Files
twenty/packages/twenty-front-component-renderer/src/constants/EventToReact.ts
T
Charles Bochet 563acc3f57 Allow copy to clipboard and pointer/mousemove events in front components (#20858)
Follow-up to #20525, picks up the clipboard + mouse/pointer events asks
from the "Allow to copy to clipboard in front-component" Slack thread.
`navigator.geolocation` and `getBoundingClientRect` are intentionally
out of scope until we have a permission model.

### `copyToClipboard` host API

New SDK function `copyToClipboard` (in `twenty-sdk/front-component`)
that goes through the host bridge to `useCopyToClipboard` in
`twenty-front`:

```ts
import { copyToClipboard } from 'twenty-sdk/front-component';

await copyToClipboard('hello');
```

Host-side hardening (front-component code is untrusted):
- Drops anything that isn't a non-empty string
- Caps payload at 64KB
- Throttles to 1 call/sec per front-component instance
- Snackbar shows a truncated preview so the user can spot a mismatch
between the affordance they clicked and what actually got copied

### `mousemove` and pointer events

Added to `COMMON_HTML_EVENTS` (and the React mapping) so they fire on
every HTML tag the renderer ships: `mousemove`, `pointerdown/up/move`,
`pointerover/out/enter/leave/cancel`. Generator rerun for
`remote-elements.ts` and `remote-components.ts`.

`SerializedEventData` now also forwards pointer geometry: `pointerId`,
`pointerType`, `pressure`, `tangentialPressure`, `tiltX/Y`, `twist`,
`width/height`, `isPrimary`. Existing positional fields are unchanged.

### Coverage

- New Storybook stories: `HostApi/CopyToClipboard` and
`HtmlTag/Grouping/Div/Events::PointerMove`
- `useFrontComponentExecutionContext` unit tests cover the API call,
preview truncation, type guard, length cap, and rate limit
- Renderer Storybook suite 227 → 229, prebuild bundle count 219 → 221
2026-05-23 08:28:11 +00:00

51 lines
1.3 KiB
TypeScript

export const EVENT_TO_REACT: Record<string, string> = {
click: 'onClick',
dblclick: 'onDoubleClick',
mousedown: 'onMouseDown',
mouseup: 'onMouseUp',
mousemove: 'onMouseMove',
mouseover: 'onMouseOver',
mouseout: 'onMouseOut',
mouseenter: 'onMouseEnter',
mouseleave: 'onMouseLeave',
pointerdown: 'onPointerDown',
pointerup: 'onPointerUp',
pointermove: 'onPointerMove',
pointerover: 'onPointerOver',
pointerout: 'onPointerOut',
pointerenter: 'onPointerEnter',
pointerleave: 'onPointerLeave',
pointercancel: 'onPointerCancel',
keydown: 'onKeyDown',
keyup: 'onKeyUp',
keypress: 'onKeyPress',
focus: 'onFocus',
blur: 'onBlur',
change: 'onChange',
input: 'onInput',
submit: 'onSubmit',
scroll: 'onScroll',
wheel: 'onWheel',
contextmenu: 'onContextMenu',
drag: 'onDrag',
timeupdate: 'onTimeUpdate',
play: 'onPlay',
pause: 'onPause',
ended: 'onEnded',
loadedmetadata: 'onLoadedMetadata',
loadeddata: 'onLoadedData',
volumechange: 'onVolumeChange',
seeking: 'onSeeking',
seeked: 'onSeeked',
error: 'onError',
canplay: 'onCanPlay',
canplaythrough: 'onCanPlayThrough',
waiting: 'onWaiting',
progress: 'onProgress',
durationchange: 'onDurationChange',
ratechange: 'onRateChange',
stalled: 'onStalled',
suspend: 'onSuspend',
emptied: 'onEmptied',
};