浏览代码

[REF-144] Add context in each component to prevent rerenders (#2198)

Masen Furer 1 年之前
父节点
当前提交
527437cf23
共有 100 个文件被更改,包括 1322 次插入607 次删除
  1. 27 0
      integration/test_var_operations.py
  2. 15 0
      reflex/.templates/jinja/web/pages/stateful_component.js.jinja2
  3. 5 0
      reflex/.templates/jinja/web/pages/stateful_components.js.jinja2
  4. 16 1
      reflex/.templates/jinja/web/utils/context.js.jinja2
  5. 4 3
      reflex/.templates/web/utils/state.js
  6. 86 59
      reflex/app.py
  7. 93 4
      reflex/compiler/compiler.py
  8. 6 0
      reflex/compiler/templates.py
  9. 20 6
      reflex/compiler/utils.py
  10. 1 1
      reflex/components/base/app_wrap.pyi
  11. 1 1
      reflex/components/base/body.pyi
  12. 6 6
      reflex/components/base/document.pyi
  13. 2 2
      reflex/components/base/head.pyi
  14. 2 2
      reflex/components/base/link.pyi
  15. 4 4
      reflex/components/base/meta.pyi
  16. 1 1
      reflex/components/base/script.pyi
  17. 441 21
      reflex/components/component.py
  18. 1 1
      reflex/components/datadisplay/badge.pyi
  19. 2 2
      reflex/components/datadisplay/code.pyi
  20. 1 1
      reflex/components/datadisplay/dataeditor.pyi
  21. 2 2
      reflex/components/datadisplay/datatable.pyi
  22. 1 1
      reflex/components/datadisplay/divider.pyi
  23. 1 1
      reflex/components/datadisplay/keyboard_key.pyi
  24. 4 4
      reflex/components/datadisplay/list.pyi
  25. 1 1
      reflex/components/datadisplay/moment.pyi
  26. 6 6
      reflex/components/datadisplay/stat.pyi
  27. 9 9
      reflex/components/datadisplay/table.pyi
  28. 5 5
      reflex/components/datadisplay/tag.pyi
  29. 5 5
      reflex/components/disclosure/accordion.pyi
  30. 5 5
      reflex/components/disclosure/tabs.pyi
  31. 6 6
      reflex/components/disclosure/transition.pyi
  32. 1 1
      reflex/components/disclosure/visuallyhidden.pyi
  33. 1 1
      reflex/components/el/element.pyi
  34. 1 1
      reflex/components/el/elements/base.pyi
  35. 14 14
      reflex/components/el/elements/forms.pyi
  36. 28 28
      reflex/components/el/elements/inline.pyi
  37. 14 14
      reflex/components/el/elements/media.pyi
  38. 5 5
      reflex/components/el/elements/metadata.pyi
  39. 7 7
      reflex/components/el/elements/other.pyi
  40. 3 3
      reflex/components/el/elements/scripts.pyi
  41. 15 15
      reflex/components/el/elements/sectioning.pyi
  42. 10 10
      reflex/components/el/elements/tables.pyi
  43. 15 15
      reflex/components/el/elements/typography.pyi
  44. 4 4
      reflex/components/feedback/alert.pyi
  45. 2 2
      reflex/components/feedback/circularprogress.pyi
  46. 1 1
      reflex/components/feedback/progress.pyi
  47. 3 3
      reflex/components/feedback/skeleton.pyi
  48. 1 1
      reflex/components/feedback/spinner.pyi
  49. 2 2
      reflex/components/forms/button.pyi
  50. 1 1
      reflex/components/forms/checkbox.py
  51. 2 2
      reflex/components/forms/checkbox.pyi
  52. 3 3
      reflex/components/forms/colormodeswitch.py
  53. 6 6
      reflex/components/forms/colormodeswitch.pyi
  54. 1 1
      reflex/components/forms/date_picker.pyi
  55. 1 1
      reflex/components/forms/date_time_picker.pyi
  56. 70 69
      reflex/components/forms/debounce.py
  57. 22 23
      reflex/components/forms/debounce.pyi
  58. 4 4
      reflex/components/forms/editable.pyi
  59. 1 1
      reflex/components/forms/editor.pyi
  60. 1 1
      reflex/components/forms/email.pyi
  61. 27 15
      reflex/components/forms/form.py
  62. 9 9
      reflex/components/forms/form.pyi
  63. 1 1
      reflex/components/forms/iconbutton.pyi
  64. 6 6
      reflex/components/forms/input.pyi
  65. 5 5
      reflex/components/forms/numberinput.pyi
  66. 1 1
      reflex/components/forms/password.pyi
  67. 4 1
      reflex/components/forms/pininput.py
  68. 2 2
      reflex/components/forms/pininput.pyi
  69. 2 2
      reflex/components/forms/radio.pyi
  70. 4 1
      reflex/components/forms/rangeslider.py
  71. 4 4
      reflex/components/forms/rangeslider.pyi
  72. 2 2
      reflex/components/forms/select.pyi
  73. 5 5
      reflex/components/forms/slider.pyi
  74. 1 1
      reflex/components/forms/switch.pyi
  75. 1 1
      reflex/components/forms/textarea.pyi
  76. 32 32
      reflex/components/forms/upload.py
  77. 81 1
      reflex/components/forms/upload.pyi
  78. 2 2
      reflex/components/graphing/plotly.pyi
  79. 25 25
      reflex/components/graphing/recharts/cartesian.pyi
  80. 11 11
      reflex/components/graphing/recharts/charts.pyi
  81. 5 5
      reflex/components/graphing/recharts/general.pyi
  82. 6 6
      reflex/components/graphing/recharts/polar.pyi
  83. 2 2
      reflex/components/graphing/recharts/recharts.pyi
  84. 1 1
      reflex/components/layout/aspect_ratio.pyi
  85. 1 1
      reflex/components/layout/box.pyi
  86. 4 4
      reflex/components/layout/card.pyi
  87. 3 3
      reflex/components/layout/center.pyi
  88. 8 8
      reflex/components/layout/cond.py
  89. 1 1
      reflex/components/layout/container.pyi
  90. 1 1
      reflex/components/layout/flex.pyi
  91. 30 32
      reflex/components/layout/foreach.py
  92. 1 1
      reflex/components/layout/fragment.pyi
  93. 3 3
      reflex/components/layout/grid.pyi
  94. 1 1
      reflex/components/layout/html.pyi
  95. 1 1
      reflex/components/layout/spacer.pyi
  96. 3 3
      reflex/components/layout/stack.pyi
  97. 2 2
      reflex/components/layout/wrap.pyi
  98. 4 4
      reflex/components/libs/chakra.pyi
  99. 1 1
      reflex/components/libs/react_player.pyi
  100. 1 1
      reflex/components/media/audio.pyi

+ 27 - 0
integration/test_var_operations.py

@@ -540,6 +540,29 @@ def VarOperations():
             rx.text(rx.Var.range(2, 10, 2).join(","), id="list_join_range2"),
             rx.text(rx.Var.range(5, 0, -1).join(","), id="list_join_range3"),
             rx.text(rx.Var.range(0, 3).join(","), id="list_join_range4"),
+            rx.box(
+                rx.foreach(
+                    rx.Var.range(0, 2), lambda x: rx.text(VarOperationState.list1[x])
+                ),
+                id="foreach_list_arg",
+            ),
+            rx.box(
+                rx.foreach(
+                    rx.Var.range(0, 2),
+                    lambda x, ix: rx.text(VarOperationState.list1[ix]),
+                ),
+                id="foreach_list_ix",
+            ),
+            rx.box(
+                rx.foreach(
+                    rx.Var.create_safe(list(range(0, 3))).to(list[int]),
+                    lambda x: rx.foreach(
+                        rx.Var.range(x),
+                        lambda y: rx.text(VarOperationState.list1[y]),
+                    ),
+                ),
+                id="foreach_list_nested",
+            ),
         )
 
     app.compile()
@@ -731,6 +754,10 @@ def test_var_operations(driver, var_operations: AppHarness):
         ("list_index_mod", "second"),
         # html component with var
         ("html_str", "hello"),
+        # index into list with foreach
+        ("foreach_list_arg", "1\n2"),
+        ("foreach_list_ix", "1\n2"),
+        ("foreach_list_nested", "1\n1\n2"),
     ]
 
     for tag, expected in tests:

+ 15 - 0
reflex/.templates/jinja/web/pages/stateful_component.js.jinja2

@@ -0,0 +1,15 @@
+{% import 'web/pages/utils.js.jinja2' as utils %}
+
+export function {{tag_name}} () {
+  {% for hook in component.get_hooks() %}
+  {{ hook }}
+  {% endfor %}
+
+  {% for hook in memo_trigger_hooks %}
+  {{ hook }}
+  {% endfor %}
+
+  return (
+    {{utils.render(component.render(), indent_width=0)}}
+  )
+}

+ 5 - 0
reflex/.templates/jinja/web/pages/stateful_components.js.jinja2

@@ -0,0 +1,5 @@
+{% extends "web/pages/base_page.js.jinja2" %}
+
+{% block export %}
+{{ memoized_code }}
+{% endblock %}

+ 16 - 1
reflex/.templates/jinja/web/utils/context.js.jinja2

@@ -1,5 +1,5 @@
 import { createContext, useContext, useMemo, useReducer, useState } from "react"
-import { applyDelta, Event, hydrateClientStorage, useEventLoop } from "/utils/state.js"
+import { applyDelta, Event, hydrateClientStorage, useEventLoop, refs } from "/utils/state.js"
 
 {% if initial_state %}
 export const initialState = {{ initial_state|json_dumps }}
@@ -8,6 +8,7 @@ export const initialState = {}
 {% endif %}
 
 export const ColorModeContext = createContext(null);
