ex4nicegui 0.6.8__py3-none-any.whl → 0.7.0__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.
Files changed (58) hide show
  1. ex4nicegui/__init__.py +2 -0
  2. ex4nicegui/bi/dataSourceFacade.py +20 -20
  3. ex4nicegui/bi/index.py +20 -23
  4. ex4nicegui/helper/client_instance_locker.py +4 -4
  5. ex4nicegui/reactive/EChartsComponent/ECharts.py +9 -8
  6. ex4nicegui/reactive/__init__.py +12 -0
  7. ex4nicegui/reactive/base.py +433 -0
  8. ex4nicegui/reactive/deferredTask.py +3 -2
  9. ex4nicegui/reactive/mixins/backgroundColor.py +41 -0
  10. ex4nicegui/reactive/mixins/disableable.py +44 -0
  11. ex4nicegui/reactive/mixins/textColor.py +66 -0
  12. ex4nicegui/reactive/officials/aggrid.py +5 -5
  13. ex4nicegui/reactive/officials/base.py +4 -453
  14. ex4nicegui/reactive/officials/button.py +43 -10
  15. ex4nicegui/reactive/officials/checkbox.py +5 -5
  16. ex4nicegui/reactive/officials/chip.py +102 -0
  17. ex4nicegui/reactive/officials/circular_progress.py +9 -7
  18. ex4nicegui/reactive/officials/color_picker.py +7 -7
  19. ex4nicegui/reactive/officials/column.py +5 -5
  20. ex4nicegui/reactive/officials/date.py +5 -5
  21. ex4nicegui/reactive/officials/dialog.py +49 -0
  22. ex4nicegui/reactive/officials/echarts.py +49 -51
  23. ex4nicegui/reactive/officials/expansion.py +5 -5
  24. ex4nicegui/reactive/officials/grid.py +3 -2
  25. ex4nicegui/reactive/officials/icon.py +8 -11
  26. ex4nicegui/reactive/officials/image.py +5 -5
  27. ex4nicegui/reactive/officials/input.py +8 -8
  28. ex4nicegui/reactive/officials/knob.py +9 -5
  29. ex4nicegui/reactive/officials/label.py +8 -15
  30. ex4nicegui/reactive/officials/linear_progress.py +8 -11
  31. ex4nicegui/reactive/officials/number.py +9 -9
  32. ex4nicegui/reactive/officials/radio.py +8 -8
  33. ex4nicegui/reactive/officials/row.py +5 -5
  34. ex4nicegui/reactive/officials/select.py +9 -8
  35. ex4nicegui/reactive/officials/slider.py +6 -6
  36. ex4nicegui/reactive/officials/switch.py +5 -5
  37. ex4nicegui/reactive/officials/tab.py +0 -12
  38. ex4nicegui/reactive/officials/tab_panels.py +113 -7
  39. ex4nicegui/reactive/officials/table.py +13 -13
  40. ex4nicegui/reactive/officials/tabs.py +5 -5
  41. ex4nicegui/reactive/officials/textarea.py +5 -5
  42. ex4nicegui/reactive/officials/tooltip.py +40 -0
  43. ex4nicegui/reactive/q_pagination.py +5 -5
  44. ex4nicegui/reactive/scopedStyle.py +4 -1
  45. ex4nicegui/reactive/systems/color_system.py +132 -0
  46. ex4nicegui/reactive/vfor.js +14 -4
  47. ex4nicegui/reactive/vfor.py +128 -58
  48. ex4nicegui/reactive/view_model.py +160 -0
  49. ex4nicegui/reactive/vmodel.py +42 -12
  50. ex4nicegui/utils/apiEffect.py +5 -1
  51. ex4nicegui/utils/effect.py +3 -2
  52. ex4nicegui/utils/scheduler.py +20 -4
  53. ex4nicegui/utils/signals.py +23 -21
  54. {ex4nicegui-0.6.8.dist-info → ex4nicegui-0.7.0.dist-info}/METADATA +247 -48
  55. {ex4nicegui-0.6.8.dist-info → ex4nicegui-0.7.0.dist-info}/RECORD +57 -50
  56. ex4nicegui/reactive/services/color_service.py +0 -56
  57. {ex4nicegui-0.6.8.dist-info → ex4nicegui-0.7.0.dist-info}/LICENSE +0 -0
  58. {ex4nicegui-0.6.8.dist-info → ex4nicegui-0.7.0.dist-info}/WHEEL +0 -0
