Compare commits

..

91 Commits

Author SHA1 Message Date
Masen Furer
ec02b2c2db
Create StatefulComponent for LiteralComponentVar
TODO: actually pass through locals properly
2025-01-27 06:05:26 -08:00
Khaleel Al-Adhami
2ffa698c6b improve match and cond checking 2025-01-23 15:03:45 -08:00
Khaleel Al-Adhami
0d746bf762 handle default args 2025-01-23 13:09:47 -08:00
Khaleel Al-Adhami
d3b12a84fa optimize var operation output 2025-01-23 11:54:45 -08:00
Khaleel Al-Adhami
6604784ca1 update pydantic requirement 2025-01-23 10:27:34 -08:00
Khaleel Al-Adhami
24f341d125 Merge branch 'main' into add-validation-to-function-vars 2025-01-23 10:26:04 -08:00
Khaleel Al-Adhami
29fc4b020a make the match logic better 2025-01-22 16:39:43 -08:00
Masen Furer
19dd15bd44
Banner components that return Fragment inherit from Fragment 2025-01-22 16:25:44 -08:00
Khaleel Al-Adhami
6a50b3a29e i was a bit silly 2025-01-22 16:24:03 -08:00
Khaleel Al-Adhami
b2a27cb8c1 fix list of component is a component 2025-01-22 16:17:08 -08:00
Khaleel Al-Adhami
540382dd3e kill callable var 2025-01-22 15:04:31 -08:00
Khaleel Al-Adhami
c6e2368c95 callable vars are not good 2025-01-22 13:35:04 -08:00
Khaleel Al-Adhami
e10cf07506 make icon to static methods 2025-01-22 13:14:55 -08:00
Khaleel Al-Adhami
84d3a2bb97 unbreak cond why not 2025-01-22 12:53:16 -08:00
Khaleel Al-Adhami
8173e10698 ok we can unbreak foreach just for you 2025-01-22 12:51:01 -08:00
Khaleel Al-Adhami
1f9fbd88de resolve merge mistakes 2025-01-22 12:47:21 -08:00
Khaleel Al-Adhami
68b8c12127 Merge branch 'main' into add-validation-to-function-vars 2025-01-22 12:11:48 -08:00
Khaleel Al-Adhami
5e45ca509b remove iterable from jinja 2025-01-17 18:23:38 -08:00
Khaleel Al-Adhami
be92063421 dang it darglint 2025-01-17 18:21:28 -08:00
Khaleel Al-Adhami
5d6b51c561 what if i deleted rx.foreach 2025-01-17 18:16:43 -08:00
Khaleel Al-Adhami
b10f6e836d remove even more cond and match 2025-01-17 16:34:48 -08:00
Khaleel Al-Adhami
db89a712e9 reformat color_mode pyi 2025-01-17 16:30:05 -08:00
Khaleel Al-Adhami
9e7eeb2a6e fix imports 2025-01-17 16:29:10 -08:00
Khaleel Al-Adhami
b7579f4d8d why not, remove cond 2025-01-17 16:27:30 -08:00
Khaleel Al-Adhami
392c5b5a69 who likes cond 2025-01-17 16:21:53 -08:00
Khaleel Al-Adhami
b11fc5a8ef update pyi 2025-01-17 16:17:47 -08:00
Khaleel Al-Adhami
00019daa27 get rid of match class 2025-01-17 16:17:24 -08:00
Khaleel Al-Adhami
36af8255d3 remove unused format functions 2025-01-17 16:06:58 -08:00
Khaleel Al-Adhami
aadd8b56bf do silly things 2025-01-17 15:51:11 -08:00
Khaleel Al-Adhami
fa6c12e8b3 remove unnecessary comment 2025-01-17 15:32:34 -08:00
Khaleel Al-Adhami
f4aa122950 don't delete thomas code that's rude 2025-01-17 15:24:32 -08:00
Khaleel Al-Adhami
9a987caf76 dang it darglint 2025-01-17 15:21:33 -08:00
Khaleel Al-Adhami
c6f05bb320 fix lineno 2025-01-17 15:15:09 -08:00
Khaleel Al-Adhami
0e539a208c fix syntax for soy 3.10 2025-01-17 15:08:58 -08:00
Khaleel Al-Adhami
a7230f1f45 resolve pyright issues 2025-01-17 15:07:32 -08:00
Khaleel Al-Adhami
0798cb8f60 fix version python 3.10 2025-01-17 14:31:49 -08:00
Khaleel Al-Adhami
270fcb996d Merge branch 'main' into add-validation-to-function-vars 2025-01-17 14:24:48 -08:00
Khaleel Al-Adhami
57d8ea02e9 down to only two pyright error 2025-01-17 14:16:03 -08:00
Khaleel Al-Adhami
112b2ed948 solve some but not all pyright issues 2025-01-16 20:06:02 -08:00
Khaleel Al-Adhami
3d73f561b7 can't have ohio 2025-01-16 19:16:53 -08:00
Khaleel Al-Adhami
72f1fa7cb4 make the var type actually work 2025-01-16 18:17:15 -08:00
Khaleel Al-Adhami
94b4443afc what if we simply didn't have match 2025-01-16 18:11:48 -08:00
Khaleel Al-Adhami
f9d45d5562 fix tests for cond and var 2025-01-16 16:02:41 -08:00
Khaleel Al-Adhami
94c9e52474 fix convert to component logic 2025-01-16 15:16:48 -08:00
Khaleel Al-Adhami
4300f338d8 add wrap components override 2025-01-16 14:50:37 -08:00
Khaleel Al-Adhami
f42d1f4b0f fix component state 2025-01-16 14:34:35 -08:00
Khaleel Al-Adhami
a488fe0c49 i missed up that 2025-01-16 14:05:38 -08:00
Khaleel Al-Adhami
076cfea6ae fix and and or 2025-01-16 13:48:42 -08:00
Khaleel Al-Adhami
d0208e678c change range a bit 2025-01-15 19:16:36 -08:00
Khaleel Al-Adhami
19b6fe9efc handle component at largest scope 2025-01-15 18:02:44 -08:00
Khaleel Al-Adhami
1aa728ee4c use infallible guy 2025-01-15 17:28:46 -08:00
Khaleel Al-Adhami
713f907bf0 silly me 2025-01-15 17:08:33 -08:00
Khaleel Al-Adhami
990bf131c6 fix that test 2025-01-15 17:04:36 -08:00
Khaleel Al-Adhami
f257122934 Merge branch 'main' into add-validation-to-function-vars 2025-01-15 17:04:28 -08:00
Khaleel Al-Adhami
f0f84d5410 fix some tests 2025-01-15 17:00:06 -08:00
Khaleel Al-Adhami
45dde0072e handle vars with var_type being BaseComponent 2025-01-15 10:32:15 -08:00
Khaleel Al-Adhami
2a02e96d87 make the thing compile again 2025-01-15 10:25:25 -08:00
Khaleel Al-Adhami
056de9e277 poetry update 2025-01-15 10:15:55 -08:00
Khaleel Al-Adhami
d31510c655 Merge branch 'main' into add-validation-to-function-vars 2025-01-14 18:40:59 -08:00
Khaleel Al-Adhami
a5526afaeb update pyright once again 2025-01-02 15:20:03 -08:00
Khaleel Al-Adhami
99a3090784 Merge branch 'main' into add-validation-to-function-vars 2025-01-02 11:44:45 -08:00
Khaleel Al-Adhami
bd2ea5b417 update poetry version 2024-12-12 07:35:18 +03:00
Khaleel Al-Adhami
8830d5ab77 update poetry 2024-12-12 07:33:36 +03:00
Khaleel Al-Adhami
06eb04f005 Merge branch 'main' into add-validation-to-function-vars 2024-12-12 07:33:24 +03:00
Khaleel Al-Adhami
2e1bc057a4 aaaaa 2024-11-15 17:39:14 -08:00
Khaleel Al-Adhami
2b05ee98ed make it handle slice 2024-11-15 17:30:45 -08:00
Khaleel Al-Adhami
ed1ae0d3a2 add missing return 2024-11-15 17:15:43 -08:00
Khaleel Al-Adhami
7d0a4f7133 make safe issubclass 2024-11-15 17:12:42 -08:00
Khaleel Al-Adhami
079cc56f59 more types 2024-11-15 16:59:28 -08:00
Khaleel Al-Adhami
92b1232806 would this fix it? no clue 2024-11-15 16:16:13 -08:00
Khaleel Al-Adhami
7f1dc7c841 remove .bool 2024-11-15 15:58:03 -08:00
Khaleel Al-Adhami
eac54d60d2 call guess type 2024-11-15 15:54:04 -08:00
Khaleel Al-Adhami
702670ff26 add components to var data 2024-11-15 15:47:46 -08:00
Khaleel Al-Adhami
88cfb3b7e2 handle var at top level 2024-11-15 15:11:44 -08:00
Khaleel Al-Adhami
53b98543cc default factory 2024-11-15 14:58:19 -08:00
Khaleel Al-Adhami
5f0546f32e what am i doing anymore 2024-11-15 14:53:51 -08:00
Khaleel Al-Adhami
2c04153013 special case ellipsis types 2024-11-14 09:45:44 -08:00
Khaleel Al-Adhami
a9db61b371 get it right pyright 2024-11-13 19:03:42 -08:00
Khaleel Al-Adhami
3cdd2097b6 fix pyright issues outside of vars 2024-11-13 18:43:20 -08:00
Khaleel Al-Adhami
9d7e353ed3 fix pyright issues 2024-11-13 18:40:06 -08:00
Khaleel Al-Adhami
f4aa1f58c3 implement type computers 2024-11-13 18:17:53 -08:00
Khaleel Al-Adhami
ebc81811c0 fix silly mistakes 2024-11-13 13:51:47 -08:00
Khaleel Al-Adhami
1e9743dcd6 Merge branch 'main' into add-validation-to-function-vars 2024-11-13 13:23:38 -08:00
Khaleel Al-Adhami
05bd41c040 add validation 2024-11-13 13:22:01 -08:00
Khaleel Al-Adhami
f9b24fe5bd get typevar from extensions 2024-11-12 16:38:30 -08:00
Khaleel Al-Adhami
6745d6cb9d don't use Any from extensions 2024-11-12 16:35:04 -08:00
Khaleel Al-Adhami
7ada0ea5b9 special case 3.9 2024-11-12 16:23:06 -08:00
Khaleel Al-Adhami
48951dbabd try importing everything from extensions 2024-11-12 16:11:30 -08:00
Khaleel Al-Adhami
7aa9245514 remove ellipsis as they are not supported in 3.9 2024-11-12 16:07:17 -08:00
Khaleel Al-Adhami
9b06d684cd import ParamSpec from typing_extensions 2024-11-12 16:03:40 -08:00
Khaleel Al-Adhami
56f0d6375b add typing to function vars 2024-11-12 16:01:32 -08:00
329 changed files with 19083 additions and 56697 deletions

View File

@ -1,2 +0,0 @@
paths-ignore:
- "**/tests/**"

View File

@ -70,6 +70,56 @@ jobs:
env:
GITHUB_SHA: ${{ github.sha }}
simple-apps-benchmarks: # This app tests the compile times of various compoonents and pages
if: github.event.pull_request.merged == true
env:
OUTPUT_FILE: benchmarks.json
timeout-minutes: 50
strategy:
# Prioritize getting more information out of the workflow (even if something fails)
fail-fast: false
matrix:
# Show OS combos first in GUI
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.10.16", "3.11.11", "3.12.8"]
exclude:
- os: windows-latest
python-version: "3.10.16"
- os: windows-latest
python-version: "3.11.11"
# keep only one python version for MacOS
- os: macos-latest
python-version: "3.10.16"
- os: macos-latest
python-version: "3.11.11"
include:
- os: windows-latest
python-version: "3.10.11"
- os: windows-latest
python-version: "3.11.9"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup_build_env
with:
python-version: ${{ matrix.python-version }}
run-poetry-install: true
create-venv-at-path: .venv
- name: Run benchmark tests
env:
APP_HARNESS_HEADLESS: 1
PYTHONUNBUFFERED: 1
run: |
poetry run pytest -v benchmarks/ --benchmark-json=${{ env.OUTPUT_FILE }} -s
- name: Upload benchmark results
# Only run if the database creds are available in this context.
run:
poetry run python benchmarks/benchmark_compile_times.py --os "${{ matrix.os }}"
--python-version "${{ matrix.python-version }}" --commit-sha "${{ github.sha }}"
--benchmark-json "${{ env.OUTPUT_FILE }}" --branch-name "${{ github.head_ref || github.ref_name }}"
--event-type "${{ github.event_name }}" --pr-id "${{ github.event.pull_request.id }}"
reflex-dist-size: # This job is used to calculate the size of the Reflex distribution (wheel file)
if: github.event.pull_request.merged == true
timeout-minutes: 30

View File

@ -1,103 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL Advanced"
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
schedule:
- cron: "36 7 * * 4"
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: javascript-typescript
build-mode: none
- language: python
build-mode: none
- language: actions
build-mode: none
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Add any setup steps before running the `github/codeql-action/init` action.
# This includes steps like installing compilers or runtimes (`actions/setup-node`
# or others). This is typically only required for manual builds.
# - name: Setup runtime (example)
# uses: actions/setup-example@v1
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
config-file: .github/codeql-config.yml
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@ -94,6 +94,26 @@ jobs:
# Check that npm is home
npm -v
poetry run bash scripts/integration.sh ./reflex-examples/counter dev
- name: Measure and upload .web size
run:
poetry run python benchmarks/benchmark_web_size.py --os "${{ matrix.os }}"
--python-version "${{ matrix.python-version }}" --commit-sha "${{ github.sha }}"
--pr-id "${{ github.event.pull_request.id }}"
--branch-name "${{ github.head_ref || github.ref_name }}"
--path ./reflex-examples/counter/.web
--app-name "counter"
- name: Install hyperfine
run: cargo install hyperfine
- name: Benchmark imports
working-directory: ./reflex-examples/counter
run: hyperfine --warmup 3 "export POETRY_VIRTUALENVS_PATH=../../.venv; poetry run python counter/counter.py" --show-output --export-json "${{ env.OUTPUT_FILE }}" --shell bash
- name: Upload Benchmarks
run:
poetry run python benchmarks/benchmark_imports.py --os "${{ matrix.os }}"
--python-version "${{ matrix.python-version }}" --commit-sha "${{ github.sha }}"
--benchmark-json "./reflex-examples/counter/${{ env.OUTPUT_FILE }}"
--branch-name "${{ github.head_ref || github.ref_name }}" --pr-id "${{ github.event.pull_request.id }}"
--app-name "counter"
- name: Install requirements for nba proxy example
working-directory: ./reflex-examples/nba-proxy
run: |
@ -154,6 +174,12 @@ jobs:
# Check that npm is home
npm -v
poetry run bash scripts/integration.sh ./reflex-web prod
- name: Measure and upload .web size
run:
poetry run python benchmarks/benchmark_web_size.py --os "${{ matrix.os }}"
--python-version "${{ matrix.python-version }}" --commit-sha "${{ github.sha }}"
--pr-id "${{ github.event.pull_request.id }}" --branch-name "${{ github.head_ref || github.ref_name }}"
--app-name "reflex-web" --path ./reflex-web/.web
rx-shout-from-template:
strategy:
@ -217,3 +243,9 @@ jobs:
# Check that npm is home
npm -v
poetry run bash scripts/integration.sh ./reflex-web prod
- name: Measure and upload .web size
run:
poetry run python benchmarks/benchmark_web_size.py --os "${{ matrix.os }}"
--python-version "${{ matrix.python-version }}" --commit-sha "${{ github.sha }}"
--pr-id "${{ github.event.pull_request.id }}" --branch-name "${{ github.head_ref || github.ref_name }}"
--app-name "reflex-web" --path ./reflex-web/.web

View File

@ -1,34 +0,0 @@
name: performance-tests
on:
push:
branches:
- "main" # or "master"
paths-ignore:
- "**/*.md"
pull_request:
workflow_dispatch:
env:
TELEMETRY_ENABLED: false
NODE_OPTIONS: "--max_old_space_size=8192"
PR_TITLE: ${{ github.event.pull_request.title }}
APP_HARNESS_HEADLESS: 1
PYTHONUNBUFFERED: 1
jobs:
benchmarks:
name: Run benchmarks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup_build_env
with:
python-version: 3.12.8
run-poetry-install: true
create-venv-at-path: .venv
- name: Run benchmarks
uses: CodSpeedHQ/action@v3
with:
token: ${{ secrets.CODSPEED_TOKEN }}
run: poetry run pytest tests/benchmarks --codspeed

2
.gitignore vendored
View File

