Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

122 lignes
3.1 KiB

  1. from __future__ import annotations
  2. from typing import TYPE_CHECKING, Any, Optional
  3. from ._input_handler import TextInputHandler
  4. from .element import CursorOffset, Element
  5. if TYPE_CHECKING:
  6. from pydantic import TypeAdapter
  7. from .styles.base import BaseStyle
  8. class Input(TextInputHandler, Element):
  9. label: Optional[str] = None
  10. def __init__(
  11. self,
  12. label: Optional[str] = None,
  13. placeholder: Optional[str] = None,
  14. default: Optional[str] = None,
  15. default_as_placeholder: bool = True,
  16. required: bool = False,
  17. required_message: Optional[str] = None,
  18. password: bool = False,
  19. inline: bool = False,
  20. name: Optional[str] = None,
  21. style: Optional[BaseStyle] = None,
  22. validator: Optional[TypeAdapter] = None,
  23. **metadata: Any,
  24. ):
  25. self.name = name
  26. self.label = label
  27. self._placeholder = placeholder
  28. self.default = default
  29. self.default_as_placeholder = default_as_placeholder
  30. self.required = required
  31. self.password = password
  32. self.inline = inline
  33. self.text = ""
  34. self.valid = None
  35. self.required_message = required_message
  36. self._validation_message: Optional[str] = None
  37. self._validator: Optional[TypeAdapter] = validator
  38. Element.__init__(self, style=style, metadata=metadata)
  39. super().__init__()
  40. @property
  41. def placeholder(self) -> str:
  42. if self.default_as_placeholder and self.default:
  43. return self.default
  44. return self._placeholder or ""
  45. @property
  46. def validation_message(self) -> Optional[str]:
  47. if self._validation_message:
  48. return self._validation_message
  49. assert self.valid
  50. return None
  51. @property
  52. def cursor_offset(self) -> CursorOffset:
  53. top = 1 if self.inline else 2
  54. left_offset = 0
  55. if self.inline and self.label:
  56. left_offset = len(self.label) + 1
  57. return CursorOffset(top=top, left=self.cursor_left + left_offset)
  58. @property
  59. def should_show_cursor(self) -> bool:
  60. return True
  61. def on_blur(self):
  62. self.on_validate()
  63. def on_validate(self):
  64. value = self.value.strip()
  65. if not value and self.required:
  66. self.valid = False
  67. self._validation_message = self.required_message or "This field is required"
  68. return
  69. if self._validator:
  70. from pydantic import ValidationError
  71. try:
  72. self._validator.validate_python(value)
  73. except ValidationError as e:
  74. self.valid = False
  75. self._validation_message = e.errors()[0]["ctx"]["reason"]
  76. return
  77. self._validation_message = None
  78. self.valid = True
  79. @property
  80. def value(self) -> str:
  81. return self.text or self.default or ""
  82. def ask(self) -> str:
  83. from .container import Container
  84. container = Container(style=self.style)
  85. container.elements = [self]
  86. container.run()
  87. return self.value