@@ -11,11 +11,13 @@ from ex4nicegui.utils.signals import (
11
11
  )
12
12
  from nicegui import ui
13
13
  from .base import BindableUi, DisableableMixin
14
+ from ex4nicegui.reactive.mixins.textColor import TextColorableMixin
14
15
 
15
16
 
16
17
  class KnobBindableUi(
17
18
  BindableUi[ui.knob],
18
19
  DisableableMixin,
20
+ TextColorableMixin,
19
21
  ):
20
22
  def __init__(
21
23
  self,
@@ -59,15 +61,17 @@ class KnobBindableUi(
59
61
  def value(self):
60
62
  return self.element.value
61
63
 
62
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
64
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
63
65
  if prop == "value":
64
- return self.bind_value(ref_ui)
66
+ return self.bind_value(value)
67
+ if prop == "color":
68
+ return self.bind_color(value)
65
69
 
66
- return super().bind_prop(prop, ref_ui)
70
+ return super().bind_prop(prop, value)
67
71
 
68
- def bind_value(self, ref_ui: TGetterOrReadonlyRef[float]):
72
+ def bind_value(self, value: TGetterOrReadonlyRef[float]):
69
73
  @self._ui_effect
70
74
  def _():
71
- self.element.set_value(to_value(ref_ui))
75
+ self.element.set_value(to_value(value))
72
76
 
73
77
  return self
@@ -7,9 +7,10 @@ from ex4nicegui.utils.signals import (
7
7
  )
8
8
  from nicegui import ui
9
9
  from .base import BindableUi
10
+ from ex4nicegui.reactive.mixins.textColor import HtmlTextColorableMixin
10
11
 
11
12
 
12
- class LabelBindableUi(BindableUi[ui.label]):
13
+ class LabelBindableUi(BindableUi[ui.label], HtmlTextColorableMixin):
13
14
  def __init__(
14
15
  self,
15
16
  text: TMaybeRef[Any] = "",
@@ -26,27 +27,19 @@ class LabelBindableUi(BindableUi[ui.label]):
26
27
  def text(self):
27
28
  return self.element.text
28
29
 
29
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
30
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
30
31
  if prop == "text":
31
- return self.bind_text(ref_ui)
32
+ return self.bind_text(value)
32
33
 
33
34
  if prop == "color":
34
- return self.bind_color(ref_ui)
35
+ return self.bind_color(value)
35
36
 
36
- return super().bind_prop(prop, ref_ui)
37
+ return super().bind_prop(prop, value)
37
38
 
38
- def bind_color(self, ref_ui: TGetterOrReadonlyRef):
39
+ def bind_text(self, text: TGetterOrReadonlyRef):
39
40
  @self._ui_effect
40
41
  def _():
41
- ele = self.element
42
- color = to_value(ref_ui)
43
- ele._style["color"] = color
44
- ele.update()
45
-
46
- def bind_text(self, ref_ui: TGetterOrReadonlyRef):
47
- @self._ui_effect
48
- def _():
49
- self.element.set_text(str(to_value(ref_ui)))
42
+ self.element.set_text(str(to_value(text)))
50
43
  self.element.update()
51
44
 
52
45
  return self
@@ -10,10 +10,10 @@ from ex4nicegui.utils.signals import (
10
10
  from nicegui import ui
11
11
 
12
12
  from .base import BindableUi
13
- from ex4nicegui.reactive.services import color_service
13
+ from ex4nicegui.reactive.mixins.textColor import TextColorableMixin
14
14
 
15
15
 
16
- class LinearProgressBindableUi(BindableUi[ui.linear_progress]):
16
+ class LinearProgressBindableUi(BindableUi[ui.linear_progress], TextColorableMixin):
17
17
  def __init__(
18
18
  self,
19
19
  value: TMaybeRef[float] = 0.0,
@@ -46,21 +46,18 @@ class LinearProgressBindableUi(BindableUi[ui.linear_progress]):
46
46
  def value(self):
47
47
  return self.element.value
48
48
 
49
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
49
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
50
50
  if prop == "value":
51
- return self.bind_value(ref_ui)
51
+ return self.bind_value(value)
52
52
 
53
53
  if prop == "color":
54
- return self.bind_color(ref_ui)
54
+ return self.bind_color(value)
55
55
 
56
- return super().bind_prop(prop, ref_ui)
56
+ return super().bind_prop(prop, value)
57
57
 
58
- def bind_color(self, ref_ui: TGetterOrReadonlyRef):
59
- return color_service.bind_color(self, ref_ui)
60
-
61
- def bind_value(self, ref_ui: TGetterOrReadonlyRef):
58
+ def bind_value(self, value: TGetterOrReadonlyRef):
62
59
  @self._ui_effect
63
60
  def _():
64
- self.element.set_value(to_value(ref_ui))
61
+ self.element.set_value(to_value(value))
65
62
 
66
63
  return self
@@ -70,26 +70,26 @@ class NumberBindableUi(BindableUi[ui.number]):
70
70
  def value(self):
71
71
  return self.element.value
72
72
 
73
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
73
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
74
74
  if prop == "value":
75
- return self.bind_value(ref_ui)
75
+ return self.bind_value(value)
76
76
 
77
77
  if prop == "precision":
78
- return self._bind_precision(ref_ui)
78
+ return self._bind_precision(value)
79
79
 
80
- return super().bind_prop(prop, ref_ui)
80
+ return super().bind_prop(prop, value)
81
81
 
82
- def bind_value(self, ref_ui: TGetterOrReadonlyRef[float]):
82
+ def bind_value(self, value: TGetterOrReadonlyRef[float]):
83
83
  @self._ui_effect
84
84
  def _():
85
- self.element.set_value(to_value(ref_ui))
85
+ self.element.set_value(to_value(value))
86
86
 
87
87
  return self
88
88
 
89
- def _bind_precision(self, ref_ui: TGetterOrReadonlyRef[int]):
90
- @self._ui_signal_on(ref_ui, onchanges=True)
89
+ def _bind_precision(self, precision: TGetterOrReadonlyRef[int]):
90
+ @self._ui_signal_on(precision, onchanges=True)
91
91
  def _():
92
- self.element.precision = to_value(ref_ui)
92
+ self.element.precision = to_value(precision)
93
93
  self.element.sanitize()
94
94
 
95
95
  return self
@@ -51,25 +51,25 @@ class RadioBindableUi(BindableUi[ui.radio]):
51
51
  def value(self):
52
52
  return self.element.value
53
53
 
54
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
54
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
55
55
  if prop == "value":
56
- return self.bind_value(ref_ui)
56
+ return self.bind_value(value)
57
57
 
58
58
  if prop == "options":
59
- return self.bind_options(ref_ui)
59
+ return self.bind_options(value)
60
60
 
61
- return super().bind_prop(prop, ref_ui)
61
+ return super().bind_prop(prop, value)
62
62
 
63
- def bind_options(self, ref_ui: TGetterOrReadonlyRef):
63
+ def bind_options(self, options: TGetterOrReadonlyRef):
64
64
  @self._ui_effect
65
65
  def _():
66
- self.element.set_options(to_value(ref_ui))
66
+ self.element.set_options(to_value(options))
67
67
 
68
68
  return self
69
69
 
70
- def bind_value(self, ref_ui: TGetterOrReadonlyRef):
70
+ def bind_value(self, value: TGetterOrReadonlyRef):
71
71
  @self._ui_effect
72
72
  def _():
73
- cast(ValueElement, self.element).set_value(to_value(ref_ui))
73
+ cast(ValueElement, self.element).set_value(to_value(value))
74
74
 
75
75
  return self
@@ -18,14 +18,14 @@ class RowBindableUi(BindableUi[ui.row]):
18
18
  for key, value in pc.get_bindings().items():
19
19
  self.bind_prop(key, value) # type: ignore
20
20
 
21
- def bind_prop(self, prop: str, ref_ui: TMaybeRef):
21
+ def bind_prop(self, prop: str, value: TMaybeRef):
22
22
  if prop == "wrap":
23
- return self.bind_wrap(ref_ui)
23
+ return self.bind_wrap(value)
24
24
 
25
- return super().bind_prop(prop, ref_ui)
25
+ return super().bind_prop(prop, value)
26
26
 
27
- def bind_wrap(self, ref_ui: TMaybeRef):
28
- self.bind_classes({"wrap": ref_ui})
27
+ def bind_wrap(self, value: TMaybeRef):
28
+ self.bind_classes({"wrap": value})
29
29
 
30
30
  def __enter__(self):
31
31
  self.element.__enter__()
@@ -13,6 +13,7 @@ from ex4nicegui.utils.signals import (
13
13
  TGetterOrReadonlyRef,
14
14
  _TMaybeRef as TMaybeRef,
15
15
  to_value,
16
+ to_raw,
16
17
  )
17
18
  from nicegui import ui
18
19
  from nicegui.elements.mixins.value_element import ValueElement
@@ -73,25 +74,25 @@ class SelectBindableUi(BindableUi[ui.select]):
73
74
  def value(self):
74
75
  return self.element.value
75
76
 
76
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
77
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
77
78
  if prop == "value":
78
- return self.bind_value(ref_ui)
79
+ return self.bind_value(value)
79
80
 
80
81
  if prop == "options":
81
- return self.bind_options(ref_ui)
82
+ return self.bind_options(value)
82
83
 
83
- return super().bind_prop(prop, ref_ui)
84
+ return super().bind_prop(prop, value)
84
85
 
85
- def bind_options(self, ref_ui: TGetterOrReadonlyRef):
86
+ def bind_options(self, options: TGetterOrReadonlyRef):
86
87
  @self._ui_effect()
87
88
  def _():
88
- self.element.set_options(to_value(ref_ui))
89
+ self.element.set_options(to_value(options))
89
90
 
90
91
  return self
91
92
 
92
- def bind_value(self, ref_ui: TGetterOrReadonlyRef):
93
+ def bind_value(self, value: TGetterOrReadonlyRef):
93
94
  @self._ui_effect()
94
95
  def _():
95
- cast(ValueElement, self.element).set_value(to_value(ref_ui) or None)
96
+ cast(ValueElement, self.element).set_value(to_raw(to_value(value)) or None)
96
97
 
97
98
  return self
@@ -30,7 +30,7 @@ class SliderBindableUi(
30
30
  min: TMaybeRef[_TSliderValue],
31
31
  max: TMaybeRef[_TSliderValue],
32
32
  step: TMaybeRef[_TSliderValue] = 1.0,
33
- value: TMaybeRef[_TSliderValue] = None,
33
+ value: Optional[TMaybeRef[_TSliderValue]] = None,
34
34
  on_change: Optional[Callable[..., Any]] = None,
35
35
  ) -> None:
36
36
  pc = ParameterClassifier(
@@ -58,16 +58,16 @@ class SliderBindableUi(
58
58
  def value(self):
59
59
  return self.element.value
60
60
 
61
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
61
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
62
62
  if prop == "value":
63
- return self.bind_value(ref_ui)
63
+ return self.bind_value(value)
64
64
 
65
- return super().bind_prop(prop, ref_ui)
65
+ return super().bind_prop(prop, value)
66
66
 
67
- def bind_value(self, ref_ui: TGetterOrReadonlyRef[float]):
67
+ def bind_value(self, value: TGetterOrReadonlyRef[float]):
68
68
  @self._ui_effect
69
69
  def _():
70
- self.element.set_value(to_value(ref_ui))
70
+ self.element.set_value(to_value(value))
71
71
  self.element.update()
72
72
 
73
73
  return self
@@ -47,15 +47,15 @@ class SwitchBindableUi(BindableUi[ui.switch]):
47
47
  def value(self):
48
48
  return self.element.value
49
49
 
50
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
50
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
51
51
  if prop == "value":
52
- return self.bind_value(ref_ui)
52
+ return self.bind_value(value)
53
53
 
54
- return super().bind_prop(prop, ref_ui)
54
+ return super().bind_prop(prop, value)
55
55
 
56
- def bind_value(self, ref_ui: TGetterOrReadonlyRef[bool]):
56
+ def bind_value(self, value: TGetterOrReadonlyRef[bool]):
57
57
  @self._ui_effect
58
58
  def _():
59
- self.element.set_value(to_value(ref_ui))
59
+ self.element.set_value(to_value(value))
60
60
 
61
61
  return self
@@ -33,12 +33,6 @@ class TabBindableUi(BindableUi[ui.tab]):
33
33
  for key, value in bindings_kws.items():
34
34
  self.bind_prop(key, value) # type: ignore
35
35
 
36
- # def bind_prop(self, prop: str, ref_ui: TMaybeRef):
37
- # if prop == "name":
38
- # return self.bind_name(ref_ui)
39
-
40
- # return super().bind_prop(prop, ref_ui)
41
-
42
36
  def __bind_label(self, binding_kws: Dict, value_kws: Dict):
43
37
  name_ref = binding_kws.get("name") or value_kws.get("name")
44
38
  label_ref = binding_kws.get("label") or value_kws.get("label")
@@ -49,9 +43,3 @@ class TabBindableUi(BindableUi[ui.tab]):
49
43
  to_value(label_ref) if label_ref is not None else to_value(name_ref)
50
44
  )
51
45
  self.element.update()
52
-
53
- # def bind_name(self, ref_ui: TMaybeRef):
54
- # @self._ui_effect
55
- # def _():
56
- # self.element._props["name"] = to_value(ref_ui)
57
- # self.element.update()
@@ -1,11 +1,14 @@
1
- from typing import Any, Callable, Optional
1
+ import inspect
2
+ from typing import Any, Awaitable, Callable, Optional, Union
3
+ from weakref import WeakValueDictionary
2
4
  from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
3
5
  from ex4nicegui.utils.signals import (
4
6
  TGetterOrReadonlyRef,
5
7
  to_value,
6
8
  _TMaybeRef as TMaybeRef,
7
9
  )
8
- from nicegui import ui
10
+ from ex4nicegui.utils.scheduler import next_tick
11
+ from nicegui import ui, background_tasks, core
9
12
  from .base import BindableUi
10
13
 
11
14
 
@@ -46,13 +49,116 @@ class TabPanelsBindableUi(BindableUi[ui.tab_panels]):
46
49
  def value(self):
47
50
  return self.element.value
48
51
 
49
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
52
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
50
53
  if prop == "value":
51
- return self.bind_value(ref_ui)
54
+ return self.bind_value(value)
52
55
 
53
- return super().bind_prop(prop, ref_ui)
56
+ return super().bind_prop(prop, value)
54
57
 
55
- def bind_value(self, ref_ui: TGetterOrReadonlyRef):
58
+ def bind_value(self, value: TGetterOrReadonlyRef):
56
59
  @self._ui_effect
57
60
  def _():
58
- self.element.set_value(to_value(ref_ui))
61
+ self.element.set_value(to_value(value))
62
+
63
+
64
+ class lazy_tab_panel(ui.tab_panel):
65
+ def __init__(self, name: str) -> None:
66
+ super().__init__(name)
67
+ self._build_fn = None
68
+
69
+ def try_run_build_fn(self):
70
+ if self._build_fn:
71
+ _helper.run_build_fn(self, self._props["name"])
72
+ self._build_fn = None
73
+
74
+ def build_fn(self, fn: Callable[..., Union[None, Awaitable]]):
75
+ self._build_fn = fn
76
+ return fn
77
+
78
+
79
+ class LazyTabPanelsBindableUi(TabPanelsBindableUi):
80
+ def __init__(
81
+ self,
82
+ value: Optional[TMaybeRef[str]] = None,
83
+ *,
84
+ on_change: Optional[Callable[..., Any]] = None,
85
+ animated: TMaybeRef[bool] = True,
86
+ keep_alive: TMaybeRef[bool] = True,
87
+ ) -> None:
88
+ """Lazy Tab Panels
89
+
90
+ @see - https://github.com/CrystalWindSnake/ex4nicegui/blob/main/README.en.md#lazy_tab_panels
91
+ @中文文档 - https://gitee.com/carson_add/ex4nicegui/tree/main/#lazy_tab_panels
92
+
93
+ Args:
94
+ value (Optional[TMaybeRef[str]], optional): The value of the tab panel. Defaults to None.
95
+ on_change (Optional[Callable[..., Any]], optional): The callback function when the value of the tab panel changes. Defaults to None.
96
+ animated (TMaybeRef[bool], optional): Whether to animate the tab panel. Defaults to True.
97
+ keep_alive (TMaybeRef[bool], optional): Whether to keep the tab panel alive. Defaults to True.
98
+ """
99
+ super().__init__(
100
+ value, on_change=on_change, animated=animated, keep_alive=keep_alive
101
+ )
102
+
103
+ self.__panels: WeakValueDictionary[str, lazy_tab_panel] = WeakValueDictionary()
104
+
105
+ if value:
106
+
107
+ @self._ui_effect
108
+ def _():
109
+ current_value = to_value(value)
110
+ if current_value in self.__panels:
111
+ panel = self.__panels[current_value]
112
+
113
+ @next_tick
114
+ def _():
115
+ panel.try_run_build_fn()
116
+
117
+ def add_tab_panel(self, name: str):
118
+ def decorator(fn: Callable[..., Union[None, Awaitable]]):
119
+ with self:
120
+ panel = lazy_tab_panel(name)
121
+ str_name = panel._props["name"]
122
+ self.__panels[str_name] = panel
123
+ panel.build_fn(fn)
124
+
125
+ if self.value == name:
126
+ panel.try_run_build_fn()
127
+
128
+ return panel
129
+
130
+ return decorator
131
+
132
+
133
+ class _helper:
134
+ @staticmethod
135
+ def run_build_fn(panel: lazy_tab_panel, name: str) -> None:
136
+ """ """
137
+ fn = panel._build_fn
138
+ if fn is None:
139
+ return
140
+ try:
141
+ expects_arguments = any(
142
+ p.default is inspect.Parameter.empty
143
+ and p.kind is not inspect.Parameter.VAR_POSITIONAL
144
+ and p.kind is not inspect.Parameter.VAR_KEYWORD
145
+ for p in inspect.signature(fn).parameters.values()
146
+ )
147
+
148
+ with panel:
149
+ result = fn(name) if expects_arguments else fn()
150
+ if isinstance(result, Awaitable):
151
+ # NOTE: await an awaitable result even if the handler is not a coroutine (like a lambda statement)
152
+ async def wait_for_result():
153
+ with panel:
154
+ try:
155
+ await result
156
+ except Exception as e:
157
+ core.app.handle_exception(e)
158
+
159
+ if core.loop and core.loop.is_running():
160
+ background_tasks.create(wait_for_result(), name=str(fn))
161
+ else:
162
+ core.app.on_startup(wait_for_result())
163
+ except Exception as e:
164
+ core.app.handle_exception(e)
@@ -145,22 +145,22 @@ class TableBindableUi(BindableUi[ui.table]):
145
145
  ]
146
146
  return cls(cols, rows, **other_kws)
147
147
 
148
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
148
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
149
149
  if prop == "dataframe":
150
- return self.bind_dataframe(ref_ui)
150
+ return self.bind_dataframe(value)
151
151
 
152
152
  if prop == "rows":
153
- return self.bind_rows(ref_ui)
153
+ return self.bind_rows(value)
154
154
 
155
155
  if prop == "columns":
156
- return self.bind_columns(ref_ui)
156
+ return self.bind_columns(value)
157
157
 
158
- return super().bind_prop(prop, ref_ui)
158
+ return super().bind_prop(prop, value)
159
159
 
160
- def bind_dataframe(self, ref_df: TGetterOrReadonlyRef):
160
+ def bind_dataframe(self, dataframe: TGetterOrReadonlyRef):
161
161
  @ref_computed
162
162
  def cp_converted_df():
163
- df = ref_df.value
163
+ df = dataframe.value
164
164
  return utils_common.convert_dataframe(df)
165
165
 
166
166
  @ref_computed
@@ -182,20 +182,20 @@ class TableBindableUi(BindableUi[ui.table]):
182
182
 
183
183
  return self
184
184
 
185
- def bind_rows(self, ref_ui: TGetterOrReadonlyRef[List[Dict]]):
186
- @self._ui_signal_on(ref_ui, deep=True)
185
+ def bind_rows(self, rows: TGetterOrReadonlyRef[List[Dict]]):
186
+ @self._ui_signal_on(rows, deep=True)
187
187
  def _():
188
188
  ele = self.element
189
- ele._props["rows"] = list(to_raw(to_value(ref_ui)))
189
+ ele._props["rows"] = list(to_raw(to_value(rows)))
190
190
  ele.update()
191
191
 
192
192
  return self
193
193
 
194
- def bind_columns(self, ref_ui: TGetterOrReadonlyRef[List[Dict]]):
195
- @self._ui_signal_on(ref_ui, deep=True)
194
+ def bind_columns(self, columns: TGetterOrReadonlyRef[List[Dict]]):
195
+ @self._ui_signal_on(columns, deep=True)
196
196
  def _():
197
197
  ele = self.element
198
- ele._props["columns"] = list(to_raw(to_value(ref_ui)))
198
+ ele._props["columns"] = list(to_raw(to_value(columns)))
199
199
  ele.update()
200
200
 
201
201
  return self
@@ -32,13 +32,13 @@ class TabsBindableUi(BindableUi[ui.tabs]):
32
32
  def value(self):
33
33
  return self.element.value
34
34
 
35
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
35
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
36
36
  if prop == "value":
37
- return self.bind_value(ref_ui)
37
+ return self.bind_value(value)
38
38
 
39
- return super().bind_prop(prop, ref_ui)
39
+ return super().bind_prop(prop, value)
40
40
 
41
- def bind_value(self, ref_ui: TGetterOrReadonlyRef):
41
+ def bind_value(self, value: TGetterOrReadonlyRef):
42
42
  @self._ui_effect
43
43
  def _():
44
- self.element.set_value(to_value(ref_ui))
44
+ self.element.set_value(to_value(value))
@@ -52,16 +52,16 @@ class TextareaBindableUi(BindableUi[ui.textarea]):
52
52
  def value(self):
53
53
  return self.element.value
54
54
 
55
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
55
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
56
56
  if prop == "value":
57
- return self.bind_value(ref_ui)
57
+ return self.bind_value(value)
58
58
 
59
- return super().bind_prop(prop, ref_ui)
59
+ return super().bind_prop(prop, value)
60
60
 
61
- def bind_value(self, ref_ui: TGetterOrReadonlyRef[str]):
61
+ def bind_value(self, value: TGetterOrReadonlyRef[str]):
62
62
  @self._ui_effect
63
63
  def _():
64
- self.element.set_value(to_value(ref_ui))
64
+ self.element.set_value(to_value(value))
65
65
 
66
66
  return self
67
67
 
@@ -0,0 +1,40 @@
1
+ from typing import Any
2
+ from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
3
+ from ex4nicegui.utils.signals import (
4
+ TGetterOrReadonlyRef,
5
+ to_value,
6
+ _TMaybeRef as TMaybeRef,
7
+ )
8
+ from nicegui import ui
9
+ from .base import BindableUi
10
+
11
+
12
+ class TooltipBindableUi(BindableUi[ui.tooltip]):
13
+ def __init__(
14
+ self,
15
+ text: TMaybeRef[Any] = "",
16
+ ) -> None:
17
+ pc = ParameterClassifier(locals(), maybeRefs=["text"], events=[])
18
+
19
+ element = ui.tooltip(**pc.get_values_kws())
20
+ super().__init__(element)
21
+
22
+ for key, value in pc.get_bindings().items():
23
+ self.bind_prop(key, value) # type: ignore
24
+
25
+ @property
26
+ def text(self):
27
+ return self.element.text
28
+
29
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
30
+ if prop == "text":
31
+ return self.bind_text(value)
32
+
33
+ return super().bind_prop(prop, value)
34
+
35
+ def bind_text(self, text: TGetterOrReadonlyRef):
36
+ @self._ui_effect
37
+ def _():
38
+ self.element.set_text(str(to_value(text)))
39
+
40
+ return self
@@ -36,15 +36,15 @@ class PaginationBindableUi(BindableUi[ui.pagination]):
36
36
  def value(self):
37
37
  return self.element.value
38
38
 
39
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
39
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
40
40
  if prop == "value":
41
- return self.bind_value(ref_ui)
41
+ return self.bind_value(value)
42
42
 
43
- return super().bind_prop(prop, ref_ui)
43
+ return super().bind_prop(prop, value)
44
44
 
45
- def bind_value(self, ref_ui: TGetterOrReadonlyRef[int]):
45
+ def bind_value(self, value: TGetterOrReadonlyRef[int]):
46
46
  @self._ui_effect
47
47
  def _():
48
- self.element.set_value(to_value(ref_ui))
48
+ self.element.set_value(to_value(value))
49
49
 
50
50
  return self
@@ -1,5 +1,6 @@
1
1
  from nicegui.element import Element
2
2
  from ex4nicegui.helper import client_instance_locker
3
+ from nicegui import ui
3
4
 
4
5
 
5
6
  class ScopedStyle(Element, component="scopedStyle.js"):
@@ -7,7 +8,9 @@ class ScopedStyle(Element, component="scopedStyle.js"):
7
8
 
8
9
  @staticmethod
9
10
  def get():
10
- return _scoped_style_factory.get_object()
11
+ if not ui.context.slot_stack:
12
+ return None
13
+ return _scoped_style_factory.get_object(ui.context.client)
11
14
 
12
15
  def create_style(self, element: Element, css: str):
13
16
  element_id = f"c{element.id}"