Khaleel Al-Adhami il y a 3 jours
Parent
commit
914ac43bed
5 fichiers modifiés avec 92 ajouts et 72 suppressions
  1. 1 1
      reflex/app.py
  2. 5 2
      reflex/compiler/compiler.py
  3. 3 2
      reflex/config.py
  4. 38 30
      reflex/plugins/tailwind_v3.py
  5. 45 37
      reflex/plugins/tailwind_v4.py

+ 1 - 1
reflex/app.py

@@ -1417,7 +1417,7 @@ class App(MiddlewareMixin, LifespanMixin):
                     add_save_task=_submit_work,
                     add_modify_task=(
                         lambda *args, plugin=plugin: modify_files_tasks.append(
-                            (plugin.__class__.__name__, *args)
+                            (plugin.__class__.__module__ + plugin.__class__.__name__, *args)
                         )
                     ),
                 )

+ 5 - 2
reflex/compiler/compiler.py

@@ -223,6 +223,9 @@ def _validate_stylesheet(stylesheet_full_path: Path, assets_app_path: Path) -> N
         )
 
 
+RADIX_THEMES_STYLESHEET = "@radix-ui/themes/styles.css"
+
+
 def _compile_root_stylesheet(stylesheets: list[str]) -> str:
     """Compile the root stylesheet.
 
@@ -236,11 +239,11 @@ def _compile_root_stylesheet(stylesheets: list[str]) -> str:
         FileNotFoundError: If a specified stylesheet in assets directory does not exist.
     """
     # Add stylesheets from plugins.
-    sheets = [
+    sheets = [RADIX_THEMES_STYLESHEET] + [
         sheet
         for plugin in get_config().plugins
         for sheet in plugin.get_stylesheet_paths()
-    ] + ["@radix-ui/themes/styles.css"]
+    ]
 
     failed_to_import_sass = False
     assets_app_path = Path.cwd() / constants.Dirs.APP_ASSETS

+ 3 - 2
reflex/config.py

@@ -34,7 +34,7 @@ import pydantic.v1 as pydantic
 from reflex import constants
 from reflex.base import Base
 from reflex.constants.base import LogLevel
