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.
- ex4nicegui/__init__.py +2 -0
- ex4nicegui/bi/dataSourceFacade.py +20 -20
- ex4nicegui/bi/index.py +20 -23
- ex4nicegui/helper/client_instance_locker.py +4 -4
- ex4nicegui/reactive/EChartsComponent/ECharts.py +9 -8
- ex4nicegui/reactive/__init__.py +12 -0
- ex4nicegui/reactive/base.py +433 -0
- ex4nicegui/reactive/deferredTask.py +3 -2
- ex4nicegui/reactive/mixins/backgroundColor.py +41 -0
- ex4nicegui/reactive/mixins/disableable.py +44 -0
- ex4nicegui/reactive/mixins/textColor.py +66 -0
- ex4nicegui/reactive/officials/aggrid.py +5 -5
- ex4nicegui/reactive/officials/base.py +4 -453
- ex4nicegui/reactive/officials/button.py +43 -10
- ex4nicegui/reactive/officials/checkbox.py +5 -5
- ex4nicegui/reactive/officials/chip.py +102 -0
- ex4nicegui/reactive/officials/circular_progress.py +9 -7
- ex4nicegui/reactive/officials/color_picker.py +7 -7
- ex4nicegui/reactive/officials/column.py +5 -5
- ex4nicegui/reactive/officials/date.py +5 -5
- ex4nicegui/reactive/officials/dialog.py +49 -0
- ex4nicegui/reactive/officials/echarts.py +49 -51
- ex4nicegui/reactive/officials/expansion.py +5 -5
- ex4nicegui/reactive/officials/grid.py +3 -2
- ex4nicegui/reactive/officials/icon.py +8 -11
- ex4nicegui/reactive/officials/image.py +5 -5
- ex4nicegui/reactive/officials/input.py +8 -8
- ex4nicegui/reactive/officials/knob.py +9 -5
- ex4nicegui/reactive/officials/label.py +8 -15
- ex4nicegui/reactive/officials/linear_progress.py +8 -11
- ex4nicegui/reactive/officials/number.py +9 -9
- ex4nicegui/reactive/officials/radio.py +8 -8
- ex4nicegui/reactive/officials/row.py +5 -5
- ex4nicegui/reactive/officials/select.py +9 -8
- ex4nicegui/reactive/officials/slider.py +6 -6
- ex4nicegui/reactive/officials/switch.py +5 -5
- ex4nicegui/reactive/officials/tab.py +0 -12
- ex4nicegui/reactive/officials/tab_panels.py +113 -7
- ex4nicegui/reactive/officials/table.py +13 -13
- ex4nicegui/reactive/officials/tabs.py +5 -5
- ex4nicegui/reactive/officials/textarea.py +5 -5
- ex4nicegui/reactive/officials/tooltip.py +40 -0
- ex4nicegui/reactive/q_pagination.py +5 -5
- ex4nicegui/reactive/scopedStyle.py +4 -1
- ex4nicegui/reactive/systems/color_system.py +132 -0
- ex4nicegui/reactive/vfor.js +14 -4
- ex4nicegui/reactive/vfor.py +128 -58
- ex4nicegui/reactive/view_model.py +160 -0
- ex4nicegui/reactive/vmodel.py +42 -12
- ex4nicegui/utils/apiEffect.py +5 -1
- ex4nicegui/utils/effect.py +3 -2
- ex4nicegui/utils/scheduler.py +20 -4
- ex4nicegui/utils/signals.py +23 -21
- {ex4nicegui-0.6.8.dist-info → ex4nicegui-0.7.0.dist-info}/METADATA +247 -48
- {ex4nicegui-0.6.8.dist-info → ex4nicegui-0.7.0.dist-info}/RECORD +57 -50
- ex4nicegui/reactive/services/color_service.py +0 -56
- {ex4nicegui-0.6.8.dist-info → ex4nicegui-0.7.0.dist-info}/LICENSE +0 -0
- {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,
|
|
64
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
63
65
|
if prop == "value":
|
|
64
|
-
return self.bind_value(
|
|
66
|
+
return self.bind_value(value)
|
|
67
|
+
if prop == "color":
|
|
68
|
+
return self.bind_color(value)
|
|
65
69
|
|
|
66
|
-
return super().bind_prop(prop,
|
|
70
|
+
return super().bind_prop(prop, value)
|
|
67
71
|
|
|
68
|
-
def bind_value(self,
|
|
72
|
+
def bind_value(self, value: TGetterOrReadonlyRef[float]):
|
|
69
73
|
@self._ui_effect
|
|
70
74
|
def _():
|
|
71
|
-
self.element.set_value(to_value(
|
|
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,
|
|
30
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
30
31
|
if prop == "text":
|
|
31
|
-
return self.bind_text(
|
|
32
|
+
return self.bind_text(value)
|
|
32
33
|
|
|
33
34
|
if prop == "color":
|
|
34
|
-
return self.bind_color(
|
|
35
|
+
return self.bind_color(value)
|
|
35
36
|
|
|
36
|
-
return super().bind_prop(prop,
|
|
37
|
+
return super().bind_prop(prop, value)
|
|
37
38
|
|
|
38
|
-
def
|
|
39
|
+
def bind_text(self, text: TGetterOrReadonlyRef):
|
|
39
40
|
@self._ui_effect
|
|
40
41
|
def _():
|
|
41
|
-
|
|
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.
|
|
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,
|
|
49
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
50
50
|
if prop == "value":
|
|
51
|
-
return self.bind_value(
|
|
51
|
+
return self.bind_value(value)
|
|
52
52
|
|
|
53
53
|
if prop == "color":
|
|
54
|
-
return self.bind_color(
|
|
54
|
+
return self.bind_color(value)
|
|
55
55
|
|
|
56
|
-
return super().bind_prop(prop,
|
|
56
|
+
return super().bind_prop(prop, value)
|
|
57
57
|
|
|
58
|
-
def
|
|
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(
|
|
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,
|
|
73
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
74
74
|
if prop == "value":
|
|
75
|
-
return self.bind_value(
|
|
75
|
+
return self.bind_value(value)
|
|
76
76
|
|
|
77
77
|
if prop == "precision":
|
|
78
|
-
return self._bind_precision(
|
|
78
|
+
return self._bind_precision(value)
|
|
79
79
|
|
|
80
|
-
return super().bind_prop(prop,
|
|
80
|
+
return super().bind_prop(prop, value)
|
|
81
81
|
|
|
82
|
-
def bind_value(self,
|
|
82
|
+
def bind_value(self, value: TGetterOrReadonlyRef[float]):
|
|
83
83
|
@self._ui_effect
|
|
84
84
|
def _():
|
|
85
|
-
self.element.set_value(to_value(
|
|
85
|
+
self.element.set_value(to_value(value))
|
|
86
86
|
|
|
87
87
|
return self
|
|
88
88
|
|
|
89
|
-
def _bind_precision(self,
|
|
90
|
-
@self._ui_signal_on(
|
|
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(
|
|
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,
|
|
54
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
55
55
|
if prop == "value":
|
|
56
|
-
return self.bind_value(
|
|
56
|
+
return self.bind_value(value)
|
|
57
57
|
|
|
58
58
|
if prop == "options":
|
|
59
|
-
return self.bind_options(
|
|
59
|
+
return self.bind_options(value)
|
|
60
60
|
|
|
61
|
-
return super().bind_prop(prop,
|
|
61
|
+
return super().bind_prop(prop, value)
|
|
62
62
|
|
|
63
|
-
def bind_options(self,
|
|
63
|
+
def bind_options(self, options: TGetterOrReadonlyRef):
|
|
64
64
|
@self._ui_effect
|
|
65
65
|
def _():
|
|
66
|
-
self.element.set_options(to_value(
|
|
66
|
+
self.element.set_options(to_value(options))
|
|
67
67
|
|
|
68
68
|
return self
|
|
69
69
|
|
|
70
|
-
def bind_value(self,
|
|
70
|
+
def bind_value(self, value: TGetterOrReadonlyRef):
|
|
71
71
|
@self._ui_effect
|
|
72
72
|
def _():
|
|
73
|
-
cast(ValueElement, self.element).set_value(to_value(
|
|
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,
|
|
21
|
+
def bind_prop(self, prop: str, value: TMaybeRef):
|
|
22
22
|
if prop == "wrap":
|
|
23
|
-
return self.bind_wrap(
|
|
23
|
+
return self.bind_wrap(value)
|
|
24
24
|
|
|
25
|
-
return super().bind_prop(prop,
|
|
25
|
+
return super().bind_prop(prop, value)
|
|
26
26
|
|
|
27
|
-
def bind_wrap(self,
|
|
28
|
-
self.bind_classes({"wrap":
|
|
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,
|
|
77
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
77
78
|
if prop == "value":
|
|
78
|
-
return self.bind_value(
|
|
79
|
+
return self.bind_value(value)
|
|
79
80
|
|
|
80
81
|
if prop == "options":
|
|
81
|
-
return self.bind_options(
|
|
82
|
+
return self.bind_options(value)
|
|
82
83
|
|
|
83
|
-
return super().bind_prop(prop,
|
|
84
|
+
return super().bind_prop(prop, value)
|
|
84
85
|
|
|
85
|
-
def bind_options(self,
|
|
86
|
+
def bind_options(self, options: TGetterOrReadonlyRef):
|
|
86
87
|
@self._ui_effect()
|
|
87
88
|
def _():
|
|
88
|
-
self.element.set_options(to_value(
|
|
89
|
+
self.element.set_options(to_value(options))
|
|
89
90
|
|
|
90
91
|
return self
|
|
91
92
|
|
|
92
|
-
def bind_value(self,
|
|
93
|
+
def bind_value(self, value: TGetterOrReadonlyRef):
|
|
93
94
|
@self._ui_effect()
|
|
94
95
|
def _():
|
|
95
|
-
cast(ValueElement, self.element).set_value(to_value(
|
|
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,
|
|
61
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
62
62
|
if prop == "value":
|
|
63
|
-
return self.bind_value(
|
|
63
|
+
return self.bind_value(value)
|
|
64
64
|
|
|
65
|
-
return super().bind_prop(prop,
|
|
65
|
+
return super().bind_prop(prop, value)
|
|
66
66
|
|
|
67
|
-
def bind_value(self,
|
|
67
|
+
def bind_value(self, value: TGetterOrReadonlyRef[float]):
|
|
68
68
|
@self._ui_effect
|
|
69
69
|
def _():
|
|
70
|
-
self.element.set_value(to_value(
|
|
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,
|
|
50
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
51
51
|
if prop == "value":
|
|
52
|
-
return self.bind_value(
|
|
52
|
+
return self.bind_value(value)
|
|
53
53
|
|
|
54
|
-
return super().bind_prop(prop,
|
|
54
|
+
return super().bind_prop(prop, value)
|
|
55
55
|
|
|
56
|
-
def bind_value(self,
|
|
56
|
+
def bind_value(self, value: TGetterOrReadonlyRef[bool]):
|
|
57
57
|
@self._ui_effect
|
|
58
58
|
def _():
|
|
59
|
-
self.element.set_value(to_value(
|
|
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
|
-
|
|
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
|
|
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,
|
|
52
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
50
53
|
if prop == "value":
|
|
51
|
-
return self.bind_value(
|
|
54
|
+
return self.bind_value(value)
|
|
52
55
|
|
|
53
|
-
return super().bind_prop(prop,
|
|
56
|
+
return super().bind_prop(prop, value)
|
|
54
57
|
|
|
55
|
-
def bind_value(self,
|
|
58
|
+
def bind_value(self, value: TGetterOrReadonlyRef):
|
|
56
59
|
@self._ui_effect
|
|
57
60
|
def _():
|
|
58
|
-
self.element.set_value(to_value(
|
|
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,
|
|
148
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
149
149
|
if prop == "dataframe":
|
|
150
|
-
return self.bind_dataframe(
|
|
150
|
+
return self.bind_dataframe(value)
|
|
151
151
|
|
|
152
152
|
if prop == "rows":
|
|
153
|
-
return self.bind_rows(
|
|
153
|
+
return self.bind_rows(value)
|
|
154
154
|
|
|
155
155
|
if prop == "columns":
|
|
156
|
-
return self.bind_columns(
|
|
156
|
+
return self.bind_columns(value)
|
|
157
157
|
|
|
158
|
-
return super().bind_prop(prop,
|
|
158
|
+
return super().bind_prop(prop, value)
|
|
159
159
|
|
|
160
|
-
def bind_dataframe(self,
|
|
160
|
+
def bind_dataframe(self, dataframe: TGetterOrReadonlyRef):
|
|
161
161
|
@ref_computed
|
|
162
162
|
def cp_converted_df():
|
|
163
|
-
df =
|
|
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,
|
|
186
|
-
@self._ui_signal_on(
|
|
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(
|
|
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,
|
|
195
|
-
@self._ui_signal_on(
|
|
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(
|
|
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,
|
|
35
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
36
36
|
if prop == "value":
|
|
37
|
-
return self.bind_value(
|
|
37
|
+
return self.bind_value(value)
|
|
38
38
|
|
|
39
|
-
return super().bind_prop(prop,
|
|
39
|
+
return super().bind_prop(prop, value)
|
|
40
40
|
|
|
41
|
-
def bind_value(self,
|
|
41
|
+
def bind_value(self, value: TGetterOrReadonlyRef):
|
|
42
42
|
@self._ui_effect
|
|
43
43
|
def _():
|
|
44
|
-
self.element.set_value(to_value(
|
|
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,
|
|
55
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
56
56
|
if prop == "value":
|
|
57
|
-
return self.bind_value(
|
|
57
|
+
return self.bind_value(value)
|
|
58
58
|
|
|
59
|
-
return super().bind_prop(prop,
|
|
59
|
+
return super().bind_prop(prop, value)
|
|
60
60
|
|
|
61
|
-
def bind_value(self,
|
|
61
|
+
def bind_value(self, value: TGetterOrReadonlyRef[str]):
|
|
62
62
|
@self._ui_effect
|
|
63
63
|
def _():
|
|
64
|
-
self.element.set_value(to_value(
|
|
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,
|
|
39
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
40
40
|
if prop == "value":
|
|
41
|
-
return self.bind_value(
|
|
41
|
+
return self.bind_value(value)
|
|
42
42
|
|
|
43
|
-
return super().bind_prop(prop,
|
|
43
|
+
return super().bind_prop(prop, value)
|
|
44
44
|
|
|
45
|
-
def bind_value(self,
|
|
45
|
+
def bind_value(self, value: TGetterOrReadonlyRef[int]):
|
|
46
46
|
@self._ui_effect
|
|
47
47
|
def _():
|
|
48
|
-
self.element.set_value(to_value(
|
|
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
|
-
|
|
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}"
|