| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
- import type { TuiPluginApi, TuiSlotContext, TuiSlotMap, TuiSlotProps } from "@opencode-ai/plugin/tui"
- import { createSlot, createSolidSlotRegistry, type JSX, type SolidPlugin } from "@opentui/solid"
- import { createSignal } from "solid-js"
- import { isRecord } from "../util/record"
- type RuntimeSlotMap = TuiSlotMap<Record<string, object>>
- type SlotView = <Name extends string>(props: TuiSlotProps<Name>) => JSX.Element | null
- export type HostSlotPlugin<Slots extends Record<string, object> = {}> = SolidPlugin<TuiSlotMap<Slots>, TuiSlotContext>
- export type HostPluginApi = TuiPluginApi
- export type HostSlots = {
- register: {
- (plugin: HostSlotPlugin): () => void
- <Slots extends Record<string, object>>(plugin: HostSlotPlugin<Slots>): () => void
- }
- dispose: () => void
- }
- function isHostSlotPlugin(value: unknown): value is HostSlotPlugin<Record<string, object>> {
- if (!isRecord(value)) return false
- if (typeof value.id !== "string") return false
- return isRecord(value.slots)
- }
- export function createSlots() {
- const empty: SlotView = () => null
- const [view, setView] = createSignal<SlotView>(empty)
- const Slot: SlotView = (props) => view()(props)
- return {
- Slot,
- setup(api: HostPluginApi): HostSlots {
- const registry = createSolidSlotRegistry<RuntimeSlotMap, TuiSlotContext>(
- api.renderer,
- { theme: api.theme },
- {
- onPluginError(event) {
- console.error("[tui.slot] plugin error", {
- plugin: event.pluginId,
- slot: event.slot,
- phase: event.phase,
- source: event.source,
- message: event.error.message,
- })
- },
- },
- )
- const slot = createSlot<RuntimeSlotMap, TuiSlotContext>(registry)
- setView(() => (props: TuiSlotProps<string>) => slot(props))
- return {
- register(plugin: HostSlotPlugin) {
- if (!isHostSlotPlugin(plugin)) return () => {}
- return registry.register(plugin)
- },
- dispose() {
- setView(() => empty)
- },
- }
- },
- clear() {
- setView(() => empty)
- },
- }
- }
|