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.

Files changed (67) hide show
  1. reflex/.templates/apps/blank/code/blank.py +1 -1
  2. reflex/.templates/apps/demo/code/demo.py +1 -1
  3. reflex/.templates/jinja/web/pages/utils.js.jinja2 +1 -1
  4. reflex/__init__.py +1 -0
  5. reflex/__init__.pyi +1 -0
  6. reflex/app.py +107 -86
  7. reflex/compiler/compiler.py +110 -0
  8. reflex/components/component.py +3 -1
  9. reflex/components/core/match.py +8 -4
  10. reflex/components/datadisplay/dataeditor.py +5 -1
  11. reflex/components/markdown/markdown.py +1 -0
  12. reflex/components/radix/__init__.py +2 -0
  13. reflex/components/radix/primitives/__init__.py +14 -1
  14. reflex/components/radix/primitives/accordion.py +426 -69
  15. reflex/components/radix/primitives/accordion.pyi +41 -11
  16. reflex/components/radix/primitives/base.py +4 -0
  17. reflex/components/radix/primitives/base.pyi +81 -0
  18. reflex/components/radix/primitives/form.py +4 -2
  19. reflex/components/radix/primitives/form.pyi +2 -2
  20. reflex/components/radix/primitives/progress.py +4 -2
  21. reflex/components/radix/primitives/progress.pyi +2 -2
  22. reflex/components/radix/primitives/slider.py +7 -5
  23. reflex/components/radix/primitives/slider.pyi +5 -5
  24. reflex/components/radix/themes/components/__init__.py +8 -2
  25. reflex/components/radix/themes/components/alertdialog.py +4 -4
  26. reflex/components/radix/themes/components/alertdialog.pyi +8 -1
  27. reflex/components/radix/themes/components/aspectratio.py +2 -4
  28. reflex/components/radix/themes/components/aspectratio.pyi +1 -3
  29. reflex/components/radix/themes/components/avatar.py +7 -3
  30. reflex/components/radix/themes/components/avatar.pyi +5 -3
  31. reflex/components/radix/themes/components/badge.py +5 -7
  32. reflex/components/radix/themes/components/badge.pyi +4 -6
  33. reflex/components/radix/themes/components/callout.py +36 -5
  34. reflex/components/radix/themes/components/callout.pyi +273 -9
  35. reflex/components/radix/themes/components/card.py +3 -3
  36. reflex/components/radix/themes/components/card.pyi +2 -2
  37. reflex/components/radix/themes/components/checkbox.py +41 -4
  38. reflex/components/radix/themes/components/checkbox.pyi +231 -8
  39. reflex/components/radix/themes/components/dialog.py +1 -1
  40. reflex/components/radix/themes/components/dialog.pyi +1 -1
  41. reflex/components/radix/themes/components/dropdownmenu.py +6 -0
  42. reflex/components/radix/themes/components/dropdownmenu.pyi +193 -0
  43. reflex/components/radix/themes/components/iconbutton.py +1 -1
  44. reflex/components/radix/themes/components/iconbutton.pyi +1 -1
  45. reflex/components/radix/themes/components/icons.py +1 -0
  46. reflex/components/radix/themes/components/inset.py +1 -0
  47. reflex/components/radix/themes/components/inset.pyi +1 -0
  48. reflex/components/radix/themes/components/radiogroup.py +68 -1
  49. reflex/components/radix/themes/components/radiogroup.pyi +254 -2
  50. reflex/components/radix/themes/components/select.py +93 -4
  51. reflex/components/radix/themes/components/select.pyi +246 -4
  52. reflex/components/radix/themes/components/slider.py +9 -6
  53. reflex/components/radix/themes/components/slider.pyi +12 -6
  54. reflex/components/radix/themes/components/tooltip.py +1 -0
  55. reflex/components/radix/themes/components/tooltip.pyi +1 -0
  56. reflex/components/radix/themes/layout/box.py +1 -1
  57. reflex/state.py +9 -4
  58. reflex/style.py +15 -0
  59. reflex/utils/path_ops.py +2 -2
  60. reflex/utils/prerequisites.py +57 -5
  61. reflex/utils/types.py +4 -1
  62. reflex/vars.py +36 -3
  63. {reflex-0.3.8a2.dist-info → reflex-0.3.9a2.dist-info}/METADATA +2 -2
  64. {reflex-0.3.8a2.dist-info → reflex-0.3.9a2.dist-info}/RECORD +67 -67
  65. {reflex-0.3.8a2.dist-info → reflex-0.3.9a2.dist-info}/WHEEL +1 -1
  66. {reflex-0.3.8a2.dist-info → reflex-0.3.9a2.dist-info}/LICENSE +0 -0
  67. {reflex-0.3.8a2.dist-info → reflex-0.3.9a2.dist-info}/entry_points.txt +0 -0
@@ -39,6 +39,6 @@ def index() -> rx.Component:
39
39
  )
40
40
 
41
41
 
42
- # Add state and page to the app.
42
+ # Create app instance and add index page.
43
43
  app = rx.App()
44
44
  app.add_page(index)
@@ -118,5 +118,5 @@ def chatapp() -> rx.Component:
118
118
  return chatapp_page()
119
119
 
120
120
 
121
- # Add state and page to the app.
121
+ # Create the app.
122
122
  app = rx.App(style=base_style)
@@ -85,7 +85,7 @@
85
85
  {% macro render_match_tag(component) %}
