ex4nicegui 0.6.7__py3-none-any.whl → 0.6.8__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 +10 -6
- ex4nicegui/gsap/__init__.py +11 -0
- ex4nicegui/helper/__init__.py +4 -0
- ex4nicegui/helper/client_instance_locker.py +31 -0
- ex4nicegui/reactive/local_file_picker.py +1 -2
- ex4nicegui/reactive/officials/aggrid.py +4 -4
- ex4nicegui/reactive/officials/base.py +188 -86
- ex4nicegui/reactive/officials/button.py +1 -1
- ex4nicegui/reactive/officials/checkbox.py +2 -3
- ex4nicegui/reactive/officials/circular_progress.py +2 -3
- ex4nicegui/reactive/officials/color_picker.py +3 -4
- ex4nicegui/reactive/officials/column.py +1 -1
- ex4nicegui/reactive/officials/date.py +2 -3
- ex4nicegui/reactive/officials/drawer.py +2 -3
- ex4nicegui/reactive/officials/echarts.py +2 -3
- ex4nicegui/reactive/officials/expansion.py +2 -3
- ex4nicegui/reactive/officials/grid.py +1 -1
- ex4nicegui/reactive/officials/html.py +1 -3
- ex4nicegui/reactive/officials/icon.py +5 -6
- ex4nicegui/reactive/officials/image.py +2 -4
- ex4nicegui/reactive/officials/input.py +4 -6
- ex4nicegui/reactive/officials/knob.py +2 -4
- ex4nicegui/reactive/officials/label.py +1 -1
- ex4nicegui/reactive/officials/linear_progress.py +5 -6
- ex4nicegui/reactive/officials/number.py +3 -6
- ex4nicegui/reactive/officials/radio.py +3 -5
- ex4nicegui/reactive/officials/row.py +1 -1
- ex4nicegui/reactive/officials/select.py +3 -5
- ex4nicegui/reactive/officials/slider.py +3 -5
- ex4nicegui/reactive/officials/switch.py +2 -4
- ex4nicegui/reactive/officials/tab.py +1 -1
- ex4nicegui/reactive/officials/tab_panel.py +1 -1
- ex4nicegui/reactive/officials/tab_panels.py +1 -1
- ex4nicegui/reactive/officials/table.py +7 -6
- ex4nicegui/reactive/officials/tabs.py +1 -1
- ex4nicegui/reactive/officials/textarea.py +3 -5
- ex4nicegui/reactive/officials/upload.py +2 -2
- ex4nicegui/reactive/q_pagination.py +2 -2
- ex4nicegui/reactive/scopedStyle.js +55 -0
- ex4nicegui/reactive/scopedStyle.py +22 -0
- ex4nicegui/reactive/services/color_service.py +56 -0
- ex4nicegui/reactive/services/pandas_service.py +31 -0
- ex4nicegui/reactive/{utils.py → services/reactive_service.py} +9 -67
- ex4nicegui/reactive/systems/color_system.py +25 -0
- ex4nicegui/reactive/systems/object_system.py +33 -0
- ex4nicegui/reactive/systems/reactive_system.py +21 -0
- ex4nicegui/reactive/useMouse/UseMouse.py +4 -4
- ex4nicegui/reactive/usePagination.py +1 -1
- ex4nicegui/reactive/vfor.py +1 -2
- ex4nicegui/reactive/vmodel.py +1 -1
- ex4nicegui/utils/refComputed.py +147 -0
- ex4nicegui/utils/refWrapper.py +57 -0
- ex4nicegui/utils/signals.py +51 -192
- ex4nicegui/utils/types.py +16 -0
- ex4nicegui/version.py +3 -0
- {ex4nicegui-0.6.7.dist-info → ex4nicegui-0.6.8.dist-info}/METADATA +33 -4
- {ex4nicegui-0.6.7.dist-info → ex4nicegui-0.6.8.dist-info}/RECORD +59 -53
- ex4nicegui/reactive/EChartsComponent/__init__.py +0 -0
- ex4nicegui/reactive/UseDraggable/__init__.py +0 -0
- ex4nicegui/reactive/dropZone/__init__.py +0 -0
- ex4nicegui/reactive/mermaid/__init__.py +0 -0
- ex4nicegui/reactive/officials/__init__.py +0 -1
- ex4nicegui/reactive/officials/utils.py +0 -11
- ex4nicegui/reactive/useMouse/__init__.py +0 -0
- {ex4nicegui-0.6.7.dist-info → ex4nicegui-0.6.8.dist-info}/LICENSE +0 -0
- {ex4nicegui-0.6.7.dist-info → ex4nicegui-0.6.8.dist-info}/WHEEL +0 -0
ex4nicegui/__init__.py
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
from ex4nicegui import reactive as rxui
|
|
2
|
+
from ex4nicegui.utils.refComputed import ref_computed
|
|
3
|
+
from ex4nicegui.utils.types import (
|
|
4
|
+
_TMaybeRef as TMaybeRef,
|
|
5
|
+
Ref,
|
|
6
|
+
ReadonlyRef,
|
|
7
|
+
TGetterOrReadonlyRef,
|
|
8
|
+
)
|
|
2
9
|
from ex4nicegui.utils.signals import (
|
|
3
|
-
ref_computed,
|
|
4
10
|
effect,
|
|
5
11
|
effect_refreshable,
|
|
6
12
|
to_raw,
|
|
@@ -10,9 +16,6 @@ from ex4nicegui.utils.signals import (
|
|
|
10
16
|
ref,
|
|
11
17
|
on,
|
|
12
18
|
event_batch,
|
|
13
|
-
_TMaybeRef as TMaybeRef,
|
|
14
|
-
Ref,
|
|
15
|
-
ReadonlyRef,
|
|
16
19
|
reactive,
|
|
17
20
|
deep_ref,
|
|
18
21
|
is_setter_ref,
|
|
@@ -21,6 +24,7 @@ from ex4nicegui.utils.signals import (
|
|
|
21
24
|
)
|
|
22
25
|
from ex4nicegui.utils.asyncComputed import async_computed
|
|
23
26
|
from ex4nicegui.utils.clientScope import new_scope
|
|
27
|
+
from .version import __version__
|
|
24
28
|
|
|
25
29
|
__all__ = [
|
|
26
30
|
"async_computed",
|
|
@@ -36,6 +40,7 @@ __all__ = [
|
|
|
36
40
|
"on",
|
|
37
41
|
"event_batch",
|
|
38
42
|
"TMaybeRef",
|
|
43
|
+
"TGetterOrReadonlyRef",
|
|
39
44
|
"Ref",
|
|
40
45
|
"ReadonlyRef",
|
|
41
46
|
"reactive",
|
|
@@ -44,6 +49,5 @@ __all__ = [
|
|
|
44
49
|
"to_raw",
|
|
45
50
|
"is_setter_ref",
|
|
46
51
|
"new_scope",
|
|
52
|
+
"__version__",
|
|
47
53
|
]
|
|
48
|
-
|
|
49
|
-
__version__ = "0.6.6"
|
ex4nicegui/gsap/__init__.py
CHANGED
|
@@ -2,6 +2,17 @@ from .gsap import set_defaults, from_, to, new, run_script
|
|
|
2
2
|
from .timeline import Timeline as timeline
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
import warnings
|
|
6
|
+
|
|
7
|
+
RED = "\033[91m"
|
|
8
|
+
RESET = "\033[0m"
|
|
9
|
+
|
|
10
|
+
warnings.warn(
|
|
11
|
+
f"{RED}The gsap module is deprecated and will be removed in the next major version.{RESET}",
|
|
12
|
+
DeprecationWarning,
|
|
13
|
+
stacklevel=2,
|
|
14
|
+
)
|
|
15
|
+
|
|
5
16
|
__all__ = [
|
|
6
17
|
"set_defaults",
|
|
7
18
|
"from_",
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from typing import Callable, TypeVar, Generic
|
|
2
|
+
from nicegui import ui, Client
|
|
3
|
+
from weakref import WeakKeyDictionary
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
_T = TypeVar("_T")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ClientInstanceLocker(Generic[_T]):
|
|
10
|
+
def __init__(self, factory: Callable[[], _T]):
|
|
11
|
+
"""Creates a new instance locker that creates a new instance for each client.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
factory (Callable[[], _T]): A factory function that creates a new instance.
|
|
15
|
+
"""
|
|
16
|
+
self._client_instances: WeakKeyDictionary[Client, _T] = WeakKeyDictionary()
|
|
17
|
+
self._factory = factory
|
|
18
|
+
|
|
19
|
+
def get_object(self):
|
|
20
|
+
if not ui.context.slot_stack:
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
client = ui.context.client
|
|
24
|
+
if client not in self._client_instances:
|
|
25
|
+
self._client_instances[client] = self._factory()
|
|
26
|
+
|
|
27
|
+
@client.on_disconnect
|
|
28
|
+
def _():
|
|
29
|
+
del self._client_instances[client]
|
|
30
|
+
|
|
31
|
+
return self._client_instances[client]
|
|
@@ -6,7 +6,6 @@ from pathlib import Path
|
|
|
6
6
|
from ex4nicegui.utils.signals import (
|
|
7
7
|
Ref,
|
|
8
8
|
effect_refreshable,
|
|
9
|
-
ReadonlyRef,
|
|
10
9
|
effect,
|
|
11
10
|
ref_computed as computed,
|
|
12
11
|
to_ref,
|
|
@@ -17,7 +16,7 @@ SelectMode = Literal["dir", "file"]
|
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
class LocalFilePickerResult:
|
|
20
|
-
def __init__(self, ref:
|
|
19
|
+
def __init__(self, ref: Ref[str], open_fn: Callable[..., None]) -> None:
|
|
21
20
|
self.__open_fn = open_fn
|
|
22
21
|
self._ref = ref
|
|
23
22
|
|
|
@@ -9,13 +9,13 @@ from ex4nicegui.utils.signals import (
|
|
|
9
9
|
is_ref,
|
|
10
10
|
ref_computed,
|
|
11
11
|
to_value,
|
|
12
|
-
|
|
12
|
+
TMaybeRef,
|
|
13
13
|
TGetterOrReadonlyRef,
|
|
14
14
|
)
|
|
15
|
-
from ex4nicegui.utils.apiEffect import ui_effect
|
|
16
15
|
from nicegui import ui
|
|
17
16
|
from .base import BindableUi
|
|
18
|
-
from ex4nicegui.reactive.
|
|
17
|
+
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
18
|
+
from ex4nicegui.reactive.services.pandas_service import dataframe2col_str
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class AggridBindableUi(BindableUi[ui.aggrid]):
|
|
@@ -85,7 +85,7 @@ class AggridBindableUi(BindableUi[ui.aggrid]):
|
|
|
85
85
|
return super().bind_prop(prop, ref_ui)
|
|
86
86
|
|
|
87
87
|
def bind_options(self, ref_ui: TGetterOrReadonlyRef[List[Dict]]):
|
|
88
|
-
@
|
|
88
|
+
@self._ui_effect
|
|
89
89
|
def _():
|
|
90
90
|
ele = self.element
|
|
91
91
|
data = to_value(ref_ui)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
from typing import (
|
|
4
5
|
Any,
|
|
5
6
|
Callable,
|
|
@@ -11,7 +12,7 @@ from typing import (
|
|
|
11
12
|
Generic,
|
|
12
13
|
Union,
|
|
13
14
|
cast,
|
|
14
|
-
|
|
15
|
+
overload,
|
|
15
16
|
)
|
|
16
17
|
|
|
17
18
|
from typing_extensions import Self
|
|
@@ -19,21 +20,18 @@ from ex4nicegui.utils.apiEffect import ui_effect
|
|
|
19
20
|
import signe
|
|
20
21
|
from ex4nicegui.utils.signals import (
|
|
21
22
|
TGetterOrReadonlyRef,
|
|
22
|
-
effect,
|
|
23
23
|
to_value,
|
|
24
24
|
is_ref,
|
|
25
25
|
WatchedState,
|
|
26
26
|
on,
|
|
27
27
|
)
|
|
28
|
+
from ex4nicegui.utils.clientScope import new_scope
|
|
28
29
|
from nicegui import Tailwind, ui
|
|
29
|
-
from nicegui.elements.mixins.color_elements import (
|
|
30
|
-
TextColorElement,
|
|
31
|
-
QUASAR_COLORS,
|
|
32
|
-
TAILWIND_COLORS,
|
|
33
|
-
)
|
|
34
30
|
from nicegui.elements.mixins.text_element import TextElement
|
|
35
31
|
from nicegui.elements.mixins.disableable_element import DisableableElement
|
|
36
|
-
|
|
32
|
+
from ex4nicegui.reactive.services.reactive_service import inject_handle_delete
|
|
33
|
+
from ex4nicegui.reactive.scopedStyle import ScopedStyle
|
|
34
|
+
from functools import partial
|
|
37
35
|
|
|
38
36
|
T = TypeVar("T")
|
|
39
37
|
|
|
@@ -42,21 +40,38 @@ TWidget = TypeVar("TWidget", bound=ui.element)
|
|
|
42
40
|
|
|
43
41
|
_T_bind_classes_type_dict = Dict[str, TGetterOrReadonlyRef[bool]]
|
|
44
42
|
_T_bind_classes_type_ref_dict = TGetterOrReadonlyRef[Dict[str, bool]]
|
|
45
|
-
|
|
43
|
+
_T_bind_classes_type_single = TGetterOrReadonlyRef[str]
|
|
44
|
+
_T_bind_classes_type_array = List[_T_bind_classes_type_single]
|
|
46
45
|
|
|
47
46
|
|
|
48
47
|
_T_bind_classes_type = Union[
|
|
49
|
-
_T_bind_classes_type_dict,
|
|
48
|
+
_T_bind_classes_type_dict,
|
|
49
|
+
_T_bind_classes_type_ref_dict,
|
|
50
|
+
_T_bind_classes_type_single,
|
|
51
|
+
_T_bind_classes_type_array,
|
|
50
52
|
]
|
|
51
53
|
|
|
52
54
|
|
|
53
55
|
class BindableUi(Generic[TWidget]):
|
|
54
56
|
def __init__(self, element: TWidget) -> None:
|
|
55
57
|
self._element = element
|
|
58
|
+
inject_handle_delete(self.element, self._on_element_delete)
|
|
56
59
|
self.tailwind = Tailwind(cast(ui.element, self._element))
|
|
60
|
+
self._effect_scope = new_scope()
|
|
57
61
|
|
|
58
|
-
def
|
|
59
|
-
|
|
62
|
+
def _on_element_delete(self):
|
|
63
|
+
self._effect_scope.dispose()
|
|
64
|
+
scope_style = ScopedStyle.get()
|
|
65
|
+
if scope_style:
|
|
66
|
+
scope_style.remove_style(self.element)
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def _ui_effect(self):
|
|
70
|
+
return partial(ui_effect, scope=self._effect_scope)
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def _ui_signal_on(self):
|
|
74
|
+
return partial(on, scope=self._effect_scope)
|
|
60
75
|
|
|
61
76
|
def props(self, add: Optional[str] = None, *, remove: Optional[str] = None):
|
|
62
77
|
cast(ui.element, self.element).props(add, remove=remove)
|
|
@@ -108,7 +123,7 @@ class BindableUi(Generic[TWidget]):
|
|
|
108
123
|
|
|
109
124
|
def delete(self) -> None:
|
|
110
125
|
"""Delete the element."""
|
|
111
|
-
self.delete()
|
|
126
|
+
self.element.delete()
|
|
112
127
|
|
|
113
128
|
def move(
|
|
114
129
|
self, target_container: Optional[ui.element] = None, target_index: int = -1
|
|
@@ -118,7 +133,7 @@ class BindableUi(Generic[TWidget]):
|
|
|
118
133
|
:param target_container: container to move the element to (default: the parent container)
|
|
119
134
|
:param target_index: index within the target slot (default: append to the end)
|
|
120
135
|
"""
|
|
121
|
-
return self.move(target_container, target_index)
|
|
136
|
+
return self.element.move(target_container, target_index)
|
|
122
137
|
|
|
123
138
|
def remove(self, element: Union[ui.element, int]) -> None:
|
|
124
139
|
"""Remove a child element.
|
|
@@ -192,6 +207,22 @@ class BindableUi(Generic[TWidget]):
|
|
|
192
207
|
def clear(self) -> None:
|
|
193
208
|
cast(ui.element, self.element).clear()
|
|
194
209
|
|
|
210
|
+
@overload
|
|
211
|
+
def bind_classes(self, classes: Dict[str, TGetterOrReadonlyRef[bool]]):
|
|
212
|
+
...
|
|
213
|
+
|
|
214
|
+
@overload
|
|
215
|
+
def bind_classes(self, classes: TGetterOrReadonlyRef[Dict[str, bool]]):
|
|
216
|
+
...
|
|
217
|
+
|
|
218
|
+
@overload
|
|
219
|
+
def bind_classes(self, classes: List[TGetterOrReadonlyRef[str]]):
|
|
220
|
+
...
|
|
221
|
+
|
|
222
|
+
@overload
|
|
223
|
+
def bind_classes(self, classes: TGetterOrReadonlyRef[str]):
|
|
224
|
+
...
|
|
225
|
+
|
|
195
226
|
def bind_classes(self, classes: _T_bind_classes_type):
|
|
196
227
|
"""data binding is manipulating an element's class list
|
|
197
228
|
|
|
@@ -199,7 +230,37 @@ class BindableUi(Generic[TWidget]):
|
|
|
199
230
|
@中文文档 - https://gitee.com/carson_add/ex4nicegui/tree/main/#%E7%BB%91%E5%AE%9A%E7%B1%BB%E5%90%8D
|
|
200
231
|
|
|
201
232
|
Args:
|
|
202
|
-
classes (_T_bind_classes_type):
|
|
233
|
+
classes (_T_bind_classes_type): dict of refs | ref to dict | str ref | list of refs
|
|
234
|
+
|
|
235
|
+
## usage
|
|
236
|
+
|
|
237
|
+
bind class names with dict,value is bool ref, for example:
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
bg_color = to_ref(True)
|
|
241
|
+
has_error = to_ref(False)
|
|
242
|
+
|
|
243
|
+
rxui.label('Hello').bind_classes({'bg-blue':bg_color, 'text-red':has_error})
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
bind list of class names with ref
|
|
247
|
+
|
|
248
|
+
```python
|
|
249
|
+
color = to_ref('red')
|
|
250
|
+
bg_color = lambda: f"bg-{color.value}"
|
|
251
|
+
|
|
252
|
+
rxui.label('Hello').bind_classes([bg_color])
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
bind single class name with ref
|
|
256
|
+
|
|
257
|
+
```python
|
|
258
|
+
color = to_ref('red')
|
|
259
|
+
bg_color = lambda: f"bg-{color.value}"
|
|
260
|
+
|
|
261
|
+
rxui.label('Hello').bind_classes(bg_color)
|
|
262
|
+
```
|
|
263
|
+
|
|
203
264
|
"""
|
|
204
265
|
if isinstance(classes, dict):
|
|
205
266
|
for name, ref_obj in classes.items():
|
|
@@ -213,24 +274,33 @@ class BindableUi(Generic[TWidget]):
|
|
|
213
274
|
|
|
214
275
|
elif is_ref(classes) or isinstance(classes, Callable):
|
|
215
276
|
ref_obj = to_value(classes) # type: ignore
|
|
216
|
-
assert isinstance(ref_obj, dict)
|
|
217
277
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
278
|
+
if isinstance(ref_obj, dict):
|
|
279
|
+
|
|
280
|
+
@self._ui_effect
|
|
281
|
+
def _():
|
|
282
|
+
for name, value in cast(Dict, to_value(classes)).items(): # type: ignore
|
|
283
|
+
if value:
|
|
284
|
+
self.classes(add=name)
|
|
285
|
+
else:
|
|
286
|
+
self.classes(remove=name)
|
|
287
|
+
else:
|
|
288
|
+
self._bind_single_class(cast(_T_bind_classes_type_single, classes))
|
|
289
|
+
|
|
225
290
|
elif isinstance(classes, list):
|
|
226
291
|
for ref_name in classes:
|
|
227
|
-
|
|
292
|
+
self._bind_single_class(ref_name)
|
|
228
293
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
294
|
+
return self
|
|
295
|
+
|
|
296
|
+
def _bind_single_class(self, class_name: _T_bind_classes_type_single):
|
|
297
|
+
if is_ref(class_name) or isinstance(class_name, Callable):
|
|
298
|
+
|
|
299
|
+
@on(class_name)
|
|
300
|
+
def _(state: WatchedState):
|
|
301
|
+
self.classes(add=state.current, remove=state.previous)
|
|
302
|
+
else:
|
|
303
|
+
self.classes(class_name) # type: ignore
|
|
234
304
|
|
|
235
305
|
return self
|
|
236
306
|
|
|
@@ -241,7 +311,21 @@ class BindableUi(Generic[TWidget]):
|
|
|
241
311
|
@中文文档 - https://gitee.com/carson_add/ex4nicegui/tree/main/#bind-style
|
|
242
312
|
|
|
243
313
|
Args:
|
|
244
|
-
style (Dict[str, Union[ReadonlyRef[str], Ref[str]]]):
|
|
314
|
+
style (Dict[str, Union[ReadonlyRef[str], Ref[str]]]): dict of style name and ref value
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
## usage
|
|
318
|
+
```python
|
|
319
|
+
bg_color = to_ref("blue")
|
|
320
|
+
text_color = to_ref("red")
|
|
321
|
+
|
|
322
|
+
rxui.label("test").bind_style(
|
|
323
|
+
{
|
|
324
|
+
"background-color": bg_color,
|
|
325
|
+
"color": text_color,
|
|
326
|
+
}
|
|
327
|
+
)
|
|
328
|
+
```
|
|
245
329
|
"""
|
|
246
330
|
if isinstance(style, dict):
|
|
247
331
|
for name, ref_obj in style.items():
|
|
@@ -254,26 +338,88 @@ class BindableUi(Generic[TWidget]):
|
|
|
254
338
|
|
|
255
339
|
return self
|
|
256
340
|
|
|
341
|
+
def scoped_style(self, selector: str, style: Union[str, Path]):
|
|
342
|
+
"""add scoped style to the element
|
|
343
|
+
|
|
344
|
+
@see - https://github.com/CrystalWindSnake/ex4nicegui/blob/main/README.en.md#scoped_style
|
|
345
|
+
@中文文档 - https://gitee.com/carson_add/ex4nicegui/tree/main/#scoped_style
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
selector (str): css selector
|
|
349
|
+
style (Union[str, Path]): path to css file or inline style string
|
|
350
|
+
|
|
351
|
+
## usage
|
|
352
|
+
```python
|
|
353
|
+
# all children of the element will have red outline, excluding itself
|
|
354
|
+
with rxui.row().scoped_style("*", "outline: 1px solid red;") as row:
|
|
355
|
+
ui.label("Hello")
|
|
356
|
+
ui.label("World")
|
|
357
|
+
|
|
358
|
+
# all children of the element will have red outline, including the element itself
|
|
359
|
+
with rxui.row().scoped_style(":self *", "outline: 1px solid red;") as row:
|
|
360
|
+
ui.label("Hello")
|
|
361
|
+
ui.label("World")
|
|
362
|
+
|
|
363
|
+
# all children of the element will have red outline when element is hovered
|
|
364
|
+
with rxui.row().scoped_style(":hover *", "outline: 1px solid red;") as row:
|
|
365
|
+
ui.label("Hello")
|
|
366
|
+
ui.label("World")
|
|
367
|
+
|
|
368
|
+
# all children of the element and itself will have red outline when element is hovered
|
|
369
|
+
with rxui.row().scoped_style(":self:hover *", "outline: 1px solid red;") as row:
|
|
370
|
+
ui.label("Hello")
|
|
371
|
+
ui.label("World")
|
|
372
|
+
```
|
|
373
|
+
"""
|
|
374
|
+
|
|
375
|
+
is_css_file = isinstance(style, Path)
|
|
376
|
+
|
|
377
|
+
if is_css_file:
|
|
378
|
+
style = style.read_text(encoding="utf-8")
|
|
379
|
+
|
|
380
|
+
id = f"c{self.element.id}"
|
|
381
|
+
selector_with_self = _utils._parent_id_with_selector(id, selector, is_css_file)
|
|
382
|
+
css = ""
|
|
383
|
+
if is_css_file:
|
|
384
|
+
css = f"{selector_with_self} {style}"
|
|
385
|
+
else:
|
|
386
|
+
css = f"{selector_with_self}{{{style}}}"
|
|
387
|
+
|
|
388
|
+
scope_style = ScopedStyle.get()
|
|
389
|
+
assert scope_style, "can not find scope style"
|
|
390
|
+
scope_style.create_style(self.element, css)
|
|
391
|
+
|
|
392
|
+
return self
|
|
393
|
+
|
|
257
394
|
def update(self):
|
|
258
395
|
"""Update the element on the client side."""
|
|
259
396
|
self.element.update()
|
|
260
397
|
|
|
261
398
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
399
|
+
class _utils:
|
|
400
|
+
@staticmethod
|
|
401
|
+
def _parent_id_with_selector(
|
|
402
|
+
parent_id: str, selector: str, is_css_file=False
|
|
403
|
+
) -> str:
|
|
404
|
+
selector_with_self = f"#{parent_id}"
|
|
405
|
+
|
|
406
|
+
selector = selector.strip()
|
|
407
|
+
if (not selector) and (not is_css_file):
|
|
408
|
+
selector = "* "
|
|
409
|
+
|
|
410
|
+
if selector.startswith(":self"):
|
|
411
|
+
selector = selector[5:].lstrip()
|
|
412
|
+
parent_selector = f"#{parent_id}"
|
|
413
|
+
if selector.startswith(":"):
|
|
414
|
+
parent_selector = f"{parent_selector}{selector.split()[0]}"
|
|
266
415
|
|
|
267
|
-
|
|
268
|
-
# def value(self) -> T:
|
|
269
|
-
# return self._ref.value # type: ignore
|
|
416
|
+
selector_with_self = f"{parent_selector},{selector_with_self}"
|
|
270
417
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
# def _():
|
|
274
|
-
# ref.value = self._ref.value # type: ignore
|
|
418
|
+
if not selector.startswith(":"):
|
|
419
|
+
selector_with_self = selector_with_self + " "
|
|
275
420
|
|
|
276
|
-
|
|
421
|
+
selector_with_self = selector_with_self + selector
|
|
422
|
+
return selector_with_self
|
|
277
423
|
|
|
278
424
|
|
|
279
425
|
_T_DisableableBinder = TypeVar("_T_DisableableBinder", bound=DisableableElement)
|
|
@@ -306,47 +452,3 @@ class DisableableMixin(Protocol):
|
|
|
306
452
|
|
|
307
453
|
|
|
308
454
|
DisableableBindableUi = DisableableMixin
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
_color_sys_type = Literal["QUASAR", "TAILWIND", "STYLE"]
|
|
312
|
-
_color_attr_name = "data-ex4ng-color"
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
def _bind_color(bindable_ui: BindableUi, ref_ui: TGetterOrReadonlyRef):
|
|
316
|
-
@effect
|
|
317
|
-
def _():
|
|
318
|
-
ele = cast(TextColorElement, bindable_ui.element)
|
|
319
|
-
color = to_value(ref_ui)
|
|
320
|
-
|
|
321
|
-
# get exists color
|
|
322
|
-
# e.g 'QUASAR:red'
|
|
323
|
-
pre_color = ele._props.get(_color_attr_name) # type: str | None
|
|
324
|
-
if pre_color:
|
|
325
|
-
color_sys, value = pre_color.split(":") # type: ignore
|
|
326
|
-
color_sys: _color_sys_type
|
|
327
|
-
|
|
328
|
-
if color_sys == "QUASAR":
|
|
329
|
-
del ele._props[ele.TEXT_COLOR_PROP]
|
|
330
|
-
elif color_sys == "TAILWIND":
|
|
331
|
-
ele.classes(remove=value)
|
|
332
|
-
else:
|
|
333
|
-
del ele._style["color"]
|
|
334
|
-
|
|
335
|
-
cur_sys: _color_sys_type = "STYLE"
|
|
336
|
-
cur_color = color
|
|
337
|
-
|
|
338
|
-
if color in QUASAR_COLORS:
|
|
339
|
-
ele._props[ele.TEXT_COLOR_PROP] = color
|
|
340
|
-
cur_sys = "QUASAR"
|
|
341
|
-
elif color in TAILWIND_COLORS:
|
|
342
|
-
cur_color = f"text-{color}"
|
|
343
|
-
ele.classes(replace=cur_color)
|
|
344
|
-
cur_sys = "TAILWIND"
|
|
345
|
-
elif color is not None:
|
|
346
|
-
ele._style["color"] = color
|
|
347
|
-
|
|
348
|
-
ele._props[_color_attr_name] = f"{cur_sys}:{color}"
|
|
349
|
-
|
|
350
|
-
ele.update()
|
|
351
|
-
|
|
352
|
-
return bindable_ui
|
|
@@ -3,7 +3,7 @@ from typing import (
|
|
|
3
3
|
Callable,
|
|
4
4
|
Optional,
|
|
5
5
|
)
|
|
6
|
-
from ex4nicegui.reactive.
|
|
6
|
+
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
7
7
|
from ex4nicegui.utils.signals import (
|
|
8
8
|
TGetterOrReadonlyRef,
|
|
9
9
|
_TMaybeRef as TMaybeRef,
|
|
@@ -4,8 +4,7 @@ from typing import (
|
|
|
4
4
|
Optional,
|
|
5
5
|
TypeVar,
|
|
6
6
|
)
|
|
7
|
-
from ex4nicegui.reactive.
|
|
8
|
-
from ex4nicegui.utils.apiEffect import ui_effect
|
|
7
|
+
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
9
8
|
from ex4nicegui.utils.signals import (
|
|
10
9
|
TGetterOrReadonlyRef,
|
|
11
10
|
_TMaybeRef as TMaybeRef,
|
|
@@ -51,7 +50,7 @@ class CheckboxBindableUi(BindableUi[ui.checkbox], DisableableMixin):
|
|
|
51
50
|
return super().bind_prop(prop, ref_ui)
|
|
52
51
|
|
|
53
52
|
def bind_value(self, ref_ui: TGetterOrReadonlyRef[bool]):
|
|
54
|
-
@
|
|
53
|
+
@self._ui_effect
|
|
55
54
|
def _():
|
|
56
55
|
self.element.set_value(to_value(ref_ui))
|
|
57
56
|
self.element.update()
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
from typing import (
|
|
2
2
|
Optional,
|
|
3
3
|
)
|
|
4
|
-
from ex4nicegui.reactive.
|
|
5
|
-
from ex4nicegui.utils.apiEffect import ui_effect
|
|
4
|
+
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
6
5
|
|
|
7
6
|
from ex4nicegui.utils.signals import (
|
|
8
7
|
TGetterOrReadonlyRef,
|
|
@@ -57,7 +56,7 @@ class CircularProgressBindableUi(
|
|
|
57
56
|
return super().bind_prop(prop, ref_ui)
|
|
58
57
|
|
|
59
58
|
def bind_value(self, ref_ui: TGetterOrReadonlyRef[float]):
|
|
60
|
-
@
|
|
59
|
+
@self._ui_effect
|
|
61
60
|
def _():
|
|
62
61
|
self.element.set_value(to_value(ref_ui))
|
|
63
62
|
|
|
@@ -4,8 +4,7 @@ from typing import (
|
|
|
4
4
|
Optional,
|
|
5
5
|
cast,
|
|
6
6
|
)
|
|
7
|
-
from ex4nicegui.reactive.
|
|
8
|
-
from ex4nicegui.utils.apiEffect import ui_effect
|
|
7
|
+
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
9
8
|
|
|
10
9
|
from ex4nicegui.utils.signals import (
|
|
11
10
|
TGetterOrReadonlyRef,
|
|
@@ -76,14 +75,14 @@ class ColorPickerBindableUi(BindableUi[ui.color_picker]):
|
|
|
76
75
|
return super().bind_prop(prop, ref_ui)
|
|
77
76
|
|
|
78
77
|
def bind_color(self, ref_ui: TGetterOrReadonlyRef[str]):
|
|
79
|
-
@
|
|
78
|
+
@self._ui_effect
|
|
80
79
|
def _():
|
|
81
80
|
self.element.set_color(to_value(ref_ui))
|
|
82
81
|
|
|
83
82
|
return self
|
|
84
83
|
|
|
85
84
|
def bind_value(self, ref_ui: TGetterOrReadonlyRef[bool]):
|
|
86
|
-
@
|
|
85
|
+
@self._ui_effect
|
|
87
86
|
def _():
|
|
88
87
|
self.element.set_value(to_value(ref_ui))
|
|
89
88
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from typing import Any, Callable, List, Optional, TypeVar
|
|
2
2
|
from typing_extensions import TypedDict
|
|
3
|
-
from ex4nicegui.reactive.
|
|
4
|
-
from ex4nicegui.utils.apiEffect import ui_effect
|
|
3
|
+
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
5
4
|
|
|
6
5
|
from ex4nicegui.utils.signals import (
|
|
7
6
|
TGetterOrReadonlyRef,
|
|
@@ -70,7 +69,7 @@ class DateBindableUi(BindableUi[ui.date]):
|
|
|
70
69
|
return super().bind_prop(prop, ref_ui)
|
|
71
70
|
|
|
72
71
|
def bind_value(self, ref_ui: TGetterOrReadonlyRef[bool]):
|
|
73
|
-
@
|
|
72
|
+
@self._ui_effect
|
|
74
73
|
def _():
|
|
75
74
|
self.element.set_value(to_value(ref_ui))
|
|
76
75
|
|
|
@@ -2,8 +2,7 @@ from typing import (
|
|
|
2
2
|
Any,
|
|
3
3
|
)
|
|
4
4
|
from typing_extensions import Literal
|
|
5
|
-
from ex4nicegui.reactive.
|
|
6
|
-
from ex4nicegui.utils.apiEffect import ui_effect
|
|
5
|
+
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
7
6
|
|
|
8
7
|
from ex4nicegui.utils.signals import (
|
|
9
8
|
is_setter_ref,
|
|
@@ -61,7 +60,7 @@ class DrawerBindableUi(BindableUi[Drawer]):
|
|
|
61
60
|
|
|
62
61
|
super().__init__(element) # type: ignore
|
|
63
62
|
|
|
64
|
-
@
|
|
63
|
+
@self._ui_effect
|
|
65
64
|
def _():
|
|
66
65
|
mvalue = "true" if to_value(value) else "false"
|
|
67
66
|
element.props(f":model-value={mvalue}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
from typing import Any, Callable, Dict, List, Union, cast, Optional, Literal
|
|
3
|
-
from ex4nicegui.reactive.
|
|
3
|
+
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
4
4
|
from ex4nicegui.utils.signals import (
|
|
5
5
|
TGetterOrReadonlyRef,
|
|
6
6
|
is_ref,
|
|
@@ -8,7 +8,6 @@ from ex4nicegui.utils.signals import (
|
|
|
8
8
|
_TMaybeRef as TMaybeRef,
|
|
9
9
|
to_value,
|
|
10
10
|
to_raw,
|
|
11
|
-
on,
|
|
12
11
|
)
|
|
13
12
|
from .base import BindableUi
|
|
14
13
|
from ex4nicegui.reactive.EChartsComponent.ECharts import echarts
|
|
@@ -141,7 +140,7 @@ class EChartsBindableUi(BindableUi[echarts]):
|
|
|
141
140
|
return super().bind_prop(prop, ref_ui)
|
|
142
141
|
|
|
143
142
|
def bind_options(self, ref_ui: TGetterOrReadonlyRef[Dict]):
|
|
144
|
-
@
|
|
143
|
+
@self._ui_signal_on(ref_ui)
|
|
145
144
|
def _():
|
|
146
145
|
ele = self.element
|
|
147
146
|
ele.update_options(to_raw(to_value(ref_ui)), self.__update_setting)
|