text_field.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. """Interactive components provided by @radix-ui/themes."""
  2. from typing import Any, Dict, Literal
  3. from reflex.components import el
  4. from reflex.components.component import Component, ComponentNamespace
  5. from reflex.components.core.debounce import DebounceInput
  6. from reflex.constants import EventTriggers
  7. from reflex.vars import Var
  8. from ..base import (
  9. LiteralAccentColor,
  10. LiteralRadius,
  11. RadixThemesComponent,
  12. )
  13. LiteralTextFieldSize = Literal["1", "2", "3"]
  14. LiteralTextFieldVariant = Literal["classic", "surface", "soft"]
  15. class TextFieldRoot(el.Div, RadixThemesComponent):
  16. """Captures user input with an optional slot for buttons and icons."""
  17. tag = "TextField.Root"
  18. # Text field size "1" - "3"
  19. size: Var[LiteralTextFieldSize]
  20. # Variant of text field: "classic" | "surface" | "soft"
  21. variant: Var[LiteralTextFieldVariant]
  22. # Override theme color for text field
  23. color_scheme: Var[LiteralAccentColor]
  24. # Override theme radius for text field: "none" | "small" | "medium" | "large" | "full"
  25. radius: Var[LiteralRadius]
  26. class TextFieldInput(el.Input, TextFieldRoot):
  27. """The input part of a TextField, may be used by itself."""
  28. tag = "TextField.Input"
  29. @classmethod
  30. def create(cls, *children, **props) -> Component:
  31. """Create an Input component.
  32. Args:
  33. *children: The children of the component.
  34. **props: The properties of the component.
  35. Returns:
  36. The component.
  37. """
  38. if props.get("value") is not None and props.get("on_change"):
  39. # create a debounced input if the user requests full control to avoid typing jank
  40. return DebounceInput.create(super().create(*children, **props))
  41. return super().create(*children, **props)
  42. def get_event_triggers(self) -> Dict[str, Any]:
  43. """Get the event triggers that pass the component's value to the handler.
  44. Returns:
  45. A dict mapping the event trigger to the var that is passed to the handler.
  46. """
  47. return {
  48. **super().get_event_triggers(),
  49. EventTriggers.ON_CHANGE: lambda e0: [e0.target.value],
  50. EventTriggers.ON_FOCUS: lambda e0: [e0.target.value],
  51. EventTriggers.ON_BLUR: lambda e0: [e0.target.value],
  52. EventTriggers.ON_KEY_DOWN: lambda e0: [e0.key],
  53. EventTriggers.ON_KEY_UP: lambda e0: [e0.key],
  54. }
  55. class TextFieldSlot(RadixThemesComponent):
  56. """Contains icons or buttons associated with an Input."""
  57. tag = "TextField.Slot"
  58. # Override theme color for text field slot
  59. color_scheme: Var[LiteralAccentColor]
  60. class Input(RadixThemesComponent):
  61. """High level wrapper for the Input component."""
  62. # Text field size "1" - "3"
  63. size: Var[LiteralTextFieldSize]
  64. # Variant of text field: "classic" | "surface" | "soft"
  65. variant: Var[LiteralTextFieldVariant]
  66. # Override theme color for text field
  67. color_scheme: Var[LiteralAccentColor]
  68. # Override theme radius for text field: "none" | "small" | "medium" | "large" | "full"
  69. radius: Var[LiteralRadius]
  70. # Whether the input should have autocomplete enabled
  71. auto_complete: Var[bool]
  72. # The value of the input when initially rendered.
  73. default_value: Var[str]
  74. # Disables the input
  75. disabled: Var[bool]
  76. # Specifies the maximum number of characters allowed in the input
  77. max_length: Var[str]
  78. # Specifies the minimum number of characters required in the input
  79. min_length: Var[str]
  80. # Name of the input, used when sending form data
  81. name: Var[str]
  82. # Placeholder text in the input
  83. placeholder: Var[str]
  84. # Indicates whether the input is read-only
  85. read_only: Var[bool]
  86. # Indicates that the input is required
  87. required: Var[bool]
  88. # Specifies the type of input
  89. type: Var[str]
  90. # Value of the input
  91. value: Var[str]
  92. @classmethod
  93. def create(cls, **props):
  94. """Create an Input component.
  95. Args:
  96. **props: The properties of the component.
  97. Returns:
  98. The component.
  99. """
  100. return TextFieldInput.create(**props)
  101. def get_event_triggers(self) -> Dict[str, Any]:
  102. """Get the event triggers that pass the component's value to the handler.
  103. Returns:
  104. A dict mapping the event trigger to the var that is passed to the handler.
  105. """
  106. return {
  107. **super().get_event_triggers(),
  108. EventTriggers.ON_CHANGE: lambda e0: [e0.target.value],
  109. EventTriggers.ON_FOCUS: lambda e0: [e0.target.value],
  110. EventTriggers.ON_BLUR: lambda e0: [e0.target.value],
  111. EventTriggers.ON_KEY_DOWN: lambda e0: [e0.key],
  112. EventTriggers.ON_KEY_UP: lambda e0: [e0.key],
  113. }
  114. class TextField(ComponentNamespace):
  115. """TextField components namespace."""
  116. root = staticmethod(TextFieldRoot.create)
  117. input = staticmethod(TextFieldInput.create)
  118. slot = staticmethod(TextFieldSlot.create)
  119. __call__ = staticmethod(Input.create)
  120. text_field = TextField()