feat(runtime): résout react/react-dom vers l'instance host pour les layouts plugin
Le runtime SDK expose désormais react/react-dom résolus contre l'instance hébergée par IdeA plutôt qu'une copie embarquée, pour que les layouts plugin en JSX/hooks partagent le même arbre React que l'host. hello-plugin migre son layout d'exemple en .tsx pour illustrer le contrat. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
58
examples/hello-plugin/src/core/layout.tsx
Normal file
58
examples/hello-plugin/src/core/layout.tsx
Normal file
@ -0,0 +1,58 @@
|
||||
import type { PluginLayoutProps } from "@idea/plugin-sdk";
|
||||
import type { ReactElement } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
|
||||
let hasLoggedFirstLayoutRender = false;
|
||||
|
||||
export function HelloWorldLayout(props: PluginLayoutProps): ReactElement {
|
||||
const [localClicks, setLocalClicks] = useState(0);
|
||||
const hostState = useMemo(() => {
|
||||
return typeof props.state === "object" && props.state !== null && !Array.isArray(props.state)
|
||||
? (props.state as Record<string, unknown>)
|
||||
: {};
|
||||
}, [props.state]);
|
||||
const persistedClicks =
|
||||
typeof hostState.clicks === "number" && Number.isFinite(hostState.clicks)
|
||||
? hostState.clicks
|
||||
: 0;
|
||||
|
||||
if (!hasLoggedFirstLayoutRender) {
|
||||
hasLoggedFirstLayoutRender = true;
|
||||
console.info("[hello-plugin] layout first render", {
|
||||
projectId: props.projectId,
|
||||
nodeId: props.nodeId,
|
||||
layoutType: props.layoutType,
|
||||
hasState: props.state !== undefined
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<section style={{ display: "grid", gap: 12, fontFamily: "system-ui, sans-serif" }}>
|
||||
<header>
|
||||
<h2 style={{ margin: 0, fontSize: 16 }}>Hello Plugin</h2>
|
||||
<p style={{ margin: "4px 0 0", color: "#667085", fontSize: 13 }}>
|
||||
React layout rendered by IdeA host React.
|
||||
</p>
|
||||
</header>
|
||||
<dl style={{ display: "grid", gap: 4, margin: 0, fontSize: 13 }}>
|
||||
<div>
|
||||
<dt style={{ color: "#667085" }}>Project</dt>
|
||||
<dd style={{ margin: 0 }}>{props.projectId}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt style={{ color: "#667085" }}>Layout</dt>
|
||||
<dd style={{ margin: 0 }}>{props.layoutType}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setLocalClicks((current) => current + 1);
|
||||
props.setState({ ...hostState, clicks: persistedClicks + 1 });
|
||||
}}
|
||||
>
|
||||
Persist click {persistedClicks} / local click {localClicks}
|
||||
</button>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user