86
86
  {
87
87
  (() => {
88
- switch (JSON.stringify({{ component.cond._var_full_name }})) {
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] = themes.theme(accent_color="blue")
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
- with progress, concurrent.futures.ThreadPoolExecutor() as thread_pool:
683
- fixed_pages = 7
684
- task = progress.add_task("Compiling:", total=len(self.pages) + fixed_pages)
693
+ progress.advance(task)
685
694
 
686
- def mark_complete(_=None):
687
- progress.advance(task)
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
- for _route, component in self.pages.items():
690
- # Merge the component style with the app style.
691
- component.add_style(self.style)
699
+ component.apply_theme(self.theme)
692
700
 
693
- component.apply_theme(self.theme)
701
+ # Add component.get_imports() to all_imports.
702
+ all_imports.update(component.get_imports())
694
703
 
695
- # Add component.get_imports() to all_imports.
696
- all_imports.update(component.get_imports())
704
+ # Add the app wrappers from this component.
705
+ app_wrappers.update(component.get_app_wrap_components())
697
706
 
698
- # Add the app wrappers from this component.
699
- app_wrappers.update(component.get_app_wrap_components())
707
+ # Add the custom components from the page to the set.
708
+ custom_components |= component.get_custom_components()
700
709
 
701
- # Add the custom components from the page to the set.
702
- custom_components |= component.get_custom_components()
710
+ progress.advance(task)
703
711
 
704
- # Perform auto-memoization of stateful components.
705
- (
706
- stateful_components_path,
707
- stateful_components_code,
708
- page_components,
709
- ) = compiler.compile_stateful_components(self.pages.values())
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
- # Catch "static" apps (that do not define a rx.State subclass) which are trying to access rx.State.
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
- result_futures = []
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
- def submit_work(fn, *args, **kwargs):
725
- """Submit work to the thread pool and add a callback to mark the task as complete.
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
- The Future will be added to the `result_futures` list.
758
+ with executor:
759
+ result_futures = []
728
760
 
729
- Args:
730
- fn: The function to submit.
731
- *args: The args to submit.
732
- **kwargs: The kwargs to submit.
733
- """
734
- f = thread_pool.submit(fn, *args, **kwargs)
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, component in zip(self.pages, page_components):
740
- submit_work(
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
- app_root = self._app_root(app_wrappers=app_wrappers)
749
- submit_work(compiler.compile_app, app_root)
774
+ _submit_work(ExecutorSafeFunctions.compile_app)
750
775
 
751
776
  # Compile the custom components.
752
- submit_work(compiler.compile_components, custom_components)
777
+ _submit_work(ExecutorSafeFunctions.compile_custom_components)
753
778
 
754
779
  # Compile the root stylesheet with base styles.
755
- submit_work(compiler.compile_root_stylesheet, self.stylesheets)
780
+ _submit_work(compiler.compile_root_stylesheet, self.stylesheets)
756
781
 
757
782
  # Compile the root document.
758
- submit_work(compiler.compile_document_root, self.head_components)
783
+ _submit_work(ExecutorSafeFunctions.compile_document_root)
759
784
 
760
785
  # Compile the theme.
761
- submit_work(compiler.compile_theme, style=self.style)
786
+ _submit_work(ExecutorSafeFunctions.compile_theme)
762
787
 
763
788
  # Compile the contexts.
764
- submit_work(compiler.compile_contexts, self.state)
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
- submit_work(compiler.compile_tailwind, config.tailwind)
796
+ _submit_work(compiler.compile_tailwind, config.tailwind)
772
797
  else:
773
- submit_work(compiler.remove_tailwind_from_postcss)
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
- # Empty the .web pages directory.
787
- compiler.purge_web_pages_dir()
804
+ # Get imports from AppWrap components.
805
+ all_imports.update(app_root.get_imports())
788
806
 
789
- # Avoid flickering when installing frontend packages
790
- progress.stop()
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
- # Install frontend packages.
793
- self.get_frontend_packages(all_imports)
811
+ progress.advance(task)
794
812
 
795
- # Write the pages at the end to trigger the NextJS hot reload only once.
796
- write_page_futures = []
797
- for output_path, code in compile_results:
798
- write_page_futures.append(
799
- thread_pool.submit(compiler_utils.write_page, output_path, code)
800
- )
801
- for future in concurrent.futures.as_completed(write_page_futures):
802
- future.result()
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]:
@@ -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)
@@ -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",
@@ -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._var_full_name,
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, case[-1].get_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, self.default.get_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] = ["lodash", "marked", "react-responsive-carousel"]
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]
@@ -41,6 +41,7 @@ _REHYPE_PLUGINS = Var.create_safe([_REHYPE_KATEX, _REHYPE_RAW])
41
41
  # These tags do NOT get props passed to them
42
42
  NO_PROPS_TAGS = ("ul", "ol", "li")
43
43
 
44
+
44
45
  # Component Mapping
45
46
  @lru_cache
46
47
  def get_base_component_map() -> dict[str, Callable]:
@@ -1 +1,3 @@
1
1
  """Namespace for components provided by @radix-ui packages."""
2
+
3
+ from . import primitives, themes
@@ -1,6 +1,12 @@
1
1
  """Radix primitive components (https://www.radix-ui.com/primitives)."""
2
2
 
3
- from .accordion import accordion, accordion_item
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