chakra.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. """Components that are based on Chakra-UI."""
  2. from __future__ import annotations
  3. from functools import lru_cache
  4. from typing import List, Literal
  5. from reflex.components.component import Component
  6. from reflex.utils import imports
  7. from reflex.vars import Var
  8. class ChakraComponent(Component):
  9. """A component that wraps a Chakra component."""
  10. library = "@chakra-ui/react@2.6.1"
  11. lib_dependencies: List[str] = [
  12. "@chakra-ui/system@2.5.7",
  13. "focus-visible@5.2.0",
  14. "framer-motion@10.16.4",
  15. ]
  16. @staticmethod
  17. @lru_cache(maxsize=None)
  18. def _get_app_wrap_components() -> dict[tuple[int, str], Component]:
  19. return {
  20. (60, "ChakraProvider"): chakra_provider,
  21. }
  22. def get_imports(self) -> imports.ImportDict:
  23. """Chakra requires focus-visible and imported into each page.
  24. This allows the GlobalStyle defined by the ChakraProvider to hide the blue border.
  25. Returns:
  26. The imports for the component.
  27. """
  28. return imports.merge_imports(
  29. super().get_imports(),
  30. {
  31. "": {
  32. imports.ImportVar(
  33. tag="focus-visible/dist/focus-visible", install=False
  34. )
  35. }
  36. },
  37. )
  38. def _get_style(self) -> dict:
  39. """Get the style for the component.
  40. Returns:
  41. The dictionary of the component style as value and the style notation as key.
  42. """
  43. return {"sx": self.style}
  44. @classmethod
  45. @lru_cache(maxsize=None)
  46. def _get_dependencies_imports(cls) -> imports.ImportDict:
  47. """Get the imports from lib_dependencies for installing.
  48. Returns:
  49. The dependencies imports of the component.
  50. """
  51. return {
  52. dep: [imports.ImportVar(tag=None, render=False)]
  53. for dep in [
  54. "@chakra-ui/system@2.5.7",
  55. "focus-visible@5.2.0",
  56. "framer-motion@10.16.4",
  57. ]
  58. }
  59. class Global(Component):
  60. """The emotion/react Global styling component."""
  61. library = "@emotion/react@^11.11.0"
  62. lib_dependencies: List[str] = [
  63. "@emotion/styled@^11.11.0",
  64. ]
  65. tag = "Global"
  66. styles: Var[str]
  67. class ChakraProvider(ChakraComponent):
  68. """Top level Chakra provider must be included in any app using chakra components."""
  69. tag = "ChakraProvider"
  70. theme: Var[str]
  71. @classmethod
  72. def create(cls) -> Component:
  73. """Create a new ChakraProvider component.
  74. Returns:
  75. A new ChakraProvider component.
  76. """
  77. return super().create(
  78. Global.create(styles=Var.create("GlobalStyles", _var_is_local=False)),
  79. theme=Var.create("extendTheme(theme)", _var_is_local=False),
  80. )
  81. def _get_imports(self) -> imports.ImportDict:
  82. _imports = super()._get_imports()
  83. _imports.setdefault(self.__fields__["library"].default, []).append(
  84. imports.ImportVar(tag="extendTheme", is_default=False),
  85. )
  86. _imports.setdefault("/utils/theme.js", []).append(
  87. imports.ImportVar(tag="theme", is_default=True),
  88. )
  89. _imports.setdefault(Global.__fields__["library"].default, []).append(
  90. imports.ImportVar(tag="css", is_default=False),
  91. )
  92. return _imports
  93. def _get_custom_code(self) -> str | None:
  94. return """
  95. const GlobalStyles = css`
  96. /* Hide the blue border around Chakra components. */
  97. .js-focus-visible :focus:not([data-focus-visible-added]) {
  98. outline: none;
  99. box-shadow: none;
  100. }
  101. `;
  102. """
  103. @staticmethod
  104. @lru_cache(maxsize=None)
  105. def _get_app_wrap_components() -> dict[tuple[int, str], Component]:
  106. return {
  107. (50, "ChakraColorModeProvider"): chakra_color_mode_provider,
  108. }
  109. chakra_provider = ChakraProvider.create()
  110. class ChakraColorModeProvider(Component):
  111. """Next-themes integration for chakra colorModeProvider."""
  112. library = "/components/reflex/chakra_color_mode_provider.js"
  113. tag = "ChakraColorModeProvider"
  114. is_default = True
  115. chakra_color_mode_provider = ChakraColorModeProvider.create()
  116. LiteralColorScheme = Literal[
  117. "none",
  118. "gray",
  119. "red",
  120. "orange",
  121. "yellow",
  122. "green",
  123. "teal",
  124. "blue",
  125. "cyan",
  126. "purple",
  127. "pink",
  128. "whiteAlpha",
  129. "blackAlpha",
  130. "linkedin",
  131. "facebook",
  132. "messenger",
  133. "whatsapp",
  134. "twitter",
  135. "telegram",
  136. ]
  137. LiteralVariant = Literal["solid", "subtle", "outline"]
  138. LiteralDividerVariant = Literal["solid", "dashed"]
  139. LiteralTheme = Literal["light", "dark"]
  140. LiteralTagColorScheme = Literal[
  141. "gray",
  142. "red",
  143. "orange",
  144. "yellow",
  145. "green",
  146. "teal",
  147. "blue",
  148. "cyan",
  149. "purple",
  150. "pink",
  151. ]
  152. LiteralTagAlign = Literal["center", "end", "start"]
  153. LiteralTabsVariant = Literal[
  154. "line",
  155. "enclosed",
  156. "enclosed-colored",
  157. "soft-rounded",
  158. "solid-rounded",
  159. "unstyled",
  160. ]
  161. LiteralStatus = Literal["success", "info", "warning", "error"]
  162. LiteralAlertVariant = Literal["subtle", "left-accent", "top-accent", "solid"]
  163. LiteralButtonVariant = Literal["ghost", "outline", "solid", "link", "unstyled"]
  164. LiteralSpinnerPlacement = Literal["start", "end"]
  165. LiteralLanguage = Literal[
  166. "en",
  167. "da",
  168. "de",
  169. "es",
  170. "fr",
  171. "ja",
  172. "ko",
  173. "pt_br",
  174. "ru",
  175. "zh_cn",
  176. "ro",
  177. "pl",
  178. "ckb",
  179. "lv",
  180. "se",
  181. "ua",
  182. "he",
  183. "it",
  184. ]
  185. LiteralInputVariant = Literal["outline", "filled", "flushed", "unstyled"]
  186. LiteralInputNumberMode = [
  187. "text",
  188. "search",
  189. "none",
  190. "tel",
  191. "url",
  192. "email",
  193. "numeric",
  194. "decimal",
  195. ]
  196. LiteralChakraDirection = Literal["ltr", "rtl"]
  197. LiteralCardVariant = Literal["outline", "filled", "elevated", "unstyled"]
  198. LiteralStackDirection = Literal["row", "column"]
  199. LiteralImageLoading = Literal["eager", "lazy"]
  200. LiteralTagSize = Literal["sm", "md", "lg"]
  201. LiteralSpinnerSize = Literal[Literal[LiteralTagSize], "xs", "xl"]
  202. LiteralAvatarSize = Literal[Literal[LiteralTagSize], "xl", "xs", "2xl", "full", "2xs"]
  203. LiteralButtonSize = Literal["sm", "md", "lg", "xs"]
  204. # Applies to AlertDialog and Modal
  205. LiteralAlertDialogSize = Literal[
  206. "sm", "md", "lg", "xs", "2xl", "full", "3xl", "4xl", "5xl", "6xl"
  207. ]
  208. LiteralDrawerSize = Literal[Literal[LiteralSpinnerSize], "xl", "full"]
  209. LiteralMenuStrategy = Literal["fixed", "absolute"]
  210. LiteralMenuOption = Literal["checkbox", "radio"]
  211. LiteralPopOverTrigger = Literal["click", "hover"]
  212. LiteralHeadingSize = Literal["lg", "md", "sm", "xs", "xl", "2xl", "3xl", "4xl"]