-from reflex.plugins import Plugin, TailwindV3Plugin
+from reflex.plugins import Plugin, TailwindV3Plugin, TailwindV4Plugin
 from reflex.utils import console
 from reflex.utils.exceptions import ConfigError, EnvironmentVarValueError
 from reflex.utils.types import (
@@ -925,7 +925,8 @@ class Config(Base):
         self._replace_defaults(**kwargs)
 
         if self.tailwind is not None and not any(
-            isinstance(plugin, TailwindV3Plugin) for plugin in self.plugins
+            isinstance(plugin, (TailwindV3Plugin, TailwindV4Plugin))
+            for plugin in self.plugins
         ):
             console.deprecate(
                 "Inferring tailwind usage",

+ 38 - 30
reflex/plugins/tailwind_v3.py

@@ -1,9 +1,9 @@
 """Base class for all plugins."""
 
-from pathlib import Path
 from types import SimpleNamespace
 
 from reflex.constants.base import Dirs
+from reflex.constants.compiler import Ext, PageNames
 from reflex.plugins.base import Plugin as PluginBase
 from reflex.utils.decorator import once
 
@@ -21,8 +21,9 @@ class Constants(SimpleNamespace):
     ROOT_STYLE_PATH = "./tailwind.css"
 
     # The default tailwind css.
-    TAILWIND_CSS = """
-@import "tailwindcss/base";
+    TAILWIND_CSS = """@import "tailwindcss/base";
+
+@import url('{radix_url}');
 
 @tailwind components;
 @tailwind utilities;
@@ -147,9 +148,9 @@ def compile_tailwind(
     return output_path, code
 
 
-def _index_of_element_that_startswith(lines: list[str], prefix: str) -> int | None:
+def _index_of_element_that_has(haystack: list[str], needle: str) -> int | None:
     return next(
-        (i for i, line in enumerate(lines) if line.strip().startswith(prefix)),
+        (i for i, line in enumerate(haystack) if needle in line),
         None,
     )
 
@@ -167,10 +168,10 @@ def add_tailwind_to_postcss_config(postcss_file_content: str) -> str:
 
     postcss_file_lines = postcss_file_content.splitlines()
 
-    if _index_of_element_that_startswith(postcss_file_lines, "tailwindcss") is not None:
+    if _index_of_element_that_has(postcss_file_lines, "tailwindcss") is not None:
         return postcss_file_content
 
-    line_with_postcss_plugins = _index_of_element_that_startswith(
+    line_with_postcss_plugins = _index_of_element_that_has(
         postcss_file_lines, "plugins"
     )
     if not line_with_postcss_plugins:
@@ -180,7 +181,7 @@ def add_tailwind_to_postcss_config(postcss_file_content: str) -> str:
         )
         return postcss_file_content
 
-    postcss_import_line = _index_of_element_that_startswith(
+    postcss_import_line = _index_of_element_that_has(
         postcss_file_lines, '"postcss-import"'
     )
     postcss_file_lines.insert(
@@ -190,6 +191,31 @@ def add_tailwind_to_postcss_config(postcss_file_content: str) -> str:
     return "\n".join(postcss_file_lines)
 
 
+def add_tailwind_to_css_file(css_file_content: str) -> str:
+    """Add tailwind to the css file.
+
+    Args:
+        css_file_content: The content of the css file.
+
+    Returns:
+        The modified css file content.
+    """
+    from reflex.compiler.compiler import RADIX_THEMES_STYLESHEET
+
+    if Constants.TAILWIND_CSS.splitlines()[0] in css_file_content:
+        return css_file_content
+    if RADIX_THEMES_STYLESHEET not in css_file_content:
+        print(  # noqa: T201
+            f"Could not find line with '{RADIX_THEMES_STYLESHEET}' in {Dirs.STYLES}. "
+            "Please make sure the file exists and is valid."
+        )
+        return css_file_content
+    return css_file_content.replace(
+        f"@import url('{RADIX_THEMES_STYLESHEET}');",
+        Constants.TAILWIND_CSS.format(radix_url=RADIX_THEMES_STYLESHEET),
+    )
+
+
 class Plugin(PluginBase):
     """Plugin for Tailwind CSS."""
 
@@ -210,28 +236,6 @@ class Plugin(PluginBase):
             for plugin in (config.tailwind or {}).get("plugins", [])
         ] + [Constants.VERSION]
 
-    def get_static_assets(self, **context):
-        """Get the static assets required by the plugin.
-
-        Args:
-            context: The context for the plugin.
-
-        Returns:
-            A list of static assets required by the plugin.
-        """
-        return [(Path("styles/tailwind.css"), Constants.TAILWIND_CSS)]
-
-    def get_stylesheet_paths(self, **context) -> list[str]:
-        """Get the paths to the stylesheets required by the plugin relative to the styles directory.
-
-        Args:
-            context: The context for the plugin.
-
-        Returns:
-            A list of paths to the stylesheets required by the plugin.
-        """
-        return [Constants.ROOT_STYLE_PATH]
-
     def pre_compile(self, **context):
         """Pre-compile the plugin.
 
@@ -245,3 +249,7 @@ class Plugin(PluginBase):
         config["content"] = config.get("content", Constants.CONTENT)
         context["add_save_task"](compile_tailwind, config)
         context["add_modify_task"](Dirs.POSTCSS_JS, add_tailwind_to_postcss_config)
+        context["add_modify_task"](
+            Dirs.STYLES + "/" + PageNames.STYLESHEET_ROOT + Ext.CSS,
+            add_tailwind_to_css_file,
+        )

+ 45 - 37
reflex/plugins/tailwind_v4.py

@@ -1,9 +1,9 @@
 """Base class for all plugins."""
 
-from pathlib import Path
 from types import SimpleNamespace
 
 from reflex.constants.base import Dirs
+from reflex.constants.compiler import Ext, PageNames
 from reflex.plugins.base import Plugin as PluginBase
 from reflex.utils.decorator import once
 
@@ -21,10 +21,11 @@ class Constants(SimpleNamespace):
     ROOT_STYLE_PATH = "./tailwind.css"
 
     # The default tailwind css.
-    TAILWIND_CSS = """
-@import "tailwindcss";
-
-@config '../tailwind.config.js';
+    TAILWIND_CSS = """@layer theme, base, components, utilities;
+@import "tailwindcss/theme.css" layer(theme);
+@import "tailwindcss/preflight.css" layer(base);
+@import "{radix_import}" layer(components);
+@import "tailwindcss/utilities.css" layer(utilities);
 """
 
 
@@ -146,9 +147,9 @@ def compile_tailwind(
     return output_path, code
 
 
-def _index_of_element_that_startswith(lines: list[str], prefix: str) -> int | None:
+def _index_of_element_that_has(haystack: list[str], needle: str) -> int | None:
     return next(
-        (i for i, line in enumerate(lines) if line.strip().startswith(prefix)),
+        (i for i, line in enumerate(haystack) if needle in line),
         None,
     )
 
@@ -166,10 +167,7 @@ def add_tailwind_to_postcss_config(postcss_file_content: str) -> str:
 
     postcss_file_lines = postcss_file_content.splitlines()
 
-    if _index_of_element_that_startswith(postcss_file_lines, "tailwindcss") is not None:
-        return postcss_file_content
-
-    line_with_postcss_plugins = _index_of_element_that_startswith(
+    line_with_postcss_plugins = _index_of_element_that_has(
         postcss_file_lines, "plugins"
     )
     if not line_with_postcss_plugins:
@@ -179,20 +177,48 @@ def add_tailwind_to_postcss_config(postcss_file_content: str) -> str:
         )
         return postcss_file_content
 
-    plugins_to_remove = ['""postcss-import"', "tailwindcss", "autoprefixer"]
+    plugins_to_remove = ['"postcss-import"', "tailwindcss", "autoprefixer"]
     plugins_to_add = ['"@tailwindcss/postcss"']
 
     for plugin in plugins_to_remove:
-        plugin_index = _index_of_element_that_startswith(postcss_file_lines, plugin)
+        plugin_index = _index_of_element_that_has(postcss_file_lines, plugin)
         if plugin_index is not None:
             postcss_file_lines.pop(plugin_index)
 
     for plugin in plugins_to_add[::-1]:
-        postcss_file_lines.insert(line_with_postcss_plugins + 1, f"  {plugin}: {{}},")
+        if not _index_of_element_that_has(postcss_file_lines, plugin):
+            postcss_file_lines.insert(
+                line_with_postcss_plugins + 1, f"  {plugin}: {{}},"
+            )
 
     return "\n".join(postcss_file_lines)
 
 
+def add_tailwind_to_css_file(css_file_content: str) -> str:
+    """Add tailwind to the css file.
+
+    Args:
+        css_file_content: The content of the css file.
+
+    Returns:
+        The modified css file content.
+    """
+    from reflex.compiler.compiler import RADIX_THEMES_STYLESHEET
+
+    if Constants.TAILWIND_CSS.splitlines()[0] in css_file_content:
+        return css_file_content
+    if RADIX_THEMES_STYLESHEET not in css_file_content:
+        print(  # noqa: T201
+            f"Could not find line with '{RADIX_THEMES_STYLESHEET}' in {Dirs.STYLES}. "
+            "Please make sure the file exists and is valid."
+        )
+        return css_file_content
+    return css_file_content.replace(
+        f"@import url('{RADIX_THEMES_STYLESHEET}');",
+        Constants.TAILWIND_CSS.format(radix_import=RADIX_THEMES_STYLESHEET),
+    )
+
+
 class Plugin(PluginBase):
     """Plugin for Tailwind CSS."""
 
@@ -211,29 +237,7 @@ class Plugin(PluginBase):
         return [
             plugin if isinstance(plugin, str) else plugin.get("name")
             for plugin in (config.tailwind or {}).get("plugins", [])
-        ] + [Constants.VERSION, "@tailwindcss/postcss4.1.7"]
-
-    def get_static_assets(self, **context):
-        """Get the static assets required by the plugin.
-
-        Args:
-            context: The context for the plugin.
-
-        Returns:
-            A list of static assets required by the plugin.
-        """
-        return [(Path("styles/tailwind.css"), Constants.TAILWIND_CSS)]
-
-    def get_stylesheet_paths(self, **context) -> list[str]:
-        """Get the paths to the stylesheets required by the plugin relative to the styles directory.
-
-        Args:
-            context: The context for the plugin.
-
-        Returns:
-            A list of paths to the stylesheets required by the plugin.
-        """
-        return [Constants.ROOT_STYLE_PATH]
+        ] + [Constants.VERSION, "@tailwindcss/postcss@4.1.7"]
 
     def pre_compile(self, **context):
         """Pre-compile the plugin.
@@ -248,3 +252,7 @@ class Plugin(PluginBase):
         config["content"] = config.get("content", Constants.CONTENT)
         context["add_save_task"](compile_tailwind, config)
         context["add_modify_task"](Dirs.POSTCSS_JS, add_tailwind_to_postcss_config)
+        context["add_modify_task"](
+            Dirs.STYLES + "/" + PageNames.STYLESHEET_ROOT + Ext.CSS,
+            add_tailwind_to_css_file,
+        )