106 lines
2.5 KiB
Markdown
106 lines
2.5 KiB
Markdown
# Layouts With React
|
|
|
|
Plugin layouts are real React components. They can use JSX and hooks.
|
|
|
|
```tsx
|
|
import type { PluginLayoutProps } from "@idea/plugin-sdk";
|
|
import { useState } from "react";
|
|
|
|
export function Dashboard(props: PluginLayoutProps): React.ReactElement {
|
|
const [localClicks, setLocalClicks] = useState(0);
|
|
|
|
return (
|
|
<button
|
|
type="button"
|
|
onClick={() => {
|
|
setLocalClicks((value) => value + 1);
|
|
props.setState({ localClicks: localClicks + 1 });
|
|
}}
|
|
>
|
|
Clicked {localClicks}
|
|
</button>
|
|
);
|
|
}
|
|
```
|
|
|
|
Register the component for a manifest-declared layout type:
|
|
|
|
```ts
|
|
ctx.layouts?.register({
|
|
type: "hello-plugin.dashboard",
|
|
component: Dashboard
|
|
});
|
|
```
|
|
|
|
The `type` must exactly match one entry in `contributes.layouts`. The host
|
|
rejects registrations for undeclared layout types. A plugin that opens this
|
|
layout for human feedback must also declare the `ui` capability so the UI
|
|
runtime and window services are part of the public contract.
|
|
|
|
```json
|
|
{
|
|
"capabilities": ["ui", "tooling"],
|
|
"contributes": {
|
|
"layouts": [
|
|
{
|
|
"type": "hello-plugin.dashboard",
|
|
"label": "Dashboard",
|
|
"component": "Dashboard"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
## Props
|
|
|
|
- `projectId`: project hosting the layout.
|
|
- `nodeId`: stable host node id for this layout instance.
|
|
- `layoutType`: manifest layout `type`.
|
|
- `state`: JSON-serializable host-persisted state.
|
|
- `setState(next)`: replace host-persisted state.
|
|
- `availability`: currently `"available"` while mounted.
|
|
|
|
Call `setState` from user actions, effects or async callbacks. Do not call it
|
|
unconditionally during render.
|
|
|
|
## Host React
|
|
|
|
Plugins must import React normally:
|
|
|
|
```ts
|
|
import { useEffect, useMemo, useState } from "react";
|
|
```
|
|
|
|
At runtime IdeA resolves these bare imports to the host instance:
|
|
|
|
- `react`
|
|
- `react-dom`
|
|
- `react-dom/client`
|
|
- `react/jsx-runtime`
|
|
- `react/jsx-dev-runtime`
|
|
|
|
Do not bundle your own copy of React or ReactDOM into the plugin. Declare them
|
|
as `peerDependencies` and `devDependencies` for local typechecking/builds.
|
|
|
|
```json
|
|
{
|
|
"peerDependencies": {
|
|
"react": "^18.2.0 || ^19.0.0",
|
|
"react-dom": "^18.2.0 || ^19.0.0"
|
|
},
|
|
"devDependencies": {
|
|
"@types/react": "^19.0.0",
|
|
"@types/react-dom": "^19.0.0",
|
|
"react": "^19.0.0",
|
|
"react-dom": "^19.0.0"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Build
|
|
|
|
Use `jsx: "react-jsx"` in `tsconfig`. A plain multi-file ESM `tsc` build is
|
|
supported as long as every emitted file imported by `main` is included in the
|
|
archive.
|