reflex.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. """Constants used to compile element classes."""
  2. from collections import defaultdict
  3. from reflex.utils import format
  4. from .html import ATTR_TO_ELEMENTS
  5. from .react import POSSIBLE_STANDARD_NAMES
  6. # Maps HTML attributes that are invalid Python identifiers to their Reflex
  7. # prop equivalents.
  8. ATTR_TO_PROP_OVERRIDES = {
  9. "async": "async_", # `async` is a reserved keyword in Python.
  10. }
  11. def attr_to_prop(attr_name: str) -> str:
  12. """Convert an HTML attribute name to its Reflex name.
  13. This function first uses React's `possibleStandardNames` to convert the
  14. HTML attribute name to its standard React name, then converts the standard
  15. name to a Reflex name.
  16. Args:
  17. attr_name: The HTML attribute name.
  18. Returns:
  19. A Reflex prop name that maps to the HTML attribute.
  20. """
  21. if attr_name in ATTR_TO_PROP_OVERRIDES:
  22. return ATTR_TO_PROP_OVERRIDES[attr_name]
  23. return format.to_snake_case(POSSIBLE_STANDARD_NAMES.get(attr_name, attr_name))
  24. # Names of HTML attributes that are provided by Reflex out of the box.
  25. REFLEX_PROVIDED_ATTRS = {"class", "id", "style"}
  26. # ATTR_TO_ELEMENTS contains HTML attribute names, which might be invalid as
  27. # Reflex prop names. PROP_TO_ELEMENTS contains the corresponding Reflex
  28. # prop names. It omits props that are provided by Reflex out of the box.
  29. PROP_TO_ELEMENTS = {
  30. attr_to_prop(attr_name): elements
  31. for attr_name, elements in ATTR_TO_ELEMENTS.items()
  32. if attr_name not in REFLEX_PROVIDED_ATTRS
  33. }
  34. # Invert PROP_TO_ELEMENTS to enable easier lookup.
  35. ELEMENT_TO_PROPS = defaultdict(list)
  36. for prop, elements in PROP_TO_ELEMENTS.items():
  37. for el in elements:
  38. ELEMENT_TO_PROPS[el].append(prop)