ex4nicegui 0.8.4__py3-none-any.whl → 0.8.6__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/reactive/EChartsComponent/events.py +11 -10
- ex4nicegui/reactive/EChartsComponent/utils.py +1 -14
- ex4nicegui/reactive/__init__.py +6 -1
- ex4nicegui/reactive/officials/grid.py +43 -3
- ex4nicegui/reactive/officials/input.py +23 -0
- ex4nicegui/reactive/officials/radio.py +13 -2
- ex4nicegui/reactive/officials/range.py +42 -0
- ex4nicegui/reactive/officials/select.py +1 -3
- ex4nicegui/reactive/officials/spinner.py +43 -0
- ex4nicegui/reactive/officials/toggle.py +5 -3
- ex4nicegui/reactive/officials/tree.py +86 -0
- ex4nicegui/reactive/systems/reactive_system.py +13 -2
- ex4nicegui/toolbox/__init__.py +5 -0
- ex4nicegui/toolbox/core/VueUse.js +2031 -0
- ex4nicegui/toolbox/core/vue_use.py +32 -0
- ex4nicegui/toolbox/functions/breakpoint.py +114 -0
- ex4nicegui/toolbox/functions/dark.py +97 -0
- ex4nicegui/toolbox/functions/qr_code.py +83 -0
- ex4nicegui/utils/asyncComputed.py +3 -0
- ex4nicegui/utils/proxy/dict.py +0 -1
- {ex4nicegui-0.8.4.dist-info → ex4nicegui-0.8.6.dist-info}/METADATA +89 -2
- {ex4nicegui-0.8.4.dist-info → ex4nicegui-0.8.6.dist-info}/RECORD +24 -16
- {ex4nicegui-0.8.4.dist-info → ex4nicegui-0.8.6.dist-info}/LICENSE +0 -0
- {ex4nicegui-0.8.4.dist-info → ex4nicegui-0.8.6.dist-info}/WHEEL +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from typing import (
|
|
2
2
|
Any,
|
|
3
|
+
Dict,
|
|
3
4
|
Optional,
|
|
4
5
|
)
|
|
5
6
|
from dataclasses import dataclass, fields
|
|
@@ -11,16 +12,16 @@ from nicegui.events import (
|
|
|
11
12
|
|
|
12
13
|
@dataclass(**KWONLY_SLOTS)
|
|
13
14
|
class EChartsMouseEventArguments(UiEventArguments):
|
|
14
|
-
componentType: str
|
|
15
|
-
seriesType: str
|
|
16
|
-
seriesIndex: int
|
|
17
|
-
seriesName: str
|
|
18
|
-
name: str
|
|
19
|
-
dataIndex: int
|
|
20
|
-
data:
|
|
21
|
-
dataType: Optional[str]
|
|
22
|
-
value: Any
|
|
23
|
-
color: str
|
|
15
|
+
componentType: Optional[str] = None
|
|
16
|
+
seriesType: Optional[str] = None
|
|
17
|
+
seriesIndex: Optional[int] = None
|
|
18
|
+
seriesName: Optional[str] = None
|
|
19
|
+
name: Optional[str] = None
|
|
20
|
+
dataIndex: Optional[int] = None
|
|
21
|
+
data: Optional[Dict] = None
|
|
22
|
+
dataType: Optional[str] = None
|
|
23
|
+
value: Optional[Any] = None
|
|
24
|
+
color: Optional[str] = None
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
_Mouse_Event_Arguments_Fields = [f.name for f in fields(EChartsMouseEventArguments)]
|
|
@@ -26,19 +26,6 @@ def create_event_handler_args(
|
|
|
26
26
|
event_name: _T_event_name, e: GenericEventArguments
|
|
27
27
|
) -> UiEventArguments:
|
|
28
28
|
if is_mouse_event(event_name):
|
|
29
|
-
return EChartsMouseEventArguments(
|
|
30
|
-
sender=e.sender,
|
|
31
|
-
client=e.client,
|
|
32
|
-
componentType=e.args["componentType"],
|
|
33
|
-
seriesType=e.args["seriesType"],
|
|
34
|
-
seriesIndex=e.args["seriesIndex"],
|
|
35
|
-
seriesName=e.args["seriesName"],
|
|
36
|
-
name=e.args["name"],
|
|
37
|
-
dataIndex=e.args["dataIndex"],
|
|
38
|
-
data=e.args["data"],
|
|
39
|
-
dataType=e.args.get("dataType"),
|
|
40
|
-
value=e.args["value"],
|
|
41
|
-
color=e.args["color"],
|
|
42
|
-
)
|
|
29
|
+
return EChartsMouseEventArguments(sender=e.sender, client=e.client, **e.args)
|
|
43
30
|
|
|
44
31
|
return GenericEventArguments(sender=e.sender, client=e.client, args=e.args)
|
ex4nicegui/reactive/__init__.py
CHANGED
|
@@ -59,7 +59,9 @@ from .officials.toggle import ToggleBindableUi as toggle
|
|
|
59
59
|
from .officials.avatar import AvatarBindableUi as avatar
|
|
60
60
|
from .officials.badge import BadgeBindableUi as badge
|
|
61
61
|
from .officials.range import RangeBindableUi as range
|
|
62
|
-
|
|
62
|
+
from .officials.range import LazyRangeBindableUi as lazy_range
|
|
63
|
+
from .officials.tree import TreeBindableUi as tree
|
|
64
|
+
from .officials.spinner import SpinnerBindableUi as spinner
|
|
63
65
|
|
|
64
66
|
from .local_file_picker import local_file_picker
|
|
65
67
|
from .UseDraggable.UseDraggable import use_draggable
|
|
@@ -142,4 +144,7 @@ __all__ = [
|
|
|
142
144
|
"avatar",
|
|
143
145
|
"badge",
|
|
144
146
|
"range",
|
|
147
|
+
"lazy_range",
|
|
148
|
+
"tree",
|
|
149
|
+
"spinner",
|
|
145
150
|
]
|
|
@@ -8,14 +8,21 @@ from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
|
8
8
|
|
|
9
9
|
from nicegui import ui
|
|
10
10
|
from .base import BindableUi
|
|
11
|
-
from ex4nicegui.utils.signals import
|
|
11
|
+
from ex4nicegui.utils.signals import (
|
|
12
|
+
_TMaybeRef as TMaybeRef,
|
|
13
|
+
TGetterOrReadonlyRef,
|
|
14
|
+
to_value,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
_T_Template = Union[TMaybeRef[str], TMaybeRef[int]]
|
|
12
19
|
|
|
13
20
|
|
|
14
21
|
class GridBindableUi(BindableUi[ui.grid]):
|
|
15
22
|
def __init__(
|
|
16
23
|
self,
|
|
17
|
-
rows: Optional[
|
|
18
|
-
columns: Optional[
|
|
24
|
+
rows: Optional[_T_Template] = None,
|
|
25
|
+
columns: Optional[_T_Template] = None,
|
|
19
26
|
) -> None:
|
|
20
27
|
pc = ParameterClassifier(locals(), maybeRefs=["rows", "columns"], events=[])
|
|
21
28
|
|
|
@@ -25,6 +32,39 @@ class GridBindableUi(BindableUi[ui.grid]):
|
|
|
25
32
|
for key, value in pc.get_bindings().items():
|
|
26
33
|
self.bind_prop(key, value) # type: ignore
|
|
27
34
|
|
|
35
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
36
|
+
if prop == "rows":
|
|
37
|
+
return self.bind_rows(value)
|
|
38
|
+
|
|
39
|
+
if prop == "columns":
|
|
40
|
+
return self.bind_columns(value)
|
|
41
|
+
|
|
42
|
+
return super().bind_prop(prop, value)
|
|
43
|
+
|
|
44
|
+
def bind_rows(self, rows: TGetterOrReadonlyRef[Union[int, str]]):
|
|
45
|
+
def template():
|
|
46
|
+
_rows = to_value(rows)
|
|
47
|
+
return (
|
|
48
|
+
f"repeat({_rows}, minmax(0, 1fr))" if isinstance(_rows, int) else _rows
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
self.bind_style({"grid-template-rows": template})
|
|
52
|
+
|
|
53
|
+
return self
|
|
54
|
+
|
|
55
|
+
def bind_columns(self, columns: TGetterOrReadonlyRef[Union[int, str]]):
|
|
56
|
+
def template():
|
|
57
|
+
_columns = to_value(columns)
|
|
58
|
+
return (
|
|
59
|
+
f"repeat({_columns}, minmax(0, 1fr))"
|
|
60
|
+
if isinstance(_columns, int)
|
|
61
|
+
else _columns
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
self.bind_style({"grid-template-columns": template})
|
|
65
|
+
|
|
66
|
+
return self
|
|
67
|
+
|
|
28
68
|
def __enter__(self):
|
|
29
69
|
self.element.__enter__()
|
|
30
70
|
return self
|
|
@@ -64,9 +64,32 @@ class InputBindableUi(
|
|
|
64
64
|
if prop == "password":
|
|
65
65
|
return self.bind_password(value)
|
|
66
66
|
|
|
67
|
+
if prop == "autocomplete":
|
|
68
|
+
return self.bind_autocomplete(value)
|
|
69
|
+
|
|
67
70
|
return super().bind_prop(prop, value)
|
|
68
71
|
|
|
72
|
+
def bind_autocomplete(self, autocomplete: TGetterOrReadonlyRef[List[str]]):
|
|
73
|
+
"""Binds the autocomplete attribute of the input element.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
autocomplete (TGetterOrReadonlyRef[List[str]]): The getter or readonly reference to the autocomplete list.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
@self._ui_signal_on(autocomplete)
|
|
80
|
+
def _():
|
|
81
|
+
self.element.set_autocomplete(to_value(autocomplete))
|
|
82
|
+
|
|
83
|
+
return self
|
|
84
|
+
|
|
69
85
|
def bind_password(self, password: TGetterOrReadonlyRef[bool]):
|
|
86
|
+
"""Binds the password attribute of the input element.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
password (TGetterOrReadonlyRef[bool]): The getter or readonly reference to the password state.
|
|
90
|
+
|
|
91
|
+
"""
|
|
92
|
+
|
|
70
93
|
@self._ui_signal_on(password)
|
|
71
94
|
def _():
|
|
72
95
|
self.element._props["type"] = "password" if to_value(password) else "text"
|
|
@@ -8,6 +8,9 @@ from typing import (
|
|
|
8
8
|
Union,
|
|
9
9
|
)
|
|
10
10
|
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
11
|
+
from ex4nicegui.reactive.systems.reactive_system import (
|
|
12
|
+
convert_to_none_if_outside_options,
|
|
13
|
+
)
|
|
11
14
|
from ex4nicegui.utils.signals import (
|
|
12
15
|
TGetterOrReadonlyRef,
|
|
13
16
|
_TMaybeRef as TMaybeRef,
|
|
@@ -51,8 +54,8 @@ class RadioBindableUi(BindableUi[ui.radio], ValueElementMixin[Any]):
|
|
|
51
54
|
return self.element.value
|
|
52
55
|
|
|
53
56
|
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
54
|
-
if
|
|
55
|
-
return self
|
|
57
|
+
if prop == "value":
|
|
58
|
+
return self.bind_value(value)
|
|
56
59
|
|
|
57
60
|
if prop == "options":
|
|
58
61
|
return self.bind_options(value)
|
|
@@ -66,3 +69,11 @@ class RadioBindableUi(BindableUi[ui.radio], ValueElementMixin[Any]):
|
|
|
66
69
|
self.element.set_options(to_value(options))
|
|
67
70
|
|
|
68
71
|
return self
|
|
72
|
+
|
|
73
|
+
def bind_value(self, value: TGetterOrReadonlyRef):
|
|
74
|
+
@self._ui_signal_on(value, deep=True)
|
|
75
|
+
def _():
|
|
76
|
+
new_value = convert_to_none_if_outside_options(value, self.element.options)
|
|
77
|
+
self.element.set_value(new_value)
|
|
78
|
+
|
|
79
|
+
return self
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
from typing import Any, Callable, Optional, Dict, cast
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
from ex4nicegui.utils.signals import to_value, is_setter_ref
|
|
4
5
|
from ex4nicegui.utils.signals import (
|
|
5
6
|
_TMaybeRef as TMaybeRef,
|
|
6
7
|
)
|
|
7
8
|
|
|
8
9
|
from nicegui import ui
|
|
10
|
+
from nicegui.events import handle_event
|
|
9
11
|
from ex4nicegui.reactive.base import BindableUi, DisableableMixin
|
|
10
12
|
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
11
13
|
from ex4nicegui.reactive.mixins.value_element import ValueElementMixin
|
|
@@ -43,3 +45,43 @@ class RangeBindableUi(
|
|
|
43
45
|
@property
|
|
44
46
|
def value(self):
|
|
45
47
|
return cast(Dict[str, int], self.element.value)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class LazyRangeBindableUi(
|
|
51
|
+
RangeBindableUi,
|
|
52
|
+
):
|
|
53
|
+
def __init__(
|
|
54
|
+
self,
|
|
55
|
+
*,
|
|
56
|
+
min: TMaybeRef[float], # pylint: disable=redefined-builtin
|
|
57
|
+
max: TMaybeRef[float], # pylint: disable=redefined-builtin
|
|
58
|
+
step: TMaybeRef[float] = 1.0,
|
|
59
|
+
value: Optional[TMaybeRef[Dict[str, int]]] = None,
|
|
60
|
+
on_change: Optional[Callable[..., Any]] = None,
|
|
61
|
+
on_update: Optional[Callable[..., Any]] = None,
|
|
62
|
+
) -> None:
|
|
63
|
+
"""A lazy version of `rxui.range` that only updates the value when the user releases the range.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
min (TMaybeRef[float]): lower bound of the range
|
|
67
|
+
max (TMaybeRef[float]): upper bound of the range
|
|
68
|
+
step (TMaybeRef[float], optional): step size. Defaults to 1.0.
|
|
69
|
+
value (Optional[TMaybeRef[Dict[str, int]]], optional): initial value to set min and max position of the range. Defaults to None.
|
|
70
|
+
on_change (Optional[Callable[..., Any]], optional): callback which is invoked when the user releases the range. Defaults to None.
|
|
71
|
+
on_update (Optional[Callable[..., Any]], optional): callback which is invoked when the component needs to change. Defaults to None.
|
|
72
|
+
"""
|
|
73
|
+
super().__init__(
|
|
74
|
+
min=min,
|
|
75
|
+
max=max,
|
|
76
|
+
step=step,
|
|
77
|
+
value=lambda: to_value(value), # type: ignore
|
|
78
|
+
on_change=on_update,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
if is_setter_ref(value):
|
|
82
|
+
|
|
83
|
+
def new_on_change(e):
|
|
84
|
+
value.set_value(e.args) # type: ignore
|
|
85
|
+
handle_event(on_change, e)
|
|
86
|
+
|
|
87
|
+
self.on("change", new_on_change)
|
|
@@ -4,7 +4,6 @@ from typing import (
|
|
|
4
4
|
List,
|
|
5
5
|
Optional,
|
|
6
6
|
TypeVar,
|
|
7
|
-
cast,
|
|
8
7
|
Dict,
|
|
9
8
|
Union,
|
|
10
9
|
)
|
|
@@ -16,7 +15,6 @@ from ex4nicegui.utils.signals import (
|
|
|
16
15
|
to_raw,
|
|
17
16
|
)
|
|
18
17
|
from nicegui import ui
|
|
19
|
-
from nicegui.elements.mixins.value_element import ValueElement
|
|
20
18
|
from .base import BindableUi
|
|
21
19
|
|
|
22
20
|
T = TypeVar("T")
|
|
@@ -94,6 +92,6 @@ class SelectBindableUi(BindableUi[ui.select]):
|
|
|
94
92
|
@self._ui_signal_on(value, deep=True)
|
|
95
93
|
def _():
|
|
96
94
|
ParameterClassifier.mark_event_source_as_internal(self.element)
|
|
97
|
-
|
|
95
|
+
self.element.set_value(to_raw(to_value(value)) or None)
|
|
98
96
|
|
|
99
97
|
return self
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
from ex4nicegui.utils.signals import (
|
|
5
|
+
TGetterOrReadonlyRef,
|
|
6
|
+
_TMaybeRef as TMaybeRef,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
from nicegui import ui
|
|
10
|
+
from ex4nicegui.reactive.base import BindableUi
|
|
11
|
+
from ex4nicegui.reactive.mixins.textColor import TextColorableMixin
|
|
12
|
+
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
13
|
+
|
|
14
|
+
from nicegui.elements.spinner import SpinnerTypes
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SpinnerBindableUi(BindableUi[ui.spinner], TextColorableMixin):
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
type: Optional[SpinnerTypes] = "default",
|
|
21
|
+
*,
|
|
22
|
+
size: TMaybeRef[str] = "1em",
|
|
23
|
+
color: Optional[TMaybeRef[str]] = "primary",
|
|
24
|
+
thickness: TMaybeRef[float] = 5.0,
|
|
25
|
+
) -> None:
|
|
26
|
+
pc = ParameterClassifier(
|
|
27
|
+
locals(), maybeRefs=["type", "size", "color", "thickness"]
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
value_kws = pc.get_values_kws()
|
|
31
|
+
element = ui.spinner(**value_kws)
|
|
32
|
+
super().__init__(element) # type: ignore
|
|
33
|
+
|
|
34
|
+
for key, value in pc.get_bindings().items():
|
|
35
|
+
self.bind_prop(key, value) # type: ignore
|
|
36
|
+
|
|
37
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
38
|
+
if prop == "type":
|
|
39
|
+
raise ValueError("type cannot be bound")
|
|
40
|
+
elif prop == "color":
|
|
41
|
+
return self.bind_color(value)
|
|
42
|
+
|
|
43
|
+
return super().bind_prop(prop, value)
|
|
@@ -8,11 +8,13 @@ from typing import (
|
|
|
8
8
|
Union,
|
|
9
9
|
)
|
|
10
10
|
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
11
|
+
from ex4nicegui.reactive.systems.reactive_system import (
|
|
12
|
+
convert_to_none_if_outside_options,
|
|
13
|
+
)
|
|
11
14
|
from ex4nicegui.utils.signals import (
|
|
12
15
|
TGetterOrReadonlyRef,
|
|
13
16
|
_TMaybeRef as TMaybeRef,
|
|
14
17
|
to_value,
|
|
15
|
-
to_raw,
|
|
16
18
|
)
|
|
17
19
|
from nicegui import ui
|
|
18
20
|
from .base import BindableUi
|
|
@@ -83,7 +85,7 @@ class ToggleBindableUi(BindableUi[ui.toggle]):
|
|
|
83
85
|
def bind_value(self, value: TGetterOrReadonlyRef):
|
|
84
86
|
@self._ui_signal_on(value, deep=True)
|
|
85
87
|
def _():
|
|
86
|
-
|
|
87
|
-
self.element.set_value(
|
|
88
|
+
new_value = convert_to_none_if_outside_options(value, self.element.options)
|
|
89
|
+
self.element.set_value(new_value)
|
|
88
90
|
|
|
89
91
|
return self
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from typing import List, Literal, Optional, Dict
|
|
2
|
+
|
|
3
|
+
from ex4nicegui.utils.signals import (
|
|
4
|
+
_TMaybeRef as TMaybeRef,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
from nicegui import ui
|
|
8
|
+
from nicegui.events import Handler, ValueChangeEventArguments
|
|
9
|
+
from .base import BindableUi
|
|
10
|
+
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TreeBindableUi(
|
|
14
|
+
BindableUi[ui.tree],
|
|
15
|
+
):
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
nodes: TMaybeRef[List[Dict]],
|
|
19
|
+
*,
|
|
20
|
+
selected: Optional[TMaybeRef[str]] = None,
|
|
21
|
+
node_key: str = "id",
|
|
22
|
+
label_key: str = "label",
|
|
23
|
+
children_key: str = "children",
|
|
24
|
+
on_select: Optional[Handler[ValueChangeEventArguments]] = None,
|
|
25
|
+
on_expand: Optional[Handler[ValueChangeEventArguments]] = None,
|
|
26
|
+
on_tick: Optional[Handler[ValueChangeEventArguments]] = None,
|
|
27
|
+
tick_strategy: Optional[
|
|
28
|
+
TMaybeRef[Literal["leaf", "leaf-filtered", "strict"]]
|
|
29
|
+
] = None,
|
|
30
|
+
) -> None:
|
|
31
|
+
"""Tree
|
|
32
|
+
|
|
33
|
+
Display hierarchical data using Quasar's `QTree <https://quasar.dev/vue-components/tree>`_ component.
|
|
34
|
+
|
|
35
|
+
If using IDs, make sure they are unique within the whole tree.
|
|
36
|
+
|
|
37
|
+
To use checkboxes and ``on_tick``, set the ``tick_strategy`` parameter to "leaf", "leaf-filtered" or "strict".
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
nodes (TMaybeRef[List[Dict]]): hierarchical list of node objects
|
|
42
|
+
selected (Optional[TMaybeRef[str]], optional): Key of node currently selected. Defaults to None.
|
|
43
|
+
node_key (str, optional): property name of each node object that holds its unique id. Defaults to "id".
|
|
44
|
+
label_key (str, optional): property name of each node object that holds its label. Defaults to "label".
|
|
45
|
+
children_key (str, optional): property name of each node object that holds its list of children. Defaults to "children".
|
|
46
|
+
on_select (Optional[Handler[ValueChangeEventArguments]], optional): callback which is invoked when the node selection changes. Defaults to None.
|
|
47
|
+
on_expand (Optional[Handler[ValueChangeEventArguments]], optional): callback which is invoked when the node expansion changes. Defaults to None.
|
|
48
|
+
on_tick (Optional[Handler[ValueChangeEventArguments]], optional): callback which is invoked when a node is ticked or unticked. Defaults to None.
|
|
49
|
+
tick_strategy (Optional[ TMaybeRef[Literal["leaf", "leaf, optional): whether and how to use checkboxes. Defaults to None.
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
Example:
|
|
53
|
+
.. code-block:: python
|
|
54
|
+
from ex4nicegui import to_ref, rxui
|
|
55
|
+
|
|
56
|
+
selected = to_ref("")
|
|
57
|
+
nodes = to_ref(
|
|
58
|
+
[
|
|
59
|
+
{"id": "numbers", "children": [{"id": "1"}, {"id": "2"}]},
|
|
60
|
+
{"id": "letters", "children": [{"id": "A"}, {"id": "B"}]},
|
|
61
|
+
]
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
rxui.label(lambda: f"Selected node: {selected.value}")
|
|
65
|
+
rxui.tree(nodes, selected=selected, label_key="id")
|
|
66
|
+
"""
|
|
67
|
+
pc = ParameterClassifier(
|
|
68
|
+
locals(),
|
|
69
|
+
maybeRefs=[
|
|
70
|
+
"nodes",
|
|
71
|
+
"node_key",
|
|
72
|
+
"label_key",
|
|
73
|
+
"children_key",
|
|
74
|
+
"tick_strategy",
|
|
75
|
+
],
|
|
76
|
+
v_model=("selected", "on_select"),
|
|
77
|
+
events=["on_select", "on_expand", "on_tick"],
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
value_kws = pc.get_values_kws()
|
|
81
|
+
value_kws.pop("selected")
|
|
82
|
+
element = ui.tree(**value_kws)
|
|
83
|
+
super().__init__(element) # type: ignore
|
|
84
|
+
|
|
85
|
+
for key, value in pc.get_bindings().items():
|
|
86
|
+
self.bind_prop(key, value) # type: ignore
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from typing import Callable, Dict
|
|
2
|
-
from ex4nicegui.utils.signals import to_value, to_raw
|
|
1
|
+
from typing import Callable, Dict, List, Union
|
|
2
|
+
from ex4nicegui.utils.signals import to_value, to_raw, TGetterOrReadonlyRef
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
def convert_kws_ref2value(kws: Dict) -> Dict:
|
|
@@ -19,3 +19,14 @@ def inject_method(obj, method_name: str, new_handle: Callable):
|
|
|
19
19
|
raise AttributeError(
|
|
20
20
|
f"'{type(obj).__name__}' object has no attribute '{method_name}'."
|
|
21
21
|
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def convert_to_none_if_outside_options(
|
|
25
|
+
value: TGetterOrReadonlyRef, options: Union[List, Dict]
|
|
26
|
+
):
|
|
27
|
+
new_value = to_raw(to_value(value))
|
|
28
|
+
|
|
29
|
+
if new_value not in options:
|
|
30
|
+
new_value = None
|
|
31
|
+
|
|
32
|
+
return new_value
|