Compare commits
91 Commits
main
...
masenf/sta
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ec02b2c2db | ||
![]() |
2ffa698c6b | ||
![]() |
0d746bf762 | ||
![]() |
d3b12a84fa | ||
![]() |
6604784ca1 | ||
![]() |
24f341d125 | ||
![]() |
29fc4b020a | ||
![]() |
19dd15bd44 | ||
![]() |
6a50b3a29e | ||
![]() |
b2a27cb8c1 | ||
![]() |
540382dd3e | ||
![]() |
c6e2368c95 | ||
![]() |
e10cf07506 | ||
![]() |
84d3a2bb97 | ||
![]() |
8173e10698 | ||
![]() |
1f9fbd88de | ||
![]() |
68b8c12127 | ||
![]() |
5e45ca509b | ||
![]() |
be92063421 | ||
![]() |
5d6b51c561 | ||
![]() |
b10f6e836d | ||
![]() |
db89a712e9 | ||
![]() |
9e7eeb2a6e | ||
![]() |
b7579f4d8d | ||
![]() |
392c5b5a69 | ||
![]() |
b11fc5a8ef | ||
![]() |
00019daa27 | ||
![]() |
36af8255d3 | ||
![]() |
aadd8b56bf | ||
![]() |
fa6c12e8b3 | ||
![]() |
f4aa122950 | ||
![]() |
9a987caf76 | ||
![]() |
c6f05bb320 | ||
![]() |
0e539a208c | ||
![]() |
a7230f1f45 | ||
![]() |
0798cb8f60 | ||
![]() |
270fcb996d | ||
![]() |
57d8ea02e9 | ||
![]() |
112b2ed948 | ||
![]() |
3d73f561b7 | ||
![]() |
72f1fa7cb4 | ||
![]() |
94b4443afc | ||
![]() |
f9d45d5562 | ||
![]() |
94c9e52474 | ||
![]() |
4300f338d8 | ||
![]() |
f42d1f4b0f | ||
![]() |
a488fe0c49 | ||
![]() |
076cfea6ae | ||
![]() |
d0208e678c | ||
![]() |
19b6fe9efc | ||
![]() |
1aa728ee4c | ||
![]() |
713f907bf0 | ||
![]() |
990bf131c6 | ||
![]() |
f257122934 | ||
![]() |
f0f84d5410 | ||
![]() |
45dde0072e | ||
![]() |
2a02e96d87 | ||
![]() |
056de9e277 | ||
![]() |
d31510c655 | ||
![]() |
a5526afaeb | ||
![]() |
99a3090784 | ||
![]() |
bd2ea5b417 | ||
![]() |
8830d5ab77 | ||
![]() |
06eb04f005 | ||
![]() |
2e1bc057a4 | ||
![]() |
2b05ee98ed | ||
![]() |
ed1ae0d3a2 | ||
![]() |
7d0a4f7133 | ||
![]() |
079cc56f59 | ||
![]() |
92b1232806 | ||
![]() |
7f1dc7c841 | ||
![]() |
eac54d60d2 | ||
![]() |
702670ff26 | ||
![]() |
88cfb3b7e2 | ||
![]() |
53b98543cc | ||
![]() |
5f0546f32e | ||
![]() |
2c04153013 | ||
![]() |
a9db61b371 | ||
![]() |
3cdd2097b6 | ||
![]() |
9d7e353ed3 | ||
![]() |
f4aa1f58c3 | ||
![]() |
ebc81811c0 | ||
![]() |
1e9743dcd6 | ||
![]() |
05bd41c040 | ||
![]() |
f9b24fe5bd | ||
![]() |
6745d6cb9d | ||
![]() |
7ada0ea5b9 | ||
![]() |
48951dbabd | ||
![]() |
7aa9245514 | ||
![]() |
9b06d684cd | ||
![]() |
56f0d6375b |
2
.github/codeql-config.yml
vendored
2
.github/codeql-config.yml
vendored
@ -1,2 +0,0 @@
|
||||
paths-ignore:
|
||||
- "**/tests/**"
|
50
.github/workflows/benchmarks.yml
vendored
50
.github/workflows/benchmarks.yml
vendored
@ -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
|
||||
|
103
.github/workflows/codeql.yml
vendored
103
.github/workflows/codeql.yml
vendored
@ -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}}"
|
32
.github/workflows/integration_tests.yml
vendored
32
.github/workflows/integration_tests.yml
vendored
@ -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
|
||||
|
34
.github/workflows/performance.yml
vendored
34
.github/workflows/performance.yml
vendored
@ -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
2
.gitignore
vendored
@ -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
|
@ -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]
|
||||
|
376
benchmarks/test_benchmark_compile_components.py
Normal file
376
benchmarks/test_benchmark_compile_components.py
Normal 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)
|
579
benchmarks/test_benchmark_compile_pages.py
Normal file
579
benchmarks/test_benchmark_compile_pages.py
Normal 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()
|
@ -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
|
||||
|
||||
|
@ -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) देखें।
|
||||
|
||||
## हमारे सभी योगदानकर्ताओं का धन्यवाद:
|
||||
|
||||
|
@ -222,7 +222,7 @@ app.add_page(index, title="DALL-E")
|
||||
|
||||
<div align="center">
|
||||
|
||||
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) | 🗞️ [Blog](https://reflex.dev/blog) | 📱 [Component Library](https://reflex.dev/docs/library) | 🖼️ [Templates](https://reflex.dev/templates/) | 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start)
|
||||
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) | 🗞️ [Blog](https://reflex.dev/blog) | 📱 [Component Library](https://reflex.dev/docs/library) | 🖼️ [Gallery](https://reflex.dev/docs/gallery) | 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start)
|
||||
|
||||
</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)をご覧ください。
|
||||
|
||||
## 私たちのコントリビュータに感謝!:
|
||||
|
||||
|
@ -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 - با تشکر از همکاران ما:
|
||||
|
@ -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) | 🗞️ [Blog](https://reflex.dev/blog) | 📱 [Component Library](https://reflex.dev/docs/library) | 🖼️ [Templates](https://reflex.dev/templates/) | 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy)
|
||||
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) | 🗞️ [Blog](https://reflex.dev/blog) | 📱 [Component Library](https://reflex.dev/docs/library) | 🖼️ [Gallery](https://reflex.dev/docs/gallery) | 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy)
|
||||
|
||||
</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:
|
||||
|
||||
|
@ -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) | 🗞️ [Blog](https://reflex.dev/blog) | 📱 [Component Library](https://reflex.dev/docs/library) | 🖼️ [Templates](https://reflex.dev/templates/) | 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start)
|
||||
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) | 🗞️ [Blog](https://reflex.dev/blog) | 📱 [Component Library](https://reflex.dev/docs/library) | 🖼️ [Gallery](https://reflex.dev/docs/gallery) | 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start)
|
||||
|
||||
</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:
|
||||
|
@ -229,7 +229,7 @@ app.add_page(index, title="DALL-E")
|
||||
|
||||
<div align="center">
|
||||
|
||||
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) | 🗞️ [Blog](https://reflex.dev/blog) | 📱 [Component Library](https://reflex.dev/docs/library) | 🖼️ [Templates](https://reflex.dev/templates/) | 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start)
|
||||
📑 [Docs](https://reflex.dev/docs/getting-started/introduction) | 🗞️ [Blog](https://reflex.dev/blog) | 📱 [Component Library](https://reflex.dev/docs/library) | 🖼️ [Gallery](https://reflex.dev/docs/gallery) | 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start)
|
||||
|
||||
</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
983
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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"
|
||||
|
||||
|
@ -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 %}
|
||||
}
|
||||
}
|
@ -38,13 +38,13 @@ export default function MyApp({ Component, pageProps }) {
|
||||
}, []);
|
||||
return (
|
||||
<ThemeProvider defaultTheme={ defaultColorMode } attribute="class">
|
||||
<AppWrap>
|
||||
<StateProvider>
|
||||
<EventLoopProvider>
|
||||
<AppWrap>
|
||||
<Component {...pageProps} />
|
||||
</AppWrap>
|
||||
</EventLoopProvider>
|
||||
</StateProvider>
|
||||
</AppWrap>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
@ -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 #}
|
||||
|
@ -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 %}
|
||||
)
|
||||
}
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -13,11 +13,11 @@
|
||||
export default function range(start, stop, step) {
|
||||
return {
|
||||
[Symbol.iterator]() {
|
||||
if (stop === undefined) {
|
||||
if ((stop ?? undefined) === undefined) {
|
||||
stop = start;
|
||||
start = 0;
|
||||
}
|
||||
if (step === undefined) {
|
||||
if ((step ?? undefined) === undefined) {
|
||||
step = 1;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
463
reflex/app.py
463
reflex/app.py
@ -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."]
|
||||
)
|
||||
|
||||
if Toaster.is_used:
|
||||
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
|
||||
) # type: ignore
|
||||
else:
|
||||
error_message.insert(0, "An error occurred.")
|
||||
return window_alert("\n".join(error_message))
|
||||
|
||||
|
||||
def default_overlay_component() -> Component:
|
||||
@ -201,22 +157,12 @@ 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)())
|
||||
|
||||
|
||||
def default_error_boundary(*children: Component) -> Component:
|
||||
"""Default error_boundary attribute for App.
|
||||
@ -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,16 +868,10 @@ 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:
|
||||
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 {state_name}.{dep}"
|
||||
f"ComputedVar {var._js_expr} on state {state.__name__} has an invalid dependency {dep}"
|
||||
)
|
||||
|
||||
for substate in state.class_subclasses:
|
||||
@ -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,16 +910,8 @@ 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()
|
||||
|
||||
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)
|
||||
@ -1106,8 +919,13 @@ class App(MiddlewareMixin, LifespanMixin):
|
||||
# Add the optional endpoints (_upload)
|
||||
self._add_optional_endpoints()
|
||||
|
||||
if not should_compile:
|
||||
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,42 +968,13 @@ 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)
|
||||
|
||||
# Catch "static" apps (that do not define a rx.State subclass) which are trying to access rx.State.
|
||||
@ -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,19 +1077,16 @@ 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)
|
||||
|
||||
# Setup the next.config.js
|
||||
@ -1362,28 +1113,9 @@ 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())
|
||||
|
||||
@contextlib.asynccontextmanager
|
||||
async def modify_state(self, token: str) -> AsyncIterator[BaseState]:
|
||||
"""Modify the state out of band.
|
||||
@ -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__
|
||||
@ -1622,7 +1353,8 @@ 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:
|
||||
return
|
||||
|
||||
# Process the event synchronously.
|
||||
async for update in state._process(event):
|
||||
# Postprocess the event.
|
||||
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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})
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()}"
|
||||
|
@ -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 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,20 +112,12 @@ 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]] = {}
|
||||
|
||||
for field in fields:
|
||||
lib_paths.setdefault(field.package_path, []).append(field)
|
||||
|
||||
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.")
|
||||
@ -136,11 +127,9 @@ def compile_imports(import_dict: ParsedImportDict) -> list[dict]:
|
||||
continue
|
||||
|
||||
# remove the version before rendering the package imports
|
||||
formatted_lib = format.format_library_name(lib) + (
|
||||
path if path != "/" else ""
|
||||
)
|
||||
lib = format.format_library_name(lib)
|
||||
|
||||
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:
|
||||
|
@ -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.
|
||||
|
@ -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,7 +41,9 @@ class Bare(Component):
|
||||
"""
|
||||
hooks = super()._get_all_hooks_internal()
|
||||
if isinstance(self.contents, Var):
|
||||
for component in _components_from_var(self.contents):
|
||||
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
|
||||
|
||||
@ -98,7 +55,9 @@ class Bare(Component):
|
||||
"""
|
||||
hooks = super()._get_all_hooks()
|
||||
if isinstance(self.contents, Var):
|
||||
for component in _components_from_var(self.contents):
|
||||
var_data = self.contents._get_all_var_data()
|
||||
if var_data:
|
||||
for component in var_data.components:
|
||||
hooks |= component._get_all_hooks()
|
||||
return hooks
|
||||
|
||||
@ -126,7 +85,9 @@ class Bare(Component):
|
||||
"""
|
||||
dynamic_imports = super()._get_all_dynamic_imports()
|
||||
if isinstance(self.contents, Var):
|
||||
for component in _components_from_var(self.contents):
|
||||
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
|
||||
|
||||
@ -138,7 +99,9 @@ class Bare(Component):
|
||||
"""
|
||||
custom_code = super()._get_all_custom_code()
|
||||
if isinstance(self.contents, Var):
|
||||
for component in _components_from_var(self.contents):
|
||||
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
|
||||
|
||||
@ -150,7 +113,9 @@ 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):
|
||||
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
|
||||
@ -163,7 +128,9 @@ class Bare(Component):
|
||||
"""
|
||||
refs = super()._get_all_refs()
|
||||
if isinstance(self.contents, Var):
|
||||
for component in _components_from_var(self.contents):
|
||||
var_data = self.contents._get_all_var_data()
|
||||
if var_data:
|
||||
for component in var_data.components:
|
||||
refs |= component._get_all_refs()
|
||||
return refs
|
||||
|
||||
@ -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):
|
||||
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)
|
||||
are_components_touched = True
|
||||
|
||||
if are_components_touched:
|
||||
GLOBAL_CACHE.clear()
|
||||
|
||||
if get_var_caching():
|
||||
set_var_caching(False)
|
||||
str(new_self)
|
||||
set_var_caching(True)
|
||||
return new_self
|
||||
|
||||
def _get_vars(
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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"
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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"
|
@ -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.
|
||||
"""
|
||||
...
|
@ -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
|
||||
|
||||
# Handle subclasses of Base.
|
||||
if isinstance(value, Base):
|
||||
base_value = LiteralVar.create(value)
|
||||
|
||||
# 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)
|
||||
self.props[camel_cased_key] = value
|
||||
setattr(self, camel_cased_key, value)
|
||||
|
||||
@classmethod
|
||||
def _are_fields_known(cls) -> bool:
|
||||
"""Check if the fields are known.
|
||||
|
||||
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,
|
||||
)
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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,7 +208,8 @@ class ConnectionModal(Component):
|
||||
"""
|
||||
if not comp:
|
||||
comp = Text.create(*default_connection_error())
|
||||
return cond(
|
||||
return super().create(
|
||||
cond(
|
||||
has_too_many_connection_errors,
|
||||
DialogRoot.create(
|
||||
DialogContent.create(
|
||||
@ -250,6 +220,7 @@ class ConnectionModal(Component):
|
||||
z_index=9999,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class WifiOffPulse(Icon):
|
||||
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
)
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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]
|
||||
|
@ -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.
|
||||
|
@ -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,23 +17,10 @@ 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."""
|
||||
|
||||
_memoization_mode = MemoizationMode(recursive=False)
|
||||
|
||||
# The iterable to create components from.
|
||||
iterable: Var[Iterable]
|
||||
|
||||
# A function from the render args to the component.
|
||||
render_fn: Callable = Fragment.create
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
def foreach(
|
||||
iterable: Var[Iterable] | Iterable,
|
||||
render_fn: Callable,
|
||||
) -> Foreach:
|
||||
) -> Var:
|
||||
"""Create a foreach component.
|
||||
|
||||
Args:
|
||||
@ -51,121 +32,22 @@ class 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 isinstance(iterable, ObjectVar):
|
||||
iterable = iterable.items()
|
||||
|
||||
if iterable._var_type == Any:
|
||||
if not isinstance(iterable, ArrayVar):
|
||||
raise ForeachVarError(
|
||||
f"Could not foreach over var `{iterable!s}` of type Any. "
|
||||
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/"
|
||||
)
|
||||
|
||||
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,
|
||||
)
|
||||
|
||||
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)
|
||||
|
@ -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.
|
||||
|
@ -1,93 +1,123 @@
|
||||
"""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."""
|
||||
|
||||
# The condition to determine which case to match.
|
||||
cond: Var[Any]
|
||||
|
||||
# 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.
|
||||
def _process_match_cases(cases: tuple[CASE_TYPE[VAR_TYPE], ...]):
|
||||
"""Process the individual match cases.
|
||||
|
||||
Args:
|
||||
cond: The condition to determine which case to match.
|
||||
cases: This list of cases to match.
|
||||
|
||||
Returns:
|
||||
The match component.
|
||||
cases: The match cases.
|
||||
|
||||
Raises:
|
||||
ValueError: When a default case is not provided for cases with Var return types.
|
||||
ValueError: If the default case is not the last case or the tuple elements are less than 2.
|
||||
"""
|
||||
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):
|
||||
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
|
||||
# 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."
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _create_condition_var(cls, cond: Any) -> Var:
|
||||
"""Convert the condition to a Var.
|
||||
|
||||
def _validate_return_types(match_cases: tuple[CASE_TYPE[VAR_TYPE], ...]) -> None:
|
||||
"""Validate that match cases have the same return types.
|
||||
|
||||
Args:
|
||||
cond: The condition.
|
||||
|
||||
Returns:
|
||||
The condition as a base var
|
||||
match_cases: The match cases.
|
||||
|
||||
Raises:
|
||||
ValueError: If the condition is not provided.
|
||||
MatchTypeError: If the return types of cases are different.
|
||||
"""
|
||||
match_cond_var = LiteralVar.create(cond)
|
||||
|
||||
if match_cond_var is None:
|
||||
raise ValueError("The condition must be set")
|
||||
return match_cond_var
|
||||
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]
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _process_cases(
|
||||
cls, cases: List
|
||||
) -> Tuple[List, Optional[Union[Var, BaseComponent]]]:
|
||||
"""Process the list of match cases and the catchall default case.
|
||||
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 _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.
|
||||
|
||||
Args:
|
||||
cases: The list of match cases.
|
||||
match_cond_var: The match condition var.
|
||||
match_cases: The match cases.
|
||||
default: The default case.
|
||||
|
||||
Returns:
|
||||
The default case and the list of match case tuples.
|
||||
The match var.
|
||||
"""
|
||||
return MatchOperation.create(match_cond_var, match_cases, default)
|
||||
|
||||
|
||||
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 there are multiple default cases.
|
||||
ValueError: If the default case is not the last case or the tuple elements are less than 2.
|
||||
"""
|
||||
default = None
|
||||
|
||||
@ -99,176 +129,35 @@ class Match(MemoizationLeaf):
|
||||
|
||||
# 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
|
||||
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)
|
||||
)
|
||||
|
||||
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.
|
||||
|
||||
Args:
|
||||
case_element: The case element.
|
||||
|
||||
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
|
||||
|
||||
@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
|
||||
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()
|
||||
|
||||
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]
|
||||
default = cast(Var[VAR_TYPE] | VAR_TYPE, default)
|
||||
|
||||
return _create_match_var(
|
||||
cond,
|
||||
actual_cases,
|
||||
default,
|
||||
)
|
||||
)
|
||||
|
||||
# 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 render(self) -> Dict:
|
||||
"""Render the component.
|
||||
|
||||
Returns:
|
||||
The dictionary for template of component.
|
||||
"""
|
||||
tag = self._render()
|
||||
tag.name = "match"
|
||||
return dict(tag)
|
||||
|
||||
def add_imports(self) -> ImportDict:
|
||||
"""Add imports for the Match component.
|
||||
|
||||
Returns:
|
||||
The import dict.
|
||||
"""
|
||||
var_data = VarData.merge(self.cond._get_all_var_data())
|
||||
return var_data.old_school_imports() if var_data else {}
|
||||
|
||||
|
||||
match = Match.create
|
||||
|
@ -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
@ -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(
|
||||
|
@ -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.
|
||||
|
@ -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"""
|
||||
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);
|
||||
console.error(`Error importing language module for ${{{language_var!s}}}:`, 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}
|
||||
}}
|
||||
}}
|
||||
"""
|
||||
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:
|
||||
|
@ -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.
|
||||
|
@ -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 (
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
)
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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/).
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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]]
|
||||
|
@ -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.
|
||||
|
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
|
||||
|
@ -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
@ -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
@ -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
@ -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.
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user