+export const UploadFilesContext = createContext(null);
 export const DispatchContext = createContext(null);
 export const StateContexts = {
   {% for state_name in initial_state %}
@@ -31,6 +32,20 @@ export const initialEvents = () => []
 
 export const isDevMode = {{ is_dev_mode|json_dumps }}
 
+export function UploadFilesProvider({ children }) {
+  const [filesById, setFilesById] = useState({})
+  refs["__clear_selected_files"] = (id) => setFilesById(filesById => {
+    const newFilesById = {...filesById}
+    delete newFilesById[id]
+    return newFilesById
+  })
+  return (
+    <UploadFilesContext.Provider value={[filesById, setFilesById]}>
+      {children}
+    </UploadFilesContext.Provider>
+  )
+}
+
 export function EventLoopProvider({ children }) {
   const dispatch = useContext(DispatchContext)
   const [addEvents, connectError] = useEventLoop(

+ 4 - 3
reflex/.templates/web/utils/state.js

@@ -34,8 +34,6 @@ const event_queue = [];
 
 // Pending upload promises, by id
 const upload_controllers = {};
-// Upload files state by id
-export const upload_files = {};
 
 /**
  * Generate a UUID (Used for session tokens).
@@ -363,7 +361,10 @@ export const uploadFiles = async (handler, files, upload_id, on_upload_progress,
         })
         resp_idx += 1
       } catch (e) {
-        console.log("Error parsing chunk", chunk, e)
+        if (progressEvent.progress === 1) {
+          // Chunk may be incomplete, so only report errors when full response is available.
+          console.log("Error parsing chunk", chunk, e)
+        }
         return
       }
     })

+ 86 - 59
reflex/app.py

@@ -2,11 +2,11 @@
 from __future__ import annotations
 
 import asyncio
+import concurrent.futures
 import contextlib
 import copy
 import functools
 import os
-from multiprocessing.pool import ThreadPool
 from typing import (
     Any,
     AsyncIterator,
@@ -636,9 +636,6 @@ class App(Base):
             TimeElapsedColumn(),
         )
 
-        task = progress.add_task("Compiling: ", total=len(self.pages))
-        # TODO: include all work done in progress indicator, not just self.pages
-
         # Get the env mode.
         config = get_config()
 
@@ -648,9 +645,7 @@ class App(Base):
         # Compile the pages in parallel.
         custom_components = set()
         # TODO Anecdotally, processes=2 works 10% faster (cpu_count=12)
-        thread_pool = ThreadPool()
         all_imports = {}
-        page_futures = []
         app_wrappers: Dict[tuple[int, str], Component] = {
             # Default app wrap component renders {children}
             (0, "AppWrap"): AppWrap.create()
@@ -659,81 +654,113 @@ class App(Base):
             # If a theme component was provided, wrap the app with it
             app_wrappers[(20, "Theme")] = self.theme
 
-        with progress:
-            for route, component in self.pages.items():
-                # TODO: this progress does not reflect actual threaded task completion
+        with progress, concurrent.futures.ThreadPoolExecutor() as thread_pool:
+            fixed_pages = 7
+            task = progress.add_task("Compiling:", total=len(self.pages) + fixed_pages)
+
+            def mark_complete(_=None):
                 progress.advance(task)
+
+            for _route, component in self.pages.items():
+                # Merge the component style with the app style.
                 component.add_style(self.style)
-                page_futures.append(
-                    thread_pool.apply_async(
-                        compiler.compile_page,
-                        args=(
-                            route,
-                            component,
-                            self.state,
-                        ),
-                    )
-                )
-                # add component.get_imports() to all_imports
+
+                # Add component.get_imports() to all_imports.
                 all_imports.update(component.get_imports())
 
-                # add the app wrappers from this component
+                # Add the app wrappers from this component.
                 app_wrappers.update(component.get_app_wrap_components())
 
                 # Add the custom components from the page to the set.
                 custom_components |= component.get_custom_components()
 
-        thread_pool.close()
-        thread_pool.join()
+            # Perform auto-memoization of stateful components.
+            (
+                stateful_components_path,
+                stateful_components_code,
+                page_components,
+            ) = compiler.compile_stateful_components(self.pages.values())
+            compile_results.append((stateful_components_path, stateful_components_code))
+
+            result_futures = []
+
+            def submit_work(fn, *args, **kwargs):
+                """Submit work to the thread pool and add a callback to mark the task as complete.
+
+                The Future will be added to the `result_futures` list.
+
+                Args:
+                    fn: The function to submit.
+                    *args: The args to submit.
+                    **kwargs: The kwargs to submit.
+                """
+                f = thread_pool.submit(fn, *args, **kwargs)
+                f.add_done_callback(mark_complete)
+                result_futures.append(f)
+
+            # Compile all page components.
+            for route, component in zip(self.pages, page_components):
+                submit_work(
+                    compiler.compile_page,
+                    route,
+                    component,
+                    self.state,
+                )
 
-        # Compile the app wrapper.
-        app_root = self._app_root(app_wrappers=app_wrappers)
-        all_imports.update(app_root.get_imports())
-        compile_results.append(compiler.compile_app(app_root))
+            # Compile the app wrapper.
+            app_root = self._app_root(app_wrappers=app_wrappers)
+            submit_work(compiler.compile_app, app_root)
 
-        # Get the compiled pages.
-        compile_results.extend(result.get() for result in page_futures)
+            # Compile the custom components.
+            submit_work(compiler.compile_components, custom_components)
 
-        # TODO the compile tasks below may also benefit from parallelization too
+            # Compile the root stylesheet with base styles.
+            submit_work(compiler.compile_root_stylesheet, self.stylesheets)
 
-        # Compile the custom components.
-        compile_results.append(compiler.compile_components(custom_components))
+            # Compile the root document.
+            submit_work(compiler.compile_document_root, self.head_components)
 
-        # Iterate through all the custom components and add their imports to the all_imports
-        for component in custom_components:
-            all_imports.update(component.get_imports())
+            # Compile the theme.
+            submit_work(compiler.compile_theme, style=self.style)
 
-        # Compile the root stylesheet with base styles.
-        compile_results.append(compiler.compile_root_stylesheet(self.stylesheets))
+            # Compile the contexts.
+            submit_work(compiler.compile_contexts, self.state)
 
-        # Compile the root document.
-        compile_results.append(compiler.compile_document_root(self.head_components))
+            # Compile the Tailwind config.
+            if config.tailwind is not None:
+                config.tailwind["content"] = config.tailwind.get(
+                    "content", constants.Tailwind.CONTENT
+                )
+            submit_work(compiler.compile_tailwind, config.tailwind)
 
-        # Compile the theme.
-        compile_results.append(compiler.compile_theme(style=self.style))
+            # Get imports from AppWrap components.
+            all_imports.update(app_root.get_imports())
 
-        # Compile the contexts.
-        compile_results.append(compiler.compile_contexts(self.state))
+            # Iterate through all the custom components and add their imports to the all_imports.
+            for component in custom_components:
+                all_imports.update(component.get_imports())
 
-        # Compile the Tailwind config.
-        if config.tailwind is not None:
-            config.tailwind["content"] = config.tailwind.get(
-                "content", constants.Tailwind.CONTENT
-            )
-            compile_results.append(compiler.compile_tailwind(config.tailwind))
+            # Wait for all compilation tasks to complete.
+            for future in concurrent.futures.as_completed(result_futures):
+                compile_results.append(future.result())
 
-        # Empty the .web pages directory
-        compiler.purge_web_pages_dir()
+            # Empty the .web pages directory.
+            compiler.purge_web_pages_dir()
 
-        # install frontend packages
-        self.get_frontend_packages(all_imports)
+            # Avoid flickering when installing frontend packages
+            progress.stop()
 
-        # Write the pages at the end to trigger the NextJS hot reload only once.
-        thread_pool = ThreadPool()
-        for output_path, code in compile_results:
-            thread_pool.apply_async(compiler_utils.write_page, args=(output_path, code))
-        thread_pool.close()
-        thread_pool.join()
+            # Install frontend packages.
+            self.get_frontend_packages(all_imports)
+
+            # Write the pages at the end to trigger the NextJS hot reload only once.
+            write_page_futures = []
+            for output_path, code in compile_results:
+                write_page_futures.append(
+                    thread_pool.submit(compiler_utils.write_page, output_path, code)
+                )
+            for future in concurrent.futures.as_completed(write_page_futures):
+                future.result()
 
     @contextlib.asynccontextmanager
     async def modify_state(self, token: str) -> AsyncIterator[State]:

+ 93 - 4
reflex/compiler/compiler.py

@@ -3,11 +3,17 @@ from __future__ import annotations
 
 import os
 from pathlib import Path
-from typing import Optional, Type
+from typing import Iterable, Optional, Type
 
 from reflex import constants
 from reflex.compiler import templates, utils
-from reflex.components.component import Component, ComponentStyle, CustomComponent
+from reflex.components.component import (
+    BaseComponent,
+    Component,
+    ComponentStyle,
+    CustomComponent,
+    StatefulComponent,
+)
 from reflex.config import get_config
 from reflex.state import State
 from reflex.utils.imports import ImportDict, ImportVar
@@ -99,8 +105,6 @@ def _compile_page(
     """
     # Merge the default imports with the app-specific imports.
     imports = utils.merge_imports(DEFAULT_IMPORTS, component.get_imports())
-    imports = {k: list(set(v)) for k, v in imports.items()}
-    utils.validate_imports(imports)
     imports = utils.compile_imports(imports)
 
     # Compile the code to render the component.
@@ -205,6 +209,68 @@ def _compile_components(components: set[CustomComponent]) -> str:
     )
 
 
+def _compile_stateful_components(
+    page_components: list[BaseComponent],
+) -> str:
+    """Walk the page components and extract shared stateful components.
+
+    Any StatefulComponent that is shared by more than one page will be rendered
+    to a separate module and marked rendered_as_shared so subsequent
+    renderings will import the component from the shared module instead of
+    directly including the code for it.
+
+    Args:
+        page_components: The Components or StatefulComponents to compile.
+
+    Returns:
+        The rendered stateful components code.
+    """
+    all_import_dicts = []
+    rendered_components = {}
+
+    def get_shared_components_recursive(component: BaseComponent):
+        """Get the shared components for a component and its children.
+
+        A shared component is a StatefulComponent that appears in 2 or more
+        pages and is a candidate for writing to a common file and importing
+        into each page where it is used.
+
+        Args:
+            component: The component to collect shared StatefulComponents for.
+        """
+        for child in component.children:
+            # Depth-first traversal.
+            get_shared_components_recursive(child)
+
+        # When the component is referenced by more than one page, render it
+        # to be included in the STATEFUL_COMPONENTS module.
+        if isinstance(component, StatefulComponent) and component.references > 1:
+            # Reset this flag to render the actual component.
+            component.rendered_as_shared = False
+
+            rendered_components.update(
+                {code: None for code in component.get_custom_code()},
+            )
+            all_import_dicts.append(component.get_imports())
+
+            # Indicate that this component now imports from the shared file.
+            component.rendered_as_shared = True
+
+    for page_component in page_components:
+        get_shared_components_recursive(page_component)
+
+    # Don't import from the file that we're about to create.
+    all_imports = utils.merge_imports(*all_import_dicts)
+    all_imports.pop(
+        f"/{constants.Dirs.UTILS}/{constants.PageNames.STATEFUL_COMPONENTS}", None
+    )
+
+    return templates.STATEFUL_COMPONENTS.render(
+        imports=utils.compile_imports(all_imports),
+        memoized_code="\n".join(rendered_components),
+    )
+
+
 def _compile_tailwind(
     config: dict,
 ) -> str:
@@ -330,6 +396,29 @@ def compile_components(components: set[CustomComponent]):
     return output_path, code
 
 
+def compile_stateful_components(
+    pages: Iterable[Component],
+) -> tuple[str, str, list[BaseComponent]]:
+    """Separately compile components that depend on State vars.
+
+    StatefulComponents are compiled as their own component functions with their own
+    useContext declarations, which allows page components to be stateless and avoid
+    re-rendering along with parts of the page that actually depend on state.
+
+    Args:
+        pages: The pages to extract stateful components from.
+
+    Returns:
+        The path and code of the compiled stateful components.
+    """
+    output_path = utils.get_stateful_components_path()
+
+    # Compile the stateful components.
+    page_components = [StatefulComponent.compile_from(page) or page for page in pages]
+    code = _compile_stateful_components(page_components)
+    return output_path, code, page_components
+
+
 def compile_tailwind(
     config: dict,
 ):

+ 6 - 0
reflex/compiler/templates.py

@@ -82,6 +82,12 @@ PAGE = get_template("web/pages/index.js.jinja2")
 # Code to render the custom components page.
 COMPONENTS = get_template("web/pages/custom_component.js.jinja2")
 
+# Code to render Component instances as part of StatefulComponent
+STATEFUL_COMPONENT = get_template("web/pages/stateful_component.js.jinja2")
+
+# Code to render StatefulComponent to an external file to be shared
+STATEFUL_COMPONENTS = get_template("web/pages/stateful_components.js.jinja2")
+
 # Sitemap config file.
 SITEMAP_CONFIG = "module.exports = {config}".format
 

+ 20 - 6
reflex/compiler/utils.py

@@ -54,17 +54,17 @@ def compile_import_statement(fields: list[imports.ImportVar]) -> tuple[str, list
     return default, list(rest)
 
 
-def validate_imports(imports: imports.ImportDict):
+def validate_imports(import_dict: imports.ImportDict):
     """Verify that the same Tag is not used in multiple import.
 
     Args:
-        imports: The dict of imports to validate
+        import_dict: The dict of imports to validate
 
     Raises:
         ValueError: if a conflict on "tag/alias" is detected for an import.
     """
     used_tags = {}
-    for lib, _imports in imports.items():
+    for lib, _imports in import_dict.items():
         for _import in _imports:
             import_name = (
                 f"{_import.tag}/{_import.alias}" if _import.alias else _import.tag
@@ -77,17 +77,19 @@ def validate_imports(imports: imports.ImportDict):
                 used_tags[import_name] = lib
 
 
-def compile_imports(imports: imports.ImportDict) -> list[dict]:
+def compile_imports(import_dict: imports.ImportDict) -> list[dict]:
     """Compile an import dict.
 
     Args:
-        imports: The import dict to compile.
+        import_dict: The import dict to compile.
 
     Returns:
         The list of import dict.
     """
+    collapsed_import_dict = imports.collapse_imports(import_dict)
+    validate_imports(collapsed_import_dict)
     import_dicts = []
-    for lib, fields in imports.items():
+    for lib, fields in collapsed_import_dict.items():
         default, rest = compile_import_statement(fields)
 
         # prevent lib from being rendered on the page if all imports are non rendered kind
@@ -356,6 +358,18 @@ def get_components_path() -> str:
     return os.path.join(constants.Dirs.WEB_UTILS, "components" + constants.Ext.JS)
 
 
+def get_stateful_components_path() -> str:
+    """Get the path of the compiled stateful components.
+
+    Returns:
+        The path of the compiled stateful components.
+    """
+    return os.path.join(
+        constants.Dirs.WEB_UTILS,
+        constants.PageNames.STATEFUL_COMPONENTS + constants.Ext.JS,
+    )
+
+
 def get_asset_path(filename: str | None = None) -> str:
     """Get the path for an asset.
 

+ 1 - 1
reflex/components/base/app_wrap.pyi

@@ -22,7 +22,7 @@ class AppWrap(Bare):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/base/body.pyi

@@ -20,7 +20,7 @@ class Body(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 6 - 6
reflex/components/base/document.pyi

@@ -21,7 +21,7 @@ class NextDocumentLib(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -100,7 +100,7 @@ class Html(NextDocumentLib):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -179,7 +179,7 @@ class DocumentHead(NextDocumentLib):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -258,7 +258,7 @@ class Main(NextDocumentLib):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -337,7 +337,7 @@ class NextScript(NextDocumentLib):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -416,7 +416,7 @@ class ColorModeScript(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 2 - 2
reflex/components/base/head.pyi

@@ -20,7 +20,7 @@ class NextHeadLib(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -99,7 +99,7 @@ class Head(NextHeadLib):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 2 - 2
reflex/components/base/link.pyi

@@ -23,7 +23,7 @@ class RawLink(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -111,7 +111,7 @@ class ScriptTag(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 4 - 4
reflex/components/base/meta.pyi

@@ -23,7 +23,7 @@ class Title(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -107,7 +107,7 @@ class Meta(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -196,7 +196,7 @@ class Description(Meta):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -285,7 +285,7 @@ class Image(Meta):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/base/script.pyi

@@ -24,7 +24,7 @@ class Script(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 441 - 21
reflex/components/component.py

@@ -2,14 +2,28 @@
 
 from __future__ import annotations
 
+import copy
 import typing
-from abc import ABC
+from abc import ABC, abstractmethod
 from functools import lru_cache, wraps
-from typing import Any, Callable, Dict, Iterator, List, Optional, Set, Type, Union
+from hashlib import md5
+from typing import (
+    Any,
+    Callable,
+    ClassVar,
+    Dict,
+    Iterator,
+    List,
+    Optional,
+    Set,
+    Type,
+    Union,
+)
 
 from reflex.base import Base
+from reflex.compiler.templates import STATEFUL_COMPONENT
 from reflex.components.tags import Tag
-from reflex.constants import Dirs, EventTriggers, Hooks, Imports
+from reflex.constants import Dirs, EventTriggers, Hooks, Imports, PageNames
 from reflex.event import (
     EventChain,
     EventHandler,
@@ -22,20 +36,17 @@ from reflex.style import Style
 from reflex.utils import console, format, imports, types
 from reflex.utils.imports import ImportVar
 from reflex.utils.serializers import serializer
-from reflex.vars import BaseVar, Var
-
+from reflex.vars import BaseVar, Var, VarData
 
-class Component(Base, ABC):
-    """The base class for all Reflex components."""
 
-    # The children nested within the component.
-    children: List[Component] = []
+class BaseComponent(Base, ABC):
+    """The base class for all Reflex components.
 
-    # The style of the component.
-    style: Style = Style()
+    This is something that can be rendered as a Component via the Reflex compiler.
+    """
 
-    # A mapping from event triggers to event chains.
-    event_triggers: Dict[str, Union[EventChain, Var]] = {}
+    # The children nested within the component.
+    children: List[BaseComponent] = []
 
     # The library that the component is based on.
     library: Optional[str] = None
@@ -46,6 +57,69 @@ class Component(Base, ABC):
     # The tag to use when rendering the component.
     tag: Optional[str] = None
 
+    @abstractmethod
+    def render(self) -> dict:
+        """Render the component.
+
+        Returns:
+            The dictionary for template of the component.
+        """
+
+    @abstractmethod
+    def get_hooks(self) -> set[str]:
+        """Get the React hooks for this component.
+
+        Returns:
+            The code that should appear just before returning the rendered component.
+        """
+
+    @abstractmethod
+    def get_imports(self) -> imports.ImportDict:
+        """Get all the libraries and fields that are used by the component.
+
+        Returns:
+            The import dict with the required imports.
+        """
+
+    @abstractmethod
+    def get_dynamic_imports(self) -> set[str]:
+        """Get dynamic imports for the component.
+
+        Returns:
+            The dynamic imports.
+        """
+
+    @abstractmethod
+    def get_custom_code(self) -> set[str]:
+        """Get custom code for the component.
+
+        Returns:
+            The custom code.
+        """
+
+    @abstractmethod
+    def get_refs(self) -> set[str]:
+        """Get the refs for the children of the component.
+
+        Returns:
+            The refs for the children.
+        """
+
+
+# Map from component to styling.
+ComponentStyle = Dict[Union[str, Type[BaseComponent]], Any]
+ComponentChild = Union[types.PrimitiveType, Var, BaseComponent]
+
+
+class Component(BaseComponent, ABC):
+    """A component with style, event trigger and other props."""
+
+    # The style of the component.
+    style: Style = Style()
+
+    # A mapping from event triggers to event chains.
+    event_triggers: Dict[str, Union[EventChain, Var]] = {}
+
     # The alias for the tag.
     alias: Optional[str] = None
 
@@ -74,7 +148,7 @@ class Component(Base, ABC):
     _valid_children: List[str] = []
 
     # custom attribute
-    custom_attrs: Dict[str, str] = {}
+    custom_attrs: Dict[str, Union[Var, str]] = {}
 
     @classmethod
     def __init_subclass__(cls, **kwargs):
@@ -493,7 +567,7 @@ class Component(Base, ABC):
         """
         if type(self) in style:
             # Extract the style for this component.
-            component_style = style[type(self)]
+            component_style = Style(style[type(self)])
 
             # Only add style props that are not overridden.
             component_style = {
@@ -505,6 +579,9 @@ class Component(Base, ABC):
 
         # Recursively add style to the children.
         for child in self.children:
+            # Skip BaseComponent and StatefulComponent children.
+            if not isinstance(child, Component):
+                continue
             child.add_style(style)
         return self
 
@@ -818,7 +895,7 @@ class Component(Base, ABC):
         """
         ref = self.get_ref()
         if ref is not None:
-            return f"const {ref} = useRef(null); refs['{ref}'] = {ref};"
+            return f"const {ref} = useRef(null); {str(Var.create_safe(ref).as_ref())} = {ref};"
 
     def _get_vars_hooks(self) -> set[str]:
         """Get the hooks required by vars referenced in this component.
@@ -953,6 +1030,9 @@ class Component(Base, ABC):
         if seen is None:
             seen = set()
         for child in self.children:
+            # Skip BaseComponent and StatefulComponent children.
+            if not isinstance(child, Component):
+                continue
             custom_components |= child.get_custom_components(seen=seen)
         return custom_components
 
@@ -991,17 +1071,15 @@ class Component(Base, ABC):
 
         # Add the app wrap components for the children.
         for child in self.children:
+            # Skip BaseComponent and StatefulComponent children.
+            if not isinstance(child, Component):
+                continue
             components.update(child.get_app_wrap_components())
 
         # Return the components.
         return components
 
 
-# Map from component to styling.
-ComponentStyle = Dict[Union[str, Type[Component]], Any]
-ComponentChild = Union[types.PrimitiveType, Var, Component]
-
-
 class CustomComponent(Component):
     """A custom user-defined component."""
 
@@ -1235,3 +1313,345 @@ def serialize_component(comp: Component):
         The serialized component.
     """
     return str(comp)
+
+
+class StatefulComponent(BaseComponent):
+    """A component that depends on state and is rendered outside of the page component.
+
+    If a StatefulComponent is used in multiple pages, it will be rendered to a common file and
+    imported into each page that uses it.
+
+    A stateful component has a tag name that includes a hash of the code that it renders
+    to. This tag name refers to the specific component with the specific props that it
+    was created with.
+    """
+
+    # A lookup table to caching memoized component instances.
+    tag_to_stateful_component: ClassVar[Dict[str, StatefulComponent]] = {}
+
+    # Reference to the original component that was memoized into this component.
+    component: Component
+
+    # The rendered (memoized) code that will be emitted.
+    code: str
+
+    # How many times this component is referenced in the app.
+    references: int = 0
+
+    # Whether the component has already been rendered to a shared file.
+    rendered_as_shared: bool = False
+
+    @classmethod
+    def create(cls, component: Component) -> StatefulComponent | None:
+        """Create a stateful component from a component.
+
+        Args:
+            component: The component to memoize.
+
+        Returns:
+            The stateful component or None if the component should not be memoized.
+        """
+        from reflex.components.layout.foreach import Foreach
+
+        if component.tag is None:
+            # Only memoize components with a tag.
+            return None
+
+        # If _var_data is found in this component, it is a candidate for auto-memoization.
+        has_var_data = False
+
+        # Determine if any Vars have associated data.
+        for prop_var in component._get_vars():
+            if prop_var._var_data:
+                has_var_data = True
+                break
+
+        if not has_var_data:
+            # Check for special-cases in child components.
+            for child in component.children:
+                # Skip BaseComponent and StatefulComponent children.
+                if not isinstance(child, Component):
+                    continue
+                # Always consider Foreach something that must be memoized by the parent.
+                if isinstance(child, Foreach):
+                    has_var_data = True
+                    break
+                child = cls._child_var(child)
+                if isinstance(child, Var) and child._var_data:
+                    has_var_data = True
+                    break
+
+        if has_var_data or component.event_triggers:
+            # Render the component to determine tag+hash based on component code.
+            tag_name = cls._get_tag_name(component)
+            if tag_name is None:
+                return None
+
+            # Look up the tag in the cache
+            stateful_component = cls.tag_to_stateful_component.get(tag_name)
+            if stateful_component is None:
+                # Render the component as a string of javascript code.
+                code = cls._render_stateful_code(component, tag_name=tag_name)
+                # Set the stateful component in the cache for the given tag.
+                stateful_component = cls.tag_to_stateful_component.setdefault(
+                    tag_name,
+                    cls(
+                        children=component.children,
+                        component=component,
+                        tag=tag_name,
+                        code=code,
+                    ),
+                )
+            # Bump the reference count -- multiple pages referencing the same component
+            # will result in writing it to a common file.
+            stateful_component.references += 1
+            return stateful_component
+
+        # Return None to indicate this component should not be memoized.
+        return None
+
+    @staticmethod
+    def _child_var(child: Component) -> Var | Component:
+        """Get the Var from a child component.
+
+        This method is used for special cases when the StatefulComponent should actually
+        wrap the parent component of the child instead of recursing into the children
+        and memoizing them independently.
+
+        Args:
+            child: The child component.
+
+        Returns:
+            The Var from the child component or the child itself (for regular cases).
+        """
+        from reflex.components.base.bare import Bare
+        from reflex.components.layout.cond import Cond
+        from reflex.components.layout.foreach import Foreach
+
+        if isinstance(child, Bare):
+            return child.contents
+        if isinstance(child, Cond):
+            return child.cond
+        if isinstance(child, Foreach):
+            return child.iterable
+        return child
+
+    @classmethod
+    def _get_tag_name(cls, component: Component) -> str | None:
+        """Get the tag based on rendering the given component.
+
+        Args:
+            component: The component to render.
+
+        Returns:
+            The tag for the stateful component.
+        """
+        # Get the render dict for the component.
+        rendered_code = component.render()
+        if not rendered_code:
+            # Never memoize non-visual components.
+            return None
+
+        # Compute the hash based on the rendered code.
+        code_hash = md5(str(rendered_code).encode("utf-8")).hexdigest()
+
+        # Format the tag name including the hash.
+        return format.format_state_name(f"{component.tag or 'Comp'}_{code_hash}")
+
+    @classmethod
+    def _render_stateful_code(
+        cls,
+        component: Component,
+        tag_name: str,
+    ) -> str:
+        """Render the code for a stateful component.
+
+        Args:
+            component: The component to render.
+            tag_name: The tag name for the stateful component (see _get_tag_name).
+
+        Returns:
+            The rendered code.
+        """
+        # Memoize event triggers useCallback to avoid unnecessary re-renders.
+        memo_event_triggers = tuple(cls._get_memoized_event_triggers(component).items())
+
+        # Trigger hooks stored separately to write after the normal hooks (see stateful_component.js.jinja2)
+        memo_trigger_hooks = []
+
+        if memo_event_triggers:
+            # Copy the component to avoid mutating the original.
+            component = copy.copy(component)
+
+            for event_trigger, (
+                memo_trigger,
+                memo_trigger_hook,
+            ) in memo_event_triggers:
+                # Replace the event trigger with the memoized version.
+                memo_trigger_hooks.append(memo_trigger_hook)
+                component.event_triggers[event_trigger] = memo_trigger
+
+        # Render the code for this component and hooks.
+        return STATEFUL_COMPONENT.render(
+            tag_name=tag_name,
+            memo_trigger_hooks=memo_trigger_hooks,
+            component=component,
+        )
+
+    @staticmethod
+    def _get_hook_deps(hook: str) -> list[str]:
+        """Extract var deps from a hook.
+
+        Args:
+            hook: The hook line to extract deps from.
+
+        Returns:
+            A list of var names created by the hook declaration.
+        """
+        var_name = hook.partition("=")[0].strip().split(None, 1)[1].strip()
+        if var_name.startswith("["):
+            # Break up array destructuring.
+            return [v.strip() for v in var_name.strip("[]").split(",")]
+        return [var_name]
+
+    @classmethod
+    def _get_memoized_event_triggers(
+        cls,
+        component: Component,
+    ) -> dict[str, tuple[Var, str]]:
+        """Memoize event handler functions with useCallback to avoid unnecessary re-renders.
+
+        Args:
+            component: The component with events to memoize.
+
+        Returns:
+            A dict of event trigger name to a tuple of the memoized event trigger Var and
+            the hook code that memoizes the event handler.
+        """
+        trigger_memo = {}
+        for event_trigger, event_args in component._get_vars_from_event_triggers(
+            component.event_triggers
+        ):
+            if event_trigger in {
+                EventTriggers.ON_MOUNT,
+                EventTriggers.ON_UNMOUNT,
+                EventTriggers.ON_SUBMIT,
+            }:
+                # Do not memoize lifecycle or submit events.
+                continue
+
+            # Get the actual EventSpec and render it.
+            event = component.event_triggers[event_trigger]
+            rendered_chain = format.format_prop(event)
+            if isinstance(rendered_chain, str):
+                rendered_chain = rendered_chain.strip("{}")
+
+            # Hash the rendered EventChain to get a deterministic function name.
+            chain_hash = md5(str(rendered_chain).encode("utf-8")).hexdigest()
+            memo_name = f"{event_trigger}_{chain_hash}"
+
+            # Calculate Var dependencies accessed by the handler for useCallback dep array.
+            var_deps = ["addEvents", "Event"]
+            for arg in event_args:
+                if arg._var_data is None:
+                    continue
+                for hook in arg._var_data.hooks:
+                    var_deps.extend(cls._get_hook_deps(hook))
+            memo_var_data = VarData.merge(
+                *[var._var_data for var in event_args],
+                VarData(  # type: ignore
+                    imports={"react": {ImportVar(tag="useCallback")}},
+                ),
+            )
+
+            # Store the memoized function name and hook code for this event trigger.
+            trigger_memo[event_trigger] = (
+                Var.create_safe(memo_name)._replace(
+                    _var_type=EventChain, merge_var_data=memo_var_data
+                ),
+                f"const {memo_name} = useCallback({rendered_chain}, [{', '.join(var_deps)}])",
+            )
+        return trigger_memo
+
+    def get_hooks(self) -> set[str]:
+        """Get the React hooks for this component.
+
+        Returns:
+            The code that should appear just before returning the rendered component.
+        """
+        return set()
+
+    def get_imports(self) -> imports.ImportDict:
+        """Get all the libraries and fields that are used by the component.
+
+        Returns:
+            The import dict with the required imports.
+        """
+        if self.rendered_as_shared:
+            return {
+                f"/{Dirs.UTILS}/{PageNames.STATEFUL_COMPONENTS}": [
+                    ImportVar(tag=self.tag)
+                ]
+            }
+        return self.component.get_imports()
+
+    def get_dynamic_imports(self) -> set[str]:
+        """Get dynamic imports for the component.
+
+        Returns:
+            The dynamic imports.
+        """
+        if self.rendered_as_shared:
+            return set()
+        return self.component.get_dynamic_imports()
+
+    def get_custom_code(self) -> set[str]:
+        """Get custom code for the component.
+
+        Returns:
+            The custom code.
+        """
+        if self.rendered_as_shared:
+            return set()
+        return self.component.get_custom_code().union({self.code})
+
+    def get_refs(self) -> set[str]:
+        """Get the refs for the children of the component.
+
+        Returns:
+            The refs for the children.
+        """
+        if self.rendered_as_shared:
+            return set()
+        return self.component.get_refs()
+
+    def render(self) -> dict:
+        """Define how to render the component in React.
+
+        Returns:
+            The tag to render.
+        """
+        return dict(Tag(name=self.tag))
+
+    @classmethod
+    def compile_from(cls, component: BaseComponent) -> BaseComponent:
+        """Walk through the component tree and memoize all stateful components.
+
+        Args:
+            component: The component to memoize.
+
+        Returns:
+            The memoized component tree.
+        """
+        from reflex.components.layout.foreach import Foreach
+
+        # Foreach must be memoized as a single component to retain index Var context.
+        if not isinstance(component, Foreach):
+            component.children = [
+                cls.compile_from(child) for child in component.children
+            ]
+        if isinstance(component, Component):
+            stateful_component = cls.create(component)
+            if stateful_component is not None:
+                return stateful_component
+        return component

+ 1 - 1
reflex/components/datadisplay/badge.pyi

@@ -28,7 +28,7 @@ class Badge(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 2 - 2
reflex/components/datadisplay/code.pyi

@@ -1034,7 +1034,7 @@ class CodeBlock(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1119,7 +1119,7 @@ class Code(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/datadisplay/dataeditor.pyi

@@ -134,7 +134,7 @@ class DataEditor(NoSSRComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_cell_activated: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 2 - 2
reflex/components/datadisplay/datatable.pyi

@@ -25,7 +25,7 @@ class Gridjs(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -110,7 +110,7 @@ class DataTable(Gridjs):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/datadisplay/divider.pyi

@@ -31,7 +31,7 @@ class Divider(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/datadisplay/keyboard_key.pyi

@@ -20,7 +20,7 @@ class KeyboardKey(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 4 - 4
reflex/components/datadisplay/list.pyi

@@ -27,7 +27,7 @@ class List(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -107,7 +107,7 @@ class ListItem(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -190,7 +190,7 @@ class OrderedList(List):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -274,7 +274,7 @@ class UnorderedList(List):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/datadisplay/moment.pyi

@@ -56,7 +56,7 @@ class Moment(NoSSRComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 6 - 6
reflex/components/datadisplay/stat.pyi

@@ -26,7 +26,7 @@ class Stat(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -106,7 +106,7 @@ class StatLabel(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -185,7 +185,7 @@ class StatNumber(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -264,7 +264,7 @@ class StatHelpText(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -344,7 +344,7 @@ class StatArrow(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -424,7 +424,7 @@ class StatGroup(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 9 - 9
reflex/components/datadisplay/table.pyi

@@ -33,7 +33,7 @@ class Table(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -118,7 +118,7 @@ class Thead(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -199,7 +199,7 @@ class Tbody(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -279,7 +279,7 @@ class Tfoot(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -360,7 +360,7 @@ class Tr(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -439,7 +439,7 @@ class Th(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -520,7 +520,7 @@ class Td(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -601,7 +601,7 @@ class TableCaption(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -681,7 +681,7 @@ class TableContainer(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 5 - 5
reflex/components/datadisplay/tag.pyi

@@ -28,7 +28,7 @@ class TagLabel(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -107,7 +107,7 @@ class TagLeftIcon(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -186,7 +186,7 @@ class TagRightIcon(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -265,7 +265,7 @@ class TagCloseButton(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -386,7 +386,7 @@ class Tag(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 5 - 5
reflex/components/disclosure/accordion.pyi

@@ -34,7 +34,7 @@ class Accordion(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -120,7 +120,7 @@ class AccordionItem(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -202,7 +202,7 @@ class AccordionButton(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -281,7 +281,7 @@ class AccordionPanel(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -360,7 +360,7 @@ class AccordionIcon(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 5 - 5
reflex/components/disclosure/tabs.pyi

@@ -111,7 +111,7 @@ class Tabs(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -201,7 +201,7 @@ class Tab(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -284,7 +284,7 @@ class TabList(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -363,7 +363,7 @@ class TabPanels(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -442,7 +442,7 @@ class TabPanel(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 6 - 6
reflex/components/disclosure/transition.pyi

@@ -24,7 +24,7 @@ class Transition(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -107,7 +107,7 @@ class Fade(Transition):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -192,7 +192,7 @@ class ScaleFade(Transition):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -278,7 +278,7 @@ class Slide(Transition):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -365,7 +365,7 @@ class SlideFade(Transition):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -454,7 +454,7 @@ class Collapse(Transition):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/disclosure/visuallyhidden.pyi

@@ -20,7 +20,7 @@ class VisuallyHidden(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/el/element.pyi

@@ -22,7 +22,7 @@ class Element(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/el/elements/base.pyi

@@ -65,7 +65,7 @@ class BaseHTML(Element):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 14 - 14
reflex/components/el/elements/forms.pyi

@@ -93,7 +93,7 @@ class Button(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -243,7 +243,7 @@ class Datalist(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -344,7 +344,7 @@ class Fieldset(Element):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -494,7 +494,7 @@ class Form(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -721,7 +721,7 @@ class Input(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -897,7 +897,7 @@ class Label(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1038,7 +1038,7 @@ class Legend(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1188,7 +1188,7 @@ class Meter(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1340,7 +1340,7 @@ class Optgroup(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1493,7 +1493,7 @@ class Option(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1641,7 +1641,7 @@ class Output(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1788,7 +1788,7 @@ class Progress(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1948,7 +1948,7 @@ class Select(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -2127,7 +2127,7 @@ class Textarea(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 28 - 28
reflex/components/el/elements/inline.pyi

@@ -86,7 +86,7 @@ class A(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -234,7 +234,7 @@ class Abbr(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -373,7 +373,7 @@ class B(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -512,7 +512,7 @@ class Bdi(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -651,7 +651,7 @@ class Bdo(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -790,7 +790,7 @@ class Br(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -929,7 +929,7 @@ class Cite(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1068,7 +1068,7 @@ class Code(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1210,7 +1210,7 @@ class Data(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1349,7 +1349,7 @@ class Dfn(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1488,7 +1488,7 @@ class Em(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1627,7 +1627,7 @@ class I(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1766,7 +1766,7 @@ class Kbd(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1905,7 +1905,7 @@ class Mark(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -2045,7 +2045,7 @@ class Q(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -2184,7 +2184,7 @@ class Rp(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -2323,7 +2323,7 @@ class Rt(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -2462,7 +2462,7 @@ class Ruby(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -2601,7 +2601,7 @@ class S(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -2740,7 +2740,7 @@ class Samp(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -2879,7 +2879,7 @@ class Small(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -3018,7 +3018,7 @@ class Span(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -3157,7 +3157,7 @@ class Strong(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -3296,7 +3296,7 @@ class Sub(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -3435,7 +3435,7 @@ class Sup(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -3577,7 +3577,7 @@ class Time(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -3716,7 +3716,7 @@ class U(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -3855,7 +3855,7 @@ class Wbr(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 14 - 14
reflex/components/el/elements/media.pyi

@@ -90,7 +90,7 @@ class Area(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -260,7 +260,7 @@ class Audio(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -448,7 +448,7 @@ class Img(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -603,7 +603,7 @@ class Map(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -754,7 +754,7 @@ class Track(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -930,7 +930,7 @@ class Video(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1089,7 +1089,7 @@ class Embed(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1259,7 +1259,7 @@ class Iframe(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1425,7 +1425,7 @@ class Object(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1572,7 +1572,7 @@ class Picture(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1711,7 +1711,7 @@ class Portal(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1861,7 +1861,7 @@ class Source(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -2011,7 +2011,7 @@ class Svg(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -2153,7 +2153,7 @@ class Path(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 5 - 5
reflex/components/el/elements/metadata.pyi

@@ -70,7 +70,7 @@ class Base(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -209,7 +209,7 @@ class Head(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -369,7 +369,7 @@ class Link(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -518,7 +518,7 @@ class Meta(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -614,7 +614,7 @@ class Title(Element):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 7 - 7
reflex/components/el/elements/other.pyi

@@ -66,7 +66,7 @@ class Details(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -207,7 +207,7 @@ class Dialog(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -347,7 +347,7 @@ class Summary(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -486,7 +486,7 @@ class Slot(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -625,7 +625,7 @@ class Template(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -764,7 +764,7 @@ class Math(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -906,7 +906,7 @@ class Html(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 3 - 3
reflex/components/el/elements/scripts.pyi

@@ -71,7 +71,7 @@ class Canvas(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -212,7 +212,7 @@ class Noscript(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -374,7 +374,7 @@ class Script(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 15 - 15
reflex/components/el/elements/sectioning.pyi

@@ -71,7 +71,7 @@ class Body(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -210,7 +210,7 @@ class Address(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -349,7 +349,7 @@ class Article(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -488,7 +488,7 @@ class Aside(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -627,7 +627,7 @@ class Footer(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -766,7 +766,7 @@ class Header(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -905,7 +905,7 @@ class H1(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1044,7 +1044,7 @@ class H2(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1183,7 +1183,7 @@ class H3(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1322,7 +1322,7 @@ class H4(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1461,7 +1461,7 @@ class H5(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1600,7 +1600,7 @@ class H6(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1739,7 +1739,7 @@ class Main(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1878,7 +1878,7 @@ class Nav(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -2017,7 +2017,7 @@ class Section(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 10 - 10
reflex/components/el/elements/tables.pyi

@@ -68,7 +68,7 @@ class Caption(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -215,7 +215,7 @@ class Col(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -364,7 +364,7 @@ class Colgroup(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -521,7 +521,7 @@ class Table(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -671,7 +671,7 @@ class Tbody(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -830,7 +830,7 @@ class Td(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -981,7 +981,7 @@ class Tfoot(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1143,7 +1143,7 @@ class Th(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1292,7 +1292,7 @@ class Thead(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1438,7 +1438,7 @@ class Tr(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 15 - 15
reflex/components/el/elements/typography.pyi

@@ -66,7 +66,7 @@ class Blockquote(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -206,7 +206,7 @@ class Dd(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -345,7 +345,7 @@ class Div(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -484,7 +484,7 @@ class Dl(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -623,7 +623,7 @@ class Dt(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -762,7 +762,7 @@ class Figcaption(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -907,7 +907,7 @@ class Hr(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1048,7 +1048,7 @@ class Li(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1188,7 +1188,7 @@ class Menu(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1335,7 +1335,7 @@ class Ol(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1477,7 +1477,7 @@ class P(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1616,7 +1616,7 @@ class Pre(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1755,7 +1755,7 @@ class Ul(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1898,7 +1898,7 @@ class Ins(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -2043,7 +2043,7 @@ class Del(BaseHTML):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 4 - 4
reflex/components/feedback/alert.pyi

@@ -41,7 +41,7 @@ class Alert(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -122,7 +122,7 @@ class AlertIcon(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -201,7 +201,7 @@ class AlertTitle(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -280,7 +280,7 @@ class AlertDescription(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 2 - 2
reflex/components/feedback/circularprogress.pyi

@@ -34,7 +34,7 @@ class CircularProgress(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -121,7 +121,7 @@ class CircularProgressLabel(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/feedback/progress.pyi

@@ -29,7 +29,7 @@ class Progress(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 3 - 3
reflex/components/feedback/skeleton.pyi

@@ -26,7 +26,7 @@ class Skeleton(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -115,7 +115,7 @@ class SkeletonCircle(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -205,7 +205,7 @@ class SkeletonText(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/feedback/spinner.pyi

@@ -31,7 +31,7 @@ class Spinner(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 2 - 2
reflex/components/forms/button.pyi

@@ -96,7 +96,7 @@ class Button(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -199,7 +199,7 @@ class ButtonGroup(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/forms/checkbox.py

@@ -51,7 +51,7 @@ class Checkbox(ChakraComponent):
     name: Var[str]
 
     # The value of the input field when checked (use is_checked prop for a bool)
-    value: Var[str] = Var.create(True)  # type: ignore
+    value: Var[str] = Var.create("true")  # type: ignore
 
     # The spacing between the checkbox and its label text (0.5rem)
     spacing: Var[str]

+ 2 - 2
reflex/components/forms/checkbox.pyi

@@ -89,7 +89,7 @@ class Checkbox(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -187,7 +187,7 @@ class CheckboxGroup(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 3 - 3
reflex/components/forms/colormodeswitch.py

@@ -18,7 +18,7 @@ from __future__ import annotations
 
 from typing import Any
 
-from reflex.components.component import Component
+from reflex.components.component import BaseComponent, Component
 from reflex.components.layout.cond import Cond, cond
 from reflex.components.media.icon import Icon
 from reflex.style import color_mode, toggle_color_mode
@@ -55,8 +55,8 @@ class ColorModeIcon(Cond):
     @classmethod
     def create(
         cls,
-        light_component: Component | None = None,
-        dark_component: Component | None = None,
+        light_component: BaseComponent | None = None,
+        dark_component: BaseComponent | None = None,
     ):
         """Create an icon component based on color_mode.
 

+ 6 - 6
reflex/components/forms/colormodeswitch.pyi

@@ -8,7 +8,7 @@ from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.style import Style
 from typing import Any
-from reflex.components.component import Component
+from reflex.components.component import BaseComponent, Component
 from reflex.components.layout.cond import Cond, cond
 from reflex.components.media.icon import Icon
 from reflex.style import color_mode, toggle_color_mode
@@ -29,14 +29,14 @@ class ColorModeIcon(Cond):
         cls,
         *children,
         cond: Optional[Union[Var[Any], Any]] = None,
-        comp1: Optional[Component] = None,
-        comp2: Optional[Component] = None,
+        comp1: Optional[BaseComponent] = None,
+        comp2: Optional[BaseComponent] = None,
         style: Optional[Style] = None,
         key: Optional[Any] = None,
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -164,7 +164,7 @@ class ColorModeSwitch(Switch):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -322,7 +322,7 @@ class ColorModeButton(Button):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/forms/date_picker.pyi

@@ -41,7 +41,7 @@ class DatePicker(Input):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/forms/date_time_picker.pyi

@@ -41,7 +41,7 @@ class DateTimePicker(Input):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 70 - 69
reflex/components/forms/debounce.py

@@ -1,12 +1,11 @@
 """Wrapper around react-debounce-input."""
 from __future__ import annotations
 
-from typing import Any, Set
+from typing import Any, Type
 
 from reflex.components import Component
-from reflex.components.tags import Tag
-from reflex.utils import imports
-from reflex.vars import Var
+from reflex.constants import EventTriggers
+from reflex.vars import Var, VarData
 
 
 class DebounceInput(Component):
@@ -35,95 +34,97 @@ class DebounceInput(Component):
     # If provided, create a fully-controlled input
     value: Var[str]
 
-    def _render(self) -> Tag:
-        """Carry first child props directly on this tag.
+    # The ref to attach to the created input
+    input_ref: Var[str]
+
+    # The element to wrap
+    element: Var[Type[Component]]
+
+    @classmethod
+    def create(cls, *children: Component, **props: Any) -> Component:
+        """Create a DebounceInput component.
+
+        Carry first child props directly on this tag.
 
         Since react-debounce-input wants to create and manage the underlying
         input component itself, we carry all props, events, and styles from
         the child, and then neuter the child's render method so it produces no output.
 
+        Args:
+            children: The child component to wrap.
+            props: The component props.
+
         Returns:
-            The rendered debounce element wrapping the first child element.
+            The DebounceInput component.
 
         Raises:
             RuntimeError: unless exactly one child element is provided.
             ValueError: if the child element does not have an on_change handler.
         """
-        child, props = _collect_first_child_and_props(self)
-        if isinstance(child, type(self)) or len(self.children) > 1:
+        if len(children) != 1:
             raise RuntimeError(
                 "Provide a single child for DebounceInput, such as rx.input() or "
                 "rx.text_area()",
             )
+
+        child = children[0]
         if "on_change" not in child.event_triggers:
             raise ValueError("DebounceInput child requires an on_change handler")
+
+        # Carry known props and event_triggers from the child.
+        props_from_child = {
+            p: getattr(child, p)
+            for p in cls.get_props()
+            if getattr(child, p, None) is not None
+        }
+        props_from_child.update(child.event_triggers)
+        props = {**props_from_child, **props}
+
+        # Carry all other child props directly via custom_attrs
+        other_props = {
+            p: getattr(child, p)
+            for p in child.get_props()
+            if p not in props_from_child and getattr(child, p) is not None
+        }
+        props.setdefault("custom_attrs", {}).update(other_props, **child.custom_attrs)
+
+        # Carry base Component props.
+        props.setdefault("style", {}).update(child.style)
+        if child.class_name is not None:
+            props["class_name"] = f"{props.get('class_name', '')} {child.class_name}"
         child_ref = child.get_ref()
-        if child_ref and not props.get("ref"):
-            props["input_ref"] = Var.create(child_ref, _var_is_local=False)
-        self.children = []
-        tag = super()._render()
-        tag.add_props(
-            **props,
-            **child.event_triggers,
-            sx=child.style,
-            id=child.id,
-            class_name=child.class_name,
-            element=Var.create(
+        if not props.get("input_ref") and child_ref:
+            props["input_ref"] = Var.create_safe(child_ref, _var_is_local=False)
+            props["id"] = child.id
+
+        # Set the child element to wrap, including any imports/hooks from the child.
+        props.setdefault(
+            "element",
+            Var.create_safe(
                 "{%s}" % (child.alias or child.tag),
                 _var_is_local=False,
                 _var_is_string=False,
+            )._replace(
+                _var_type=Type[Component],
+                merge_var_data=VarData(  # type: ignore
+                    imports=child._get_imports(),
+                    hooks=child._get_hooks_internal(),
+                ),
             ),
         )
-        # do NOT render the child, DebounceInput will create it
-        object.__setattr__(child, "render", lambda: "")
-        return tag
-
-    def _get_imports(self) -> imports.ImportDict:
-        return imports.merge_imports(
-            super()._get_imports(), *[c._get_imports() for c in self.children]
-        )
-
-    def _get_hooks_internal(self) -> Set[str]:
-        hooks = super()._get_hooks_internal()
-        for child in self.children:
-            hooks.update(child._get_hooks_internal())
-        return hooks
 
+        return super().create(**props)
 
-def props_not_none(c: Component) -> dict[str, Any]:
-    """Get all properties of the component that are not None.
+    def get_event_triggers(self) -> dict[str, Any]:
+        """Get the event triggers that pass the component's value to the handler.
 
-    Args:
-        c: the component to get_props from
-
-    Returns:
-        dict of all props that are not None.
-    """
-    cdict = {a: getattr(c, a) for a in c.get_props() if getattr(c, a, None) is not None}
-    return cdict
-
-
-def _collect_first_child_and_props(c: Component) -> tuple[Component, dict[str, Any]]:
-    """Recursively find the first child of a different type than `c` with props.
-
-    This function is used to collapse nested DebounceInput components by
-    applying props from each level. Parent props take precedent over child
-    props. The first child component that differs in type will be returned
-    along with all combined parent props seen along the way.
-
-    Args:
-        c: the component to get_props from
+        Returns:
+            A dict mapping the event trigger to the var that is passed to the handler.
+        """
+        return {
+            **super().get_event_triggers(),
+            EventTriggers.ON_CHANGE: lambda e0: [e0.value],
+        }
 
-    Returns:
-        tuple containing the first nested child of a different type and the collected
-        props from each component traversed.
-    """
-    props = props_not_none(c)
-    if not c.children:
-        return c, props
-    child = c.children[0]
-    if not isinstance(child, type(c)):
-        return child, {**props_not_none(child), **props}
-    # carry props from nested DebounceInput components
-    recursive_child, child_props = _collect_first_child_and_props(child)
-    return recursive_child, {**child_props, **props}
+    def _render(self):
+        return super()._render().remove_props("ref")

+ 22 - 23
reflex/components/forms/debounce.pyi

@@ -7,11 +7,10 @@ from typing import Any, Dict, Literal, Optional, Union, overload
 from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.style import Style
-from typing import Any, Set
+from typing import Any, Type
 from reflex.components import Component
-from reflex.components.tags import Tag
-from reflex.utils import imports
-from reflex.vars import Var
+from reflex.constants import EventTriggers
+from reflex.vars import Var, VarData
 
 class DebounceInput(Component):
     @overload
@@ -24,15 +23,20 @@ class DebounceInput(Component):
         force_notify_by_enter: Optional[Union[Var[bool], bool]] = None,
         force_notify_on_blur: Optional[Union[Var[bool], bool]] = None,
         value: Optional[Union[Var[str], str]] = None,
+        input_ref: Optional[Union[Var[str], str]] = None,
+        element: Optional[Union[Var[Type[Component]], Type[Component]]] = None,
         style: Optional[Style] = None,
         key: Optional[Any] = None,
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
+        on_change: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -77,29 +81,24 @@ class DebounceInput(Component):
         ] = None,
         **props
     ) -> "DebounceInput":
-        """Create the component.
+        """Create a DebounceInput component.
+
+        Carry first child props directly on this tag.
+
+        Since react-debounce-input wants to create and manage the underlying
+        input component itself, we carry all props, events, and styles from
+        the child, and then neuter the child's render method so it produces no output.
 
         Args:
-            *children: The children of the component.
-            min_length: Minimum input characters before triggering the on_change event
-            debounce_timeout: Time to wait between end of input and triggering on_change
-            force_notify_by_enter: If true, notify when Enter key is pressed
-            force_notify_on_blur: If true, notify when form control loses focus
-            value: If provided, create a fully-controlled input
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
+            children: The child component to wrap.
+            props: The component props.
 
         Returns:
-            The component.
+            The DebounceInput component.
 
         Raises:
-            TypeError: If an invalid child is passed.
+            RuntimeError: unless exactly one child element is provided.
+            ValueError: if the child element does not have an on_change handler.
         """
         ...
-
-def props_not_none(c: Component) -> dict[str, Any]: ...
+    def get_event_triggers(self) -> dict[str, Any]: ...

+ 4 - 4
reflex/components/forms/editable.pyi

@@ -32,7 +32,7 @@ class Editable(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -131,7 +131,7 @@ class EditableInput(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -210,7 +210,7 @@ class EditableTextarea(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -289,7 +289,7 @@ class EditablePreview(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/forms/editor.pyi

@@ -126,7 +126,7 @@ class Editor(NoSSRComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/forms/email.pyi

@@ -41,7 +41,7 @@ class Email(Input):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 27 - 15
reflex/components/forms/form.py

@@ -1,7 +1,8 @@
 """Form components."""
 from __future__ import annotations
 
-from typing import Any, Dict
+from hashlib import md5
+from typing import Any, Dict, Iterator
 
 from jinja2 import Environment
 
@@ -12,13 +13,12 @@ from reflex.constants import Dirs, EventTriggers
 from reflex.event import EventChain
 from reflex.utils import imports
 from reflex.utils.format import format_event_chain, to_camel_case
-from reflex.utils.serializers import serialize
-from reflex.vars import BaseVar, Var, get_unique_variable_name
+from reflex.vars import BaseVar, Var
 
 FORM_DATA = Var.create("form_data")
 HANDLE_SUBMIT_JS_JINJA2 = Environment().from_string(
     """
-    const handleSubmit{{ handle_submit_unique_name }} = useCallback((ev) => {
+    const handleSubmit_{{ handle_submit_unique_name }} = useCallback((ev) => {
         const $form = ev.target
         ev.preventDefault()
         const {{ form_data }} = {...Object.fromEntries(new FormData($form).entries()), ...{{ field_ref_mapping }}}
@@ -58,9 +58,15 @@ class Form(ChakraComponent):
         Returns:
             The form component.
         """
-        if "handle_submit_unique_name" not in props:
-            props["handle_submit_unique_name"] = get_unique_variable_name()
-        return super().create(*children, **props)
+        if "handle_submit_unique_name" in props:
+            return super().create(*children, **props)
+
+        # Render the form hooks and use the hash of the resulting code to create a unique name.
+        props["handle_submit_unique_name"] = ""
+        form = super().create(*children, **props)
+        code_hash = md5(str(form.get_hooks()).encode("utf-8")).hexdigest()
+        form.handle_submit_unique_name = code_hash
+        return form
 
     def _get_imports(self) -> imports.ImportDict:
         return imports.merge_imports(
@@ -80,7 +86,7 @@ class Form(ChakraComponent):
         return HANDLE_SUBMIT_JS_JINJA2.render(
             handle_submit_unique_name=self.handle_submit_unique_name,
             form_data=FORM_DATA,
-            field_ref_mapping=serialize(self._get_form_refs()),
+            field_ref_mapping=str(Var.create_safe(self._get_form_refs())),
             on_submit_event_chain=format_event_chain(
                 self.event_triggers[EventTriggers.ON_SUBMIT]
             ),
@@ -101,7 +107,7 @@ class Form(ChakraComponent):
             render_tag.add_props(
                 **{
                     EventTriggers.ON_SUBMIT: BaseVar(
-                        _var_name=f"handleSubmit{self.handle_submit_unique_name}",
+                        _var_name=f"handleSubmit_{self.handle_submit_unique_name}",
                         _var_type=EventChain,
                     )
                 }
@@ -115,13 +121,15 @@ class Form(ChakraComponent):
             # when ref start with refs_ it's an array of refs, so we need different method
             # to collect data
             if ref.startswith("refs_"):
-                form_refs[ref[5:-3]] = Var.create(
-                    f"getRefValues({ref[:-3]})", _var_is_local=False
-                )
+                ref_var = Var.create_safe(ref[:-3]).as_ref()
+                form_refs[ref[5:-3]] = Var.create_safe(
+                    f"getRefValues({str(ref_var)})", _var_is_local=False
+                )._replace(merge_var_data=ref_var._var_data)
             else:
-                form_refs[ref[4:]] = Var.create(
-                    f"getRefValue({ref})", _var_is_local=False
-                )
+                ref_var = Var.create_safe(ref).as_ref()
+                form_refs[ref[4:]] = Var.create_safe(
+                    f"getRefValue({str(ref_var)})", _var_is_local=False
+                )._replace(merge_var_data=ref_var._var_data)
         return form_refs
 
     def get_event_triggers(self) -> Dict[str, Any]:
@@ -135,6 +143,10 @@ class Form(ChakraComponent):
             EventTriggers.ON_SUBMIT: lambda e0: [FORM_DATA],
         }
 
+    def _get_vars(self) -> Iterator[Var]:
+        yield from super()._get_vars()
+        yield from self._get_form_refs().values()
+
 
 class FormControl(ChakraComponent):
     """Provide context to form components."""

+ 9 - 9
reflex/components/forms/form.pyi

@@ -7,7 +7,8 @@ from typing import Any, Dict, Literal, Optional, Union, overload
 from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.style import Style
-from typing import Any, Dict
+from hashlib import md5
+from typing import Any, Dict, Iterator
 from jinja2 import Environment
 from reflex.components.component import Component
 from reflex.components.libs.chakra import ChakraComponent
@@ -16,12 +17,11 @@ from reflex.constants import Dirs, EventTriggers
 from reflex.event import EventChain
 from reflex.utils import imports
 from reflex.utils.format import format_event_chain, to_camel_case
-from reflex.utils.serializers import serialize
-from reflex.vars import BaseVar, Var, get_unique_variable_name
+from reflex.vars import BaseVar, Var
 
 FORM_DATA = Var.create("form_data")
 HANDLE_SUBMIT_JS_JINJA2 = Environment().from_string(
-    "\n    const handleSubmit{{ handle_submit_unique_name }} = useCallback((ev) => {\n        const $form = ev.target\n        ev.preventDefault()\n        const {{ form_data }} = {...Object.fromEntries(new FormData($form).entries()), ...{{ field_ref_mapping }}}\n\n        {{ on_submit_event_chain }}\n\n        if ({{ reset_on_submit }}) {\n            $form.reset()\n        }\n    })\n    "
+    "\n    const handleSubmit_{{ handle_submit_unique_name }} = useCallback((ev) => {\n        const $form = ev.target\n        ev.preventDefault()\n        const {{ form_data }} = {...Object.fromEntries(new FormData($form).entries()), ...{{ field_ref_mapping }}}\n\n        {{ on_submit_event_chain }}\n\n        if ({{ reset_on_submit }}) {\n            $form.reset()\n        }\n    })\n    "
 )
 
 class Form(ChakraComponent):
@@ -38,7 +38,7 @@ class Form(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -129,7 +129,7 @@ class FormControl(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -216,7 +216,7 @@ class FormHelperText(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -296,7 +296,7 @@ class FormLabel(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -376,7 +376,7 @@ class FormErrorMessage(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/forms/iconbutton.pyi

@@ -33,7 +33,7 @@ class IconButton(Text):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 6 - 6
reflex/components/forms/input.pyi

@@ -51,7 +51,7 @@ class Input(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -149,7 +149,7 @@ class InputGroup(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -228,7 +228,7 @@ class InputLeftAddon(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -307,7 +307,7 @@ class InputRightAddon(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -386,7 +386,7 @@ class InputLeftElement(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -465,7 +465,7 @@ class InputRightElement(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 5 - 5
reflex/components/forms/numberinput.pyi

@@ -48,7 +48,7 @@ class NumberInput(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -146,7 +146,7 @@ class NumberInputField(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -225,7 +225,7 @@ class NumberInputStepper(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -304,7 +304,7 @@ class NumberIncrementStepper(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -383,7 +383,7 @@ class NumberDecrementStepper(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/forms/password.pyi

@@ -41,7 +41,7 @@ class Password(Input):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 4 - 1
reflex/components/forms/pininput.py

@@ -119,7 +119,10 @@ class PinInput(ChakraComponent):
             )
             refs_declaration._var_is_local = True
             if ref:
-                return f"const {ref} = {str(refs_declaration)}"
+                return (
+                    f"const {ref} = {str(refs_declaration)}; "
+                    f"{str(Var.create_safe(ref).as_ref())} = {ref}"
+                )
             return super()._get_ref_hook()
 
     def _render(self) -> Tag:

+ 2 - 2
reflex/components/forms/pininput.pyi

@@ -49,7 +49,7 @@ class PinInput(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -154,7 +154,7 @@ class PinInputField(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 2 - 2
reflex/components/forms/radio.pyi

@@ -31,7 +31,7 @@ class RadioGroup(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -124,7 +124,7 @@ class Radio(Text):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 4 - 1
reflex/components/forms/rangeslider.py

@@ -78,7 +78,10 @@ class RangeSlider(ChakraComponent):
         if self.id:
             ref = format.format_array_ref(self.id, None)
             if ref:
-                return f"const {ref} = Array.from({{length:2}}, () => useRef(null));"
+                return (
+                    f"const {ref} = Array.from({{length:2}}, () => useRef(null)); "
+                    f"{str(Var.create_safe(ref).as_ref())} = {ref}"
+                )
             return super()._get_ref_hook()
 
     @classmethod

+ 4 - 4
reflex/components/forms/rangeslider.pyi

@@ -40,7 +40,7 @@ class RangeSlider(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -138,7 +138,7 @@ class RangeSliderTrack(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -217,7 +217,7 @@ class RangeSliderFilledTrack(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -298,7 +298,7 @@ class RangeSliderThumb(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 2 - 2
reflex/components/forms/select.pyi

@@ -44,7 +44,7 @@ class Select(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -140,7 +140,7 @@ class Option(Text):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 5 - 5
reflex/components/forms/slider.pyi

@@ -51,7 +51,7 @@ class Slider(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -156,7 +156,7 @@ class SliderTrack(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -235,7 +235,7 @@ class SliderFilledTrack(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -315,7 +315,7 @@ class SliderThumb(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -395,7 +395,7 @@ class SliderMark(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/forms/switch.pyi

@@ -82,7 +82,7 @@ class Switch(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/forms/textarea.pyi

@@ -42,7 +42,7 @@ class TextArea(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 32 - 32
reflex/components/forms/upload.py

@@ -14,6 +14,18 @@ from reflex.vars import BaseVar, CallableVar, Var, VarData
 
 DEFAULT_UPLOAD_ID: str = "default"
 
+upload_files_context_var_data: VarData = VarData(  # type: ignore
+    imports={
+        "react": {imports.ImportVar(tag="useContext")},
+        f"/{Dirs.CONTEXTS_PATH}": {
+            imports.ImportVar(tag="UploadFilesContext"),
+        },
+    },
+    hooks={
+        "const [filesById, setFilesById] = useContext(UploadFilesContext);",
+    },
+)
+
 
 @CallableVar
 def upload_file(id_: str = DEFAULT_UPLOAD_ID) -> BaseVar:
@@ -29,15 +41,9 @@ def upload_file(id_: str = DEFAULT_UPLOAD_ID) -> BaseVar:
         A var referencing the file upload drop trigger.
     """
     return BaseVar(
-        _var_name=f"e => upload_files.{id_}[1]((files) => e)",
+        _var_name=f"e => setFilesById(filesById => ({{...filesById, {id_}: e}}))",
         _var_type=EventChain,
-        _var_data=VarData(  # type: ignore
-            imports={
-                f"/{Dirs.STATE_PATH}": {
-                    imports.ImportVar(tag="upload_files"),
-                },
-            },
-        ),
+        _var_data=upload_files_context_var_data,
     )
 
 
@@ -52,15 +58,9 @@ def selected_files(id_: str = DEFAULT_UPLOAD_ID) -> BaseVar:
         A var referencing the list of selected file paths.
     """
     return BaseVar(
-        _var_name=f"(upload_files.{id_} ? upload_files.{id_}[0]?.map((f) => (f.path || f.name)) : [])",
+        _var_name=f"(filesById.{id_} ? filesById.{id_}.map((f) => (f.path || f.name)) : [])",
         _var_type=List[str],
-        _var_data=VarData(  # type: ignore
-            imports={
-                f"/{Dirs.STATE_PATH}": {
-                    imports.ImportVar(tag="upload_files"),
-                },
-            },
-        ),
+        _var_data=upload_files_context_var_data,
     )
 
 
@@ -74,7 +74,10 @@ def clear_selected_files(id_: str = DEFAULT_UPLOAD_ID) -> EventSpec:
     Returns:
         An event spec that clears the list of selected files when triggered.
     """
-    return call_script(f"upload_files.{id_}[1]((files) => [])")
+    # UploadFilesProvider assigns a special function to clear selected files
+    # into the shared global refs object to make it accessible outside a React
+    # component via `call_script` (otherwise backend could never clear files).
+    return call_script(f"refs['__clear_selected_files']({id_!r})")
 
 
 def cancel_upload(upload_id: str) -> EventSpec:
@@ -89,6 +92,13 @@ def cancel_upload(upload_id: str) -> EventSpec:
     return call_script(f"upload_controllers[{upload_id!r}]?.abort()")
 
 
+class UploadFilesProvider(Component):
+    """AppWrap component that provides a dict of selected files by ID via useContext."""
+
+    library = f"/{Dirs.CONTEXTS_PATH}"
+    tag = "UploadFilesProvider"
+
+
 class Upload(Component):
     """A file upload component."""
 
@@ -179,18 +189,8 @@ class Upload(Component):
         out.args = ("getRootProps", "getInputProps")
         return out
 
-    def _get_hooks(self) -> str | None:
-        return (
-            super()._get_hooks() or ""
-        ) + f"upload_files.{self.id or DEFAULT_UPLOAD_ID} = useState([]);"
-
-    def _get_imports(self) -> imports.ImportDict:
-        return imports.merge_imports(
-            super()._get_imports(),
-            {
-                "react": {imports.ImportVar(tag="useState")},
-                f"/{constants.Dirs.STATE_PATH}": [
-                    imports.ImportVar(tag="upload_files")
-                ],
-            },
-        )
+    @staticmethod
+    def _get_app_wrap_components() -> dict[tuple[int, str], Component]:
+        return {
+            (5, "UploadFilesProvider"): UploadFilesProvider(),
+        }

+ 81 - 1
reflex/components/forms/upload.pyi

@@ -18,6 +18,7 @@ from reflex.utils import imports
 from reflex.vars import BaseVar, CallableVar, Var, VarData
 
 DEFAULT_UPLOAD_ID: str
+upload_files_context_var_data: VarData
 
 @CallableVar
 def upload_file(id_: str = DEFAULT_UPLOAD_ID) -> BaseVar: ...
@@ -27,6 +28,85 @@ def selected_files(id_: str = DEFAULT_UPLOAD_ID) -> BaseVar: ...
 def clear_selected_files(id_: str = DEFAULT_UPLOAD_ID) -> EventSpec: ...
 def cancel_upload(upload_id: str) -> EventSpec: ...
 
+class UploadFilesProvider(Component):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "UploadFilesProvider":
+        """Create the component.
+
+        Args:
+            *children: The children of the component.
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The props of the component.
+
+        Returns:
+            The component.
+
+        Raises:
+            TypeError: If an invalid child is passed.
+        """
+        ...
+
 class Upload(Component):
     @overload
     @classmethod
@@ -49,7 +129,7 @@ class Upload(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 2 - 2
reflex/components/graphing/plotly.pyi

@@ -29,7 +29,7 @@ class PlotlyLib(NoSSRComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -113,7 +113,7 @@ class Plotly(PlotlyLib):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 25 - 25
reflex/components/graphing/recharts/cartesian.pyi

@@ -95,7 +95,7 @@ class Axis(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -218,7 +218,7 @@ class XAxis(Axis):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -341,7 +341,7 @@ class YAxis(Axis):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -451,7 +451,7 @@ class ZAxis(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -547,7 +547,7 @@ class Brush(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_change: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -605,7 +605,7 @@ class Cartesian(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -634,7 +634,7 @@ class Cartesian(Recharts):
             data_key: The key of a group of data which should be unique in an area chart.
             x_axis_id: The id of x-axis which is corresponding to the data.
             y_axis_id: The id of y-axis which is corresponding to the data.
-            style: The style of the component.
+            style: The type of icon in legend. If set to 'none', no legend item will be rendered. 'line' | 'plainline' | 'square' | 'rect'| 'circle' | 'cross' | 'diamond' | 'star' | 'triangle' | 'wye' | 'none'optional  legend_type: Var[LiteralLegendType]  The style of the component.
             key: A unique key for the component.
             id: The id for the component.
             class_name: The class name for the component.
@@ -717,7 +717,7 @@ class Area(Cartesian):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -754,7 +754,7 @@ class Area(Cartesian):
             data_key: The key of a group of data which should be unique in an area chart.
             x_axis_id: The id of x-axis which is corresponding to the data.
             y_axis_id: The id of y-axis which is corresponding to the data.
-            style: The style of the component.
+            style: The type of icon in legend. If set to 'none', no legend item will be rendered. 'line' | 'plainline' | 'square' | 'rect'| 'circle' | 'cross' | 'diamond' | 'star' | 'triangle' | 'wye' | 'none'optional  legend_type: Var[LiteralLegendType]  The style of the component.
             key: A unique key for the component.
             id: The id for the component.
             class_name: The class name for the component.
@@ -798,7 +798,7 @@ class Bar(Cartesian):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -835,7 +835,7 @@ class Bar(Cartesian):
             data_key: The key of a group of data which should be unique in an area chart.
             x_axis_id: The id of x-axis which is corresponding to the data.
             y_axis_id: The id of y-axis which is corresponding to the data.
-            style: The style of the component.
+            style: The type of icon in legend. If set to 'none', no legend item will be rendered. 'line' | 'plainline' | 'square' | 'rect'| 'circle' | 'cross' | 'diamond' | 'star' | 'triangle' | 'wye' | 'none'optional  legend_type: Var[LiteralLegendType]  The style of the component.
             key: A unique key for the component.
             id: The id for the component.
             class_name: The class name for the component.
@@ -918,7 +918,7 @@ class Line(Cartesian):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -955,7 +955,7 @@ class Line(Cartesian):
             data_key: The key of a group of data which should be unique in an area chart.
             x_axis_id: The id of x-axis which is corresponding to the data.
             y_axis_id: The id of y-axis which is corresponding to the data.
-            style: The style of the component.
+            style: The type of icon in legend. If set to 'none', no legend item will be rendered. 'line' | 'plainline' | 'square' | 'rect'| 'circle' | 'cross' | 'diamond' | 'star' | 'triangle' | 'wye' | 'none'optional  legend_type: Var[LiteralLegendType]  The style of the component.
             key: A unique key for the component.
             id: The id for the component.
             class_name: The class name for the component.
@@ -1017,7 +1017,7 @@ class Scatter(Cartesian):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1053,7 +1053,7 @@ class Scatter(Cartesian):
             data_key: The key of a group of data which should be unique in an area chart.
             x_axis_id: The id of x-axis which is corresponding to the data.
             y_axis_id: The id of y-axis which is corresponding to the data.
-            style: The style of the component.
+            style: The type of icon in legend. If set to 'none', no legend item will be rendered. 'line' | 'plainline' | 'square' | 'rect'| 'circle' | 'cross' | 'diamond' | 'star' | 'triangle' | 'wye' | 'none'optional  legend_type: Var[LiteralLegendType]  The style of the component.
             key: A unique key for the component.
             id: The id for the component.
             class_name: The class name for the component.
@@ -1098,7 +1098,7 @@ class Funnel(Cartesian):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1131,7 +1131,7 @@ class Funnel(Cartesian):
             data_key: The key of a group of data which should be unique in an area chart.
             x_axis_id: The id of x-axis which is corresponding to the data.
             y_axis_id: The id of y-axis which is corresponding to the data.
-            style: The style of the component.
+            style: The type of icon in legend. If set to 'none', no legend item will be rendered. 'line' | 'plainline' | 'square' | 'rect'| 'circle' | 'cross' | 'diamond' | 'star' | 'triangle' | 'wye' | 'none'optional  legend_type: Var[LiteralLegendType]  The style of the component.
             key: A unique key for the component.
             id: The id for the component.
             class_name: The class name for the component.
@@ -1165,7 +1165,7 @@ class ErrorBar(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1260,7 +1260,7 @@ class Reference(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1357,7 +1357,7 @@ class ReferenceLine(Reference):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1455,7 +1455,7 @@ class ReferenceDot(Reference):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1529,7 +1529,7 @@ class ReferenceArea(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1623,7 +1623,7 @@ class Grid(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1715,7 +1715,7 @@ class CartesianGrid(Grid):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -1826,7 +1826,7 @@ class CartesianAxis(Grid):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 11 - 11
reflex/components/graphing/recharts/charts.pyi

@@ -53,7 +53,7 @@ class ChartBase(RechartsCharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -130,7 +130,7 @@ class AreaChart(ChartBase):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -207,7 +207,7 @@ class BarChart(ChartBase):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -283,7 +283,7 @@ class LineChart(ChartBase):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -364,7 +364,7 @@ class ComposedChart(ChartBase):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -441,7 +441,7 @@ class PieChart(ChartBase):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -516,7 +516,7 @@ class RadarChart(ChartBase):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -603,7 +603,7 @@ class RadialBarChart(ChartBase):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -684,7 +684,7 @@ class ScatterChart(ChartBase):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -755,7 +755,7 @@ class FunnelChart(RechartsCharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -823,7 +823,7 @@ class Treemap(RechartsCharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 5 - 5
reflex/components/graphing/recharts/general.pyi

@@ -36,7 +36,7 @@ class ResponsiveContainer(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -176,7 +176,7 @@ class Legend(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -246,7 +246,7 @@ class GraphingTooltip(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -382,7 +382,7 @@ class Label(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -515,7 +515,7 @@ class LabelList(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 6 - 6
reflex/components/graphing/recharts/polar.pyi

@@ -46,7 +46,7 @@ class Pie(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -130,7 +130,7 @@ class Radar(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -226,7 +226,7 @@ class RadialBar(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -299,7 +299,7 @@ class PolarAngleAxis(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -371,7 +371,7 @@ class PolarGrid(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -512,7 +512,7 @@ class PolarRadiusAxis(Recharts):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_click: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 2 - 2
reflex/components/graphing/recharts/recharts.pyi

@@ -21,7 +21,7 @@ class Recharts(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -100,7 +100,7 @@ class RechartsCharts(NoSSRComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/layout/aspect_ratio.pyi

@@ -22,7 +22,7 @@ class AspectRatio(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/layout/box.pyi

@@ -25,7 +25,7 @@ class Box(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 4 - 4
reflex/components/layout/card.pyi

@@ -28,7 +28,7 @@ class CardHeader(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -107,7 +107,7 @@ class CardBody(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -186,7 +186,7 @@ class CardFooter(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -327,7 +327,7 @@ class Card(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 3 - 3
reflex/components/layout/center.pyi

@@ -20,7 +20,7 @@ class Center(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -99,7 +99,7 @@ class Square(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -178,7 +178,7 @@ class Circle(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 8 - 8
reflex/components/layout/cond.py

@@ -3,7 +3,7 @@ from __future__ import annotations
 
 from typing import Any, Dict, Optional, overload
 
-from reflex.components.component import Component
+from reflex.components.component import BaseComponent, Component
 from reflex.components.layout.fragment import Fragment
 from reflex.components.tags import CondTag, Tag
 from reflex.constants import Dirs
@@ -22,17 +22,17 @@ class Cond(Component):
     cond: Var[Any]
 
     # The component to render if the cond is true.
-    comp1: Component = Fragment.create()
+    comp1: BaseComponent = Fragment.create()
 
     # The component to render if the cond is false.
-    comp2: Component = Fragment.create()
+    comp2: BaseComponent = Fragment.create()
 
     @classmethod
     def create(
         cls,
         cond: Var,
-        comp1: Component,
-        comp2: Optional[Component] = None,
+        comp1: BaseComponent,
+        comp2: Optional[BaseComponent] = None,
     ) -> Component:
         """Create a conditional component.
 
@@ -141,9 +141,9 @@ def cond(condition: Any, c1: Any, c2: Any = None):
     assert cond_var is not None, "The condition must be set."
 
     # If the first component is a component, create a Cond component.
-    if isinstance(c1, Component):
+    if isinstance(c1, BaseComponent):
         assert c2 is None or isinstance(
-            c2, Component
+            c2, BaseComponent
         ), "Both arguments must be components."
         return Cond.create(cond_var, c1, c2)
     if isinstance(c1, Var):
@@ -151,7 +151,7 @@ def cond(condition: Any, c1: Any, c2: Any = None):
 
     # Otherwise, create a conditional Var.
     # Check that the second argument is valid.
-    if isinstance(c2, Component):
+    if isinstance(c2, BaseComponent):
         raise ValueError("Both arguments must be props.")
     if c2 is None:
         raise ValueError("For conditional vars, the second argument must be set.")

+ 1 - 1
reflex/components/layout/container.pyi

@@ -22,7 +22,7 @@ class Container(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/layout/flex.pyi

@@ -31,7 +31,7 @@ class Flex(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 30 - 32
reflex/components/layout/foreach.py

@@ -1,13 +1,14 @@
 """Create a list of components from an iterable."""
 from __future__ import annotations
 
-import typing
+import inspect
+from hashlib import md5
 from typing import Any, Callable, Iterable
 
 from reflex.components.component import Component
 from reflex.components.layout.fragment import Fragment
 from reflex.components.tags import IterTag
-from reflex.vars import BaseVar, Var, get_unique_variable_name
+from reflex.vars import Var
 
 
 class Foreach(Component):
@@ -34,33 +35,43 @@ class Foreach(Component):
         Raises:
             TypeError: If the iterable is of type Any.
         """
-        try:
-            type_ = (
-                iterable._var_type
-                if iterable._var_type.mro()[0] == dict
-                else iterable._var_type.__args__[0]
-            )
-        except Exception:
-            type_ = Any
         iterable = Var.create(iterable)  # type: ignore
         if iterable._var_type == Any:
             raise TypeError(
                 f"Could not foreach over var of type Any. (If you are trying to foreach over a state var, add a type annotation to the var.)"
             )
-        arg = BaseVar(_var_name="_", _var_type=type_, _var_is_local=True)
-        comp = IterTag(iterable=iterable, render_fn=render_fn).render_component(arg)
-        return cls(
+        component = cls(
             iterable=iterable,
             render_fn=render_fn,
-            children=[comp],
             **props,
         )
+        # Keep a ref to a rendered component to determine correct imports.
+        component.children = [
+            component._render(props=dict(index_var_name="i")).render_component()
+        ]
+        return component
+
+    def _render(self, props: dict[str, Any] | None = None) -> IterTag:
+        props = {} if props is None else props.copy()
+
+        # Determine the arg var name based on the params accepted by render_fn.
+        render_sig = inspect.signature(self.render_fn)
+        params = list(render_sig.parameters.values())
+        if len(params) >= 1:
+            props.setdefault("arg_var_name", params[0].name)
+
+        if len(params) >= 2:
+            # Determine the index var name based on the params accepted by render_fn.
+            props.setdefault("index_var_name", params[1].name)
+        elif "index_var_name" not in props:
+            # Otherwise, use a deterministic index, based on the rendered code.
+            code_hash = md5(str(self.children[0].render()).encode("utf-8")).hexdigest()
+            props.setdefault("index_var_name", f"index_{code_hash}")
 
-    def _render(self) -> IterTag:
         return IterTag(
             iterable=self.iterable,
             render_fn=self.render_fn,
-            index_var_name=get_unique_variable_name(),
+            **props,
         )
 
     def render(self):
@@ -70,20 +81,7 @@ class Foreach(Component):
             The dictionary for template of component.
         """
         tag = self._render()
-        try:
-            type_ = (
-                tag.iterable._var_type
-                if tag.iterable._var_type.mro()[0] == dict
-                else typing.get_args(tag.iterable._var_type)[0]
-            )
-        except Exception:
-            type_ = Any
-        arg = BaseVar(
-            _var_name=get_unique_variable_name(),
-            _var_type=type_,
-        )
-        index_arg = tag.get_index_var_arg()
-        component = tag.render_component(arg)
+        component = tag.render_component()
         return dict(
             tag.add_props(
                 **self.event_triggers,
@@ -96,7 +94,7 @@ class Foreach(Component):
                 props=tag.format_props(),
             ),
             iterable_state=tag.iterable._var_full_name,
-            arg_name=arg._var_name,
-            arg_index=index_arg,
+            arg_name=tag.arg_var_name,
+            arg_index=tag.get_index_var_arg(),
             iterable_type=tag.iterable._var_type.mro()[0].__name__,
         )

+ 1 - 1
reflex/components/layout/fragment.pyi

@@ -20,7 +20,7 @@ class Fragment(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 3 - 3
reflex/components/layout/grid.pyi

@@ -29,7 +29,7 @@ class Grid(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -122,7 +122,7 @@ class GridItem(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -221,7 +221,7 @@ class ResponsiveGrid(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/layout/html.pyi

@@ -28,7 +28,7 @@ class Html(Box):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/layout/spacer.pyi

@@ -20,7 +20,7 @@ class Spacer(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 3 - 3
reflex/components/layout/stack.pyi

@@ -35,7 +35,7 @@ class Stack(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -135,7 +135,7 @@ class Hstack(Stack):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -235,7 +235,7 @@ class Vstack(Stack):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 2 - 2
reflex/components/layout/wrap.pyi

@@ -30,7 +30,7 @@ class Wrap(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -114,7 +114,7 @@ class WrapItem(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 4 - 4
reflex/components/libs/chakra.pyi

@@ -24,7 +24,7 @@ class ChakraComponent(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -104,7 +104,7 @@ class Global(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -184,7 +184,7 @@ class ChakraProvider(ChakraComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,
@@ -252,7 +252,7 @@ class ChakraColorModeProvider(Component):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/libs/react_player.pyi

@@ -30,7 +30,7 @@ class ReactPlayerComponent(NoSSRComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

+ 1 - 1
reflex/components/media/audio.pyi

@@ -31,7 +31,7 @@ class Audio(ReactPlayerComponent):
         id: Optional[Any] = None,
         class_name: Optional[Any] = None,
         autofocus: Optional[bool] = None,
-        custom_attrs: Optional[Dict[str, str]] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
         on_blur: Optional[
             Union[EventHandler, EventSpec, list, function, BaseVar]
         ] = None,

部分文件因为文件数量过多而无法显示