Fixes #20354 ## Problem Front component form events currently expose serialized form state through a sandbox-specific event shape, such as `event.detail.value` and `event.detail.checked`. That works for examples that explicitly read `event.detail`, but it is surprising for app authors writing standard React form handlers: ```tsx onChange={(event) => { setValue(event.target.value); }} Internal app code already has to defend against multiple possible shapes: // Values may live on e.detail.value, e.value, or e.target.value. This suggests the sandbox event shape is leaking into userland. Solution This change keeps the existing event.detail behavior, but also syncs serialized event target properties back onto the remote element before dispatching the event. That means both styles work: // Existing sandbox-specific style event.detail.value; // Standard React style event.target.value; The same applies to checked, files, scroll/media target properties, and similar serialized target state. What Changed Added a shared helper to apply serialized event target properties onto the remote element. Updated generated remote element event configs to dispatch serialized events through a custom event config. Updated the remote-dom element generator so regenerated files preserve this behavior. Updated Storybook form-event examples to use standard React event target reads. Added/updated Storybook coverage for input, checkbox, textarea, select, submit, and caret preservation flows. Validation Ran git diff --check Ran a targeted TypeScript error scan for the changed front component renderer files Manually verified the Storybook FrontComponent/EventForwarding form event story locally: text input updates state checkbox updates state submit reflects the updated JSON Note: local Storybook verification on Windows required temporary local build/cache fixes that are not included in this PR, to keep this change focused on front component event behavior. --------- Co-authored-by: Charles Bochet <charles@twenty.com>
51 lines
1.4 KiB
TypeScript
51 lines
1.4 KiB
TypeScript
import { useState } from 'react';
|
|
import { defineFrontComponent } from 'twenty-sdk/define';
|
|
import { updateProgress } from 'twenty-sdk/front-component';
|
|
|
|
import { FrontComponentCard } from '@/__stories__/shared/front-components/front-component-card';
|
|
import { BUTTON_STYLE } from '@/__stories__/shared/front-components/styles';
|
|
|
|
const STATUS_STYLE = {
|
|
fontSize: 13,
|
|
color: '#1f2937',
|
|
fontFamily: 'monospace',
|
|
};
|
|
|
|
const HostApiProgressFrontComponent = () => {
|
|
const [status, setStatus] = useState('idle');
|
|
|
|
const handleClick = async () => {
|
|
try {
|
|
await updateProgress(50);
|
|
setStatus('progress:success');
|
|
} catch (error) {
|
|
setStatus(
|
|
`progress:error:${error instanceof Error ? error.message : String(error)}`,
|
|
);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<FrontComponentCard title="host-api:progress">
|
|
<button
|
|
data-testid="subject"
|
|
type="button"
|
|
onClick={handleClick}
|
|
style={BUTTON_STYLE}
|
|
>
|
|
Update Progress
|
|
</button>
|
|
<span data-testid="api-status" style={STATUS_STYLE}>
|
|
{status}
|
|
</span>
|
|
</FrontComponentCard>
|
|
);
|
|
};
|
|
|
|
export default defineFrontComponent({
|
|
universalIdentifier: 'fc-host-progress-00000000-0000-0000-0000-000000000020',
|
|
name: 'host-api-progress-front-component',
|
|
description: 'Front component covering updateProgress host API',
|
|
component: HostApiProgressFrontComponent,
|
|
});
|