Merge branch 'main' into lendemor/fix_duplicate_tab_issue
This commit is contained in:
commit
d2b183e3f9
2
.github/codeql-config.yml
vendored
Normal file
2
.github/codeql-config.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
paths-ignore:
|
||||
- "**/tests/**"
|
58
.github/workflows/benchmarks.yml
vendored
58
.github/workflows/benchmarks.yml
vendored
@ -70,58 +70,6 @@ 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.9.21", "3.10.16", "3.11.11", "3.12.8"]
|
||||
exclude:
|
||||
- os: windows-latest
|
||||
python-version: "3.10.16"
|
||||
- os: windows-latest
|
||||
python-version: "3.9.21"
|
||||
# keep only one python version for MacOS
|
||||
- os: macos-latest
|
||||
python-version: "3.9.21"
|
||||
- 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.9.13"
|
||||
|
||||
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
|
||||
@ -161,7 +109,11 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up python
|
||||
id: setup-python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install Poetry
|
||||
uses: snok/install-poetry@v1
|
||||
with:
|
||||
|
@ -16,7 +16,7 @@ jobs:
|
||||
|
||||
- uses: ./.github/actions/setup_build_env
|
||||
with:
|
||||
python-version: "3.9.21"
|
||||
python-version: '3.10'
|
||||
run-poetry-install: true
|
||||
create-venv-at-path: .venv
|
||||
|
||||
@ -55,7 +55,7 @@ jobs:
|
||||
path: reflex-web
|
||||
- name: Install Requirements for reflex-web
|
||||
working-directory: ./reflex-web
|
||||
run: poetry run uv pip install -r requirements.txt
|
||||
run: poetry run uv pip install $(grep -ivE "reflex " requirements.txt)
|
||||
- name: Install additional dependencies for DB access
|
||||
run: poetry run uv pip install psycopg
|
||||
- name: Init Website for reflex-web
|
||||
@ -73,7 +73,7 @@ jobs:
|
||||
echo "$outdated"
|
||||
|
||||
# Ignore 3rd party dependencies that are not updated.
|
||||
filtered_outdated=$(echo "$outdated" | grep -vE 'Package|@chakra-ui|lucide-react|@splinetool/runtime|ag-grid-react|framer-motion|react-markdown|remark-math|remark-gfm|rehype-katex|rehype-raw|remark-unwrap-images' || true)
|
||||
filtered_outdated=$(echo "$outdated" | grep -vE 'Package|@chakra-ui|lucide-react|@splinetool/runtime|ag-grid-react|framer-motion|react-markdown|remark-math|remark-gfm|rehype-katex|rehype-raw|remark-unwrap-images|ag-grid' || true)
|
||||
no_extra=$(echo "$filtered_outdated" | grep -vE '\|\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-' || true)
|
||||
|
||||
|
||||
|
103
.github/workflows/codeql.yml
vendored
Normal file
103
.github/workflows/codeql.yml
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
# 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}}"
|
11
.github/workflows/integration_app_harness.yml
vendored
11
.github/workflows/integration_app_harness.yml
vendored
@ -47,17 +47,10 @@ jobs:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
run-poetry-install: true
|
||||
create-venv-at-path: .venv
|
||||
- run: poetry run uv pip install pyvirtualdisplay pillow pytest-split
|
||||
- run: poetry run uv pip install pyvirtualdisplay pillow pytest-split pytest-retry
|
||||
- name: Run app harness tests
|
||||
env:
|
||||
SCREENSHOT_DIR: /tmp/screenshots/${{ matrix.state_manager }}/${{ matrix.python-version }}/${{ matrix.split_index }}
|
||||
REDIS_URL: ${{ matrix.state_manager == 'redis' && 'redis://localhost:6379' || '' }}
|
||||
run: |
|
||||
poetry run playwright install chromium
|
||||
poetry run pytest tests/integration --splits 2 --group ${{matrix.split_index}}
|
||||
- uses: actions/upload-artifact@v4
|
||||
name: Upload failed test screenshots
|
||||
if: always()
|
||||
with:
|
||||
name: failed_test_screenshots
|
||||
path: /tmp/screenshots
|
||||
poetry run pytest tests/integration --retries 3 --maxfail=5 --splits 2 --group ${{matrix.split_index}}
|
||||
|
67
.github/workflows/integration_tests.yml
vendored
67
.github/workflows/integration_tests.yml
vendored
@ -33,7 +33,7 @@ env:
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
|
||||
jobs:
|
||||
example-counter:
|
||||
example-counter-and-nba-proxy:
|
||||
env:
|
||||
OUTPUT_FILE: import_benchmark.json
|
||||
timeout-minutes: 30
|
||||
@ -43,22 +43,17 @@ jobs:
|
||||
matrix:
|
||||
# Show OS combos first in GUI
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
python-version: ["3.9.21", "3.10.16", "3.11.11", "3.12.8", "3.13.1"]
|
||||
# Windows is a bit behind on Python version availability in Github
|
||||
python-version: ['3.10.16', '3.11.11', '3.12.8', '3.13.1']
|
||||
exclude:
|
||||
- os: windows-latest
|
||||
python-version: "3.11.11"
|
||||
- os: windows-latest
|
||||
python-version: "3.10.16"
|
||||
- os: windows-latest
|
||||
python-version: "3.9.21"
|
||||
python-version: '3.10.16'
|
||||
include:
|
||||
- os: windows-latest
|
||||
python-version: "3.11.9"
|
||||
- os: windows-latest
|
||||
python-version: "3.10.11"
|
||||
- os: windows-latest
|
||||
python-version: "3.9.13"
|
||||
python-version: '3.10.11'
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
@ -84,8 +79,6 @@ jobs:
|
||||
run: |
|
||||
poetry run reflex export --backend-only
|
||||
- name: Check run --backend-only before init for counter example
|
||||
env:
|
||||
WAIT_FOR_LISTENING_PORT_ARGS: --path ping
|
||||
run: |
|
||||
poetry run bash scripts/integration.sh ./reflex-examples/counter dev 8001 --backend-only --backend-port 8001
|
||||
- name: Init Website for counter example
|
||||
@ -101,26 +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: |
|
||||
poetry run uv pip install -r requirements.txt
|
||||
- name: Install additional dependencies for DB access
|
||||
run: poetry run uv pip install psycopg
|
||||
- name: Check export --backend-only before init for nba-proxy example
|
||||
working-directory: ./reflex-examples/nba-proxy
|
||||
run: |
|
||||
poetry run reflex export --backend-only
|
||||
- name: Init Website for nba-proxy example
|
||||
working-directory: ./reflex-examples/nba-proxy
|
||||
run: |
|
||||
poetry run reflex init --loglevel debug
|
||||
- name: Run Website and Check for errors
|
||||
run: |
|
||||
# Check that npm is home
|
||||
npm -v
|
||||
poetry run bash scripts/integration.sh ./reflex-examples/nba-proxy dev
|
||||
|
||||
|
||||
reflex-web:
|
||||
strategy:
|
||||
@ -161,12 +154,6 @@ 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:
|
||||
@ -230,9 +217,3 @@ 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
|
||||
|
1
.github/workflows/integration_tests_wsl.yml
vendored
1
.github/workflows/integration_tests_wsl.yml
vendored
@ -78,7 +78,6 @@ jobs:
|
||||
shell: wsl-bash {0}
|
||||
run: |
|
||||
export TELEMETRY_ENABLED=false
|
||||
export WAIT_FOR_LISTENING_PORT_ARGS="--path ping"
|
||||
dos2unix scripts/integration.sh
|
||||
poetry run bash scripts/integration.sh ./reflex-examples/counter dev 8001 --backend-only --backend-port 8001
|
||||
- name: Init Website for counter example
|
||||
|
34
.github/workflows/performance.yml
vendored
Normal file
34
.github/workflows/performance.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
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
|
10
.github/workflows/unit_tests.yml
vendored
10
.github/workflows/unit_tests.yml
vendored
@ -28,22 +28,18 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
python-version: ["3.9.21", "3.10.16", "3.11.11", "3.12.8", "3.13.1"]
|
||||
python-version: ["3.10.16", "3.11.11", "3.12.8", "3.13.1"]
|
||||
# Windows is a bit behind on Python version availability in Github
|
||||
exclude:
|
||||
- os: windows-latest
|
||||
python-version: "3.11.11"
|
||||
- os: windows-latest
|
||||
python-version: "3.10.16"
|
||||
- os: windows-latest
|
||||
python-version: "3.9.21"
|
||||
include:
|
||||
- os: windows-latest
|
||||
python-version: "3.11.9"
|
||||
- os: windows-latest
|
||||
python-version: "3.10.11"
|
||||
- os: windows-latest
|
||||
python-version: "3.9.13"
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
# Service containers to run with `runner-job`
|
||||
@ -92,8 +88,8 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Note: py39, py310, py311 versions chosen due to available arm64 darwin builds.
|
||||
python-version: ["3.9.13", "3.10.11", "3.11.9", "3.12.8", "3.13.1"]
|
||||
# Note: py310, py311 versions chosen due to available arm64 darwin builds.
|
||||
python-version: ["3.10.11", "3.11.9", "3.12.8", "3.13.1"]
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,6 +4,7 @@ assets/external/*
|
||||
dist/*
|
||||
examples/
|
||||
.web
|
||||
.states
|
||||
.idea
|
||||
.vscode
|
||||
.coverage
|
||||
@ -14,3 +15,4 @@ 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.8.2
|
||||
rev: v0.9.6
|
||||
hooks:
|
||||
- id: ruff-format
|
||||
args: [reflex, tests]
|
||||
@ -24,11 +24,12 @@ 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.313
|
||||
rev: v1.1.393
|
||||
hooks:
|
||||
- id: pyright
|
||||
args: [reflex, tests]
|
||||
|
@ -8,7 +8,7 @@ Here is a quick guide on how to run Reflex repo locally so you can start contrib
|
||||
|
||||
**Prerequisites:**
|
||||
|
||||
- Python >= 3.9
|
||||
- Python >= 3.10
|
||||
- Poetry version >= 1.4.0 and add it to your path (see [Poetry Docs](https://python-poetry.org/docs/#installation) for more info).
|
||||
|
||||
**1. Fork this repository:**
|
||||
@ -87,7 +87,7 @@ poetry run ruff format .
|
||||
```
|
||||
|
||||
Consider installing git pre-commit hooks so Ruff, Pyright, Darglint and `make_pyi` will run automatically before each commit.
|
||||
Note that pre-commit will only be installed when you use a Python version >= 3.9.
|
||||
Note that pre-commit will only be installed when you use a Python version >= 3.10.
|
||||
|
||||
``` bash
|
||||
pre-commit install
|
||||
|
@ -34,7 +34,7 @@ See our [architecture page](https://reflex.dev/blog/2024-03-21-reflex-architectu
|
||||
|
||||
## ⚙️ Installation
|
||||
|
||||
Open a terminal and run (Requires Python 3.9+):
|
||||
Open a terminal and run (Requires Python 3.10+):
|
||||
|
||||
```bash
|
||||
pip install reflex
|
||||
|
@ -21,7 +21,7 @@ def get_package_size(venv_path: Path, os_name):
|
||||
ValueError: when venv does not exist or python version is None.
|
||||
"""
|
||||
python_version = get_python_version(venv_path, os_name)
|
||||
print("Python version:", python_version) # noqa: T201
|
||||
print("Python version:", python_version)
|
||||
if python_version is None:
|
||||
raise ValueError("Error: Failed to determine Python version.")
|
||||
|
||||
|
@ -1,376 +0,0 @@
|
||||
"""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)
|
@ -1,579 +0,0 @@
|
||||
"""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()
|
@ -34,7 +34,7 @@ Auf unserer [Architektur-Seite](https://reflex.dev/blog/2024-03-21-reflex-archit
|
||||
|
||||
## ⚙️ Installation
|
||||
|
||||
Öffne ein Terminal und führe den folgenden Befehl aus (benötigt Python 3.9+):
|
||||
Öffne ein Terminal und führe den folgenden Befehl aus (benötigt Python 3.10+):
|
||||
|
||||
```bash
|
||||
pip install reflex
|
||||
|
@ -35,7 +35,7 @@ Consulta nuestra [página de arquitectura](https://reflex.dev/blog/2024-03-21-re
|
||||
|
||||
## ⚙️ Instalación
|
||||
|
||||
Abra un terminal y ejecute (Requiere Python 3.9+):
|
||||
Abra un terminal y ejecute (Requiere Python 3.10+):
|
||||
|
||||
```bash
|
||||
pip install reflex
|
||||
@ -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 [CONTIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
|
||||
Buscamos colaboradores, sin importar su nivel o experiencia. Para contribuir consulta [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
|
||||
|
||||
## Licencia
|
||||
|
||||
|
@ -35,7 +35,7 @@ Reflex के अंदर के कामकाज को जानने क
|
||||
|
||||
## ⚙️ इंस्टॉलेशन (Installation)
|
||||
|
||||
एक टर्मिनल खोलें और चलाएं (Python 3.9+ की आवश्यकता है):
|
||||
एक टर्मिनल खोलें और चलाएं (Python 3.10+ की आवश्यकता है):
|
||||
|
||||
```bash
|
||||
pip install reflex
|
||||
@ -239,7 +239,7 @@ Reflex में हर सप्ताह नए रिलीज़ और फ
|
||||
- **GitHub Discussions** (गिटहब चर्चाएँ): उन सुविधाओं के बारे में बात करने का एक शानदार तरीका जिन्हें आप जोड़ना चाहते हैं या ऐसी चीज़ें जो भ्रमित करने वाली हैं/स्पष्टीकरण की आवश्यकता है।
|
||||
- **GitHub Issues** (गिटहब समस्याएं): ये [बग](https://github.com/reflex-dev/reflex/issues) की रिपोर्ट करने का एक शानदार तरीका है। इसके अतिरिक्त, आप किसी मौजूदा समस्या को हल करने का प्रयास कर सकते हैं और एक पीआर सबमिट कर सकते हैं।
|
||||
|
||||
हम सक्रिय रूप से योगदानकर्ताओं की तलाश कर रहे हैं, चाहे आपका कौशल स्तर या अनुभव कुछ भी हो।योगदान करने के लिए [CONTIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) देखें।
|
||||
हम सक्रिय रूप से योगदानकर्ताओं की तलाश कर रहे हैं, चाहे आपका कौशल स्तर या अनुभव कुछ भी हो।योगदान करने के लिए [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) देखें।
|
||||
|
||||
## हमारे सभी योगदानकर्ताओं का धन्यवाद:
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
## ⚙️ Installazione
|
||||
|
||||
Apri un terminale ed esegui (Richiede Python 3.9+):
|
||||
Apri un terminale ed esegui (Richiede Python 3.10+):
|
||||
|
||||
```bash
|
||||
pip install reflex
|
||||
|
@ -37,7 +37,7 @@ Reflex がどのように動作しているかを知るには、[アーキテク
|
||||
|
||||
## ⚙️ インストール
|
||||
|
||||
ターミナルを開いて以下のコマンドを実行してください。(Python 3.9 以上が必要です。):
|
||||
ターミナルを開いて以下のコマンドを実行してください。(Python 3.10 以上が必要です。):
|
||||
|
||||
```bash
|
||||
pip install reflex
|
||||
@ -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) | 🖼️ [Gallery](https://reflex.dev/docs/gallery) | 🛸 [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) | 🖼️ [Templates](https://reflex.dev/templates/) | 🛸 [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 のサブミットにチャレンジしていただくことも、可能です。
|
||||
|
||||
スキルや経験に関わらず、私たちはコントリビュータを積極的に探しています。コントリビュートするために、[CONTIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)をご覧ください。
|
||||
CONTスキルや経験に関わらず、私たちはコントリビュータを積極的に探しています。コントリビュートするために、[CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)をご覧ください。
|
||||
|
||||
## 私たちのコントリビュータに感謝!:
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
---
|
||||
## ⚙️ 설치
|
||||
|
||||
터미널을 열고 실행하세요. (Python 3.9+ 필요):
|
||||
터미널을 열고 실행하세요. (Python 3.10+ 필요):
|
||||
|
||||
```bash
|
||||
pip install reflex
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
## ⚙️ Installation - نصب و راه اندازی
|
||||
|
||||
یک ترمینال را باز کنید و اجرا کنید (نیازمند Python 3.9+):
|
||||
یک ترمینال را باز کنید و اجرا کنید (نیازمند Python 3.10+):
|
||||
|
||||
```bash
|
||||
pip install reflex
|
||||
@ -249,7 +249,7 @@ app.add_page(index, title="DALL-E")
|
||||
- **بحث های GitHub**: راهی عالی برای صحبت در مورد ویژگی هایی که می خواهید اضافه کنید یا چیزهایی که گیج کننده هستند/نیاز به توضیح دارند.
|
||||
- **قسمت مشکلات GitHub**: [قسمت مشکلات](https://github.com/reflex-dev/reflex/issues) یک راه عالی برای گزارش اشکال هستند. علاوه بر این، می توانید یک مشکل موجود را حل کنید و یک PR(pull request) ارسال کنید.
|
||||
|
||||
ما فعالانه به دنبال مشارکت کنندگان هستیم، فارغ از سطح مهارت یا تجربه شما. برای مشارکت [CONTIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) را بررسی کنید.
|
||||
ما فعالانه به دنبال مشارکت کنندگان هستیم، فارغ از سطح مهارت یا تجربه شما. برای مشارکت [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) را بررسی کنید.
|
||||
|
||||
|
||||
## All Thanks To Our Contributors - با تشکر از همکاران ما:
|
||||
|
@ -21,7 +21,7 @@
|
||||
---
|
||||
## ⚙️ Instalação
|
||||
|
||||
Abra um terminal e execute (Requer Python 3.9+):
|
||||
Abra um terminal e execute (Requer Python 3.10+):
|
||||
|
||||
```bash
|
||||
pip install reflex
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
## ⚙️ Kurulum
|
||||
|
||||
Bir terminal açın ve çalıştırın (Python 3.9+ gerekir):
|
||||
Bir terminal açın ve çalıştırın (Python 3.10+ gerekir):
|
||||
|
||||
```bash
|
||||
pip install reflex
|
||||
@ -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) | 🖼️ [Gallery](https://reflex.dev/docs/gallery) | 🛸 [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) | 🖼️ [Templates](https://reflex.dev/templates/) | 🛸 [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: [CONTIBUTING.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: [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
|
||||
|
||||
## Hepsi Katkıda Bulunanlar Sayesinde:
|
||||
|
||||
|
@ -34,7 +34,7 @@ Các tính năng chính:
|
||||
|
||||
## ⚙️ Cài đặt
|
||||
|
||||
Mở cửa sổ lệnh và chạy (Yêu cầu Python phiên bản 3.9+):
|
||||
Mở cửa sổ lệnh và chạy (Yêu cầu Python phiên bản 3.10+):
|
||||
|
||||
```bash
|
||||
pip install reflex
|
||||
@ -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) | 🖼️ [Gallery](https://reflex.dev/docs/gallery) | 🛸 [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) | 🖼️ [Templates](https://reflex.dev/templates/) | 🛸 [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
|
||||
[CONTIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
|
||||
[CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
|
||||
|
||||
|
||||
## Xin cảm ơn các Contributors:
|
||||
|
@ -34,7 +34,7 @@ Reflex 是一个使用纯Python构建全栈web应用的库。
|
||||
|
||||
## ⚙️ 安装
|
||||
|
||||
打开一个终端并且运行(要求Python3.9+):
|
||||
打开一个终端并且运行(要求Python3.10+):
|
||||
|
||||
```bash
|
||||
pip install reflex
|
||||
|
@ -36,7 +36,7 @@ Reflex 是一個可以用純 Python 構建全端網頁應用程式的函式庫
|
||||
|
||||
## ⚙️ 安裝
|
||||
|
||||
開啟一個終端機並且執行 (需要 Python 3.9+):
|
||||
開啟一個終端機並且執行 (需要 Python 3.10+):
|
||||
|
||||
```bash
|
||||
pip install reflex
|
||||
@ -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) | 🖼️ [Gallery](https://reflex.dev/docs/gallery) | 🛸 [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) | 🖼️ [Templates](https://reflex.dev/templates/) | 🛸 [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。
|
||||
|
||||
我們積極尋找貢獻者,不論您的技能水平或經驗如何。要貢獻,請查看 [CONTIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
|
||||
我們積極尋找貢獻者,不論您的技能水平或經驗如何。要貢獻,請查看 [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
|
||||
|
||||
|
||||
## 感謝所有貢獻者:
|
||||
|
2638
poetry.lock
generated
2638
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "reflex"
|
||||
version = "0.6.8dev1"
|
||||
version = "0.7.1dev1"
|
||||
description = "Web apps in pure Python."
|
||||
license = "Apache-2.0"
|
||||
authors = [
|
||||
@ -18,30 +18,27 @@ keywords = ["web", "framework"]
|
||||
classifiers = ["Development Status :: 4 - Beta"]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.9"
|
||||
python = ">=3.10, <4.0"
|
||||
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.2,<3.0"
|
||||
pydantic = ">=1.10.21,<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.4.2,<1.0"
|
||||
typer = ">=0.15.1,<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 = [
|
||||
{ version = ">=1.14.0,<2.0", python = ">=3.11" },
|
||||
{ version = ">=1.11.0,<2.0", python = "<3.11" },
|
||||
]
|
||||
wrapt = ">=1.17.0,<2.0"
|
||||
packaging = ">=23.1,<25.0"
|
||||
reflex-hosting-cli = ">=0.1.29,<2.0"
|
||||
reflex-hosting-cli = ">=0.1.29"
|
||||
charset-normalizer = ">=3.3.2,<4.0"
|
||||
wheel = ">=0.42.0,<1.0"
|
||||
build = ">=1.0.3,<2.0"
|
||||
@ -49,21 +46,19 @@ setuptools = ">=75.0"
|
||||
httpx = ">=0.25.1,<1.0"
|
||||
twine = ">=4.0.0,<7.0"
|
||||
tomlkit = ">=0.12.4,<1.0"
|
||||
asgiproxy = { version = "==0.1.1", optional = true }
|
||||
lazy_loader = ">=0.4"
|
||||
reflex-chakra = ">=0.6.0"
|
||||
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.229,<1.1.335"
|
||||
pyright = ">=1.1.394, <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.8.2"
|
||||
ruff = "0.9.6"
|
||||
pandas = ">=2.1.1,<3.0"
|
||||
pillow = ">=10.0.0,<12.0"
|
||||
plotly = ">=5.13.0,<6.0"
|
||||
@ -73,39 +68,70 @@ selenium = ">=4.11.0,<5.0"
|
||||
pytest-benchmark = ">=4.0.0,<6.0"
|
||||
playwright = ">=1.46.0"
|
||||
pytest-playwright = ">=0.5.1"
|
||||
asgiproxy = "==0.1.1"
|
||||
pytest-codspeed = "^3.1.2"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
reflex = "reflex.reflex:cli"
|
||||
|
||||
[tool.poetry.extras]
|
||||
proxy = ["asgiproxy"]
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.5.1"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.pyright]
|
||||
reportIncompatibleMethodOverride = false
|
||||
|
||||
[tool.ruff]
|
||||
target-version = "py39"
|
||||
target-version = "py310"
|
||||
output-format = "concise"
|
||||
lint.isort.split-on-trailing-comma = false
|
||||
lint.select = ["B", "C4", "D", "E", "ERA", "F", "FURB", "I", "PERF", "PTH", "RUF", "SIM", "T", "W"]
|
||||
lint.ignore = ["B008", "D205", "E501", "F403", "SIM115", "RUF006", "RUF012"]
|
||||
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.pydocstyle.convention = "google"
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"__init__.py" = ["F401"]
|
||||
"tests/*.py" = ["D100", "D103", "D104", "B018", "PERF", "T"]
|
||||
"tests/*.py" = ["ANN001", "D100", "D103", "D104", "B018", "PERF", "T", "N"]
|
||||
"benchmarks/*.py" = ["ANN001", "D100", "D103", "D104", "B018", "PERF", "T", "N"]
|
||||
"reflex/.templates/*.py" = ["D100", "D103", "D104"]
|
||||
"*.pyi" = ["D301", "D415", "D417", "D418", "E742"]
|
||||
"*.pyi" = ["D301", "D415", "D417", "D418", "E742", "N", "PGH"]
|
||||
"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"
|
||||
|
||||
[tool.codespell]
|
||||
skip = "docs/*,*.html,examples/*, *.pyi"
|
||||
ignore-words-list = "te, TreeE"
|
||||
skip = "docs/*,*.html,examples/*, *.pyi, poetry.lock"
|
||||
ignore-words-list = "te, TreeE"
|
||||
|
@ -8,7 +8,7 @@ version = "0.0.1"
|
||||
description = "Reflex custom component {{ module_name }}"
|
||||
readme = "README.md"
|
||||
license = { text = "Apache-2.0" }
|
||||
requires-python = ">=3.9"
|
||||
requires-python = ">=3.10"
|
||||
authors = [{ name = "", email = "YOUREMAIL@domain.com" }]
|
||||
keywords = ["reflex","reflex-custom-components"]
|
||||
|
||||
|
@ -38,13 +38,13 @@ export default function MyApp({ Component, pageProps }) {
|
||||
}, []);
|
||||
return (
|
||||
<ThemeProvider defaultTheme={ defaultColorMode } attribute="class">
|
||||
<AppWrap>
|
||||
<StateProvider>
|
||||
<EventLoopProvider>
|
||||
<Component {...pageProps} />
|
||||
</EventLoopProvider>
|
||||
</StateProvider>
|
||||
</AppWrap>
|
||||
<StateProvider>
|
||||
<EventLoopProvider>
|
||||
<AppWrap>
|
||||
<Component {...pageProps} />
|
||||
</AppWrap>
|
||||
</EventLoopProvider>
|
||||
</StateProvider>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@
|
||||
{# Args: #}
|
||||
{# component: component dictionary #}
|
||||
{% macro render_iterable_tag(component) %}
|
||||
<>{ {%- if component.iterable_type == 'dict' -%}Object.entries({{- component.iterable_state }}){%- else -%}{{- component.iterable_state }}{%- endif -%}.map(({{ component.arg_name }}, {{ component.arg_index }}) => (
|
||||
<>{ {{ component.iterable_state }}.map(({{ component.arg_name }}, {{ component.arg_index }}) => (
|
||||
{% for child in component.children %}
|
||||
{{ render(child) }}
|
||||
{% endfor %}
|
||||
@ -86,11 +86,11 @@
|
||||
{% for condition in case[:-1] %}
|
||||
case JSON.stringify({{ condition._js_expr }}):
|
||||
{% endfor %}
|
||||
return {{ case[-1] }};
|
||||
return {{ render(case[-1]) }};
|
||||
break;
|
||||
{% endfor %}
|
||||
default:
|
||||
return {{ component.default }};
|
||||
return {{ render(component.default) }};
|
||||
break;
|
||||
}
|
||||
})()
|
||||
|
@ -10,16 +10,15 @@ import {
|
||||
export default function RadixThemesColorModeProvider({ children }) {
|
||||
const { theme, resolvedTheme, setTheme } = useTheme();
|
||||
const [rawColorMode, setRawColorMode] = useState(defaultColorMode);
|
||||
const [resolvedColorMode, setResolvedColorMode] = useState("dark");
|
||||
const [resolvedColorMode, setResolvedColorMode] = useState(
|
||||
defaultColorMode === "dark" ? "dark" : "light"
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDevMode) {
|
||||
const lastCompiledTimeInLocalStorage =
|
||||
localStorage.getItem("last_compiled_time");
|
||||
if (
|
||||
lastCompiledTimeInLocalStorage &&
|
||||
lastCompiledTimeInLocalStorage !== lastCompiledTimeStamp
|
||||
) {
|
||||
if (lastCompiledTimeInLocalStorage !== lastCompiledTimeStamp) {
|
||||
// on app startup, make sure the application color mode is persisted correctly.
|
||||
setTheme(defaultColorMode);
|
||||
localStorage.setItem("last_compiled_time", lastCompiledTimeStamp);
|
||||
|
@ -3,6 +3,7 @@ import axios from "axios";
|
||||
import io from "socket.io-client";
|
||||
import JSON5 from "json5";
|
||||
import env from "$/env.json";
|
||||
import reflexEnvironment from "$/reflex.json";
|
||||
import Cookies from "universal-cookie";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import Router, { useRouter } from "next/router";
|
||||
@ -105,6 +106,18 @@ 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.
|
||||
*
|
||||
@ -404,11 +417,19 @@ export const connect = async (
|
||||
socket.current = io(endpoint.href, {
|
||||
path: endpoint["pathname"],
|
||||
transports: transports,
|
||||
protocols: [reflexEnvironment.version],
|
||||
autoUnref: false,
|
||||
query: { token: getToken() },
|
||||
});
|
||||
// Ensure undefined fields in events are sent as null instead of removed
|
||||
socket.current.io.encoder.replacer = (k, v) => (v === undefined ? null : v);
|
||||
socket.current.io.decoder.tryParse = (str) => {
|
||||
try {
|
||||
return JSON5.parse(str);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
function checkVisibility() {
|
||||
if (document.visibilityState === "visible") {
|
||||
@ -801,14 +822,10 @@ export const useEventLoop = (
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Main event loop.
|
||||
// Handle socket connect/disconnect.
|
||||
useEffect(() => {
|
||||
// Skip if the router is not ready.
|
||||
if (!router.isReady) {
|
||||
return;
|
||||
}
|
||||
// only use websockets if state is present
|
||||
if (Object.keys(initialState).length > 1) {
|
||||
// only use websockets if state is present and backend is not disabled (reflex cloud).
|
||||
if (Object.keys(initialState).length > 1 && !isBackendDisabled()) {
|
||||
// Initialize the websocket connection.
|
||||
if (!socket.current) {
|
||||
connect(
|
||||
@ -819,13 +836,28 @@ export const useEventLoop = (
|
||||
client_storage
|
||||
);
|
||||
}
|
||||
(async () => {
|
||||
// Process all outstanding events.
|
||||
while (event_queue.length > 0 && !event_processing) {
|
||||
await processEvent(socket.current);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
// Cleanup function.
|
||||
return () => {
|
||||
if (socket.current) {
|
||||
socket.current.disconnect();
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Main event loop.
|
||||
useEffect(() => {
|
||||
// Skip if the router is not ready.
|
||||
if (!router.isReady || isBackendDisabled()) {
|
||||
return;
|
||||
}
|
||||
(async () => {
|
||||
// Process all outstanding events.
|
||||
while (event_queue.length > 0 && !event_processing) {
|
||||
await processEvent(socket.current);
|
||||
}
|
||||
})();
|
||||
});
|
||||
|
||||
// localStorage event handling
|
||||
|
@ -84,6 +84,9 @@ 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,
|
||||
@ -245,6 +248,7 @@ COMPONENTS_CORE_MAPPING: dict = {
|
||||
"selected_files",
|
||||
"upload",
|
||||
],
|
||||
"components.core.auto_scroll": ["auto_scroll"],
|
||||
}
|
||||
|
||||
COMPONENTS_BASE_MAPPING: dict = {
|
||||
@ -303,7 +307,6 @@ _MAPPING: dict = {
|
||||
"event": [
|
||||
"EventChain",
|
||||
"EventHandler",
|
||||
"background",
|
||||
"call_script",
|
||||
"call_function",
|
||||
"run_script",
|
||||
@ -366,20 +369,5 @@ getattr, __dir__, __all__ = lazy_loader.attach(
|
||||
)
|
||||
|
||||
|
||||
def __getattr__(name):
|
||||
if name == "chakra":
|
||||
from reflex.utils import console
|
||||
|
||||
console.deprecate(
|
||||
"rx.chakra",
|
||||
reason="and moved to a separate package. "
|
||||
"To continue using Chakra UI components, install the `reflex-chakra` package via `pip install "
|
||||
"reflex-chakra`.",
|
||||
deprecation_version="0.6.0",
|
||||
removal_version="0.7.0",
|
||||
dedupe=True,
|
||||
)
|
||||
import reflex_chakra as rc
|
||||
|
||||
return rc
|
||||
def __getattr__(name: ModuleType | Any):
|
||||
return getattr(name)
|
||||
|
@ -34,6 +34,7 @@ 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
|
||||
@ -131,7 +132,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
|
||||
from .components.radix.themes.layout.list import list_ns as list # noqa: F401
|
||||
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
|
||||
@ -156,7 +157,6 @@ from .constants import Env as Env
|
||||
from .constants.colors import Color as Color
|
||||
from .event import EventChain as EventChain
|
||||
from .event import EventHandler as EventHandler
|
||||
from .event import background as background
|
||||
from .event import call_function as call_function
|
||||
from .event import call_script as call_script
|
||||
from .event import clear_local_storage as clear_local_storage
|
||||
|
708
reflex/app.py
708
reflex/app.py
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@ from typing import Callable, Coroutine, Set, Union
|
||||
from fastapi import FastAPI
|
||||
|
||||
from reflex.utils import console
|
||||
from reflex.utils.exceptions import InvalidLifespanTaskType
|
||||
from reflex.utils.exceptions import InvalidLifespanTaskTypeError
|
||||
|
||||
from .mixin import AppMixin
|
||||
|
||||
@ -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}}" # type: ignore
|
||||
run_msg = f"Started lifespan task: {task.__name__} as {{type}}" # pyright: ignore [reportAttributeAccessIssue]
|
||||
if isinstance(task, asyncio.Task):
|
||||
running_tasks.append(task)
|
||||
else:
|
||||
@ -61,19 +61,19 @@ class LifespanMixin(AppMixin):
|
||||
|
||||
Args:
|
||||
task: The task to register.
|
||||
task_kwargs: The kwargs of the task.
|
||||
**task_kwargs: The kwargs of the task.
|
||||
|
||||
Raises:
|
||||
InvalidLifespanTaskType: If the task is a generator function.
|
||||
InvalidLifespanTaskTypeError: If the task is a generator function.
|
||||
"""
|
||||
if inspect.isgeneratorfunction(task) or inspect.isasyncgenfunction(task):
|
||||
raise InvalidLifespanTaskType(
|
||||
raise InvalidLifespanTaskTypeError(
|
||||
f"Task {task.__name__} of type generator must be decorated with contextlib.asynccontextmanager."
|
||||
)
|
||||
|
||||
if task_kwargs:
|
||||
original_task = task
|
||||
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
|
||||
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]
|
||||
|
@ -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) # type: ignore
|
||||
out = await middleware.preprocess(app=self, state=state, event=event) # pyright: ignore [reportArgumentType]
|
||||
else:
|
||||
out = middleware.preprocess(app=self, state=state, event=event) # type: ignore
|
||||
out = middleware.preprocess(app=self, state=state, event=event) # pyright: ignore [reportArgumentType]
|
||||
if out is not None:
|
||||
return out # type: ignore
|
||||
return out # pyright: ignore [reportReturnType]
|
||||
|
||||
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, # type: ignore
|
||||
app=self, # pyright: ignore [reportArgumentType]
|
||||
state=state,
|
||||
event=event,
|
||||
update=update,
|
||||
)
|
||||
else:
|
||||
out = middleware.postprocess(
|
||||
app=self, # type: ignore
|
||||
app=self, # pyright: ignore [reportArgumentType]
|
||||
state=state,
|
||||
event=event,
|
||||
update=update,
|
||||
)
|
||||
if out is not None:
|
||||
return out # type: ignore
|
||||
return out # pyright: ignore [reportReturnType]
|
||||
return update
|
||||
|
@ -5,16 +5,13 @@ Only the app attribute is explicitly exposed.
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
from reflex import constants
|
||||
from reflex.utils import telemetry
|
||||
from reflex.utils.exec import is_prod_mode
|
||||
from reflex.utils.prerequisites import get_app
|
||||
from reflex.utils.prerequisites import get_and_validate_app
|
||||
|
||||
if constants.CompileVars.APP != "app":
|
||||
raise AssertionError("unexpected variable name for 'app'")
|
||||
|
||||
telemetry.send("compile")
|
||||
app_module = get_app(reload=False)
|
||||
app = getattr(app_module, constants.CompileVars.APP)
|
||||
app, app_module = get_and_validate_app(reload=False)
|
||||
# For py3.9 compatibility when redis is used, we MUST add any decorator pages
|
||||
# before compiling the app in a thread to avoid event loop error (REF-2172).
|
||||
app._apply_decorated_pages()
|
||||
@ -30,8 +27,7 @@ if is_prod_mode():
|
||||
# ensure only "app" is exposed.
|
||||
del app_module
|
||||
del compile_future
|
||||
del get_app
|
||||
del get_and_validate_app
|
||||
del is_prod_mode
|
||||
del telemetry
|
||||
del constants
|
||||
del ThreadPoolExecutor
|
||||
|
@ -5,15 +5,9 @@ from __future__ import annotations
|
||||
import os
|
||||
from typing import TYPE_CHECKING, Any, List, Type
|
||||
|
||||
try:
|
||||
import pydantic.v1.main as pydantic_main
|
||||
from pydantic.v1 import BaseModel
|
||||
from pydantic.v1.fields import ModelField
|
||||
except ModuleNotFoundError:
|
||||
if not TYPE_CHECKING:
|
||||
import pydantic.main as pydantic_main
|
||||
from pydantic import BaseModel
|
||||
from pydantic.fields import ModelField # type: ignore
|
||||
import pydantic.v1.main as pydantic_main
|
||||
from pydantic.v1 import BaseModel
|
||||
from pydantic.v1.fields import ModelField
|
||||
|
||||
|
||||
def validate_field_name(bases: List[Type["BaseModel"]], field_name: str) -> None:
|
||||
@ -44,13 +38,13 @@ 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 # type: ignore
|
||||
pydantic_main.validate_field_name = validate_field_name # pyright: ignore [reportPossiblyUnboundVariable, reportPrivateImportUsage]
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from reflex.vars import Var
|
||||
|
||||
|
||||
class Base(BaseModel): # pyright: ignore [reportUnboundVariable]
|
||||
class Base(BaseModel):
|
||||
"""The base class subclassed by all Reflex classes.
|
||||
|
||||
This class wraps Pydantic and provides common methods such as
|
||||
@ -75,12 +69,12 @@ class Base(BaseModel): # pyright: ignore [reportUnboundVariable]
|
||||
"""
|
||||
from reflex.utils.serializers import serialize
|
||||
|
||||
return self.__config__.json_dumps( # type: ignore
|
||||
return self.__config__.json_dumps(
|
||||
self.dict(),
|
||||
default=serialize,
|
||||
)
|
||||
|
||||
def set(self, **kwargs):
|
||||
def set(self, **kwargs: Any):
|
||||
"""Set multiple fields and return the object.
|
||||
|
||||
Args:
|
||||
@ -113,12 +107,12 @@ class Base(BaseModel): # pyright: ignore [reportUnboundVariable]
|
||||
default_value: The default value of the field
|
||||
"""
|
||||
var_name = var._var_field_name
|
||||
new_field = ModelField.infer(
|
||||
new_field = ModelField.infer( # pyright: ignore [reportPossiblyUnboundVariable]
|
||||
name=var_name,
|
||||
value=default_value,
|
||||
annotation=var._var_type,
|
||||
class_validators=None,
|
||||
config=cls.__config__, # type: ignore
|
||||
config=cls.__config__,
|
||||
)
|
||||
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, Tuple, Type, Union
|
||||
from typing import TYPE_CHECKING, Dict, Iterable, Optional, Sequence, Tuple, Type, Union
|
||||
|
||||
from reflex import constants
|
||||
from reflex.compiler import templates, utils
|
||||
@ -78,6 +78,7 @@ 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(),
|
||||
)
|
||||
|
||||
|
||||
@ -239,11 +240,19 @@ 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,
|
||||
)
|
||||
@ -499,7 +508,7 @@ def compile_tailwind(
|
||||
The compiled Tailwind config.
|
||||
"""
|
||||
# Get the path for the output file.
|
||||
output_path = get_web_dir() / constants.Tailwind.CONFIG
|
||||
output_path = str((get_web_dir() / constants.Tailwind.CONFIG).absolute())
|
||||
|
||||
# Compile the config.
|
||||
code = _compile_tailwind(config)
|
||||
@ -536,7 +545,47 @@ def purge_web_pages_dir():
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from reflex.app import UnevaluatedPage
|
||||
from reflex.app import ComponentCallable, UnevaluatedPage
|
||||
|
||||
|
||||
def _into_component_once(component: Component | ComponentCallable) -> Component | None:
|
||||
"""Convert a component to a Component.
|
||||
|
||||
Args:
|
||||
component: The component to convert.
|
||||
|
||||
Returns:
|
||||
The converted 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)}")
|
||||
|
||||
|
||||
def compile_unevaluated_page(
|
||||
@ -559,12 +608,7 @@ def compile_unevaluated_page(
|
||||
The compiled component and whether state should be enabled.
|
||||
"""
|
||||
# Generate the component if it is a callable.
|
||||
component = page.component
|
||||
component = component if isinstance(component, Component) else component()
|
||||
|
||||
# unpack components that return tuples in an rx.fragment.
|
||||
if isinstance(component, tuple):
|
||||
component = Fragment.create(*component)
|
||||
component = into_component(page.component)
|
||||
|
||||
component._add_style_recursive(style or {}, theme)
|
||||
|
||||
@ -669,10 +713,8 @@ class ExecutorSafeFunctions:
|
||||
The route, compiled component, and compiled page.
|
||||
"""
|
||||
component, enable_state = compile_unevaluated_page(
|
||||
route, cls.UNCOMPILED_PAGES[route]
|
||||
route, cls.UNCOMPILED_PAGES[route], cls.STATE, style, theme
|
||||
)
|
||||
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,11 +48,10 @@ 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,17 +2,15 @@
|
||||
|
||||
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 pydantic.v1.fields import ModelField
|
||||
|
||||
from reflex import constants
|
||||
from reflex.components.base import (
|
||||
@ -29,10 +27,13 @@ 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
|
||||
from reflex.state import BaseState, _resolve_delta
|
||||
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
|
||||
@ -112,24 +113,34 @@ 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): # type: ignore
|
||||
if not any(f.render for f in fields):
|
||||
continue
|
||||
|
||||
if not lib:
|
||||
if default:
|
||||
raise ValueError("No default field allowed for empty library.")
|
||||
if rest is None or len(rest) == 0:
|
||||
raise ValueError("No fields to import.")
|
||||
import_dicts.extend(get_import_dict(module) for module in sorted(rest))
|
||||
continue
|
||||
lib_paths: dict[str, list[ImportVar]] = {}
|
||||
|
||||
# remove the version before rendering the package imports
|
||||
lib = format.format_library_name(lib)
|
||||
for field in fields:
|
||||
lib_paths.setdefault(field.package_path, []).append(field)
|
||||
|
||||
import_dicts.append(get_import_dict(lib, default, rest))
|
||||
compiled = {
|
||||
path: compile_import_statement(fields) for path, fields in lib_paths.items()
|
||||
}
|
||||
|
||||
for path, (default, rest) in compiled.items():
|
||||
if not lib:
|
||||
if default:
|
||||
raise ValueError("No default field allowed for empty library.")
|
||||
if rest is None or len(rest) == 0:
|
||||
raise ValueError("No fields to import.")
|
||||
import_dicts.extend(get_import_dict(module) for module in sorted(rest))
|
||||
continue
|
||||
|
||||
# remove the version before rendering the package imports
|
||||
formatted_lib = format.format_library_name(lib) + (
|
||||
path if path != "/" else ""
|
||||
)
|
||||
|
||||
import_dicts.append(get_import_dict(formatted_lib, default, rest))
|
||||
return import_dicts
|
||||
|
||||
|
||||
@ -151,6 +162,22 @@ 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.
|
||||
|
||||
@ -163,13 +190,31 @@ 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, excluding them: {e}"
|
||||
f"Failed to compile initial state with computed vars. Error log saved to {log_path}"
|
||||
)
|
||||
initial_state = state(_reflex_internal_init=True).dict(
|
||||
initial=True, include_computed=False
|
||||
)
|
||||
return initial_state
|
||||
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))
|
||||
|
||||
|
||||
def _compile_client_storage_field(
|
||||
@ -292,6 +337,7 @@ 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,
|
||||
)
|
||||
@ -471,6 +517,8 @@ 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")
|
||||
|
||||
|
||||
@ -494,7 +542,7 @@ def empty_dir(path: str | Path, keep_files: list[str] | None = None):
|
||||
path_ops.rm(element)
|
||||
|
||||
|
||||
def is_valid_url(url) -> bool:
|
||||
def is_valid_url(url: str) -> 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 BASE_STATE, EventType
|
||||
from reflex.event import 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[[], 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,
|
||||
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,
|
||||
) -> "AppWrap":
|
||||
"""Create a new AppWrap component.
|
||||
|
@ -2,14 +2,54 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Iterator
|
||||
from typing import Any, Iterator, Sequence
|
||||
|
||||
from reflex.components.component import Component, LiteralComponentVar
|
||||
from reflex.components.component import BaseComponent, 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 VarData
|
||||
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 ()
|
||||
|
||||
|
||||
class Bare(Component):
|
||||
@ -28,10 +68,15 @@ 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) # type: ignore
|
||||
|
||||
return cls(contents=contents)
|
||||
|
||||
def _get_all_hooks_internal(self) -> dict[str, VarData | None]:
|
||||
"""Include the hooks for the component.
|
||||
@ -40,8 +85,9 @@ class Bare(Component):
|
||||
The hooks for the component.
|
||||
"""
|
||||
hooks = super()._get_all_hooks_internal()
|
||||
if isinstance(self.contents, LiteralComponentVar):
|
||||
hooks |= self.contents._var_value._get_all_hooks_internal()
|
||||
if isinstance(self.contents, Var):
|
||||
for component in _components_from_var(self.contents):
|
||||
hooks |= component._get_all_hooks_internal()
|
||||
return hooks
|
||||
|
||||
def _get_all_hooks(self) -> dict[str, VarData | None]:
|
||||
@ -51,18 +97,22 @@ class Bare(Component):
|
||||
The hooks for the component.
|
||||
"""
|
||||
hooks = super()._get_all_hooks()
|
||||
if isinstance(self.contents, LiteralComponentVar):
|
||||
hooks |= self.contents._var_value._get_all_hooks()
|
||||
if isinstance(self.contents, Var):
|
||||
for component in _components_from_var(self.contents):
|
||||
hooks |= component._get_all_hooks()
|
||||
return hooks
|
||||
|
||||
def _get_all_imports(self) -> ParsedImportDict:
|
||||
def _get_all_imports(self, collapse: bool = False) -> ParsedImportDict:
|
||||
"""Include the imports for the component.
|
||||
|
||||
Args:
|
||||
collapse: Whether to collapse the imports.
|
||||
|
||||
Returns:
|
||||
The imports for the component.
|
||||
"""
|
||||
imports = super()._get_all_imports()
|
||||
if isinstance(self.contents, LiteralComponentVar):
|
||||
imports = super()._get_all_imports(collapse=collapse)
|
||||
if isinstance(self.contents, Var):
|
||||
var_data = self.contents._get_all_var_data()
|
||||
if var_data:
|
||||
imports |= {k: list(v) for k, v in var_data.imports}
|
||||
@ -75,8 +125,9 @@ class Bare(Component):
|
||||
The dynamic imports.
|
||||
"""
|
||||
dynamic_imports = super()._get_all_dynamic_imports()
|
||||
if isinstance(self.contents, LiteralComponentVar):
|
||||
dynamic_imports |= self.contents._var_value._get_all_dynamic_imports()
|
||||
if isinstance(self.contents, Var):
|
||||
for component in _components_from_var(self.contents):
|
||||
dynamic_imports |= component._get_all_dynamic_imports()
|
||||
return dynamic_imports
|
||||
|
||||
def _get_all_custom_code(self) -> set[str]:
|
||||
@ -86,10 +137,24 @@ class Bare(Component):
|
||||
The custom code.
|
||||
"""
|
||||
custom_code = super()._get_all_custom_code()
|
||||
if isinstance(self.contents, LiteralComponentVar):
|
||||
custom_code |= self.contents._var_value._get_all_custom_code()
|
||||
if isinstance(self.contents, Var):
|
||||
for component in _components_from_var(self.contents):
|
||||
custom_code |= component._get_all_custom_code()
|
||||
return custom_code
|
||||
|
||||
def _get_all_app_wrap_components(self) -> dict[tuple[int, str], Component]:
|
||||
"""Get the components that should be wrapped in the app.
|
||||
|
||||
Returns:
|
||||
The components that should be wrapped in the app.
|
||||
"""
|
||||
app_wrap_components = super()._get_all_app_wrap_components()
|
||||
if isinstance(self.contents, Var):
|
||||
for component in _components_from_var(self.contents):
|
||||
if isinstance(component, Component):
|
||||
app_wrap_components |= component._get_all_app_wrap_components()
|
||||
return app_wrap_components
|
||||
|
||||
def _get_all_refs(self) -> set[str]:
|
||||
"""Get the refs for the children of the component.
|
||||
|
||||
@ -97,8 +162,9 @@ class Bare(Component):
|
||||
The refs for the children.
|
||||
"""
|
||||
refs = super()._get_all_refs()
|
||||
if isinstance(self.contents, LiteralComponentVar):
|
||||
refs |= self.contents._var_value._get_all_refs()
|
||||
if isinstance(self.contents, Var):
|
||||
for component in _components_from_var(self.contents):
|
||||
refs |= component._get_all_refs()
|
||||
return refs
|
||||
|
||||
def _render(self) -> Tag:
|
||||
@ -108,6 +174,33 @@ class Bare(Component):
|
||||
return Tagless(contents=f"{{{self.contents!s}}}")
|
||||
return Tagless(contents=str(self.contents))
|
||||
|
||||
def _add_style_recursive(
|
||||
self, style: ComponentStyle, theme: Component | None = None
|
||||
) -> Component:
|
||||
"""Add style to the component and its children.
|
||||
|
||||
Args:
|
||||
style: The style to add.
|
||||
theme: The theme to add.
|
||||
|
||||
Returns:
|
||||
The component with the style added.
|
||||
"""
|
||||
new_self = super()._add_style_recursive(style, theme)
|
||||
|
||||
are_components_touched = False
|
||||
|
||||
if isinstance(self.contents, Var):
|
||||
for component in _components_from_var(self.contents):
|
||||
if isinstance(component, Component):
|
||||
component._add_style_recursive(style, theme)
|
||||
are_components_touched = True
|
||||
|
||||
if are_components_touched:
|
||||
GLOBAL_CACHE.clear()
|
||||
|
||||
return new_self
|
||||
|
||||
def _get_vars(
|
||||
self, include_children: bool = False, ignore_ids: set[int] | None = None
|
||||
) -> Iterator[Var]:
|
||||
|
@ -6,7 +6,7 @@
|
||||
from typing import Any, Dict, Optional, Union, overload
|
||||
|
||||
from reflex.components.component import Component
|
||||
from reflex.event import BASE_STATE, EventType
|
||||
from reflex.event import 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[[], 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,
|
||||
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,
|
||||
) -> "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 BASE_STATE, EventType
|
||||
from reflex.event import 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[[], 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,
|
||||
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,
|
||||
) -> "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[[], 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,
|
||||
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,
|
||||
) -> "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[[], 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,
|
||||
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,
|
||||
) -> "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[[], 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,
|
||||
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,
|
||||
) -> "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[[], 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,
|
||||
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,
|
||||
) -> "NextScript":
|
||||
"""Create the component.
|
||||
|
@ -11,10 +11,11 @@ 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: Var[Dict[str, str]], info: Var[Dict[str, str]]
|
||||
error: ObjectVar[Dict[str, str]], info: ObjectVar[Dict[str, str]]
|
||||
) -> Tuple[Var[str], Var[str]]:
|
||||
"""The spec for the on_error event handler.
|
||||
|
||||
|
@ -6,12 +6,13 @@
|
||||
from typing import Any, Dict, Optional, Tuple, Union, overload
|
||||
|
||||
from reflex.components.component import Component
|
||||
from reflex.event import BASE_STATE, EventType
|
||||
from reflex.event import EventType
|
||||
from reflex.style import Style
|
||||
from reflex.vars.base import Var
|
||||
from reflex.vars.object import ObjectVar
|
||||
|
||||
def on_error_spec(
|
||||
error: Var[Dict[str, str]], info: Var[Dict[str, str]]
|
||||
error: ObjectVar[Dict[str, str]], info: ObjectVar[Dict[str, str]]
|
||||
) -> Tuple[Var[str], Var[str]]: ...
|
||||
|
||||
class ErrorBoundary(Component):
|
||||
@ -27,28 +28,24 @@ 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[[], 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_blur: Optional[EventType[()]] = None,
|
||||
on_click: Optional[EventType[()]] = None,
|
||||
on_context_menu: Optional[EventType[()]] = None,
|
||||
on_double_click: Optional[EventType[()]] = None,
|
||||
on_error: Optional[
|
||||
Union[
|
||||
EventType[[], BASE_STATE],
|
||||
EventType[[str], BASE_STATE],
|
||||
EventType[[str, str], BASE_STATE],
|
||||
]
|
||||
Union[EventType[()], EventType[str], EventType[str, str]]
|
||||
] = 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,
|
||||
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,
|
||||
) -> "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 BASE_STATE, EventType
|
||||
from reflex.event import 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[[], 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,
|
||||
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,
|
||||
) -> "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 BASE_STATE, EventType
|
||||
from reflex.event import 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[[], 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,
|
||||
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,
|
||||
) -> "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[[], 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,
|
||||
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,
|
||||
) -> "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 BASE_STATE, EventType
|
||||
from reflex.event import 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[[], 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,
|
||||
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,
|
||||
) -> "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[[], 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,
|
||||
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,
|
||||
) -> "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 = "description"
|
||||
name: str | None = "description"
|
||||
|
||||
|
||||
class Image(Meta):
|
||||
"""A component that displays the title of the current page."""
|
||||
|
||||
# The type of the image.
|
||||
property: str = "og:image"
|
||||
property: str | None = "og:image"
|
||||
|
@ -6,7 +6,7 @@
|
||||
from typing import Any, Dict, Optional, Union, overload
|
||||
|
||||
from reflex.components.component import Component
|
||||
from reflex.event import BASE_STATE, EventType
|
||||
from reflex.event import 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[[], 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,
|
||||
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,
|
||||
) -> "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[[], 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,
|
||||
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,
|
||||
) -> "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[[], 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,
|
||||
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,
|
||||
) -> "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[[], 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,
|
||||
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,
|
||||
) -> "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 BASE_STATE, EventType
|
||||
from reflex.event import 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[[], 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,
|
||||
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,
|
||||
**props,
|
||||
) -> "Script":
|
||||
"""Create an inline or user-defined script.
|
||||
|
10
reflex/components/base/strict_mode.py
Normal file
10
reflex/components/base/strict_mode.py
Normal file
@ -0,0 +1,10 @@
|
||||
"""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"
|
57
reflex/components/base/strict_mode.pyi
Normal file
57
reflex/components/base/strict_mode.pyi
Normal file
@ -0,0 +1,57 @@
|
||||
"""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,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import dataclasses
|
||||
import inspect
|
||||
import typing
|
||||
from abc import ABC, abstractmethod
|
||||
from functools import lru_cache, wraps
|
||||
@ -21,9 +22,11 @@ from typing import (
|
||||
Set,
|
||||
Type,
|
||||
Union,
|
||||
get_args,
|
||||
get_origin,
|
||||
)
|
||||
|
||||
from typing_extensions import deprecated
|
||||
from typing_extensions import Self
|
||||
|
||||
import reflex.state
|
||||
from reflex.base import Base
|
||||
@ -43,22 +46,16 @@ 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,
|
||||
EventSpec,
|
||||
EventVar,
|
||||
no_args_event_spec,
|
||||
)
|
||||
from reflex.style import Style, format_as_emotion
|
||||
from reflex.utils import console, format, imports, types
|
||||
from reflex.utils.imports import (
|
||||
ImmutableParsedImportDict,
|
||||
ImportDict,
|
||||
ImportVar,
|
||||
ParsedImportDict,
|
||||
parse_imports,
|
||||
)
|
||||
from reflex.utils import format, imports, types
|
||||
from reflex.utils.imports import ImportDict, ImportVar, ParsedImportDict, parse_imports
|
||||
from reflex.vars import VarData
|
||||
from reflex.vars.base import (
|
||||
CachedVarOperation,
|
||||
@ -153,7 +150,7 @@ class BaseComponent(Base, ABC):
|
||||
class ComponentNamespace(SimpleNamespace):
|
||||
"""A namespace to manage components with subcomponents."""
|
||||
|
||||
def __hash__(self) -> int:
|
||||
def __hash__(self) -> int: # pyright: ignore [reportIncompatibleVariableOverride]
|
||||
"""Get the hash of the namespace.
|
||||
|
||||
Returns:
|
||||
@ -182,6 +179,7 @@ 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:
|
||||
@ -194,11 +192,26 @@ def satisfies_type_hint(obj: Any, type_hint: Any) -> bool:
|
||||
Returns:
|
||||
Whether the object satisfies the type hint.
|
||||
"""
|
||||
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)
|
||||
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 ()
|
||||
|
||||
|
||||
class Component(BaseComponent, ABC):
|
||||
@ -429,20 +442,22 @@ class Component(BaseComponent, ABC):
|
||||
else:
|
||||
continue
|
||||
|
||||
def determine_key(value: Any):
|
||||
# Try to create a var from the value
|
||||
key = value if isinstance(value, Var) else LiteralVar.create(value)
|
||||
|
||||
# Check that the var type is not None.
|
||||
if key is None:
|
||||
raise TypeError
|
||||
|
||||
return key
|
||||
|
||||
# Check whether the key is a component prop.
|
||||
if types._issubclass(field_type, Var):
|
||||
# Used to store the passed types if var type is a union.
|
||||
passed_types = None
|
||||
try:
|
||||
# Try to create a var from the value.
|
||||
if isinstance(value, Var):
|
||||
kwargs[key] = value
|
||||
else:
|
||||
kwargs[key] = LiteralVar.create(value)
|
||||
|
||||
# Check that the var type is not None.
|
||||
if kwargs[key] is None:
|
||||
raise TypeError
|
||||
kwargs[key] = determine_key(value)
|
||||
|
||||
expected_type = fields[key].outer_type_.__args__[0]
|
||||
# validate literal fields.
|
||||
@ -463,9 +478,7 @@ 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__ # type: ignore
|
||||
if arg is not type(None)
|
||||
arg for arg in passed_type.__args__ if arg is not type(None)
|
||||
)
|
||||
if (
|
||||
# If the passed var is a union, check if all possible types are valid.
|
||||
@ -492,14 +505,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, # type: ignore
|
||||
value=value,
|
||||
args_spec=component_specific_triggers[key],
|
||||
key=key,
|
||||
)
|
||||
|
||||
# Remove any keys that were added as events.
|
||||
for key in kwargs["event_triggers"]:
|
||||
del kwargs[key]
|
||||
kwargs.pop(key, None)
|
||||
|
||||
# Place data_ and aria_ attributes into custom_attrs
|
||||
special_attributes = tuple(
|
||||
@ -545,41 +558,6 @@ class Component(BaseComponent, ABC):
|
||||
# Construct the component.
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@deprecated("Use rx.EventChain.create instead.")
|
||||
def _create_event_chain(
|
||||
self,
|
||||
args_spec: types.ArgsSpec | Sequence[types.ArgsSpec],
|
||||
value: Union[
|
||||
Var,
|
||||
EventHandler,
|
||||
EventSpec,
|
||||
List[Union[EventHandler, EventSpec, EventVar]],
|
||||
Callable,
|
||||
],
|
||||
key: Optional[str] = None,
|
||||
) -> Union[EventChain, Var]:
|
||||
"""Create an event chain from a variety of input types.
|
||||
|
||||
Args:
|
||||
args_spec: The args_spec of the event trigger being bound.
|
||||
value: The value to create the event chain from.
|
||||
key: The key of the event trigger being bound.
|
||||
|
||||
Returns:
|
||||
The event chain.
|
||||
"""
|
||||
console.deprecate(
|
||||
"Component._create_event_chain",
|
||||
"Use rx.EventChain.create instead.",
|
||||
deprecation_version="0.6.8",
|
||||
removal_version="0.7.0",
|
||||
)
|
||||
return EventChain.create(
|
||||
value=value, # type: ignore
|
||||
args_spec=args_spec,
|
||||
key=key,
|
||||
)
|
||||
|
||||
def get_event_triggers(
|
||||
self,
|
||||
) -> Dict[str, types.ArgsSpec | Sequence[types.ArgsSpec]]:
|
||||
@ -614,7 +592,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) # type: ignore
|
||||
default_triggers[field.name] = args_spec or (no_args_event_spec)
|
||||
return default_triggers
|
||||
|
||||
def __repr__(self) -> str:
|
||||
@ -661,8 +639,7 @@ class Component(BaseComponent, ABC):
|
||||
if props is None:
|
||||
# Add component props to the tag.
|
||||
props = {
|
||||
attr[:-1] if attr.endswith("_") else attr: getattr(self, attr)
|
||||
for attr in self.get_props()
|
||||
attr.removesuffix("_"): getattr(self, attr) for attr in self.get_props()
|
||||
}
|
||||
|
||||
# Add ref to element if `id` is not None.
|
||||
@ -712,12 +689,21 @@ class Component(BaseComponent, ABC):
|
||||
return set()
|
||||
|
||||
@classmethod
|
||||
@lru_cache(maxsize=None)
|
||||
def get_component_props(cls) -> set[str]:
|
||||
"""Get the props that expected a component as value.
|
||||
def _are_fields_known(cls) -> bool:
|
||||
"""Check if all fields are known at compile time. True for most components.
|
||||
|
||||
Returns:
|
||||
The components props.
|
||||
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.
|
||||
|
||||
Returns:
|
||||
The names of the component props.
|
||||
"""
|
||||
return {
|
||||
name
|
||||
@ -726,8 +712,28 @@ 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) -> Component:
|
||||
def create(cls, *children, **props) -> Self:
|
||||
"""Create the component.
|
||||
|
||||
Args:
|
||||
@ -740,22 +746,21 @@ class Component(BaseComponent, ABC):
|
||||
# Import here to avoid circular imports.
|
||||
from reflex.components.base.bare import Bare
|
||||
from reflex.components.base.fragment import Fragment
|
||||
from reflex.utils.exceptions import ComponentTypeError
|
||||
from reflex.utils.exceptions import ChildrenTypeError
|
||||
|
||||
# Filter out None props
|
||||
props = {key: value for key, value in props.items() if value is not None}
|
||||
|
||||
def validate_children(children):
|
||||
def validate_children(children: tuple | list):
|
||||
for child in children:
|
||||
if isinstance(child, tuple):
|
||||
if isinstance(child, (tuple, list)):
|
||||
validate_children(child)
|
||||
|
||||
# Make sure the child is a valid type.
|
||||
if not types._isinstance(child, ComponentChild):
|
||||
raise ComponentTypeError(
|
||||
"Children of Reflex components must be other components, "
|
||||
"state vars, or primitive Python types. "
|
||||
f"Got child {child} of type {type(child)}.",
|
||||
)
|
||||
if isinstance(child, dict) or not isinstance(
|
||||
child, ComponentChildTypes
|
||||
):
|
||||
raise ChildrenTypeError(component=cls.__name__, child=child)
|
||||
|
||||
# Validate all the children.
|
||||
validate_children(children)
|
||||
@ -798,7 +803,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) # type: ignore
|
||||
s = base.add_style(self)
|
||||
if s is not None:
|
||||
styles.append(s)
|
||||
|
||||
@ -890,7 +895,7 @@ class Component(BaseComponent, ABC):
|
||||
else {}
|
||||
)
|
||||
|
||||
def render(self) -> Dict:
|
||||
def render(self) -> dict:
|
||||
"""Render the component.
|
||||
|
||||
Returns:
|
||||
@ -908,7 +913,7 @@ class Component(BaseComponent, ABC):
|
||||
self._replace_prop_names(rendered_dict)
|
||||
return rendered_dict
|
||||
|
||||
def _replace_prop_names(self, rendered_dict) -> None:
|
||||
def _replace_prop_names(self, rendered_dict: dict) -> None:
|
||||
"""Replace the prop names in the render dictionary.
|
||||
|
||||
Args:
|
||||
@ -948,7 +953,7 @@ class Component(BaseComponent, ABC):
|
||||
comp.__name__ for comp in (Fragment, Foreach, Cond, Match)
|
||||
]
|
||||
|
||||
def validate_child(child):
|
||||
def validate_child(child: Any):
|
||||
child_name = type(child).__name__
|
||||
|
||||
# Iterate through the immediate children of fragment
|
||||
@ -1183,6 +1188,9 @@ 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):
|
||||
@ -1210,7 +1218,7 @@ class Component(BaseComponent, ABC):
|
||||
The dynamic imports.
|
||||
"""
|
||||
# Store the import in a set to avoid duplicates.
|
||||
dynamic_imports = set()
|
||||
dynamic_imports: set[str] = set()
|
||||
|
||||
# Get dynamic import for this component.
|
||||
dynamic_import = self._get_dynamic_imports()
|
||||
@ -1221,25 +1229,12 @@ class Component(BaseComponent, ABC):
|
||||
for child in self.children:
|
||||
dynamic_imports |= child._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()
|
||||
for component in self._get_components_in_props():
|
||||
dynamic_imports |= component._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.
|
||||
|
||||
@ -1249,7 +1244,7 @@ class Component(BaseComponent, ABC):
|
||||
Returns:
|
||||
True if the dependency should be transpiled.
|
||||
"""
|
||||
return (
|
||||
return bool(self.transpile_packages) and (
|
||||
dep in self.transpile_packages
|
||||
or format.format_library_name(dep or "") in self.transpile_packages
|
||||
)
|
||||
@ -1332,9 +1327,10 @@ class Component(BaseComponent, ABC):
|
||||
event_imports = Imports.EVENTS if self.event_triggers else {}
|
||||
|
||||
# Collect imports from Vars used directly by this component.
|
||||
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
|
||||
var_imports = [
|
||||
var_data.imports
|
||||
for var in self._get_vars()
|
||||
if (var_data := var._get_all_var_data()) is not None
|
||||
]
|
||||
|
||||
added_import_dicts: list[ParsedImportDict] = []
|
||||
@ -1349,7 +1345,6 @@ class Component(BaseComponent, ABC):
|
||||
)
|
||||
|
||||
return imports.merge_imports(
|
||||
*self._get_props_imports(),
|
||||
self._get_dependencies_imports(),
|
||||
self._get_hooks_imports(),
|
||||
_imports,
|
||||
@ -1426,6 +1421,8 @@ 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]:
|
||||
@ -1574,6 +1571,9 @@ 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,6 +1597,9 @@ 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
|
||||
@ -1660,17 +1663,65 @@ class CustomComponent(Component):
|
||||
# The props of the component.
|
||||
props: Dict[str, Any] = {}
|
||||
|
||||
# Props that reference other components.
|
||||
component_props: Dict[str, Component] = {}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
def __init__(self, **kwargs):
|
||||
"""Initialize the custom component.
|
||||
|
||||
Args:
|
||||
*args: The args to pass to the component.
|
||||
**kwargs: The kwargs to pass to the component.
|
||||
"""
|
||||
super().__init__(*args, **kwargs)
|
||||
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]
|
||||
|
||||
# Unset the style.
|
||||
self.style = Style()
|
||||
@ -1678,51 +1729,36 @@ class CustomComponent(Component):
|
||||
# Set the tag to the name of the function.
|
||||
self.tag = format.to_title_case(self.component_fn.__name__)
|
||||
|
||||
# Get the event triggers defined in the component declaration.
|
||||
event_triggers_in_component_declaration = self.get_event_triggers()
|
||||
|
||||
# Set the props.
|
||||
props = typing.get_type_hints(self.component_fn)
|
||||
for key, value in kwargs.items():
|
||||
for key, value in props.items():
|
||||
# Skip kwargs that are not props.
|
||||
if key not in props:
|
||||
if key not in props_types:
|
||||
continue
|
||||
|
||||
camel_cased_key = format.to_camel_case(key)
|
||||
|
||||
# Get the type based on the annotation.
|
||||
type_ = props[key]
|
||||
type_ = props_types[key]
|
||||
|
||||
# Handle event chains.
|
||||
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,
|
||||
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
|
||||
)
|
||||
self.props[format.to_camel_case(key)] = value
|
||||
continue
|
||||
|
||||
# Handle subclasses of Base.
|
||||
if isinstance(value, Base):
|
||||
base_value = LiteralVar.create(value)
|
||||
value = LiteralVar.create(value)
|
||||
self.props[camel_cased_key] = value
|
||||
setattr(self, camel_cased_key, 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)
|
||||
@classmethod
|
||||
def _are_fields_known(cls) -> bool:
|
||||
"""Check if the fields are known.
|
||||
|
||||
# Set the prop.
|
||||
self.props[format.to_camel_case(key)] = value
|
||||
Returns:
|
||||
Whether the fields are known.
|
||||
"""
|
||||
return False
|
||||
|
||||
def __eq__(self, other: Any) -> bool:
|
||||
"""Check if the component is equal to another.
|
||||
@ -1781,27 +1817,8 @@ 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.
|
||||
|
||||
@ -1812,34 +1829,19 @@ class CustomComponent(Component):
|
||||
Var(
|
||||
_js_expr=name,
|
||||
_var_type=(
|
||||
prop._var_type if types._isinstance(prop, Var) else type(prop)
|
||||
prop._var_type
|
||||
if isinstance(prop, Var)
|
||||
else (
|
||||
type(prop)
|
||||
if not isinstance(prop, EventActionsMixin)
|
||||
else EventChain
|
||||
)
|
||||
),
|
||||
).guess_type()
|
||||
for name, prop in self.props.items()
|
||||
]
|
||||
|
||||
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
|
||||
@lru_cache(maxsize=None) # noqa: B019
|
||||
def get_component(self) -> Component:
|
||||
"""Render the component.
|
||||
|
||||
@ -1983,7 +1985,7 @@ class StatefulComponent(BaseComponent):
|
||||
|
||||
if not should_memoize:
|
||||
# Determine if any Vars have associated data.
|
||||
for prop_var in component._get_vars():
|
||||
for prop_var in component._get_vars(include_children=True):
|
||||
if prop_var._get_all_var_data():
|
||||
should_memoize = True
|
||||
break
|
||||
@ -2366,8 +2368,8 @@ class MemoizationLeaf(Component):
|
||||
"""
|
||||
comp = super().create(*children, **props)
|
||||
if comp._get_all_hooks():
|
||||
comp._memoization_mode = cls._memoization_mode.copy(
|
||||
update={"disposition": MemoizationDisposition.ALWAYS}
|
||||
comp._memoization_mode = dataclasses.replace(
|
||||
comp._memoization_mode, disposition=MemoizationDisposition.ALWAYS
|
||||
)
|
||||
return comp
|
||||
|
||||
@ -2428,7 +2430,7 @@ def render_dict_to_var(tag: dict | Component | str, imported_names: set[str]) ->
|
||||
if tag["name"] == "match":
|
||||
element = tag["cond"]
|
||||
|
||||
conditionals = tag["default"]
|
||||
conditionals = render_dict_to_var(tag["default"], imported_names)
|
||||
|
||||
for case in tag["match_cases"][::-1]:
|
||||
condition = case[0].to_string() == element.to_string()
|
||||
@ -2437,7 +2439,7 @@ def render_dict_to_var(tag: dict | Component | str, imported_names: set[str]) ->
|
||||
|
||||
conditionals = ternary_operation(
|
||||
condition,
|
||||
case[-1],
|
||||
render_dict_to_var(case[-1], imported_names),
|
||||
conditionals,
|
||||
)
|
||||
|
||||
@ -2496,6 +2498,7 @@ 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."""
|
||||
@ -2525,6 +2528,7 @@ class LiteralComponentVar(CachedVarOperation, LiteralVar, ComponentVar):
|
||||
The VarData for the var.
|
||||
"""
|
||||
return VarData.merge(
|
||||
self._var_data,
|
||||
VarData(
|
||||
imports={
|
||||
"@emotion/react": [
|
||||
@ -2567,9 +2571,21 @@ 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())
|
||||
]
|
||||
|
||||
return LiteralComponentVar(
|
||||
_js_expr="",
|
||||
_var_type=type(value),
|
||||
_var_data=_var_data,
|
||||
_var_data=VarData.merge(
|
||||
_var_data,
|
||||
*var_datas,
|
||||
VarData(
|
||||
components=(value,),
|
||||
),
|
||||
),
|
||||
_var_value=value,
|
||||
)
|
||||
|
@ -48,6 +48,7 @@ _SUBMOD_ATTRS: dict[str, list[str]] = {
|
||||
"get_upload_url",
|
||||
"selected_files",
|
||||
],
|
||||
"auto_scroll": ["auto_scroll"],
|
||||
}
|
||||
|
||||
__getattr__, __dir__, __all__ = lazy_loader.attach(
|
||||
|
@ -4,6 +4,7 @@
|
||||
# ------------------------------------------------------
|
||||
|
||||
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
|
||||
|
111
reflex/components/core/auto_scroll.py
Normal file
111
reflex/components/core/auto_scroll.py
Normal file
@ -0,0 +1,111 @@
|
||||
"""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)
|
||||
|
||||
@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 containerRef = useRef(null);",
|
||||
"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;
|
||||
|
||||
// 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
|
284
reflex/components/core/auto_scroll.pyi
Normal file
284
reflex/components/core/auto_scroll.pyi
Normal file
@ -0,0 +1,284 @@
|
||||
"""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,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from reflex import constants
|
||||
from reflex.components.component import Component
|
||||
from reflex.components.core.cond import cond
|
||||
from reflex.components.el.elements.typography import Div
|
||||
@ -16,6 +17,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 Toaster, ToastProps
|
||||
from reflex.config import environment
|
||||
from reflex.constants import Dirs, Hooks, Imports
|
||||
from reflex.constants.compiler import CompileVars
|
||||
from reflex.utils.imports import ImportVar
|
||||
@ -25,7 +27,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( # type: ignore
|
||||
connect_error_var_data: VarData = VarData(
|
||||
imports=Imports.EVENTS,
|
||||
hooks={Hooks.EVENTS: None},
|
||||
)
|
||||
@ -99,24 +101,56 @@ class ConnectionToaster(Toaster):
|
||||
"""
|
||||
toast_id = "websocket-error"
|
||||
target_url = WebsocketTargetURL.create()
|
||||
props = ToastProps( # type: ignore
|
||||
props = ToastProps(
|
||||
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 = [
|
||||
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), # type: ignore
|
||||
**dict(target_url._get_all_var_data().imports), # pyright: ignore [reportArgumentType, reportOptionalMemberAccess]
|
||||
}
|
||||
),
|
||||
).call(
|
||||
@ -126,10 +160,7 @@ class ConnectionToaster(Toaster):
|
||||
() => {{
|
||||
if ({has_too_many_connection_errors!s}) {{
|
||||
if (!userDismissed) {{
|
||||
toast.error(
|
||||
`Cannot connect to server: ${{{connection_error}}}.`,
|
||||
{{...toast_props, onDismiss: () => setUserDismissed(true)}},
|
||||
)
|
||||
{toast_var!s}
|
||||
}}
|
||||
}} else {{
|
||||
toast.dismiss("{toast_id}");
|
||||
@ -138,7 +169,7 @@ class ConnectionToaster(Toaster):
|
||||
}}
|
||||
"""
|
||||
),
|
||||
LiteralArrayVar.create([connect_errors]),
|
||||
LiteralArrayVar.create([connect_errors, Var("waitedForBackend")]),
|
||||
),
|
||||
]
|
||||
|
||||
@ -293,7 +324,161 @@ 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
|
||||
|
@ -10,7 +10,7 @@ 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 BASE_STATE, EventType
|
||||
from reflex.event import EventType
|
||||
from reflex.style import Style
|
||||
from reflex.utils.imports import ImportVar
|
||||
from reflex.vars import VarData
|
||||
@ -89,21 +89,21 @@ class ConnectionToaster(Toaster):
|
||||
class_name: Optional[Any] = None,
|
||||
autofocus: Optional[bool] = None,
|
||||
custom_attrs: Optional[Dict[str, Union[Var, Any]]] = 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,
|
||||
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,
|
||||
) -> "ConnectionToaster":
|
||||
"""Create a connection toaster component.
|
||||
@ -149,21 +149,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[[], 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,
|
||||
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,
|
||||
) -> "ConnectionBanner":
|
||||
"""Create a connection banner component.
|
||||
@ -188,21 +188,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[[], 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,
|
||||
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,
|
||||
) -> "ConnectionModal":
|
||||
"""Create a connection banner component.
|
||||
@ -228,21 +228,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[[], 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,
|
||||
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,
|
||||
) -> "WifiOffPulse":
|
||||
"""Create a wifi_off icon with an animated opacity pulse.
|
||||
@ -271,51 +271,232 @@ class ConnectionPulser(Div):
|
||||
def create( # type: ignore
|
||||
cls,
|
||||
*children,
|
||||
access_key: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
|
||||
access_key: Optional[Union[Var[str], str]] = None,
|
||||
auto_capitalize: Optional[
|
||||
Union[Var[Union[bool, int, str]], bool, int, str]
|
||||
Union[
|
||||
Literal["characters", "none", "off", "on", "sentences", "words"],
|
||||
Var[Literal["characters", "none", "off", "on", "sentences", "words"]],
|
||||
]
|
||||
] = None,
|
||||
content_editable: Optional[
|
||||
Union[Var[Union[bool, int, str]], bool, int, str]
|
||||
Union[
|
||||
Literal["inherit", "plaintext-only", False, True],
|
||||
Var[Literal["inherit", "plaintext-only", False, True]],
|
||||
]
|
||||
] = 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,
|
||||
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[Var[Union[bool, int, str]], bool, int, str]
|
||||
Union[
|
||||
Literal["done", "enter", "go", "next", "previous", "search", "send"],
|
||||
Var[
|
||||
Literal["done", "enter", "go", "next", "previous", "search", "send"]
|
||||
],
|
||||
]
|
||||
] = 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,
|
||||
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[[], 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,
|
||||
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,
|
||||
) -> "ConnectionPulser":
|
||||
"""Create a connection pulser component.
|
||||
@ -350,7 +531,274 @@ 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")
|
||||
K = TypeVar("K", bound=str)
|
||||
V = TypeVar("V")
|
||||
|
||||
|
||||
@ -82,7 +82,9 @@ class Breakpoints(Dict[K, V]):
|
||||
return Breakpoints(
|
||||
{
|
||||
k: v
|
||||
for k, v in zip(["initial", *breakpoint_names], thresholds)
|
||||
for k, v in zip(
|
||||
["initial", *breakpoint_names], thresholds, strict=True
|
||||
)
|
||||
if v is not None
|
||||
}
|
||||
)
|
||||
|
@ -41,7 +41,7 @@ class ClientSideRouting(Component):
|
||||
return ""
|
||||
|
||||
|
||||
def wait_for_client_redirect(component) -> Component:
|
||||
def wait_for_client_redirect(component: 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 BASE_STATE, EventType
|
||||
from reflex.event import 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[[], 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,
|
||||
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,
|
||||
) -> "ClientSideRouting":
|
||||
"""Create the component.
|
||||
@ -60,7 +60,7 @@ class ClientSideRouting(Component):
|
||||
"""
|
||||
...
|
||||
|
||||
def wait_for_client_redirect(component) -> Component: ...
|
||||
def wait_for_client_redirect(component: 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[[], 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,
|
||||
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,
|
||||
) -> "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 BASE_STATE, EventType
|
||||
from reflex.event import EventType
|
||||
from reflex.style import Style
|
||||
from reflex.utils.imports import ImportVar
|
||||
from reflex.vars.base import Var
|
||||
@ -27,27 +27,24 @@ 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[[], 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_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_paste: Optional[
|
||||
Union[
|
||||
EventType[[], BASE_STATE],
|
||||
EventType[[list[tuple[str, str]]], BASE_STATE],
|
||||
]
|
||||
Union[EventType[()], EventType[list[tuple[str, str]]]]
|
||||
] = None,
|
||||
on_scroll: Optional[EventType[[], BASE_STATE]] = None,
|
||||
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
|
||||
on_scroll: Optional[EventType[()]] = None,
|
||||
on_unmount: Optional[EventType[()]] = None,
|
||||
**props,
|
||||
) -> "Clipboard":
|
||||
"""Create a Clipboard component.
|
||||
|
@ -26,10 +26,9 @@ class Cond(MemoizationLeaf):
|
||||
cond: Var[Any]
|
||||
|
||||
# The component to render if the cond is true.
|
||||
comp1: BaseComponent = None # type: ignore
|
||||
|
||||
comp1: BaseComponent | None = None
|
||||
# The component to render if the cond is false.
|
||||
comp2: BaseComponent = None # type: ignore
|
||||
comp2: BaseComponent | None = None
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
@ -62,19 +61,11 @@ class Cond(MemoizationLeaf):
|
||||
)
|
||||
)
|
||||
|
||||
def _get_props_imports(self):
|
||||
"""Get the imports needed for component's props.
|
||||
|
||||
Returns:
|
||||
The imports for the component's props of the component.
|
||||
"""
|
||||
return []
|
||||
|
||||
def _render(self) -> Tag:
|
||||
return CondTag(
|
||||
cond=self.cond,
|
||||
true_value=self.comp1.render(),
|
||||
false_value=self.comp2.render(),
|
||||
true_value=self.comp1.render(), # pyright: ignore [reportOptionalMemberAccess]
|
||||
false_value=self.comp2.render(), # pyright: ignore [reportOptionalMemberAccess]
|
||||
)
|
||||
|
||||
def render(self) -> Dict:
|
||||
@ -111,7 +102,7 @@ class Cond(MemoizationLeaf):
|
||||
|
||||
|
||||
@overload
|
||||
def cond(condition: Any, c1: Component, c2: Any) -> Component: ...
|
||||
def cond(condition: Any, c1: Component, c2: Any) -> Component: ... # pyright: ignore [reportOverlappingOverload]
|
||||
|
||||
|
||||
@overload
|
||||
@ -154,7 +145,7 @@ def cond(condition: Any, c1: Any, c2: Any = None) -> Component | Var:
|
||||
if c2 is None:
|
||||
raise ValueError("For conditional vars, the second argument must be set.")
|
||||
|
||||
def create_var(cond_part):
|
||||
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.
|
||||
@ -163,16 +154,16 @@ def cond(condition: Any, c1: Any, c2: Any = None) -> Component | Var:
|
||||
|
||||
# Create the conditional var.
|
||||
return ternary_operation(
|
||||
cond_var.bool()._replace( # type: ignore
|
||||
cond_var.bool()._replace(
|
||||
merge_var_data=VarData(imports=_IS_TRUE_IMPORT),
|
||||
), # type: ignore
|
||||
),
|
||||
c1,
|
||||
c2,
|
||||
)
|
||||
|
||||
|
||||
@overload
|
||||
def color_mode_cond(light: Component, dark: Component | None = None) -> Component: ... # type: ignore
|
||||
def color_mode_cond(light: Component, dark: Component | None = None) -> Component: ... # pyright: ignore [reportOverlappingOverload]
|
||||
|
||||
|
||||
@overload
|
||||
|
@ -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] = DEFAULT_DEBOUNCE_TIMEOUT # type: ignore
|
||||
debounce_timeout: Var[int] = Var.create(DEFAULT_DEBOUNCE_TIMEOUT)
|
||||
|
||||
# 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 BASE_STATE, EventType
|
||||
from reflex.event import 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[[], 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,
|
||||
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,
|
||||
**props,
|
||||
) -> "DebounceInput":
|
||||
"""Create a DebounceInput component.
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import functools
|
||||
import inspect
|
||||
from typing import Any, Callable, Iterable
|
||||
|
||||
@ -10,6 +11,7 @@ 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
|
||||
|
||||
|
||||
@ -50,8 +52,12 @@ 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.
|
||||
"""
|
||||
iterable = LiteralVar.create(iterable)
|
||||
from reflex.vars import ArrayVar, ObjectVar, StringVar
|
||||
|
||||
iterable = LiteralVar.create(iterable).guess_type()
|
||||
|
||||
if iterable._var_type == Any:
|
||||
raise ForeachVarError(
|
||||
f"Could not foreach over var `{iterable!s}` of type Any. "
|
||||
@ -67,12 +73,30 @@ class Foreach(Component):
|
||||
"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,
|
||||
)
|
||||
# Keep a ref to a rendered component to determine correct imports/hooks/styles.
|
||||
component.children = [component._render().render_component()]
|
||||
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:
|
||||
@ -97,9 +121,20 @@ class Foreach(Component):
|
||||
# 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(self.render_fn.__code__)
|
||||
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",
|
||||
|
@ -14,7 +14,7 @@ class Html(Div):
|
||||
"""
|
||||
|
||||
# The HTML to render.
|
||||
dangerouslySetInnerHTML: Var[Dict[str, str]]
|
||||
dangerouslySetInnerHTML: Var[Dict[str, str]] # noqa: N815
|
||||
|
||||
@classmethod
|
||||
def create(cls, *children, **props):
|
||||
|
@ -3,10 +3,10 @@
|
||||
# ------------------- DO NOT EDIT ----------------------
|
||||
# This file was generated by `reflex/utils/pyi_generator.py`!
|
||||
# ------------------------------------------------------
|
||||
from typing import Any, Dict, Optional, Union, overload
|
||||
from typing import Any, Dict, Literal, Optional, Union, overload
|
||||
|
||||
from reflex.components.el.elements.typography import Div
|
||||
from reflex.event import BASE_STATE, EventType
|
||||
from reflex.event import EventType
|
||||
from reflex.style import Style
|
||||
from reflex.vars.base import Var
|
||||
|
||||
@ -19,51 +19,232 @@ class Html(Div):
|
||||
dangerouslySetInnerHTML: Optional[
|
||||
Union[Dict[str, str], Var[Dict[str, str]]]
|
||||
] = None,
|
||||
access_key: Optional[Union[Var[Union[bool, int, str]], bool, int, str]] = None,
|
||||
access_key: Optional[Union[Var[str], str]] = None,
|
||||
auto_capitalize: Optional[
|
||||
Union[Var[Union[bool, int, str]], bool, int, str]
|
||||
Union[
|
||||
Literal["characters", "none", "off", "on", "sentences", "words"],
|
||||
Var[Literal["characters", "none", "off", "on", "sentences", "words"]],
|
||||
]
|
||||
] = None,
|
||||
content_editable: Optional[
|
||||
Union[Var[Union[bool, int, str]], bool, int, str]
|
||||
Union[
|
||||
Literal["inherit", "plaintext-only", False, True],
|
||||
Var[Literal["inherit", "plaintext-only", False, True]],
|
||||
]
|
||||
] = 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,
|
||||
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[Var[Union[bool, int, str]], bool, int, str]
|
||||
Union[
|
||||
Literal["done", "enter", "go", "next", "previous", "search", "send"],
|
||||
Var[
|
||||
Literal["done", "enter", "go", "next", "previous", "search", "send"]
|
||||
],
|
||||
]
|
||||
] = 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,
|
||||
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[[], 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,
|
||||
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,
|
||||
) -> "Html":
|
||||
"""Create a html component.
|
||||
|
@ -109,7 +109,7 @@ class Match(MemoizationLeaf):
|
||||
return cases, default
|
||||
|
||||
@classmethod
|
||||
def _create_case_var_with_var_data(cls, case_element):
|
||||
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.
|
||||
@ -178,9 +178,9 @@ class Match(MemoizationLeaf):
|
||||
first_case_return = match_cases[0][-1]
|
||||
return_type = type(first_case_return)
|
||||
|
||||
if types._isinstance(first_case_return, BaseComponent):
|
||||
if isinstance(first_case_return, BaseComponent):
|
||||
return_type = BaseComponent
|
||||
elif types._isinstance(first_case_return, Var):
|
||||
elif isinstance(first_case_return, Var):
|
||||
return_type = Var
|
||||
|
||||
for index, case in enumerate(match_cases):
|
||||
@ -222,27 +222,27 @@ class Match(MemoizationLeaf):
|
||||
cond=match_cond_var,
|
||||
match_cases=match_cases,
|
||||
default=default,
|
||||
children=[case[-1] for case in match_cases] + [default], # type: ignore
|
||||
children=[case[-1] for case in match_cases] + [default], # pyright: ignore [reportArgumentType]
|
||||
)
|
||||
)
|
||||
|
||||
# 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 types._isinstance(case[-1], Var)
|
||||
) or not types._isinstance(default, Var):
|
||||
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, # type: ignore
|
||||
default=default, # pyright: ignore [reportArgumentType]
|
||||
),
|
||||
_var_type=default._var_type, # type: ignore
|
||||
_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(), # type: ignore
|
||||
default._get_all_var_data(), # pyright: ignore [reportAttributeAccessIssue, reportOptionalMemberAccess]
|
||||
),
|
||||
)
|
||||
|
||||
|
134
reflex/components/core/sticky.py
Normal file
134
reflex/components/core/sticky.py
Normal file
@ -0,0 +1,134 @@
|
||||
"""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()
|
1233
reflex/components/core/sticky.pyi
Normal file
1233
reflex/components/core/sticky.pyi
Normal file
File diff suppressed because it is too large
Load Diff
@ -29,7 +29,7 @@ from reflex.event import (
|
||||
from reflex.utils import format
|
||||
from reflex.utils.imports import ImportVar
|
||||
from reflex.vars import VarData
|
||||
from reflex.vars.base import CallableVar, Var, get_unique_variable_name
|
||||
from reflex.vars.base import Var, get_unique_variable_name
|
||||
from reflex.vars.sequence import LiteralStringVar
|
||||
|
||||
DEFAULT_UPLOAD_ID: str = "default"
|
||||
@ -45,7 +45,6 @@ upload_files_context_var_data: VarData = VarData(
|
||||
)
|
||||
|
||||
|
||||
@CallableVar
|
||||
def upload_file(id_: str = DEFAULT_UPLOAD_ID) -> Var:
|
||||
"""Get the file upload drop trigger.
|
||||
|
||||
@ -75,7 +74,6 @@ def upload_file(id_: str = DEFAULT_UPLOAD_ID) -> Var:
|
||||
)
|
||||
|
||||
|
||||
@CallableVar
|
||||
def selected_files(id_: str = DEFAULT_UPLOAD_ID) -> Var:
|
||||
"""Get the list of selected files.
|
||||
|
||||
@ -149,7 +147,7 @@ uploaded_files_url_prefix = Var(
|
||||
).to(str)
|
||||
|
||||
|
||||
def get_upload_url(file_path: str) -> Var[str]:
|
||||
def get_upload_url(file_path: str | Var[str]) -> Var[str]:
|
||||
"""Get the URL of an uploaded file.
|
||||
|
||||
Args:
|
||||
@ -160,7 +158,7 @@ def get_upload_url(file_path: str) -> Var[str]:
|
||||
"""
|
||||
Upload.is_used = True
|
||||
|
||||
return uploaded_files_url_prefix + "/" + file_path
|
||||
return Var.create(f"{uploaded_files_url_prefix}/{file_path}")
|
||||
|
||||
|
||||
def _on_drop_spec(files: Var) -> Tuple[Var[Any]]:
|
||||
@ -192,7 +190,7 @@ class GhostUpload(Fragment):
|
||||
class Upload(MemoizationLeaf):
|
||||
"""A file upload component."""
|
||||
|
||||
library = "react-dropzone@14.2.10"
|
||||
library = "react-dropzone@14.3.5"
|
||||
|
||||
tag = ""
|
||||
|
||||
@ -269,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) # type: ignore
|
||||
on_drop = call_event_fn(on_drop, _on_drop_spec)
|
||||
if isinstance(on_drop, EventSpec):
|
||||
# Update the provided args for direct use with on_drop.
|
||||
on_drop = on_drop.with_args(
|
||||
|
@ -9,18 +9,16 @@ 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 BASE_STATE, CallableEventSpec, EventSpec, EventType
|
||||
from reflex.event import CallableEventSpec, EventSpec, EventType
|
||||
from reflex.style import Style
|
||||
from reflex.utils.imports import ImportVar
|
||||
from reflex.vars import VarData
|
||||
from reflex.vars.base import CallableVar, Var
|
||||
from reflex.vars.base import Var
|
||||
|
||||
DEFAULT_UPLOAD_ID: str
|
||||
upload_files_context_var_data: VarData
|
||||
|
||||
@CallableVar
|
||||
def upload_file(id_: str = DEFAULT_UPLOAD_ID) -> Var: ...
|
||||
@CallableVar
|
||||
def selected_files(id_: str = DEFAULT_UPLOAD_ID) -> Var: ...
|
||||
@CallableEventSpec
|
||||
def clear_selected_files(id_: str = DEFAULT_UPLOAD_ID) -> EventSpec: ...
|
||||
@ -37,7 +35,7 @@ uploaded_files_url_prefix = Var(
|
||||
),
|
||||
).to(str)
|
||||
|
||||
def get_upload_url(file_path: str) -> Var[str]: ...
|
||||
def get_upload_url(file_path: str | Var[str]) -> Var[str]: ...
|
||||
|
||||
class UploadFilesProvider(Component):
|
||||
@overload
|
||||
@ -51,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[[], 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,
|
||||
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,
|
||||
) -> "UploadFilesProvider":
|
||||
"""Create the component.
|
||||
@ -97,24 +95,22 @@ 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[[], 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,
|
||||
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,
|
||||
**props,
|
||||
) -> "GhostUpload":
|
||||
"""Create the component.
|
||||
@ -158,24 +154,22 @@ 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[[], 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,
|
||||
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,
|
||||
**props,
|
||||
) -> "Upload":
|
||||
"""Create an upload component.
|
||||
@ -226,24 +220,22 @@ 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[[], 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,
|
||||
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,
|
||||
**props,
|
||||
) -> "StyledUpload":
|
||||
"""Create the styled upload component.
|
||||
@ -294,24 +286,22 @@ 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[[], 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,
|
||||
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,
|
||||
**props,
|
||||
) -> "StyledUpload":
|
||||
"""Create the styled upload component.
|
||||
|
@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import typing
|
||||
from typing import ClassVar, Dict, Literal, Optional, Union
|
||||
|
||||
from reflex.components.component import Component, ComponentNamespace
|
||||
@ -14,7 +15,7 @@ from reflex.components.radix.themes.layout.box import Box
|
||||
from reflex.constants.colors import Color
|
||||
from reflex.event import set_clipboard
|
||||
from reflex.style import Style
|
||||
from reflex.utils import console, format
|
||||
from reflex.utils import format
|
||||
from reflex.utils.imports import ImportVar
|
||||
from reflex.vars.base import LiteralVar, Var, VarData
|
||||
|
||||
@ -382,7 +383,7 @@ for theme_name in dir(Theme):
|
||||
class CodeBlock(Component, MarkdownComponentMap):
|
||||
"""A code block."""
|
||||
|
||||
library = "react-syntax-highlighter@15.6.0"
|
||||
library = "react-syntax-highlighter@15.6.1"
|
||||
|
||||
tag = "PrismAsyncLight"
|
||||
|
||||
@ -438,6 +439,8 @@ class CodeBlock(Component, MarkdownComponentMap):
|
||||
can_copy = props.pop("can_copy", False)
|
||||
copy_button = props.pop("copy_button", None)
|
||||
|
||||
# react-syntax-highlighter doesn't have an explicit "light" or "dark" theme so we use one-light and one-dark
|
||||
# themes respectively to ensure code compatibility.
|
||||
if "theme" not in props:
|
||||
# Default color scheme responds to global color mode.
|
||||
props["theme"] = color_mode_cond(
|
||||
@ -445,20 +448,9 @@ class CodeBlock(Component, MarkdownComponentMap):
|
||||
dark=Theme.one_dark,
|
||||
)
|
||||
|
||||
# react-syntax-highlighter doesn't have an explicit "light" or "dark" theme so we use one-light and one-dark
|
||||
# themes respectively to ensure code compatibility.
|
||||
if "theme" in props and not isinstance(props["theme"], Var):
|
||||
props["theme"] = getattr(Theme, format.to_snake_case(props["theme"])) # type: ignore
|
||||
console.deprecate(
|
||||
feature_name="theme prop as string",
|
||||
reason="Use code_block.themes instead.",
|
||||
deprecation_version="0.6.0",
|
||||
removal_version="0.7.0",
|
||||
)
|
||||
|
||||
if can_copy:
|
||||
code = children[0]
|
||||
copy_button = ( # type: ignore
|
||||
copy_button = (
|
||||
copy_button
|
||||
if copy_button is not None
|
||||
else Button.create(
|
||||
@ -512,7 +504,7 @@ class CodeBlock(Component, MarkdownComponentMap):
|
||||
return ["can_copy", "copy_button"]
|
||||
|
||||
@classmethod
|
||||
def _get_language_registration_hook(cls, language_var: Var = _LANGUAGE) -> str:
|
||||
def _get_language_registration_hook(cls, language_var: Var = _LANGUAGE) -> Var:
|
||||
"""Get the hook to register the language.
|
||||
|
||||
Args:
|
||||
@ -523,21 +515,46 @@ class CodeBlock(Component, MarkdownComponentMap):
|
||||
Returns:
|
||||
The hook to register the language.
|
||||
"""
|
||||
return f"""
|
||||
if ({language_var!s}) {{
|
||||
(async () => {{
|
||||
try {{
|
||||
language_in_there = Var.create(typing.get_args(LiteralCodeLanguage)).contains(
|
||||
language_var
|
||||
)
|
||||
async_load = f"""
|
||||
(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(`Error importing language module for ${{{language_var!s}}}:`, error);
|
||||
}}
|
||||
}})();
|
||||
}} catch (error) {{
|
||||
console.error(`Language ${{{language_var!s}}} is not supported for code blocks inside of markdown: `, error);
|
||||
}}
|
||||
}})();
|
||||
"""
|
||||
return Var(
|
||||
f"""
|
||||
if ({language_var!s}) {{
|
||||
if (!{language_in_there!s}) {{
|
||||
console.warn(`Language \\`${{{language_var!s}}}\\` is not supported for code blocks inside of markdown.`);
|
||||
{language_var!s} = '';
|
||||
}} else {{
|
||||
{async_load!s}
|
||||
}}
|
||||
}}
|
||||
"""
|
||||
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) -> str:
|
||||
def get_component_map_custom_code(cls) -> Var:
|
||||
"""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 BASE_STATE, EventType
|
||||
from reflex.event import 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[[], 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,
|
||||
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,
|
||||
) -> "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) -> str: ...
|
||||
def get_component_map_custom_code(cls) -> Var: ...
|
||||
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[[], 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,
|
||||
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,
|
||||
) -> "CodeBlock":
|
||||
"""Create a text component.
|
||||
|
@ -3,9 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, List, Literal, Optional, Tuple, Union
|
||||
|
||||
from typing_extensions import TypedDict
|
||||
from typing import Any, Dict, List, Literal, Optional, Tuple, TypedDict, Union
|
||||
|
||||
from reflex.base import Base
|
||||
from reflex.components.component import Component, NoSSRComponent
|
||||
@ -165,7 +163,7 @@ class DataEditor(NoSSRComponent):
|
||||
|
||||
tag = "DataEditor"
|
||||
is_default = True
|
||||
library: str = "@glideapps/glide-data-grid@^6.0.3"
|
||||
library: str | None = "@glideapps/glide-data-grid@^6.0.3"
|
||||
lib_dependencies: List[str] = [
|
||||
"lodash@^4.17.21",
|
||||
"react-responsive-carousel@^3.2.7",
|
||||
@ -321,6 +319,8 @@ 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) # type: ignore
|
||||
self.get_cell_content = Var(_js_expr=data_callback)
|
||||
|
||||
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,7 +385,8 @@ class DataEditor(NoSSRComponent):
|
||||
raise ValueError(
|
||||
"DataEditor data must be an ArrayVar if rows is not provided."
|
||||
)
|
||||
props["rows"] = data.length() if isinstance(data, Var) else len(data)
|
||||
|
||||
props["rows"] = data.length() if isinstance(data, ArrayVar) else len(data)
|
||||
|
||||
if not isinstance(columns, Var) and len(columns):
|
||||
if types.is_dataframe(type(data)) or (
|
||||
|
@ -4,13 +4,11 @@
|
||||
# This file was generated by `reflex/utils/pyi_generator.py`!
|
||||
# ------------------------------------------------------
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, List, Literal, Optional, Union, overload
|
||||
|
||||
from typing_extensions import TypedDict
|
||||
from typing import Any, Dict, List, Literal, Optional, TypedDict, Union, overload
|
||||
|
||||
from reflex.base import Base
|
||||
from reflex.components.component import NoSSRComponent
|
||||
from reflex.event import BASE_STATE, EventType
|
||||
from reflex.event import EventType
|
||||
from reflex.style import Style
|
||||
from reflex.utils.imports import ImportDict
|
||||
from reflex.utils.serializers import serializer
|
||||
@ -183,93 +181,79 @@ 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[[], BASE_STATE]] = None,
|
||||
on_blur: Optional[EventType[()]] = None,
|
||||
on_cell_activated: Optional[
|
||||
Union[EventType[[], BASE_STATE], EventType[[tuple[int, int]], BASE_STATE]]
|
||||
Union[EventType[()], EventType[tuple[int, int]]]
|
||||
] = None,
|
||||
on_cell_clicked: Optional[
|
||||
Union[EventType[[], BASE_STATE], EventType[[tuple[int, int]], BASE_STATE]]
|
||||
Union[EventType[()], EventType[tuple[int, int]]]
|
||||
] = None,
|
||||
on_cell_context_menu: Optional[
|
||||
Union[EventType[[], BASE_STATE], EventType[[tuple[int, int]], BASE_STATE]]
|
||||
Union[EventType[()], EventType[tuple[int, int]]]
|
||||
] = None,
|
||||
on_cell_edited: Optional[
|
||||
Union[
|
||||
EventType[[], BASE_STATE],
|
||||
EventType[[tuple[int, int]], BASE_STATE],
|
||||
EventType[[tuple[int, int], GridCell], BASE_STATE],
|
||||
EventType[()],
|
||||
EventType[tuple[int, int]],
|
||||
EventType[tuple[int, int], GridCell],
|
||||
]
|
||||
] = None,
|
||||
on_click: Optional[EventType[[], BASE_STATE]] = None,
|
||||
on_click: Optional[EventType[()]] = None,
|
||||
on_column_resize: Optional[
|
||||
Union[
|
||||
EventType[[], BASE_STATE],
|
||||
EventType[[GridColumn], BASE_STATE],
|
||||
EventType[[GridColumn, int], BASE_STATE],
|
||||
]
|
||||
Union[EventType[()], EventType[GridColumn], EventType[GridColumn, int]]
|
||||
] = 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_context_menu: Optional[EventType[()]] = None,
|
||||
on_delete: Optional[Union[EventType[()], EventType[GridSelection]]] = None,
|
||||
on_double_click: Optional[EventType[()]] = None,
|
||||
on_finished_editing: Optional[
|
||||
Union[
|
||||
EventType[[], BASE_STATE],
|
||||
EventType[[Union[GridCell, None]], BASE_STATE],
|
||||
EventType[[Union[GridCell, None], tuple[int, int]], BASE_STATE],
|
||||
EventType[()],
|
||||
EventType[Union[GridCell, None]],
|
||||
EventType[Union[GridCell, None], tuple[int, int]],
|
||||
]
|
||||
] = None,
|
||||
on_focus: Optional[EventType[[], BASE_STATE]] = None,
|
||||
on_focus: Optional[EventType[()]] = None,
|
||||
on_group_header_clicked: Optional[
|
||||
Union[
|
||||
EventType[[], BASE_STATE],
|
||||
EventType[[tuple[int, int]], BASE_STATE],
|
||||
EventType[[tuple[int, int], GridCell], BASE_STATE],
|
||||
EventType[()],
|
||||
EventType[tuple[int, int]],
|
||||
EventType[tuple[int, int], GridCell],
|
||||
]
|
||||
] = None,
|
||||
on_group_header_context_menu: Optional[
|
||||
Union[
|
||||
EventType[[], BASE_STATE],
|
||||
EventType[[int], BASE_STATE],
|
||||
EventType[[int, GroupHeaderClickedEventArgs], BASE_STATE],
|
||||
EventType[()],
|
||||
EventType[int],
|
||||
EventType[int, GroupHeaderClickedEventArgs],
|
||||
]
|
||||
] = None,
|
||||
on_group_header_renamed: Optional[
|
||||
Union[
|
||||
EventType[[], BASE_STATE],
|
||||
EventType[[str], BASE_STATE],
|
||||
EventType[[str, str], BASE_STATE],
|
||||
]
|
||||
Union[EventType[()], EventType[str], EventType[str, str]]
|
||||
] = None,
|
||||
on_header_clicked: Optional[
|
||||
Union[EventType[[], BASE_STATE], EventType[[tuple[int, int]], BASE_STATE]]
|
||||
Union[EventType[()], EventType[tuple[int, int]]]
|
||||
] = None,
|
||||
on_header_context_menu: Optional[
|
||||
Union[EventType[[], BASE_STATE], EventType[[tuple[int, int]], BASE_STATE]]
|
||||
Union[EventType[()], EventType[tuple[int, int]]]
|
||||
] = None,
|
||||
on_header_menu_click: Optional[
|
||||
Union[
|
||||
EventType[[], BASE_STATE],
|
||||
EventType[[int], BASE_STATE],
|
||||
EventType[[int, Rectangle], BASE_STATE],
|
||||
]
|
||||
Union[EventType[()], EventType[int], EventType[int, Rectangle]]
|
||||
] = None,
|
||||
on_item_hovered: Optional[
|
||||
Union[EventType[[], BASE_STATE], EventType[[tuple[int, int]], BASE_STATE]]
|
||||
Union[EventType[()], EventType[tuple[int, int]]]
|
||||
] = 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,
|
||||
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,
|
||||
**props,
|
||||
) -> "DataEditor":
|
||||
"""Create the DataEditor component.
|
||||
|
@ -5,20 +5,22 @@ from typing import Union
|
||||
import reflex as rx
|
||||
|
||||
|
||||
def svg_logo(color: Union[str, rx.Var[str]] = rx.color_mode_cond("#110F1F", "white")):
|
||||
def svg_logo(
|
||||
color: Union[str, rx.Var[str]] = rx.color_mode_cond("#110F1F", "white"),
|
||||
**props,
|
||||
):
|
||||
"""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):
|
||||
return rx.el.svg.path(
|
||||
d=d,
|
||||
)
|
||||
def logo_path(d: str):
|
||||
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",
|
||||
@ -31,11 +33,14 @@ def svg_logo(color: Union[str, rx.Var[str]] = rx.color_mode_cond("#110F1F", "whi
|
||||
|
||||
return rx.el.svg(
|
||||
*[logo_path(d) for d in paths],
|
||||
width="56",
|
||||
height="12",
|
||||
viewBox="0 0 56 12",
|
||||
rx.el.title("Reflex"),
|
||||
aria_label="Reflex",
|
||||
role="img",
|
||||
width=props.pop("width", "56"),
|
||||
height=props.pop("height", "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: # type: ignore
|
||||
for transformer in code_block.transformers._var_value: # pyright: ignore [reportAttributeAccessIssue]
|
||||
if isinstance(transformer, ShikiBaseTransformers) and transformer.style:
|
||||
transformer_styles.update(transformer.style)
|
||||
transformer_styles.update(code_wrapper_props.pop("style", {}))
|
||||
@ -621,18 +621,22 @@ 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
|
||||
@ -653,8 +657,9 @@ class ShikiCodeBlock(Component, MarkdownComponentMap):
|
||||
raise ValueError(
|
||||
f"the function names should be str names of functions in the specified transformer: {library!r}"
|
||||
)
|
||||
return ShikiBaseTransformers( # type: ignore
|
||||
library=library, fns=[FunctionStringVar.create(fn) for fn in fns]
|
||||
return ShikiBaseTransformers(
|
||||
library=library,
|
||||
fns=[FunctionStringVar.create(fn) for fn in fns], # pyright: ignore [reportCallIssue]
|
||||
)
|
||||
|
||||
def _render(self, props: dict[str, Any] | None = None):
|
||||
@ -757,13 +762,13 @@ class ShikiHighLevelCodeBlock(ShikiCodeBlock):
|
||||
|
||||
if can_copy:
|
||||
code = children[0]
|
||||
copy_button = ( # type: ignore
|
||||
copy_button = (
|
||||
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)), # type: ignore
|
||||
set_clipboard(cls._strip_transformer_triggers(code)),
|
||||
copy_script(),
|
||||
],
|
||||
style=Style(
|
||||
|
@ -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 BASE_STATE, EventType
|
||||
from reflex.event import 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[[], 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,
|
||||
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,
|
||||
) -> "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[[], 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,
|
||||
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,
|
||||
) -> "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[[], 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,
|
||||
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,
|
||||
) -> "ShikiHighLevelCodeBlock":
|
||||
"""Create a code block component using [shiki syntax highlighter](https://shiki.matsu.io/).
|
||||
|
@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Union
|
||||
|
||||
from reflex import constants
|
||||
from reflex.utils import imports
|
||||
from reflex.utils.exceptions import DynamicComponentMissingLibrary
|
||||
from reflex.utils.exceptions import DynamicComponentMissingLibraryError
|
||||
from reflex.utils.format import format_library_name
|
||||
from reflex.utils.serializers import serializer
|
||||
from reflex.vars import Var, get_unique_variable_name
|
||||
@ -36,13 +36,15 @@ def bundle_library(component: Union["Component", str]):
|
||||
component: The component to bundle the library with.
|
||||
|
||||
Raises:
|
||||
DynamicComponentMissingLibrary: Raised when a dynamic component is missing a library.
|
||||
DynamicComponentMissingLibraryError: Raised when a dynamic component is missing a library.
|
||||
"""
|
||||
if isinstance(component, str):
|
||||
bundled_libraries.add(component)
|
||||
return
|
||||
if component.library is None:
|
||||
raise DynamicComponentMissingLibrary("Component must have a library to bundle.")
|
||||
raise DynamicComponentMissingLibraryError(
|
||||
"Component must have a library to bundle."
|
||||
)
|
||||
bundled_libraries.add(format_library_name(component.library))
|
||||
|
||||
|
||||
@ -136,6 +138,23 @@ def load_dynamic_serializer():
|
||||
|
||||
module_code_lines.insert(0, "const React = window.__reflex.react;")
|
||||
|
||||
function_line = next(
|
||||
index
|
||||
for index, line in enumerate(module_code_lines)
|
||||
if line.startswith("export default function")
|
||||
)
|
||||
|
||||
module_code_lines = [
|
||||
line
|
||||
for _, line in sorted(
|
||||
enumerate(module_code_lines),
|
||||
key=lambda x: (
|
||||
not (x[1].startswith("import ") and x[0] < function_line),
|
||||
x[0],
|
||||
),
|
||||
)
|
||||
]
|
||||
|
||||
return "\n".join(
|
||||
[
|
||||
"//__reflex_evaluate",
|
||||
|
@ -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) # type: ignore
|
||||
ELEMENT_TO_PROPS[el].append(prop)
|
||||
|
@ -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):
|
||||
def __eq__(self, other: object):
|
||||
"""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 BASE_STATE, EventType
|
||||
from reflex.event import 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[[], 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,
|
||||
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,
|
||||
) -> "Element":
|
||||
"""Create the component.
|
||||
|
@ -1,58 +1,136 @@
|
||||
"""Base classes."""
|
||||
|
||||
from typing import Union
|
||||
from typing import Literal
|
||||
|
||||
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[Union[str, int, bool]]
|
||||
access_key: Var[str]
|
||||
|
||||
# Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
|
||||
auto_capitalize: Var[Union[str, int, bool]]
|
||||
auto_capitalize: Var[AutoCapitalize]
|
||||
|
||||
# Indicates whether the element's content is editable.
|
||||
content_editable: Var[Union[str, int, bool]]
|
||||
content_editable: Var[ContentEditable]
|
||||
|
||||
# Defines the ID of a <menu> element which will serve as the element's context menu.
|
||||
context_menu: Var[Union[str, int, bool]]
|
||||
context_menu: Var[str]
|
||||
|
||||
# Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)
|
||||
dir: Var[Union[str, int, bool]]
|
||||
dir: Var[str]
|
||||
|
||||
# Defines whether the element can be dragged.
|
||||
draggable: Var[Union[str, int, bool]]
|
||||
draggable: Var[bool]
|
||||
|
||||
# Hints what media types the media element is able to play.
|
||||
enter_key_hint: Var[Union[str, int, bool]]
|
||||
enter_key_hint: Var[EnterKeyHint]
|
||||
|
||||
# Defines whether the element is hidden.
|
||||
hidden: Var[Union[str, int, bool]]
|
||||
hidden: Var[bool]
|
||||
|
||||
# Defines the type of the element.
|
||||
input_mode: Var[Union[str, int, bool]]
|
||||
input_mode: Var[InputMode]
|
||||
|
||||
# Defines the name of the element for metadata purposes.
|
||||
item_prop: Var[Union[str, int, bool]]
|
||||
item_prop: Var[str]
|
||||
|
||||
# Defines the language used in the element.
|
||||
lang: Var[Union[str, int, bool]]
|
||||
lang: Var[str]
|
||||
|
||||
# Defines the role of the element.
|
||||
role: Var[Union[str, int, bool]]
|
||||
role: Var[AriaRole]
|
||||
|
||||
# Assigns a slot in a shadow DOM shadow tree to an element.
|
||||
slot: Var[Union[str, int, bool]]
|
||||
slot: Var[str]
|
||||
|
||||
# Defines whether the element may be checked for spelling errors.
|
||||
spell_check: Var[Union[str, int, bool]]
|
||||
spell_check: Var[bool]
|
||||
|
||||
# Defines the position of the current element in the tabbing order.
|
||||
tab_index: Var[Union[str, int, bool]]
|
||||
tab_index: Var[int]
|
||||
|
||||
# Defines a tooltip for the element.
|
||||
title: Var[Union[str, int, bool]]
|
||||
title: Var[str]
|
||||
|
@ -3,64 +3,323 @@
|
||||
# ------------------- DO NOT EDIT ----------------------
|
||||
# This file was generated by `reflex/utils/pyi_generator.py`!
|
||||
# ------------------------------------------------------
|
||||
from typing import Any, Dict, Optional, Union, overload
|
||||
from typing import Any, Dict, Literal, Optional, Union, overload
|
||||
|
||||
from reflex.components.el.element import Element
|
||||
from reflex.event import BASE_STATE, EventType
|
||||
from reflex.event import 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[Union[bool, int, str]], bool, int, str]] = None,
|
||||
access_key: Optional[Union[Var[str], str]] = None,
|
||||
auto_capitalize: Optional[
|
||||
Union[Var[Union[bool, int, str]], bool, int, str]
|
||||
Union[
|
||||
Literal["characters", "none", "off", "on", "sentences", "words"],
|
||||
Var[Literal["characters", "none", "off", "on", "sentences", "words"]],
|
||||
]
|
||||
] = None,
|
||||
content_editable: Optional[
|
||||
Union[Var[Union[bool, int, str]], bool, int, str]
|
||||
Union[
|
||||
Literal["inherit", "plaintext-only", False, True],
|
||||
Var[Literal["inherit", "plaintext-only", False, True]],
|
||||
]
|
||||
] = 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,
|
||||
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[Var[Union[bool, int, str]], bool, int, str]
|
||||
Union[
|
||||
Literal["done", "enter", "go", "next", "previous", "search", "send"],
|
||||
Var[
|
||||
Literal["done", "enter", "go", "next", "previous", "search", "send"]
|
||||
],
|
||||
]
|
||||
] = 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,
|
||||
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[[], 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,
|
||||
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,
|
||||
) -> "BaseHTML":
|
||||
"""Create the component.
|
||||
|
@ -3,7 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from hashlib import md5
|
||||
from typing import Any, Dict, Iterator, Set, Tuple, Union
|
||||
from typing import Any, Dict, Iterator, Literal, Set, Tuple, Union
|
||||
|
||||
from jinja2 import Environment
|
||||
|
||||
@ -41,6 +41,8 @@ HANDLE_SUBMIT_JS_JINJA2 = Environment().from_string(
|
||||
"""
|
||||
)
|
||||
|
||||
ButtonType = Literal["submit", "reset", "button"]
|
||||
|
||||
|
||||
class Button(BaseHTML):
|
||||
"""Display the button element."""
|
||||
@ -48,37 +50,37 @@ class Button(BaseHTML):
|
||||
tag = "button"
|
||||
|
||||
# Automatically focuses the button when the page loads
|
||||
auto_focus: Var[Union[str, int, bool]]
|
||||
auto_focus: Var[bool]
|
||||
|
||||
# Disables the button
|
||||
disabled: Var[bool]
|
||||
|
||||
# Associates the button with a form (by id)
|
||||
form: Var[Union[str, int, bool]]
|
||||
form: Var[str]
|
||||
|
||||
# URL to send the form data to (for type="submit" buttons)
|
||||
form_action: Var[Union[str, int, bool]]
|
||||
form_action: Var[str]
|
||||
|
||||
# How the form data should be encoded when submitting to the server (for type="submit" buttons)
|
||||
form_enc_type: Var[Union[str, int, bool]]
|
||||
form_enc_type: Var[str]
|
||||
|
||||
# HTTP method to use for sending form data (for type="submit" buttons)
|
||||
form_method: Var[Union[str, int, bool]]
|
||||
form_method: Var[str]
|
||||
|
||||
# Bypasses form validation when submitting (for type="submit" buttons)
|
||||
form_no_validate: Var[Union[str, int, bool]]
|
||||
form_no_validate: Var[bool]
|
||||
|
||||
# Specifies where to display the response after submitting the form (for type="submit" buttons)
|
||||
form_target: Var[Union[str, int, bool]]
|
||||
form_target: Var[str]
|
||||
|
||||
# Name of the button, used when sending form data
|
||||
name: Var[Union[str, int, bool]]
|
||||
name: Var[str]
|
||||
|
||||
# Type of the button (submit, reset, or button)
|
||||
type: Var[Union[str, int, bool]]
|
||||
type: Var[ButtonType]
|
||||
|
||||
# Value of the button, used when sending form data
|
||||
value: Var[Union[str, int, bool]]
|
||||
value: Var[Union[str, int, float]]
|
||||
|
||||
|
||||
class Datalist(BaseHTML):
|
||||
@ -93,16 +95,16 @@ class Fieldset(Element):
|
||||
tag = "fieldset"
|
||||
|
||||
# Disables all the form control descendants of the fieldset
|
||||
disabled: Var[Union[str, int, bool]]
|
||||
disabled: Var[bool]
|
||||
|
||||
# Associates the fieldset with a form (by id)
|
||||
form: Var[Union[str, int, bool]]
|
||||
form: Var[str]
|
||||
|
||||
# Name of the fieldset, used for scripting
|
||||
name: Var[Union[str, int, bool]]
|
||||
name: Var[str]
|
||||
|
||||
|
||||
def on_submit_event_spec() -> Tuple[Var[Dict[str, Any]]]:
|
||||
def on_submit_event_spec() -> Tuple[Var[dict[str, Any]]]:
|
||||
"""Event handler spec for the on_submit event.
|
||||
|
||||
Returns:
|
||||
@ -111,7 +113,7 @@ def on_submit_event_spec() -> Tuple[Var[Dict[str, Any]]]:
|
||||
return (FORM_DATA,)
|
||||
|
||||
|
||||
def on_submit_string_event_spec() -> Tuple[Var[Dict[str, str]]]:
|
||||
def on_submit_string_event_spec() -> Tuple[Var[dict[str, str]]]:
|
||||
"""Event handler spec for the on_submit event.
|
||||
|
||||
Returns:
|
||||
@ -126,34 +128,34 @@ class Form(BaseHTML):
|
||||
tag = "form"
|
||||
|
||||
# MIME types the server accepts for file upload
|
||||
accept: Var[Union[str, int, bool]]
|
||||
accept: Var[str]
|
||||
|
||||
# Character encodings to be used for form submission
|
||||
accept_charset: Var[Union[str, int, bool]]
|
||||
accept_charset: Var[str]
|
||||
|
||||
# URL where the form's data should be submitted
|
||||
action: Var[Union[str, int, bool]]
|
||||
action: Var[str]
|
||||
|
||||
# Whether the form should have autocomplete enabled
|
||||
auto_complete: Var[Union[str, int, bool]]
|
||||
auto_complete: Var[str]
|
||||
|
||||
# Encoding type for the form data when submitted
|
||||
enc_type: Var[Union[str, int, bool]]
|
||||
enc_type: Var[str]
|
||||
|
||||
# HTTP method to use for form submission
|
||||
method: Var[Union[str, int, bool]]
|
||||
method: Var[str]
|
||||
|
||||
# Name of the form
|
||||
name: Var[Union[str, int, bool]]
|
||||
name: Var[str]
|
||||
|
||||
# Indicates that the form should not be validated on submit
|
||||
no_validate: Var[Union[str, int, bool]]
|
||||
no_validate: Var[bool]
|
||||
|
||||
# Where to display the response after submitting the form
|
||||
target: Var[Union[str, int, bool]]
|
||||
target: Var[str]
|
||||
|
||||
# If true, the form will be cleared after submit.
|
||||
reset_on_submit: Var[bool] = False # type: ignore
|
||||
reset_on_submit: Var[bool] = Var.create(False)
|
||||
|
||||
# The name used to make this form's submit handler function unique.
|
||||
handle_submit_unique_name: Var[str]
|
||||
@ -266,106 +268,126 @@ 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[Union[str, int, bool]]
|
||||
accept: Var[str]
|
||||
|
||||
# Alternate text for input type="image"
|
||||
alt: Var[Union[str, int, bool]]
|
||||
alt: Var[str]
|
||||
|
||||
# Whether the input should have autocomplete enabled
|
||||
auto_complete: Var[Union[str, int, bool]]
|
||||
auto_complete: Var[str]
|
||||
|
||||
# Automatically focuses the input when the page loads
|
||||
auto_focus: Var[Union[str, int, bool]]
|
||||
auto_focus: Var[bool]
|
||||
|
||||
# Captures media from the user (camera or microphone)
|
||||
capture: Var[Union[str, int, bool]]
|
||||
capture: Var[Literal[True, False, "user", "environment"]]
|
||||
|
||||
# Indicates whether the input is checked (for checkboxes and radio buttons)
|
||||
checked: Var[Union[str, int, bool]]
|
||||
checked: Var[bool]
|
||||
|
||||
# The initial value (for checkboxes and radio buttons)
|
||||
default_checked: Var[bool]
|
||||
|
||||
# The initial value for a text field
|
||||
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]]
|
||||
default_value: Var[Union[str, int, float]]
|
||||
|
||||
# Disables the input
|
||||
disabled: Var[Union[str, int, bool]]
|
||||
disabled: Var[bool]
|
||||
|
||||
# Associates the input with a form (by id)
|
||||
form: Var[Union[str, int, bool]]
|
||||
form: Var[str]
|
||||
|
||||
# URL to send the form data to (for type="submit" buttons)
|
||||
form_action: Var[Union[str, int, bool]]
|
||||
form_action: Var[str]
|
||||
|
||||
# How the form data should be encoded when submitting to the server (for type="submit" buttons)
|
||||
form_enc_type: Var[Union[str, int, bool]]
|
||||
form_enc_type: Var[str]
|
||||
|
||||
# HTTP method to use for sending form data (for type="submit" buttons)
|
||||
form_method: Var[Union[str, int, bool]]
|
||||
form_method: Var[str]
|
||||
|
||||
# Bypasses form validation when submitting (for type="submit" buttons)
|
||||
form_no_validate: Var[Union[str, int, bool]]
|
||||
form_no_validate: Var[bool]
|
||||
|
||||
# Specifies where to display the response after submitting the form (for type="submit" buttons)
|
||||
form_target: Var[Union[str, int, bool]]
|
||||
form_target: Var[str]
|
||||
|
||||
# References a datalist for suggested options
|
||||
list: Var[Union[str, int, bool]]
|
||||
list: Var[str]
|
||||
|
||||
# Specifies the maximum value for the input
|
||||
max: Var[Union[str, int, bool]]
|
||||
max: Var[Union[str, int, float]]
|
||||
|
||||
# Specifies the maximum number of characters allowed in the input
|
||||
max_length: Var[Union[str, int, bool]]
|
||||
max_length: Var[Union[int, float]]
|
||||
|
||||
# Specifies the minimum number of characters required in the input
|
||||
min_length: Var[Union[str, int, bool]]
|
||||
min_length: Var[Union[int, float]]
|
||||
|
||||
# Specifies the minimum value for the input
|
||||
min: Var[Union[str, int, bool]]
|
||||
min: Var[Union[str, int, float]]
|
||||
|
||||
# Indicates whether multiple values can be entered in an input of the type email or file
|
||||
multiple: Var[Union[str, int, bool]]
|
||||
multiple: Var[bool]
|
||||
|
||||
# Name of the input, used when sending form data
|
||||
name: Var[Union[str, int, bool]]
|
||||
name: Var[str]
|
||||
|
||||
# Regex pattern the input's value must match to be valid
|
||||
pattern: Var[Union[str, int, bool]]
|
||||
pattern: Var[str]
|
||||
|
||||
# Placeholder text in the input
|
||||
placeholder: Var[Union[str, int, bool]]
|
||||
placeholder: Var[str]
|
||||
|
||||
# Indicates whether the input is read-only
|
||||
read_only: Var[Union[str, int, bool]]
|
||||
read_only: Var[bool]
|
||||
|
||||
# Indicates that the input is required
|
||||
required: Var[Union[str, int, bool]]
|
||||
required: Var[bool]
|
||||
|
||||
# Specifies the visible width of a text control
|
||||
size: Var[Union[str, int, bool]]
|
||||
size: Var[Union[int, float]]
|
||||
|
||||
# URL for image inputs
|
||||
src: Var[Union[str, int, bool]]
|
||||
src: Var[str]
|
||||
|
||||
# Specifies the legal number intervals for an input
|
||||
step: Var[Union[str, int, bool]]
|
||||
step: Var[Union[str, int, float]]
|
||||
|
||||
# Specifies the type of input
|
||||
type: Var[Union[str, int, bool]]
|
||||
|
||||
# Name of the image map used with the input
|
||||
use_map: Var[Union[str, int, bool]]
|
||||
type: Var[HTMLInputTypeAttribute]
|
||||
|
||||
# Value of the input
|
||||
value: Var[Union[str, int, float]]
|
||||
@ -405,7 +427,7 @@ class Input(BaseHTML):
|
||||
(value_var := Var.create(value))._var_type
|
||||
):
|
||||
props["value"] = ternary_operation(
|
||||
(value_var != Var.create(None)) # pyright: ignore [reportGeneralTypeIssues]
|
||||
(value_var != Var.create(None)) # pyright: ignore [reportArgumentType]
|
||||
& (value_var != Var(_js_expr="undefined")),
|
||||
value,
|
||||
Var.create(""),
|
||||
@ -419,10 +441,10 @@ class Label(BaseHTML):
|
||||
tag = "label"
|
||||
|
||||
# ID of a form control with which the label is associated
|
||||
html_for: Var[Union[str, int, bool]]
|
||||
html_for: Var[str]
|
||||
|
||||
# Associates the label with a form (by id)
|
||||
form: Var[Union[str, int, bool]]
|
||||
form: Var[str]
|
||||
|
||||
|
||||
class Legend(BaseHTML):
|
||||
@ -437,25 +459,25 @@ class Meter(BaseHTML):
|
||||
tag = "meter"
|
||||
|
||||
# Associates the meter with a form (by id)
|
||||
form: Var[Union[str, int, bool]]
|
||||
form: Var[str]
|
||||
|
||||
# High limit of range (above this is considered high value)
|
||||
high: Var[Union[str, int, bool]]
|
||||
high: Var[Union[int, float]]
|
||||
|
||||
# Low limit of range (below this is considered low value)
|
||||
low: Var[Union[str, int, bool]]
|
||||
low: Var[Union[int, float]]
|
||||
|
||||
# Maximum value of the range
|
||||
max: Var[Union[str, int, bool]]
|
||||
max: Var[Union[int, float]]
|
||||
|
||||
# Minimum value of the range
|
||||
min: Var[Union[str, int, bool]]
|
||||
min: Var[Union[int, float]]
|
||||
|
||||
# Optimum value in the range
|
||||
optimum: Var[Union[str, int, bool]]
|
||||
optimum: Var[Union[int, float]]
|
||||
|
||||
# Current value of the meter
|
||||
value: Var[Union[str, int, bool]]
|
||||
value: Var[Union[int, float]]
|
||||
|
||||
|
||||
class Optgroup(BaseHTML):
|
||||
@ -464,10 +486,10 @@ class Optgroup(BaseHTML):
|
||||
tag = "optgroup"
|
||||
|
||||
# Disables the optgroup
|
||||
disabled: Var[Union[str, int, bool]]
|
||||
disabled: Var[bool]
|
||||
|
||||
# Label for the optgroup
|
||||
label: Var[Union[str, int, bool]]
|
||||
label: Var[str]
|
||||
|
||||
|
||||
class Option(BaseHTML):
|
||||
@ -476,16 +498,16 @@ class Option(BaseHTML):
|
||||
tag = "option"
|
||||
|
||||
# Disables the option
|
||||
disabled: Var[Union[str, int, bool]]
|
||||
disabled: Var[bool]
|
||||
|
||||
# Label for the option, if the text is not the label
|
||||
label: Var[Union[str, int, bool]]
|
||||
label: Var[str]
|
||||
|
||||
# Indicates that the option is initially selected
|
||||
selected: Var[Union[str, int, bool]]
|
||||
selected: Var[bool]
|
||||
|
||||
# Value to be sent as form data
|
||||
value: Var[Union[str, int, bool]]
|
||||
value: Var[Union[str, int, float]]
|
||||
|
||||
|
||||
class Output(BaseHTML):
|
||||
@ -494,13 +516,13 @@ class Output(BaseHTML):
|
||||
tag = "output"
|
||||
|
||||
# Associates the output with one or more elements (by their IDs)
|
||||
html_for: Var[Union[str, int, bool]]
|
||||
html_for: Var[str]
|
||||
|
||||
# Associates the output with a form (by id)
|
||||
form: Var[Union[str, int, bool]]
|
||||
form: Var[str]
|
||||
|
||||
# Name of the output element for form submission
|
||||
name: Var[Union[str, int, bool]]
|
||||
name: Var[str]
|
||||
|
||||
|
||||
class Progress(BaseHTML):
|
||||
@ -509,13 +531,13 @@ class Progress(BaseHTML):
|
||||
tag = "progress"
|
||||
|
||||
# Associates the progress element with a form (by id)
|
||||
form: Var[Union[str, int, bool]]
|
||||
form: Var[str]
|
||||
|
||||
# Maximum value of the progress indicator
|
||||
max: Var[Union[str, int, bool]]
|
||||
max: Var[Union[str, int, float]]
|
||||
|
||||
# Current value of the progress indicator
|
||||
value: Var[Union[str, int, bool]]
|
||||
value: Var[Union[str, int, float]]
|
||||
|
||||
|
||||
class Select(BaseHTML):
|
||||
@ -524,28 +546,28 @@ class Select(BaseHTML):
|
||||
tag = "select"
|
||||
|
||||
# Whether the form control should have autocomplete enabled
|
||||
auto_complete: Var[Union[str, int, bool]]
|
||||
auto_complete: Var[str]
|
||||
|
||||
# Automatically focuses the select when the page loads
|
||||
auto_focus: Var[Union[str, int, bool]]
|
||||
auto_focus: Var[bool]
|
||||
|
||||
# Disables the select control
|
||||
disabled: Var[Union[str, int, bool]]
|
||||
disabled: Var[bool]
|
||||
|
||||
# Associates the select with a form (by id)
|
||||
form: Var[Union[str, int, bool]]
|
||||
form: Var[str]
|
||||
|
||||
# Indicates that multiple options can be selected
|
||||
multiple: Var[Union[str, int, bool]]
|
||||
multiple: Var[bool]
|
||||
|
||||
# Name of the select, used when submitting the form
|
||||
name: Var[Union[str, int, bool]]
|
||||
name: Var[str]
|
||||
|
||||
# Indicates that the select control must have a selected option
|
||||
required: Var[Union[str, int, bool]]
|
||||
required: Var[bool]
|
||||
|
||||
# Number of visible options in a drop-down list
|
||||
size: Var[Union[str, int, bool]]
|
||||
size: Var[int]
|
||||
|
||||
# Fired when the select value changes
|
||||
on_change: EventHandler[input_event]
|
||||
@ -587,58 +609,58 @@ class Textarea(BaseHTML):
|
||||
tag = "textarea"
|
||||
|
||||
# Whether the form control should have autocomplete enabled
|
||||
auto_complete: Var[Union[str, int, bool]]
|
||||
auto_complete: Var[str]
|
||||
|
||||
# Automatically focuses the textarea when the page loads
|
||||
auto_focus: Var[Union[str, int, bool]]
|
||||
auto_focus: Var[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[Union[str, int, bool]]
|
||||
cols: Var[int]
|
||||
|
||||
# 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[Union[str, int, bool]]
|
||||
dirname: Var[str]
|
||||
|
||||
# Disables the textarea
|
||||
disabled: Var[Union[str, int, bool]]
|
||||
disabled: Var[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[Union[str, int, bool]]
|
||||
form: Var[str]
|
||||
|
||||
# Maximum number of characters allowed in the textarea
|
||||
max_length: Var[Union[str, int, bool]]
|
||||
max_length: Var[int]
|
||||
|
||||
# Minimum number of characters required in the textarea
|
||||
min_length: Var[Union[str, int, bool]]
|
||||
min_length: Var[int]
|
||||
|
||||
# Name of the textarea, used when submitting the form
|
||||
name: Var[Union[str, int, bool]]
|
||||
name: Var[str]
|
||||
|
||||
# Placeholder text in the textarea
|
||||
placeholder: Var[Union[str, int, bool]]
|
||||
placeholder: Var[str]
|
||||
|
||||
# Indicates whether the textarea is read-only
|
||||
read_only: Var[Union[str, int, bool]]
|
||||
read_only: Var[bool]
|
||||
|
||||
# Indicates that the textarea is required
|
||||
required: Var[Union[str, int, bool]]
|
||||
required: Var[bool]
|
||||
|
||||
# Visible number of lines in the text control
|
||||
rows: Var[Union[str, int, bool]]
|
||||
rows: Var[int]
|
||||
|
||||
# The controlled value of the textarea, read only unless used with on_change
|
||||
value: Var[Union[str, int, bool]]
|
||||
value: Var[str]
|
||||
|
||||
# How the text in the textarea is to be wrapped when submitting the form
|
||||
wrap: Var[Union[str, int, bool]]
|
||||
wrap: Var[str]
|
||||
|
||||
# Fired when the input value changes
|
||||
on_change: EventHandler[input_event]
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,23 @@
|
||||
"""Inline classes."""
|
||||
|
||||
from typing import Union
|
||||
from typing import Literal, 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."""
|
||||
@ -13,31 +25,28 @@ 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, int, bool]]
|
||||
download: Var[Union[str, bool]]
|
||||
|
||||
# Specifies the URL of the page the link goes to
|
||||
href: Var[Union[str, int, bool]]
|
||||
href: Var[str]
|
||||
|
||||
# Specifies the language of the linked document
|
||||
href_lang: Var[Union[str, int, bool]]
|
||||
href_lang: Var[str]
|
||||
|
||||
# Specifies what media/device the linked document is optimized for
|
||||
media: Var[Union[str, int, bool]]
|
||||
media: Var[str]
|
||||
|
||||
# Specifies which referrer is sent when fetching the resource
|
||||
ping: Var[Union[str, int, bool]]
|
||||
ping: Var[str]
|
||||
|
||||
# Specifies the relationship between the current document and the linked document
|
||||
referrer_policy: Var[Union[str, int, bool]]
|
||||
referrer_policy: Var[ReferrerPolicy]
|
||||
|
||||
# Specifies the relationship between the linked document and the current document
|
||||
rel: Var[Union[str, int, bool]]
|
||||
|
||||
# Specifies the shape of the area
|
||||
shape: Var[Union[str, int, bool]]
|
||||
rel: Var[str]
|
||||
|
||||
# Specifies where to open the linked document
|
||||
target: Var[Union[str, int, bool]]
|
||||
target: Var[Union[str, Literal["_self", "_blank", "_parent", "_top"]]]
|
||||
|
||||
|
||||
class Abbr(BaseHTML):
|
||||
@ -88,7 +97,7 @@ class Data(BaseHTML):
|
||||
tag = "data"
|
||||
|
||||
# Specifies the machine-readable translation of the data element.
|
||||
value: Var[Union[str, int, bool]]
|
||||
value: Var[Union[str, int, float]]
|
||||
|
||||
|
||||
class Dfn(BaseHTML):
|
||||
@ -127,7 +136,7 @@ class Q(BaseHTML):
|
||||
tag = "q"
|
||||
|
||||
# Specifies the source URL of the quote.
|
||||
cite: Var[Union[str, int, bool]]
|
||||
cite: Var[str]
|
||||
|
||||
|
||||
class Rp(BaseHTML):
|
||||
@ -196,7 +205,7 @@ class Time(BaseHTML):
|
||||
tag = "time"
|
||||
|
||||
# Specifies the date and/or time of the element.
|
||||
date_time: Var[Union[str, int, bool]]
|
||||
date_time: Var[str]
|
||||
|
||||
|
||||
class U(BaseHTML):
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,9 @@
|
||||
"""Media classes."""
|
||||
|
||||
from typing import Any, Union
|
||||
from typing import Any, Literal, 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
|
||||
|
||||
@ -15,37 +16,37 @@ class Area(BaseHTML):
|
||||
tag = "area"
|
||||
|
||||
# Alternate text for the area, used for accessibility
|
||||
alt: Var[Union[str, int, bool]]
|
||||
alt: Var[str]
|
||||
|
||||
# Coordinates to define the shape of the area
|
||||
coords: Var[Union[str, int, bool]]
|
||||
coords: Var[str]
|
||||
|
||||
# Specifies that the target will be downloaded when clicked
|
||||
download: Var[Union[str, int, bool]]
|
||||
download: Var[Union[str, bool]]
|
||||
|
||||
# Hyperlink reference for the area
|
||||
href: Var[Union[str, int, bool]]
|
||||
href: Var[str]
|
||||
|
||||
# Language of the linked resource
|
||||
href_lang: Var[Union[str, int, bool]]
|
||||
href_lang: Var[str]
|
||||
|
||||
# Specifies what media/device the linked resource is optimized for
|
||||
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]]
|
||||
media: Var[str]
|
||||
|
||||
# Specifies which referrer information to send with the link
|
||||
referrer_policy: Var[Union[str, int, bool]]
|
||||
referrer_policy: Var[ReferrerPolicy]
|
||||
|
||||
# Specifies the relationship of the target object to the link object
|
||||
rel: Var[Union[str, int, bool]]
|
||||
rel: Var[str]
|
||||
|
||||
# Defines the shape of the area (rectangle, circle, polygon)
|
||||
shape: Var[Union[str, int, bool]]
|
||||
shape: Var[str]
|
||||
|
||||
# Specifies where to open the linked document
|
||||
target: Var[Union[str, int, bool]]
|
||||
target: Var[str]
|
||||
|
||||
|
||||
CrossOrigin = Literal["anonymous", "use-credentials", ""]
|
||||
|
||||
|
||||
class Audio(BaseHTML):
|
||||
@ -54,28 +55,29 @@ class Audio(BaseHTML):
|
||||
tag = "audio"
|
||||
|
||||
# Specifies that the audio will start playing as soon as it is ready
|
||||
auto_play: Var[Union[str, int, bool]]
|
||||
|
||||
# Represents the time range of the buffered media
|
||||
buffered: Var[Union[str, int, bool]]
|
||||
auto_play: Var[bool]
|
||||
|
||||
# Displays the standard audio controls
|
||||
controls: Var[Union[str, int, bool]]
|
||||
controls: Var[bool]
|
||||
|
||||
# Configures the CORS requests for the element
|
||||
cross_origin: Var[Union[str, int, bool]]
|
||||
cross_origin: Var[CrossOrigin]
|
||||
|
||||
# Specifies that the audio will loop
|
||||
loop: Var[Union[str, int, bool]]
|
||||
loop: Var[bool]
|
||||
|
||||
# Indicates whether the audio is muted by default
|
||||
muted: Var[Union[str, int, bool]]
|
||||
muted: Var[bool]
|
||||
|
||||
# Specifies how the audio file should be preloaded
|
||||
preload: Var[Union[str, int, bool]]
|
||||
preload: Var[str]
|
||||
|
||||
# URL of the audio to play
|
||||
src: Var[Union[str, int, bool]]
|
||||
src: Var[str]
|
||||
|
||||
|
||||
ImageDecoding = Literal["async", "auto", "sync"]
|
||||
ImageLoading = Literal["eager", "lazy"]
|
||||
|
||||
|
||||
class Img(BaseHTML):
|
||||
@ -83,41 +85,32 @@ 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[Union[str, int, bool]]
|
||||
alt: Var[str]
|
||||
|
||||
# Configures the CORS requests for the image
|
||||
cross_origin: Var[Union[str, int, bool]]
|
||||
cross_origin: Var[CrossOrigin]
|
||||
|
||||
# How the image should be decoded
|
||||
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]]
|
||||
decoding: Var[ImageDecoding]
|
||||
|
||||
# Specifies the loading behavior of the image
|
||||
loading: Var[Union[str, int, bool]]
|
||||
loading: Var[ImageLoading]
|
||||
|
||||
# Referrer policy for the image
|
||||
referrer_policy: Var[Union[str, int, bool]]
|
||||
referrer_policy: Var[ReferrerPolicy]
|
||||
|
||||
# Sizes of the image for different layouts
|
||||
sizes: Var[Union[str, int, bool]]
|
||||
sizes: Var[str]
|
||||
|
||||
# URL of the image to display
|
||||
src: Var[Any]
|
||||
|
||||
# A set of source sizes and URLs for responsive images
|
||||
src_set: Var[Union[str, int, bool]]
|
||||
src_set: Var[str]
|
||||
|
||||
# The name of the map to use with the image
|
||||
use_map: Var[Union[str, int, bool]]
|
||||
use_map: Var[str]
|
||||
|
||||
@classmethod
|
||||
def create(cls, *children, **props) -> Component:
|
||||
@ -143,7 +136,7 @@ class Map(BaseHTML):
|
||||
tag = "map"
|
||||
|
||||
# Name of the map, referenced by the 'usemap' attribute in 'img' and 'object' elements
|
||||
name: Var[Union[str, int, bool]]
|
||||
name: Var[str]
|
||||
|
||||
|
||||
class Track(BaseHTML):
|
||||
@ -152,19 +145,19 @@ class Track(BaseHTML):
|
||||
tag = "track"
|
||||
|
||||
# Indicates that the track should be enabled unless the user's preferences indicate otherwise
|
||||
default: Var[Union[str, int, bool]]
|
||||
default: Var[bool]
|
||||
|
||||
# Specifies the kind of text track
|
||||
kind: Var[Union[str, int, bool]]
|
||||
kind: Var[str]
|
||||
|
||||
# Title of the text track, used by the browser when listing available text tracks
|
||||
label: Var[Union[str, int, bool]]
|
||||
label: Var[str]
|
||||
|
||||
# URL of the track file
|
||||
src: Var[Union[str, int, bool]]
|
||||
src: Var[str]
|
||||
|
||||
# Language of the track text data
|
||||
src_lang: Var[Union[str, int, bool]]
|
||||
src_lang: Var[str]
|
||||
|
||||
|
||||
class Video(BaseHTML):
|
||||
@ -173,34 +166,31 @@ class Video(BaseHTML):
|
||||
tag = "video"
|
||||
|
||||
# Specifies that the video will start playing as soon as it is ready
|
||||
auto_play: Var[Union[str, int, bool]]
|
||||
|
||||
# Represents the time range of the buffered media
|
||||
buffered: Var[Union[str, int, bool]]
|
||||
auto_play: Var[bool]
|
||||
|
||||
# Displays the standard video controls
|
||||
controls: Var[Union[str, int, bool]]
|
||||
controls: Var[bool]
|
||||
|
||||
# Configures the CORS requests for the video
|
||||
cross_origin: Var[Union[str, int, bool]]
|
||||
cross_origin: Var[CrossOrigin]
|
||||
|
||||
# Specifies that the video will loop
|
||||
loop: Var[Union[str, int, bool]]
|
||||
loop: Var[bool]
|
||||
|
||||
# Indicates whether the video is muted by default
|
||||
muted: Var[Union[str, int, bool]]
|
||||
muted: Var[bool]
|
||||
|
||||
# Indicates that the video should play 'inline', inside its element's playback area
|
||||
plays_inline: Var[Union[str, int, bool]]
|
||||
plays_inline: Var[bool]
|
||||
|
||||
# URL of an image to show while the video is downloading, or until the user hits the play button
|
||||
poster: Var[Union[str, int, bool]]
|
||||
poster: Var[str]
|
||||
|
||||
# Specifies how the video file should be preloaded
|
||||
preload: Var[Union[str, int, bool]]
|
||||
preload: Var[str]
|
||||
|
||||
# URL of the video to play
|
||||
src: Var[Union[str, int, bool]]
|
||||
src: Var[str]
|
||||
|
||||
|
||||
class Embed(BaseHTML):
|
||||
@ -209,10 +199,10 @@ class Embed(BaseHTML):
|
||||
tag = "embed"
|
||||
|
||||
# URL of the embedded content
|
||||
src: Var[Union[str, int, bool]]
|
||||
src: Var[str]
|
||||
|
||||
# Media type of the embedded content
|
||||
type: Var[Union[str, int, bool]]
|
||||
type: Var[str]
|
||||
|
||||
|
||||
class Iframe(BaseHTML):
|
||||
@ -220,32 +210,26 @@ 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[Union[str, int, bool]]
|
||||
|
||||
# Content Security Policy to apply to the iframe's content
|
||||
csp: Var[Union[str, int, bool]]
|
||||
allow: Var[str]
|
||||
|
||||
# Specifies the loading behavior of the iframe
|
||||
loading: Var[Union[str, int, bool]]
|
||||
loading: Var[Literal["eager", "lazy"]]
|
||||
|
||||
# Name of the iframe, used as a target for hyperlinks and forms
|
||||
name: Var[Union[str, int, bool]]
|
||||
name: Var[str]
|
||||
|
||||
# Referrer policy for the iframe
|
||||
referrer_policy: Var[Union[str, int, bool]]
|
||||
referrer_policy: Var[ReferrerPolicy]
|
||||
|
||||
# Security restrictions for the content in the iframe
|
||||
sandbox: Var[Union[str, int, bool]]
|
||||
sandbox: Var[str]
|
||||
|
||||
# URL of the document to display in the iframe
|
||||
src: Var[Union[str, int, bool]]
|
||||
src: Var[str]
|
||||
|
||||
# HTML content to embed directly within the iframe
|
||||
src_doc: Var[Union[str, int, bool]]
|
||||
src_doc: Var[str]
|
||||
|
||||
|
||||
class Object(BaseHTML):
|
||||
@ -254,19 +238,19 @@ class Object(BaseHTML):
|
||||
tag = "object"
|
||||
|
||||
# URL of the data to be used by the object
|
||||
data: Var[Union[str, int, bool]]
|
||||
data: Var[str]
|
||||
|
||||
# Associates the object with a form element
|
||||
form: Var[Union[str, int, bool]]
|
||||
form: Var[str]
|
||||
|
||||
# Name of the object, used for scripting or as a target for forms and links
|
||||
name: Var[Union[str, int, bool]]
|
||||
name: Var[str]
|
||||
|
||||
# Media type of the data specified in the data attribute
|
||||
type: Var[Union[str, int, bool]]
|
||||
type: Var[str]
|
||||
|
||||
# Name of an image map to use with the object
|
||||
use_map: Var[Union[str, int, bool]]
|
||||
use_map: Var[str]
|
||||
|
||||
|
||||
class Picture(BaseHTML):
|
||||
@ -287,19 +271,19 @@ class Source(BaseHTML):
|
||||
tag = "source"
|
||||
|
||||
# Media query indicating what device the linked resource is optimized for
|
||||
media: Var[Union[str, int, bool]]
|
||||
media: Var[str]
|
||||
|
||||
# Sizes of the source for different layouts
|
||||
sizes: Var[Union[str, int, bool]]
|
||||
sizes: Var[str]
|
||||
|
||||
# URL of the media file or an image for the element to use
|
||||
src: Var[Union[str, int, bool]]
|
||||
src: Var[str]
|
||||
|
||||
# A set of source sizes and URLs for responsive images
|
||||
src_set: Var[Union[str, int, bool]]
|
||||
src_set: Var[str]
|
||||
|
||||
# Media type of the source
|
||||
type: Var[Union[str, int, bool]]
|
||||
type: Var[str]
|
||||
|
||||
|
||||
class Svg(BaseHTML):
|
||||
@ -431,16 +415,16 @@ class LinearGradient(BaseHTML):
|
||||
spread_method: Var[Union[str, bool]]
|
||||
|
||||
# X coordinate of the starting point of the gradient.
|
||||
x1: Var[Union[str, int, bool]]
|
||||
x1: Var[Union[str, int, float]]
|
||||
|
||||
# X coordinate of the ending point of the gradient.
|
||||
x2: Var[Union[str, int, bool]]
|
||||
x2: Var[Union[str, int, float]]
|
||||
|
||||
# Y coordinate of the starting point of the gradient.
|
||||
y1: Var[Union[str, int, bool]]
|
||||
y1: Var[Union[str, int, float]]
|
||||
|
||||
# Y coordinate of the ending point of the gradient.
|
||||
y2: Var[Union[str, int, bool]]
|
||||
y2: Var[Union[str, int, float]]
|
||||
|
||||
|
||||
class RadialGradient(BaseHTML):
|
||||
@ -449,19 +433,19 @@ class RadialGradient(BaseHTML):
|
||||
tag = "radialGradient"
|
||||
|
||||
# The x coordinate of the end circle of the radial gradient.
|
||||
cx: Var[Union[str, int, bool]]
|
||||
cx: Var[Union[str, int, float]]
|
||||
|
||||
# The y coordinate of the end circle of the radial gradient.
|
||||
cy: Var[Union[str, int, bool]]
|
||||
cy: Var[Union[str, int, float]]
|
||||
|
||||
# The radius of the start circle of the radial gradient.
|
||||
fr: Var[Union[str, int, bool]]
|
||||
fr: Var[Union[str, int, float]]
|
||||
|
||||
# The x coordinate of the start circle of the radial gradient.
|
||||
fx: Var[Union[str, int, bool]]
|
||||
fx: Var[Union[str, int, float]]
|
||||
|
||||
# The y coordinate of the start circle of the radial gradient.
|
||||
fy: Var[Union[str, int, bool]]
|
||||
fy: Var[Union[str, int, float]]
|
||||
|
||||
# Units for the gradient.
|
||||
gradient_units: Var[Union[str, bool]]
|
||||
@ -470,7 +454,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, bool]]
|
||||
r: Var[Union[str, int, float]]
|
||||
|
||||
# Method used to spread the gradient.
|
||||
spread_method: Var[Union[str, bool]]
|
||||
@ -497,7 +481,7 @@ class Path(BaseHTML):
|
||||
tag = "path"
|
||||
|
||||
# Defines the shape of the path.
|
||||
d: Var[Union[str, int, bool]]
|
||||
d: Var[Union[str, int, float]]
|
||||
|
||||
|
||||
class SVG(ComponentNamespace):
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user