dialog-prompt.tsx 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import { TextareaRenderable, TextAttributes } from "@opentui/core"
  2. import { useTheme } from "../context/theme"
  3. import { useDialog, type DialogContext } from "./dialog"
  4. import { onMount } from "solid-js"
  5. import { useKeyboard } from "@opentui/solid"
  6. export type DialogPromptProps = {
  7. title: string
  8. value?: string
  9. onConfirm?: (value: string) => void
  10. onCancel?: () => void
  11. }
  12. export function DialogPrompt(props: DialogPromptProps) {
  13. const dialog = useDialog()
  14. const { theme } = useTheme()
  15. let textarea: TextareaRenderable
  16. useKeyboard((evt) => {
  17. if (evt.name === "return") {
  18. props.onConfirm?.(textarea.plainText)
  19. dialog.clear()
  20. }
  21. })
  22. onMount(() => {
  23. dialog.setSize("large")
  24. setTimeout(() => {
  25. textarea.focus()
  26. }, 1)
  27. textarea.gotoLineEnd()
  28. })
  29. return (
  30. <box paddingLeft={2} paddingRight={2} gap={1}>
  31. <box flexDirection="row" justifyContent="space-between">
  32. <text attributes={TextAttributes.BOLD}>{props.title}</text>
  33. <text fg={theme.textMuted}>esc</text>
  34. </box>
  35. <box>
  36. <textarea
  37. onSubmit={() => {
  38. props.onConfirm?.(textarea.plainText)
  39. dialog.clear()
  40. }}
  41. keyBindings={[{ name: "return", action: "submit" }]}
  42. ref={(val: TextareaRenderable) => (textarea = val)}
  43. initialValue={props.value}
  44. placeholder="Enter text"
  45. />
  46. </box>
  47. <box paddingBottom={1}>
  48. <text fg={theme.textMuted}>Press enter to confirm, esc to cancel</text>
  49. </box>
  50. </box>
  51. )
  52. }
  53. DialogPrompt.show = (dialog: DialogContext, title: string, value?: string) => {
  54. return new Promise<string | null>((resolve) => {
  55. dialog.replace(
  56. () => (
  57. <DialogPrompt
  58. title={title}
  59. value={value}
  60. onConfirm={(value) => resolve(value)}
  61. onCancel={() => resolve(null)}
  62. />
  63. ),
  64. () => resolve(null),
  65. )
  66. })
  67. }