@ -4,7 +4,6 @@ assets/external/*
dist/*
examples/
.web
.states
.idea
.vscode
.coverage
@ -15,4 +14,3 @@ requirements.txt
.pyi_generator_last_run
.pyi_generator_diff
reflex.db
.codspeed

View File

@ -3,7 +3,7 @@ fail_fast: true
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.9.6
rev: v0.8.2
hooks:
- id: ruff-format
args: [reflex, tests]
@ -24,12 +24,11 @@ repos:
name: update-pyi-files
always_run: true
language: system
require_serial: true
description: 'Update pyi files as needed'
entry: python3 scripts/make_pyi.py
- repo: https://github.com/RobertCraigie/pyright-python
rev: v1.1.393
rev: v1.1.334
hooks:
- id: pyright
args: [reflex, tests]

View File

@ -0,0 +1,376 @@
"""Benchmark tests for apps with varying component numbers."""
from __future__ import annotations
import functools
import time
from typing import Generator
import pytest
from benchmarks import WINDOWS_SKIP_REASON
from reflex import constants
from reflex.compiler import utils
from reflex.testing import AppHarness, chdir
from reflex.utils import build
from reflex.utils.prerequisites import get_web_dir
web_pages = get_web_dir() / constants.Dirs.PAGES
def render_component(num: int):
"""Generate a number of components based on num.
Args:
num: number of components to produce.
Returns:
The rendered number of components.
"""
import reflex as rx
return [
rx.fragment(
rx.box(
rx.accordion.root(
rx.accordion.item(
header="Full Ingredients", # type: ignore
content="Yes. It's built with accessibility in mind.", # type: ignore
font_size="3em",
),
rx.accordion.item(
header="Applications", # type: ignore
content="Yes. It's unstyled by default, giving you freedom over the look and feel.", # type: ignore
),
collapsible=True,
variant="ghost",
width="25rem",
),
padding_top="20px",
),
rx.box(
rx.drawer.root(
rx.drawer.trigger(
rx.button("Open Drawer with snap points"), as_child=True
),
rx.drawer.overlay(),
rx.drawer.portal(
rx.drawer.content(
rx.flex(
rx.drawer.title("Drawer Content"),
rx.drawer.description("Drawer description"),
rx.drawer.close(
rx.button("Close Button"),
as_child=True,
),
direction="column",
margin="5em",
align_items="center",
),
top="auto",
height="100%",
flex_direction="column",
background_color="var(--green-3)",
),
),
snap_points=["148px", "355px", 1],
),
),
rx.box(
rx.callout(
"You will need admin privileges to install and access this application.",
icon="info",
size="3",
),
),
rx.box(
rx.table.root(
rx.table.header(
rx.table.row(
rx.table.column_header_cell("Full name"),
rx.table.column_header_cell("Email"),
rx.table.column_header_cell("Group"),
),
),
rx.table.body(
rx.table.row(
rx.table.row_header_cell("Danilo Sousa"),
rx.table.cell("danilo@example.com"),
rx.table.cell("Developer"),
),
rx.table.row(
rx.table.row_header_cell("Zahra Ambessa"),
rx.table.cell("zahra@example.com"),
rx.table.cell("Admin"),
),
rx.table.row(
rx.table.row_header_cell("Jasper Eriksson"),
rx.table.cell("jasper@example.com"),
rx.table.cell("Developer"),
),
),
)
),
)
] * num
def AppWithTenComponentsOnePage():
"""A reflex app with roughly 10 components on one page."""
import reflex as rx
def index() -> rx.Component:
return rx.center(rx.vstack(*render_component(1)))
app = rx.App(_state=rx.State)
app.add_page(index)
def AppWithHundredComponentOnePage():
"""A reflex app with roughly 100 components on one page."""
import reflex as rx
def index() -> rx.Component:
return rx.center(rx.vstack(*render_component(100)))
app = rx.App(_state=rx.State)
app.add_page(index)
def AppWithThousandComponentsOnePage():
"""A reflex app with roughly 1000 components on one page."""
import reflex as rx
def index() -> rx.Component:
return rx.center(rx.vstack(*render_component(1000)))
app = rx.App(_state=rx.State)
app.add_page(index)
@pytest.fixture(scope="session")
def app_with_10_components(
tmp_path_factory,
) -> Generator[AppHarness, None, None]:
"""Start Blank Template app at tmp_path via AppHarness.
Args:
tmp_path_factory: pytest tmp_path_factory fixture
Yields:
running AppHarness instance
"""
root = tmp_path_factory.mktemp("app10components")
yield AppHarness.create(
root=root,
app_source=functools.partial(
AppWithTenComponentsOnePage,
render_component=render_component, # type: ignore
),
) # type: ignore
@pytest.fixture(scope="session")
def app_with_100_components(
tmp_path_factory,
) -> Generator[AppHarness, None, None]:
"""Start Blank Template app at tmp_path via AppHarness.
Args:
tmp_path_factory: pytest tmp_path_factory fixture
Yields:
running AppHarness instance
"""
root = tmp_path_factory.mktemp("app100components")
yield AppHarness.create(
root=root,
app_source=functools.partial(
AppWithHundredComponentOnePage,
render_component=render_component, # type: ignore
),
) # type: ignore
@pytest.fixture(scope="session")
def app_with_1000_components(
tmp_path_factory,
) -> Generator[AppHarness, None, None]:
"""Create an app with 1000 components at tmp_path via AppHarness.
Args:
tmp_path_factory: pytest tmp_path_factory fixture
Yields:
an AppHarness instance
"""
root = tmp_path_factory.mktemp("app1000components")
yield AppHarness.create(
root=root,
app_source=functools.partial(
AppWithThousandComponentsOnePage,
render_component=render_component, # type: ignore
),
) # type: ignore
@pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
@pytest.mark.benchmark(
group="Compile time of varying component numbers",
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_10_compile_time_cold(benchmark, app_with_10_components):
"""Test the compile time on a cold start for an app with roughly 10 components.
Args:
benchmark: The benchmark fixture.
app_with_10_components: The app harness.
"""
def setup():
with chdir(app_with_10_components.app_path):
utils.empty_dir(web_pages, ["_app.js"])
app_with_10_components._initialize_app()
build.setup_frontend(app_with_10_components.app_path)
def benchmark_fn():
with chdir(app_with_10_components.app_path):
app_with_10_components.app_instance._compile()
benchmark.pedantic(benchmark_fn, setup=setup, rounds=10)
@pytest.mark.benchmark(
group="Compile time of varying component numbers",
min_rounds=5,
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_10_compile_time_warm(benchmark, app_with_10_components):
"""Test the compile time on a warm start for an app with roughly 10 components.
Args:
benchmark: The benchmark fixture.
app_with_10_components: The app harness.
"""
with chdir(app_with_10_components.app_path):
app_with_10_components._initialize_app()
build.setup_frontend(app_with_10_components.app_path)
def benchmark_fn():
with chdir(app_with_10_components.app_path):
app_with_10_components.app_instance._compile()
benchmark(benchmark_fn)
@pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
@pytest.mark.benchmark(
group="Compile time of varying component numbers",
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_100_compile_time_cold(benchmark, app_with_100_components):
"""Test the compile time on a cold start for an app with roughly 100 components.
Args:
benchmark: The benchmark fixture.
app_with_100_components: The app harness.
"""
def setup():
with chdir(app_with_100_components.app_path):
utils.empty_dir(web_pages, ["_app.js"])
app_with_100_components._initialize_app()
build.setup_frontend(app_with_100_components.app_path)
def benchmark_fn():
with chdir(app_with_100_components.app_path):
app_with_100_components.app_instance._compile()
benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
@pytest.mark.benchmark(
group="Compile time of varying component numbers",
min_rounds=5,
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_100_compile_time_warm(benchmark, app_with_100_components):
"""Test the compile time on a warm start for an app with roughly 100 components.
Args:
benchmark: The benchmark fixture.
app_with_100_components: The app harness.
"""
with chdir(app_with_100_components.app_path):
app_with_100_components._initialize_app()
build.setup_frontend(app_with_100_components.app_path)
def benchmark_fn():
with chdir(app_with_100_components.app_path):
app_with_100_components.app_instance._compile()
benchmark(benchmark_fn)
@pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
@pytest.mark.benchmark(
group="Compile time of varying component numbers",
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_1000_compile_time_cold(benchmark, app_with_1000_components):
"""Test the compile time on a cold start for an app with roughly 1000 components.
Args:
benchmark: The benchmark fixture.
app_with_1000_components: The app harness.
"""
def setup():
with chdir(app_with_1000_components.app_path):
utils.empty_dir(web_pages, keep_files=["_app.js"])
app_with_1000_components._initialize_app()
build.setup_frontend(app_with_1000_components.app_path)
def benchmark_fn():
with chdir(app_with_1000_components.app_path):
app_with_1000_components.app_instance._compile()
benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
@pytest.mark.benchmark(
group="Compile time of varying component numbers",
min_rounds=5,
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_1000_compile_time_warm(benchmark, app_with_1000_components):
"""Test the compile time on a warm start for an app with roughly 1000 components.
Args:
benchmark: The benchmark fixture.
app_with_1000_components: The app harness.
"""
with chdir(app_with_1000_components.app_path):
app_with_1000_components._initialize_app()
build.setup_frontend(app_with_1000_components.app_path)
def benchmark_fn():
with chdir(app_with_1000_components.app_path):
app_with_1000_components.app_instance._compile()
benchmark(benchmark_fn)

View File

@ -0,0 +1,579 @@
"""Benchmark tests for apps with varying page numbers."""
from __future__ import annotations
import functools
import time
from typing import Generator
import pytest
from benchmarks import WINDOWS_SKIP_REASON
from reflex import constants
from reflex.compiler import utils
from reflex.testing import AppHarness, chdir
from reflex.utils import build
from reflex.utils.prerequisites import get_web_dir
web_pages = get_web_dir() / constants.Dirs.PAGES
def render_multiple_pages(app, num: int):
"""Add multiple pages based on num.
Args:
app: The App object.
num: number of pages to render.
"""
from typing import Tuple
from rxconfig import config # type: ignore
import reflex as rx
docs_url = "https://reflex.dev/docs/getting-started/introduction/"
filename = f"{config.app_name}/{config.app_name}.py"
college = [
"Stanford University",
"Arizona",
"Arizona state",
"Baylor",
"Boston College",
"Boston University",
]
class State(rx.State):
"""The app state."""
position: str
college: str
age: Tuple[int, int] = (18, 50)
salary: Tuple[int, int] = (0, 25000000)
comp1 = rx.center(
rx.theme_panel(),
rx.vstack(
rx.heading("Welcome to Reflex!", size="9"),
rx.text("Get started by editing ", rx.code(filename)),
rx.button(
"Check out our docs!",
on_click=lambda: rx.redirect(docs_url),
size="4",
),
align="center",
spacing="7",
font_size="2em",
),
height="100vh",
)
comp2 = rx.vstack(
rx.hstack(
rx.vstack(
rx.select(
["C", "PF", "SF", "PG", "SG"],
placeholder="Select a position. (All)",
on_change=State.set_position, # type: ignore
size="3",
),
rx.select(
college,
placeholder="Select a college. (All)",
on_change=State.set_college, # type: ignore
size="3",
),
),
rx.vstack(
rx.vstack(
rx.hstack(
rx.badge("Min Age: ", State.age[0]),
rx.divider(orientation="vertical"),
rx.badge("Max Age: ", State.age[1]),
),
rx.slider(
default_value=[18, 50],
min=18,
max=50,
on_value_commit=State.set_age, # type: ignore
),
align_items="left",
width="100%",
),
rx.vstack(
rx.hstack(
rx.badge("Min Sal: ", State.salary[0] // 1000000, "M"),
rx.divider(orientation="vertical"),
rx.badge("Max Sal: ", State.salary[1] // 1000000, "M"),
),
rx.slider(
default_value=[0, 25000000],
min=0,
max=25000000,
on_value_commit=State.set_salary, # type: ignore
),
align_items="left",
width="100%",
),
),
spacing="4",
),
width="100%",
)
for i in range(1, num + 1):
if i % 2 == 1:
app.add_page(comp1, route=f"page{i}")
else:
app.add_page(comp2, route=f"page{i}")
def AppWithOnePage():
"""A reflex app with one page."""
from rxconfig import config # type: ignore
import reflex as rx
docs_url = "https://reflex.dev/docs/getting-started/introduction/"
filename = f"{config.app_name}/{config.app_name}.py"
class State(rx.State):
"""The app state."""
pass
def index() -> rx.Component:
return rx.center(
rx.input(
id="token", value=State.router.session.client_token, is_read_only=True
),
rx.vstack(
rx.heading("Welcome to Reflex!", size="9"),
rx.text("Get started by editing ", rx.code(filename)),
rx.button(
"Check out our docs!",
on_click=lambda: rx.redirect(docs_url),
size="4",
),
align="center",
spacing="7",
font_size="2em",
),
height="100vh",
)
app = rx.App(_state=rx.State)
app.add_page(index)
def AppWithTenPages():
"""A reflex app with 10 pages."""
import reflex as rx
app = rx.App(_state=rx.State)
render_multiple_pages(app, 10)
def AppWithHundredPages():
"""A reflex app with 100 pages."""
import reflex as rx
app = rx.App(_state=rx.State)
render_multiple_pages(app, 100)
def AppWithThousandPages():
"""A reflex app with Thousand pages."""
import reflex as rx
app = rx.App(_state=rx.State)
render_multiple_pages(app, 1000)
def AppWithTenThousandPages():
"""A reflex app with ten thousand pages."""
import reflex as rx
app = rx.App(_state=rx.State)
render_multiple_pages(app, 10000)
@pytest.fixture(scope="session")
def app_with_one_page(
tmp_path_factory,
) -> Generator[AppHarness, None, None]:
"""Create an app with 10000 pages at tmp_path via AppHarness.
Args:
tmp_path_factory: pytest tmp_path_factory fixture
Yields:
an AppHarness instance
"""
root = tmp_path_factory.mktemp("app1")
yield AppHarness.create(root=root, app_source=AppWithOnePage)
@pytest.fixture(scope="session")
def app_with_ten_pages(
tmp_path_factory,
) -> Generator[AppHarness, None, None]:
"""Create an app with 10 pages at tmp_path via AppHarness.
Args:
tmp_path_factory: pytest tmp_path_factory fixture
Yields:
an AppHarness instance
"""
root = tmp_path_factory.mktemp("app10")
yield AppHarness.create(
root=root,
app_source=functools.partial(
AppWithTenPages,
render_comp=render_multiple_pages, # type: ignore
),
)
@pytest.fixture(scope="session")
def app_with_hundred_pages(
tmp_path_factory,
) -> Generator[AppHarness, None, None]:
"""Create an app with 100 pages at tmp_path via AppHarness.
Args:
tmp_path_factory: pytest tmp_path_factory fixture
Yields:
an AppHarness instance
"""
root = tmp_path_factory.mktemp("app100")
yield AppHarness.create(
root=root,
app_source=functools.partial(
AppWithHundredPages,
render_comp=render_multiple_pages, # type: ignore
),
) # type: ignore
@pytest.fixture(scope="session")
def app_with_thousand_pages(
tmp_path_factory,
) -> Generator[AppHarness, None, None]:
"""Create an app with 1000 pages at tmp_path via AppHarness.
Args:
tmp_path_factory: pytest tmp_path_factory fixture
Yields:
an AppHarness instance
"""
root = tmp_path_factory.mktemp("app1000")
yield AppHarness.create(
root=root,
app_source=functools.partial(
AppWithThousandPages,
render_comp=render_multiple_pages, # type: ignore
),
) # type: ignore
@pytest.fixture(scope="session")
def app_with_ten_thousand_pages(
tmp_path_factory,
) -> Generator[AppHarness, None, None]:
"""Create an app with 10000 pages at tmp_path via AppHarness.
Args:
tmp_path_factory: pytest tmp_path_factory fixture
Yields:
running AppHarness instance
"""
root = tmp_path_factory.mktemp("app10000")
yield AppHarness.create(
root=root,
app_source=functools.partial(
AppWithTenThousandPages,
render_comp=render_multiple_pages, # type: ignore
),
) # type: ignore
@pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
@pytest.mark.benchmark(
group="Compile time of varying page numbers",
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_1_compile_time_cold(benchmark, app_with_one_page):
"""Test the compile time on a cold start for an app with 1 page.
Args:
benchmark: The benchmark fixture.
app_with_one_page: The app harness.
"""
def setup():
with chdir(app_with_one_page.app_path):
utils.empty_dir(web_pages, keep_files=["_app.js"])
app_with_one_page._initialize_app()
build.setup_frontend(app_with_one_page.app_path)
def benchmark_fn():
with chdir(app_with_one_page.app_path):
app_with_one_page.app_instance._compile()
benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
app_with_one_page._reload_state_module()
@pytest.mark.benchmark(
group="Compile time of varying page numbers",
min_rounds=5,
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_1_compile_time_warm(benchmark, app_with_one_page):
"""Test the compile time on a warm start for an app with 1 page.
Args:
benchmark: The benchmark fixture.
app_with_one_page: The app harness.
"""
with chdir(app_with_one_page.app_path):
app_with_one_page._initialize_app()
build.setup_frontend(app_with_one_page.app_path)
def benchmark_fn():
with chdir(app_with_one_page.app_path):
app_with_one_page.app_instance._compile()
benchmark(benchmark_fn)
app_with_one_page._reload_state_module()
@pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
@pytest.mark.benchmark(
group="Compile time of varying page numbers",
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_10_compile_time_cold(benchmark, app_with_ten_pages):
"""Test the compile time on a cold start for an app with 10 page.
Args:
benchmark: The benchmark fixture.
app_with_ten_pages: The app harness.
"""
def setup():
with chdir(app_with_ten_pages.app_path):
utils.empty_dir(web_pages, keep_files=["_app.js"])
app_with_ten_pages._initialize_app()
build.setup_frontend(app_with_ten_pages.app_path)
def benchmark_fn():
with chdir(app_with_ten_pages.app_path):
app_with_ten_pages.app_instance._compile()
benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
app_with_ten_pages._reload_state_module()
@pytest.mark.benchmark(
group="Compile time of varying page numbers",
min_rounds=5,
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_10_compile_time_warm(benchmark, app_with_ten_pages):
"""Test the compile time on a warm start for an app with 10 page.
Args:
benchmark: The benchmark fixture.
app_with_ten_pages: The app harness.
"""
with chdir(app_with_ten_pages.app_path):
app_with_ten_pages._initialize_app()
build.setup_frontend(app_with_ten_pages.app_path)
def benchmark_fn():
with chdir(app_with_ten_pages.app_path):
app_with_ten_pages.app_instance._compile()
benchmark(benchmark_fn)
app_with_ten_pages._reload_state_module()
@pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
@pytest.mark.benchmark(
group="Compile time of varying page numbers",
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_100_compile_time_cold(benchmark, app_with_hundred_pages):
"""Test the compile time on a cold start for an app with 100 page.
Args:
benchmark: The benchmark fixture.
app_with_hundred_pages: The app harness.
"""
def setup():
with chdir(app_with_hundred_pages.app_path):
utils.empty_dir(web_pages, keep_files=["_app.js"])
app_with_hundred_pages._initialize_app()
build.setup_frontend(app_with_hundred_pages.app_path)
def benchmark_fn():
with chdir(app_with_hundred_pages.app_path):
app_with_hundred_pages.app_instance._compile()
benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
app_with_hundred_pages._reload_state_module()
@pytest.mark.benchmark(
group="Compile time of varying page numbers",
min_rounds=5,
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_100_compile_time_warm(benchmark, app_with_hundred_pages):
"""Test the compile time on a warm start for an app with 100 page.
Args:
benchmark: The benchmark fixture.
app_with_hundred_pages: The app harness.
"""
with chdir(app_with_hundred_pages.app_path):
app_with_hundred_pages._initialize_app()
build.setup_frontend(app_with_hundred_pages.app_path)
def benchmark_fn():
with chdir(app_with_hundred_pages.app_path):
app_with_hundred_pages.app_instance._compile()
benchmark(benchmark_fn)
app_with_hundred_pages._reload_state_module()
@pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
@pytest.mark.benchmark(
group="Compile time of varying page numbers",
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_1000_compile_time_cold(benchmark, app_with_thousand_pages):
"""Test the compile time on a cold start for an app with 1000 page.
Args:
benchmark: The benchmark fixture.
app_with_thousand_pages: The app harness.
"""
def setup():
with chdir(app_with_thousand_pages.app_path):
utils.empty_dir(web_pages, keep_files=["_app.js"])
app_with_thousand_pages._initialize_app()
build.setup_frontend(app_with_thousand_pages.app_path)
def benchmark_fn():
with chdir(app_with_thousand_pages.app_path):
app_with_thousand_pages.app_instance._compile()
benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
app_with_thousand_pages._reload_state_module()
@pytest.mark.benchmark(
group="Compile time of varying page numbers",
min_rounds=5,
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_1000_compile_time_warm(benchmark, app_with_thousand_pages):
"""Test the compile time on a warm start for an app with 1000 page.
Args:
benchmark: The benchmark fixture.
app_with_thousand_pages: The app harness.
"""
with chdir(app_with_thousand_pages.app_path):
app_with_thousand_pages._initialize_app()
build.setup_frontend(app_with_thousand_pages.app_path)
def benchmark_fn():
with chdir(app_with_thousand_pages.app_path):
app_with_thousand_pages.app_instance._compile()
benchmark(benchmark_fn)
app_with_thousand_pages._reload_state_module()
@pytest.mark.skip
@pytest.mark.benchmark(
group="Compile time of varying page numbers",
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_10000_compile_time_cold(benchmark, app_with_ten_thousand_pages):
"""Test the compile time on a cold start for an app with 10000 page.
Args:
benchmark: The benchmark fixture.
app_with_ten_thousand_pages: The app harness.
"""
def setup():
with chdir(app_with_ten_thousand_pages.app_path):
utils.empty_dir(web_pages, keep_files=["_app.js"])
app_with_ten_thousand_pages._initialize_app()
build.setup_frontend(app_with_ten_thousand_pages.app_path)
def benchmark_fn():
with chdir(app_with_ten_thousand_pages.app_path):
app_with_ten_thousand_pages.app_instance._compile()
benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
app_with_ten_thousand_pages._reload_state_module()
@pytest.mark.skip
@pytest.mark.benchmark(
group="Compile time of varying page numbers",
min_rounds=5,
timer=time.perf_counter,
disable_gc=True,
warmup=False,
)
def test_app_10000_compile_time_warm(benchmark, app_with_ten_thousand_pages):
"""Test the compile time on a warm start for an app with 10000 page.
Args:
benchmark: The benchmark fixture.
app_with_ten_thousand_pages: The app harness.
"""
def benchmark_fn():
with chdir(app_with_ten_thousand_pages.app_path):
app_with_ten_thousand_pages.app_instance._compile()
benchmark(benchmark_fn)
app_with_ten_thousand_pages._reload_state_module()

View File

@ -239,7 +239,7 @@ Reflex se lanzó en diciembre de 2022 con el nombre de Pynecone.
- **Discusiones de GitHub**: Una excelente manera de hablar sobre las características que deseas agregar o las cosas que te resultan confusas o necesitan aclaración.
- **GitHub Issues**: Las incidencias son una forma excelente de informar de errores. Además, puedes intentar resolver un problema existente y enviar un PR.
Buscamos colaboradores, sin importar su nivel o experiencia. Para contribuir consulta [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
Buscamos colaboradores, sin importar su nivel o experiencia. Para contribuir consulta [CONTIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
## Licencia

View File

@ -239,7 +239,7 @@ Reflex में हर सप्ताह नए रिलीज़ और फ
- **GitHub Discussions** (गिटहब चर्चाएँ): उन सुविधाओं के बारे में बात करने का एक शानदार तरीका जिन्हें आप जोड़ना चाहते हैं या ऐसी चीज़ें जो भ्रमित करने वाली हैं/स्पष्टीकरण की आवश्यकता है।
- **GitHub Issues** (गिटहब समस्याएं): ये [बग](https://github.com/reflex-dev/reflex/issues) की रिपोर्ट करने का एक शानदार तरीका है। इसके अतिरिक्त, आप किसी मौजूदा समस्या को हल करने का प्रयास कर सकते हैं और एक पीआर सबमिट कर सकते हैं।
हम सक्रिय रूप से योगदानकर्ताओं की तलाश कर रहे हैं, चाहे आपका कौशल स्तर या अनुभव कुछ भी हो।योगदान करने के लिए [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) देखें।
हम सक्रिय रूप से योगदानकर्ताओं की तलाश कर रहे हैं, चाहे आपका कौशल स्तर या अनुभव कुछ भी हो।योगदान करने के लिए [CONTIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) देखें।
## हमारे सभी योगदानकर्ताओं का धन्यवाद:

View File

@ -222,7 +222,7 @@ app.add_page(index, title="DALL-E")
<div align="center">
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Gallery](https://reflex.dev/docs/gallery) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;
</div>
@ -242,7 +242,7 @@ Reflex は毎週、新しいリリースや機能追加を行っています!
- **GitHub Discussions**: GitHub Discussions では、追加したい機能や、複雑で解明が必要な事柄についての議論に適している場所です。
- **GitHub Issues**: [Issues](https://github.com/reflex-dev/reflex/issues)はバグの報告に適している場所です。また、課題を解決した PR のサブミットにチャレンジしていただくことも、可能です。
CONTスキルや経験に関わらず、私たちはコントリビュータを積極的に探しています。コントリビュートするために、[CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)をご覧ください。
スキルや経験に関わらず、私たちはコントリビュータを積極的に探しています。コントリビュートするために、[CONTIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)をご覧ください。
## 私たちのコントリビュータに感謝!:

View File

@ -249,7 +249,7 @@ app.add_page(index, title="DALL-E")
- **بحث های GitHub**: راهی عالی برای صحبت در مورد ویژگی هایی که می خواهید اضافه کنید یا چیزهایی که گیج کننده هستند/نیاز به توضیح دارند.
- **قسمت مشکلات GitHub**: [قسمت مشکلات](https://github.com/reflex-dev/reflex/issues) یک راه عالی برای گزارش اشکال هستند. علاوه بر این، می توانید یک مشکل موجود را حل کنید و یک PR(pull request) ارسال کنید.
ما فعالانه به دنبال مشارکت کنندگان هستیم، فارغ از سطح مهارت یا تجربه شما. برای مشارکت [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) را بررسی کنید.
ما فعالانه به دنبال مشارکت کنندگان هستیم، فارغ از سطح مهارت یا تجربه شما. برای مشارکت [CONTIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) را بررسی کنید.
## All Thanks To Our Contributors - با تشکر از همکاران ما:

View File

@ -200,7 +200,7 @@ Daha fazla sayfa ekleyerek çok sayfalı bir uygulama oluşturabilirsiniz.
<div align="center">
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy) &nbsp;
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Gallery](https://reflex.dev/docs/gallery) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy) &nbsp;
</div>
@ -229,7 +229,7 @@ Her boyuttaki katkıları memnuniyetle karşılıyoruz! Aşağıda Reflex toplul
- **GitHub Discussions**: Eklemek istediğiniz özellikler veya kafa karıştırıcı, açıklığa kavuşturulması gereken şeyler hakkında konuşmanın harika bir yolu.
- **GitHub Issues**: [Issues](https://github.com/reflex-dev/reflex/issues) hataları bildirmenin mükemmel bir yoludur. Ayrıca mevcut bir sorunu deneyip çözebilir ve bir PR (Pull Requests) gönderebilirsiniz.
Beceri düzeyiniz veya deneyiminiz ne olursa olsun aktif olarak katkıda bulunacak kişiler arıyoruz. Katkı sağlamak için katkı sağlama rehberimize bakabilirsiniz: [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
Beceri düzeyiniz veya deneyiminiz ne olursa olsun aktif olarak katkıda bulunacak kişiler arıyoruz. Katkı sağlamak için katkı sağlama rehberimize bakabilirsiniz: [CONTIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
## Hepsi Katkıda Bulunanlar Sayesinde:

View File

@ -232,7 +232,7 @@ Bạn có thể tạo một ứng dụng nhiều trang bằng cách thêm trang.
<div align="center">
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Gallery](https://reflex.dev/docs/gallery) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;
</div>
@ -254,7 +254,7 @@ Chúng tôi chào đón mọi đóng góp dù lớn hay nhỏ. Dưới đây là
- **GitHub Issues**: [Issues](https://github.com/reflex-dev/reflex/issues) là nơi tốt nhất để thông báo. Ngoài ra bạn có thể sửa chữa các vấn đề bằng cách tạo PR.
Chúng tôi luôn sẵn sàng tìm kiếm các contributor, bất kể kinh nghiệm. Để tham gia đóng góp, xin mời xem
[CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
[CONTIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
## Xin cảm ơn các Contributors:

View File

@ -229,7 +229,7 @@ app.add_page(index, title="DALL-E")
<div align="center">
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Gallery](https://reflex.dev/docs/gallery) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;
</div>
@ -251,7 +251,7 @@ Reflex 每周都有新功能和釋出新版本! 確保你按下 :star: 和 :eyes
- **GitHub Discussions**: 這是一個討論您想新增的功能或對於一些困惑/需要澄清事項的好方法。
- **GitHub Issues**: 在 [Issues](https://github.com/reflex-dev/reflex/issues) 頁面報告錯誤是一個絕佳的方式。此外,您也可以嘗試解決現有 Issue 並提交 PR。
我們積極尋找貢獻者,不論您的技能水平或經驗如何。要貢獻,請查看 [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
我們積極尋找貢獻者,不論您的技能水平或經驗如何。要貢獻,請查看 [CONTIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
## 感謝所有貢獻者:

983
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[tool.poetry]
name = "reflex"
version = "0.7.2dev1"
version = "0.7.0dev1"
description = "Web apps in pure Python."
license = "Apache-2.0"
authors = [
@ -18,27 +18,30 @@ keywords = ["web", "framework"]
classifiers = ["Development Status :: 4 - Beta"]
[tool.poetry.dependencies]
python = ">=3.10, <4.0"
python = "^3.10"
fastapi = ">=0.96.0,!=0.111.0,!=0.111.1"
gunicorn = ">=20.1.0,<24.0"
jinja2 = ">=3.1.2,<4.0"
psutil = ">=5.9.4,<7.0"
pydantic = ">=1.10.21,<3.0"
pydantic = ">=1.10.17,<3.0"
python-multipart = ">=0.0.5,<0.1"
python-socketio = ">=5.7.0,<6.0"
redis = ">=4.3.5,<6.0"
rich = ">=13.0.0,<14.0"
sqlmodel = ">=0.0.14,<0.1"
typer = ">=0.15.1,<1.0"
typer = ">=0.4.2,<1.0"
uvicorn = ">=0.20.0"
starlette-admin = ">=0.11.0,<1.0"
alembic = ">=1.11.1,<2.0"
platformdirs = ">=3.10.0,<5.0"
distro = { version = ">=1.8.0,<2.0", platform = "linux" }
python-engineio = "!=4.6.0"
wrapt = ">=1.17.0,<2.0"
wrapt = [
{ version = ">=1.14.0,<2.0", python = ">=3.11" },
{ version = ">=1.11.0,<2.0", python = "<3.11" },
]
packaging = ">=23.1,<25.0"
reflex-hosting-cli = ">=0.1.29"
reflex-hosting-cli = ">=0.1.29,<2.0"
charset-normalizer = ">=3.3.2,<4.0"
wheel = ">=0.42.0,<1.0"
build = ">=1.0.3,<2.0"
@ -52,13 +55,13 @@ typing_extensions = ">=4.6.0"
[tool.poetry.group.dev.dependencies]
pytest = ">=7.1.2,<9.0"
pytest-mock = ">=3.10.0,<4.0"
pyright = ">=1.1.394, <1.2"
pyright = ">=1.1.392.post0,<1.2"
darglint = ">=1.8.1,<2.0"
dill = ">=0.3.8"
toml = ">=0.10.2,<1.0"
pytest-asyncio = ">=0.24.0"
pytest-cov = ">=4.0.0,<7.0"
ruff = "0.9.6"
ruff = "0.8.2"
pandas = ">=2.1.1,<3.0"
pillow = ">=10.0.0,<12.0"
plotly = ">=5.13.0,<6.0"
@ -68,7 +71,6 @@ selenium = ">=4.11.0,<5.0"
pytest-benchmark = ">=4.0.0,<6.0"
playwright = ">=1.46.0"
pytest-playwright = ">=0.5.1"
pytest-codspeed = "^3.1.2"
[tool.poetry.scripts]
reflex = "reflex.reflex:cli"
@ -79,56 +81,27 @@ build-backend = "poetry.core.masonry.api"
[tool.pyright]
reportIncompatibleMethodOverride = false
reportIncompatibleVariableOverride = false
[tool.ruff]
target-version = "py310"
target-version = "py39"
output-format = "concise"
lint.isort.split-on-trailing-comma = false
lint.select = [
"ANN001",
"B",
"C4",
"D",
"E",
"ERA",
"F",
"FURB",
"I",
"N",
"PERF",
"PGH",
"PTH",
"RUF",
"SIM",
"T",
"TRY",
"W",
]
lint.ignore = [
"B008",
"D205",
"E501",
"F403",
"SIM115",
"RUF006",
"RUF008",
"RUF012",
"TRY0",
]
lint.select = ["B", "C4", "D", "E", "ERA", "F", "FURB", "I", "N", "PERF", "PTH", "RUF", "SIM", "T", "TRY", "W"]
lint.ignore = ["B008", "D205", "E501", "F403", "SIM115", "RUF006", "RUF012", "TRY0"]
lint.pydocstyle.convention = "google"
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
"tests/*.py" = ["ANN001", "D100", "D103", "D104", "B018", "PERF", "T", "N"]
"benchmarks/*.py" = ["ANN001", "D100", "D103", "D104", "B018", "PERF", "T", "N"]
"tests/*.py" = ["D100", "D103", "D104", "B018", "PERF", "T", "N"]
"benchmarks/*.py" = ["D100", "D103", "D104", "B018", "PERF", "T", "N"]
"reflex/.templates/*.py" = ["D100", "D103", "D104"]
"*.pyi" = ["D301", "D415", "D417", "D418", "E742", "N", "PGH"]
"*.pyi" = ["D301", "D415", "D417", "D418", "E742", "N"]
"pyi_generator.py" = ["N802"]
"reflex/constants/*.py" = ["N"]
"*/blank.py" = ["I001"]
[tool.pytest.ini_options]
filterwarnings = "ignore:fields may not start with an underscore:RuntimeWarning"
asyncio_default_fixture_loop_scope = "function"
asyncio_mode = "auto"

View File

@ -16,12 +16,6 @@
{% for package, version in dev_dependencies.items() %}
"{{ package }}": "{{ version }}"{% if not loop.last %},{% endif %}
{% endfor %}
},
"overrides": {
{% for package, version in overrides.items() %}
"{{ package }}": "{{ version }}"{% if not loop.last %},{% endif %}
{% endfor %}
}
}

View File

@ -38,13 +38,13 @@ export default function MyApp({ Component, pageProps }) {
}, []);
return (
<ThemeProvider defaultTheme={ defaultColorMode } attribute="class">
<StateProvider>
<EventLoopProvider>
<AppWrap>
<Component {...pageProps} />
</AppWrap>
</EventLoopProvider>
</StateProvider>
<AppWrap>
<StateProvider>
<EventLoopProvider>
<Component {...pageProps} />
</EventLoopProvider>
</StateProvider>
</AppWrap>
</ThemeProvider>
);
}

View File

