74 lines
1.9 KiB
TypeScript
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),
|
|
)
|
|
})
|
|
}
|