reflex 0.3.8a2__py3-none-any.whl → 0.3.9a2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of reflex might be problematic. Click here for more details.
- reflex/.templates/apps/blank/code/blank.py +1 -1
- reflex/.templates/apps/demo/code/demo.py +1 -1
- reflex/.templates/jinja/web/pages/utils.js.jinja2 +1 -1
- reflex/__init__.py +1 -0
- reflex/__init__.pyi +1 -0
- reflex/app.py +107 -86
- reflex/compiler/compiler.py +110 -0
- reflex/components/component.py +3 -1
- reflex/components/core/match.py +8 -4
- reflex/components/datadisplay/dataeditor.py +5 -1
- reflex/components/markdown/markdown.py +1 -0
- reflex/components/radix/__init__.py +2 -0
- reflex/components/radix/primitives/__init__.py +14 -1
- reflex/components/radix/primitives/accordion.py +426 -69
- reflex/components/radix/primitives/accordion.pyi +41 -11
- reflex/components/radix/primitives/base.py +4 -0
- reflex/components/radix/primitives/base.pyi +81 -0
- reflex/components/radix/primitives/form.py +4 -2
- reflex/components/radix/primitives/form.pyi +2 -2
- reflex/components/radix/primitives/progress.py +4 -2
- reflex/components/radix/primitives/progress.pyi +2 -2
- reflex/components/radix/primitives/slider.py +7 -5
- reflex/components/radix/primitives/slider.pyi +5 -5
- reflex/components/radix/themes/components/__init__.py +8 -2
- reflex/components/radix/themes/components/alertdialog.py +4 -4
- reflex/components/radix/themes/components/alertdialog.pyi +8 -1
- reflex/components/radix/themes/components/aspectratio.py +2 -4
- reflex/components/radix/themes/components/aspectratio.pyi +1 -3
- reflex/components/radix/themes/components/avatar.py +7 -3
- reflex/components/radix/themes/components/avatar.pyi +5 -3
- reflex/components/radix/themes/components/badge.py +5 -7
- reflex/components/radix/themes/components/badge.pyi +4 -6
- reflex/components/radix/themes/components/callout.py +36 -5
- reflex/components/radix/themes/components/callout.pyi +273 -9
- reflex/components/radix/themes/components/card.py +3 -3
- reflex/components/radix/themes/components/card.pyi +2 -2
- reflex/components/radix/themes/components/checkbox.py +41 -4
- reflex/components/radix/themes/components/checkbox.pyi +231 -8
- reflex/components/radix/themes/components/dialog.py +1 -1
- reflex/components/radix/themes/components/dialog.pyi +1 -1
- reflex/components/radix/themes/components/dropdownmenu.py +6 -0
- reflex/components/radix/themes/components/dropdownmenu.pyi +193 -0
- reflex/components/radix/themes/components/iconbutton.py +1 -1
- reflex/components/radix/themes/components/iconbutton.pyi +1 -1
- reflex/components/radix/themes/components/icons.py +1 -0
- reflex/components/radix/themes/components/inset.py +1 -0
- reflex/components/radix/themes/components/inset.pyi +1 -0
- reflex/components/radix/themes/components/radiogroup.py +68 -1
- reflex/components/radix/themes/components/radiogroup.pyi +254 -2
- reflex/components/radix/themes/components/select.py +93 -4
- reflex/components/radix/themes/components/select.pyi +246 -4
- reflex/components/radix/themes/components/slider.py +9 -6
- reflex/components/radix/themes/components/slider.pyi +12 -6
- reflex/components/radix/themes/components/tooltip.py +1 -0
- reflex/components/radix/themes/components/tooltip.pyi +1 -0
- reflex/components/radix/themes/layout/box.py +1 -1
- reflex/state.py +9 -4
- reflex/style.py +15 -0
- reflex/utils/path_ops.py +2 -2
- reflex/utils/prerequisites.py +57 -5
- reflex/utils/types.py +4 -1
- reflex/vars.py +36 -3
- {reflex-0.3.8a2.dist-info → reflex-0.3.9a2.dist-info}/METADATA +2 -2
- {reflex-0.3.8a2.dist-info → reflex-0.3.9a2.dist-info}/RECORD +67 -67
- {reflex-0.3.8a2.dist-info → reflex-0.3.9a2.dist-info}/WHEEL +1 -1
- {reflex-0.3.8a2.dist-info → reflex-0.3.9a2.dist-info}/LICENSE +0 -0
- {reflex-0.3.8a2.dist-info → reflex-0.3.9a2.dist-info}/entry_points.txt +0 -0
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
{% macro render_match_tag(component) %}
|
|
86
86
|
{
|
|
87
87
|
(() => {
|
|
88
|
-
switch (JSON.stringify({{ component.cond.
|
|
88
|
+
switch (JSON.stringify({{ component.cond._var_name_unwrapped }})) {
|
|
89
89
|
{% for case in component.match_cases %}
|
|
90
90
|
{% for condition in case[:-1] %}
|
|
91
91
|
case JSON.stringify({{ condition._var_name_unwrapped }}):
|
reflex/__init__.py
CHANGED
|
@@ -253,6 +253,7 @@ _MAPPING = {
|
|
|
253
253
|
"reflex.compiler.utils": ["get_asset_path"],
|
|
254
254
|
"reflex.components": _ALL_COMPONENTS + ["chakra", "next"],
|
|
255
255
|
"reflex.components.component": ["memo"],
|
|
256
|
+
"reflex.components.radix": ["radix"],
|
|
256
257
|
"reflex.components.recharts": ["recharts"],
|
|
257
258
|
"reflex.components.moment.moment": ["MomentDelta"],
|
|
258
259
|
"reflex.config": ["config", "Config", "DBConfig"],
|
reflex/__init__.pyi
CHANGED
|
@@ -447,6 +447,7 @@ from reflex.components import NoSSRComponent as NoSSRComponent
|
|
|
447
447
|
from reflex.components import chakra as chakra
|
|
448
448
|
from reflex.components import next as next
|
|
449
449
|
from reflex.components.component import memo as memo
|
|
450
|
+
from reflex.components import radix as radix
|
|
450
451
|
from reflex.components import recharts as recharts
|
|
451
452
|
from reflex.components.moment.moment import MomentDelta as MomentDelta
|
|
452
453
|
from reflex import config as config
|
reflex/app.py
CHANGED
|
@@ -6,7 +6,9 @@ import concurrent.futures
|
|
|
6
6
|
import contextlib
|
|
7
7
|
import copy
|
|
8
8
|
import functools
|
|
9
|
+
import multiprocessing
|
|
9
10
|
import os
|
|
11
|
+
import platform
|
|
10
12
|
from typing import (
|
|
11
13
|
Any,
|
|
12
14
|
AsyncIterator,
|
|
@@ -35,6 +37,7 @@ from reflex.admin import AdminDash
|
|
|
35
37
|
from reflex.base import Base
|
|
36
38
|
from reflex.compiler import compiler
|
|
37
39
|
from reflex.compiler import utils as compiler_utils
|
|
40
|
+
from reflex.compiler.compiler import ExecutorSafeFunctions
|
|
38
41
|
from reflex.components import connection_modal
|
|
39
42
|
from reflex.components.base.app_wrap import AppWrap
|
|
40
43
|
from reflex.components.base.fragment import Fragment
|
|
@@ -43,7 +46,6 @@ from reflex.components.core.client_side_routing import (
|
|
|
43
46
|
Default404Page,
|
|
44
47
|
wait_for_client_redirect,
|
|
45
48
|
)
|
|
46
|
-
from reflex.components.radix import themes
|
|
47
49
|
from reflex.config import get_config
|
|
48
50
|
from reflex.event import Event, EventHandler, EventSpec
|
|
49
51
|
from reflex.middleware import HydrateMiddleware, Middleware
|
|
@@ -129,11 +131,11 @@ class App(Base):
|
|
|
129
131
|
Union[Component, ComponentCallable]
|
|
130
132
|
] = default_overlay_component
|
|
131
133
|
|
|
132
|
-
# Background tasks that are currently running
|
|
134
|
+
# Background tasks that are currently running.
|
|
133
135
|
background_tasks: Set[asyncio.Task] = set()
|
|
134
136
|
|
|
135
|
-
# The radix theme for the entire app
|
|
136
|
-
theme: Optional[Component]
|
|
137
|
+
# The radix theme for the entire app.
|
|
138
|
+
theme: Optional[Component]
|
|
137
139
|
|
|
138
140
|
def __init__(self, *args, **kwargs):
|
|
139
141
|
"""Initialize the app.
|
|
@@ -592,7 +594,7 @@ class App(Base):
|
|
|
592
594
|
continue
|
|
593
595
|
_frontend_packages.append(package)
|
|
594
596
|
page_imports.update(_frontend_packages)
|
|
595
|
-
prerequisites.install_frontend_packages(page_imports)
|
|
597
|
+
prerequisites.install_frontend_packages(page_imports, get_config())
|
|
596
598
|
|
|
597
599
|
def _app_root(self, app_wrappers: dict[tuple[int, str], Component]) -> Component:
|
|
598
600
|
for component in tuple(app_wrappers.values()):
|
|
@@ -661,15 +663,24 @@ class App(Base):
|
|
|
661
663
|
TimeElapsedColumn(),
|
|
662
664
|
)
|
|
663
665
|
|
|
666
|
+
# try to be somewhat accurate - but still not 100%
|
|
667
|
+
adhoc_steps_without_executor = 6
|
|
668
|
+
fixed_pages_within_executor = 7
|
|
669
|
+
progress.start()
|
|
670
|
+
task = progress.add_task(
|
|
671
|
+
"Compiling:",
|
|
672
|
+
total=len(self.pages)
|
|
673
|
+
+ fixed_pages_within_executor
|
|
674
|
+
+ adhoc_steps_without_executor,
|
|
675
|
+
)
|
|
676
|
+
|
|
664
677
|
# Get the env mode.
|
|
665
678
|
config = get_config()
|
|
666
679
|
|
|
667
680
|
# Store the compile results.
|
|
668
681
|
compile_results = []
|
|
669
682
|
|
|
670
|
-
# Compile the pages in parallel.
|
|
671
683
|
custom_components = set()
|
|
672
|
-
# TODO Anecdotally, processes=2 works 10% faster (cpu_count=12)
|
|
673
684
|
all_imports = {}
|
|
674
685
|
app_wrappers: Dict[tuple[int, str], Component] = {
|
|
675
686
|
# Default app wrap component renders {children}
|
|
@@ -679,127 +690,137 @@ class App(Base):
|
|
|
679
690
|
# If a theme component was provided, wrap the app with it
|
|
680
691
|
app_wrappers[(20, "Theme")] = self.theme
|
|
681
692
|
|
|
682
|
-
|
|
683
|
-
fixed_pages = 7
|
|
684
|
-
task = progress.add_task("Compiling:", total=len(self.pages) + fixed_pages)
|
|
693
|
+
progress.advance(task)
|
|
685
694
|
|
|
686
|
-
|
|
687
|
-
|
|
695
|
+
for _route, component in self.pages.items():
|
|
696
|
+
# Merge the component style with the app style.
|
|
697
|
+
component.add_style(self.style)
|
|
688
698
|
|
|
689
|
-
|
|
690
|
-
# Merge the component style with the app style.
|
|
691
|
-
component.add_style(self.style)
|
|
699
|
+
component.apply_theme(self.theme)
|
|
692
700
|
|
|
693
|
-
|
|
701
|
+
# Add component.get_imports() to all_imports.
|
|
702
|
+
all_imports.update(component.get_imports())
|
|
694
703
|
|
|
695
|
-
|
|
696
|
-
|
|
704
|
+
# Add the app wrappers from this component.
|
|
705
|
+
app_wrappers.update(component.get_app_wrap_components())
|
|
697
706
|
|
|
698
|
-
|
|
699
|
-
|
|
707
|
+
# Add the custom components from the page to the set.
|
|
708
|
+
custom_components |= component.get_custom_components()
|
|
700
709
|
|
|
701
|
-
|
|
702
|
-
custom_components |= component.get_custom_components()
|
|
710
|
+
progress.advance(task)
|
|
703
711
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
712
|
+
# Perform auto-memoization of stateful components.
|
|
713
|
+
(
|
|
714
|
+
stateful_components_path,
|
|
715
|
+
stateful_components_code,
|
|
716
|
+
page_components,
|
|
717
|
+
) = compiler.compile_stateful_components(self.pages.values())
|
|
710
718
|
|
|
711
|
-
|
|
712
|
-
if (
|
|
713
|
-
code_uses_state_contexts(stateful_components_code)
|
|
714
|
-
and self.state is None
|
|
715
|
-
):
|
|
716
|
-
raise RuntimeError(
|
|
717
|
-
"To access rx.State in frontend components, at least one "
|
|
718
|
-
"subclass of rx.State must be defined in the app."
|
|
719
|
-
)
|
|
720
|
-
compile_results.append((stateful_components_path, stateful_components_code))
|
|
719
|
+
progress.advance(task)
|
|
721
720
|
|
|
722
|
-
|
|
721
|
+
# Catch "static" apps (that do not define a rx.State subclass) which are trying to access rx.State.
|
|
722
|
+
if code_uses_state_contexts(stateful_components_code) and self.state is None:
|
|
723
|
+
raise RuntimeError(
|
|
724
|
+
"To access rx.State in frontend components, at least one "
|
|
725
|
+
"subclass of rx.State must be defined in the app."
|
|
726
|
+
)
|
|
727
|
+
compile_results.append((stateful_components_path, stateful_components_code))
|
|
728
|
+
|
|
729
|
+
app_root = self._app_root(app_wrappers=app_wrappers)
|
|
730
|
+
|
|
731
|
+
progress.advance(task)
|
|
732
|
+
|
|
733
|
+
# Prepopulate the global ExecutorSafeFunctions class with input data required by the compile functions.
|
|
734
|
+
# This is required for multiprocessing to work, in presence of non-picklable inputs.
|
|
735
|
+
for route, component in zip(self.pages, page_components):
|
|
736
|
+
ExecutorSafeFunctions.COMPILE_PAGE_ARGS_BY_ROUTE[route] = (
|
|
737
|
+
route,
|
|
738
|
+
component,
|
|
739
|
+
self.state,
|
|
740
|
+
)
|
|
723
741
|
|
|
724
|
-
|
|
725
|
-
|
|
742
|
+
ExecutorSafeFunctions.COMPILE_APP_APP_ROOT = app_root
|
|
743
|
+
ExecutorSafeFunctions.CUSTOM_COMPONENTS = custom_components
|
|
744
|
+
ExecutorSafeFunctions.HEAD_COMPONENTS = self.head_components
|
|
745
|
+
ExecutorSafeFunctions.STYLE = self.style
|
|
746
|
+
ExecutorSafeFunctions.STATE = self.state
|
|
747
|
+
|
|
748
|
+
# Use a forking process pool, if possible. Much faster, especially for large sites.
|
|
749
|
+
# Fallback to ThreadPoolExecutor as something that will always work.
|
|
750
|
+
executor = None
|
|
751
|
+
if platform.system() in ("Linux", "Darwin"):
|
|
752
|
+
executor = concurrent.futures.ProcessPoolExecutor(
|
|
753
|
+
mp_context=multiprocessing.get_context("fork")
|
|
754
|
+
)
|
|
755
|
+
else:
|
|
756
|
+
executor = concurrent.futures.ThreadPoolExecutor()
|
|
726
757
|
|
|
727
|
-
|
|
758
|
+
with executor:
|
|
759
|
+
result_futures = []
|
|
728
760
|
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
f
|
|
735
|
-
f.add_done_callback(mark_complete)
|
|
761
|
+
def _mark_complete(_=None):
|
|
762
|
+
progress.advance(task)
|
|
763
|
+
|
|
764
|
+
def _submit_work(fn, *args, **kwargs):
|
|
765
|
+
f = executor.submit(fn, *args, **kwargs)
|
|
766
|
+
f.add_done_callback(_mark_complete)
|
|
736
767
|
result_futures.append(f)
|
|
737
768
|
|
|
738
769
|
# Compile all page components.
|
|
739
|
-
for route
|
|
740
|
-
|
|
741
|
-
compiler.compile_page,
|
|
742
|
-
route,
|
|
743
|
-
component,
|
|
744
|
-
self.state,
|
|
745
|
-
)
|
|
770
|
+
for route in self.pages:
|
|
771
|
+
_submit_work(ExecutorSafeFunctions.compile_page, route)
|
|
746
772
|
|
|
747
773
|
# Compile the app wrapper.
|
|
748
|
-
|
|
749
|
-
submit_work(compiler.compile_app, app_root)
|
|
774
|
+
_submit_work(ExecutorSafeFunctions.compile_app)
|
|
750
775
|
|
|
751
776
|
# Compile the custom components.
|
|
752
|
-
|
|
777
|
+
_submit_work(ExecutorSafeFunctions.compile_custom_components)
|
|
753
778
|
|
|
754
779
|
# Compile the root stylesheet with base styles.
|
|
755
|
-
|
|
780
|
+
_submit_work(compiler.compile_root_stylesheet, self.stylesheets)
|
|
756
781
|
|
|
757
782
|
# Compile the root document.
|
|
758
|
-
|
|
783
|
+
_submit_work(ExecutorSafeFunctions.compile_document_root)
|
|
759
784
|
|
|
760
785
|
# Compile the theme.
|
|
761
|
-
|
|
786
|
+
_submit_work(ExecutorSafeFunctions.compile_theme)
|
|
762
787
|
|
|
763
788
|
# Compile the contexts.
|
|
764
|
-
|
|
789
|
+
_submit_work(ExecutorSafeFunctions.compile_contexts)
|
|
765
790
|
|
|
766
791
|
# Compile the Tailwind config.
|
|
767
792
|
if config.tailwind is not None:
|
|
768
793
|
config.tailwind["content"] = config.tailwind.get(
|
|
769
794
|
"content", constants.Tailwind.CONTENT
|
|
770
795
|
)
|
|
771
|
-
|
|
796
|
+
_submit_work(compiler.compile_tailwind, config.tailwind)
|
|
772
797
|
else:
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
# Get imports from AppWrap components.
|
|
776
|
-
all_imports.update(app_root.get_imports())
|
|
777
|
-
|
|
778
|
-
# Iterate through all the custom components and add their imports to the all_imports.
|
|
779
|
-
for component in custom_components:
|
|
780
|
-
all_imports.update(component.get_imports())
|
|
798
|
+
_submit_work(compiler.remove_tailwind_from_postcss)
|
|
781
799
|
|
|
782
800
|
# Wait for all compilation tasks to complete.
|
|
783
801
|
for future in concurrent.futures.as_completed(result_futures):
|
|
784
802
|
compile_results.append(future.result())
|
|
785
803
|
|
|
786
|
-
|
|
787
|
-
|
|
804
|
+
# Get imports from AppWrap components.
|
|
805
|
+
all_imports.update(app_root.get_imports())
|
|
788
806
|
|
|
789
|
-
|
|
790
|
-
|
|
807
|
+
# Iterate through all the custom components and add their imports to the all_imports.
|
|
808
|
+
for component in custom_components:
|
|
809
|
+
all_imports.update(component.get_imports())
|
|
791
810
|
|
|
792
|
-
|
|
793
|
-
self.get_frontend_packages(all_imports)
|
|
811
|
+
progress.advance(task)
|
|
794
812
|
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
813
|
+
# Empty the .web pages directory.
|
|
814
|
+
compiler.purge_web_pages_dir()
|
|
815
|
+
|
|
816
|
+
progress.advance(task)
|
|
817
|
+
progress.stop()
|
|
818
|
+
|
|
819
|
+
# Install frontend packages.
|
|
820
|
+
self.get_frontend_packages(all_imports)
|
|
821
|
+
|
|
822
|
+
for output_path, code in compile_results:
|
|
823
|
+
compiler_utils.write_page(output_path, code)
|
|
803
824
|
|
|
804
825
|
@contextlib.asynccontextmanager
|
|
805
826
|
async def modify_state(self, token: str) -> AsyncIterator[BaseState]:
|
reflex/compiler/compiler.py
CHANGED
|
@@ -454,3 +454,113 @@ def remove_tailwind_from_postcss() -> tuple[str, str]:
|
|
|
454
454
|
def purge_web_pages_dir():
|
|
455
455
|
"""Empty out .web directory."""
|
|
456
456
|
utils.empty_dir(constants.Dirs.WEB_PAGES, keep_files=["_app.js"])
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
class ExecutorSafeFunctions:
|
|
460
|
+
"""Helper class to allow parallelisation of parts of the compilation process.
|
|
461
|
+
|
|
462
|
+
This class (and its class attributes) are available at global scope.
|
|
463
|
+
|
|
464
|
+
In a multiprocessing context (like when using a ProcessPoolExecutor), the content of this
|
|
465
|
+
global class is logically replicated to any FORKED process.
|
|
466
|
+
|
|
467
|
+
How it works:
|
|
468
|
+
* Before the child process is forked, ensure that we stash any input data required by any future
|
|
469
|
+
function call in the child process.
|
|
470
|
+
* After the child process is forked, the child process will have a copy of the global class, which
|
|
471
|
+
includes the previously stashed input data.
|
|
472
|
+
* Any task submitted to the child process simply needs a way to communicate which input data the
|
|
473
|
+
requested function call requires.
|
|
474
|
+
|
|
475
|
+
Why do we need this? Passing input data directly to child process often not possible because the input data is not picklable.
|
|
476
|
+
The mechanic described here removes the need to pickle the input data at all.
|
|
477
|
+
|
|
478
|
+
Limitations:
|
|
479
|
+
* This can never support returning unpicklable OUTPUT data.
|
|
480
|
+
* Any object mutations done by the child process will not propagate back to the parent process (fork goes one way!).
|
|
481
|
+
|
|
482
|
+
"""
|
|
483
|
+
|
|
484
|
+
COMPILE_PAGE_ARGS_BY_ROUTE = {}
|
|
485
|
+
COMPILE_APP_APP_ROOT: Component | None = None
|
|
486
|
+
CUSTOM_COMPONENTS: set[CustomComponent] | None = None
|
|
487
|
+
HEAD_COMPONENTS: list[Component] | None = None
|
|
488
|
+
STYLE: ComponentStyle | None = None
|
|
489
|
+
STATE: type[BaseState] | None = None
|
|
490
|
+
|
|
491
|
+
@classmethod
|
|
492
|
+
def compile_page(cls, route: str):
|
|
493
|
+
"""Compile a page.
|
|
494
|
+
|
|
495
|
+
Args:
|
|
496
|
+
route: The route of the page to compile.
|
|
497
|
+
|
|
498
|
+
Returns:
|
|
499
|
+
The path and code of the compiled page.
|
|
500
|
+
"""
|
|
501
|
+
return compile_page(*cls.COMPILE_PAGE_ARGS_BY_ROUTE[route])
|
|
502
|
+
|
|
503
|
+
@classmethod
|
|
504
|
+
def compile_app(cls):
|
|
505
|
+
"""Compile the app.
|
|
506
|
+
|
|
507
|
+
Returns:
|
|
508
|
+
The path and code of the compiled app.
|
|
509
|
+
|
|
510
|
+
Raises:
|
|
511
|
+
ValueError: If the app root is not set.
|
|
512
|
+
"""
|
|
513
|
+
if cls.COMPILE_APP_APP_ROOT is None:
|
|
514
|
+
raise ValueError("COMPILE_APP_APP_ROOT should be set")
|
|
515
|
+
return compile_app(cls.COMPILE_APP_APP_ROOT)
|
|
516
|
+
|
|
517
|
+
@classmethod
|
|
518
|
+
def compile_custom_components(cls):
|
|
519
|
+
"""Compile the custom components.
|
|
520
|
+
|
|
521
|
+
Returns:
|
|
522
|
+
The path and code of the compiled custom components.
|
|
523
|
+
|
|
524
|
+
Raises:
|
|
525
|
+
ValueError: If the custom components are not set.
|
|
526
|
+
"""
|
|
527
|
+
if cls.CUSTOM_COMPONENTS is None:
|
|
528
|
+
raise ValueError("CUSTOM_COMPONENTS should be set")
|
|
529
|
+
return compile_components(cls.CUSTOM_COMPONENTS)
|
|
530
|
+
|
|
531
|
+
@classmethod
|
|
532
|
+
def compile_document_root(cls):
|
|
533
|
+
"""Compile the document root.
|
|
534
|
+
|
|
535
|
+
Returns:
|
|
536
|
+
The path and code of the compiled document root.
|
|
537
|
+
|
|
538
|
+
Raises:
|
|
539
|
+
ValueError: If the head components are not set.
|
|
540
|
+
"""
|
|
541
|
+
if cls.HEAD_COMPONENTS is None:
|
|
542
|
+
raise ValueError("HEAD_COMPONENTS should be set")
|
|
543
|
+
return compile_document_root(cls.HEAD_COMPONENTS)
|
|
544
|
+
|
|
545
|
+
@classmethod
|
|
546
|
+
def compile_theme(cls):
|
|
547
|
+
"""Compile the theme.
|
|
548
|
+
|
|
549
|
+
Returns:
|
|
550
|
+
The path and code of the compiled theme.
|
|
551
|
+
|
|
552
|
+
Raises:
|
|
553
|
+
ValueError: If the style is not set.
|
|
554
|
+
"""
|
|
555
|
+
if cls.STYLE is None:
|
|
556
|
+
raise ValueError("STYLE should be set")
|
|
557
|
+
return compile_theme(cls.STYLE)
|
|
558
|
+
|
|
559
|
+
@classmethod
|
|
560
|
+
def compile_contexts(cls):
|
|
561
|
+
"""Compile the contexts.
|
|
562
|
+
|
|
563
|
+
Returns:
|
|
564
|
+
The path and code of the compiled contexts.
|
|
565
|
+
"""
|
|
566
|
+
return compile_contexts(cls.STATE)
|
reflex/components/component.py
CHANGED
|
@@ -623,6 +623,8 @@ class Component(BaseComponent, ABC):
|
|
|
623
623
|
Returns:
|
|
624
624
|
The dictionary of the component style as value and the style notation as key.
|
|
625
625
|
"""
|
|
626
|
+
if isinstance(self.style, Var):
|
|
627
|
+
return {"css": self.style}
|
|
626
628
|
return {"css": Var.create(format_as_emotion(self.style))}
|
|
627
629
|
|
|
628
630
|
def render(self) -> Dict:
|
|
@@ -721,7 +723,7 @@ class Component(BaseComponent, ABC):
|
|
|
721
723
|
vars.append(prop_var)
|
|
722
724
|
|
|
723
725
|
# Style keeps track of its own VarData instance, so embed in a temp Var that is yielded.
|
|
724
|
-
if self.style:
|
|
726
|
+
if isinstance(self.style, dict) and self.style or isinstance(self.style, Var):
|
|
725
727
|
vars.append(
|
|
726
728
|
BaseVar(
|
|
727
729
|
_var_name="style",
|
reflex/components/core/match.py
CHANGED
|
@@ -64,7 +64,8 @@ class Match(MemoizationLeaf):
|
|
|
64
64
|
Raises:
|
|
65
65
|
ValueError: If the condition is not provided.
|
|
66
66
|
"""
|
|
67
|
-
match_cond_var = Var.create(cond)
|
|
67
|
+
match_cond_var = Var.create(cond, _var_is_string=type(cond) is str)
|
|
68
|
+
|
|
68
69
|
if match_cond_var is None:
|
|
69
70
|
raise ValueError("The condition must be set")
|
|
70
71
|
return match_cond_var # type: ignore
|
|
@@ -216,13 +217,14 @@ class Match(MemoizationLeaf):
|
|
|
216
217
|
|
|
217
218
|
return match_cond_var._replace(
|
|
218
219
|
_var_name=format.format_match(
|
|
219
|
-
cond=match_cond_var.
|
|
220
|
+
cond=match_cond_var._var_name_unwrapped,
|
|
220
221
|
match_cases=match_cases, # type: ignore
|
|
221
222
|
default=default, # type: ignore
|
|
222
223
|
),
|
|
223
224
|
_var_type=default._var_type, # type: ignore
|
|
224
225
|
_var_is_local=False,
|
|
225
226
|
_var_full_name_needs_state_prefix=False,
|
|
227
|
+
_var_is_string=False,
|
|
226
228
|
merge_var_data=VarData.merge(*var_data),
|
|
227
229
|
)
|
|
228
230
|
|
|
@@ -247,11 +249,13 @@ class Match(MemoizationLeaf):
|
|
|
247
249
|
for case in self.match_cases:
|
|
248
250
|
if isinstance(case[-1], BaseComponent):
|
|
249
251
|
merged_imports = imports.merge_imports(
|
|
250
|
-
merged_imports,
|
|
252
|
+
merged_imports,
|
|
253
|
+
case[-1].get_imports(),
|
|
251
254
|
)
|
|
252
255
|
# Get the import of the default case component.
|
|
253
256
|
if isinstance(self.default, BaseComponent):
|
|
254
257
|
merged_imports = imports.merge_imports(
|
|
255
|
-
merged_imports,
|
|
258
|
+
merged_imports,
|
|
259
|
+
self.default.get_imports(),
|
|
256
260
|
)
|
|
257
261
|
return merged_imports
|
|
@@ -109,7 +109,11 @@ class DataEditor(NoSSRComponent):
|
|
|
109
109
|
tag = "DataEditor"
|
|
110
110
|
is_default = True
|
|
111
111
|
library: str = "@glideapps/glide-data-grid@^5.3.0"
|
|
112
|
-
lib_dependencies: List[str] = [
|
|
112
|
+
lib_dependencies: List[str] = [
|
|
113
|
+
"lodash@^4.17.21",
|
|
114
|
+
"marked@^4.0.10",
|
|
115
|
+
"react-responsive-carousel@^3.2.7",
|
|
116
|
+
]
|
|
113
117
|
|
|
114
118
|
# Number of rows.
|
|
115
119
|
rows: Var[int]
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
"""Radix primitive components (https://www.radix-ui.com/primitives)."""
|
|
2
2
|
|
|
3
|
-
from .accordion import
|
|
3
|
+
from .accordion import (
|
|
4
|
+
AccordionContent,
|
|
5
|
+
AccordionHeader,
|
|
6
|
+
AccordionRoot,
|
|
7
|
+
AccordionTrigger,
|
|
8
|
+
accordion_item,
|
|
9
|
+
)
|
|
4
10
|
from .form import (
|
|
5
11
|
form_control,
|
|
6
12
|
form_field,
|
|
@@ -12,3 +18,10 @@ from .form import (
|
|
|
12
18
|
)
|
|
13
19
|
from .progress import progress
|
|
14
20
|
from .slider import slider
|
|
21
|
+
|
|
22
|
+
# accordion
|
|
23
|
+
accordion = AccordionRoot.create
|
|
24
|
+
accordion_root = AccordionRoot.create
|
|
25
|
+
accordion_header = AccordionHeader.create
|
|
26
|
+
accordion_trigger = AccordionTrigger.create
|
|
27
|
+
accordion_content = AccordionContent.create
|