import { useDialog } from "@tui/ui/dialog" import { DialogSelect, type DialogSelectOption } from "@tui/ui/dialog-select" import { createContext, createMemo, createSignal, onCleanup, useContext, type Accessor, type ParentProps, } from "solid-js" import { useKeyboard } from "@opentui/solid" import { useKeybind } from "@tui/context/keybind" import type { KeybindsConfig } from "@opencode-ai/sdk" type Context = ReturnType const ctx = createContext() export type CommandOption = DialogSelectOption & { keybind?: keyof KeybindsConfig } function init() { const [registrations, setRegistrations] = createSignal[]>([]) const dialog = useDialog() const keybind = useKeybind() const options = createMemo(() => { return registrations().flatMap((x) => x()) }) let keybinds = true useKeyboard((evt) => { if (!keybinds) return for (const option of options()) { if (option.keybind && keybind.match(option.keybind, evt)) { evt.preventDefault() option.onSelect?.(dialog) return } } }) const result = { trigger(name: string, source?: "prompt") { for (const option of options()) { if (option.value === name) { option.onSelect?.(dialog, source) return } } }, keybinds(enabled: boolean) { keybinds = enabled }, show() { dialog.replace(() => ) }, register(cb: () => CommandOption[]) { const results = createMemo(cb) setRegistrations((arr) => [results, ...arr]) onCleanup(() => { setRegistrations((arr) => arr.filter((x) => x !== results)) }) }, get options() { return options() }, } return result } export function useCommandDialog() { const value = useContext(ctx) if (!value) { throw new Error("useCommandDialog must be used within a CommandProvider") } return value } export function CommandProvider(props: ParentProps) { const value = init() const dialog = useDialog() const keybind = useKeybind() useKeyboard((evt) => { if (keybind.match("command_list", evt) && dialog.stack.length === 0) { evt.preventDefault() dialog.replace(() => ) return } }) return {props.children} } function DialogCommand(props: { options: CommandOption[] }) { const keybind = useKeybind() return ( ({ ...x, footer: x.keybind ? keybind.print(x.keybind) : undefined, }))} /> ) }