@ -6,12 +6,6 @@
{% filter indent(width=indent_width) %}
{%- if component is not mapping %}
{{- component }}
{%- elif "iterable" in component %}
{{- render_iterable_tag(component) }}
{%- elif component.name == "match"%}
{{- render_match_tag(component) }}
{%- elif "cond" in component %}
{{- render_condition_tag(component) }}
{%- elif component.children|length %}
{{- render_tag(component) }}
{%- else %}
@ -44,30 +38,6 @@
{%- endmacro %}
{# Rendering condition component. #}
{# Args: #}
{# component: component dictionary #}
{% macro render_condition_tag(component) %}
{ {{- component.cond_state }} ? (
{{ render(component.true_value) }}
) : (
{{ render(component.false_value) }}
)}
{%- endmacro %}
{# Rendering iterable component. #}
{# Args: #}
{# component: component dictionary #}
{% macro render_iterable_tag(component) %}
<>{ {{ component.iterable_state }}.map(({{ component.arg_name }}, {{ component.arg_index }}) => (
{% for child in component.children %}
{{ render(child) }}
{% endfor %}
))}</>
{%- endmacro %}
{# Rendering props of a component. #}
{# Args: #}
{# component: component dictionary #}
@ -75,29 +45,6 @@
{% if props|length %} {{ props|join(" ") }}{% endif %}
{% endmacro %}
{# Rendering Match component. #}
{# Args: #}
{# component: component dictionary #}
{% macro render_match_tag(component) %}
{
(() => {
switch (JSON.stringify({{ component.cond._js_expr }})) {
{% for case in component.match_cases %}
{% for condition in case[:-1] %}
case JSON.stringify({{ condition._js_expr }}):
{% endfor %}
return {{ render(case[-1]) }};
break;
{% endfor %}
default:
return {{ render(component.default) }};
break;
}
})()
}
{%- endmacro %}
{# Rendering content with args. #}
{# Args: #}
{# component: component dictionary #}

View File

@ -78,9 +78,9 @@ export function UploadFilesProvider({ children }) {
return newFilesById
})
return (
<UploadFilesContext value={[filesById, setFilesById]}>
<UploadFilesContext.Provider value={[filesById, setFilesById]}>
{children}
</UploadFilesContext>
</UploadFilesContext.Provider>
)
}
@ -92,9 +92,9 @@ export function EventLoopProvider({ children }) {
clientStorage,
)
return (
<EventLoopContext value={[addEvents, connectErrors]}>
<EventLoopContext.Provider value={[addEvents, connectErrors]}>
{children}
</EventLoopContext>
</EventLoopContext.Provider>
)
}
@ -112,13 +112,13 @@ export function StateProvider({ children }) {
return (
{% for state_name in initial_state %}
<StateContexts.{{state_name|var_name}} value={ {{state_name|var_name}} }>
<StateContexts.{{state_name|var_name}}.Provider value={ {{state_name|var_name}} }>
{% endfor %}
<DispatchContext value={dispatchers}>
<DispatchContext.Provider value={dispatchers}>
{children}
</DispatchContext>
</DispatchContext.Provider>
{% for state_name in initial_state|reverse %}
</StateContexts.{{state_name|var_name}}>
</StateContexts.{{state_name|var_name}}.Provider>
{% endfor %}
)
}

View File

@ -10,9 +10,7 @@ import {
export default function RadixThemesColorModeProvider({ children }) {
const { theme, resolvedTheme, setTheme } = useTheme();
const [rawColorMode, setRawColorMode] = useState(defaultColorMode);
const [resolvedColorMode, setResolvedColorMode] = useState(
defaultColorMode === "dark" ? "dark" : "light"
);
const [resolvedColorMode, setResolvedColorMode] = useState("dark");
useEffect(() => {
if (isDevMode) {
@ -36,17 +34,17 @@ export default function RadixThemesColorModeProvider({ children }) {
const allowedModes = ["light", "dark", "system"];
if (!allowedModes.includes(mode)) {
console.error(
`Invalid color mode "${mode}". Defaulting to "${defaultColorMode}".`,
`Invalid color mode "${mode}". Defaulting to "${defaultColorMode}".`
);
mode = defaultColorMode;
}
setTheme(mode);
};
return (
<ColorModeContext
<ColorModeContext.Provider
value={{ rawColorMode, resolvedColorMode, toggleColorMode, setColorMode }}
>
{children}
</ColorModeContext>
</ColorModeContext.Provider>
);
}

View File

@ -11,33 +11,33 @@
* @returns {object} an object with a Symbol.iterator method over the range
*/
export default function range(start, stop, step) {
return {
[Symbol.iterator]() {
if (stop === undefined) {
stop = start;
start = 0;
}
if (step === undefined) {
step = 1;
}
return {
[Symbol.iterator]() {
if ((stop ?? undefined) === undefined) {
stop = start;
start = 0;
}
if ((step ?? undefined) === undefined) {
step = 1;
}
let i = start - step;
let i = start - step;
return {
next() {
i += step;
if ((step > 0 && i < stop) || (step < 0 && i > stop)) {
return {
value: i,
done: false,
};
}
return {
next() {
i += step;
if ((step > 0 && i < stop) || (step < 0 && i > stop)) {
return {
value: undefined,
done: true,
value: i,
done: false,
};
},
};
},
};
}
}
return {
value: undefined,
done: true,
};
},
};
},
};
}

View File

@ -106,18 +106,6 @@ export const getBackendURL = (url_str) => {
return endpoint;
};
/**
* Check if the backend is disabled.
*
* @returns True if the backend is disabled, false otherwise.
*/
export const isBackendDisabled = () => {
const cookie = document.cookie
.split("; ")
.find((row) => row.startsWith("backend-enabled="));
return cookie !== undefined && cookie.split("=")[1] == "false";
};
/**
* Determine if any event in the event queue is stateful.
*
@ -227,8 +215,8 @@ export const applyEvent = async (event, socket) => {
a.href = eval?.(
event.payload.url.replace(
"getBackendURL(env.UPLOAD)",
`"${getBackendURL(env.UPLOAD)}"`,
),
`"${getBackendURL(env.UPLOAD)}"`
)
);
}
a.download = event.payload.filename;
@ -341,7 +329,7 @@ export const applyRestEvent = async (event, socket) => {
event.payload.files,
event.payload.upload_id,
event.payload.on_upload_progress,
socket,
socket
);
return false;
}
@ -408,7 +396,7 @@ export const connect = async (
dispatch,
transports,
setConnectErrors,
client_storage = {},
client_storage = {}
) => {
// Get backend URL object from the endpoint.
const endpoint = getBackendURL(EVENTURL);
@ -417,7 +405,7 @@ export const connect = async (
socket.current = io(endpoint.href, {
path: endpoint["pathname"],
transports: transports,
protocols: [reflexEnvironment.version],
protocols: env.TEST_MODE ? undefined : [reflexEnvironment.version],
autoUnref: false,
});
// Ensure undefined fields in events are sent as null instead of removed
@ -499,7 +487,7 @@ export const uploadFiles = async (
files,
upload_id,
on_upload_progress,
socket,
socket
) => {
// return if there's no file to upload
if (files === undefined || files.length === 0) {
@ -604,7 +592,7 @@ export const Event = (
name,
payload = {},
event_actions = {},
handler = null,
handler = null
) => {
return { name, payload, handler, event_actions };
};
@ -631,7 +619,7 @@ export const hydrateClientStorage = (client_storage) => {
for (const state_key in client_storage.local_storage) {
const options = client_storage.local_storage[state_key];
const local_storage_value = localStorage.getItem(
options.name || state_key,
options.name || state_key
);
if (local_storage_value !== null) {
client_storage_values[state_key] = local_storage_value;
@ -642,7 +630,7 @@ export const hydrateClientStorage = (client_storage) => {
for (const state_key in client_storage.session_storage) {
const session_options = client_storage.session_storage[state_key];
const session_storage_value = sessionStorage.getItem(
session_options.name || state_key,
session_options.name || state_key
);
if (session_storage_value != null) {
client_storage_values[state_key] = session_storage_value;
@ -667,7 +655,7 @@ export const hydrateClientStorage = (client_storage) => {
const applyClientStorageDelta = (client_storage, delta) => {
// find the main state and check for is_hydrated
const unqualified_states = Object.keys(delta).filter(
(key) => key.split(".").length === 1,
(key) => key.split(".").length === 1
);
if (unqualified_states.length === 1) {
const main_state = delta[unqualified_states[0]];
@ -701,7 +689,7 @@ const applyClientStorageDelta = (client_storage, delta) => {
const session_options = client_storage.session_storage[state_key];
sessionStorage.setItem(
session_options.name || state_key,
delta[substate][key],
delta[substate][key]
);
}
}
@ -721,7 +709,7 @@ const applyClientStorageDelta = (client_storage, delta) => {
export const useEventLoop = (
dispatch,
initial_events = () => [],
client_storage = {},
client_storage = {}
) => {
const socket = useRef(null);
const router = useRouter();
@ -735,7 +723,7 @@ export const useEventLoop = (
event_actions = events.reduce(
(acc, e) => ({ ...acc, ...e.event_actions }),
event_actions ?? {},
event_actions ?? {}
);
const _e = args.filter((o) => o?.preventDefault !== undefined)[0];
@ -763,7 +751,7 @@ export const useEventLoop = (
debounce(
combined_name,
() => queueEvents(events, socket),
event_actions.debounce,
event_actions.debounce
);
} else {
queueEvents(events, socket);
@ -782,7 +770,7 @@ export const useEventLoop = (
query,
asPath,
}))(router),
})),
}))
);
sentHydrate.current = true;
}
@ -817,10 +805,14 @@ export const useEventLoop = (
};
}, []);
// Handle socket connect/disconnect.
// Main event loop.
useEffect(() => {
// only use websockets if state is present and backend is not disabled (reflex cloud).
if (Object.keys(initialState).length > 1 && !isBackendDisabled()) {
// Skip if the router is not ready.
if (!router.isReady) {
return;
}
// only use websockets if state is present
if (Object.keys(initialState).length > 1) {
// Initialize the websocket connection.
if (!socket.current) {
connect(
@ -828,31 +820,16 @@ export const useEventLoop = (
dispatch,
["websocket"],
setConnectErrors,
client_storage,
client_storage
);
}
(async () => {
// Process all outstanding events.
while (event_queue.length > 0 && !event_processing) {
await processEvent(socket.current);
}
})();
}
// Cleanup function.
return () => {
if (socket.current) {
socket.current.disconnect();
}
};
}, []);
// Main event loop.
useEffect(() => {
// Skip if the router is not ready.
if (!router.isReady || isBackendDisabled()) {
return;
}
(async () => {
// Process all outstanding events.
while (event_queue.length > 0 && !event_processing) {
await processEvent(socket.current);
}
})();
});
// localStorage event handling
@ -876,7 +853,7 @@ export const useEventLoop = (
vars[storage_to_state_map[e.key]] = e.newValue;
const event = Event(
`${state_name}.reflex___state____update_vars_internal_state.update_vars_internal`,
{ vars: vars },
{ vars: vars }
);
addEvents([event], e);
}
@ -926,6 +903,45 @@ export const isTrue = (val) => {
return Boolean(val);
};
/**
* Returns a copy of a section of an array.
* @param {Array | string} arrayLike The array to slice.
* @param {[number, number, number]} slice The slice to apply.
* @returns The sliced array.
*/
export const atSlice = (arrayLike, slice) => {
const array = [...arrayLike];
const [startSlice, endSlice, stepSlice] = slice;
if (stepSlice ?? null === null) {
return array.slice(startSlice ?? undefined, endSlice ?? undefined);
}
const step = stepSlice ?? 1;
if (step > 0) {
return array
.slice(startSlice ?? undefined, endSlice ?? undefined)
.filter((_, i) => i % step === 0);
}
const actualStart = (endSlice ?? null) === null ? 0 : endSlice + 1;
const actualEnd =
(startSlice ?? null) === null ? array.length : startSlice + 1;
return array
.slice(actualStart, actualEnd)
.reverse()
.filter((_, i) => i % step === 0);
};
/**
* Get the value at a slice or index.
* @param {Array | string} arrayLike The array to get the value from.
* @param {number | [number, number, number]} sliceOrIndex The slice or index to get the value at.
* @returns The value at the slice or index.
*/
export const atSliceOrIndex = (arrayLike, sliceOrIndex) => {
return Array.isArray(sliceOrIndex)
? atSlice(arrayLike, sliceOrIndex)
: arrayLike.at(sliceOrIndex);
};
/**
* Get the value from a ref.
* @param ref The ref to get the value from.
@ -969,7 +985,7 @@ export const getRefValues = (refs) => {
return refs.map((ref) =>
ref.current
? ref.current.value || ref.current.getAttribute("aria-valuenow")
: null,
: null
);
};

View File

@ -84,9 +84,6 @@ In the example above, you will be able to do `rx.list`
from __future__ import annotations
from types import ModuleType
from typing import Any
from reflex.utils import (
compat, # for side-effects
lazy_loader,
@ -248,7 +245,6 @@ COMPONENTS_CORE_MAPPING: dict = {
"selected_files",
"upload",
],
"components.core.auto_scroll": ["auto_scroll"],
}
COMPONENTS_BASE_MAPPING: dict = {
@ -369,5 +365,5 @@ getattr, __dir__, __all__ = lazy_loader.attach(
)
def __getattr__(name: ModuleType | Any):
def __getattr__(name):
return getattr(name)

View File

@ -34,7 +34,6 @@ from .components.component import Component as Component
from .components.component import ComponentNamespace as ComponentNamespace
from .components.component import NoSSRComponent as NoSSRComponent
from .components.component import memo as memo
from .components.core.auto_scroll import auto_scroll as auto_scroll
from .components.core.banner import connection_banner as connection_banner
from .components.core.banner import connection_modal as connection_modal
from .components.core.breakpoints import breakpoints as breakpoints
@ -132,7 +131,7 @@ from .components.radix.themes.layout.container import container as container
from .components.radix.themes.layout.flex import flex as flex
from .components.radix.themes.layout.grid import grid as grid
from .components.radix.themes.layout.list import list_item as list_item
from .components.radix.themes.layout.list import list_ns as list # noqa: F401
from .components.radix.themes.layout.list import list_ns as list # noqa
from .components.radix.themes.layout.list import ordered_list as ordered_list
from .components.radix.themes.layout.list import unordered_list as unordered_list
from .components.radix.themes.layout.section import section as section

View File

@ -11,22 +11,22 @@ import functools
import inspect
import io
import json
import multiprocessing
import platform
import sys
import traceback
from datetime import datetime
from pathlib import Path
from timeit import default_timer as timer
from types import SimpleNamespace
from typing import (
TYPE_CHECKING,
Any,
AsyncIterator,
BinaryIO,
Callable,
Coroutine,
Dict,
Generic,
List,
MutableMapping,
Optional,
Set,
Type,
@ -35,15 +35,12 @@ from typing import (
get_type_hints,
)
from fastapi import FastAPI, HTTPException, Request
from fastapi import UploadFile as FastAPIUploadFile
from fastapi import FastAPI, HTTPException, Request, UploadFile
from fastapi.middleware import cors
from fastapi.responses import JSONResponse, StreamingResponse
from fastapi.staticfiles import StaticFiles
from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn
from socketio import ASGIApp, AsyncNamespace, AsyncServer
from starlette.datastructures import Headers
from starlette.datastructures import UploadFile as StarletteUploadFile
from starlette_admin.contrib.sqla.admin import Admin
from starlette_admin.contrib.sqla.view import ModelView
@ -56,35 +53,30 @@ from reflex.compiler.compiler import ExecutorSafeFunctions, compile_theme
from reflex.components.base.app_wrap import AppWrap
from reflex.components.base.error_boundary import ErrorBoundary
from reflex.components.base.fragment import Fragment
from reflex.components.base.strict_mode import StrictMode
from reflex.components.component import (
Component,
ComponentStyle,
evaluate_style_namespaces,
)
from reflex.components.core.banner import (
backend_disabled,
connection_pulser,
connection_toaster,
)
from reflex.components.core.banner import connection_pulser, connection_toaster
from reflex.components.core.breakpoints import set_breakpoints
from reflex.components.core.client_side_routing import (
Default404Page,
wait_for_client_redirect,
)
from reflex.components.core.sticky import sticky
from reflex.components.core.upload import Upload, get_upload_dir
from reflex.components.radix import themes
from reflex.components.sonner.toast import toast
from reflex.config import ExecutorType, environment, get_config
from reflex.config import environment, get_config
from reflex.event import (
_EVENT_FIELDS,
BASE_STATE,
Event,
EventHandler,
EventSpec,
EventType,
IndividualEventType,
get_hydrate_event,
window_alert,
)
from reflex.model import Model, get_db_status
from reflex.page import DECORATED_PAGES
@ -100,25 +92,15 @@ from reflex.state import (
StateManager,
StateUpdate,
_substate_key,
all_base_state_classes,
code_uses_state_contexts,
)
from reflex.utils import (
codespaces,
console,
exceptions,
format,
path_ops,
prerequisites,
types,
)
from reflex.utils.exec import get_compile_context, is_prod_mode, is_testing_env
from reflex.utils import codespaces, console, exceptions, format, prerequisites, types
from reflex.utils.exec import is_prod_mode, is_testing_env
from reflex.utils.imports import ImportVar
if TYPE_CHECKING:
from reflex.vars import Var
# Define custom types.
ComponentCallable = Callable[[], Component]
Reducer = Callable[[Event], Coroutine[Any, Any, StateUpdate]]
@ -144,7 +126,7 @@ def default_backend_exception_handler(exception: Exception) -> EventSpec:
EventSpec: The window alert event.
"""
from reflex.components.sonner.toast import toast
from reflex.components.sonner.toast import Toaster, toast
error = traceback.format_exc()
@ -155,44 +137,18 @@ def default_backend_exception_handler(exception: Exception) -> EventSpec:
if is_prod_mode()
else [f"{type(exception).__name__}: {exception}.", "See logs for details."]
)
return toast(
"An error occurred.",
level="error",
fallback_to_alert=True,
description="<br/>".join(error_message),
position="top-center",
id="backend_error",
style={"width": "500px"},
)
def extra_overlay_function() -> Optional[Component]:
"""Extra overlay function to add to the overlay component.
Returns:
The extra overlay function.
"""
config = get_config()
extra_config = config.extra_overlay_function
config_overlay = None
if extra_config:
module, _, function_name = extra_config.rpartition(".")
try:
module = __import__(module)
config_overlay = Fragment.create(getattr(module, function_name)())
config_overlay._get_all_imports()
except Exception as e:
from reflex.compiler.utils import save_error
log_path = save_error(e)
console.error(
f"Error loading extra_overlay_function {extra_config}. Error saved to {log_path}"
)
return config_overlay
if Toaster.is_used:
return toast(
"An error occurred.",
level="error",
description="<br/>".join(error_message),
position="top-center",
id="backend_error",
style={"width": "500px"},
) # type: ignore
else:
error_message.insert(0, "An error occurred.")
return window_alert("\n".join(error_message))
def default_overlay_component() -> Component:
@ -201,21 +157,11 @@ def default_overlay_component() -> Component:
Returns:
The default overlay_component, which is a connection_modal.
"""
from reflex.components.component import memo
def default_overlay_components():
return Fragment.create(
connection_pulser(),
connection_toaster(),
*(
[backend_disabled()]
if get_compile_context() == constants.CompileContext.DEPLOY
else []
),
*codespaces.codespaces_auto_redirect(),
)
return Fragment.create(memo(default_overlay_components)())
return Fragment.create(
connection_pulser(),
connection_toaster(),
*codespaces.codespaces_auto_redirect(),
)
def default_error_boundary(*children: Component) -> Component:
@ -237,57 +183,10 @@ class OverlayFragment(Fragment):
pass
@dataclasses.dataclass(frozen=True)
class UploadFile(StarletteUploadFile):
"""A file uploaded to the server.
Args:
file: The standard Python file object (non-async).
filename: The original file name.
size: The size of the file in bytes.
headers: The headers of the request.
"""
file: BinaryIO
path: Optional[Path] = dataclasses.field(default=None)
_deprecated_filename: Optional[str] = dataclasses.field(default=None)
size: Optional[int] = dataclasses.field(default=None)
headers: Headers = dataclasses.field(default_factory=Headers)
@property
def name(self) -> Optional[str]:
"""Get the name of the uploaded file.
Returns:
The name of the uploaded file.
"""
if self.path:
return self.path.name
@property
def filename(self) -> Optional[str]:
"""Get the filename of the uploaded file.
Returns:
The filename of the uploaded file.
"""
console.deprecate(
feature_name="UploadFile.filename",
reason="Use UploadFile.name instead.",
deprecation_version="0.7.1",
removal_version="0.8.0",
)
return self._deprecated_filename
@dataclasses.dataclass(
frozen=True,
)
class UnevaluatedPage:
class UnevaluatedPage(Generic[BASE_STATE]):
"""An uncompiled page."""
component: Union[Component, ComponentCallable]
@ -295,7 +194,7 @@ class UnevaluatedPage:
title: Union[Var, str, None]
description: Union[Var, str, None]
image: str
on_load: Union[EventType[()], None]
on_load: Union[EventType[[], BASE_STATE], None]
meta: List[Dict[str, str]]
@ -334,26 +233,11 @@ class App(MiddlewareMixin, LifespanMixin):
# A component that is present on every page (defaults to the Connection Error banner).
overlay_component: Optional[Union[Component, ComponentCallable]] = (
dataclasses.field(default=None)
dataclasses.field(default_factory=default_overlay_component)
)
# Error boundary component to wrap the app with.
error_boundary: Optional[ComponentCallable] = dataclasses.field(default=None)
# App wraps to be applied to the whole app. Expected to be a dictionary of (order, name) to a function that takes whether the state is enabled and optionally returns a component.
app_wraps: Dict[tuple[int, str], Callable[[bool], Optional[Component]]] = (
dataclasses.field(
default_factory=lambda: {
(55, "ErrorBoundary"): (
lambda stateful: default_error_boundary() if stateful else None
),
(5, "Overlay"): (
lambda stateful: default_overlay_component() if stateful else None
),
(4, "ExtraOverlay"): lambda stateful: extra_overlay_function(),
}
)
)
error_boundary: Optional[ComponentCallable] = default_error_boundary
# Components to add to the head of every page.
head_components: List[Component] = dataclasses.field(default_factory=list)
@ -375,9 +259,6 @@ class App(MiddlewareMixin, LifespanMixin):
# A map from a page route to the component to render. Users should use `add_page`.
_pages: Dict[str, Component] = dataclasses.field(default_factory=dict)
# A mapping of pages which created states as they were being evaluated.
_stateful_pages: Dict[str, None] = dataclasses.field(default_factory=dict)
# The backend API object.
_api: FastAPI | None = None
@ -388,7 +269,7 @@ class App(MiddlewareMixin, LifespanMixin):
_state_manager: Optional[StateManager] = None
# Mapping from a route to event handlers to trigger when the page loads.
_load_events: Dict[str, List[IndividualEventType[()]]] = dataclasses.field(
_load_events: Dict[str, List[IndividualEventType[[], Any]]] = dataclasses.field(
default_factory=dict
)
@ -411,9 +292,6 @@ class App(MiddlewareMixin, LifespanMixin):
[Exception], Union[EventSpec, List[EventSpec], None]
] = default_backend_exception_handler
# Put the toast provider in the app wrap.
toaster: Component | None = dataclasses.field(default_factory=toast.provider)
@property
def api(self) -> FastAPI | None:
"""Get the backend api.
@ -527,36 +405,7 @@ class App(MiddlewareMixin, LifespanMixin):
self.sio.register_namespace(self.event_namespace)
# Mount the socket app with the API.
if self.api:
class HeaderMiddleware:
def __init__(self, app: ASGIApp):
self.app = app
async def __call__(
self, scope: MutableMapping[str, Any], receive: Any, send: Callable
):
original_send = send
async def modified_send(message: dict):
if message["type"] == "websocket.accept":
if scope.get("subprotocols"):
# The following *does* say "subprotocol" instead of "subprotocols", intentionally.
message["subprotocol"] = scope["subprotocols"][0]
headers = dict(message.get("headers", []))
header_key = b"sec-websocket-protocol"
if subprotocol := headers.get(header_key):
message["headers"] = [
*message.get("headers", []),
(header_key, subprotocol),
]
return await original_send(message)
return await self.app(scope, receive, modified_send)
socket_app_with_headers = HeaderMiddleware(socket_app)
self.api.mount(str(constants.Endpoint.EVENT), socket_app_with_headers)
self.api.mount(str(constants.Endpoint.EVENT), socket_app)
# Check the exception handlers
self._validate_exception_handlers()
@ -595,10 +444,8 @@ class App(MiddlewareMixin, LifespanMixin):
"""Add optional api endpoints (_upload)."""
if not self.api:
return
upload_is_used_marker = (
prerequisites.get_backend_dir() / constants.Dirs.UPLOAD_IS_USED
)
if Upload.is_used or upload_is_used_marker.exists():
if Upload.is_used:
# To upload files.
self.api.post(str(constants.Endpoint.UPLOAD))(upload(self))
@ -608,15 +455,10 @@ class App(MiddlewareMixin, LifespanMixin):
StaticFiles(directory=get_upload_dir()),
name="uploaded_files",
)
upload_is_used_marker.parent.mkdir(parents=True, exist_ok=True)
upload_is_used_marker.touch()
if codespaces.is_running_in_codespaces():
self.api.get(str(constants.Endpoint.AUTH_CODESPACE))(
codespaces.auth_codespace
)
if environment.REFLEX_ADD_ALL_ROUTES_ENDPOINT.get():
self.add_all_routes_endpoint()
def _add_cors(self):
"""Add CORS middleware to the app."""
@ -654,9 +496,7 @@ class App(MiddlewareMixin, LifespanMixin):
Returns:
The generated component.
"""
from reflex.compiler.compiler import into_component
return into_component(component)
return component if isinstance(component, Component) else component()
def add_page(
self,
@ -665,7 +505,7 @@ class App(MiddlewareMixin, LifespanMixin):
title: str | Var | None = None,
description: str | Var | None = None,
image: str = constants.DefaultPage.IMAGE,
on_load: EventType[()] | None = None,
on_load: EventType[[], BASE_STATE] | None = None,
meta: list[dict[str, str]] = constants.DefaultPage.META_LIST,
):
"""Add a page to the app.
@ -757,25 +597,19 @@ class App(MiddlewareMixin, LifespanMixin):
route: The route of the page to compile.
save_page: If True, the compiled page is saved to self._pages.
"""
n_states_before = len(all_base_state_classes)
component, enable_state = compiler.compile_unevaluated_page(
route, self._unevaluated_pages[route], self._state, self.style, self.theme
)
# Indicate that the app should use state.
if enable_state:
self._enable_state()
# Indicate that evaluating this page creates one or more state classes.
if len(all_base_state_classes) > n_states_before:
self._stateful_pages[route] = None
# Add the page.
self._check_routes_conflict(route)
if save_page:
self._pages[route] = component
def get_load_events(self, route: str) -> list[IndividualEventType[()]]:
def get_load_events(self, route: str) -> list[IndividualEventType[[], Any]]:
"""Get the load events for a route.
Args:
@ -814,10 +648,7 @@ class App(MiddlewareMixin, LifespanMixin):
for route in self._pages:
replaced_route = replace_brackets_with_keywords(route)
for rw, r, nr in zip(
replaced_route.split("/"),
route.split("/"),
new_route.split("/"),
strict=False,
replaced_route.split("/"), route.split("/"), new_route.split("/")
):
if rw in segments and r != nr:
# If the slugs in the segments of both routes are not the same, then the route is invalid
@ -837,7 +668,7 @@ class App(MiddlewareMixin, LifespanMixin):
title: str = constants.Page404.TITLE,
image: str = constants.Page404.IMAGE,
description: str = constants.Page404.DESCRIPTION,
on_load: EventType[()] | None = None,
on_load: EventType[[], BASE_STATE] | None = None,
meta: list[dict[str, str]] = constants.DefaultPage.META_LIST,
):
"""Define a custom 404 page for any url having no match.
@ -848,8 +679,8 @@ class App(MiddlewareMixin, LifespanMixin):
Args:
component: The component to display at the page.
title: The title of the page.
image: The image to display on the page.
description: The description of the page.
image: The image to display on the page.
on_load: The event handler(s) that will be called each time the page load.
meta: The metadata of the page.
"""
@ -916,7 +747,7 @@ class App(MiddlewareMixin, LifespanMixin):
frontend_packages = get_config().frontend_packages
_frontend_packages = []
for package in frontend_packages:
if package in (get_config().tailwind or {}).get("plugins", []):
if package in (get_config().tailwind or {}).get("plugins", []): # type: ignore
console.warn(
f"Tailwind packages are inferred from 'plugins', remove `{package}` from `frontend_packages`"
)
@ -984,14 +815,24 @@ class App(MiddlewareMixin, LifespanMixin):
for k, component in self._pages.items():
self._pages[k] = self._add_overlay_to_component(component)
def _setup_sticky_badge(self):
"""Add the sticky badge to the app."""
def _add_error_boundary_to_component(self, component: Component) -> Component:
if self.error_boundary is None:
return component
component = self.error_boundary(*component.children)
return component
def _setup_error_boundary(self):
"""If a State is not used and no error_boundary is specified, do not render the error boundary."""
if self._state is None and self.error_boundary is default_error_boundary:
self.error_boundary = None
for k, component in self._pages.items():
# Would be nice to share single sticky_badge across all pages, but
# it bungles the StatefulComponent compile step.
sticky_badge = sticky()
sticky_badge._add_style_recursive({})
self._pages[k] = Fragment.create(sticky_badge, component)
# Skip the 404 page
if k == constants.Page404.SLUG:
continue
self._pages[k] = self._add_error_boundary_to_component(component)
def _apply_decorated_pages(self):
"""Add @rx.page decorated pages to the app.
@ -1027,17 +868,11 @@ class App(MiddlewareMixin, LifespanMixin):
if not var._cache:
continue
deps = var._deps(objclass=state)
for state_name, dep_set in deps.items():
state_cls = (
state.get_root_state().get_class_substate(state_name)
if state_name != state.get_full_name()
else state
)
for dep in dep_set:
if dep not in state_cls.vars and dep not in state_cls.backend_vars:
raise exceptions.VarDependencyError(
f"ComputedVar {var._js_expr} on state {state.__name__} has an invalid dependency {state_name}.{dep}"
)
for dep in deps:
if dep not in state.vars and dep not in state.backend_vars:
raise exceptions.VarDependencyError(
f"ComputedVar {var._js_expr} on state {state.__name__} has an invalid dependency {dep}"
)
for substate in state.class_subclasses:
self._validate_var_dependencies(substate)
@ -1058,20 +893,6 @@ class App(MiddlewareMixin, LifespanMixin):
def get_compilation_time() -> str:
return str(datetime.now().time()).split(".")[0]
should_compile = self._should_compile()
backend_dir = prerequisites.get_backend_dir()
if not should_compile and backend_dir.exists():
stateful_pages_marker = backend_dir / constants.Dirs.STATEFUL_PAGES
if stateful_pages_marker.exists():
with stateful_pages_marker.open("r") as f:
stateful_pages = json.load(f)
for route in stateful_pages:
console.info(f"BE Evaluating stateful page: {route}")
self._compile_page(route, save_page=False)
self._enable_state()
self._add_optional_endpoints()
return
# Render a default 404 page if the user didn't supply one
if constants.Page404.SLUG not in self._unevaluated_pages:
self.add_page(route=constants.Page404.SLUG)
@ -1089,25 +910,22 @@ class App(MiddlewareMixin, LifespanMixin):
# If a theme component was provided, wrap the app with it
app_wrappers[(20, "Theme")] = self.theme
# Get the env mode.
config = get_config()
if config.react_strict_mode:
app_wrappers[(200, "StrictMode")] = StrictMode.create()
should_compile = self._should_compile()
for route in self._unevaluated_pages:
console.debug(f"Evaluating page: {route}")
self._compile_page(route, save_page=should_compile)
# Add the optional endpoints (_upload)
self._add_optional_endpoints()
if not should_compile:
with console.timing("Evaluate Pages (Backend)"):
for route in self._unevaluated_pages:
console.debug(f"Evaluating page: {route}")
self._compile_page(route, save_page=should_compile)
# Add the optional endpoints (_upload)
self._add_optional_endpoints()
return
self._validate_var_dependencies()
self._setup_overlay_component()
self._setup_error_boundary()
# Create a progress bar.
progress = Progress(
*Progress.get_default_columns()[:-1],
@ -1116,58 +934,21 @@ class App(MiddlewareMixin, LifespanMixin):
)
# try to be somewhat accurate - but still not 100%
adhoc_steps_without_executor = 7
adhoc_steps_without_executor = 6
fixed_pages_within_executor = 5
progress.start()
task = progress.add_task(
f"[{get_compilation_time()}] Compiling:",
total=len(self._pages)
+ (len(self._unevaluated_pages) * 2)
+ fixed_pages_within_executor
+ adhoc_steps_without_executor,
)
with console.timing("Evaluate Pages (Frontend)"):
performance_metrics: list[tuple[str, float]] = []
for route in self._unevaluated_pages:
console.debug(f"Evaluating page: {route}")
start = timer()
self._compile_page(route, save_page=should_compile)
end = timer()
performance_metrics.append((route, end - start))
progress.advance(task)
console.debug(
"Slowest pages:\n"
+ "\n".join(
f"{route}: {time * 1000:.1f}ms"
for route, time in sorted(
performance_metrics, key=lambda x: x[1], reverse=True
)[:10]
)
)
# Add the optional endpoints (_upload)
self._add_optional_endpoints()
self._validate_var_dependencies()
self._setup_overlay_component()
if config.show_built_with_reflex is None:
if (
get_compile_context() == constants.CompileContext.DEPLOY
and prerequisites.get_user_tier() in ["pro", "team", "enterprise"]
):
config.show_built_with_reflex = False
else:
config.show_built_with_reflex = True
if is_prod_mode() and config.show_built_with_reflex:
self._setup_sticky_badge()
progress.advance(task)
# Get the env mode.
config = get_config()
# Store the compile results.
compile_results: list[tuple[str, str]] = []
compile_results = []
progress.advance(task)
@ -1187,43 +968,14 @@ class App(MiddlewareMixin, LifespanMixin):
# Add the custom components from the page to the set.
custom_components |= component._get_all_custom_components()
if (toaster := self.toaster) is not None:
from reflex.components.component import memo
@memo
def memoized_toast_provider():
return toaster
toast_provider = Fragment.create(memoized_toast_provider())
app_wrappers[(1, "ToasterProvider")] = toast_provider
# Add the app wraps to the app.
for key, app_wrap in self.app_wraps.items():
component = app_wrap(self._state is not None)
if component is not None:
app_wrappers[key] = component
for component in app_wrappers.values():
custom_components |= component._get_all_custom_components()
if self.error_boundary:
console.deprecate(
feature_name="App.error_boundary",
reason="Use app_wraps instead.",
deprecation_version="0.7.1",
removal_version="0.8.0",
)
app_wrappers[(55, "ErrorBoundary")] = self.error_boundary()
# Perform auto-memoization of stateful components.
with console.timing("Auto-memoize StatefulComponents"):
(
stateful_components_path,
stateful_components_code,
page_components,
) = compiler.compile_stateful_components(self._pages.values())
progress.advance(task)
(
stateful_components_path,
stateful_components_code,
page_components,
) = compiler.compile_stateful_components(self._pages.values())
progress.advance(task)
# Catch "static" apps (that do not define a rx.State subclass) which are trying to access rx.State.
if code_uses_state_contexts(stateful_components_code) and self._state is None:
@ -1240,36 +992,39 @@ class App(MiddlewareMixin, LifespanMixin):
compiler.compile_document_root(
self.head_components,
html_lang=self.html_lang,
html_custom_attrs=self.html_custom_attrs, # pyright: ignore [reportArgumentType]
html_custom_attrs=self.html_custom_attrs, # type: ignore
)
)
progress.advance(task)
# Copy the assets.
assets_src = Path.cwd() / constants.Dirs.APP_ASSETS
if assets_src.is_dir():
with console.timing("Copy assets"):
path_ops.update_directory_tree(
src=assets_src,
dest=(
Path.cwd() / prerequisites.get_web_dir() / constants.Dirs.PUBLIC
),
)
# Use a forking process pool, if possible. Much faster, especially for large sites.
# Fallback to ThreadPoolExecutor as something that will always work.
executor = None
if (
platform.system() in ("Linux", "Darwin")
and (number_of_processes := environment.REFLEX_COMPILE_PROCESSES.get())
is not None
):
executor = concurrent.futures.ProcessPoolExecutor(
max_workers=number_of_processes or None,
mp_context=multiprocessing.get_context("fork"),
)
else:
executor = concurrent.futures.ThreadPoolExecutor(
max_workers=environment.REFLEX_COMPILE_THREADS.get() or None
)
executor = ExecutorType.get_executor_from_environment()
for route, component in zip(self._pages, page_components, strict=True):
for route, component in zip(self._pages, page_components):
ExecutorSafeFunctions.COMPONENTS[route] = component
ExecutorSafeFunctions.STATE = self._state
with console.timing("Compile to Javascript"), executor as executor:
result_futures: list[concurrent.futures.Future[tuple[str, str]]] = []
with executor:
result_futures = []
def _submit_work(fn: Callable[..., tuple[str, str]], *args, **kwargs):
def _submit_work(fn, *args, **kwargs):
f = executor.submit(fn, *args, **kwargs)
f.add_done_callback(lambda _: progress.advance(task))
result_futures.append(f)
# Compile the pre-compiled pages.
@ -1295,10 +1050,9 @@ class App(MiddlewareMixin, LifespanMixin):
_submit_work(compiler.remove_tailwind_from_postcss)
# Wait for all compilation tasks to complete.
compile_results.extend(
future.result()
for future in concurrent.futures.as_completed(result_futures)
)
for future in concurrent.futures.as_completed(result_futures):
compile_results.append(future.result())
progress.advance(task)
app_root = self._app_root(app_wrappers=app_wrappers)
@ -1323,20 +1077,17 @@ class App(MiddlewareMixin, LifespanMixin):
progress.advance(task)
# Compile custom components.
(
custom_components_output,
custom_components_result,
custom_components_imports,
) = compiler.compile_components(custom_components)
compile_results.append((custom_components_output, custom_components_result))
*custom_components_result, custom_components_imports = (
compiler.compile_components(custom_components)
)
compile_results.append(custom_components_result)
all_imports.update(custom_components_imports)
progress.advance(task)
progress.stop()
# Install frontend packages.
with console.timing("Install Frontend Packages"):
self._get_frontend_packages(all_imports)
self._get_frontend_packages(all_imports)
# Setup the next.config.js
transpile_packages = [
@ -1362,27 +1113,8 @@ class App(MiddlewareMixin, LifespanMixin):
# Remove pages that are no longer in the app.
p.unlink()
with console.timing("Write to Disk"):
for output_path, code in compile_results:
compiler_utils.write_page(output_path, code)
# Write list of routes that create dynamic states for backend to use.
if self._state is not None:
stateful_pages_marker = (
prerequisites.get_backend_dir() / constants.Dirs.STATEFUL_PAGES
)
stateful_pages_marker.parent.mkdir(parents=True, exist_ok=True)
with stateful_pages_marker.open("w") as f:
json.dump(list(self._stateful_pages), f)
def add_all_routes_endpoint(self):
"""Add an endpoint to the app that returns all the routes."""
if not self.api:
return
@self.api.get(str(constants.Endpoint.ALL_ROUTES))
async def all_routes():
return list(self._unevaluated_pages.keys())
for output_path, code in compile_results:
compiler_utils.write_page(output_path, code)
@contextlib.asynccontextmanager
async def modify_state(self, token: str) -> AsyncIterator[BaseState]:
@ -1480,7 +1212,6 @@ class App(MiddlewareMixin, LifespanMixin):
frontend_arg_spec,
backend_arg_spec,
],
strict=True,
):
if hasattr(handler_fn, "__name__"):
_fn_name = handler_fn.__name__
@ -1521,7 +1252,7 @@ class App(MiddlewareMixin, LifespanMixin):
):
raise ValueError(
f"Provided custom {handler_domain} exception handler `{_fn_name}` has the wrong argument order."
f"Expected `{required_arg}` as the {required_arg_index + 1} argument but got `{list(arg_annotations.keys())[required_arg_index]}`"
f"Expected `{required_arg}` as the {required_arg_index+1} argument but got `{list(arg_annotations.keys())[required_arg_index]}`"
)
if not issubclass(arg_annotations[required_arg], Exception):
@ -1622,14 +1353,15 @@ async def process(
if app._process_background(state, event) is not None:
# `final=True` allows the frontend send more events immediately.
yield StateUpdate(final=True)
else:
# Process the event synchronously.
async for update in state._process(event):
# Postprocess the event.
update = await app._postprocess(state, event, update)
return
# Yield the update.
yield update
# Process the event synchronously.
async for update in state._process(event):
# Postprocess the event.
update = await app._postprocess(state, event, update)
# Yield the update.
yield update
except Exception as ex:
telemetry.send_error(ex, context="backend")
@ -1690,7 +1422,7 @@ def upload(app: App):
The upload function.
"""
async def upload_file(request: Request, files: List[FastAPIUploadFile]):
async def upload_file(request: Request, files: List[UploadFile]):
"""Upload a file.
Args:
@ -1766,8 +1498,7 @@ def upload(app: App):
file_copies.append(
UploadFile(
file=content_copy,
path=Path(file.filename.lstrip("/")) if file.filename else None,
_deprecated_filename=file.filename,
filename=file.filename,
size=file.size,
headers=file.headers,
)
@ -1825,20 +1556,20 @@ class EventNamespace(AsyncNamespace):
self.sid_to_token = {}
self.app = app
def on_connect(self, sid: str, environ: dict):
def on_connect(self, sid, environ):
"""Event for when the websocket is connected.
Args:
sid: The Socket.IO session id.
environ: The request information, including HTTP headers.
"""
subprotocol = environ.get("HTTP_SEC_WEBSOCKET_PROTOCOL")
subprotocol = environ.get("HTTP_SEC_WEBSOCKET_PROTOCOL", None)
if subprotocol and subprotocol != constants.Reflex.VERSION:
console.warn(
f"Frontend version {subprotocol} for session {sid} does not match the backend version {constants.Reflex.VERSION}."
)
def on_disconnect(self, sid: str):
def on_disconnect(self, sid):
"""Event for when the websocket disconnects.
Args:
@ -1860,7 +1591,7 @@ class EventNamespace(AsyncNamespace):
self.emit(str(constants.SocketEvent.EVENT), update, to=sid)
)
async def on_event(self, sid: str, data: Any):
async def on_event(self, sid, data):
"""Event for receiving front-end websocket events.
Raises:
@ -1927,7 +1658,7 @@ class EventNamespace(AsyncNamespace):
# Emit the update from processing the event.
await self.emit_update(update=update, sid=sid)
async def on_ping(self, sid: str):
async def on_ping(self, sid):
"""Event for testing the API endpoint.
Args:

View File

@ -32,7 +32,7 @@ class LifespanMixin(AppMixin):
try:
async with contextlib.AsyncExitStack() as stack:
for task in self.lifespan_tasks:
run_msg = f"Started lifespan task: {task.__name__} as {{type}}" # pyright: ignore [reportAttributeAccessIssue]
run_msg = f"Started lifespan task: {task.__name__} as {{type}}" # type: ignore
if isinstance(task, asyncio.Task):
running_tasks.append(task)
else:
@ -61,7 +61,7 @@ class LifespanMixin(AppMixin):
Args:
task: The task to register.
**task_kwargs: The kwargs of the task.
task_kwargs: The kwargs of the task.
Raises:
InvalidLifespanTaskTypeError: If the task is a generator function.
@ -73,7 +73,7 @@ class LifespanMixin(AppMixin):
if task_kwargs:
original_task = task
task = functools.partial(task, **task_kwargs) # pyright: ignore [reportArgumentType]
functools.update_wrapper(task, original_task) # pyright: ignore [reportArgumentType]
self.lifespan_tasks.add(task)
console.debug(f"Registered lifespan task: {task.__name__}") # pyright: ignore [reportAttributeAccessIssue]
task = functools.partial(task, **task_kwargs) # type: ignore
functools.update_wrapper(task, original_task) # type: ignore
self.lifespan_tasks.add(task) # type: ignore
console.debug(f"Registered lifespan task: {task.__name__}") # type: ignore

View File

@ -53,11 +53,11 @@ class MiddlewareMixin(AppMixin):
"""
for middleware in self.middleware:
if asyncio.iscoroutinefunction(middleware.preprocess):
out = await middleware.preprocess(app=self, state=state, event=event) # pyright: ignore [reportArgumentType]
out = await middleware.preprocess(app=self, state=state, event=event) # type: ignore
else:
out = middleware.preprocess(app=self, state=state, event=event) # pyright: ignore [reportArgumentType]
out = middleware.preprocess(app=self, state=state, event=event) # type: ignore
if out is not None:
return out # pyright: ignore [reportReturnType]
return out # type: ignore
async def _postprocess(
self, state: BaseState, event: Event, update: StateUpdate
@ -78,18 +78,18 @@ class MiddlewareMixin(AppMixin):
for middleware in self.middleware:
if asyncio.iscoroutinefunction(middleware.postprocess):
out = await middleware.postprocess(
app=self, # pyright: ignore [reportArgumentType]
app=self, # type: ignore
state=state,
event=event,
update=update,
)
else:
out = middleware.postprocess(
app=self, # pyright: ignore [reportArgumentType]
app=self, # type: ignore
state=state,
event=event,
update=update,
)
if out is not None:
return out # pyright: ignore [reportReturnType]
return out # type: ignore
return update

View File

@ -38,7 +38,7 @@ def validate_field_name(bases: List[Type["BaseModel"]], field_name: str) -> None
# monkeypatch pydantic validate_field_name method to skip validating
# shadowed state vars when reloading app via utils.prerequisites.get_app(reload=True)
pydantic_main.validate_field_name = validate_field_name # pyright: ignore [reportPossiblyUnboundVariable, reportPrivateImportUsage]
pydantic_main.validate_field_name = validate_field_name # type: ignore
if TYPE_CHECKING:
from reflex.vars import Var
@ -69,12 +69,12 @@ class Base(BaseModel):
"""
from reflex.utils.serializers import serialize
return self.__config__.json_dumps(
return self.__config__.json_dumps( # type: ignore
self.dict(),
default=serialize,
)
def set(self, **kwargs: Any):
def set(self, **kwargs):
"""Set multiple fields and return the object.
Args:
@ -107,12 +107,12 @@ class Base(BaseModel):
default_value: The default value of the field
"""
var_name = var._var_field_name
new_field = ModelField.infer( # pyright: ignore [reportPossiblyUnboundVariable]
new_field = ModelField.infer(
name=var_name,
value=default_value,
annotation=var._var_type,
class_validators=None,
config=cls.__config__,
config=cls.__config__, # type: ignore
)
cls.__fields__.update({var_name: new_field})

View File

@ -4,7 +4,7 @@ from __future__ import annotations
from datetime import datetime
from pathlib import Path
from typing import TYPE_CHECKING, Dict, Iterable, Optional, Sequence, Tuple, Type, Union
from typing import TYPE_CHECKING, Callable, Dict, Iterable, Optional, Tuple, Type, Union
from reflex import constants
from reflex.compiler import templates, utils
@ -78,7 +78,6 @@ def _compile_app(app_root: Component) -> str:
hooks=app_root._get_all_hooks(),
window_libraries=window_libraries,
render=app_root.render(),
dynamic_imports=app_root._get_all_dynamic_imports(),
)
@ -240,19 +239,11 @@ def _compile_components(
component_renders.append(component_render)
imports = utils.merge_imports(imports, component_imports)
dynamic_imports = {
comp_import: None
for comp_render in component_renders
if "dynamic_imports" in comp_render
for comp_import in comp_render["dynamic_imports"]
}
# Compile the components page.
return (
templates.COMPONENTS.render(
imports=utils.compile_imports(imports),
components=component_renders,
dynamic_imports=dynamic_imports,
),
imports,
)
@ -508,7 +499,7 @@ def compile_tailwind(
The compiled Tailwind config.
"""
# Get the path for the output file.
output_path = str((get_web_dir() / constants.Tailwind.CONFIG).absolute())
output_path = get_web_dir() / constants.Tailwind.CONFIG
# Compile the config.
code = _compile_tailwind(config)
@ -545,47 +536,30 @@ def purge_web_pages_dir():
if TYPE_CHECKING:
from reflex.app import ComponentCallable, UnevaluatedPage
from reflex.app import UnevaluatedPage
COMPONENT_TYPE = Union[Component, Var, Tuple[Union[Component, Var], ...]]
COMPONENT_TYPE_OR_CALLABLE = Union[COMPONENT_TYPE, Callable[[], COMPONENT_TYPE]]
def _into_component_once(component: Component | ComponentCallable) -> Component | None:
"""Convert a component to a Component.
def componentify_unevaluated(
possible_component: COMPONENT_TYPE_OR_CALLABLE,
) -> Component:
"""Convert a possible component to a component.
Args:
component: The component to convert.
possible_component: The possible component to convert.
Returns:
The converted component.
The component.
"""
if isinstance(component, Component):
return component
if isinstance(component, (Var, int, float, str)):
return Fragment.create(component)
if isinstance(component, Sequence):
return Fragment.create(*component)
return None
def into_component(component: Component | ComponentCallable) -> Component:
"""Convert a component to a Component.
Args:
component: The component to convert.
Returns:
The converted component.
Raises:
TypeError: If the component is not a Component.
"""
if (converted := _into_component_once(component)) is not None:
return converted
if (
callable(component)
and (converted := _into_component_once(component())) is not None
):
return converted
raise TypeError(f"Expected a Component, got {type(component)}")
if isinstance(possible_component, Var):
return Fragment.create(possible_component)
if isinstance(possible_component, tuple):
return Fragment.create(*possible_component)
if isinstance(possible_component, Component):
return possible_component
return componentify_unevaluated(possible_component())
def compile_unevaluated_page(
@ -608,7 +582,7 @@ def compile_unevaluated_page(
The compiled component and whether state should be enabled.
"""
# Generate the component if it is a callable.
component = into_component(page.component)
component = componentify_unevaluated(page.component)
component._add_style_recursive(style or {}, theme)
@ -713,8 +687,10 @@ class ExecutorSafeFunctions:
The route, compiled component, and compiled page.
"""
component, enable_state = compile_unevaluated_page(
route, cls.UNCOMPILED_PAGES[route], cls.STATE, style, theme
route, cls.UNCOMPILED_PAGES[route]
)
component = component if isinstance(component, Component) else component()
component._add_style_recursive(style, theme)
return route, component, compile_page(route, component, cls.STATE)
@classmethod

View File

@ -48,10 +48,11 @@ class ReflexJinjaEnvironment(Environment):
def __init__(self) -> None:
"""Set default environment."""
extensions = ["jinja2.ext.debug"]
super().__init__(
extensions=extensions,
trim_blocks=True,
lstrip_blocks=True,
auto_reload=False,
)
self.filters["json_dumps"] = json_dumps
self.filters["react_setter"] = lambda state: f"set{state.capitalize()}"

View File

@ -2,15 +2,17 @@
from __future__ import annotations
import asyncio
import concurrent.futures
import traceback
from datetime import datetime
from pathlib import Path
from typing import Any, Callable, Dict, Optional, Type, Union
from urllib.parse import urlparse
from pydantic.v1.fields import ModelField
from reflex.utils.prerequisites import get_web_dir
from reflex.vars.base import Var
try:
from pydantic.v1.fields import ModelField
except ModuleNotFoundError:
from pydantic.fields import ModelField # type: ignore
from reflex import constants
from reflex.components.base import (
@ -27,13 +29,10 @@ from reflex.components.base import (
)
from reflex.components.component import Component, ComponentStyle, CustomComponent
from reflex.istate.storage import Cookie, LocalStorage, SessionStorage
from reflex.state import BaseState, _resolve_delta
from reflex.state import BaseState
from reflex.style import Style
from reflex.utils import console, format, imports, path_ops
from reflex.utils.exec import is_in_app_harness
from reflex.utils.imports import ImportVar, ParsedImportDict
from reflex.utils.prerequisites import get_web_dir
from reflex.vars.base import Var
# To re-export this function.
merge_imports = imports.merge_imports
@ -113,34 +112,24 @@ def compile_imports(import_dict: ParsedImportDict) -> list[dict]:
validate_imports(collapsed_import_dict)
import_dicts = []
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
if not any(f.render for f in fields):
if not any(f.render for f in fields): # type: ignore
continue
lib_paths: dict[str, list[ImportVar]] = {}
if not lib:
if default:
raise ValueError("No default field allowed for empty library.")
if rest is None or len(rest) == 0:
raise ValueError("No fields to import.")
import_dicts.extend(get_import_dict(module) for module in sorted(rest))
continue
for field in fields:
lib_paths.setdefault(field.package_path, []).append(field)
# remove the version before rendering the package imports
lib = format.format_library_name(lib)
compiled = {
path: compile_import_statement(fields) for path, fields in lib_paths.items()
}
for path, (default, rest) in compiled.items():
if not lib:
if default:
raise ValueError("No default field allowed for empty library.")
if rest is None or len(rest) == 0:
raise ValueError("No fields to import.")
import_dicts.extend(get_import_dict(module) for module in sorted(rest))
continue
# remove the version before rendering the package imports
formatted_lib = format.format_library_name(lib) + (
path if path != "/" else ""
)
import_dicts.append(get_import_dict(formatted_lib, default, rest))
import_dicts.append(get_import_dict(lib, default, rest))
return import_dicts
@ -162,22 +151,6 @@ def get_import_dict(lib: str, default: str = "", rest: list[str] | None = None)
}
def save_error(error: Exception) -> str:
"""Save the error to a file.
Args:
error: The error to save.
Returns:
The path of the saved error.
"""
timestamp = datetime.now().strftime("%Y-%m-%d__%H-%M-%S")
constants.Reflex.LOGS_DIR.mkdir(parents=True, exist_ok=True)
log_path = constants.Reflex.LOGS_DIR / f"error_{timestamp}.log"
traceback.TracebackException.from_exception(error).print(file=log_path.open("w+"))
return str(log_path)
def compile_state(state: Type[BaseState]) -> dict:
"""Compile the state of the app.
@ -190,31 +163,13 @@ def compile_state(state: Type[BaseState]) -> dict:
try:
initial_state = state(_reflex_internal_init=True).dict(initial=True)
except Exception as e:
log_path = save_error(e)
console.warn(
f"Failed to compile initial state with computed vars. Error log saved to {log_path}"
f"Failed to compile initial state with computed vars, excluding them: {e}"
)
initial_state = state(_reflex_internal_init=True).dict(
initial=True, include_computed=False
)
try:
_ = asyncio.get_running_loop()
except RuntimeError:
pass
else:
if is_in_app_harness():
# Playwright tests already have an event loop running, so we can't use asyncio.run.
with concurrent.futures.ThreadPoolExecutor() as pool:
resolved_initial_state = pool.submit(
asyncio.run, _resolve_delta(initial_state)
).result()
console.warn(
f"Had to get initial state in a thread 🤮 {resolved_initial_state}",
)
return resolved_initial_state
# Normally the compile runs before any event loop starts, we asyncio.run is available for calling.
return asyncio.run(_resolve_delta(initial_state))
return initial_state
def _compile_client_storage_field(
@ -337,7 +292,6 @@ def compile_custom_component(
"render": render.render(),
"hooks": render._get_all_hooks(),
"custom_code": render._get_all_custom_code(),
"dynamic_imports": render._get_all_dynamic_imports(),
},
imports,
)
@ -517,8 +471,6 @@ def write_page(path: str | Path, code: str):
"""
path = Path(path)
path_ops.mkdir(path.parent)
if path.exists() and path.read_text(encoding="utf-8") == code:
return
path.write_text(code, encoding="utf-8")
@ -542,7 +494,7 @@ def empty_dir(path: str | Path, keep_files: list[str] | None = None):
path_ops.rm(element)
def is_valid_url(url: str) -> bool:
def is_valid_url(url) -> bool:
"""Check if a url is valid.
Args:

View File

@ -6,7 +6,7 @@
from typing import Any, Dict, Optional, Union, overload
from reflex.components.base.fragment import Fragment
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -22,21 +22,21 @@ class AppWrap(Fragment):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "AppWrap":
"""Create a new AppWrap component.

View File

@ -2,54 +2,14 @@
from __future__ import annotations
from typing import Any, Iterator, Sequence
from typing import Any, Iterator
from reflex.components.component import BaseComponent, Component, ComponentStyle
from reflex.components.component import Component, ComponentStyle
from reflex.components.tags import Tag
from reflex.components.tags.tagless import Tagless
from reflex.config import PerformanceMode, environment
from reflex.utils import console
from reflex.utils.decorator import once
from reflex.utils.imports import ParsedImportDict
from reflex.vars import BooleanVar, ObjectVar, Var
from reflex.vars.base import GLOBAL_CACHE, VarData
from reflex.vars.sequence import LiteralStringVar
@once
def get_performance_mode():
"""Get the performance mode.
Returns:
The performance mode.
"""
return environment.REFLEX_PERF_MODE.get()
def validate_str(value: str):
"""Validate a string value.
Args:
value: The value to validate.
Raises:
ValueError: If the value is a Var and the performance mode is set to raise.
"""
perf_mode = get_performance_mode()
if perf_mode != PerformanceMode.OFF and value.startswith("reflex___state"):
if perf_mode == PerformanceMode.WARN:
console.warn(
f"Output includes {value!s} which will be displayed as a string. If you are calling `str` on a Var, consider using .to_string() instead."
)
elif perf_mode == PerformanceMode.RAISE:
raise ValueError(
f"Output includes {value!s} which will be displayed as a string. If you are calling `str` on a Var, consider using .to_string() instead."
)
def _components_from_var(var: Var) -> Sequence[BaseComponent]:
var_data = var._get_all_var_data()
return var_data.components if var_data else ()
from reflex.vars.base import VarData, get_var_caching, set_var_caching
class Bare(Component):
@ -68,15 +28,10 @@ class Bare(Component):
The component.
"""
if isinstance(contents, Var):
if isinstance(contents, LiteralStringVar):
validate_str(contents._var_value)
return cls(contents=contents)
else:
if isinstance(contents, str):
validate_str(contents)
contents = str(contents) if contents is not None else ""
return cls(contents=contents)
return cls(contents=contents) # type: ignore
def _get_all_hooks_internal(self) -> dict[str, VarData | None]:
"""Include the hooks for the component.
@ -86,8 +41,10 @@ class Bare(Component):
"""
hooks = super()._get_all_hooks_internal()
if isinstance(self.contents, Var):
for component in _components_from_var(self.contents):
hooks |= component._get_all_hooks_internal()
var_data = self.contents._get_all_var_data()
if var_data:
for component in var_data.components:
hooks |= component._get_all_hooks_internal()
return hooks
def _get_all_hooks(self) -> dict[str, VarData | None]:
@ -98,8 +55,10 @@ class Bare(Component):
"""
hooks = super()._get_all_hooks()
if isinstance(self.contents, Var):
for component in _components_from_var(self.contents):
hooks |= component._get_all_hooks()
var_data = self.contents._get_all_var_data()
if var_data:
for component in var_data.components:
hooks |= component._get_all_hooks()
return hooks
def _get_all_imports(self, collapse: bool = False) -> ParsedImportDict:
@ -126,8 +85,10 @@ class Bare(Component):
"""
dynamic_imports = super()._get_all_dynamic_imports()
if isinstance(self.contents, Var):
for component in _components_from_var(self.contents):
dynamic_imports |= component._get_all_dynamic_imports()
var_data = self.contents._get_all_var_data()
if var_data:
for component in var_data.components:
dynamic_imports |= component._get_all_dynamic_imports()
return dynamic_imports
def _get_all_custom_code(self) -> set[str]:
@ -138,8 +99,10 @@ class Bare(Component):
"""
custom_code = super()._get_all_custom_code()
if isinstance(self.contents, Var):
for component in _components_from_var(self.contents):
custom_code |= component._get_all_custom_code()
var_data = self.contents._get_all_var_data()
if var_data:
for component in var_data.components:
custom_code |= component._get_all_custom_code()
return custom_code
def _get_all_app_wrap_components(self) -> dict[tuple[int, str], Component]:
@ -150,9 +113,11 @@ class Bare(Component):
"""
app_wrap_components = super()._get_all_app_wrap_components()
if isinstance(self.contents, Var):
for component in _components_from_var(self.contents):
if isinstance(component, Component):
app_wrap_components |= component._get_all_app_wrap_components()
var_data = self.contents._get_all_var_data()
if var_data:
for component in var_data.components:
if isinstance(component, Component):
app_wrap_components |= component._get_all_app_wrap_components()
return app_wrap_components
def _get_all_refs(self) -> set[str]:
@ -163,8 +128,10 @@ class Bare(Component):
"""
refs = super()._get_all_refs()
if isinstance(self.contents, Var):
for component in _components_from_var(self.contents):
refs |= component._get_all_refs()
var_data = self.contents._get_all_var_data()
if var_data:
for component in var_data.components:
refs |= component._get_all_refs()
return refs
def _render(self) -> Tag:
@ -187,18 +154,16 @@ class Bare(Component):
The component with the style added.
"""
new_self = super()._add_style_recursive(style, theme)
are_components_touched = False
if isinstance(self.contents, Var):
for component in _components_from_var(self.contents):
if isinstance(component, Component):
component._add_style_recursive(style, theme)
are_components_touched = True
if are_components_touched:
GLOBAL_CACHE.clear()
var_data = self.contents._get_all_var_data()
if var_data:
for component in var_data.components:
if isinstance(component, Component):
component._add_style_recursive(style, theme)
if get_var_caching():
set_var_caching(False)
str(new_self)
set_var_caching(True)
return new_self
def _get_vars(

View File

@ -6,7 +6,7 @@
from typing import Any, Dict, Optional, Union, overload
from reflex.components.component import Component
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -22,21 +22,21 @@ class Body(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Body":
"""Create the component.

View File

@ -6,7 +6,7 @@
from typing import Any, Dict, Optional, Union, overload
from reflex.components.component import Component
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -22,21 +22,21 @@ class NextDocumentLib(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "NextDocumentLib":
"""Create the component.
@ -69,21 +69,21 @@ class Html(NextDocumentLib):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Html":
"""Create the component.
@ -115,21 +115,21 @@ class DocumentHead(NextDocumentLib):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "DocumentHead":
"""Create the component.
@ -161,21 +161,21 @@ class Main(NextDocumentLib):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Main":
"""Create the component.
@ -207,21 +207,21 @@ class NextScript(NextDocumentLib):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "NextScript":
"""Create the component.

View File

@ -11,11 +11,10 @@ from reflex.event import EventHandler, set_clipboard
from reflex.state import FrontendEventExceptionState
from reflex.vars.base import Var
from reflex.vars.function import ArgsFunctionOperation
from reflex.vars.object import ObjectVar
def on_error_spec(
error: ObjectVar[Dict[str, str]], info: ObjectVar[Dict[str, str]]
error: Var[Dict[str, str]], info: Var[Dict[str, str]]
) -> Tuple[Var[str], Var[str]]:
"""The spec for the on_error event handler.

View File

@ -6,13 +6,12 @@
from typing import Any, Dict, Optional, Tuple, Union, overload
from reflex.components.component import Component
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
from reflex.vars.object import ObjectVar
def on_error_spec(
error: ObjectVar[Dict[str, str]], info: ObjectVar[Dict[str, str]]
error: Var[Dict[str, str]], info: Var[Dict[str, str]]
) -> Tuple[Var[str], Var[str]]: ...
class ErrorBoundary(Component):
@ -28,24 +27,28 @@ class ErrorBoundary(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_error: Optional[
Union[EventType[()], EventType[str], EventType[str, str]]
Union[
EventType[[], BASE_STATE],
EventType[[str], BASE_STATE],
EventType[[str, str], BASE_STATE],
]
] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "ErrorBoundary":
"""Create an ErrorBoundary component.

View File

@ -6,7 +6,7 @@
from typing import Any, Dict, Optional, Union, overload
from reflex.components.component import Component
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -22,21 +22,21 @@ class Fragment(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Fragment":
"""Create the component.

View File

@ -6,7 +6,7 @@
from typing import Any, Dict, Optional, Union, overload
from reflex.components.component import Component, MemoizationLeaf
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -22,21 +22,21 @@ class NextHeadLib(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "NextHeadLib":
"""Create the component.
@ -68,21 +68,21 @@ class Head(NextHeadLib, MemoizationLeaf):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Head":
"""Create a new memoization leaf component.

View File

@ -6,7 +6,7 @@
from typing import Any, Dict, Optional, Union, overload
from reflex.components.component import Component
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -24,21 +24,21 @@ class RawLink(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "RawLink":
"""Create the component.
@ -79,21 +79,21 @@ class ScriptTag(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "ScriptTag":
"""Create the component.

View File

@ -53,11 +53,11 @@ class Description(Meta):
"""A component that displays the title of the current page."""
# The type of the description.
name: str | None = "description"
name: str = "description"
class Image(Meta):
"""A component that displays the title of the current page."""
# The type of the image.
property: str | None = "og:image"
property: str = "og:image"

View File

@ -6,7 +6,7 @@
from typing import Any, Dict, Optional, Union, overload
from reflex.components.component import Component
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -23,21 +23,21 @@ class Title(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Title":
"""Create the component.
@ -74,21 +74,21 @@ class Meta(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Meta":
"""Create the component.
@ -130,21 +130,21 @@ class Description(Meta):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Description":
"""Create the component.
@ -186,21 +186,21 @@ class Image(Meta):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Image":
"""Create the component.

View File

@ -6,7 +6,7 @@
from typing import Any, Dict, Literal, Optional, Union, overload
from reflex.components.component import Component
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -29,24 +29,24 @@ class Script(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_error: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_load: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_ready: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_error: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_load: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_ready: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Script":
"""Create an inline or user-defined script.

View File

@ -1,10 +0,0 @@
"""Module for the StrictMode component."""
from reflex.components.component import Component
class StrictMode(Component):
"""A React strict mode component to enable strict mode for its children."""
library = "react"
tag = "StrictMode"

View File

@ -1,57 +0,0 @@
"""Stub file for reflex/components/base/strict_mode.py"""
# ------------------- DO NOT EDIT ----------------------
# This file was generated by `reflex/utils/pyi_generator.py`!
# ------------------------------------------------------
from typing import Any, Dict, Optional, Union, overload
from reflex.components.component import Component
from reflex.event import EventType
from reflex.style import Style
from reflex.vars.base import Var
class StrictMode(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, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
**props,
) -> "StrictMode":
"""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.
"""
...

View File

@ -4,7 +4,6 @@ from __future__ import annotations
import copy
import dataclasses
import inspect
import typing
from abc import ABC, abstractmethod
from functools import lru_cache, wraps
@ -22,12 +21,8 @@ from typing import (
Set,
Type,
Union,
get_args,
get_origin,
)
from typing_extensions import Self
import reflex.state
from reflex.base import Base
from reflex.compiler.templates import STATEFUL_COMPONENT
@ -46,7 +41,6 @@ from reflex.constants import (
from reflex.constants.compiler import SpecialAttributes
from reflex.constants.state import FRONTEND_EVENT_STATE
from reflex.event import (
EventActionsMixin,
EventCallback,
EventChain,
EventHandler,
@ -55,7 +49,13 @@ from reflex.event import (
)
from reflex.style import Style, format_as_emotion
from reflex.utils import format, imports, types
from reflex.utils.imports import ImportDict, ImportVar, ParsedImportDict, parse_imports
from reflex.utils.imports import (
ImmutableParsedImportDict,
ImportDict,
ImportVar,
ParsedImportDict,
parse_imports,
)
from reflex.vars import VarData
from reflex.vars.base import (
CachedVarOperation,
@ -63,8 +63,7 @@ from reflex.vars.base import (
Var,
cached_property_no_lock,
)
from reflex.vars.function import ArgsFunctionOperation, FunctionStringVar
from reflex.vars.number import ternary_operation
from reflex.vars.function import FunctionStringVar
from reflex.vars.object import ObjectVar
from reflex.vars.sequence import LiteralArrayVar
@ -150,7 +149,7 @@ class BaseComponent(Base, ABC):
class ComponentNamespace(SimpleNamespace):
"""A namespace to manage components with subcomponents."""
def __hash__(self) -> int: # pyright: ignore [reportIncompatibleVariableOverride]
def __hash__(self) -> int:
"""Get the hash of the namespace.
Returns:
@ -179,7 +178,6 @@ ComponentStyle = Dict[
Union[str, Type[BaseComponent], Callable, ComponentNamespace], Any
]
ComponentChild = Union[types.PrimitiveType, Var, BaseComponent]
ComponentChildTypes = (*types.PrimitiveTypes, Var, BaseComponent)
def satisfies_type_hint(obj: Any, type_hint: Any) -> bool:
@ -192,26 +190,11 @@ def satisfies_type_hint(obj: Any, type_hint: Any) -> bool:
Returns:
Whether the object satisfies the type hint.
"""
return types._isinstance(obj, type_hint, nested=1)
def _components_from(
component_or_var: Union[BaseComponent, Var],
) -> tuple[BaseComponent, ...]:
"""Get the components from a component or Var.
Args:
component_or_var: The component or Var to get the components from.
Returns:
The components.
"""
if isinstance(component_or_var, Var):
var_data = component_or_var._get_all_var_data()
return var_data.components if var_data else ()
if isinstance(component_or_var, BaseComponent):
return (component_or_var,)
return ()
if isinstance(obj, LiteralVar):
return types._isinstance(obj._var_value, type_hint)
if isinstance(obj, Var):
return types._issubclass(obj._var_type, type_hint)
return types._isinstance(obj, type_hint)
class Component(BaseComponent, ABC):
@ -442,7 +425,7 @@ class Component(BaseComponent, ABC):
else:
continue
def determine_key(value: Any):
def determine_key(value):
# Try to create a var from the value
key = value if isinstance(value, Var) else LiteralVar.create(value)
@ -478,7 +461,9 @@ class Component(BaseComponent, ABC):
if types.is_union(passed_type):
# We need to check all possible types in the union.
passed_types = (
arg for arg in passed_type.__args__ if arg is not type(None)
arg
for arg in passed_type.__args__ # type: ignore
if arg is not type(None)
)
if (
# If the passed var is a union, check if all possible types are valid.
@ -505,14 +490,14 @@ class Component(BaseComponent, ABC):
# Check if the key is an event trigger.
if key in component_specific_triggers:
kwargs["event_triggers"][key] = EventChain.create(
value=value,
value=value, # type: ignore
args_spec=component_specific_triggers[key],
key=key,
)
# Remove any keys that were added as events.
for key in kwargs["event_triggers"]:
kwargs.pop(key, None)
del kwargs[key]
# Place data_ and aria_ attributes into custom_attrs
special_attributes = tuple(
@ -592,7 +577,7 @@ class Component(BaseComponent, ABC):
annotation = field.annotation
if (metadata := getattr(annotation, "__metadata__", None)) is not None:
args_spec = metadata[0]
default_triggers[field.name] = args_spec or (no_args_event_spec)
default_triggers[field.name] = args_spec or (no_args_event_spec) # type: ignore
return default_triggers
def __repr__(self) -> str:
@ -639,7 +624,8 @@ class Component(BaseComponent, ABC):
if props is None:
# Add component props to the tag.
props = {
attr.removesuffix("_"): getattr(self, attr) for attr in self.get_props()
attr[:-1] if attr.endswith("_") else attr: getattr(self, attr)
for attr in self.get_props()
}
# Add ref to element if `id` is not None.
@ -688,22 +674,13 @@ class Component(BaseComponent, ABC):
"""
return set()
@classmethod
def _are_fields_known(cls) -> bool:
"""Check if all fields are known at compile time. True for most components.
Returns:
Whether all fields are known at compile time.
"""
return True
@classmethod
@lru_cache(maxsize=None)
def _get_component_prop_names(cls) -> Set[str]:
"""Get the names of the component props. NOTE: This assumes all fields are known.
def get_component_props(cls) -> set[str]:
"""Get the props that expected a component as value.
Returns:
The names of the component props.
The components props.
"""
return {
name
@ -712,28 +689,8 @@ class Component(BaseComponent, ABC):
and types._issubclass(field.outer_type_, Component)
}
def _get_components_in_props(self) -> Sequence[BaseComponent]:
"""Get the components in the props.
Returns:
The components in the props
"""
if self._are_fields_known():
return [
component
for name in self._get_component_prop_names()
for component in _components_from(getattr(self, name))
]
return [
component
for prop in self.get_props()
if (value := getattr(self, prop)) is not None
and isinstance(value, (BaseComponent, Var))
for component in _components_from(value)
]
@classmethod
def create(cls, *children, **props) -> Self:
def create(cls, *children, **props) -> Component:
"""Create the component.
Args:
@ -751,14 +708,14 @@ class Component(BaseComponent, ABC):
# Filter out None props
props = {key: value for key, value in props.items() if value is not None}
def validate_children(children: tuple | list):
def validate_children(children):
for child in children:
if isinstance(child, (tuple, list)):
validate_children(child)
# Make sure the child is a valid type.
if isinstance(child, dict) or not isinstance(
child, ComponentChildTypes
if isinstance(child, dict) or not types._isinstance(
child, ComponentChild
):
raise ChildrenTypeError(component=cls.__name__, child=child)
@ -803,7 +760,7 @@ class Component(BaseComponent, ABC):
# Walk the MRO to call all `add_style` methods.
for base in self._iter_parent_classes_with_method("add_style"):
s = base.add_style(self)
s = base.add_style(self) # type: ignore
if s is not None:
styles.append(s)
@ -895,7 +852,7 @@ class Component(BaseComponent, ABC):
else {}
)
def render(self) -> dict:
def render(self) -> Dict:
"""Render the component.
Returns:
@ -913,7 +870,7 @@ class Component(BaseComponent, ABC):
self._replace_prop_names(rendered_dict)
return rendered_dict
def _replace_prop_names(self, rendered_dict: dict) -> None:
def _replace_prop_names(self, rendered_dict) -> None:
"""Replace the prop names in the render dictionary.
Args:
@ -935,10 +892,8 @@ class Component(BaseComponent, ABC):
children: The children of the component.
"""
from reflex.components.base.bare import Bare
from reflex.components.base.fragment import Fragment
from reflex.components.core.cond import Cond
from reflex.components.core.foreach import Foreach
from reflex.components.core.match import Match
no_valid_parents_defined = all(child._valid_parents == [] for child in children)
if (
@ -949,11 +904,9 @@ class Component(BaseComponent, ABC):
return
comp_name = type(self).__name__
allowed_components = [
comp.__name__ for comp in (Fragment, Foreach, Cond, Match)
]
allowed_components = [comp.__name__ for comp in (Fragment,)]
def validate_child(child: Any):
def validate_child(child):
child_name = type(child).__name__
# Iterate through the immediate children of fragment
@ -961,24 +914,38 @@ class Component(BaseComponent, ABC):
for c in child.children:
validate_child(c)
if isinstance(child, Cond):
validate_child(child.comp1)
validate_child(child.comp2)
if isinstance(child, Match):
for cases in child.match_cases:
validate_child(cases[-1])
validate_child(child.default)
if (
isinstance(child, Bare)
and child.contents is not None
and isinstance(child.contents, Var)
):
var_data = child.contents._get_all_var_data()
if var_data is not None:
for c in var_data.components:
validate_child(c)
if self._invalid_children and child_name in self._invalid_children:
raise ValueError(
f"The component `{comp_name}` cannot have `{child_name}` as a child component"
)
if self._valid_children and child_name not in [
*self._valid_children,
*allowed_components,
]:
valid_children = self._valid_children + allowed_components
def child_is_in_valid(child):
if type(child).__name__ in valid_children:
return True
if (
not isinstance(child, Bare)
or child.contents is None
or not isinstance(child.contents, Var)
or (var_data := child.contents._get_all_var_data()) is None
):
return False
return all(child_is_in_valid(c) for c in var_data.components)
if self._valid_children and not child_is_in_valid(child):
valid_child_list = ", ".join(
[f"`{v_child}`" for v_child in self._valid_children]
)
@ -1188,9 +1155,6 @@ class Component(BaseComponent, ABC):
if custom_code is not None:
code.add(custom_code)
for component in self._get_components_in_props():
code |= component._get_all_custom_code()
# Add the custom code from add_custom_code method.
for clz in self._iter_parent_classes_with_method("add_custom_code"):
for item in clz.add_custom_code(self):
@ -1218,7 +1182,7 @@ class Component(BaseComponent, ABC):
The dynamic imports.
"""
# Store the import in a set to avoid duplicates.
dynamic_imports: set[str] = set()
dynamic_imports = set()
# Get dynamic import for this component.
dynamic_import = self._get_dynamic_imports()
@ -1229,12 +1193,25 @@ class Component(BaseComponent, ABC):
for child in self.children:
dynamic_imports |= child._get_all_dynamic_imports()
for component in self._get_components_in_props():
dynamic_imports |= component._get_all_dynamic_imports()
for prop in self.get_component_props():
if getattr(self, prop) is not None:
dynamic_imports |= getattr(self, prop)._get_all_dynamic_imports()
# Return the dynamic imports
return dynamic_imports
def _get_props_imports(self) -> List[ParsedImportDict]:
"""Get the imports needed for components props.
Returns:
The imports for the components props of the component.
"""
return [
getattr(self, prop)._get_all_imports()
for prop in self.get_component_props()
if getattr(self, prop) is not None
]
def _should_transpile(self, dep: str | None) -> bool:
"""Check if a dependency should be transpiled.
@ -1244,7 +1221,7 @@ class Component(BaseComponent, ABC):
Returns:
True if the dependency should be transpiled.
"""
return bool(self.transpile_packages) and (
return (
dep in self.transpile_packages
or format.format_library_name(dep or "") in self.transpile_packages
)
@ -1327,10 +1304,9 @@ class Component(BaseComponent, ABC):
event_imports = Imports.EVENTS if self.event_triggers else {}
# Collect imports from Vars used directly by this component.
var_imports = [
var_data.imports
for var in self._get_vars()
if (var_data := var._get_all_var_data()) is not None
var_datas = [var._get_all_var_data() for var in self._get_vars()]
var_imports: List[ImmutableParsedImportDict] = [
var_data.imports for var_data in var_datas if var_data is not None
]
added_import_dicts: list[ParsedImportDict] = []
@ -1345,6 +1321,7 @@ class Component(BaseComponent, ABC):
)
return imports.merge_imports(
*self._get_props_imports(),
self._get_dependencies_imports(),
self._get_hooks_imports(),
_imports,
@ -1421,8 +1398,6 @@ class Component(BaseComponent, ABC):
for k in var_data.hooks
}
)
for component in var_data.components:
vars_hooks.update(component._get_all_hooks())
return vars_hooks
def _get_events_hooks(self) -> dict[str, VarData | None]:
@ -1571,9 +1546,6 @@ class Component(BaseComponent, ABC):
refs.add(ref)
for child in self.children:
refs |= child._get_all_refs()
for component in self._get_components_in_props():
refs |= component._get_all_refs()
return refs
def _get_all_custom_components(
@ -1597,9 +1569,6 @@ class Component(BaseComponent, ABC):
if not isinstance(child, Component):
continue
custom_components |= child._get_all_custom_components(seen=seen)
for component in self._get_components_in_props():
if isinstance(component, Component) and component.tag is not None:
custom_components |= component._get_all_custom_components(seen=seen)
return custom_components
@property
@ -1663,65 +1632,17 @@ class CustomComponent(Component):
# The props of the component.
props: Dict[str, Any] = {}
def __init__(self, **kwargs):
# Props that reference other components.
component_props: Dict[str, Component] = {}
def __init__(self, *args, **kwargs):
"""Initialize the custom component.
Args:
*args: The args to pass to the component.
**kwargs: The kwargs to pass to the component.
"""
component_fn = kwargs.get("component_fn")
# Set the props.
props_types = typing.get_type_hints(component_fn) if component_fn else {}
props = {key: value for key, value in kwargs.items() if key in props_types}
kwargs = {key: value for key, value in kwargs.items() if key not in props_types}
event_types = {
key
for key in props
if (
(get_origin((annotation := props_types.get(key))) or annotation)
== EventHandler
)
}
def get_args_spec(key: str) -> types.ArgsSpec | Sequence[types.ArgsSpec]:
type_ = props_types[key]
return (
args[0]
if (args := get_args(type_))
else (
annotation_args[1]
if get_origin(
(
annotation := inspect.getfullargspec(
component_fn
).annotations[key]
)
)
is typing.Annotated
and (annotation_args := get_args(annotation))
else no_args_event_spec
)
)
super().__init__(
event_triggers={
key: EventChain.create(
value=props[key],
args_spec=get_args_spec(key),
key=key,
)
for key in event_types
},
**kwargs,
)
to_camel_cased_props = {
format.to_camel_case(key) for key in props if key not in event_types
}
self.get_props = lambda: to_camel_cased_props # pyright: ignore [reportIncompatibleVariableOverride]
super().__init__(*args, **kwargs)
# Unset the style.
self.style = Style()
@ -1729,36 +1650,51 @@ class CustomComponent(Component):
# Set the tag to the name of the function.
self.tag = format.to_title_case(self.component_fn.__name__)
for key, value in props.items():
# Skip kwargs that are not props.
if key not in props_types:
continue
# Get the event triggers defined in the component declaration.
event_triggers_in_component_declaration = self.get_event_triggers()
camel_cased_key = format.to_camel_case(key)
# Set the props.
props = typing.get_type_hints(self.component_fn)
for key, value in kwargs.items():
# Skip kwargs that are not props.
if key not in props:
continue
# Get the type based on the annotation.
type_ = props_types[key]
type_ = props[key]
# Handle event chains.
if types._issubclass(type_, EventActionsMixin):
inspect.getfullargspec(component_fn).annotations[key]
self.props[camel_cased_key] = EventChain.create(
value=value, args_spec=get_args_spec(key), key=key
if types._issubclass(type_, EventChain):
value = EventChain.create(
value=value,
args_spec=event_triggers_in_component_declaration.get(
key, no_args_event_spec
),
key=key,
)
self.props[format.to_camel_case(key)] = value
continue
value = LiteralVar.create(value)
self.props[camel_cased_key] = value
setattr(self, camel_cased_key, value)
# Handle subclasses of Base.
if isinstance(value, Base):
base_value = LiteralVar.create(value)
@classmethod
def _are_fields_known(cls) -> bool:
"""Check if the fields are known.
# Track hooks and imports associated with Component instances.
if base_value is not None and isinstance(value, Component):
self.component_props[key] = value
value = base_value._replace(
merge_var_data=VarData( # type: ignore
imports=value._get_all_imports(),
hooks=value._get_all_hooks(),
)
)
else:
value = base_value
else:
value = LiteralVar.create(value)
Returns:
Whether the fields are known.
"""
return False
# Set the prop.
self.props[format.to_camel_case(key)] = value
def __eq__(self, other: Any) -> bool:
"""Check if the component is equal to another.
@ -1817,8 +1753,27 @@ class CustomComponent(Component):
seen=seen
)
# Fetch custom components from props as well.
for child_component in self.component_props.values():
if child_component.tag is None:
continue
if child_component.tag not in seen:
seen.add(child_component.tag)
if isinstance(child_component, CustomComponent):
custom_components |= {child_component}
custom_components |= child_component._get_all_custom_components(
seen=seen
)
return custom_components
def _render(self) -> Tag:
"""Define how to render the component in React.
Returns:
The tag to render.
"""
return super()._render(props=self.props)
def get_prop_vars(self) -> List[Var]:
"""Get the prop vars.
@ -1829,19 +1784,34 @@ class CustomComponent(Component):
Var(
_js_expr=name,
_var_type=(
prop._var_type
if isinstance(prop, Var)
else (
type(prop)
if not isinstance(prop, EventActionsMixin)
else EventChain
)
prop._var_type if types._isinstance(prop, Var) else type(prop)
),
).guess_type()
for name, prop in self.props.items()
]
@lru_cache(maxsize=None) # noqa: B019
def _get_vars(
self, include_children: bool = False, ignore_ids: set[int] | None = None
) -> Iterator[Var]:
"""Walk all Vars used in this component.
Args:
include_children: Whether to include Vars from children.
ignore_ids: The ids to ignore.
Yields:
Each var referenced by the component (props, styles, event handlers).
"""
ignore_ids = ignore_ids or set()
yield from super()._get_vars(
include_children=include_children, ignore_ids=ignore_ids
)
yield from filter(lambda prop: isinstance(prop, Var), self.props.values())
yield from self.get_component(self)._get_vars(
include_children=include_children, ignore_ids=ignore_ids
)
@lru_cache(maxsize=None) # noqa
def get_component(self) -> Component:
"""Render the component.
@ -1966,8 +1936,6 @@ class StatefulComponent(BaseComponent):
Returns:
The stateful component or None if the component should not be memoized.
"""
from reflex.components.core.foreach import Foreach
if component._memoization_mode.disposition == MemoizationDisposition.NEVER:
# Never memoize this component.
return None
@ -1985,7 +1953,7 @@ class StatefulComponent(BaseComponent):
if not should_memoize:
# Determine if any Vars have associated data.
for prop_var in component._get_vars(include_children=True):
for prop_var in component._get_vars():
if prop_var._get_all_var_data():
should_memoize = True
break
@ -1996,10 +1964,6 @@ class StatefulComponent(BaseComponent):
# 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):
should_memoize = True
break
child = cls._child_var(child)
if isinstance(child, Var) and child._get_all_var_data():
should_memoize = True
@ -2049,18 +2013,9 @@ class StatefulComponent(BaseComponent):
The Var from the child component or the child itself (for regular cases).
"""
from reflex.components.base.bare import Bare
from reflex.components.core.cond import Cond
from reflex.components.core.foreach import Foreach
from reflex.components.core.match import Match
if isinstance(child, Bare):
return child.contents
if isinstance(child, Cond):
return child.cond
if isinstance(child, Foreach):
return child.iterable
if isinstance(child, Match):
return child.cond
return child
@classmethod
@ -2319,6 +2274,10 @@ class StatefulComponent(BaseComponent):
return _compile_component(self)
def __getattr__(self, name) -> Any:
# if we don't provide the attribute, get it from the wrapped component
return getattr(self.component, name)
@classmethod
def compile_from(cls, component: BaseComponent) -> BaseComponent:
"""Walk through the component tree and memoize all stateful components.
@ -2368,8 +2327,8 @@ class MemoizationLeaf(Component):
"""
comp = super().create(*children, **props)
if comp._get_all_hooks():
comp._memoization_mode = dataclasses.replace(
comp._memoization_mode, disposition=MemoizationDisposition.ALWAYS
comp._memoization_mode = cls._memoization_mode.copy(
update={"disposition": MemoizationDisposition.ALWAYS}
)
return comp
@ -2407,53 +2366,6 @@ def render_dict_to_var(tag: dict | Component | str, imported_names: set[str]) ->
return render_dict_to_var(tag.render(), imported_names)
return Var.create(tag)
if "iterable" in tag:
function_return = Var.create(
[
render_dict_to_var(child.render(), imported_names)
for child in tag["children"]
]
)
func = ArgsFunctionOperation.create(
(tag["arg_var_name"], tag["index_var_name"]),
function_return,
)
return FunctionStringVar.create("Array.prototype.map.call").call(
tag["iterable"]
if not isinstance(tag["iterable"], ObjectVar)
else tag["iterable"].items(),
func,
)
if tag["name"] == "match":
element = tag["cond"]
conditionals = render_dict_to_var(tag["default"], imported_names)
for case in tag["match_cases"][::-1]:
condition = case[0].to_string() == element.to_string()
for pattern in case[1:-1]:
condition = condition | (pattern.to_string() == element.to_string())
conditionals = ternary_operation(
condition,
render_dict_to_var(case[-1], imported_names),
conditionals,
)
return conditionals
if "cond" in tag:
return ternary_operation(
tag["cond"],
render_dict_to_var(tag["true_value"], imported_names),
render_dict_to_var(tag["false_value"], imported_names)
if tag["false_value"] is not None
else Var.create(None),
)
props = {}
special_props = []
@ -2498,7 +2410,6 @@ def render_dict_to_var(tag: dict | Component | str, imported_names: set[str]) ->
@dataclasses.dataclass(
eq=False,
frozen=True,
slots=True,
)
class LiteralComponentVar(CachedVarOperation, LiteralVar, ComponentVar):
"""A Var that represents a Component."""
@ -2528,23 +2439,19 @@ class LiteralComponentVar(CachedVarOperation, LiteralVar, ComponentVar):
The VarData for the var.
"""
return VarData.merge(
self._var_data,
VarData(
imports={
"@emotion/react": [
ImportVar(tag="jsx"),
],
}
),
VarData(
imports=self._var_value._get_all_imports(),
),
VarData(
imports={
"react": [
ImportVar(tag="Fragment"),
],
}
},
components=(self._var_value,),
),
VarData(
imports=self._var_value._get_all_imports(),
),
)
@ -2571,21 +2478,11 @@ class LiteralComponentVar(CachedVarOperation, LiteralVar, ComponentVar):
Returns:
The var.
"""
var_datas = [
var_data
for var in value._get_vars(include_children=True)
if (var_data := var._get_all_var_data())
]
if not isinstance(value, StatefulComponent):
value = StatefulComponent.compile_from(value) or value
return LiteralComponentVar(
_js_expr="",
_var_type=type(value),
_var_data=VarData.merge(
_var_data,
*var_datas,
VarData(
components=(value,),
),
),
_var_data=_var_data,
_var_value=value,
)

View File

@ -21,16 +21,14 @@ _SUBMOD_ATTRS: dict[str, list[str]] = {
"colors": [
"color",
],
"cond": ["Cond", "color_mode_cond", "cond"],
"cond": ["color_mode_cond", "cond"],
"debounce": ["DebounceInput", "debounce_input"],
"foreach": [
"foreach",
"Foreach",
],
"html": ["html", "Html"],
"match": [
"match",
"Match",
],
"breakpoints": ["breakpoints", "set_breakpoints"],
"responsive": [
@ -48,7 +46,6 @@ _SUBMOD_ATTRS: dict[str, list[str]] = {
"get_upload_url",
"selected_files",
],
"auto_scroll": ["auto_scroll"],
}
__getattr__, __dir__, __all__ = lazy_loader.attach(

View File

@ -4,7 +4,6 @@
# ------------------------------------------------------
from . import layout as layout
from .auto_scroll import auto_scroll as auto_scroll
from .banner import ConnectionBanner as ConnectionBanner
from .banner import ConnectionModal as ConnectionModal
from .banner import ConnectionPulser as ConnectionPulser
@ -18,16 +17,13 @@ from .breakpoints import set_breakpoints as set_breakpoints
from .clipboard import Clipboard as Clipboard
from .clipboard import clipboard as clipboard
from .colors import color as color
from .cond import Cond as Cond
from .cond import color_mode_cond as color_mode_cond
from .cond import cond as cond
from .debounce import DebounceInput as DebounceInput
from .debounce import debounce_input as debounce_input
from .foreach import Foreach as Foreach
from .foreach import foreach as foreach
from .html import Html as Html
from .html import html as html
from .match import Match as Match
from .match import match as match
from .responsive import desktop_only as desktop_only
from .responsive import mobile_and_tablet as mobile_and_tablet

View File

@ -1,114 +0,0 @@
"""A component that automatically scrolls to the bottom when new content is added."""
from __future__ import annotations
from reflex.components.el.elements.typography import Div
from reflex.constants.compiler import MemoizationDisposition, MemoizationMode
from reflex.utils.imports import ImportDict
from reflex.vars.base import Var, get_unique_variable_name
class AutoScroll(Div):
"""A div that automatically scrolls to the bottom when new content is added."""
_memoization_mode = MemoizationMode(
disposition=MemoizationDisposition.ALWAYS, recursive=False
)
@classmethod
def create(cls, *children, **props):
"""Create an AutoScroll component.
Args:
*children: The children of the component.
**props: The props of the component.
Returns:
An AutoScroll component.
"""
props.setdefault("overflow", "auto")
props.setdefault("id", get_unique_variable_name())
return super().create(*children, **props)
def add_imports(self) -> ImportDict | list[ImportDict]:
"""Add imports required for the component.
Returns:
The imports required for the component.
"""
return {"react": ["useEffect", "useRef"]}
def add_hooks(self) -> list[str | Var]:
"""Add hooks required for the component.
Returns:
The hooks required for the component.
"""
ref_name = self.get_ref()
return [
"const wasNearBottom = useRef(false);",
"const hadScrollbar = useRef(false);",
f"""
const checkIfNearBottom = () => {{
if (!{ref_name}.current) return;
const container = {ref_name}.current;
const nearBottomThreshold = 50; // pixels from bottom to trigger auto-scroll
const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight;
wasNearBottom.current = distanceFromBottom <= nearBottomThreshold;
// Track if container had a scrollbar
hadScrollbar.current = container.scrollHeight > container.clientHeight;
}};
""",
f"""
const scrollToBottomIfNeeded = () => {{
if (!{ref_name}.current) return;
const container = {ref_name}.current;
const hasScrollbarNow = container.scrollHeight > container.clientHeight;
// Scroll if:
// 1. User was near bottom, OR
// 2. Container didn't have scrollbar before but does now
if (wasNearBottom.current || (!hadScrollbar.current && hasScrollbarNow)) {{
container.scrollTop = container.scrollHeight;
}}
// Update scrollbar state for next check
hadScrollbar.current = hasScrollbarNow;
}};
""",
f"""
useEffect(() => {{
const container = {ref_name}.current;
if (!container) return;
scrollToBottomIfNeeded();
// Create ResizeObserver to detect height changes
const resizeObserver = new ResizeObserver(() => {{
scrollToBottomIfNeeded();
}});
// Track scroll position before height changes
container.addEventListener('scroll', checkIfNearBottom);
// Initial check
checkIfNearBottom();
// Observe container for size changes
resizeObserver.observe(container);
return () => {{
container.removeEventListener('scroll', checkIfNearBottom);
resizeObserver.disconnect();
}};
}});
""",
]
auto_scroll = AutoScroll.create

View File

@ -1,284 +0,0 @@
"""Stub file for reflex/components/core/auto_scroll.py"""
# ------------------- DO NOT EDIT ----------------------
# This file was generated by `reflex/utils/pyi_generator.py`!
# ------------------------------------------------------
from typing import Any, Dict, Literal, Optional, Union, overload
from reflex.components.el.elements.typography import Div
from reflex.event import EventType
from reflex.style import Style
from reflex.utils.imports import ImportDict
from reflex.vars.base import Var
class AutoScroll(Div):
@overload
@classmethod
def create( # type: ignore
cls,
*children,
access_key: Optional[Union[Var[str], str]] = None,
auto_capitalize: Optional[
Union[
Literal["characters", "none", "off", "on", "sentences", "words"],
Var[Literal["characters", "none", "off", "on", "sentences", "words"]],
]
] = None,
content_editable: Optional[
Union[
Literal["inherit", "plaintext-only", False, True],
Var[Literal["inherit", "plaintext-only", False, True]],
]
] = None,
context_menu: Optional[Union[Var[str], str]] = None,
dir: Optional[Union[Var[str], str]] = None,
draggable: Optional[Union[Var[bool], bool]] = None,
enter_key_hint: Optional[
Union[
Literal["done", "enter", "go", "next", "previous", "search", "send"],
Var[
Literal["done", "enter", "go", "next", "previous", "search", "send"]
],
]
] = None,
hidden: Optional[Union[Var[bool], bool]] = None,
input_mode: Optional[
Union[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
],
Var[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
]
],
]
] = None,
item_prop: Optional[Union[Var[str], str]] = None,
lang: Optional[Union[Var[str], str]] = None,
role: Optional[
Union[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
],
Var[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
]
],
]
] = None,
slot: Optional[Union[Var[str], str]] = None,
spell_check: Optional[Union[Var[bool], bool]] = None,
tab_index: Optional[Union[Var[int], int]] = None,
title: Optional[Union[Var[str], str]] = 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, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
**props,
) -> "AutoScroll":
"""Create an AutoScroll component.
Args:
*children: The children of the component.
access_key: Provides a hint for generating a keyboard shortcut for the current element.
auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
content_editable: Indicates whether the element's content is editable.
context_menu: Defines the ID of a <menu> element which will serve as the element's context menu.
dir: Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)
draggable: Defines whether the element can be dragged.
enter_key_hint: Hints what media types the media element is able to play.
hidden: Defines whether the element is hidden.
input_mode: Defines the type of the element.
item_prop: Defines the name of the element for metadata purposes.
lang: Defines the language used in the element.
role: Defines the role of the element.
slot: Assigns a slot in a shadow DOM shadow tree to an element.
spell_check: Defines whether the element may be checked for spelling errors.
tab_index: Defines the position of the current element in the tabbing order.
title: Defines a tooltip for the element.
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:
An AutoScroll component.
"""
...
def add_imports(self) -> ImportDict | list[ImportDict]: ...
def add_hooks(self) -> list[str | Var]: ...
auto_scroll = AutoScroll.create

View File

@ -4,7 +4,6 @@ from __future__ import annotations
from typing import Optional
from reflex import constants
from reflex.components.base.fragment import Fragment
from reflex.components.component import Component
from reflex.components.core.cond import cond
@ -17,8 +16,7 @@ from reflex.components.radix.themes.components.dialog import (
)
from reflex.components.radix.themes.layout.flex import Flex
from reflex.components.radix.themes.typography.text import Text
from reflex.components.sonner.toast import ToastProps, toast_ref
from reflex.config import environment
from reflex.components.sonner.toast import Toaster, ToastProps
from reflex.constants import Dirs, Hooks, Imports
from reflex.constants.compiler import CompileVars
from reflex.utils.imports import ImportVar
@ -28,7 +26,7 @@ from reflex.vars.function import FunctionStringVar
from reflex.vars.number import BooleanVar
from reflex.vars.sequence import LiteralArrayVar
connect_error_var_data: VarData = VarData(
connect_error_var_data: VarData = VarData( # type: ignore
imports=Imports.EVENTS,
hooks={Hooks.EVENTS: None},
)
@ -91,7 +89,7 @@ def default_connection_error() -> list[str | Var | Component]:
]
class ConnectionToaster(Fragment):
class ConnectionToaster(Toaster):
"""A connection toaster component."""
def add_hooks(self) -> list[str | Var]:
@ -102,57 +100,24 @@ class ConnectionToaster(Fragment):
"""
toast_id = "websocket-error"
target_url = WebsocketTargetURL.create()
props = ToastProps(
props = ToastProps( # type: ignore
description=LiteralVar.create(
f"Check if server is reachable at {target_url}",
),
close_button=True,
duration=120000,
id=toast_id,
) # pyright: ignore [reportCallIssue]
if environment.REFLEX_DOES_BACKEND_COLD_START.get():
loading_message = Var.create("Backend is starting.")
backend_is_loading_toast_var = Var(
f"toast?.loading({loading_message!s}, {{...toast_props, description: '', closeButton: false, onDismiss: () => setUserDismissed(true)}},)"
)
backend_is_not_responding = Var.create("Backend is not responding.")
backend_is_down_toast_var = Var(
f"toast?.error({backend_is_not_responding!s}, {{...toast_props, description: '', onDismiss: () => setUserDismissed(true)}},)"
)
toast_var = Var(
f"""
if (waitedForBackend) {{
{backend_is_down_toast_var!s}
}} else {{
{backend_is_loading_toast_var!s};
}}
setTimeout(() => {{
if ({has_too_many_connection_errors!s}) {{
setWaitedForBackend(true);
}}
}}, {environment.REFLEX_BACKEND_COLD_START_TIMEOUT.get() * 1000});
"""
)
else:
loading_message = Var.create(
f"Cannot connect to server: {connection_error}."
)
toast_var = Var(
f"toast?.error({loading_message!s}, {{...toast_props, onDismiss: () => setUserDismissed(true)}},)"
)
)
individual_hooks = [
Var(f"const toast = {toast_ref};"),
f"const toast_props = {LiteralVar.create(props)!s};",
"const [userDismissed, setUserDismissed] = useState(false);",
"const [waitedForBackend, setWaitedForBackend] = useState(false);",
FunctionStringVar(
"useEffect",
_var_data=VarData(
imports={
"react": ["useEffect", "useState"],
**dict(target_url._get_all_var_data().imports), # pyright: ignore [reportArgumentType, reportOptionalMemberAccess]
**dict(target_url._get_all_var_data().imports), # type: ignore
}
),
).call(
@ -162,16 +127,19 @@ setTimeout(() => {{
() => {{
if ({has_too_many_connection_errors!s}) {{
if (!userDismissed) {{
{toast_var!s}
toast.error(
`Cannot connect to server: ${{{connection_error}}}.`,
{{...toast_props, onDismiss: () => setUserDismissed(true)}},
)
}}
}} else {{
toast?.dismiss("{toast_id}");
toast.dismiss("{toast_id}");
setUserDismissed(false); // after reconnection reset dismissed state
}}
}}
"""
),
LiteralArrayVar.create([connect_errors, Var("waitedForBackend")]),
LiteralArrayVar.create([connect_errors]),
),
]
@ -191,10 +159,11 @@ setTimeout(() => {{
Returns:
The connection toaster component.
"""
Toaster.is_used = True
return super().create(*children, **props)
class ConnectionBanner(Component):
class ConnectionBanner(Fragment):
"""A connection banner component."""
@classmethod
@ -221,10 +190,10 @@ class ConnectionBanner(Component):
position="fixed",
)
return cond(has_connection_errors, comp)
return super().create(cond(has_connection_errors, comp))
class ConnectionModal(Component):
class ConnectionModal(Fragment):
"""A connection status modal window."""
@classmethod
@ -239,16 +208,18 @@ class ConnectionModal(Component):
"""
if not comp:
comp = Text.create(*default_connection_error())
return cond(
has_too_many_connection_errors,
DialogRoot.create(
DialogContent.create(
DialogTitle.create("Connection Error"),
comp,
return super().create(
cond(
has_too_many_connection_errors,
DialogRoot.create(
DialogContent.create(
DialogTitle.create("Connection Error"),
comp,
),
open=has_too_many_connection_errors,
z_index=9999,
),
open=has_too_many_connection_errors,
z_index=9999,
),
)
)
@ -325,161 +296,7 @@ class ConnectionPulser(Div):
)
class BackendDisabled(Div):
"""A component that displays a message when the backend is disabled."""
@classmethod
def create(cls, **props) -> Component:
"""Create a backend disabled component.
Args:
**props: The properties of the component.
Returns:
The backend disabled component.
"""
import reflex as rx
is_backend_disabled = Var(
"backendDisabled",
_var_type=bool,
_var_data=VarData(
hooks={
"const [backendDisabled, setBackendDisabled] = useState(false);": None,
"useEffect(() => { setBackendDisabled(isBackendDisabled()); }, []);": None,
},
imports={
f"$/{constants.Dirs.STATE_PATH}": [
ImportVar(tag="isBackendDisabled")
],
},
),
)
return super().create(
rx.cond(
is_backend_disabled,
rx.box(
rx.el.link(
rel="preconnect",
href="https://fonts.googleapis.com",
),
rx.el.link(
rel="preconnect",
href="https://fonts.gstatic.com",
crossorigin="",
),
rx.el.link(
href="https://fonts.googleapis.com/css2?family=Instrument+Sans:ital,wght@0,500;0,600&display=swap",
rel="stylesheet",
),
rx.box(
rx.vstack(
rx.text(
"This app is paused",
font_size="1.5rem",
font_weight="600",
line_height="1.25rem",
letter_spacing="-0.0375rem",
),
rx.hstack(
rx.el.svg(
rx.el.svg.path(
d="M6.90816 1.34341C7.61776 1.10786 8.38256 1.10786 9.09216 1.34341C9.7989 1.57799 10.3538 2.13435 10.9112 2.91605C11.4668 3.69515 12.0807 4.78145 12.872 6.18175L12.9031 6.23672C13.6946 7.63721 14.3085 8.72348 14.6911 9.60441C15.0755 10.4896 15.267 11.2539 15.1142 11.9881C14.9604 12.7275 14.5811 13.3997 14.0287 13.9079C13.4776 14.4147 12.7273 14.6286 11.7826 14.7313C10.8432 14.8334 9.6143 14.8334 8.0327 14.8334H7.9677C6.38604 14.8334 5.15719 14.8334 4.21778 14.7313C3.27301 14.6286 2.52269 14.4147 1.97164 13.9079C1.41924 13.3997 1.03995 12.7275 0.88613 11.9881C0.733363 11.2539 0.92483 10.4896 1.30926 9.60441C1.69184 8.72348 2.30573 7.63721 3.09722 6.23671L3.12828 6.18175C3.91964 4.78146 4.53355 3.69515 5.08914 2.91605C5.64658 2.13435 6.20146 1.57799 6.90816 1.34341ZM7.3335 11.3334C7.3335 10.9652 7.63063 10.6667 7.99716 10.6667H8.00316C8.3697 10.6667 8.66683 10.9652 8.66683 11.3334C8.66683 11.7016 8.3697 12.0001 8.00316 12.0001H7.99716C7.63063 12.0001 7.3335 11.7016 7.3335 11.3334ZM7.3335 8.66675C7.3335 9.03495 7.63196 9.33341 8.00016 9.33341C8.36836 9.33341 8.66683 9.03495 8.66683 8.66675V6.00008C8.66683 5.63189 8.36836 5.33341 8.00016 5.33341C7.63196 5.33341 7.3335 5.63189 7.3335 6.00008V8.66675Z",
fill_rule="evenodd",
clip_rule="evenodd",
fill=rx.color("amber", 11),
),
width="16",
height="16",
viewBox="0 0 16 16",
fill="none",
xmlns="http://www.w3.org/2000/svg",
margin_top="0.125rem",
flex_shrink="0",
),
rx.text(
"If you are the owner of this app, visit ",
rx.link(
"Reflex Cloud",
color=rx.color("amber", 11),
underline="always",
_hover={
"color": rx.color("amber", 11),
"text_decoration_color": rx.color(
"amber", 11
),
},
text_decoration_color=rx.color("amber", 10),
href="https://cloud.reflex.dev/",
font_weight="600",
is_external=True,
),
" for more information on how to resume your app.",
font_size="0.875rem",
font_weight="500",
line_height="1.25rem",
letter_spacing="-0.01094rem",
color=rx.color("amber", 11),
),
align="start",
gap="0.625rem",
border_radius="0.75rem",
border_width="1px",
border_color=rx.color("amber", 5),
background_color=rx.color("amber", 3),
padding="0.625rem",
),
rx.link(
rx.el.button(
"Resume app",
color="rgba(252, 252, 253, 1)",
font_size="0.875rem",
font_weight="600",
line_height="1.25rem",
letter_spacing="-0.01094rem",
height="2.5rem",
padding="0rem 0.75rem",
width="100%",
border_radius="0.75rem",
background=f"linear-gradient(180deg, {rx.color('violet', 9)} 0%, {rx.color('violet', 10)} 100%)",
_hover={
"background": f"linear-gradient(180deg, {rx.color('violet', 10)} 0%, {rx.color('violet', 10)} 100%)",
},
),
width="100%",
underline="none",
href="https://cloud.reflex.dev/",
is_external=True,
),
gap="1rem",
),
font_family='"Instrument Sans", "Helvetica", "Arial", sans-serif',
position="fixed",
top="50%",
left="50%",
transform="translate(-50%, -50%)",
width="60ch",
max_width="90vw",
border_radius="0.75rem",
border_width="1px",
border_color=rx.color("slate", 4),
padding="1.5rem",
background_color=rx.color("slate", 1),
box_shadow="0px 2px 5px 0px light-dark(rgba(28, 32, 36, 0.03), rgba(0, 0, 0, 0.00))",
),
position="fixed",
z_index=9999,
backdrop_filter="grayscale(1) blur(5px)",
width="100dvw",
height="100dvh",
),
)
)
connection_banner = ConnectionBanner.create
connection_modal = ConnectionModal.create
connection_toaster = ConnectionToaster.create
connection_pulser = ConnectionPulser.create
backend_disabled = BackendDisabled.create

View File

@ -9,8 +9,9 @@ from reflex.components.base.fragment import Fragment
from reflex.components.component import Component
from reflex.components.el.elements.typography import Div
from reflex.components.lucide.icon import Icon
from reflex.components.sonner.toast import Toaster, ToastProps
from reflex.constants.compiler import CompileVars
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.utils.imports import ImportVar
from reflex.vars import VarData
@ -41,40 +42,89 @@ class WebsocketTargetURL(Var):
def default_connection_error() -> list[str | Var | Component]: ...
class ConnectionToaster(Fragment):
class ConnectionToaster(Toaster):
def add_hooks(self) -> list[str | Var]: ...
@overload
@classmethod
def create( # type: ignore
cls,
*children,
theme: Optional[Union[Var[str], str]] = None,
rich_colors: Optional[Union[Var[bool], bool]] = None,
expand: Optional[Union[Var[bool], bool]] = None,
visible_toasts: Optional[Union[Var[int], int]] = None,
position: Optional[
Union[
Literal[
"bottom-center",
"bottom-left",
"bottom-right",
"top-center",
"top-left",
"top-right",
],
Var[
Literal[
"bottom-center",
"bottom-left",
"bottom-right",
"top-center",
"top-left",
"top-right",
]
],
]
] = None,
close_button: Optional[Union[Var[bool], bool]] = None,
offset: Optional[Union[Var[str], str]] = None,
dir: Optional[Union[Var[str], str]] = None,
hotkey: Optional[Union[Var[str], str]] = None,
invert: Optional[Union[Var[bool], bool]] = None,
toast_options: Optional[Union[ToastProps, Var[ToastProps]]] = None,
gap: Optional[Union[Var[int], int]] = None,
loading_icon: Optional[Union[Icon, Var[Icon]]] = None,
pause_when_page_is_hidden: Optional[Union[Var[bool], bool]] = 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, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "ConnectionToaster":
"""Create a connection toaster component.
Args:
*children: The children of the component.
theme: the theme of the toast
rich_colors: whether to show rich colors
expand: whether to expand the toast
visible_toasts: the number of toasts that are currently visible
position: the position of the toast
close_button: whether to show the close button
offset: offset of the toast
dir: directionality of the toast (default: ltr)
hotkey: Keyboard shortcut that will move focus to the toaster area.
invert: Dark toasts in light mode and vice versa.
toast_options: These will act as default options for all toasts. See toast() for all available options.
gap: Gap between toasts when expanded
loading_icon: Changes the default loading icon
pause_when_page_is_hidden: Pauses toast timers when the page is hidden, e.g., when the tab is backgrounded, the browser is minimized, or the OS is locked.
style: The style of the component.
key: A unique key for the component.
id: The id for the component.
@ -88,7 +138,7 @@ class ConnectionToaster(Fragment):
"""
...
class ConnectionBanner(Component):
class ConnectionBanner(Fragment):
@overload
@classmethod
def create( # type: ignore
@ -100,21 +150,21 @@ class ConnectionBanner(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "ConnectionBanner":
"""Create a connection banner component.
@ -127,7 +177,7 @@ class ConnectionBanner(Component):
"""
...
class ConnectionModal(Component):
class ConnectionModal(Fragment):
@overload
@classmethod
def create( # type: ignore
@ -139,21 +189,21 @@ class ConnectionModal(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "ConnectionModal":
"""Create a connection banner component.
@ -179,21 +229,21 @@ class WifiOffPulse(Icon):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "WifiOffPulse":
"""Create a wifi_off icon with an animated opacity pulse.
@ -222,232 +272,51 @@ class ConnectionPulser(Div):
def create( # type: ignore
cls,
*children,
access_key: Optional[Union[Var[str], str]] = None,
access_key: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
auto_capitalize: Optional[
Union[
Literal["characters", "none", "off", "on", "sentences", "words"],
Var[Literal["characters", "none", "off", "on", "sentences", "words"]],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
content_editable: Optional[
Union[
Literal["inherit", "plaintext-only", False, True],
Var[Literal["inherit", "plaintext-only", False, True]],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
context_menu: Optional[Union[Var[str], str]] = None,
dir: Optional[Union[Var[str], str]] = None,
draggable: Optional[Union[Var[bool], bool]] = None,
context_menu: Optional[
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
dir: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
draggable: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
enter_key_hint: Optional[
Union[
Literal["done", "enter", "go", "next", "previous", "search", "send"],
Var[
Literal["done", "enter", "go", "next", "previous", "search", "send"]
],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
hidden: Optional[Union[Var[bool], bool]] = None,
input_mode: Optional[
Union[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
],
Var[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
]
],
]
] = None,
item_prop: Optional[Union[Var[str], str]] = None,
lang: Optional[Union[Var[str], str]] = None,
role: Optional[
Union[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
],
Var[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
]
],
]
] = None,
slot: Optional[Union[Var[str], str]] = None,
spell_check: Optional[Union[Var[bool], bool]] = None,
tab_index: Optional[Union[Var[int], int]] = None,
title: Optional[Union[Var[str], str]] = None,
hidden: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
input_mode: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
item_prop: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
lang: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
role: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
slot: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
spell_check: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
tab_index: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
title: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = 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, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "ConnectionPulser":
"""Create a connection pulser component.
@ -482,274 +351,7 @@ class ConnectionPulser(Div):
"""
...
class BackendDisabled(Div):
@overload
@classmethod
def create( # type: ignore
cls,
*children,
access_key: Optional[Union[Var[str], str]] = None,
auto_capitalize: Optional[
Union[
Literal["characters", "none", "off", "on", "sentences", "words"],
Var[Literal["characters", "none", "off", "on", "sentences", "words"]],
]
] = None,
content_editable: Optional[
Union[
Literal["inherit", "plaintext-only", False, True],
Var[Literal["inherit", "plaintext-only", False, True]],
]
] = None,
context_menu: Optional[Union[Var[str], str]] = None,
dir: Optional[Union[Var[str], str]] = None,
draggable: Optional[Union[Var[bool], bool]] = None,
enter_key_hint: Optional[
Union[
Literal["done", "enter", "go", "next", "previous", "search", "send"],
Var[
Literal["done", "enter", "go", "next", "previous", "search", "send"]
],
]
] = None,
hidden: Optional[Union[Var[bool], bool]] = None,
input_mode: Optional[
Union[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
],
Var[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
]
],
]
] = None,
item_prop: Optional[Union[Var[str], str]] = None,
lang: Optional[Union[Var[str], str]] = None,
role: Optional[
Union[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
],
Var[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
]
],
]
] = None,
slot: Optional[Union[Var[str], str]] = None,
spell_check: Optional[Union[Var[bool], bool]] = None,
tab_index: Optional[Union[Var[int], int]] = None,
title: Optional[Union[Var[str], str]] = 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, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
**props,
) -> "BackendDisabled":
"""Create a backend disabled component.
Args:
access_key: Provides a hint for generating a keyboard shortcut for the current element.
auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
content_editable: Indicates whether the element's content is editable.
context_menu: Defines the ID of a <menu> element which will serve as the element's context menu.
dir: Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)
draggable: Defines whether the element can be dragged.
enter_key_hint: Hints what media types the media element is able to play.
hidden: Defines whether the element is hidden.
input_mode: Defines the type of the element.
item_prop: Defines the name of the element for metadata purposes.
lang: Defines the language used in the element.
role: Defines the role of the element.
slot: Assigns a slot in a shadow DOM shadow tree to an element.
spell_check: Defines whether the element may be checked for spelling errors.
tab_index: Defines the position of the current element in the tabbing order.
title: Defines a tooltip for the element.
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 properties of the component.
Returns:
The backend disabled component.
"""
...
connection_banner = ConnectionBanner.create
connection_modal = ConnectionModal.create
connection_toaster = ConnectionToaster.create
connection_pulser = ConnectionPulser.create
backend_disabled = BackendDisabled.create

View File

@ -18,7 +18,7 @@ def set_breakpoints(values: Tuple[str, str, str, str, str]):
breakpoints_values.extend(values)
K = TypeVar("K", bound=str)
K = TypeVar("K")
V = TypeVar("V")
@ -82,9 +82,7 @@ class Breakpoints(Dict[K, V]):
return Breakpoints(
{
k: v
for k, v in zip(
["initial", *breakpoint_names], thresholds, strict=True
)
for k, v in zip(["initial", *breakpoint_names], thresholds)
if v is not None
}
)

View File

@ -41,7 +41,7 @@ class ClientSideRouting(Component):
return ""
def wait_for_client_redirect(component: Component) -> Component:
def wait_for_client_redirect(component) -> Component:
"""Wait for a redirect to occur before rendering a component.
This prevents the 404 page from flashing while the redirect is happening.

View File

@ -6,7 +6,7 @@
from typing import Any, Dict, Optional, Union, overload
from reflex.components.component import Component
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -26,21 +26,21 @@ class ClientSideRouting(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "ClientSideRouting":
"""Create the component.
@ -60,7 +60,7 @@ class ClientSideRouting(Component):
"""
...
def wait_for_client_redirect(component: Component) -> Component: ...
def wait_for_client_redirect(component) -> Component: ...
class Default404Page(Component):
@overload
@ -75,21 +75,21 @@ class Default404Page(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Default404Page":
"""Create the component.

View File

@ -6,7 +6,7 @@
from typing import Any, Dict, List, Optional, Union, overload
from reflex.components.base.fragment import Fragment
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.utils.imports import ImportVar
from reflex.vars.base import Var
@ -27,24 +27,27 @@ class Clipboard(Fragment):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_paste: Optional[
Union[EventType[()], EventType[list[tuple[str, str]]]]
Union[
EventType[[], BASE_STATE],
EventType[[list[tuple[str, str]]], BASE_STATE],
]
] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Clipboard":
"""Create a Clipboard component.

View File

@ -2,111 +2,18 @@
from __future__ import annotations
from typing import Any, Dict, Optional, overload
from typing import Any, Union, overload
from reflex.components.base.fragment import Fragment
from reflex.components.component import BaseComponent, Component, MemoizationLeaf
from reflex.components.tags import CondTag, Tag
from reflex.constants import Dirs
from reflex.components.component import BaseComponent, Component
from reflex.style import LIGHT_COLOR_MODE, resolved_color_mode
from reflex.utils.imports import ImportDict, ImportVar
from reflex.vars import VarData
from reflex.utils import types
from reflex.vars.base import LiteralVar, Var
from reflex.vars.number import ternary_operation
_IS_TRUE_IMPORT: ImportDict = {
f"$/{Dirs.STATE_PATH}": [ImportVar(tag="isTrue")],
}
class Cond(MemoizationLeaf):
"""Render one of two components based on a condition."""
# The cond to determine which component to render.
cond: Var[Any]
# The component to render if the cond is true.
comp1: BaseComponent | None = None
# The component to render if the cond is false.
comp2: BaseComponent | None = None
@classmethod
def create(
cls,
cond: Var,
comp1: BaseComponent,
comp2: Optional[BaseComponent] = None,
) -> Component:
"""Create a conditional component.
Args:
cond: The cond to determine which component to render.
comp1: The component to render if the cond is true.
comp2: The component to render if the cond is false.
Returns:
The conditional component.
"""
# Wrap everything in fragments.
if type(comp1).__name__ != "Fragment":
comp1 = Fragment.create(comp1)
if comp2 is None or type(comp2).__name__ != "Fragment":
comp2 = Fragment.create(comp2) if comp2 else Fragment.create()
return Fragment.create(
cls(
cond=cond,
comp1=comp1,
comp2=comp2,
children=[comp1, comp2],
)
)
def _render(self) -> Tag:
return CondTag(
cond=self.cond,
true_value=self.comp1.render(), # pyright: ignore [reportOptionalMemberAccess]
false_value=self.comp2.render(), # pyright: ignore [reportOptionalMemberAccess]
)
def render(self) -> Dict:
"""Render the component.
Returns:
The dictionary for template of component.
"""
tag = self._render()
return dict(
tag.add_props(
**self.event_triggers,
key=self.key,
sx=self.style,
id=self.id,
class_name=self.class_name,
).set(
props=tag.format_props(),
),
cond_state=f"isTrue({self.cond!s})",
)
def add_imports(self) -> ImportDict:
"""Add imports for the Cond component.
Returns:
The import dict for the component.
"""
var_data = VarData.merge(self.cond._get_all_var_data())
imports = var_data.old_school_imports() if var_data else {}
return {**imports, **_IS_TRUE_IMPORT}
@overload
def cond(condition: Any, c1: Component, c2: Any) -> Component: ... # pyright: ignore [reportOverlappingOverload]
@overload
def cond(condition: Any, c1: Component) -> Component: ...
def cond(condition: Any, c1: Component, c2: Any = None) -> Component: ...
@overload
@ -129,41 +36,30 @@ def cond(condition: Any, c1: Any, c2: Any = None) -> Component | Var:
"""
# Convert the condition to a Var.
cond_var = LiteralVar.create(condition)
if cond_var is None:
raise ValueError("The condition must be set.")
# If the first component is a component, create a Cond component.
if isinstance(c1, BaseComponent):
if c2 is not None and not isinstance(c2, BaseComponent):
raise ValueError("Both arguments must be components.")
return Cond.create(cond_var, c1, c2)
# If the first component is a component, create a Fragment if the second component is not set.
if isinstance(c1, BaseComponent) or (
isinstance(c1, Var)
and types.safe_typehint_issubclass(
c1._var_type, Union[BaseComponent, list[BaseComponent]]
)
):
c2 = c2 if c2 is not None else Fragment.create()
# Otherwise, create a conditional Var.
# Check that the second argument is valid.
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.")
def create_var(cond_part: Any) -> Var[Any]:
return LiteralVar.create(cond_part)
# convert the truth and false cond parts into vars so the _var_data can be obtained.
c1 = create_var(c1)
c2 = create_var(c2)
# Create the conditional var.
return ternary_operation(
cond_var.bool()._replace(
merge_var_data=VarData(imports=_IS_TRUE_IMPORT),
),
cond_var.bool(),
c1,
c2,
)
@overload
def color_mode_cond(light: Component, dark: Component | None = None) -> Component: ... # pyright: ignore [reportOverlappingOverload]
def color_mode_cond(light: Component, dark: Component | None = None) -> Component: ... # type: ignore
@overload
@ -185,3 +81,9 @@ def color_mode_cond(light: Any, dark: Any = None) -> Var | Component:
light,
dark,
)
class Cond:
"""Create a conditional component or Prop."""
create = staticmethod(cond)

View File

@ -28,7 +28,7 @@ class DebounceInput(Component):
min_length: Var[int]
# Time to wait between end of input and triggering on_change
debounce_timeout: Var[int] = Var.create(DEFAULT_DEBOUNCE_TIMEOUT)
debounce_timeout: Var[int] = DEFAULT_DEBOUNCE_TIMEOUT # type: ignore
# If true, notify when Enter key is pressed
force_notify_by_enter: Var[bool]

View File

@ -6,7 +6,7 @@
from typing import Any, Dict, Optional, Type, Union, overload
from reflex.components.component import Component
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -31,22 +31,22 @@ class DebounceInput(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_change: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_change: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "DebounceInput":
"""Create a DebounceInput component.

View File

@ -2,17 +2,11 @@
from __future__ import annotations
import functools
import inspect
from typing import Any, Callable, Iterable
from typing import Callable, Iterable
from reflex.components.base.fragment import Fragment
from reflex.components.component import Component
from reflex.components.tags import IterTag
from reflex.constants import MemoizationMode
from reflex.state import ComponentState
from reflex.utils.exceptions import UntypedVarError
from reflex.vars.base import LiteralVar, Var
from reflex.vars.object import ObjectVar
from reflex.vars.sequence import ArrayVar
class ForeachVarError(TypeError):
@ -23,149 +17,37 @@ class ForeachRenderError(TypeError):
"""Raised when there is an error with the foreach render function."""
class Foreach(Component):
"""A component that takes in an iterable and a render function and renders a list of components."""
def foreach(
iterable: Var[Iterable] | Iterable,
render_fn: Callable,
) -> Var:
"""Create a foreach component.
_memoization_mode = MemoizationMode(recursive=False)
Args:
iterable: The iterable to create components from.
render_fn: A function from the render args to the component.
# The iterable to create components from.
iterable: Var[Iterable]
Returns:
The foreach component.
# A function from the render args to the component.
render_fn: Callable = Fragment.create
Raises:
ForeachVarError: If the iterable is of type Any.
"""
iterable = LiteralVar.create(iterable).guess_type()
if isinstance(iterable, ObjectVar):
iterable = iterable.items()
@classmethod
def create(
cls,
iterable: Var[Iterable] | Iterable,
render_fn: Callable,
) -> Foreach:
"""Create a foreach component.
Args:
iterable: The iterable to create components from.
render_fn: A function from the render args to the component.
Returns:
The foreach component.
Raises:
ForeachVarError: If the iterable is of type Any.
TypeError: If the render function is a ComponentState.
UntypedVarError: If the iterable is of type Any without a type annotation.
"""
from reflex.vars import ArrayVar, ObjectVar, StringVar
iterable = LiteralVar.create(iterable).guess_type()
if iterable._var_type == Any:
raise ForeachVarError(
f"Could not foreach over var `{iterable!s}` of type Any. "
"(If you are trying to foreach over a state var, add a type annotation to the var). "
"See https://reflex.dev/docs/library/dynamic-rendering/foreach/"
)
if (
hasattr(render_fn, "__qualname__")
and render_fn.__qualname__ == ComponentState.create.__qualname__
):
raise TypeError(
"Using a ComponentState as `render_fn` inside `rx.foreach` is not supported yet."
)
if isinstance(iterable, ObjectVar):
iterable = iterable.entries()
if isinstance(iterable, StringVar):
iterable = iterable.split()
if not isinstance(iterable, ArrayVar):
raise ForeachVarError(
f"Could not foreach over var `{iterable!s}` of type {iterable._var_type}. "
"See https://reflex.dev/docs/library/dynamic-rendering/foreach/"
)
component = cls(
iterable=iterable,
render_fn=render_fn,
)
try:
# Keep a ref to a rendered component to determine correct imports/hooks/styles.
component.children = [component._render().render_component()]
except UntypedVarError as e:
raise UntypedVarError(
f"Could not foreach over var `{iterable!s}` without a type annotation. "
"See https://reflex.dev/docs/library/dynamic-rendering/foreach/"
) from e
return component
def _render(self) -> IterTag:
props = {}
render_sig = inspect.signature(self.render_fn)
params = list(render_sig.parameters.values())
# Validate the render function signature.
if len(params) == 0 or len(params) > 2:
raise ForeachRenderError(
"Expected 1 or 2 parameters in foreach render function, got "
f"{[p.name for p in params]}. See "
"https://reflex.dev/docs/library/dynamic-rendering/foreach/"
)
if len(params) >= 1:
# Determine the arg var name based on the params accepted by render_fn.
props["arg_var_name"] = params[0].name
if len(params) == 2:
# Determine the index var name based on the params accepted by render_fn.
props["index_var_name"] = params[1].name
else:
render_fn = self.render_fn
# Otherwise, use a deterministic index, based on the render function bytecode.
code_hash = (
hash(
getattr(
render_fn,
"__code__",
(
repr(self.render_fn)
if not isinstance(render_fn, functools.partial)
else render_fn.func.__code__
),
)
)
.to_bytes(
length=8,
byteorder="big",
signed=True,
)
.hex()
)
props["index_var_name"] = f"index_{code_hash}"
return IterTag(
iterable=self.iterable,
render_fn=self.render_fn,
children=self.children,
**props,
if not isinstance(iterable, ArrayVar):
raise ForeachVarError(
f"Could not foreach over var `{iterable!s}` of type {iterable._var_type!s}. "
"(If you are trying to foreach over a state var, add a type annotation to the var). "
"See https://reflex.dev/docs/library/dynamic-rendering/foreach/"
)
def render(self):
"""Render the component.
Returns:
The dictionary for template of component.
"""
tag = self._render()
return dict(
tag,
iterable_state=str(tag.iterable),
arg_name=tag.arg_var_name,
arg_index=tag.get_index_var_arg(),
iterable_type=tag.iterable._var_type.mro()[0].__name__,
)
return iterable.foreach(render_fn)
foreach = Foreach.create
class Foreach:
"""Create a list of components from an iterable."""
create = staticmethod(foreach)

View File

@ -3,10 +3,10 @@
# ------------------- DO NOT EDIT ----------------------
# This file was generated by `reflex/utils/pyi_generator.py`!
# ------------------------------------------------------
from typing import Any, Dict, Literal, Optional, Union, overload
from typing import Any, Dict, Optional, Union, overload
from reflex.components.el.elements.typography import Div
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -19,232 +19,51 @@ class Html(Div):
dangerouslySetInnerHTML: Optional[
Union[Dict[str, str], Var[Dict[str, str]]]
] = None,
access_key: Optional[Union[Var[str], str]] = None,
access_key: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
auto_capitalize: Optional[
Union[
Literal["characters", "none", "off", "on", "sentences", "words"],
Var[Literal["characters", "none", "off", "on", "sentences", "words"]],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
content_editable: Optional[
Union[
Literal["inherit", "plaintext-only", False, True],
Var[Literal["inherit", "plaintext-only", False, True]],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
context_menu: Optional[Union[Var[str], str]] = None,
dir: Optional[Union[Var[str], str]] = None,
draggable: Optional[Union[Var[bool], bool]] = None,
context_menu: Optional[
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
dir: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
draggable: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
enter_key_hint: Optional[
Union[
Literal["done", "enter", "go", "next", "previous", "search", "send"],
Var[
Literal["done", "enter", "go", "next", "previous", "search", "send"]
],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
hidden: Optional[Union[Var[bool], bool]] = None,
input_mode: Optional[
Union[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
],
Var[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
]
],
]
] = None,
item_prop: Optional[Union[Var[str], str]] = None,
lang: Optional[Union[Var[str], str]] = None,
role: Optional[
Union[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
],
Var[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
]
],
]
] = None,
slot: Optional[Union[Var[str], str]] = None,
spell_check: Optional[Union[Var[bool], bool]] = None,
tab_index: Optional[Union[Var[int], int]] = None,
title: Optional[Union[Var[str], str]] = None,
hidden: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
input_mode: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
item_prop: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
lang: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
role: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
slot: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
spell_check: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
tab_index: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
title: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = 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, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Html":
"""Create a html component.

View File

@ -1,274 +1,163 @@
"""rx.match."""
import textwrap
from typing import Any, Dict, List, Optional, Tuple, Union
from typing import Any, Union, cast
from typing_extensions import Unpack
from reflex.components.base import Fragment
from reflex.components.component import BaseComponent, Component, MemoizationLeaf
from reflex.components.tags import MatchTag, Tag
from reflex.style import Style
from reflex.utils import format, types
from reflex.components.component import BaseComponent, Component
from reflex.utils import types
from reflex.utils.exceptions import MatchTypeError
from reflex.utils.imports import ImportDict
from reflex.vars import VarData
from reflex.vars.base import LiteralVar, Var
from reflex.vars.base import VAR_TYPE, Var
from reflex.vars.number import MatchOperation
CASE_TYPE = tuple[Unpack[tuple[Any, ...]], Var[VAR_TYPE] | VAR_TYPE]
class Match(MemoizationLeaf):
"""Match cases based on a condition."""
def _process_match_cases(cases: tuple[CASE_TYPE[VAR_TYPE], ...]):
"""Process the individual match cases.
# The condition to determine which case to match.
cond: Var[Any]
Args:
cases: The match cases.
# The list of match cases to be matched.
match_cases: List[Any] = []
# The catchall case to match.
default: Any
@classmethod
def create(cls, cond: Any, *cases) -> Union[Component, Var]:
"""Create a Match Component.
Args:
cond: The condition to determine which case to match.
cases: This list of cases to match.
Returns:
The match component.
Raises:
ValueError: When a default case is not provided for cases with Var return types.
"""
match_cond_var = cls._create_condition_var(cond)
cases, default = cls._process_cases(list(cases))
match_cases = cls._process_match_cases(cases)
cls._validate_return_types(match_cases)
if default is None and types._issubclass(type(match_cases[0][-1]), Var):
Raises:
ValueError: If the default case is not the last case or the tuple elements are less than 2.
"""
for case in cases:
if not isinstance(case, tuple):
raise ValueError(
"For cases with return types as Vars, a default case must be provided"
"rx.match should have tuples of cases and a default case as the last argument."
)
return cls._create_match_cond_var_or_component(
match_cond_var, match_cases, default
)
@classmethod
def _create_condition_var(cls, cond: Any) -> Var:
"""Convert the condition to a Var.
Args:
cond: The condition.
Returns:
The condition as a base var
Raises:
ValueError: If the condition is not provided.
"""
match_cond_var = LiteralVar.create(cond)
if match_cond_var is None:
raise ValueError("The condition must be set")
return match_cond_var
@classmethod
def _process_cases(
cls, cases: List
) -> Tuple[List, Optional[Union[Var, BaseComponent]]]:
"""Process the list of match cases and the catchall default case.
Args:
cases: The list of match cases.
Returns:
The default case and the list of match case tuples.
Raises:
ValueError: If there are multiple default cases.
"""
default = None
if len([case for case in cases if not isinstance(case, tuple)]) > 1:
raise ValueError("rx.match can only have one default case.")
if not cases:
raise ValueError("rx.match should have at least one case.")
# Get the default case which should be the last non-tuple arg
if not isinstance(cases[-1], tuple):
default = cases.pop()
default = (
cls._create_case_var_with_var_data(default)
if not isinstance(default, BaseComponent)
else default
# There should be at least two elements in a case tuple(a condition and return value)
if len(case) < 2:
raise ValueError(
"A case tuple should have at least a match case element and a return value."
)
return cases, default
@classmethod
def _create_case_var_with_var_data(cls, case_element: Any) -> Var:
"""Convert a case element into a Var.If the case
is a Style type, we extract the var data and merge it with the
newly created Var.
def _validate_return_types(match_cases: tuple[CASE_TYPE[VAR_TYPE], ...]) -> None:
"""Validate that match cases have the same return types.
Args:
case_element: The case element.
Args:
match_cases: The match cases.
Returns:
The case element Var.
"""
_var_data = case_element._var_data if isinstance(case_element, Style) else None
case_element = LiteralVar.create(case_element, _var_data=_var_data)
return case_element
Raises:
MatchTypeError: If the return types of cases are different.
"""
@classmethod
def _process_match_cases(cls, cases: List) -> List[List[Var]]:
"""Process the individual match cases.
Args:
cases: The match cases.
Returns:
The processed match cases.
Raises:
ValueError: If the default case is not the last case or the tuple elements are less than 2.
"""
match_cases = []
for case in cases:
if not isinstance(case, tuple):
raise ValueError(
"rx.match should have tuples of cases and a default case as the last argument."
)
# There should be at least two elements in a case tuple(a condition and return value)
if len(case) < 2:
raise ValueError(
"A case tuple should have at least a match case element and a return value."
)
case_list = []
for element in case:
# convert all non component element to vars.
el = (
cls._create_case_var_with_var_data(element)
if not isinstance(element, BaseComponent)
else element
)
if not isinstance(el, (Var, BaseComponent)):
raise ValueError("Case element must be a var or component")
case_list.append(el)
match_cases.append(case_list)
return match_cases
@classmethod
def _validate_return_types(cls, match_cases: List[List[Var]]) -> None:
"""Validate that match cases have the same return types.
Args:
match_cases: The match cases.
Raises:
MatchTypeError: If the return types of cases are different.
"""
first_case_return = match_cases[0][-1]
return_type = type(first_case_return)
if isinstance(first_case_return, BaseComponent):
return_type = BaseComponent
elif isinstance(first_case_return, Var):
return_type = Var
for index, case in enumerate(match_cases):
if not types._issubclass(type(case[-1]), return_type):
raise MatchTypeError(
f"Match cases should have the same return types. Case {index} with return "
f"value `{case[-1]._js_expr if isinstance(case[-1], Var) else textwrap.shorten(str(case[-1]), width=250)}`"
f" of type {type(case[-1])!r} is not {return_type}"
)
@classmethod
def _create_match_cond_var_or_component(
cls,
match_cond_var: Var,
match_cases: List[List[Var]],
default: Optional[Union[Var, BaseComponent]],
) -> Union[Component, Var]:
"""Create and return the match condition var or component.
Args:
match_cond_var: The match condition.
match_cases: The list of match cases.
default: The default case.
Returns:
The match component wrapped in a fragment or the match var.
Raises:
ValueError: If the return types are not vars when creating a match var for Var types.
"""
if default is None and types._issubclass(
type(match_cases[0][-1]), BaseComponent
):
default = Fragment.create()
if types._issubclass(type(match_cases[0][-1]), BaseComponent):
return Fragment.create(
cls(
cond=match_cond_var,
match_cases=match_cases,
default=default,
children=[case[-1] for case in match_cases] + [default], # pyright: ignore [reportArgumentType]
)
def is_component_or_component_var(obj: Any) -> bool:
return types._isinstance(obj, BaseComponent) or (
isinstance(obj, Var)
and types.safe_typehint_issubclass(
obj._var_type, Union[list[BaseComponent], BaseComponent]
)
# Validate the match cases (as well as the default case) to have Var return types.
if any(
case for case in match_cases if not isinstance(case[-1], Var)
) or not isinstance(default, Var):
raise ValueError("Return types of match cases should be Vars.")
return Var(
_js_expr=format.format_match(
cond=str(match_cond_var),
match_cases=match_cases,
default=default, # pyright: ignore [reportArgumentType]
),
_var_type=default._var_type, # pyright: ignore [reportAttributeAccessIssue,reportOptionalMemberAccess]
_var_data=VarData.merge(
match_cond_var._get_all_var_data(),
*[el._get_all_var_data() for case in match_cases for el in case],
default._get_all_var_data(), # pyright: ignore [reportAttributeAccessIssue, reportOptionalMemberAccess]
),
)
def _render(self) -> Tag:
return MatchTag(
cond=self.cond, match_cases=self.match_cases, default=self.default
def type_of_return_type(obj: Any) -> Any:
if isinstance(obj, Var):
return obj._var_type
return type(obj)
return_types = [case[-1] for case in match_cases]
if any(
is_component_or_component_var(return_type) for return_type in return_types
) and not all(
is_component_or_component_var(return_type) for return_type in return_types
):
non_component_return_types = [
(type_of_return_type(return_type), i)
for i, return_type in enumerate(return_types)
if not is_component_or_component_var(return_type)
]
raise MatchTypeError(
"Match cases should have the same return types. "
+ "Expected return types to be of type Component or Var[Component]. "
+ ". ".join(
[
f"Return type of case {i} is {return_type}"
for return_type, i in non_component_return_types
]
)
)
def render(self) -> Dict:
"""Render the component.
Returns:
The dictionary for template of component.
"""
tag = self._render()
tag.name = "match"
return dict(tag)
def _create_match_var(
match_cond_var: Var,
match_cases: tuple[CASE_TYPE[VAR_TYPE], ...],
default: VAR_TYPE | Var[VAR_TYPE],
) -> Var[VAR_TYPE]:
"""Create the match var.
def add_imports(self) -> ImportDict:
"""Add imports for the Match component.
Args:
match_cond_var: The match condition var.
match_cases: The match cases.
default: The default case.
Returns:
The import dict.
"""
var_data = VarData.merge(self.cond._get_all_var_data())
return var_data.old_school_imports() if var_data else {}
Returns:
The match var.
"""
return MatchOperation.create(match_cond_var, match_cases, default)
match = Match.create
def match(
cond: Any,
*cases: Unpack[
tuple[Unpack[tuple[CASE_TYPE[VAR_TYPE], ...]], Var[VAR_TYPE] | VAR_TYPE]
],
) -> Var[VAR_TYPE]:
"""Create a match var.
Args:
cond: The condition to match.
cases: The match cases. Each case should be a tuple with the first elements as the match case and the last element as the return value. The last argument should be the default case.
Returns:
The match var.
Raises:
ValueError: If the default case is not the last case or the tuple elements are less than 2.
"""
default = None
if len([case for case in cases if not isinstance(case, tuple)]) > 1:
raise ValueError("rx.match can only have one default case.")
if not cases:
raise ValueError("rx.match should have at least one case.")
# Get the default case which should be the last non-tuple arg
if not isinstance(cases[-1], tuple):
default = cases[-1]
actual_cases = cases[:-1]
else:
actual_cases = cast(tuple[CASE_TYPE[VAR_TYPE], ...], cases)
_process_match_cases(actual_cases)
_validate_return_types(actual_cases)
if default is None and any(
not (
isinstance((return_type := case[-1]), Component)
or (
isinstance(return_type, Var)
and types.typehint_issubclass(return_type._var_type, Component)
)
)
for case in actual_cases
):
raise ValueError(
"For cases with return types as Vars, a default case must be provided"
)
elif default is None:
default = Fragment.create()
default = cast(Var[VAR_TYPE] | VAR_TYPE, default)
return _create_match_var(
cond,
actual_cases,
default,
)

View File

@ -1,134 +0,0 @@
"""Components for displaying the Reflex sticky logo."""
from reflex.components.component import ComponentNamespace
from reflex.components.core.colors import color
from reflex.components.core.cond import color_mode_cond
from reflex.components.core.responsive import desktop_only
from reflex.components.el.elements.inline import A
from reflex.components.el.elements.media import Path, Rect, Svg
from reflex.components.radix.themes.typography.text import Text
from reflex.style import Style
class StickyLogo(Svg):
"""A simple Reflex logo SVG with only the letter R."""
@classmethod
def create(cls):
"""Create the simple Reflex logo SVG.
Returns:
The simple Reflex logo SVG.
"""
return super().create(
Rect.create(width="16", height="16", rx="2", fill="#6E56CF"),
Path.create(d="M10 9V13H12V9H10Z", fill="white"),
Path.create(d="M4 3V13H6V9H10V7H6V5H10V7H12V3H4Z", fill="white"),
width="16",
height="16",
viewBox="0 0 16 16",
xmlns="http://www.w3.org/2000/svg",
)
def add_style(self):
"""Add the style to the component.
Returns:
The style of the component.
"""
return Style(
{
"fill": "white",
}
)
class StickyLabel(Text):
"""A label that displays the Reflex sticky."""
@classmethod
def create(cls):
"""Create the sticky label.
Returns:
The sticky label.
"""
return super().create("Built with Reflex")
def add_style(self):
"""Add the style to the component.
Returns:
The style of the component.
"""
return Style(
{
"color": color("slate", 1),
"font_weight": "600",
"font_family": "'Instrument Sans', sans-serif",
"font_size": "0.875rem",
"line_height": "1rem",
"letter_spacing": "-0.00656rem",
}
)
class StickyBadge(A):
"""A badge that displays the Reflex sticky logo."""
@classmethod
def create(cls):
"""Create the sticky badge.
Returns:
The sticky badge.
"""
return super().create(
StickyLogo.create(),
desktop_only(StickyLabel.create()),
href="https://reflex.dev",
target="_blank",
width="auto",
padding="0.375rem",
align="center",
text_align="center",
)
def add_style(self):
"""Add the style to the component.
Returns:
The style of the component.
"""
return Style(
{
"position": "fixed",
"bottom": "1rem",
"right": "1rem",
"display": "flex",
"flex-direction": "row",
"gap": "0.375rem",
"align-items": "center",
"width": "auto",
"border-radius": "0.5rem",
"color": color_mode_cond("#E5E7EB", "#27282B"),
"border": color_mode_cond("1px solid #27282B", "1px solid #E5E7EB"),
"background-color": color_mode_cond("#151618", "#FCFCFD"),
"padding": "0.375rem",
"transition": "background-color 0.2s ease-in-out",
"box-shadow": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
"z-index": "9998",
"cursor": "pointer",
},
)
class StickyNamespace(ComponentNamespace):
"""Sticky components namespace."""
__call__ = staticmethod(StickyBadge.create)
label = staticmethod(StickyLabel.create)
logo = staticmethod(StickyLogo.create)
sticky = StickyNamespace()

File diff suppressed because it is too large Load Diff

View File

@ -147,7 +147,7 @@ uploaded_files_url_prefix = Var(
).to(str)
def get_upload_url(file_path: str | Var[str]) -> Var[str]:
def get_upload_url(file_path: str) -> Var[str]:
"""Get the URL of an uploaded file.
Args:
@ -158,7 +158,7 @@ def get_upload_url(file_path: str | Var[str]) -> Var[str]:
"""
Upload.is_used = True
return Var.create(f"{uploaded_files_url_prefix}/{file_path}")
return uploaded_files_url_prefix + "/" + file_path
def _on_drop_spec(files: Var) -> Tuple[Var[Any]]:
@ -267,7 +267,7 @@ class Upload(MemoizationLeaf):
on_drop = upload_props["on_drop"]
if isinstance(on_drop, Callable):
# Call the lambda to get the event chain.
on_drop = call_event_fn(on_drop, _on_drop_spec)
on_drop = call_event_fn(on_drop, _on_drop_spec) # type: ignore
if isinstance(on_drop, EventSpec):
# Update the provided args for direct use with on_drop.
on_drop = on_drop.with_args(

View File

@ -9,7 +9,7 @@ from typing import Any, ClassVar, Dict, List, Optional, Union, overload
from reflex.components.base.fragment import Fragment
from reflex.components.component import Component, ComponentNamespace, MemoizationLeaf
from reflex.constants import Dirs
from reflex.event import CallableEventSpec, EventSpec, EventType
from reflex.event import BASE_STATE, CallableEventSpec, EventSpec, EventType
from reflex.style import Style
from reflex.utils.imports import ImportVar
from reflex.vars import VarData
@ -35,7 +35,7 @@ uploaded_files_url_prefix = Var(
),
).to(str)
def get_upload_url(file_path: str | Var[str]) -> Var[str]: ...
def get_upload_url(file_path: str) -> Var[str]: ...
class UploadFilesProvider(Component):
@overload
@ -49,21 +49,21 @@ class UploadFilesProvider(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "UploadFilesProvider":
"""Create the component.
@ -95,22 +95,24 @@ class GhostUpload(Fragment):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_drop: Optional[Union[EventType[()], EventType[Any]]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_drop: Optional[
Union[EventType[[], BASE_STATE], EventType[[Any], BASE_STATE]]
] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "GhostUpload":
"""Create the component.
@ -154,22 +156,24 @@ class Upload(MemoizationLeaf):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_drop: Optional[Union[EventType[()], EventType[Any]]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_drop: Optional[
Union[EventType[[], BASE_STATE], EventType[[Any], BASE_STATE]]
] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Upload":
"""Create an upload component.
@ -220,22 +224,24 @@ class StyledUpload(Upload):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_drop: Optional[Union[EventType[()], EventType[Any]]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_drop: Optional[
Union[EventType[[], BASE_STATE], EventType[[Any], BASE_STATE]]
] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "StyledUpload":
"""Create the styled upload component.
@ -286,22 +292,24 @@ class UploadNamespace(ComponentNamespace):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_drop: Optional[Union[EventType[()], EventType[Any]]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_drop: Optional[
Union[EventType[[], BASE_STATE], EventType[[Any], BASE_STATE]]
] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "StyledUpload":
"""Create the styled upload component.

View File

@ -3,7 +3,6 @@
from __future__ import annotations
import dataclasses
import typing
from typing import ClassVar, Dict, Literal, Optional, Union
from reflex.components.component import Component, ComponentNamespace
@ -450,7 +449,7 @@ class CodeBlock(Component, MarkdownComponentMap):
if can_copy:
code = children[0]
copy_button = (
copy_button = ( # type: ignore
copy_button
if copy_button is not None
else Button.create(
@ -504,7 +503,7 @@ class CodeBlock(Component, MarkdownComponentMap):
return ["can_copy", "copy_button"]
@classmethod
def _get_language_registration_hook(cls, language_var: Var = _LANGUAGE) -> Var:
def _get_language_registration_hook(cls, language_var: Var = _LANGUAGE) -> str:
"""Get the hook to register the language.
Args:
@ -515,46 +514,21 @@ class CodeBlock(Component, MarkdownComponentMap):
Returns:
The hook to register the language.
"""
language_in_there = Var.create(typing.get_args(LiteralCodeLanguage)).contains(
language_var
)
async_load = f"""
(async () => {{
try {{
return f"""
if ({language_var!s}) {{
(async () => {{
try {{
const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${{{language_var!s}}}`);
SyntaxHighlighter.registerLanguage({language_var!s}, module.default);
}} catch (error) {{
console.error(`Language ${{{language_var!s}}} is not supported for code blocks inside of markdown: `, error);
}}
}})();
"""
return Var(
f"""
if ({language_var!s}) {{
if (!{language_in_there!s}) {{
console.warn(`Language \\`${{{language_var!s}}}\\` is not supported for code blocks inside of markdown.`);
{language_var!s} = '';
}} else {{
{async_load!s}
}}
}} catch (error) {{
console.error(`Error importing language module for ${{{language_var!s}}}:`, error);
}}
}})();
}}
"""
if not isinstance(language_var, LiteralVar)
else f"""
if ({language_var!s}) {{
{async_load!s}
}}""",
_var_data=VarData(
imports={
cls.__fields__["library"].default: [
ImportVar(tag="PrismAsyncLight", alias="SyntaxHighlighter")
]
},
),
)
@classmethod
def get_component_map_custom_code(cls) -> Var:
def get_component_map_custom_code(cls) -> str:
"""Get the custom code for the component.
Returns:

View File

@ -9,7 +9,7 @@ from typing import Any, ClassVar, Dict, Literal, Optional, Union, overload
from reflex.components.component import Component, ComponentNamespace
from reflex.components.markdown.markdown import MarkdownComponentMap
from reflex.constants.colors import Color
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -938,21 +938,21 @@ class CodeBlock(Component, MarkdownComponentMap):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "CodeBlock":
"""Create a text component.
@ -984,7 +984,7 @@ class CodeBlock(Component, MarkdownComponentMap):
def add_style(self): ...
@classmethod
def get_component_map_custom_code(cls) -> Var: ...
def get_component_map_custom_code(cls) -> str: ...
def add_hooks(self) -> list[str | Var]: ...
class CodeblockNamespace(ComponentNamespace):
@ -1576,21 +1576,21 @@ class CodeblockNamespace(ComponentNamespace):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "CodeBlock":
"""Create a text component.

View File

@ -3,7 +3,9 @@
from __future__ import annotations
from enum import Enum
from typing import Any, Dict, List, Literal, Optional, Tuple, TypedDict, Union
from typing import Any, Dict, List, Literal, Optional, Tuple, Union
from typing_extensions import TypedDict
from reflex.base import Base
from reflex.components.component import Component, NoSSRComponent
@ -163,7 +165,7 @@ class DataEditor(NoSSRComponent):
tag = "DataEditor"
is_default = True
library: str | None = "@glideapps/glide-data-grid@^6.0.3"
library: str = "@glideapps/glide-data-grid@^6.0.3"
lib_dependencies: List[str] = [
"lodash@^4.17.21",
"react-responsive-carousel@^3.2.7",
@ -301,7 +303,7 @@ class DataEditor(NoSSRComponent):
# Fired when editing is finished.
on_finished_editing: EventHandler[
passthrough_event_spec(Union[GridCell, None], tuple[int, int])
passthrough_event_spec(Union[GridCell, None], tuple[int, int]) # pyright: ignore[reportArgumentType]
]
# Fired when a row is appended.
@ -319,8 +321,6 @@ class DataEditor(NoSSRComponent):
Returns:
The import dict.
"""
if self.library is None:
return {}
return {
"": f"{format.format_library_name(self.library)}/dist/index.css",
self.library: "GridCellKind",
@ -343,9 +343,9 @@ class DataEditor(NoSSRComponent):
data_callback = self.get_cell_content._js_expr
else:
data_callback = f"getData_{editor_id}"
self.get_cell_content = Var(_js_expr=data_callback)
self.get_cell_content = Var(_js_expr=data_callback) # type: ignore
code = [f"function {data_callback}([col, row]){{"]
code = [f"function {data_callback}([col, row])" "{"]
columns_path = str(self.columns)
data_path = str(self.data)
@ -385,8 +385,7 @@ class DataEditor(NoSSRComponent):
raise ValueError(
"DataEditor data must be an ArrayVar if rows is not provided."
)
props["rows"] = data.length() if isinstance(data, ArrayVar) else len(data)
props["rows"] = data.length() if isinstance(data, Var) else len(data)
if not isinstance(columns, Var) and len(columns):
if types.is_dataframe(type(data)) or (

View File

@ -4,11 +4,13 @@
# This file was generated by `reflex/utils/pyi_generator.py`!
# ------------------------------------------------------
from enum import Enum
from typing import Any, Dict, List, Literal, Optional, TypedDict, Union, overload
from typing import Any, Dict, List, Literal, Optional, Union, overload
from typing_extensions import TypedDict
from reflex.base import Base
from reflex.components.component import NoSSRComponent
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.utils.imports import ImportDict
from reflex.utils.serializers import serializer
@ -181,79 +183,93 @@ class DataEditor(NoSSRComponent):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_cell_activated: Optional[
Union[EventType[()], EventType[tuple[int, int]]]
Union[EventType[[], BASE_STATE], EventType[[tuple[int, int]], BASE_STATE]]
] = None,
on_cell_clicked: Optional[
Union[EventType[()], EventType[tuple[int, int]]]
Union[EventType[[], BASE_STATE], EventType[[tuple[int, int]], BASE_STATE]]
] = None,
on_cell_context_menu: Optional[
Union[EventType[()], EventType[tuple[int, int]]]
Union[EventType[[], BASE_STATE], EventType[[tuple[int, int]], BASE_STATE]]
] = None,
on_cell_edited: Optional[
Union[
EventType[()],
EventType[tuple[int, int]],
EventType[tuple[int, int], GridCell],
EventType[[], BASE_STATE],
EventType[[tuple[int, int]], BASE_STATE],
EventType[[tuple[int, int], GridCell], BASE_STATE],
]
] = None,
on_click: Optional[EventType[()]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_column_resize: Optional[
Union[EventType[()], EventType[GridColumn], EventType[GridColumn, int]]
Union[
EventType[[], BASE_STATE],
EventType[[GridColumn], BASE_STATE],
EventType[[GridColumn, int], BASE_STATE],
]
] = None,
on_context_menu: Optional[EventType[()]] = None,
on_delete: Optional[Union[EventType[()], EventType[GridSelection]]] = None,
on_double_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_delete: Optional[
Union[EventType[[], BASE_STATE], EventType[[GridSelection], BASE_STATE]]
] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_finished_editing: Optional[
Union[
EventType[()],
EventType[Union[GridCell, None]],
EventType[Union[GridCell, None], tuple[int, int]],
EventType[[], BASE_STATE],
EventType[[Union[GridCell, None]], BASE_STATE],
EventType[[Union[GridCell, None], tuple[int, int]], BASE_STATE],
]
] = None,
on_focus: Optional[EventType[()]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_group_header_clicked: Optional[
Union[
EventType[()],
EventType[tuple[int, int]],
EventType[tuple[int, int], GridCell],
EventType[[], BASE_STATE],
EventType[[tuple[int, int]], BASE_STATE],
EventType[[tuple[int, int], GridCell], BASE_STATE],
]
] = None,
on_group_header_context_menu: Optional[
Union[
EventType[()],
EventType[int],
EventType[int, GroupHeaderClickedEventArgs],
EventType[[], BASE_STATE],
EventType[[int], BASE_STATE],
EventType[[int, GroupHeaderClickedEventArgs], BASE_STATE],
]
] = None,
on_group_header_renamed: Optional[
Union[EventType[()], EventType[str], EventType[str, str]]
Union[
EventType[[], BASE_STATE],
EventType[[str], BASE_STATE],
EventType[[str, str], BASE_STATE],
]
] = None,
on_header_clicked: Optional[
Union[EventType[()], EventType[tuple[int, int]]]
Union[EventType[[], BASE_STATE], EventType[[tuple[int, int]], BASE_STATE]]
] = None,
on_header_context_menu: Optional[
Union[EventType[()], EventType[tuple[int, int]]]
Union[EventType[[], BASE_STATE], EventType[[tuple[int, int]], BASE_STATE]]
] = None,
on_header_menu_click: Optional[
Union[EventType[()], EventType[int], EventType[int, Rectangle]]
Union[
EventType[[], BASE_STATE],
EventType[[int], BASE_STATE],
EventType[[int, Rectangle], BASE_STATE],
]
] = None,
on_item_hovered: Optional[
Union[EventType[()], EventType[tuple[int, int]]]
Union[EventType[[], BASE_STATE], EventType[[tuple[int, int]], BASE_STATE]]
] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_row_appended: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_selection_cleared: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_row_appended: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_selection_cleared: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "DataEditor":
"""Create the DataEditor component.

View File

@ -5,22 +5,20 @@ from typing import Union
import reflex as rx
def svg_logo(
color: Union[str, rx.Var[str]] = rx.color_mode_cond("#110F1F", "white"),
**props,
):
def svg_logo(color: Union[str, rx.Var[str]] = rx.color_mode_cond("#110F1F", "white")):
"""A Reflex logo SVG.
Args:
color: The color of the logo.
props: Extra props to pass to the svg component.
Returns:
The Reflex logo SVG.
"""
def logo_path(d: str):
return rx.el.svg.path(d=d)
def logo_path(d):
return rx.el.svg.path(
d=d,
)
paths = [
"M0 11.5999V0.399902H8.96V4.8799H6.72V2.6399H2.24V4.8799H6.72V7.1199H2.24V11.5999H0ZM6.72 11.5999V7.1199H8.96V11.5999H6.72Z",
@ -33,14 +31,11 @@ def svg_logo(
return rx.el.svg(
*[logo_path(d) for d in paths],
rx.el.title("Reflex"),
aria_label="Reflex",
role="img",
width=props.pop("width", "56"),
height=props.pop("height", "12"),
width="56",
height="12",
viewBox="0 0 56 12",
fill=color,
xmlns="http://www.w3.org/2000/svg",
**props,
)

View File

@ -602,7 +602,7 @@ class ShikiCodeBlock(Component, MarkdownComponentMap):
transformer_styles = {}
# Collect styles from transformers and wrapper
for transformer in code_block.transformers._var_value: # pyright: ignore [reportAttributeAccessIssue]
for transformer in code_block.transformers._var_value: # type: ignore
if isinstance(transformer, ShikiBaseTransformers) and transformer.style:
transformer_styles.update(transformer.style)
transformer_styles.update(code_wrapper_props.pop("style", {}))
@ -621,22 +621,18 @@ class ShikiCodeBlock(Component, MarkdownComponentMap):
Returns:
Imports for the component.
Raises:
ValueError: If the transformers are not of type LiteralVar.
"""
imports = defaultdict(list)
if not isinstance(self.transformers, LiteralVar):
raise ValueError(
f"transformers should be a LiteralVar type. Got {type(self.transformers)} instead."
)
for transformer in self.transformers._var_value:
if isinstance(transformer, ShikiBaseTransformers):
imports[transformer.library].extend(
[ImportVar(tag=str(fn)) for fn in transformer.fns]
)
if transformer.library not in self.lib_dependencies:
(
self.lib_dependencies.append(transformer.library)
if transformer.library not in self.lib_dependencies
else None
)
return imports
@classmethod
@ -657,9 +653,8 @@ class ShikiCodeBlock(Component, MarkdownComponentMap):
raise ValueError(
f"the function names should be str names of functions in the specified transformer: {library!r}"
)
return ShikiBaseTransformers(
library=library,
fns=[FunctionStringVar.create(fn) for fn in fns], # pyright: ignore [reportCallIssue]
return ShikiBaseTransformers( # type: ignore
library=library, fns=[FunctionStringVar.create(fn) for fn in fns]
)
def _render(self, props: dict[str, Any] | None = None):
@ -762,13 +757,13 @@ class ShikiHighLevelCodeBlock(ShikiCodeBlock):
if can_copy:
code = children[0]
copy_button = (
copy_button = ( # type: ignore
copy_button
if copy_button is not None
else Button.create(
Icon.create(tag="copy", size=16, color=color("gray", 11)),
on_click=[
set_clipboard(cls._strip_transformer_triggers(code)),
set_clipboard(cls._strip_transformer_triggers(code)), # type: ignore
copy_script(),
],
style=Style(
@ -828,7 +823,7 @@ class ShikiHighLevelCodeBlock(ShikiCodeBlock):
if isinstance(code, Var):
return string_replace_operation(
code, StringVar(_js_expr=f"/{regex_pattern}/g", _var_type=str), ""
)
).guess_type()
if isinstance(code, str):
return re.sub(regex_pattern, "", code)

View File

@ -9,7 +9,7 @@ from reflex.base import Base
from reflex.components.component import Component, ComponentNamespace
from reflex.components.markdown.markdown import MarkdownComponentMap
from reflex.components.props import NoExtrasAllowedProps
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
from reflex.vars.function import FunctionStringVar
@ -928,21 +928,21 @@ class ShikiCodeBlock(Component, MarkdownComponentMap):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "ShikiCodeBlock":
"""Create a code block component using [shiki syntax highlighter](https://shiki.matsu.io/).
@ -1555,21 +1555,21 @@ class ShikiHighLevelCodeBlock(ShikiCodeBlock):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "ShikiHighLevelCodeBlock":
"""Create a code block component using [shiki syntax highlighter](https://shiki.matsu.io/).
@ -2185,21 +2185,21 @@ class CodeblockNamespace(ComponentNamespace):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "ShikiHighLevelCodeBlock":
"""Create a code block component using [shiki syntax highlighter](https://shiki.matsu.io/).

View File

@ -48,4 +48,4 @@ PROP_TO_ELEMENTS = {
ELEMENT_TO_PROPS = defaultdict(list)
for prop, elements in PROP_TO_ELEMENTS.items():
for el in elements:
ELEMENT_TO_PROPS[el].append(prop)
ELEMENT_TO_PROPS[el].append(prop) # type: ignore

View File

@ -6,7 +6,7 @@ from reflex.components.component import Component
class Element(Component):
"""The base class for all raw HTML elements."""
def __eq__(self, other: object):
def __eq__(self, other):
"""Two elements are equal if they have the same tag.
Args:

View File

@ -6,7 +6,7 @@
from typing import Any, Dict, Optional, Union, overload
from reflex.components.component import Component
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -22,21 +22,21 @@ class Element(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Element":
"""Create the component.

View File

@ -1,136 +1,58 @@
"""Base classes."""
from typing import Literal
from typing import Union
from reflex.components.el.element import Element
from reflex.vars.base import Var
AutoCapitalize = Literal["off", "none", "on", "sentences", "words", "characters"]
ContentEditable = Literal[True, False, "inherit", "plaintext-only"]
EnterKeyHint = Literal["enter", "done", "go", "next", "previous", "search", "send"]
InputMode = Literal[
"none", "text", "tel", "url", "email", "numeric", "decimal", "search", "search"
]
AriaRole = Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
]
class BaseHTML(Element):
"""Base class for common attributes."""
# Provides a hint for generating a keyboard shortcut for the current element.
access_key: Var[str]
access_key: Var[Union[str, int, bool]]
# Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
auto_capitalize: Var[AutoCapitalize]
auto_capitalize: Var[Union[str, int, bool]]
# Indicates whether the element's content is editable.
content_editable: Var[ContentEditable]
content_editable: Var[Union[str, int, bool]]
# Defines the ID of a <menu> element which will serve as the element's context menu.
context_menu: Var[str]
context_menu: Var[Union[str, int, bool]]
# Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)
dir: Var[str]
dir: Var[Union[str, int, bool]]
# Defines whether the element can be dragged.
draggable: Var[bool]
draggable: Var[Union[str, int, bool]]
# Hints what media types the media element is able to play.
enter_key_hint: Var[EnterKeyHint]
enter_key_hint: Var[Union[str, int, bool]]
# Defines whether the element is hidden.
hidden: Var[bool]
hidden: Var[Union[str, int, bool]]
# Defines the type of the element.
input_mode: Var[InputMode]
input_mode: Var[Union[str, int, bool]]
# Defines the name of the element for metadata purposes.
item_prop: Var[str]
item_prop: Var[Union[str, int, bool]]
# Defines the language used in the element.
lang: Var[str]
lang: Var[Union[str, int, bool]]
# Defines the role of the element.
role: Var[AriaRole]
role: Var[Union[str, int, bool]]
# Assigns a slot in a shadow DOM shadow tree to an element.
slot: Var[str]
slot: Var[Union[str, int, bool]]
# Defines whether the element may be checked for spelling errors.
spell_check: Var[bool]
spell_check: Var[Union[str, int, bool]]
# Defines the position of the current element in the tabbing order.
tab_index: Var[int]
tab_index: Var[Union[str, int, bool]]
# Defines a tooltip for the element.
title: Var[str]
title: Var[Union[str, int, bool]]

View File

@ -3,323 +3,64 @@
# ------------------- DO NOT EDIT ----------------------
# This file was generated by `reflex/utils/pyi_generator.py`!
# ------------------------------------------------------
from typing import Any, Dict, Literal, Optional, Union, overload
from typing import Any, Dict, Optional, Union, overload
from reflex.components.el.element import Element
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
AutoCapitalize = Literal["off", "none", "on", "sentences", "words", "characters"]
ContentEditable = Literal[True, False, "inherit", "plaintext-only"]
EnterKeyHint = Literal["enter", "done", "go", "next", "previous", "search", "send"]
InputMode = Literal[
"none", "text", "tel", "url", "email", "numeric", "decimal", "search", "search"
]
AriaRole = Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
]
class BaseHTML(Element):
@overload
@classmethod
def create( # type: ignore
cls,
*children,
access_key: Optional[Union[Var[str], str]] = None,
access_key: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
auto_capitalize: Optional[
Union[
Literal["characters", "none", "off", "on", "sentences", "words"],
Var[Literal["characters", "none", "off", "on", "sentences", "words"]],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
content_editable: Optional[
Union[
Literal["inherit", "plaintext-only", False, True],
Var[Literal["inherit", "plaintext-only", False, True]],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
context_menu: Optional[Union[Var[str], str]] = None,
dir: Optional[Union[Var[str], str]] = None,
draggable: Optional[Union[Var[bool], bool]] = None,
context_menu: Optional[
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
dir: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
draggable: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
enter_key_hint: Optional[
Union[
Literal["done", "enter", "go", "next", "previous", "search", "send"],
Var[
Literal["done", "enter", "go", "next", "previous", "search", "send"]
],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
hidden: Optional[Union[Var[bool], bool]] = None,
input_mode: Optional[
Union[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
],
Var[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
]
],
]
] = None,
item_prop: Optional[Union[Var[str], str]] = None,
lang: Optional[Union[Var[str], str]] = None,
role: Optional[
Union[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
],
Var[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
]
],
]
] = None,
slot: Optional[Union[Var[str], str]] = None,
spell_check: Optional[Union[Var[bool], bool]] = None,
tab_index: Optional[Union[Var[int], int]] = None,
title: Optional[Union[Var[str], str]] = None,
hidden: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
input_mode: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
item_prop: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
lang: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
role: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
slot: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
spell_check: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
tab_index: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
title: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = 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, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "BaseHTML":
"""Create the component.

View File

@ -3,7 +3,7 @@
from __future__ import annotations
from hashlib import md5
from typing import Any, Dict, Iterator, Literal, Set, Tuple, Union
from typing import Any, Dict, Iterator, Set, Tuple, Union
from jinja2 import Environment
@ -41,8 +41,6 @@ HANDLE_SUBMIT_JS_JINJA2 = Environment().from_string(
"""
)
ButtonType = Literal["submit", "reset", "button"]
class Button(BaseHTML):
"""Display the button element."""
@ -50,37 +48,37 @@ class Button(BaseHTML):
tag = "button"
# Automatically focuses the button when the page loads
auto_focus: Var[bool]
auto_focus: Var[Union[str, int, bool]]
# Disables the button
disabled: Var[bool]
# Associates the button with a form (by id)
form: Var[str]
form: Var[Union[str, int, bool]]
# URL to send the form data to (for type="submit" buttons)
form_action: Var[str]
form_action: Var[Union[str, int, bool]]
# How the form data should be encoded when submitting to the server (for type="submit" buttons)
form_enc_type: Var[str]
form_enc_type: Var[Union[str, int, bool]]
# HTTP method to use for sending form data (for type="submit" buttons)
form_method: Var[str]
form_method: Var[Union[str, int, bool]]
# Bypasses form validation when submitting (for type="submit" buttons)
form_no_validate: Var[bool]
form_no_validate: Var[Union[str, int, bool]]
# Specifies where to display the response after submitting the form (for type="submit" buttons)
form_target: Var[str]
form_target: Var[Union[str, int, bool]]
# Name of the button, used when sending form data
name: Var[str]
name: Var[Union[str, int, bool]]
# Type of the button (submit, reset, or button)
type: Var[ButtonType]
type: Var[Union[str, int, bool]]
# Value of the button, used when sending form data
value: Var[Union[str, int, float]]
value: Var[Union[str, int, bool]]
class Datalist(BaseHTML):
@ -95,13 +93,13 @@ class Fieldset(Element):
tag = "fieldset"
# Disables all the form control descendants of the fieldset
disabled: Var[bool]
disabled: Var[Union[str, int, bool]]
# Associates the fieldset with a form (by id)
form: Var[str]
form: Var[Union[str, int, bool]]
# Name of the fieldset, used for scripting
name: Var[str]
name: Var[Union[str, int, bool]]
def on_submit_event_spec() -> Tuple[Var[dict[str, Any]]]:
@ -128,34 +126,34 @@ class Form(BaseHTML):
tag = "form"
# MIME types the server accepts for file upload
accept: Var[str]
accept: Var[Union[str, int, bool]]
# Character encodings to be used for form submission
accept_charset: Var[str]
accept_charset: Var[Union[str, int, bool]]
# URL where the form's data should be submitted
action: Var[str]
action: Var[Union[str, int, bool]]
# Whether the form should have autocomplete enabled
auto_complete: Var[str]
auto_complete: Var[Union[str, int, bool]]
# Encoding type for the form data when submitted
enc_type: Var[str]
enc_type: Var[Union[str, int, bool]]
# HTTP method to use for form submission
method: Var[str]
method: Var[Union[str, int, bool]]
# Name of the form
name: Var[str]
name: Var[Union[str, int, bool]]
# Indicates that the form should not be validated on submit
no_validate: Var[bool]
no_validate: Var[Union[str, int, bool]]
# Where to display the response after submitting the form
target: Var[str]
target: Var[Union[str, int, bool]]
# If true, the form will be cleared after submit.
reset_on_submit: Var[bool] = Var.create(False)
reset_on_submit: Var[bool] = False # type: ignore
# The name used to make this form's submit handler function unique.
handle_submit_unique_name: Var[str]
@ -268,126 +266,106 @@ class Form(BaseHTML):
]
HTMLInputTypeAttribute = Literal[
"button",
"checkbox",
"color",
"date",
"datetime-local",
"email",
"file",
"hidden",
"image",
"month",
"number",
"password",
"radio",
"range",
"reset",
"search",
"submit",
"tel",
"text",
"time",
"url",
"week",
]
class Input(BaseHTML):
"""Display the input element."""
tag = "input"
# Accepted types of files when the input is file type
accept: Var[str]
accept: Var[Union[str, int, bool]]
# Alternate text for input type="image"
alt: Var[str]
alt: Var[Union[str, int, bool]]
# Whether the input should have autocomplete enabled
auto_complete: Var[str]
auto_complete: Var[Union[str, int, bool]]
# Automatically focuses the input when the page loads
auto_focus: Var[bool]
auto_focus: Var[Union[str, int, bool]]
# Captures media from the user (camera or microphone)
capture: Var[Literal[True, False, "user", "environment"]]
capture: Var[Union[str, int, bool]]
# Indicates whether the input is checked (for checkboxes and radio buttons)
checked: Var[bool]
checked: Var[Union[str, int, bool]]
# The initial value (for checkboxes and radio buttons)
default_checked: Var[bool]
# The initial value for a text field
default_value: Var[Union[str, int, float]]
default_value: Var[str]
# Name part of the input to submit in 'dir' and 'name' pair when form is submitted
dirname: Var[Union[str, int, bool]]
# Disables the input
disabled: Var[bool]
disabled: Var[Union[str, int, bool]]
# Associates the input with a form (by id)
form: Var[str]
form: Var[Union[str, int, bool]]
# URL to send the form data to (for type="submit" buttons)
form_action: Var[str]
form_action: Var[Union[str, int, bool]]
# How the form data should be encoded when submitting to the server (for type="submit" buttons)
form_enc_type: Var[str]
form_enc_type: Var[Union[str, int, bool]]
# HTTP method to use for sending form data (for type="submit" buttons)
form_method: Var[str]
form_method: Var[Union[str, int, bool]]
# Bypasses form validation when submitting (for type="submit" buttons)
form_no_validate: Var[bool]
form_no_validate: Var[Union[str, int, bool]]
# Specifies where to display the response after submitting the form (for type="submit" buttons)
form_target: Var[str]
form_target: Var[Union[str, int, bool]]
# References a datalist for suggested options
list: Var[str]
list: Var[Union[str, int, bool]]
# Specifies the maximum value for the input
max: Var[Union[str, int, float]]
max: Var[Union[str, int, bool]]
# Specifies the maximum number of characters allowed in the input
max_length: Var[Union[int, float]]
max_length: Var[Union[str, int, bool]]
# Specifies the minimum number of characters required in the input
min_length: Var[Union[int, float]]
min_length: Var[Union[str, int, bool]]
# Specifies the minimum value for the input
min: Var[Union[str, int, float]]
min: Var[Union[str, int, bool]]
# Indicates whether multiple values can be entered in an input of the type email or file
multiple: Var[bool]
multiple: Var[Union[str, int, bool]]
# Name of the input, used when sending form data
name: Var[str]
name: Var[Union[str, int, bool]]
# Regex pattern the input's value must match to be valid
pattern: Var[str]
pattern: Var[Union[str, int, bool]]
# Placeholder text in the input
placeholder: Var[str]
placeholder: Var[Union[str, int, bool]]
# Indicates whether the input is read-only
read_only: Var[bool]
read_only: Var[Union[str, int, bool]]
# Indicates that the input is required
required: Var[bool]
required: Var[Union[str, int, bool]]
# Specifies the visible width of a text control
size: Var[Union[int, float]]
size: Var[Union[str, int, bool]]
# URL for image inputs
src: Var[str]
src: Var[Union[str, int, bool]]
# Specifies the legal number intervals for an input
step: Var[Union[str, int, float]]
step: Var[Union[str, int, bool]]
# Specifies the type of input
type: Var[HTMLInputTypeAttribute]
type: Var[Union[str, int, bool]]
# Name of the image map used with the input
use_map: Var[Union[str, int, bool]]
# Value of the input
value: Var[Union[str, int, float]]
@ -427,7 +405,7 @@ class Input(BaseHTML):
(value_var := Var.create(value))._var_type
):
props["value"] = ternary_operation(
(value_var != Var.create(None)) # pyright: ignore [reportArgumentType]
(value_var != Var.create(None)) # pyright: ignore [reportGeneralTypeIssues]
& (value_var != Var(_js_expr="undefined")),
value,
Var.create(""),
@ -441,10 +419,10 @@ class Label(BaseHTML):
tag = "label"
# ID of a form control with which the label is associated
html_for: Var[str]
html_for: Var[Union[str, int, bool]]
# Associates the label with a form (by id)
form: Var[str]
form: Var[Union[str, int, bool]]
class Legend(BaseHTML):
@ -459,25 +437,25 @@ class Meter(BaseHTML):
tag = "meter"
# Associates the meter with a form (by id)
form: Var[str]
form: Var[Union[str, int, bool]]
# High limit of range (above this is considered high value)
high: Var[Union[int, float]]
high: Var[Union[str, int, bool]]
# Low limit of range (below this is considered low value)
low: Var[Union[int, float]]
low: Var[Union[str, int, bool]]
# Maximum value of the range
max: Var[Union[int, float]]
max: Var[Union[str, int, bool]]
# Minimum value of the range
min: Var[Union[int, float]]
min: Var[Union[str, int, bool]]
# Optimum value in the range
optimum: Var[Union[int, float]]
optimum: Var[Union[str, int, bool]]
# Current value of the meter
value: Var[Union[int, float]]
value: Var[Union[str, int, bool]]
class Optgroup(BaseHTML):
@ -486,10 +464,10 @@ class Optgroup(BaseHTML):
tag = "optgroup"
# Disables the optgroup
disabled: Var[bool]
disabled: Var[Union[str, int, bool]]
# Label for the optgroup
label: Var[str]
label: Var[Union[str, int, bool]]
class Option(BaseHTML):
@ -498,16 +476,16 @@ class Option(BaseHTML):
tag = "option"
# Disables the option
disabled: Var[bool]
disabled: Var[Union[str, int, bool]]
# Label for the option, if the text is not the label
label: Var[str]
label: Var[Union[str, int, bool]]
# Indicates that the option is initially selected
selected: Var[bool]
selected: Var[Union[str, int, bool]]
# Value to be sent as form data
value: Var[Union[str, int, float]]
value: Var[Union[str, int, bool]]
class Output(BaseHTML):
@ -516,13 +494,13 @@ class Output(BaseHTML):
tag = "output"
# Associates the output with one or more elements (by their IDs)
html_for: Var[str]
html_for: Var[Union[str, int, bool]]
# Associates the output with a form (by id)
form: Var[str]
form: Var[Union[str, int, bool]]
# Name of the output element for form submission
name: Var[str]
name: Var[Union[str, int, bool]]
class Progress(BaseHTML):
@ -531,13 +509,13 @@ class Progress(BaseHTML):
tag = "progress"
# Associates the progress element with a form (by id)
form: Var[str]
form: Var[Union[str, int, bool]]
# Maximum value of the progress indicator
max: Var[Union[str, int, float]]
max: Var[Union[str, int, bool]]
# Current value of the progress indicator
value: Var[Union[str, int, float]]
value: Var[Union[str, int, bool]]
class Select(BaseHTML):
@ -546,28 +524,28 @@ class Select(BaseHTML):
tag = "select"
# Whether the form control should have autocomplete enabled
auto_complete: Var[str]
auto_complete: Var[Union[str, int, bool]]
# Automatically focuses the select when the page loads
auto_focus: Var[bool]
auto_focus: Var[Union[str, int, bool]]
# Disables the select control
disabled: Var[bool]
disabled: Var[Union[str, int, bool]]
# Associates the select with a form (by id)
form: Var[str]
form: Var[Union[str, int, bool]]
# Indicates that multiple options can be selected
multiple: Var[bool]
multiple: Var[Union[str, int, bool]]
# Name of the select, used when submitting the form
name: Var[str]
name: Var[Union[str, int, bool]]
# Indicates that the select control must have a selected option
required: Var[bool]
required: Var[Union[str, int, bool]]
# Number of visible options in a drop-down list
size: Var[int]
size: Var[Union[str, int, bool]]
# Fired when the select value changes
on_change: EventHandler[input_event]
@ -609,58 +587,58 @@ class Textarea(BaseHTML):
tag = "textarea"
# Whether the form control should have autocomplete enabled
auto_complete: Var[str]
auto_complete: Var[Union[str, int, bool]]
# Automatically focuses the textarea when the page loads
auto_focus: Var[bool]
auto_focus: Var[Union[str, int, bool]]
# Automatically fit the content height to the text (use min-height with this prop)
auto_height: Var[bool]
# Visible width of the text control, in average character widths
cols: Var[int]
cols: Var[Union[str, int, bool]]
# The default value of the textarea when initially rendered
default_value: Var[str]
# Name part of the textarea to submit in 'dir' and 'name' pair when form is submitted
dirname: Var[str]
dirname: Var[Union[str, int, bool]]
# Disables the textarea
disabled: Var[bool]
disabled: Var[Union[str, int, bool]]
# Enter key submits form (shift-enter adds new line)
enter_key_submit: Var[bool]
# Associates the textarea with a form (by id)
form: Var[str]
form: Var[Union[str, int, bool]]
# Maximum number of characters allowed in the textarea
max_length: Var[int]
max_length: Var[Union[str, int, bool]]
# Minimum number of characters required in the textarea
min_length: Var[int]
min_length: Var[Union[str, int, bool]]
# Name of the textarea, used when submitting the form
name: Var[str]
name: Var[Union[str, int, bool]]
# Placeholder text in the textarea
placeholder: Var[str]
placeholder: Var[Union[str, int, bool]]
# Indicates whether the textarea is read-only
read_only: Var[bool]
read_only: Var[Union[str, int, bool]]
# Indicates that the textarea is required
required: Var[bool]
required: Var[Union[str, int, bool]]
# Visible number of lines in the text control
rows: Var[int]
rows: Var[Union[str, int, bool]]
# The controlled value of the textarea, read only unless used with on_change
value: Var[str]
value: Var[Union[str, int, bool]]
# How the text in the textarea is to be wrapped when submitting the form
wrap: Var[str]
wrap: Var[Union[str, int, bool]]
# Fired when the input value changes
on_change: EventHandler[input_event]

File diff suppressed because it is too large Load Diff

View File

@ -1,23 +1,11 @@
"""Inline classes."""
from typing import Literal, Union
from typing import Union
from reflex.vars.base import Var
from .base import BaseHTML
ReferrerPolicy = Literal[
"",
"no-referrer",
"no-referrer-when-downgrade",
"origin",
"origin-when-cross-origin",
"same-origin",
"strict-origin",
"strict-origin-when-cross-origin",
"unsafe-url",
]
class A(BaseHTML): # Inherits common attributes from BaseMeta
"""Display the 'a' element."""
@ -25,28 +13,31 @@ class A(BaseHTML): # Inherits common attributes from BaseMeta
tag = "a"
# Specifies that the target (the file specified in the href attribute) will be downloaded when a user clicks on the hyperlink.
download: Var[Union[str, bool]]
download: Var[Union[str, int, bool]]
# Specifies the URL of the page the link goes to
href: Var[str]
href: Var[Union[str, int, bool]]
# Specifies the language of the linked document
href_lang: Var[str]
href_lang: Var[Union[str, int, bool]]
# Specifies what media/device the linked document is optimized for
media: Var[str]
media: Var[Union[str, int, bool]]
# Specifies which referrer is sent when fetching the resource
ping: Var[str]
ping: Var[Union[str, int, bool]]
# Specifies the relationship between the current document and the linked document
referrer_policy: Var[ReferrerPolicy]
referrer_policy: Var[Union[str, int, bool]]
# Specifies the relationship between the linked document and the current document
rel: Var[str]
rel: Var[Union[str, int, bool]]
# Specifies the shape of the area
shape: Var[Union[str, int, bool]]
# Specifies where to open the linked document
target: Var[Union[str, Literal["_self", "_blank", "_parent", "_top"]]]
target: Var[Union[str, int, bool]]
class Abbr(BaseHTML):
@ -97,7 +88,7 @@ class Data(BaseHTML):
tag = "data"
# Specifies the machine-readable translation of the data element.
value: Var[Union[str, int, float]]
value: Var[Union[str, int, bool]]
class Dfn(BaseHTML):
@ -136,7 +127,7 @@ class Q(BaseHTML):
tag = "q"
# Specifies the source URL of the quote.
cite: Var[str]
cite: Var[Union[str, int, bool]]
class Rp(BaseHTML):
@ -205,7 +196,7 @@ class Time(BaseHTML):
tag = "time"
# Specifies the date and/or time of the element.
date_time: Var[str]
date_time: Var[Union[str, int, bool]]
class U(BaseHTML):

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,8 @@
"""Media classes."""
from typing import Any, Literal, Union
from typing import Any, Union
from reflex import Component, ComponentNamespace
from reflex.components.el.elements.inline import ReferrerPolicy
from reflex.constants.colors import Color
from reflex.vars.base import Var
@ -16,37 +15,37 @@ class Area(BaseHTML):
tag = "area"
# Alternate text for the area, used for accessibility
alt: Var[str]
alt: Var[Union[str, int, bool]]
# Coordinates to define the shape of the area
coords: Var[str]
coords: Var[Union[str, int, bool]]
# Specifies that the target will be downloaded when clicked
download: Var[Union[str, bool]]
download: Var[Union[str, int, bool]]
# Hyperlink reference for the area
href: Var[str]
href: Var[Union[str, int, bool]]
# Language of the linked resource
href_lang: Var[str]
href_lang: Var[Union[str, int, bool]]
# Specifies what media/device the linked resource is optimized for
media: Var[str]
media: Var[Union[str, int, bool]]
# A list of URLs to be notified if the user follows the hyperlink
ping: Var[Union[str, int, bool]]
# Specifies which referrer information to send with the link
referrer_policy: Var[ReferrerPolicy]
referrer_policy: Var[Union[str, int, bool]]
# Specifies the relationship of the target object to the link object
rel: Var[str]
rel: Var[Union[str, int, bool]]
# Defines the shape of the area (rectangle, circle, polygon)
shape: Var[str]
shape: Var[Union[str, int, bool]]
# Specifies where to open the linked document
target: Var[str]
CrossOrigin = Literal["anonymous", "use-credentials", ""]
target: Var[Union[str, int, bool]]
class Audio(BaseHTML):
@ -55,29 +54,28 @@ class Audio(BaseHTML):
tag = "audio"
# Specifies that the audio will start playing as soon as it is ready
auto_play: Var[bool]
auto_play: Var[Union[str, int, bool]]
# Represents the time range of the buffered media
buffered: Var[Union[str, int, bool]]
# Displays the standard audio controls
controls: Var[bool]
controls: Var[Union[str, int, bool]]
# Configures the CORS requests for the element
cross_origin: Var[CrossOrigin]
cross_origin: Var[Union[str, int, bool]]
# Specifies that the audio will loop
loop: Var[bool]
loop: Var[Union[str, int, bool]]
# Indicates whether the audio is muted by default
muted: Var[bool]
muted: Var[Union[str, int, bool]]
# Specifies how the audio file should be preloaded
preload: Var[str]
preload: Var[Union[str, int, bool]]
# URL of the audio to play
src: Var[str]
ImageDecoding = Literal["async", "auto", "sync"]
ImageLoading = Literal["eager", "lazy"]
src: Var[Union[str, int, bool]]
class Img(BaseHTML):
@ -85,32 +83,41 @@ class Img(BaseHTML):
tag = "img"
# Image alignment with respect to its surrounding elements
align: Var[Union[str, int, bool]]
# Alternative text for the image
alt: Var[str]
alt: Var[Union[str, int, bool]]
# Configures the CORS requests for the image
cross_origin: Var[CrossOrigin]
cross_origin: Var[Union[str, int, bool]]
# How the image should be decoded
decoding: Var[ImageDecoding]
decoding: Var[Union[str, int, bool]]
# Specifies an intrinsic size for the image
intrinsicsize: Var[Union[str, int, bool]]
# Whether the image is a server-side image map
ismap: Var[Union[str, int, bool]]
# Specifies the loading behavior of the image
loading: Var[ImageLoading]
loading: Var[Union[str, int, bool]]
# Referrer policy for the image
referrer_policy: Var[ReferrerPolicy]
referrer_policy: Var[Union[str, int, bool]]
# Sizes of the image for different layouts
sizes: Var[str]
sizes: Var[Union[str, int, bool]]
# URL of the image to display
src: Var[Any]
# A set of source sizes and URLs for responsive images
src_set: Var[str]
src_set: Var[Union[str, int, bool]]
# The name of the map to use with the image
use_map: Var[str]
use_map: Var[Union[str, int, bool]]
@classmethod
def create(cls, *children, **props) -> Component:
@ -136,7 +143,7 @@ class Map(BaseHTML):
tag = "map"
# Name of the map, referenced by the 'usemap' attribute in 'img' and 'object' elements
name: Var[str]
name: Var[Union[str, int, bool]]
class Track(BaseHTML):
@ -145,19 +152,19 @@ class Track(BaseHTML):
tag = "track"
# Indicates that the track should be enabled unless the user's preferences indicate otherwise
default: Var[bool]
default: Var[Union[str, int, bool]]
# Specifies the kind of text track
kind: Var[str]
kind: Var[Union[str, int, bool]]
# Title of the text track, used by the browser when listing available text tracks
label: Var[str]
label: Var[Union[str, int, bool]]
# URL of the track file
src: Var[str]
src: Var[Union[str, int, bool]]
# Language of the track text data
src_lang: Var[str]
src_lang: Var[Union[str, int, bool]]
class Video(BaseHTML):
@ -166,31 +173,34 @@ class Video(BaseHTML):
tag = "video"
# Specifies that the video will start playing as soon as it is ready
auto_play: Var[bool]
auto_play: Var[Union[str, int, bool]]
# Represents the time range of the buffered media
buffered: Var[Union[str, int, bool]]
# Displays the standard video controls
controls: Var[bool]
controls: Var[Union[str, int, bool]]
# Configures the CORS requests for the video
cross_origin: Var[CrossOrigin]
cross_origin: Var[Union[str, int, bool]]
# Specifies that the video will loop
loop: Var[bool]
loop: Var[Union[str, int, bool]]
# Indicates whether the video is muted by default
muted: Var[bool]
muted: Var[Union[str, int, bool]]
# Indicates that the video should play 'inline', inside its element's playback area
plays_inline: Var[bool]
plays_inline: Var[Union[str, int, bool]]
# URL of an image to show while the video is downloading, or until the user hits the play button
poster: Var[str]
poster: Var[Union[str, int, bool]]
# Specifies how the video file should be preloaded
preload: Var[str]
preload: Var[Union[str, int, bool]]
# URL of the video to play
src: Var[str]
src: Var[Union[str, int, bool]]
class Embed(BaseHTML):
@ -199,10 +209,10 @@ class Embed(BaseHTML):
tag = "embed"
# URL of the embedded content
src: Var[str]
src: Var[Union[str, int, bool]]
# Media type of the embedded content
type: Var[str]
type: Var[Union[str, int, bool]]
class Iframe(BaseHTML):
@ -210,26 +220,32 @@ class Iframe(BaseHTML):
tag = "iframe"
# Alignment of the iframe within the page or surrounding elements
align: Var[Union[str, int, bool]]
# Permissions policy for the iframe
allow: Var[str]
allow: Var[Union[str, int, bool]]
# Content Security Policy to apply to the iframe's content
csp: Var[Union[str, int, bool]]
# Specifies the loading behavior of the iframe
loading: Var[Literal["eager", "lazy"]]
loading: Var[Union[str, int, bool]]
# Name of the iframe, used as a target for hyperlinks and forms
name: Var[str]
name: Var[Union[str, int, bool]]
# Referrer policy for the iframe
referrer_policy: Var[ReferrerPolicy]
referrer_policy: Var[Union[str, int, bool]]
# Security restrictions for the content in the iframe
sandbox: Var[str]
sandbox: Var[Union[str, int, bool]]
# URL of the document to display in the iframe
src: Var[str]
src: Var[Union[str, int, bool]]
# HTML content to embed directly within the iframe
src_doc: Var[str]
src_doc: Var[Union[str, int, bool]]
class Object(BaseHTML):
@ -238,19 +254,19 @@ class Object(BaseHTML):
tag = "object"
# URL of the data to be used by the object
data: Var[str]
data: Var[Union[str, int, bool]]
# Associates the object with a form element
form: Var[str]
form: Var[Union[str, int, bool]]
# Name of the object, used for scripting or as a target for forms and links
name: Var[str]
name: Var[Union[str, int, bool]]
# Media type of the data specified in the data attribute
type: Var[str]
type: Var[Union[str, int, bool]]
# Name of an image map to use with the object
use_map: Var[str]
use_map: Var[Union[str, int, bool]]
class Picture(BaseHTML):
@ -271,19 +287,19 @@ class Source(BaseHTML):
tag = "source"
# Media query indicating what device the linked resource is optimized for
media: Var[str]
media: Var[Union[str, int, bool]]
# Sizes of the source for different layouts
sizes: Var[str]
sizes: Var[Union[str, int, bool]]
# URL of the media file or an image for the element to use
src: Var[str]
src: Var[Union[str, int, bool]]
# A set of source sizes and URLs for responsive images
src_set: Var[str]
src_set: Var[Union[str, int, bool]]
# Media type of the source
type: Var[str]
type: Var[Union[str, int, bool]]
class Svg(BaseHTML):
@ -415,16 +431,16 @@ class LinearGradient(BaseHTML):
spread_method: Var[Union[str, bool]]
# X coordinate of the starting point of the gradient.
x1: Var[Union[str, int, float]]
x1: Var[Union[str, int, bool]]
# X coordinate of the ending point of the gradient.
x2: Var[Union[str, int, float]]
x2: Var[Union[str, int, bool]]
# Y coordinate of the starting point of the gradient.
y1: Var[Union[str, int, float]]
y1: Var[Union[str, int, bool]]
# Y coordinate of the ending point of the gradient.
y2: Var[Union[str, int, float]]
y2: Var[Union[str, int, bool]]
class RadialGradient(BaseHTML):
@ -433,19 +449,19 @@ class RadialGradient(BaseHTML):
tag = "radialGradient"
# The x coordinate of the end circle of the radial gradient.
cx: Var[Union[str, int, float]]
cx: Var[Union[str, int, bool]]
# The y coordinate of the end circle of the radial gradient.
cy: Var[Union[str, int, float]]
cy: Var[Union[str, int, bool]]
# The radius of the start circle of the radial gradient.
fr: Var[Union[str, int, float]]
fr: Var[Union[str, int, bool]]
# The x coordinate of the start circle of the radial gradient.
fx: Var[Union[str, int, float]]
fx: Var[Union[str, int, bool]]
# The y coordinate of the start circle of the radial gradient.
fy: Var[Union[str, int, float]]
fy: Var[Union[str, int, bool]]
# Units for the gradient.
gradient_units: Var[Union[str, bool]]
@ -454,7 +470,7 @@ class RadialGradient(BaseHTML):
gradient_transform: Var[Union[str, bool]]
# The radius of the end circle of the radial gradient.
r: Var[Union[str, int, float]]
r: Var[Union[str, int, bool]]
# Method used to spread the gradient.
spread_method: Var[Union[str, bool]]
@ -481,7 +497,7 @@ class Path(BaseHTML):
tag = "path"
# Defines the shape of the path.
d: Var[Union[str, int, float]]
d: Var[Union[str, int, bool]]
class SVG(ComponentNamespace):

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,8 @@
"""Metadata classes."""
from typing import List
from typing import List, Union
from reflex.components.el.element import Element
from reflex.components.el.elements.inline import ReferrerPolicy
from reflex.components.el.elements.media import CrossOrigin
from reflex.vars.base import Var
from .base import BaseHTML
@ -16,8 +14,8 @@ class Base(BaseHTML):
tag = "base"
tag = "base"
href: Var[str]
target: Var[str]
href: Var[Union[str, int, bool]]
target: Var[Union[str, int, bool]]
class Head(BaseHTML):
@ -32,31 +30,31 @@ class Link(BaseHTML):
tag = "link"
# Specifies the CORS settings for the linked resource
cross_origin: Var[CrossOrigin]
cross_origin: Var[Union[str, int, bool]]
# Specifies the URL of the linked document/resource
href: Var[str]
href: Var[Union[str, int, bool]]
# Specifies the language of the text in the linked document
href_lang: Var[str]
href_lang: Var[Union[str, int, bool]]
# Allows a browser to check the fetched link for integrity
integrity: Var[str]
integrity: Var[Union[str, int, bool]]
# Specifies on what device the linked document will be displayed
media: Var[str]
media: Var[Union[str, int, bool]]
# Specifies the referrer policy of the linked document
referrer_policy: Var[ReferrerPolicy]
referrer_policy: Var[Union[str, int, bool]]
# Specifies the relationship between the current document and the linked one
rel: Var[str]
rel: Var[Union[str, int, bool]]
# Specifies the sizes of icons for visual media
sizes: Var[str]
sizes: Var[Union[str, int, bool]]
# Specifies the MIME type of the linked document
type: Var[str]
type: Var[Union[str, int, bool]]
class Meta(BaseHTML): # Inherits common attributes from BaseHTML
@ -65,16 +63,16 @@ class Meta(BaseHTML): # Inherits common attributes from BaseHTML
tag = "meta" # The HTML tag for this element is <meta>
# Specifies the character encoding for the HTML document
char_set: Var[str]
char_set: Var[Union[str, int, bool]]
# Defines the content of the metadata
content: Var[str]
content: Var[Union[str, int, bool]]
# Provides an HTTP header for the information/value of the content attribute
http_equiv: Var[str]
http_equiv: Var[Union[str, int, bool]]
# Specifies a name for the metadata
name: Var[str]
name: Var[Union[str, int, bool]]
class Title(Element):
@ -89,7 +87,7 @@ class StyleEl(Element):
tag = "style"
media: Var[str]
media: Var[Union[str, int, bool]]
special_props: List[Var] = [Var(_js_expr="suppressHydrationWarning")]

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
"""Other classes."""
from typing import Union
from reflex.vars.base import Var
from .base import BaseHTML
@ -11,7 +13,7 @@ class Details(BaseHTML):
tag = "details"
# Indicates whether the details will be visible (expanded) to the user
open: Var[bool]
open: Var[Union[str, int, bool]]
class Dialog(BaseHTML):
@ -20,7 +22,7 @@ class Dialog(BaseHTML):
tag = "dialog"
# Indicates whether the dialog is active and can be interacted with
open: Var[bool]
open: Var[Union[str, int, bool]]
class Summary(BaseHTML):
@ -65,7 +67,7 @@ class Html(BaseHTML):
tag = "html"
# Specifies the URL of the document's cache manifest (obsolete in HTML5)
manifest: Var[str]
manifest: Var[Union[str, int, bool]]
details = Details.create

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
"""Scripts classes."""
from reflex.components.el.elements.inline import ReferrerPolicy
from reflex.components.el.elements.media import CrossOrigin
from typing import Union
from reflex.vars.base import Var
from .base import BaseHTML
@ -25,28 +25,31 @@ class Script(BaseHTML):
tag = "script"
# Indicates that the script should be executed asynchronously
async_: Var[bool]
async_: Var[Union[str, int, bool]]
# Character encoding of the external script
char_set: Var[str]
char_set: Var[Union[str, int, bool]]
# Configures the CORS requests for the script
cross_origin: Var[CrossOrigin]
cross_origin: Var[Union[str, int, bool]]
# Indicates that the script should be executed after the page has finished parsing
defer: Var[bool]
defer: Var[Union[str, int, bool]]
# Security feature allowing browsers to verify what they fetch
integrity: Var[str]
integrity: Var[Union[str, int, bool]]
# Specifies the scripting language used in the type attribute
language: Var[Union[str, int, bool]]
# Specifies which referrer information to send when fetching the script
referrer_policy: Var[ReferrerPolicy]
referrer_policy: Var[Union[str, int, bool]]
# URL of an external script
src: Var[str]
src: Var[Union[str, int, bool]]
# Specifies the MIME type of the script
type: Var[str]
type: Var[Union[str, int, bool]]
canvas = Canvas.create

View File

@ -3,9 +3,9 @@
# ------------------- DO NOT EDIT ----------------------
# This file was generated by `reflex/utils/pyi_generator.py`!
# ------------------------------------------------------
from typing import Any, Dict, Literal, Optional, Union, overload
from typing import Any, Dict, Optional, Union, overload
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.vars.base import Var
@ -17,232 +17,51 @@ class Canvas(BaseHTML):
def create( # type: ignore
cls,
*children,
access_key: Optional[Union[Var[str], str]] = None,
access_key: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
auto_capitalize: Optional[
Union[
Literal["characters", "none", "off", "on", "sentences", "words"],
Var[Literal["characters", "none", "off", "on", "sentences", "words"]],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
content_editable: Optional[
Union[
Literal["inherit", "plaintext-only", False, True],
Var[Literal["inherit", "plaintext-only", False, True]],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
context_menu: Optional[Union[Var[str], str]] = None,
dir: Optional[Union[Var[str], str]] = None,
draggable: Optional[Union[Var[bool], bool]] = None,
context_menu: Optional[
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
dir: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
draggable: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
enter_key_hint: Optional[
Union[
Literal["done", "enter", "go", "next", "previous", "search", "send"],
Var[
Literal["done", "enter", "go", "next", "previous", "search", "send"]
],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
hidden: Optional[Union[Var[bool], bool]] = None,
input_mode: Optional[
Union[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
],
Var[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
]
],
]
] = None,
item_prop: Optional[Union[Var[str], str]] = None,
lang: Optional[Union[Var[str], str]] = None,
role: Optional[
Union[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
],
Var[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
]
],
]
] = None,
slot: Optional[Union[Var[str], str]] = None,
spell_check: Optional[Union[Var[bool], bool]] = None,
tab_index: Optional[Union[Var[int], int]] = None,
title: Optional[Union[Var[str], str]] = None,
hidden: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
input_mode: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
item_prop: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
lang: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
role: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
slot: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
spell_check: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
tab_index: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
title: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = 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, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Canvas":
"""Create the component.
@ -284,232 +103,51 @@ class Noscript(BaseHTML):
def create( # type: ignore
cls,
*children,
access_key: Optional[Union[Var[str], str]] = None,
access_key: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
auto_capitalize: Optional[
Union[
Literal["characters", "none", "off", "on", "sentences", "words"],
Var[Literal["characters", "none", "off", "on", "sentences", "words"]],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
content_editable: Optional[
Union[
Literal["inherit", "plaintext-only", False, True],
Var[Literal["inherit", "plaintext-only", False, True]],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
context_menu: Optional[Union[Var[str], str]] = None,
dir: Optional[Union[Var[str], str]] = None,
draggable: Optional[Union[Var[bool], bool]] = None,
context_menu: Optional[
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
dir: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
draggable: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
enter_key_hint: Optional[
Union[
Literal["done", "enter", "go", "next", "previous", "search", "send"],
Var[
Literal["done", "enter", "go", "next", "previous", "search", "send"]
],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
hidden: Optional[Union[Var[bool], bool]] = None,
input_mode: Optional[
Union[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
],
Var[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
]
],
]
] = None,
item_prop: Optional[Union[Var[str], str]] = None,
lang: Optional[Union[Var[str], str]] = None,
role: Optional[
Union[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
],
Var[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
]
],
]
] = None,
slot: Optional[Union[Var[str], str]] = None,
spell_check: Optional[Union[Var[bool], bool]] = None,
tab_index: Optional[Union[Var[int], int]] = None,
title: Optional[Union[Var[str], str]] = None,
hidden: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
input_mode: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
item_prop: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
lang: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
role: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
slot: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
spell_check: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
tab_index: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
title: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = 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, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Noscript":
"""Create the component.
@ -551,272 +189,64 @@ class Script(BaseHTML):
def create( # type: ignore
cls,
*children,
async_: Optional[Union[Var[bool], bool]] = None,
char_set: Optional[Union[Var[str], str]] = None,
async_: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
char_set: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
cross_origin: Optional[
Union[
Literal["", "anonymous", "use-credentials"],
Var[Literal["", "anonymous", "use-credentials"]],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
defer: Optional[Union[Var[bool], bool]] = None,
integrity: Optional[Union[Var[str], str]] = None,
defer: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
integrity: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
language: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
referrer_policy: Optional[
Union[
Literal[
"",
"no-referrer",
"no-referrer-when-downgrade",
"origin",
"origin-when-cross-origin",
"same-origin",
"strict-origin",
"strict-origin-when-cross-origin",
"unsafe-url",
],
Var[
Literal[
"",
"no-referrer",
"no-referrer-when-downgrade",
"origin",
"origin-when-cross-origin",
"same-origin",
"strict-origin",
"strict-origin-when-cross-origin",
"unsafe-url",
]
],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
src: Optional[Union[Var[str], str]] = None,
type: Optional[Union[Var[str], str]] = None,
access_key: Optional[Union[Var[str], str]] = None,
src: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
type: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
access_key: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
auto_capitalize: Optional[
Union[
Literal["characters", "none", "off", "on", "sentences", "words"],
Var[Literal["characters", "none", "off", "on", "sentences", "words"]],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
content_editable: Optional[
Union[
Literal["inherit", "plaintext-only", False, True],
Var[Literal["inherit", "plaintext-only", False, True]],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
context_menu: Optional[Union[Var[str], str]] = None,
dir: Optional[Union[Var[str], str]] = None,
draggable: Optional[Union[Var[bool], bool]] = None,
context_menu: Optional[
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
dir: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
draggable: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
enter_key_hint: Optional[
Union[
Literal["done", "enter", "go", "next", "previous", "search", "send"],
Var[
Literal["done", "enter", "go", "next", "previous", "search", "send"]
],
]
Union[Var[Union[bool, int, str]], bool, int, str]
] = None,
hidden: Optional[Union[Var[bool], bool]] = None,
input_mode: Optional[
Union[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
],
Var[
Literal[
"decimal",
"email",
"none",
"numeric",
"search",
"tel",
"text",
"url",
]
],
]
] = None,
item_prop: Optional[Union[Var[str], str]] = None,
lang: Optional[Union[Var[str], str]] = None,
role: Optional[
Union[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
],
Var[
Literal[
"alert",
"alertdialog",
"application",
"article",
"banner",
"button",
"cell",
"checkbox",
"columnheader",
"combobox",
"complementary",
"contentinfo",
"definition",
"dialog",
"directory",
"document",
"feed",
"figure",
"form",
"grid",
"gridcell",
"group",
"heading",
"img",
"link",
"list",
"listbox",
"listitem",
"log",
"main",
"marquee",
"math",
"menu",
"menubar",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"navigation",
"none",
"note",
"option",
"presentation",
"progressbar",
"radio",
"radiogroup",
"region",
"row",
"rowgroup",
"rowheader",
"scrollbar",
"search",
"searchbox",
"separator",
"slider",
"spinbutton",
"status",
"switch",
"tab",
"table",
"tablist",
"tabpanel",
"term",
"textbox",
"timer",
"toolbar",
"tooltip",
"tree",
"treegrid",
"treeitem",
]
],
]
] = None,
slot: Optional[Union[Var[str], str]] = None,
spell_check: Optional[Union[Var[bool], bool]] = None,
tab_index: Optional[Union[Var[int], int]] = None,
title: Optional[Union[Var[str], str]] = None,
hidden: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
input_mode: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
item_prop: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
lang: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
role: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
slot: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
spell_check: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
tab_index: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
title: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = 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, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Script":
"""Create the component.
@ -828,6 +258,7 @@ class Script(BaseHTML):
cross_origin: Configures the CORS requests for the script
defer: Indicates that the script should be executed after the page has finished parsing
integrity: Security feature allowing browsers to verify what they fetch
language: Specifies the scripting language used in the type attribute
referrer_policy: Specifies which referrer information to send when fetching the script
src: URL of an external script
type: Specifies the MIME type of the script

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
"""Tables classes."""
from typing import Literal
from typing import Union
from reflex.vars.base import Var
@ -12,14 +12,20 @@ class Caption(BaseHTML):
tag = "caption"
# Alignment of the caption
align: Var[Union[str, int, bool]]
class Col(BaseHTML):
"""Display the col element."""
tag = "col"
# Alignment of the content within the column
align: Var[Union[str, int, bool]]
# Number of columns the col element spans
span: Var[int]
span: Var[Union[str, int, bool]]
class Colgroup(BaseHTML):
@ -27,8 +33,11 @@ class Colgroup(BaseHTML):
tag = "colgroup"
# Alignment of the content within the column group
align: Var[Union[str, int, bool]]
# Number of columns the colgroup element spans
span: Var[int]
span: Var[Union[str, int, bool]]
class Table(BaseHTML):
@ -37,10 +46,10 @@ class Table(BaseHTML):
tag = "table"
# Alignment of the table
align: Var[Literal["left", "center", "right"]]
align: Var[Union[str, int, bool]]
# Provides a summary of the table's purpose and structure
summary: Var[str]
summary: Var[Union[str, int, bool]]
class Tbody(BaseHTML):
@ -48,6 +57,9 @@ class Tbody(BaseHTML):
tag = "tbody"
# Alignment of the content within the table body
align: Var[Union[str, int, bool]]
class Td(BaseHTML):
"""Display the td element."""
@ -55,16 +67,16 @@ class Td(BaseHTML):
tag = "td"
# Alignment of the content within the table cell
align: Var[Literal["left", "center", "right", "justify", "char"]]
align: Var[Union[str, int, bool]]
# Number of columns a cell should span
col_span: Var[int]
col_span: Var[Union[str, int, bool]]
# IDs of the headers associated with this cell
headers: Var[str]
headers: Var[Union[str, int, bool]]
# Number of rows a cell should span
row_span: Var[int]
row_span: Var[Union[str, int, bool]]
class Tfoot(BaseHTML):
@ -72,6 +84,9 @@ class Tfoot(BaseHTML):
tag = "tfoot"
# Alignment of the content within the table footer
align: Var[Union[str, int, bool]]
class Th(BaseHTML):
"""Display the th element."""
@ -79,19 +94,19 @@ class Th(BaseHTML):
tag = "th"
# Alignment of the content within the table header cell
align: Var[Literal["left", "center", "right", "justify", "char"]]
align: Var[Union[str, int, bool]]
# Number of columns a header cell should span
col_span: Var[int]
col_span: Var[Union[str, int, bool]]
# IDs of the headers associated with this header cell
headers: Var[str]
headers: Var[Union[str, int, bool]]
# Number of rows a header cell should span
row_span: Var[int]
row_span: Var[Union[str, int, bool]]
# Scope of the header cell (row, col, rowgroup, colgroup)
scope: Var[str]
scope: Var[Union[str, int, bool]]
class Thead(BaseHTML):
@ -99,12 +114,18 @@ class Thead(BaseHTML):
tag = "thead"
# Alignment of the content within the table header
align: Var[Union[str, int, bool]]
class Tr(BaseHTML):
"""Display the tr element."""
tag = "tr"
# Alignment of the content within the table row
align: Var[Union[str, int, bool]]
caption = Caption.create
col = Col.create

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
"""Typography classes."""
from typing import Literal
from typing import Union
from reflex.vars.base import Var
@ -13,7 +13,7 @@ class Blockquote(BaseHTML):
tag = "blockquote"
# Define the title of a work.
cite: Var[str]
cite: Var[Union[str, int, bool]]
class Dd(BaseHTML):
@ -51,6 +51,9 @@ class Hr(BaseHTML):
tag = "hr"
# Used to specify the alignment of text content of The Element. this attribute is used in all elements.
align: Var[Union[str, int, bool]]
class Li(BaseHTML):
"""Display the li element."""
@ -64,7 +67,7 @@ class Menu(BaseHTML):
tag = "menu"
# Specifies that the menu element is a context menu.
type: Var[str]
type: Var[Union[str, int, bool]]
class Ol(BaseHTML):
@ -73,13 +76,13 @@ class Ol(BaseHTML):
tag = "ol"
# Reverses the order of the list.
reversed: Var[bool]
reversed: Var[Union[str, int, bool]]
# Specifies the start value of the first list item in an ordered list.
start: Var[int]
start: Var[Union[str, int, bool]]
# Specifies the kind of marker to use in the list (letters or numbers).
type: Var[Literal["1", "a", "A", "i", "I"]]
type: Var[Union[str, int, bool]]
class P(BaseHTML):
@ -106,10 +109,10 @@ class Ins(BaseHTML):
tag = "ins"
# Specifies the URL of the document that explains the reason why the text was inserted/changed.
cite: Var[str]
cite: Var[Union[str, int, bool]]
# Specifies the date and time of when the text was inserted/changed.
date_time: Var[str]
date_time: Var[Union[str, int, bool]]
class Del(BaseHTML):
@ -118,10 +121,10 @@ class Del(BaseHTML):
tag = "del"
# Specifies the URL of the document that explains the reason why the text was deleted.
cite: Var[str]
cite: Var[Union[str, int, bool]]
# Specifies the date and time of when the text was deleted.
date_time: Var[str]
date_time: Var[Union[str, int, bool]]
blockquote = Blockquote.create

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@
from typing import Any, Dict, List, Optional, Union, overload
from reflex.components.component import Component
from reflex.event import EventType
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.utils.imports import ImportDict
from reflex.vars.base import Var
@ -23,21 +23,21 @@ class Gridjs(Component):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Gridjs":
"""Create the component.
@ -75,21 +75,21 @@ class DataTable(Gridjs):
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = None,
on_blur: Optional[EventType[()]] = None,
on_click: Optional[EventType[()]] = None,
on_context_menu: Optional[EventType[()]] = None,
on_double_click: Optional[EventType[()]] = None,
on_focus: Optional[EventType[()]] = None,
on_mount: Optional[EventType[()]] = None,
on_mouse_down: Optional[EventType[()]] = None,
on_mouse_enter: Optional[EventType[()]] = None,
on_mouse_leave: Optional[EventType[()]] = None,
on_mouse_move: Optional[EventType[()]] = None,
on_mouse_out: Optional[EventType[()]] = None,
on_mouse_over: Optional[EventType[()]] = None,
on_mouse_up: Optional[EventType[()]] = None,
on_scroll: Optional[EventType[()]] = None,
on_unmount: Optional[EventType[()]] = None,
on_blur: Optional[EventType[[], BASE_STATE]] = None,
on_click: Optional[EventType[[], BASE_STATE]] = None,
on_context_menu: Optional[EventType[[], BASE_STATE]] = None,
on_double_click: Optional[EventType[[], BASE_STATE]] = None,
on_focus: Optional[EventType[[], BASE_STATE]] = None,
on_mount: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_down: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_enter: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_leave: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_move: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_out: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_over: Optional[EventType[[], BASE_STATE]] = None,
on_mouse_up: Optional[EventType[[], BASE_STATE]] = None,
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "DataTable":
"""Create a datatable component.

View File

@ -4,7 +4,7 @@ from reflex.components.component import Component
from reflex.utils import format
from reflex.utils.imports import ImportVar
from reflex.vars.base import LiteralVar, Var
from reflex.vars.sequence import LiteralStringVar, StringVar
from reflex.vars.sequence import LiteralStringVar
class LucideIconComponent(Component):
@ -40,12 +40,7 @@ class Icon(LucideIconComponent):
The created component.
"""
if children:
if len(children) == 1:
child = Var.create(children[0]).guess_type()
if not isinstance(child, StringVar):
raise AttributeError(
f"Icon name must be a string, got {children[0]._var_type if isinstance(children[0], Var) else children[0]}"
)
if len(children) == 1 and isinstance(children[0], str):
props["tag"] = children[0]
else:
raise AttributeError(
@ -54,33 +49,22 @@ class Icon(LucideIconComponent):
if "tag" not in props:
raise AttributeError("Missing 'tag' keyword-argument for Icon")
tag: str | Var | LiteralVar = Var.create(props.pop("tag"))
tag: str | Var | LiteralVar = props.pop("tag")
if isinstance(tag, LiteralVar):
if isinstance(tag, LiteralStringVar):
tag = tag._var_value
else:
raise TypeError(f"Icon name must be a string, got {type(tag)}")
elif isinstance(tag, Var):
tag_stringified = tag.guess_type()
if not isinstance(tag_stringified, StringVar):
raise TypeError(f"Icon name must be a string, got {tag._var_type}")
return DynamicIcon.create(name=tag_stringified.replace("_", "-"), **props)
return DynamicIcon.create(name=tag, **props)
if (
not isinstance(tag, str)
or format.to_snake_case(tag) not in LUCIDE_ICON_LIST
):
if isinstance(tag, str):
icons_sorted = sorted(
LUCIDE_ICON_LIST,
key=lambda s: format.length_of_largest_common_substring(tag, s),
reverse=True,
)
else:
icons_sorted = LUCIDE_ICON_LIST
raise ValueError(
f"Invalid icon tag: {tag}. Please use one of the following: {', '.join(icons_sorted[0:25])}, ..."
"\nSee full list at https://reflex.dev/docs/library/data-display/icon/#icons-list."
f"Invalid icon tag: {tag}. Please use one of the following: {', '.join(LUCIDE_ICON_LIST[0:25])}, ..."
"\nSee full list at https://lucide.dev/icons."
)
if tag in LUCIDE_ICON_MAPPING_OVERRIDE:

Some files were not shown because too many files have changed in this diff Show More