Appearance
interactive
Renders interactive elements with event handlers and persistent state across re-renders. Demonstrates that the plugin system preserves interactivity even when the streaming renderer updates surrounding content.
Details
| Property | Value |
|---|---|
| Name | interactive |
| Priority | 45 |
| Type | Block |
| Factory | interactive() |
Syntax
markdown
<button>Click me</button>
<toggle label="Dark mode" />
<input placeholder="Type here..." />Built-in Interactive Elements
<md-button>
Renders an HTML <button> element. Emits a button-click event on each click with the button text and cumulative click count.
markdown
<button>Click me</button>ts
md.on('interactive:button-click', (data) => {
// data: { text: "Click me", clickCount: 3 }
});<md-toggle>
Renders a checkbox with a label. Emits a toggle event when the state changes.
markdown
<toggle label="Dark mode" />
<toggle label="Notifications" checked />| Attribute | Type | Default | Description |
|---|---|---|---|
label | string | "" | Label text displayed next to the checkbox |
checked | boolean | false | Initial checked state |
ts
md.on('interactive:toggle', (data) => {
// data: { label: "Dark mode", checked: true }
});<md-input>
Renders an <input> element. Emits an input-change event on input.
markdown
<input placeholder="Type here..." />
<input placeholder="Name" value="Default" />| Attribute | Type | Default | Description |
|---|---|---|---|
placeholder | string | "" | Placeholder text |
value | string | "" | Initial value |
ts
md.on('interactive:input-change', (data) => {
// data: { value: "typed text" }
});State Preservation
Interactive elements maintain their state across re-renders. When new markdown chunks arrive and surrounding content changes, the plugin ensures:
- Button click counts are not reset
- Input field text is preserved
- Toggle state is maintained
This is achieved through stable element identity keyed on the token's position in the stream. The plugin tracks live elements and reuses them during re-renders instead of creating new ones.
API
ts
import { interactive } from '@generative-dom/plugins';
const plugin = interactive();No configuration options.
Edge Cases
- State across
push(): After pushing new chunks, interactive elements from earlier chunks retain their state (click counts, typed text, toggle state). reset()behavior: Callingmd.reset()properly destroys interactive elements and cleans up event listeners.- Rapid re-renders: Fast streaming does not duplicate interactive elements.
- End-of-stream elements: An interactive element at the end of the stream, followed by more chunks, stays in place while new content appears after it.
- Memory leaks: Creating and destroying many interactive elements does not leak memory. The object pool and
cleanup()method handle resource release.
Rendering
| Syntax | Output Element | Events |
|---|---|---|
<button>text</button> | <button> | interactive:button-click |
<toggle label="..." /> | <input type="checkbox"> + <label> | interactive:toggle |
<input placeholder="..." /> | <input> | interactive:input-change |