|
|
@@ -0,0 +1,65 @@
|
|
|
+import { TextareaRenderable, TextAttributes } from "@opentui/core"
|
|
|
+import { useTheme } from "../context/theme"
|
|
|
+import { useDialog, type DialogContext } from "./dialog"
|
|
|
+import { onMount } from "solid-js"
|
|
|
+
|
|
|
+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
|
|
|
+
|
|
|
+ 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),
|
|
|
+ )
|
|
|
+ })
|
|
|
+}
|