Orbit documentation: docs, wiki and FAQ pages
This commit is contained in:
commit
bcbe5fff22
18 changed files with 714 additions and 0 deletions
100
docs/compiled-plugins.md
Normal file
100
docs/compiled-plugins.md
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
# Compiled plugins
|
||||
|
||||
A quick `.js` plugin (see [Plugin system](/docs/plugins/)) is great for small
|
||||
things. For anything substantial — real components with state and hooks — build
|
||||
the plugin like a normal project and compile it down to **one droppable file**: a
|
||||
compiled, externalized-React plugin model.
|
||||
|
||||
## The trick: externalize React
|
||||
|
||||
The output bundle must **not** carry its own copy of React. Two React instances
|
||||
on one page break hooks ("invalid hook call"). Instead, mark `react`, `react-dom`
|
||||
and `react/jsx-runtime` **external** and map them to Orbit's globals, so your
|
||||
plugin shares the host's single React instance:
|
||||
|
||||
| Module | Maps to |
|
||||
|---|---|
|
||||
| `react` | `Orbit.React` |
|
||||
| `react-dom` | `Orbit.ReactDOM` |
|
||||
| `react/jsx-runtime` | `Orbit.jsxRuntime` |
|
||||
|
||||
Because your component is created with Orbit's React and rendered through a slot
|
||||
into Orbit's tree, **hooks, state, context and effects all work**.
|
||||
|
||||
## Vite config
|
||||
|
||||
```ts
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
build: {
|
||||
lib: { entry: 'src/index.tsx', formats: ['iife'], name: 'MyOrbitPlugin',
|
||||
fileName: () => 'my-plugin.js' },
|
||||
rollupOptions: {
|
||||
external: ['react', 'react-dom', 'react/jsx-runtime'],
|
||||
output: { globals: {
|
||||
react: 'Orbit.React',
|
||||
'react-dom': 'Orbit.ReactDOM',
|
||||
'react/jsx-runtime': 'Orbit.jsxRuntime',
|
||||
} },
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Write normal TSX
|
||||
|
||||
```tsx
|
||||
import { useState } from 'react';
|
||||
|
||||
Orbit.plugin('my-plugin', (orbit) => {
|
||||
orbit.addUi('composer_button', () => <ShrugButton orbit={orbit} />);
|
||||
orbit.addSettingsSection({
|
||||
label: 'My plugin', icon: '🧩',
|
||||
render: () => <Panel orbit={orbit} />,
|
||||
});
|
||||
});
|
||||
|
||||
function Panel({ orbit }) {
|
||||
const [count, setCount] = useState(() => orbit.storage.get('count', 0));
|
||||
const bump = () => { const n = count + 1; setCount(n); orbit.storage.set('count', n); };
|
||||
return (
|
||||
<div className="scard"><div className="scard__body">
|
||||
<div className="sfield"><div className="sfield__intro">
|
||||
Compiled plugin — real React with hooks. You are <b>{orbit.state.nick()}</b>.
|
||||
</div></div>
|
||||
<div className="modal__actions">
|
||||
<button className="upbtn upbtn--primary" onClick={bump}>Clicked {count}×</button>
|
||||
</div>
|
||||
</div></div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
The compiled bundle is tiny — it contains only your code, calling Orbit's React.
|
||||
|
||||
## Starter template
|
||||
|
||||
A ready-to-copy starter (Vite config with the externals set up, `tsconfig`,
|
||||
ambient types and a working example) lives in the repo at
|
||||
[`plugin-template/`](https://codeberg.org/reversefr/orbit/src/branch/main/plugin-template).
|
||||
|
||||
```bash
|
||||
git clone https://codeberg.org/reversefr/orbit.git
|
||||
cd orbit/plugin-template
|
||||
npm install
|
||||
npm run build # → dist/orbit-plugin-template.js
|
||||
```
|
||||
|
||||
## Deploy
|
||||
|
||||
1. Copy the built `.js` to where Orbit can fetch it (e.g. `/app/plugins/`).
|
||||
2. List it in the deployed `config.json` — no rebuild of Orbit needed:
|
||||
|
||||
```json
|
||||
{ "plugins": ["/app/plugins/my-plugin.js"] }
|
||||
```
|
||||
|
||||
3. Reload. Your composer button and Settings section appear.
|
||||
Loading…
Add table
Add a link
Reference in a new issue