Files
zmo-cli/packages/opencode/src/cli/cmd/tui/ui/dialog-prompt.tsx
T

74 lines
1.9 KiB
TypeScript

import { TextareaRenderable, TextAttributes } from "@opentui/core"
import { useTheme } from "../context/theme"
import { useDialog, type DialogContext } from "./dialog"
import { onMount } from "solid-js"
import { useKeyboard } from "@opentui/solid"
export type DialogPromptProps = {
title: string
value?: string
onConfirm?: (value: string) => void
onCancel?: () => void
}
export function DialogPrompt(props: DialogPromptProps) {
const dialog = useDialog()
const { theme } = useTheme()
let textarea: TextareaRenderable
useKeyboard((evt) => {
if (evt.name === "return") {
props.onConfirm?.(textarea.plainText)
dialog.clear()
}
})
onMount(() => {
dialog.setSize("large")
setTimeout(() => {
textarea.focus()
}, 1)
textarea.gotoLineEnd()
})
return (
<box paddingLeft={2} paddingRight={2} gap={1}>
<box flexDirection="row" justifyContent="space-between">
<text attributes={TextAttributes.BOLD}>{props.title}</text>
<text fg={theme.textMuted}>esc</text>
</box>
<box>
<textarea
onSubmit={() => {
props.onConfirm?.(textarea.plainText)
dialog.clear()
}}
keyBindings={[{ name: "return", action: "submit" }]}
ref={(val: TextareaRenderable) => (textarea = val)}
initialValue={props.value}
placeholder="Enter text"
/>
</box>
<box paddingBottom={1}>
<text fg={theme.textMuted}>Press enter to confirm, esc to cancel</text>
</box>
</box>
)
}
DialogPrompt.show = (dialog: DialogContext, title: string, value?: string) => {
return new Promise<string | null>((resolve) => {
dialog.replace(
() => (
<DialogPrompt
title={title}
value={value}
onConfirm={(value) => resolve(value)}
onCancel={() => resolve(null)}
/>
),
() => resolve(null),
)
})
}