From 527437cf231eb0134ad2c1e41195a0dd942d73a3 Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Mon, 27 Nov 2023 16:05:59 -0800 Subject: [PATCH] [REF-144] Add context in each component to prevent rerenders (#2198) --- integration/test_var_operations.py | 27 + .../web/pages/stateful_component.js.jinja2 | 15 + .../web/pages/stateful_components.js.jinja2 | 5 + .../jinja/web/utils/context.js.jinja2 | 17 +- reflex/.templates/web/utils/state.js | 7 +- reflex/app.py | 145 +++--- reflex/compiler/compiler.py | 97 +++- reflex/compiler/templates.py | 6 + reflex/compiler/utils.py | 26 +- reflex/components/base/app_wrap.pyi | 2 +- reflex/components/base/body.pyi | 2 +- reflex/components/base/document.pyi | 12 +- reflex/components/base/head.pyi | 4 +- reflex/components/base/link.pyi | 4 +- reflex/components/base/meta.pyi | 8 +- reflex/components/base/script.pyi | 2 +- reflex/components/component.py | 462 +++++++++++++++++- reflex/components/datadisplay/badge.pyi | 2 +- reflex/components/datadisplay/code.pyi | 4 +- reflex/components/datadisplay/dataeditor.pyi | 2 +- reflex/components/datadisplay/datatable.pyi | 4 +- reflex/components/datadisplay/divider.pyi | 2 +- .../components/datadisplay/keyboard_key.pyi | 2 +- reflex/components/datadisplay/list.pyi | 8 +- reflex/components/datadisplay/moment.pyi | 2 +- reflex/components/datadisplay/stat.pyi | 12 +- reflex/components/datadisplay/table.pyi | 18 +- reflex/components/datadisplay/tag.pyi | 10 +- reflex/components/disclosure/accordion.pyi | 10 +- reflex/components/disclosure/tabs.pyi | 10 +- reflex/components/disclosure/transition.pyi | 12 +- .../components/disclosure/visuallyhidden.pyi | 2 +- reflex/components/el/element.pyi | 2 +- reflex/components/el/elements/base.pyi | 2 +- reflex/components/el/elements/forms.pyi | 28 +- reflex/components/el/elements/inline.pyi | 56 +-- reflex/components/el/elements/media.pyi | 28 +- reflex/components/el/elements/metadata.pyi | 10 +- reflex/components/el/elements/other.pyi | 14 +- reflex/components/el/elements/scripts.pyi | 6 +- reflex/components/el/elements/sectioning.pyi | 30 +- reflex/components/el/elements/tables.pyi | 20 +- reflex/components/el/elements/typography.pyi | 30 +- reflex/components/feedback/alert.pyi | 8 +- .../components/feedback/circularprogress.pyi | 4 +- reflex/components/feedback/progress.pyi | 2 +- reflex/components/feedback/skeleton.pyi | 6 +- reflex/components/feedback/spinner.pyi | 2 +- reflex/components/forms/button.pyi | 4 +- reflex/components/forms/checkbox.py | 2 +- reflex/components/forms/checkbox.pyi | 4 +- reflex/components/forms/colormodeswitch.py | 6 +- reflex/components/forms/colormodeswitch.pyi | 12 +- reflex/components/forms/date_picker.pyi | 2 +- reflex/components/forms/date_time_picker.pyi | 2 +- reflex/components/forms/debounce.py | 139 +++--- reflex/components/forms/debounce.pyi | 45 +- reflex/components/forms/editable.pyi | 8 +- reflex/components/forms/editor.pyi | 2 +- reflex/components/forms/email.pyi | 2 +- reflex/components/forms/form.py | 42 +- reflex/components/forms/form.pyi | 18 +- reflex/components/forms/iconbutton.pyi | 2 +- reflex/components/forms/input.pyi | 12 +- reflex/components/forms/numberinput.pyi | 10 +- reflex/components/forms/password.pyi | 2 +- reflex/components/forms/pininput.py | 5 +- reflex/components/forms/pininput.pyi | 4 +- reflex/components/forms/radio.pyi | 4 +- reflex/components/forms/rangeslider.py | 5 +- reflex/components/forms/rangeslider.pyi | 8 +- reflex/components/forms/select.pyi | 4 +- reflex/components/forms/slider.pyi | 10 +- reflex/components/forms/switch.pyi | 2 +- reflex/components/forms/textarea.pyi | 2 +- reflex/components/forms/upload.py | 64 +-- reflex/components/forms/upload.pyi | 82 +++- reflex/components/graphing/plotly.pyi | 4 +- .../graphing/recharts/cartesian.pyi | 50 +- .../components/graphing/recharts/charts.pyi | 22 +- .../components/graphing/recharts/general.pyi | 10 +- reflex/components/graphing/recharts/polar.pyi | 12 +- .../components/graphing/recharts/recharts.pyi | 4 +- reflex/components/layout/aspect_ratio.pyi | 2 +- reflex/components/layout/box.pyi | 2 +- reflex/components/layout/card.pyi | 8 +- reflex/components/layout/center.pyi | 6 +- reflex/components/layout/cond.py | 16 +- reflex/components/layout/container.pyi | 2 +- reflex/components/layout/flex.pyi | 2 +- reflex/components/layout/foreach.py | 62 ++- reflex/components/layout/fragment.pyi | 2 +- reflex/components/layout/grid.pyi | 6 +- reflex/components/layout/html.pyi | 2 +- reflex/components/layout/spacer.pyi | 2 +- reflex/components/layout/stack.pyi | 6 +- reflex/components/layout/wrap.pyi | 4 +- reflex/components/libs/chakra.pyi | 8 +- reflex/components/libs/react_player.pyi | 2 +- reflex/components/media/audio.pyi | 2 +- reflex/components/media/avatar.pyi | 6 +- reflex/components/media/icon.pyi | 4 +- reflex/components/media/image.pyi | 2 +- reflex/components/media/video.pyi | 2 +- reflex/components/navigation/breadcrumb.pyi | 8 +- .../navigation/client_side_routing.pyi | 4 +- reflex/components/navigation/link.pyi | 2 +- reflex/components/navigation/linkoverlay.pyi | 4 +- reflex/components/navigation/nextlink.pyi | 2 +- reflex/components/navigation/stepper.pyi | 18 +- reflex/components/overlay/alertdialog.pyi | 14 +- reflex/components/overlay/banner.pyi | 6 +- reflex/components/overlay/drawer.pyi | 14 +- reflex/components/overlay/menu.pyi | 16 +- reflex/components/overlay/modal.pyi | 14 +- reflex/components/overlay/popover.pyi | 18 +- reflex/components/overlay/tooltip.pyi | 2 +- reflex/components/radix/themes/base.pyi | 10 +- reflex/components/radix/themes/components.pyi | 10 +- reflex/components/radix/themes/layout.pyi | 12 +- reflex/components/radix/themes/typography.pyi | 18 +- reflex/components/tags/iter_tag.py | 55 ++- reflex/components/typography/heading.pyi | 2 +- reflex/components/typography/highlight.pyi | 2 +- reflex/components/typography/markdown.pyi | 2 +- reflex/components/typography/span.pyi | 2 +- reflex/components/typography/text.pyi | 2 +- reflex/constants/compiler.py | 2 + reflex/event.py | 17 +- reflex/style.py | 5 +- reflex/utils/format.py | 4 +- reflex/utils/imports.py | 12 + reflex/utils/serializers.py | 10 +- reflex/vars.py | 48 +- reflex/vars.pyi | 1 + tests/components/forms/test_form.py | 2 +- tests/components/forms/test_uploads.py | 4 +- tests/components/layout/test_foreach.py | 4 +- tests/components/test_component.py | 125 ++++- tests/test_event.py | 10 +- 140 files changed, 1688 insertions(+), 736 deletions(-) create mode 100644 reflex/.templates/jinja/web/pages/stateful_component.js.jinja2 create mode 100644 reflex/.templates/jinja/web/pages/stateful_components.js.jinja2 diff --git a/integration/test_var_operations.py b/integration/test_var_operations.py index 7da9d0bd0..f327b662c 100644 --- a/integration/test_var_operations.py +++ b/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: diff --git a/reflex/.templates/jinja/web/pages/stateful_component.js.jinja2 b/reflex/.templates/jinja/web/pages/stateful_component.js.jinja2 new file mode 100644 index 000000000..8ac952827 --- /dev/null +++ b/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)}} + ) +} diff --git a/reflex/.templates/jinja/web/pages/stateful_components.js.jinja2 b/reflex/.templates/jinja/web/pages/stateful_components.js.jinja2 new file mode 100644 index 000000000..420c7ca5d --- /dev/null +++ b/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 %} diff --git a/reflex/.templates/jinja/web/utils/context.js.jinja2 b/reflex/.templates/jinja/web/utils/context.js.jinja2 index 53d7d4e58..54ca36ff8 100644 --- a/reflex/.templates/jinja/web/utils/context.js.jinja2 +++ b/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 ( + + {children} + + ) +} + export function EventLoopProvider({ children }) { const dispatch = useContext(DispatchContext) const [addEvents, connectError] = useEventLoop( diff --git a/reflex/.templates/web/utils/state.js b/reflex/.templates/web/utils/state.js index 9ae46d3c9..aedce21c0 100644 --- a/reflex/.templates/web/utils/state.js +++ b/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 } }) diff --git a/reflex/app.py b/reflex/app.py index bb72ca529..747919914 100644 --- a/reflex/app.py +++ b/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)) - # 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)) + result_futures = [] - # Get the compiled pages. - compile_results.extend(result.get() for result in page_futures) + def submit_work(fn, *args, **kwargs): + """Submit work to the thread pool and add a callback to mark the task as complete. - # TODO the compile tasks below may also benefit from parallelization too + The Future will be added to the `result_futures` list. - # Compile the custom components. - compile_results.append(compiler.compile_components(custom_components)) + 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) - # 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 all page components. + for route, component in zip(self.pages, page_components): + submit_work( + compiler.compile_page, + route, + component, + self.state, + ) - # Compile the root stylesheet with base styles. - compile_results.append(compiler.compile_root_stylesheet(self.stylesheets)) + # Compile the app wrapper. + app_root = self._app_root(app_wrappers=app_wrappers) + submit_work(compiler.compile_app, app_root) - # Compile the root document. - compile_results.append(compiler.compile_document_root(self.head_components)) + # Compile the custom components. + submit_work(compiler.compile_components, custom_components) - # Compile the theme. - compile_results.append(compiler.compile_theme(style=self.style)) + # Compile the root stylesheet with base styles. + submit_work(compiler.compile_root_stylesheet, self.stylesheets) - # Compile the contexts. - compile_results.append(compiler.compile_contexts(self.state)) + # Compile the root document. + submit_work(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 - ) - compile_results.append(compiler.compile_tailwind(config.tailwind)) + # Compile the theme. + submit_work(compiler.compile_theme, style=self.style) - # Empty the .web pages directory - compiler.purge_web_pages_dir() + # Compile the contexts. + submit_work(compiler.compile_contexts, self.state) - # install frontend packages - self.get_frontend_packages(all_imports) + # 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) - # 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() + # Get imports from AppWrap components. + all_imports.update(app_root.get_imports()) + + # 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()) + + # 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() + + # Avoid flickering when installing frontend packages + progress.stop() + + # 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]: diff --git a/reflex/compiler/compiler.py b/reflex/compiler/compiler.py index 3b9d7db3e..580ac5d3c 100644 --- a/reflex/compiler/compiler.py +++ b/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, ): diff --git a/reflex/compiler/templates.py b/reflex/compiler/templates.py index 57bbb44b8..5099d2884 100644 --- a/reflex/compiler/templates.py +++ b/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 diff --git a/reflex/compiler/utils.py b/reflex/compiler/utils.py index 10a4691a4..074593b4b 100644 --- a/reflex/compiler/utils.py +++ b/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. diff --git a/reflex/components/base/app_wrap.pyi b/reflex/components/base/app_wrap.pyi index 5c319fcb2..cde179f96 100644 --- a/reflex/components/base/app_wrap.pyi +++ b/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, diff --git a/reflex/components/base/body.pyi b/reflex/components/base/body.pyi index 8c61df7f8..7ba105a0d 100644 --- a/reflex/components/base/body.pyi +++ b/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, diff --git a/reflex/components/base/document.pyi b/reflex/components/base/document.pyi index 8bd40820a..f37857b9d 100644 --- a/reflex/components/base/document.pyi +++ b/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, diff --git a/reflex/components/base/head.pyi b/reflex/components/base/head.pyi index c2f8208ff..d5f40a4ea 100644 --- a/reflex/components/base/head.pyi +++ b/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, diff --git a/reflex/components/base/link.pyi b/reflex/components/base/link.pyi index a9a62f755..a7754ae9a 100644 --- a/reflex/components/base/link.pyi +++ b/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, diff --git a/reflex/components/base/meta.pyi b/reflex/components/base/meta.pyi index 00fabe628..61f3e344a 100644 --- a/reflex/components/base/meta.pyi +++ b/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, diff --git a/reflex/components/base/script.pyi b/reflex/components/base/script.pyi index 33e902cd4..3a1e6f582 100644 --- a/reflex/components/base/script.pyi +++ b/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, diff --git a/reflex/components/component.py b/reflex/components/component.py index 448def29b..5e25396b9 100644 --- a/reflex/components/component.py +++ b/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.""" +class BaseComponent(Base, ABC): + """The base class for all Reflex components. + + This is something that can be rendered as a Component via the Reflex compiler. + """ # The children nested within the component. - children: List[Component] = [] - - # The style of the component. - style: Style = Style() - - # A mapping from event triggers to event chains. - event_triggers: Dict[str, Union[EventChain, Var]] = {} + 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 diff --git a/reflex/components/datadisplay/badge.pyi b/reflex/components/datadisplay/badge.pyi index bb5539055..2c22630f5 100644 --- a/reflex/components/datadisplay/badge.pyi +++ b/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, diff --git a/reflex/components/datadisplay/code.pyi b/reflex/components/datadisplay/code.pyi index 5a88faeb3..797d30958 100644 --- a/reflex/components/datadisplay/code.pyi +++ b/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, diff --git a/reflex/components/datadisplay/dataeditor.pyi b/reflex/components/datadisplay/dataeditor.pyi index af209f422..fcc299926 100644 --- a/reflex/components/datadisplay/dataeditor.pyi +++ b/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, diff --git a/reflex/components/datadisplay/datatable.pyi b/reflex/components/datadisplay/datatable.pyi index 49e3ad752..bca394cd0 100644 --- a/reflex/components/datadisplay/datatable.pyi +++ b/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, diff --git a/reflex/components/datadisplay/divider.pyi b/reflex/components/datadisplay/divider.pyi index 5bd3dc52a..a2dfcb98f 100644 --- a/reflex/components/datadisplay/divider.pyi +++ b/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, diff --git a/reflex/components/datadisplay/keyboard_key.pyi b/reflex/components/datadisplay/keyboard_key.pyi index 6c553c525..69441c0c0 100644 --- a/reflex/components/datadisplay/keyboard_key.pyi +++ b/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, diff --git a/reflex/components/datadisplay/list.pyi b/reflex/components/datadisplay/list.pyi index b0a58028f..c7d7f6703 100644 --- a/reflex/components/datadisplay/list.pyi +++ b/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, diff --git a/reflex/components/datadisplay/moment.pyi b/reflex/components/datadisplay/moment.pyi index f06545861..0d19ff4ae 100644 --- a/reflex/components/datadisplay/moment.pyi +++ b/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, diff --git a/reflex/components/datadisplay/stat.pyi b/reflex/components/datadisplay/stat.pyi index 419384b6c..b70e8d5a6 100644 --- a/reflex/components/datadisplay/stat.pyi +++ b/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, diff --git a/reflex/components/datadisplay/table.pyi b/reflex/components/datadisplay/table.pyi index a41d44a5f..8b9093802 100644 --- a/reflex/components/datadisplay/table.pyi +++ b/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, diff --git a/reflex/components/datadisplay/tag.pyi b/reflex/components/datadisplay/tag.pyi index 78059c06f..8593afc3f 100644 --- a/reflex/components/datadisplay/tag.pyi +++ b/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, diff --git a/reflex/components/disclosure/accordion.pyi b/reflex/components/disclosure/accordion.pyi index e754ce4bc..f10c7a78b 100644 --- a/reflex/components/disclosure/accordion.pyi +++ b/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, diff --git a/reflex/components/disclosure/tabs.pyi b/reflex/components/disclosure/tabs.pyi index 3ca50fe7b..71c903cd8 100644 --- a/reflex/components/disclosure/tabs.pyi +++ b/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, diff --git a/reflex/components/disclosure/transition.pyi b/reflex/components/disclosure/transition.pyi index 1529a5f50..ad330bfda 100644 --- a/reflex/components/disclosure/transition.pyi +++ b/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, diff --git a/reflex/components/disclosure/visuallyhidden.pyi b/reflex/components/disclosure/visuallyhidden.pyi index c0a41f30b..396c6b481 100644 --- a/reflex/components/disclosure/visuallyhidden.pyi +++ b/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, diff --git a/reflex/components/el/element.pyi b/reflex/components/el/element.pyi index 33546a9fe..36f534ede 100644 --- a/reflex/components/el/element.pyi +++ b/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, diff --git a/reflex/components/el/elements/base.pyi b/reflex/components/el/elements/base.pyi index 3a9c023b0..8f2616f23 100644 --- a/reflex/components/el/elements/base.pyi +++ b/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, diff --git a/reflex/components/el/elements/forms.pyi b/reflex/components/el/elements/forms.pyi index 158f15adb..af4885be2 100644 --- a/reflex/components/el/elements/forms.pyi +++ b/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, diff --git a/reflex/components/el/elements/inline.pyi b/reflex/components/el/elements/inline.pyi index f8b6b2bc0..ba158068d 100644 --- a/reflex/components/el/elements/inline.pyi +++ b/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, diff --git a/reflex/components/el/elements/media.pyi b/reflex/components/el/elements/media.pyi index 76f9e26ec..6a5fa25b2 100644 --- a/reflex/components/el/elements/media.pyi +++ b/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, diff --git a/reflex/components/el/elements/metadata.pyi b/reflex/components/el/elements/metadata.pyi index dc0aad081..e50f1b153 100644 --- a/reflex/components/el/elements/metadata.pyi +++ b/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, diff --git a/reflex/components/el/elements/other.pyi b/reflex/components/el/elements/other.pyi index 1b65df2dd..2fd7fd05b 100644 --- a/reflex/components/el/elements/other.pyi +++ b/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, diff --git a/reflex/components/el/elements/scripts.pyi b/reflex/components/el/elements/scripts.pyi index 97e1bf295..f04699215 100644 --- a/reflex/components/el/elements/scripts.pyi +++ b/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, diff --git a/reflex/components/el/elements/sectioning.pyi b/reflex/components/el/elements/sectioning.pyi index e3d79012e..ff9ad49ae 100644 --- a/reflex/components/el/elements/sectioning.pyi +++ b/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, diff --git a/reflex/components/el/elements/tables.pyi b/reflex/components/el/elements/tables.pyi index 14ec2607d..7823fd851 100644 --- a/reflex/components/el/elements/tables.pyi +++ b/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, diff --git a/reflex/components/el/elements/typography.pyi b/reflex/components/el/elements/typography.pyi index b8ba0ca02..55c665ad5 100644 --- a/reflex/components/el/elements/typography.pyi +++ b/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, diff --git a/reflex/components/feedback/alert.pyi b/reflex/components/feedback/alert.pyi index 325c64eed..98bf48664 100644 --- a/reflex/components/feedback/alert.pyi +++ b/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, diff --git a/reflex/components/feedback/circularprogress.pyi b/reflex/components/feedback/circularprogress.pyi index a59bb7533..429c0367a 100644 --- a/reflex/components/feedback/circularprogress.pyi +++ b/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, diff --git a/reflex/components/feedback/progress.pyi b/reflex/components/feedback/progress.pyi index a6b33a648..044ccab71 100644 --- a/reflex/components/feedback/progress.pyi +++ b/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, diff --git a/reflex/components/feedback/skeleton.pyi b/reflex/components/feedback/skeleton.pyi index 288bf8122..5374c7c1f 100644 --- a/reflex/components/feedback/skeleton.pyi +++ b/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, diff --git a/reflex/components/feedback/spinner.pyi b/reflex/components/feedback/spinner.pyi index ba492ab2a..760851f17 100644 --- a/reflex/components/feedback/spinner.pyi +++ b/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, diff --git a/reflex/components/forms/button.pyi b/reflex/components/forms/button.pyi index 9e11204ef..1a9f97600 100644 --- a/reflex/components/forms/button.pyi +++ b/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, diff --git a/reflex/components/forms/checkbox.py b/reflex/components/forms/checkbox.py index 51bf37a49..3f0c5d327 100644 --- a/reflex/components/forms/checkbox.py +++ b/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] diff --git a/reflex/components/forms/checkbox.pyi b/reflex/components/forms/checkbox.pyi index efc04a9b6..84009769d 100644 --- a/reflex/components/forms/checkbox.pyi +++ b/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, diff --git a/reflex/components/forms/colormodeswitch.py b/reflex/components/forms/colormodeswitch.py index ca071a2a7..443e680f9 100644 --- a/reflex/components/forms/colormodeswitch.py +++ b/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. diff --git a/reflex/components/forms/colormodeswitch.pyi b/reflex/components/forms/colormodeswitch.pyi index 83af8f20c..2b64eb067 100644 --- a/reflex/components/forms/colormodeswitch.pyi +++ b/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, diff --git a/reflex/components/forms/date_picker.pyi b/reflex/components/forms/date_picker.pyi index 7fa84b5e3..537c349d1 100644 --- a/reflex/components/forms/date_picker.pyi +++ b/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, diff --git a/reflex/components/forms/date_time_picker.pyi b/reflex/components/forms/date_time_picker.pyi index fa64038d0..4aa99df83 100644 --- a/reflex/components/forms/date_time_picker.pyi +++ b/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, diff --git a/reflex/components/forms/debounce.py b/reflex/components/forms/debounce.py index 1618d29ba..1d74f5687 100644 --- a/reflex/components/forms/debounce.py +++ b/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] - ) + return super().create(**props) - 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 + def get_event_triggers(self) -> dict[str, Any]: + """Get the event triggers that pass the component's value to the handler. + 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], + } -def props_not_none(c: Component) -> dict[str, Any]: - """Get all properties of the component that are not None. - - 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: - 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") diff --git a/reflex/components/forms/debounce.pyi b/reflex/components/forms/debounce.pyi index 975aa8be2..5fed96e4d 100644 --- a/reflex/components/forms/debounce.pyi +++ b/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]: ... diff --git a/reflex/components/forms/editable.pyi b/reflex/components/forms/editable.pyi index 3ff0f7fa0..bfef91b3b 100644 --- a/reflex/components/forms/editable.pyi +++ b/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, diff --git a/reflex/components/forms/editor.pyi b/reflex/components/forms/editor.pyi index 1eaeea038..2dfbc78cd 100644 --- a/reflex/components/forms/editor.pyi +++ b/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, diff --git a/reflex/components/forms/email.pyi b/reflex/components/forms/email.pyi index c72589e3d..d15a09181 100644 --- a/reflex/components/forms/email.pyi +++ b/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, diff --git a/reflex/components/forms/form.py b/reflex/components/forms/form.py index 301fec8e0..cf4124a49 100644 --- a/reflex/components/forms/form.py +++ b/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.""" diff --git a/reflex/components/forms/form.pyi b/reflex/components/forms/form.pyi index e1a9c325a..5af7df927 100644 --- a/reflex/components/forms/form.pyi +++ b/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, diff --git a/reflex/components/forms/iconbutton.pyi b/reflex/components/forms/iconbutton.pyi index 4e452b6f5..1e2f20203 100644 --- a/reflex/components/forms/iconbutton.pyi +++ b/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, diff --git a/reflex/components/forms/input.pyi b/reflex/components/forms/input.pyi index d49a6a6df..e9e16e295 100644 --- a/reflex/components/forms/input.pyi +++ b/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, diff --git a/reflex/components/forms/numberinput.pyi b/reflex/components/forms/numberinput.pyi index 545b65d8e..4f099992b 100644 --- a/reflex/components/forms/numberinput.pyi +++ b/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, diff --git a/reflex/components/forms/password.pyi b/reflex/components/forms/password.pyi index 60b7206e4..334e9f1a9 100644 --- a/reflex/components/forms/password.pyi +++ b/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, diff --git a/reflex/components/forms/pininput.py b/reflex/components/forms/pininput.py index 83323c25c..35e27f6f9 100644 --- a/reflex/components/forms/pininput.py +++ b/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: diff --git a/reflex/components/forms/pininput.pyi b/reflex/components/forms/pininput.pyi index b22ebdf3f..9aa24d22a 100644 --- a/reflex/components/forms/pininput.pyi +++ b/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, diff --git a/reflex/components/forms/radio.pyi b/reflex/components/forms/radio.pyi index dd6e57ac2..dd1ab7eea 100644 --- a/reflex/components/forms/radio.pyi +++ b/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, diff --git a/reflex/components/forms/rangeslider.py b/reflex/components/forms/rangeslider.py index 6eb0b688c..44f600bab 100644 --- a/reflex/components/forms/rangeslider.py +++ b/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 diff --git a/reflex/components/forms/rangeslider.pyi b/reflex/components/forms/rangeslider.pyi index 0a2721327..c19d8d902 100644 --- a/reflex/components/forms/rangeslider.pyi +++ b/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, diff --git a/reflex/components/forms/select.pyi b/reflex/components/forms/select.pyi index 5596e6a7a..33148dfe7 100644 --- a/reflex/components/forms/select.pyi +++ b/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, diff --git a/reflex/components/forms/slider.pyi b/reflex/components/forms/slider.pyi index 6799f3a9a..3304d6850 100644 --- a/reflex/components/forms/slider.pyi +++ b/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, diff --git a/reflex/components/forms/switch.pyi b/reflex/components/forms/switch.pyi index 34f8289de..d1bd61cc7 100644 --- a/reflex/components/forms/switch.pyi +++ b/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, diff --git a/reflex/components/forms/textarea.pyi b/reflex/components/forms/textarea.pyi index bc593d6f1..4f3844e78 100644 --- a/reflex/components/forms/textarea.pyi +++ b/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, diff --git a/reflex/components/forms/upload.py b/reflex/components/forms/upload.py index b79e0b106..ed644ed4e 100644 --- a/reflex/components/forms/upload.py +++ b/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(), + } diff --git a/reflex/components/forms/upload.pyi b/reflex/components/forms/upload.pyi index 5486ee90d..6ab052af8 100644 --- a/reflex/components/forms/upload.pyi +++ b/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, diff --git a/reflex/components/graphing/plotly.pyi b/reflex/components/graphing/plotly.pyi index 14ac271b6..c270674a9 100644 --- a/reflex/components/graphing/plotly.pyi +++ b/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, diff --git a/reflex/components/graphing/recharts/cartesian.pyi b/reflex/components/graphing/recharts/cartesian.pyi index bd11f5ab6..dacae8971 100644 --- a/reflex/components/graphing/recharts/cartesian.pyi +++ b/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, diff --git a/reflex/components/graphing/recharts/charts.pyi b/reflex/components/graphing/recharts/charts.pyi index afdb77f56..80cdf4af7 100644 --- a/reflex/components/graphing/recharts/charts.pyi +++ b/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, diff --git a/reflex/components/graphing/recharts/general.pyi b/reflex/components/graphing/recharts/general.pyi index f0aed07f5..dc1570225 100644 --- a/reflex/components/graphing/recharts/general.pyi +++ b/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, diff --git a/reflex/components/graphing/recharts/polar.pyi b/reflex/components/graphing/recharts/polar.pyi index b4c38d92e..8d9d45295 100644 --- a/reflex/components/graphing/recharts/polar.pyi +++ b/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, diff --git a/reflex/components/graphing/recharts/recharts.pyi b/reflex/components/graphing/recharts/recharts.pyi index eaeee39ca..7c8092be1 100644 --- a/reflex/components/graphing/recharts/recharts.pyi +++ b/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, diff --git a/reflex/components/layout/aspect_ratio.pyi b/reflex/components/layout/aspect_ratio.pyi index d131f9474..b8203467c 100644 --- a/reflex/components/layout/aspect_ratio.pyi +++ b/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, diff --git a/reflex/components/layout/box.pyi b/reflex/components/layout/box.pyi index 98a50b5c7..d2b7a9c7b 100644 --- a/reflex/components/layout/box.pyi +++ b/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, diff --git a/reflex/components/layout/card.pyi b/reflex/components/layout/card.pyi index e39b4de81..e8532894c 100644 --- a/reflex/components/layout/card.pyi +++ b/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, diff --git a/reflex/components/layout/center.pyi b/reflex/components/layout/center.pyi index c9d2b7c10..e1f9192b8 100644 --- a/reflex/components/layout/center.pyi +++ b/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, diff --git a/reflex/components/layout/cond.py b/reflex/components/layout/cond.py index 37b86fcc2..467a2e692 100644 --- a/reflex/components/layout/cond.py +++ b/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.") diff --git a/reflex/components/layout/container.pyi b/reflex/components/layout/container.pyi index c5385e585..7b459c8df 100644 --- a/reflex/components/layout/container.pyi +++ b/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, diff --git a/reflex/components/layout/flex.pyi b/reflex/components/layout/flex.pyi index 97440f899..85cd6d777 100644 --- a/reflex/components/layout/flex.pyi +++ b/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, diff --git a/reflex/components/layout/foreach.py b/reflex/components/layout/foreach.py index dc00e767c..0dbd860ea 100644 --- a/reflex/components/layout/foreach.py +++ b/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__, ) diff --git a/reflex/components/layout/fragment.pyi b/reflex/components/layout/fragment.pyi index ecac8ed72..808dc5da8 100644 --- a/reflex/components/layout/fragment.pyi +++ b/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, diff --git a/reflex/components/layout/grid.pyi b/reflex/components/layout/grid.pyi index 8d620d9cc..4720f2cd5 100644 --- a/reflex/components/layout/grid.pyi +++ b/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, diff --git a/reflex/components/layout/html.pyi b/reflex/components/layout/html.pyi index aec46e2f9..34e57ca96 100644 --- a/reflex/components/layout/html.pyi +++ b/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, diff --git a/reflex/components/layout/spacer.pyi b/reflex/components/layout/spacer.pyi index 833047b9d..f1db9e89a 100644 --- a/reflex/components/layout/spacer.pyi +++ b/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, diff --git a/reflex/components/layout/stack.pyi b/reflex/components/layout/stack.pyi index 7bfa38994..400c47bde 100644 --- a/reflex/components/layout/stack.pyi +++ b/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, diff --git a/reflex/components/layout/wrap.pyi b/reflex/components/layout/wrap.pyi index 5ce60afcc..947b3af5d 100644 --- a/reflex/components/layout/wrap.pyi +++ b/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, diff --git a/reflex/components/libs/chakra.pyi b/reflex/components/libs/chakra.pyi index d410a1c9f..0c8098611 100644 --- a/reflex/components/libs/chakra.pyi +++ b/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, diff --git a/reflex/components/libs/react_player.pyi b/reflex/components/libs/react_player.pyi index a6209a4f6..9d5ccf3cc 100644 --- a/reflex/components/libs/react_player.pyi +++ b/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, diff --git a/reflex/components/media/audio.pyi b/reflex/components/media/audio.pyi index c66a709cc..1946877c6 100644 --- a/reflex/components/media/audio.pyi +++ b/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, diff --git a/reflex/components/media/avatar.pyi b/reflex/components/media/avatar.pyi index bf8695af4..1becbdcb7 100644 --- a/reflex/components/media/avatar.pyi +++ b/reflex/components/media/avatar.pyi @@ -36,7 +36,7 @@ class Avatar(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, @@ -126,7 +126,7 @@ class AvatarBadge(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, @@ -207,7 +207,7 @@ class AvatarGroup(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, diff --git a/reflex/components/media/icon.pyi b/reflex/components/media/icon.pyi index 8747ea95f..ee673a665 100644 --- a/reflex/components/media/icon.pyi +++ b/reflex/components/media/icon.pyi @@ -22,7 +22,7 @@ class ChakraIconComponent(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, @@ -101,7 +101,7 @@ class Icon(ChakraIconComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, diff --git a/reflex/components/media/image.pyi b/reflex/components/media/image.pyi index e6270ad10..85a9fa89d 100644 --- a/reflex/components/media/image.pyi +++ b/reflex/components/media/image.pyi @@ -40,7 +40,7 @@ class Image(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, diff --git a/reflex/components/media/video.pyi b/reflex/components/media/video.pyi index 5651deb44..59f6b3f05 100644 --- a/reflex/components/media/video.pyi +++ b/reflex/components/media/video.pyi @@ -31,7 +31,7 @@ class Video(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, diff --git a/reflex/components/navigation/breadcrumb.pyi b/reflex/components/navigation/breadcrumb.pyi index 429eb63df..9c4b4fbc6 100644 --- a/reflex/components/navigation/breadcrumb.pyi +++ b/reflex/components/navigation/breadcrumb.pyi @@ -27,7 +27,7 @@ class Breadcrumb(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 BreadcrumbItem(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, @@ -196,7 +196,7 @@ class BreadcrumbSeparator(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 BreadcrumbLink(Link): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, diff --git a/reflex/components/navigation/client_side_routing.pyi b/reflex/components/navigation/client_side_routing.pyi index b7801246e..d6de0d1a6 100644 --- a/reflex/components/navigation/client_side_routing.pyi +++ b/reflex/components/navigation/client_side_routing.pyi @@ -26,7 +26,7 @@ class ClientSideRouting(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, @@ -108,7 +108,7 @@ class Default404Page(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, diff --git a/reflex/components/navigation/link.pyi b/reflex/components/navigation/link.pyi index b5af30572..011037a69 100644 --- a/reflex/components/navigation/link.pyi +++ b/reflex/components/navigation/link.pyi @@ -31,7 +31,7 @@ class Link(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, diff --git a/reflex/components/navigation/linkoverlay.pyi b/reflex/components/navigation/linkoverlay.pyi index 013a90a3d..749980403 100644 --- a/reflex/components/navigation/linkoverlay.pyi +++ b/reflex/components/navigation/linkoverlay.pyi @@ -23,7 +23,7 @@ class LinkOverlay(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, @@ -104,7 +104,7 @@ class LinkBox(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, diff --git a/reflex/components/navigation/nextlink.pyi b/reflex/components/navigation/nextlink.pyi index 030294c97..a204d3f03 100644 --- a/reflex/components/navigation/nextlink.pyi +++ b/reflex/components/navigation/nextlink.pyi @@ -23,7 +23,7 @@ class NextLink(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, diff --git a/reflex/components/navigation/stepper.pyi b/reflex/components/navigation/stepper.pyi index eb658ad68..d4176348e 100644 --- a/reflex/components/navigation/stepper.pyi +++ b/reflex/components/navigation/stepper.pyi @@ -80,7 +80,7 @@ class Stepper(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, @@ -162,7 +162,7 @@ class Step(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, @@ -241,7 +241,7 @@ class StepDescription(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, @@ -320,7 +320,7 @@ class StepIcon(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, @@ -399,7 +399,7 @@ class StepIndicator(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, @@ -478,7 +478,7 @@ class StepNumber(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, @@ -557,7 +557,7 @@ class StepSeparator(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, @@ -639,7 +639,7 @@ class StepStatus(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, @@ -719,7 +719,7 @@ class StepTitle(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, diff --git a/reflex/components/overlay/alertdialog.pyi b/reflex/components/overlay/alertdialog.pyi index a2ed99205..b9b96ae06 100644 --- a/reflex/components/overlay/alertdialog.pyi +++ b/reflex/components/overlay/alertdialog.pyi @@ -62,7 +62,7 @@ class AlertDialog(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, @@ -170,7 +170,7 @@ class AlertDialogBody(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, @@ -249,7 +249,7 @@ class AlertDialogHeader(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, @@ -328,7 +328,7 @@ class AlertDialogFooter(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, @@ -407,7 +407,7 @@ class AlertDialogContent(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, @@ -486,7 +486,7 @@ class AlertDialogOverlay(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, @@ -565,7 +565,7 @@ class AlertDialogCloseButton(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, diff --git a/reflex/components/overlay/banner.pyi b/reflex/components/overlay/banner.pyi index db3cafd04..e86e5d16a 100644 --- a/reflex/components/overlay/banner.pyi +++ b/reflex/components/overlay/banner.pyi @@ -33,7 +33,7 @@ class WebsocketTargetURL(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, @@ -101,7 +101,7 @@ class ConnectionBanner(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, @@ -170,7 +170,7 @@ class ConnectionModal(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, diff --git a/reflex/components/overlay/drawer.pyi b/reflex/components/overlay/drawer.pyi index a8dd1345b..612c911b4 100644 --- a/reflex/components/overlay/drawer.pyi +++ b/reflex/components/overlay/drawer.pyi @@ -101,7 +101,7 @@ class Drawer(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, @@ -212,7 +212,7 @@ class DrawerBody(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, @@ -291,7 +291,7 @@ class DrawerHeader(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, @@ -370,7 +370,7 @@ class DrawerFooter(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, @@ -449,7 +449,7 @@ class DrawerOverlay(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, @@ -528,7 +528,7 @@ class DrawerContent(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, @@ -607,7 +607,7 @@ class DrawerCloseButton(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, diff --git a/reflex/components/overlay/menu.pyi b/reflex/components/overlay/menu.pyi index d4484a4db..8da41cfd4 100644 --- a/reflex/components/overlay/menu.pyi +++ b/reflex/components/overlay/menu.pyi @@ -52,7 +52,7 @@ class Menu(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 MenuButton(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, @@ -236,7 +236,7 @@ class MenuList(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, @@ -318,7 +318,7 @@ class MenuItem(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, @@ -412,7 +412,7 @@ class MenuItemOption(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, @@ -499,7 +499,7 @@ class MenuGroup(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, @@ -582,7 +582,7 @@ class MenuOptionGroup(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, @@ -663,7 +663,7 @@ class MenuDivider(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, diff --git a/reflex/components/overlay/modal.pyi b/reflex/components/overlay/modal.pyi index 22f3fcde9..c6cca2d54 100644 --- a/reflex/components/overlay/modal.pyi +++ b/reflex/components/overlay/modal.pyi @@ -49,7 +49,7 @@ class Modal(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, @@ -157,7 +157,7 @@ class ModalOverlay(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, @@ -236,7 +236,7 @@ class ModalHeader(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 ModalFooter(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, @@ -394,7 +394,7 @@ class ModalContent(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, @@ -473,7 +473,7 @@ class ModalBody(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, @@ -552,7 +552,7 @@ class ModalCloseButton(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, diff --git a/reflex/components/overlay/popover.pyi b/reflex/components/overlay/popover.pyi index 37e022486..295886416 100644 --- a/reflex/components/overlay/popover.pyi +++ b/reflex/components/overlay/popover.pyi @@ -58,7 +58,7 @@ class Popover(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, @@ -165,7 +165,7 @@ class PopoverContent(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, @@ -244,7 +244,7 @@ class PopoverHeader(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, @@ -323,7 +323,7 @@ class PopoverFooter(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, @@ -402,7 +402,7 @@ class PopoverBody(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, @@ -481,7 +481,7 @@ class PopoverArrow(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, @@ -560,7 +560,7 @@ class PopoverCloseButton(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, @@ -639,7 +639,7 @@ class PopoverAnchor(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, @@ -718,7 +718,7 @@ class PopoverTrigger(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, diff --git a/reflex/components/overlay/tooltip.pyi b/reflex/components/overlay/tooltip.pyi index 6853bd732..39297602e 100644 --- a/reflex/components/overlay/tooltip.pyi +++ b/reflex/components/overlay/tooltip.pyi @@ -42,7 +42,7 @@ class Tooltip(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, diff --git a/reflex/components/radix/themes/base.pyi b/reflex/components/radix/themes/base.pyi index 9f840f2a8..f22a09a27 100644 --- a/reflex/components/radix/themes/base.pyi +++ b/reflex/components/radix/themes/base.pyi @@ -70,7 +70,7 @@ class CommonMarginProps(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, @@ -156,7 +156,7 @@ class RadixThemesComponent(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, @@ -359,7 +359,7 @@ class Theme(RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -446,7 +446,7 @@ class ThemePanel(RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -525,7 +525,7 @@ class RadixThemesColorModeProvider(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, diff --git a/reflex/components/radix/themes/components.pyi b/reflex/components/radix/themes/components.pyi index d4b443e77..ad452bfc4 100644 --- a/reflex/components/radix/themes/components.pyi +++ b/reflex/components/radix/themes/components.pyi @@ -156,7 +156,7 @@ class Button(CommonMarginProps, RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -378,7 +378,7 @@ class Switch(CommonMarginProps, RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: 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 TextFieldRoot(CommonMarginProps, RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -931,7 +931,7 @@ class TextField(TextFieldRoot, el.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, @@ -1145,7 +1145,7 @@ class TextFieldSlot(RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, diff --git a/reflex/components/radix/themes/layout.pyi b/reflex/components/radix/themes/layout.pyi index 6923db8fa..5d085f26f 100644 --- a/reflex/components/radix/themes/layout.pyi +++ b/reflex/components/radix/themes/layout.pyi @@ -116,7 +116,7 @@ class LayoutComponent(CommonMarginProps, RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -297,7 +297,7 @@ class Box(LayoutComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -519,7 +519,7 @@ class Flex(LayoutComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -663,7 +663,7 @@ class Grid(RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -842,7 +842,7 @@ class Container(LayoutComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -1029,7 +1029,7 @@ class Section(LayoutComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, diff --git a/reflex/components/radix/themes/typography.pyi b/reflex/components/radix/themes/typography.pyi index 147307fe6..121a256f8 100644 --- a/reflex/components/radix/themes/typography.pyi +++ b/reflex/components/radix/themes/typography.pyi @@ -163,7 +163,7 @@ class Text(CommonMarginProps, RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -388,7 +388,7 @@ class Heading(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, @@ -599,7 +599,7 @@ class Blockquote(CommonMarginProps, RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -812,7 +812,7 @@ class Code(Blockquote): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -945,7 +945,7 @@ class Em(CommonMarginProps, RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -1079,7 +1079,7 @@ class Kbd(CommonMarginProps, RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -1298,7 +1298,7 @@ class Link(CommonMarginProps, RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -1433,7 +1433,7 @@ class Quote(CommonMarginProps, RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, @@ -1561,7 +1561,7 @@ class Strong(CommonMarginProps, RadixThemesComponent): id: Optional[Any] = None, class_name: Optional[Any] = None, autofocus: Optional[bool] = None, - custom_attrs: Optional[Dict[str, str]] = None, + custom_attrs: Optional[Dict[str, Union[Var, str]]] = None, on_blur: Optional[ Union[EventHandler, EventSpec, list, function, BaseVar] ] = None, diff --git a/reflex/components/tags/iter_tag.py b/reflex/components/tags/iter_tag.py index 1900a1f70..65050f620 100644 --- a/reflex/components/tags/iter_tag.py +++ b/reflex/components/tags/iter_tag.py @@ -2,7 +2,7 @@ from __future__ import annotations import inspect -from typing import TYPE_CHECKING, Callable, List +from typing import TYPE_CHECKING, Any, Callable, List, Type from reflex.components.tags.tag import Tag from reflex.vars import BaseVar, Var @@ -20,8 +20,26 @@ class IterTag(Tag): # The component render function for each item in the iterable. render_fn: Callable + # The name of the arg var. + arg_var_name: str + # The name of the index var. - index_var_name: str = "i" + index_var_name: str + + def get_iterable_var_type(self) -> Type: + """Get the type of the iterable var. + + Returns: + The type of the iterable var. + """ + try: + return ( + self.iterable._var_type + if self.iterable._var_type.mro()[0] == dict + else self.iterable._var_type.__args__[0] + ) + except Exception: + return Any def get_index_var(self) -> Var: """Get the index var for the tag (with curly braces). @@ -36,6 +54,19 @@ class IterTag(Tag): _var_type=int, ) + def get_arg_var(self) -> Var: + """Get the arg var for the tag (with curly braces). + + This is used to reference the arg var within the tag. + + Returns: + The arg var. + """ + return BaseVar( + _var_name=self.arg_var_name, + _var_type=self.get_iterable_var_type(), + ) + def get_index_var_arg(self) -> Var: """Get the index var for the tag (without curly braces). @@ -50,11 +81,22 @@ class IterTag(Tag): _var_is_local=True, ) - def render_component(self, arg: Var) -> Component: - """Render the component. + def get_arg_var_arg(self) -> Var: + """Get the arg var for the tag (without curly braces). - Args: - arg: The argument to pass to the render function. + This is used to render the arg var in the .map() function. + + Returns: + The arg var. + """ + return BaseVar( + _var_name=self.arg_var_name, + _var_type=self.get_iterable_var_type(), + _var_is_local=True, + ) + + def render_component(self) -> Component: + """Render the component. Returns: The rendered component. @@ -66,6 +108,7 @@ class IterTag(Tag): # Get the render function arguments. args = inspect.getfullargspec(self.render_fn).args + arg = self.get_arg_var() index = self.get_index_var() if len(args) == 1: diff --git a/reflex/components/typography/heading.pyi b/reflex/components/typography/heading.pyi index 00e365b0c..1810b0278 100644 --- a/reflex/components/typography/heading.pyi +++ b/reflex/components/typography/heading.pyi @@ -28,7 +28,7 @@ class Heading(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, diff --git a/reflex/components/typography/highlight.pyi b/reflex/components/typography/highlight.pyi index d92b39bca..87d19ac50 100644 --- a/reflex/components/typography/highlight.pyi +++ b/reflex/components/typography/highlight.pyi @@ -25,7 +25,7 @@ class Highlight(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, diff --git a/reflex/components/typography/markdown.pyi b/reflex/components/typography/markdown.pyi index cb9140435..e5f9d09f7 100644 --- a/reflex/components/typography/markdown.pyi +++ b/reflex/components/typography/markdown.pyi @@ -46,7 +46,7 @@ class Markdown(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, diff --git a/reflex/components/typography/span.pyi b/reflex/components/typography/span.pyi index 9e80a9c16..98bca50ae 100644 --- a/reflex/components/typography/span.pyi +++ b/reflex/components/typography/span.pyi @@ -22,7 +22,7 @@ class Span(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, diff --git a/reflex/components/typography/text.pyi b/reflex/components/typography/text.pyi index ecfb2c1c0..b659da68d 100644 --- a/reflex/components/typography/text.pyi +++ b/reflex/components/typography/text.pyi @@ -23,7 +23,7 @@ class Text(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, diff --git a/reflex/constants/compiler.py b/reflex/constants/compiler.py index e309c5d4a..b1155ad58 100644 --- a/reflex/constants/compiler.py +++ b/reflex/constants/compiler.py @@ -71,6 +71,8 @@ class PageNames(SimpleNamespace): DOCUMENT_ROOT = "_document" # The name of the theme page. THEME = "theme" + # The module containing shared stateful components + STATEFUL_COMPONENTS = "stateful_components" class ComponentName(Enum): diff --git a/reflex/event.py b/reflex/event.py index 3a3708855..cbaf65b0c 100644 --- a/reflex/event.py +++ b/reflex/event.py @@ -329,13 +329,20 @@ class FileUpload(Base): Raises: ValueError: If the on_upload_progress is not a valid event handler. """ - from reflex.components.forms.upload import DEFAULT_UPLOAD_ID + from reflex.components.forms.upload import ( + DEFAULT_UPLOAD_ID, + upload_files_context_var_data, + ) upload_id = self.upload_id or DEFAULT_UPLOAD_ID spec_args = [ - # `upload_files` is defined in state.js and assigned in the Upload component's _use_hooks - (Var.create_safe("files"), Var.create_safe(f"upload_files.{upload_id}[0]")), + ( + Var.create_safe("files"), + Var.create_safe(f"filesById.{upload_id}")._replace( + _var_data=upload_files_context_var_data + ), + ), ( Var.create_safe("upload_id"), Var.create_safe(upload_id, _var_is_string=True), @@ -459,7 +466,7 @@ def set_focus(ref: str) -> EventSpec: return server_side( "_set_focus", get_fn_signature(set_focus), - ref=Var.create_safe(format.format_ref(ref)), + ref=Var.create_safe(format.format_ref(ref), _var_is_string=True), ) @@ -476,7 +483,7 @@ def set_value(ref: str, value: Any) -> EventSpec: return server_side( "_set_value", get_fn_signature(set_value), - ref=Var.create_safe(format.format_ref(ref)), + ref=Var.create_safe(format.format_ref(ref), _var_is_string=True), value=value, ) diff --git a/reflex/style.py b/reflex/style.py index d67029992..1e5d94fa2 100644 --- a/reflex/style.py +++ b/reflex/style.py @@ -89,7 +89,10 @@ class Style(dict): """ if kwargs: style_dict = {**(style_dict or {}), **kwargs} - converted_dict = type(self)(style_dict) + if not isinstance(style_dict, Style): + converted_dict = type(self)(style_dict) + else: + converted_dict = style_dict # Combine our VarData with that of any Vars in the style_dict that was passed. self._var_data = VarData.merge(self._var_data, converted_dict._var_data) super().update(converted_dict) diff --git a/reflex/utils/format.py b/reflex/utils/format.py index 4050706ea..4d95d44d9 100644 --- a/reflex/utils/format.py +++ b/reflex/utils/format.py @@ -620,14 +620,16 @@ def unwrap_vars(value: str) -> str: """ def unescape_double_quotes_in_var(m: re.Match) -> str: + prefix = m.group(1) or "" # Since the outer quotes are removed, the inner escaped quotes must be unescaped. - return re.sub('\\\\"', '"', m.group(1)) + return prefix + re.sub('\\\\"', '"', m.group(2)) # This substitution is necessary to unwrap var values. return re.sub( pattern=r""" (?.*?)? # Optional encoded VarData (non-greedy) {(.*?)} # extract the value between curly braces (non-greedy) " # match must end with an unescaped double quote """, diff --git a/reflex/utils/imports.py b/reflex/utils/imports.py index d878fe438..66ac62213 100644 --- a/reflex/utils/imports.py +++ b/reflex/utils/imports.py @@ -24,6 +24,18 @@ def merge_imports(*imports) -> ImportDict: return all_imports +def collapse_imports(imports: ImportDict) -> ImportDict: + """Remove all duplicate ImportVar within an ImportDict. + + Args: + imports: The import dict to collapse. + + Returns: + The collapsed import dict. + """ + return {lib: list(set(import_vars)) for lib, import_vars in imports.items()} + + class ImportVar(Base): """An import var.""" diff --git a/reflex/utils/serializers.py b/reflex/utils/serializers.py index 665aa10d3..de1987eb0 100644 --- a/reflex/utils/serializers.py +++ b/reflex/utils/serializers.py @@ -175,10 +175,8 @@ def serialize_list(value: Union[List, Tuple, Set]) -> str: Returns: The serialized list. """ - from reflex.vars import Var - - # Convert any var values to strings. - fprop = format.json_dumps([str(v) if isinstance(v, Var) else v for v in value]) + # Dump the list to a string. + fprop = format.json_dumps(list(value)) # Unwrap var values. return format.unwrap_vars(fprop) @@ -199,11 +197,9 @@ def serialize_dict(prop: Dict[str, Any]) -> str: """ # Import here to avoid circular imports. from reflex.event import EventHandler - from reflex.vars import Var prop_dict = {} - # Convert any var keys to strings. for key, value in prop.items(): if types._issubclass(type(value), Callable): raise exceptions.InvalidStylePropError( @@ -211,7 +207,7 @@ def serialize_dict(prop: Dict[str, Any]) -> str: f"`{value.fn.__qualname__ if isinstance(value, EventHandler) else value.__qualname__ if isinstance(value, builtin_types.FunctionType) else value}`, " f"an event handler or callable as its value" ) - prop_dict[key] = str(value) if isinstance(value, Var) else value + prop_dict[key] = value # Dump the dict to a string. fprop = format.json_dumps(prop_dict) diff --git a/reflex/vars.py b/reflex/vars.py index d4d785b7a..caec26f87 100644 --- a/reflex/vars.py +++ b/reflex/vars.py @@ -31,6 +31,8 @@ from typing import ( get_type_hints, ) +import pydantic + from reflex import constants from reflex.base import Base from reflex.utils import console, format, imports, serializers, types @@ -147,6 +149,24 @@ class VarData(Base): """ return bool(self.state or self.imports or self.hooks) + def __eq__(self, other: Any) -> bool: + """Check if two var data objects are equal. + + Args: + other: The other var data object to compare. + + Returns: + True if all fields are equal and collapsed imports are equal. + """ + if not isinstance(other, VarData): + return False + return ( + self.state == other.state + and self.hooks == other.hooks + and imports.collapse_imports(self.imports) + == imports.collapse_imports(other.imports) + ) + def dict(self) -> dict: """Convert the var data to a dictionary. @@ -191,7 +211,11 @@ def _decode_var(value: str) -> tuple[VarData | None, str]: # Extract the state name from a formatted var while m := re.match(r"(.*)(.*)(.*)", value): value = m.group(1) + m.group(3) - var_datas.append(VarData.parse_raw(m.group(2))) + try: + var_datas.append(VarData.parse_raw(m.group(2))) + except pydantic.ValidationError: + # If the VarData is invalid, it was probably json-encoded twice... + var_datas.append(VarData.parse_raw(json.loads(f'"{m.group(2)}"'))) if var_datas: return VarData.merge(*var_datas), value return None, value @@ -1413,6 +1437,24 @@ class Var: """ return self._replace(_var_type=type_) + def as_ref(self) -> Var: + """Convert the var to a ref. + + Returns: + The var as a ref. + """ + return self._replace( + _var_name=f"refs['{self._var_full_name}']", + _var_is_local=True, + _var_is_string=False, + _var_full_name_needs_state_prefix=False, + merge_var_data=VarData( + imports={ + f"/{constants.Dirs.STATE_PATH}": [imports.ImportVar(tag="refs")], + }, + ), + ) + @property def _var_full_name(self) -> str: """Get the full name of the var. @@ -1466,6 +1508,10 @@ class Var: return self._var_data.state if self._var_data else "" +# Allow automatic serialization of Var within JSON structures +serializers.serializer(_encode_var) + + @dataclasses.dataclass( eq=False, **{"slots": True} if sys.version_info >= (3, 10) else {}, diff --git a/reflex/vars.pyi b/reflex/vars.pyi index 9208013db..c4c96af90 100644 --- a/reflex/vars.pyi +++ b/reflex/vars.pyi @@ -107,6 +107,7 @@ class Var: step: Var | int | None = None, ) -> Var: ... def to(self, type_: Type) -> Var: ... + def as_ref(self) -> Var: ... @property def _var_full_name(self) -> str: ... def _var_set_state(self, state: Type[State] | str) -> Any: ... diff --git a/tests/components/forms/test_form.py b/tests/components/forms/test_form.py index d57b6f95c..0b0664050 100644 --- a/tests/components/forms/test_form.py +++ b/tests/components/forms/test_form.py @@ -10,7 +10,7 @@ def test_render_on_submit(): _var_type=EventChain, ) f = Form.create(on_submit=submit_it) - exp_submit_name = f"handleSubmit{f.handle_submit_unique_name}" # type: ignore + exp_submit_name = f"handleSubmit_{f.handle_submit_unique_name}" # type: ignore assert f"onSubmit={{{exp_submit_name}}}" in f.render()["props"] diff --git a/tests/components/forms/test_uploads.py b/tests/components/forms/test_uploads.py index fee58ec3b..c3ca14cfb 100644 --- a/tests/components/forms/test_uploads.py +++ b/tests/components/forms/test_uploads.py @@ -54,7 +54,7 @@ def test_upload_component_render(upload_component): assert upload["props"] == [ "id={`default`}", "multiple={true}", - "onDrop={e => upload_files.default[1]((files) => e)}", + "onDrop={e => setFilesById(filesById => ({...filesById, default: e}))}", "ref={ref_default}", ] assert upload["args"] == ("getRootProps", "getInputProps") @@ -95,6 +95,6 @@ def test_upload_component_with_props_render(upload_component_with_props): "maxFiles={2}", "multiple={true}", "noDrag={true}", - "onDrop={e => upload_files.default[1]((files) => e)}", + "onDrop={e => setFilesById(filesById => ({...filesById, default: e}))}", "ref={ref_default}", ] diff --git a/tests/components/layout/test_foreach.py b/tests/components/layout/test_foreach.py index 11c8be563..aacdf3638 100644 --- a/tests/components/layout/test_foreach.py +++ b/tests/components/layout/test_foreach.py @@ -67,11 +67,11 @@ def display_nested_color_with_shades_v2(color): def display_color_tuple(color): - return box(text(color)) + return box(text(color, "tuple")) def display_colors_set(color): - return box(text(color)) + return box(text(color, "set")) def display_nested_list_element(element: str, index: int): diff --git a/tests/components/test_component.py b/tests/components/test_component.py index 6d6b0a0cc..d90efd658 100644 --- a/tests/components/test_component.py +++ b/tests/components/test_component.py @@ -5,7 +5,12 @@ import pytest import reflex as rx from reflex.base import Base from reflex.components.base.bare import Bare -from reflex.components.component import Component, CustomComponent, custom_component +from reflex.components.component import ( + Component, + CustomComponent, + StatefulComponent, + custom_component, +) from reflex.components.layout.box import Box from reflex.constants import EventTriggers from reflex.event import EventChain, EventHandler @@ -604,6 +609,47 @@ def test_format_component(component, rendered): assert str(component) == rendered +def test_stateful_component(test_state): + """Test that a stateful component is created correctly. + + Args: + test_state: A test state. + """ + text_component = rx.text(test_state.num) + stateful_component = StatefulComponent.compile_from(text_component) + assert isinstance(stateful_component, StatefulComponent) + assert stateful_component.tag is not None + assert stateful_component.tag.startswith("Text_") + assert stateful_component.references == 1 + sc2 = StatefulComponent.compile_from(rx.text(test_state.num)) + assert isinstance(sc2, StatefulComponent) + assert stateful_component.references == 2 + assert sc2.references == 2 + + +def test_stateful_component_memoize_event_trigger(test_state): + """Test that a stateful component is created correctly with events. + + Args: + test_state: A test state. + """ + button_component = rx.button("Click me", on_click=test_state.do_something) + stateful_component = StatefulComponent.compile_from(button_component) + assert isinstance(stateful_component, StatefulComponent) + + # No event trigger? No StatefulComponent + assert not isinstance( + StatefulComponent.compile_from(rx.button("Click me")), StatefulComponent + ) + + +def test_stateful_banner(): + """Test that a stateful component is created correctly with events.""" + connection_modal_component = rx.connection_modal() + stateful_component = StatefulComponent.compile_from(connection_modal_component) + assert isinstance(stateful_component, StatefulComponent) + + TEST_VAR = Var.create_safe("test")._replace( merge_var_data=VarData( hooks={"useTest"}, imports={"test": {ImportVar(tag="test")}}, state="Test" @@ -614,6 +660,43 @@ STYLE_VAR = TEST_VAR._replace(_var_name="style", _var_is_local=False) EVENT_CHAIN_VAR = TEST_VAR._replace(_var_type=EventChain) ARG_VAR = Var.create("arg") +TEST_VAR_DICT_OF_DICT = Var.create_safe({"a": {"b": "test"}})._replace( + merge_var_data=TEST_VAR._var_data +) +FORMATTED_TEST_VAR_DICT_OF_DICT = Var.create_safe({"a": {"b": f"footestbar"}})._replace( + merge_var_data=TEST_VAR._var_data +) + +TEST_VAR_LIST_OF_LIST = Var.create_safe([["test"]])._replace( + merge_var_data=TEST_VAR._var_data +) +FORMATTED_TEST_VAR_LIST_OF_LIST = Var.create_safe([["footestbar"]])._replace( + merge_var_data=TEST_VAR._var_data +) + +TEST_VAR_LIST_OF_LIST_OF_LIST = Var.create_safe([[["test"]]])._replace( + merge_var_data=TEST_VAR._var_data +) +FORMATTED_TEST_VAR_LIST_OF_LIST_OF_LIST = Var.create_safe([[["footestbar"]]])._replace( + merge_var_data=TEST_VAR._var_data +) + +TEST_VAR_LIST_OF_DICT = Var.create_safe([{"a": "test"}])._replace( + merge_var_data=TEST_VAR._var_data +) +FORMATTED_TEST_VAR_LIST_OF_DICT = Var.create_safe([{"a": "footestbar"}])._replace( + merge_var_data=TEST_VAR._var_data +) + + +class ComponentNestedVar(Component): + """A component with nested Var types.""" + + dict_of_dict: Var[Dict[str, Dict[str, str]]] + list_of_list: Var[List[List[str]]] + list_of_list_of_list: Var[List[List[List[str]]]] + list_of_dict: Var[List[Dict[str, str]]] + class EventState(rx.State): """State for testing event handlers with _get_vars.""" @@ -750,6 +833,46 @@ class EventState(rx.State): [ARG_VAR, TEST_VAR], id="direct-event-handler-lambda", ), + pytest.param( + ComponentNestedVar.create(dict_of_dict={"a": {"b": TEST_VAR}}), + [TEST_VAR_DICT_OF_DICT], + id="direct-dict_of_dict", + ), + pytest.param( + ComponentNestedVar.create(dict_of_dict={"a": {"b": f"foo{TEST_VAR}bar"}}), + [FORMATTED_TEST_VAR_DICT_OF_DICT], + id="fstring-dict_of_dict", + ), + pytest.param( + ComponentNestedVar.create(list_of_list=[[TEST_VAR]]), + [TEST_VAR_LIST_OF_LIST], + id="direct-list_of_list", + ), + pytest.param( + ComponentNestedVar.create(list_of_list=[[f"foo{TEST_VAR}bar"]]), + [FORMATTED_TEST_VAR_LIST_OF_LIST], + id="fstring-list_of_list", + ), + pytest.param( + ComponentNestedVar.create(list_of_list_of_list=[[[TEST_VAR]]]), + [TEST_VAR_LIST_OF_LIST_OF_LIST], + id="direct-list_of_list_of_list", + ), + pytest.param( + ComponentNestedVar.create(list_of_list_of_list=[[[f"foo{TEST_VAR}bar"]]]), + [FORMATTED_TEST_VAR_LIST_OF_LIST_OF_LIST], + id="fstring-list_of_list_of_list", + ), + pytest.param( + ComponentNestedVar.create(list_of_dict=[{"a": TEST_VAR}]), + [TEST_VAR_LIST_OF_DICT], + id="direct-list_of_dict", + ), + pytest.param( + ComponentNestedVar.create(list_of_dict=[{"a": f"foo{TEST_VAR}bar"}]), + [FORMATTED_TEST_VAR_LIST_OF_DICT], + id="fstring-list_of_dict", + ), ), ) def test_get_vars(component, exp_vars): diff --git a/tests/test_event.py b/tests/test_event.py index 69e69905f..284012b13 100644 --- a/tests/test_event.py +++ b/tests/test_event.py @@ -185,9 +185,9 @@ def test_set_focus(): assert spec.handler.fn.__qualname__ == "_set_focus" assert spec.args[0][0].equals(Var.create_safe("ref")) assert spec.args[0][1].equals(Var.create_safe("ref_input1")) - assert format.format_event(spec) == 'Event("_set_focus", {ref:ref_input1})' + assert format.format_event(spec) == 'Event("_set_focus", {ref:`ref_input1`})' spec = event.set_focus("input1") - assert format.format_event(spec) == 'Event("_set_focus", {ref:ref_input1})' + assert format.format_event(spec) == 'Event("_set_focus", {ref:`ref_input1`})' def test_set_value(): @@ -199,11 +199,13 @@ def test_set_value(): assert spec.args[0][1].equals(Var.create_safe("ref_input1")) assert spec.args[1][0].equals(Var.create_safe("value")) assert spec.args[1][1].equals(Var.create_safe("")) - assert format.format_event(spec) == 'Event("_set_value", {ref:ref_input1,value:``})' + assert ( + format.format_event(spec) == 'Event("_set_value", {ref:`ref_input1`,value:``})' + ) spec = event.set_value("input1", Var.create_safe("message")) assert ( format.format_event(spec) - == 'Event("_set_value", {ref:ref_input1,value:message})' + == 'Event("_set_value", {ref:`ref_input1`,value:message})' )