ex4nicegui 0.2.3__py3-none-any.whl → 0.2.5__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 +1 -1
- ex4nicegui/reactive/__index.py +1 -31
- ex4nicegui/reactive/officials/__init__.py +37 -0
- ex4nicegui/reactive/officials/aggrid.py +81 -0
- ex4nicegui/reactive/officials/base.py +167 -0
- ex4nicegui/reactive/officials/button.py +86 -0
- ex4nicegui/reactive/officials/card.py +59 -0
- ex4nicegui/reactive/officials/checkbox.py +68 -0
- ex4nicegui/reactive/officials/color_picker.py +101 -0
- ex4nicegui/reactive/officials/date.py +85 -0
- ex4nicegui/reactive/officials/drawer.py +88 -0
- ex4nicegui/reactive/officials/echarts.py +70 -0
- ex4nicegui/reactive/officials/html.py +66 -0
- ex4nicegui/reactive/officials/icon.py +62 -0
- ex4nicegui/reactive/officials/image.py +54 -0
- ex4nicegui/reactive/officials/input.py +116 -0
- ex4nicegui/reactive/officials/label.py +67 -0
- ex4nicegui/reactive/officials/radio.py +80 -0
- ex4nicegui/reactive/officials/row.py +21 -0
- ex4nicegui/reactive/officials/select.py +93 -0
- ex4nicegui/reactive/officials/slider.py +97 -0
- ex4nicegui/reactive/officials/switch.py +72 -0
- ex4nicegui/reactive/officials/table.py +144 -0
- ex4nicegui/reactive/officials/textarea.py +103 -0
- ex4nicegui/reactive/officials/upload.py +78 -0
- ex4nicegui/reactive/officials/utils.py +11 -0
- {ex4nicegui-0.2.3.dist-info → ex4nicegui-0.2.5.dist-info}/METADATA +1 -1
- ex4nicegui-0.2.5.dist-info/RECORD +56 -0
- ex4nicegui/reactive/officials.py +0 -1585
- ex4nicegui-0.2.3.dist-info/RECORD +0 -33
- {ex4nicegui-0.2.3.data → ex4nicegui-0.2.5.data}/data/ECharts/ECharts.js +0 -0
- {ex4nicegui-0.2.3.data → ex4nicegui-0.2.5.data}/data/UseDraggable/UseDraggable.js +0 -0
- {ex4nicegui-0.2.3.data → ex4nicegui-0.2.5.data}/data/useMouse/UseMouse.js +0 -0
- {ex4nicegui-0.2.3.dist-info → ex4nicegui-0.2.5.dist-info}/LICENSE +0 -0
- {ex4nicegui-0.2.3.dist-info → ex4nicegui-0.2.5.dist-info}/WHEEL +0 -0
- {ex4nicegui-0.2.3.dist-info → ex4nicegui-0.2.5.dist-info}/top_level.txt +0 -0
ex4nicegui/__init__.py
CHANGED
ex4nicegui/reactive/__index.py
CHANGED
|
@@ -1,33 +1,4 @@
|
|
|
1
|
-
from .officials import
|
|
2
|
-
TableBindableUi as table,
|
|
3
|
-
AggridBindableUi as aggrid,
|
|
4
|
-
RadioBindableUi as radio,
|
|
5
|
-
SelectBindableUi as select,
|
|
6
|
-
SwitchBindableUi as switch,
|
|
7
|
-
InputBindableUi as input,
|
|
8
|
-
LazyInputBindableUi as lazy_input,
|
|
9
|
-
TextareaBindableUi as textarea,
|
|
10
|
-
LazyTextareaBindableUi as lazy_textarea,
|
|
11
|
-
CheckboxBindableUi as checkbox,
|
|
12
|
-
LabelBindableUi as label,
|
|
13
|
-
IconBindableUi as icon,
|
|
14
|
-
ButtonBindableUi as button,
|
|
15
|
-
ColorPickerBindableUi as color_picker,
|
|
16
|
-
ColorPickerLazyBindableUi as lazy_color_picker,
|
|
17
|
-
EChartsBindableUi as echarts,
|
|
18
|
-
RowBindableUi as row,
|
|
19
|
-
CardBindableUi as card,
|
|
20
|
-
CardSectionBindableUi as card_section,
|
|
21
|
-
CardActionsBindableUi as card_actions,
|
|
22
|
-
SliderBindableUi as slider,
|
|
23
|
-
LazySliderBindableUi as lazy_slider,
|
|
24
|
-
HtmlBindableUi as html,
|
|
25
|
-
ImageBindableUi as image,
|
|
26
|
-
UploadBindableUi as upload,
|
|
27
|
-
UploadResult,
|
|
28
|
-
DrawerBindableUi as drawer,
|
|
29
|
-
DateBindableUi as date,
|
|
30
|
-
)
|
|
1
|
+
from .officials import *
|
|
31
2
|
from .q_pagination import QPagination as q_pagination
|
|
32
3
|
from .local_file_picker import local_file_picker
|
|
33
4
|
from ex4nicegui.utils.signals import ref_computed
|
|
@@ -35,5 +6,4 @@ from signe import effect
|
|
|
35
6
|
from .UseDraggable.UseDraggable import use_draggable
|
|
36
7
|
from .useMouse.UseMouse import use_mouse
|
|
37
8
|
|
|
38
|
-
# from .drawer import drawer
|
|
39
9
|
from .usePagination import PaginationRef as use_pagination
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from .aggrid import AggridBindableUi as aggird
|
|
2
|
+
from .button import ButtonBindableUi as button
|
|
3
|
+
from .card import (
|
|
4
|
+
CardBindableUi as card,
|
|
5
|
+
CardActionsBindableUi as card_actions,
|
|
6
|
+
CardSectionBindableUi as card_section,
|
|
7
|
+
)
|
|
8
|
+
from .checkbox import CheckboxBindableUi as checkbox
|
|
9
|
+
from .color_picker import (
|
|
10
|
+
ColorPickerBindableUi as color_picker,
|
|
11
|
+
ColorPickerLazyBindableUi as lazy_color_picker,
|
|
12
|
+
)
|
|
13
|
+
from .date import DateBindableUi as date
|
|
14
|
+
from .drawer import DrawerBindableUi as drawer
|
|
15
|
+
from .echarts import EChartsBindableUi as echarts
|
|
16
|
+
from .html import HtmlBindableUi as html
|
|
17
|
+
from .icon import IconBindableUi as icon
|
|
18
|
+
from .image import ImageBindableUi as image
|
|
19
|
+
from .input import (
|
|
20
|
+
InputBindableUi as input,
|
|
21
|
+
LazyInputBindableUi as lazy_input,
|
|
22
|
+
)
|
|
23
|
+
from .label import LabelBindableUi as label
|
|
24
|
+
from .radio import RadioBindableUi as radio
|
|
25
|
+
from .row import RowBindableUi as row
|
|
26
|
+
from .select import SelectBindableUi as select
|
|
27
|
+
from .slider import SliderBindableUi as slider, LazySliderBindableUi as lazy_slider
|
|
28
|
+
from .switch import SwitchBindableUi as switch
|
|
29
|
+
from .table import TableBindableUi as table
|
|
30
|
+
from .textarea import (
|
|
31
|
+
TextareaBindableUi as textarea,
|
|
32
|
+
LazyTextareaBindableUi as lazy_textarea,
|
|
33
|
+
)
|
|
34
|
+
from .upload import (
|
|
35
|
+
UploadBindableUi as upload,
|
|
36
|
+
UploadResult,
|
|
37
|
+
)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
List,
|
|
3
|
+
Dict,
|
|
4
|
+
)
|
|
5
|
+
import ex4nicegui.utils.common as utils_common
|
|
6
|
+
from signe import effect
|
|
7
|
+
from ex4nicegui.utils.signals import (
|
|
8
|
+
ReadonlyRef,
|
|
9
|
+
is_ref,
|
|
10
|
+
ref_computed,
|
|
11
|
+
_TMaybeRef as TMaybeRef,
|
|
12
|
+
)
|
|
13
|
+
from nicegui import ui
|
|
14
|
+
from .base import BindableUi
|
|
15
|
+
from .utils import _convert_kws_ref2value
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AggridBindableUi(BindableUi[ui.aggrid]):
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
options: TMaybeRef[Dict],
|
|
22
|
+
*,
|
|
23
|
+
html_columns: TMaybeRef[List[int]] = [],
|
|
24
|
+
theme: TMaybeRef[str] = "balham",
|
|
25
|
+
) -> None:
|
|
26
|
+
kws = {
|
|
27
|
+
"options": options,
|
|
28
|
+
"html_columns": html_columns,
|
|
29
|
+
"theme": theme,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
value_kws = _convert_kws_ref2value(kws)
|
|
33
|
+
|
|
34
|
+
element = ui.aggrid(**value_kws)
|
|
35
|
+
|
|
36
|
+
super().__init__(element)
|
|
37
|
+
|
|
38
|
+
for key, value in kws.items():
|
|
39
|
+
if is_ref(value):
|
|
40
|
+
self.bind_prop(key, value) # type: ignore
|
|
41
|
+
|
|
42
|
+
@staticmethod
|
|
43
|
+
def from_pandas(df: TMaybeRef):
|
|
44
|
+
if is_ref(df):
|
|
45
|
+
|
|
46
|
+
@ref_computed
|
|
47
|
+
def cp_convert_df():
|
|
48
|
+
return utils_common.convert_dataframe(df.value)
|
|
49
|
+
|
|
50
|
+
@ref_computed
|
|
51
|
+
def cp_options():
|
|
52
|
+
columnDefs = [
|
|
53
|
+
{"headerName": col, "field": col}
|
|
54
|
+
for col in cp_convert_df.value.columns
|
|
55
|
+
]
|
|
56
|
+
rowData = cp_convert_df.value.to_dict("records")
|
|
57
|
+
data = {"columnDefs": columnDefs, "rowData": rowData}
|
|
58
|
+
return data
|
|
59
|
+
|
|
60
|
+
return AggridBindableUi(cp_options)
|
|
61
|
+
|
|
62
|
+
columnDefs = [{"headerName": col, "field": col} for col in df.columns] # type: ignore
|
|
63
|
+
rowData = df.to_dict("records") # type: ignore
|
|
64
|
+
options = {"columnDefs": columnDefs, "rowData": rowData}
|
|
65
|
+
return AggridBindableUi(options)
|
|
66
|
+
|
|
67
|
+
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
68
|
+
if prop == "options":
|
|
69
|
+
return self.bind_options(ref_ui)
|
|
70
|
+
|
|
71
|
+
return super().bind_prop(prop, ref_ui)
|
|
72
|
+
|
|
73
|
+
def bind_options(self, ref_ui: ReadonlyRef[List[Dict]]):
|
|
74
|
+
@effect
|
|
75
|
+
def _():
|
|
76
|
+
ele = self.element
|
|
77
|
+
data = ref_ui.value
|
|
78
|
+
ele._props["options"].update(data)
|
|
79
|
+
ele.update()
|
|
80
|
+
|
|
81
|
+
return self
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import (
|
|
4
|
+
Any,
|
|
5
|
+
Callable,
|
|
6
|
+
List,
|
|
7
|
+
Optional,
|
|
8
|
+
TypeVar,
|
|
9
|
+
Generic,
|
|
10
|
+
cast,
|
|
11
|
+
overload,
|
|
12
|
+
)
|
|
13
|
+
from typing_extensions import Self
|
|
14
|
+
from signe import effect
|
|
15
|
+
from ex4nicegui.utils.signals import (
|
|
16
|
+
ReadonlyRef,
|
|
17
|
+
Ref,
|
|
18
|
+
to_ref,
|
|
19
|
+
_TMaybeRef as TMaybeRef,
|
|
20
|
+
)
|
|
21
|
+
from nicegui import Tailwind, ui
|
|
22
|
+
from nicegui.elements.mixins.color_elements import (
|
|
23
|
+
TextColorElement,
|
|
24
|
+
QUASAR_COLORS,
|
|
25
|
+
TAILWIND_COLORS,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
T = TypeVar("T")
|
|
29
|
+
|
|
30
|
+
TWidget = TypeVar("TWidget")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class BindableUi(Generic[TWidget]):
|
|
34
|
+
def __init__(self, element: TWidget) -> None:
|
|
35
|
+
self.__element = element
|
|
36
|
+
|
|
37
|
+
def props(self, add: Optional[str] = None, *, remove: Optional[str] = None):
|
|
38
|
+
cast(ui.element, self.element).props(add, remove=remove)
|
|
39
|
+
return self
|
|
40
|
+
|
|
41
|
+
def classes(
|
|
42
|
+
self,
|
|
43
|
+
add: Optional[str] = None,
|
|
44
|
+
*,
|
|
45
|
+
remove: Optional[str] = None,
|
|
46
|
+
replace: Optional[str] = None,
|
|
47
|
+
):
|
|
48
|
+
cast(ui.element, self.element).classes(add, remove=remove, replace=replace)
|
|
49
|
+
return self
|
|
50
|
+
|
|
51
|
+
def style(
|
|
52
|
+
self,
|
|
53
|
+
add: Optional[str] = None,
|
|
54
|
+
*,
|
|
55
|
+
remove: Optional[str] = None,
|
|
56
|
+
replace: Optional[str] = None,
|
|
57
|
+
):
|
|
58
|
+
cast(ui.element, self.element).style(add, remove=remove, replace=replace)
|
|
59
|
+
return self
|
|
60
|
+
|
|
61
|
+
@overload
|
|
62
|
+
def tailwind(self, *tailwind: Tailwind) -> Self:
|
|
63
|
+
...
|
|
64
|
+
|
|
65
|
+
@overload
|
|
66
|
+
def tailwind(self, *classes: str) -> Self:
|
|
67
|
+
...
|
|
68
|
+
|
|
69
|
+
def tailwind(self, *args):
|
|
70
|
+
cast(ui.element, self.element).tailwind(*args)
|
|
71
|
+
return self
|
|
72
|
+
|
|
73
|
+
def tooltip(self, text: str) -> Self:
|
|
74
|
+
cast(ui.element, self.element).tooltip(text)
|
|
75
|
+
return self
|
|
76
|
+
|
|
77
|
+
def add_slot(self, name: str, template: Optional[str] = None):
|
|
78
|
+
"""Add a slot to the element.
|
|
79
|
+
|
|
80
|
+
:param name: name of the slot
|
|
81
|
+
:param template: Vue template of the slot
|
|
82
|
+
:return: the slot
|
|
83
|
+
"""
|
|
84
|
+
return cast(ui.element, self.element).add_slot(name, template)
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def element(self):
|
|
88
|
+
return self.__element
|
|
89
|
+
|
|
90
|
+
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
91
|
+
if prop == "visible":
|
|
92
|
+
return self.bind_visible(ref_ui)
|
|
93
|
+
|
|
94
|
+
@effect
|
|
95
|
+
def _():
|
|
96
|
+
element = cast(ui.element, self.element)
|
|
97
|
+
element._props[prop] = ref_ui.value
|
|
98
|
+
element.update()
|
|
99
|
+
|
|
100
|
+
return self
|
|
101
|
+
|
|
102
|
+
def bind_visible(self, ref_ui: ReadonlyRef[bool]):
|
|
103
|
+
@effect
|
|
104
|
+
def _():
|
|
105
|
+
element = cast(ui.element, self.element)
|
|
106
|
+
element.set_visibility(ref_ui.value)
|
|
107
|
+
|
|
108
|
+
return self
|
|
109
|
+
|
|
110
|
+
def on(
|
|
111
|
+
self,
|
|
112
|
+
type: str,
|
|
113
|
+
handler: Optional[Callable[..., Any]] = None,
|
|
114
|
+
args: Optional[List[str]] = None,
|
|
115
|
+
*,
|
|
116
|
+
throttle: float = 0.0,
|
|
117
|
+
leading_events: bool = True,
|
|
118
|
+
trailing_events: bool = True,
|
|
119
|
+
):
|
|
120
|
+
ele = cast(ui.element, self.element)
|
|
121
|
+
ele.on(
|
|
122
|
+
type,
|
|
123
|
+
handler,
|
|
124
|
+
args,
|
|
125
|
+
throttle=throttle,
|
|
126
|
+
leading_events=leading_events,
|
|
127
|
+
trailing_events=trailing_events,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
return self
|
|
131
|
+
|
|
132
|
+
def clear(self) -> None:
|
|
133
|
+
cast(ui.element, self.element).clear()
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class SingleValueBindableUi(BindableUi[TWidget], Generic[T, TWidget]):
|
|
137
|
+
def __init__(self, value: TMaybeRef[T], element: TWidget) -> None:
|
|
138
|
+
super().__init__(element)
|
|
139
|
+
self._ref = to_ref(value)
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def value(self) -> T:
|
|
143
|
+
return self._ref.value
|
|
144
|
+
|
|
145
|
+
def bind_ref(self, ref: Ref[T]):
|
|
146
|
+
@effect
|
|
147
|
+
def _():
|
|
148
|
+
ref.value = self._ref.value
|
|
149
|
+
|
|
150
|
+
return self
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _bind_color(bindable_ui: SingleValueBindableUi, ref_ui: ReadonlyRef):
|
|
154
|
+
@effect
|
|
155
|
+
def _():
|
|
156
|
+
ele = cast(TextColorElement, bindable_ui.element)
|
|
157
|
+
color = ref_ui.value
|
|
158
|
+
|
|
159
|
+
if color in QUASAR_COLORS:
|
|
160
|
+
ele._props[ele.TEXT_COLOR_PROP] = color
|
|
161
|
+
elif color in TAILWIND_COLORS:
|
|
162
|
+
ele.classes(replace=f"text-{color}")
|
|
163
|
+
elif color is not None:
|
|
164
|
+
ele._style["color"] = color
|
|
165
|
+
ele.update()
|
|
166
|
+
|
|
167
|
+
return bindable_ui
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Any,
|
|
3
|
+
Callable,
|
|
4
|
+
Optional,
|
|
5
|
+
)
|
|
6
|
+
from signe import effect
|
|
7
|
+
from ex4nicegui.utils.signals import (
|
|
8
|
+
ReadonlyRef,
|
|
9
|
+
is_ref,
|
|
10
|
+
_TMaybeRef as TMaybeRef,
|
|
11
|
+
)
|
|
12
|
+
from nicegui import ui
|
|
13
|
+
from .base import SingleValueBindableUi, _bind_color
|
|
14
|
+
from .utils import _convert_kws_ref2value
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ButtonBindableUi(SingleValueBindableUi[str, ui.button]):
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
text: TMaybeRef[str] = "",
|
|
21
|
+
*,
|
|
22
|
+
on_click: Optional[Callable[..., Any]] = None,
|
|
23
|
+
color: Optional[TMaybeRef[str]] = "primary",
|
|
24
|
+
icon: Optional[TMaybeRef[str]] = None,
|
|
25
|
+
) -> None:
|
|
26
|
+
kws = {
|
|
27
|
+
"text": text,
|
|
28
|
+
"color": color,
|
|
29
|
+
"icon": icon,
|
|
30
|
+
"on_click": on_click,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
value_kws = _convert_kws_ref2value(kws)
|
|
34
|
+
|
|
35
|
+
element = ui.button(**value_kws)
|
|
36
|
+
|
|
37
|
+
super().__init__(text, element)
|
|
38
|
+
|
|
39
|
+
for key, value in kws.items():
|
|
40
|
+
if is_ref(value):
|
|
41
|
+
self.bind_prop(key, value) # type: ignore
|
|
42
|
+
|
|
43
|
+
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
44
|
+
if prop == "text":
|
|
45
|
+
return self.bind_text(ref_ui)
|
|
46
|
+
if prop == "icon":
|
|
47
|
+
return self.bind_icon(ref_ui)
|
|
48
|
+
if prop == "color":
|
|
49
|
+
return self.bind_color(ref_ui)
|
|
50
|
+
|
|
51
|
+
return super().bind_prop(prop, ref_ui)
|
|
52
|
+
|
|
53
|
+
def bind_color(self, ref_ui: ReadonlyRef):
|
|
54
|
+
return _bind_color(self, ref_ui)
|
|
55
|
+
|
|
56
|
+
def bind_text(self, ref_ui: ReadonlyRef):
|
|
57
|
+
@effect
|
|
58
|
+
def _():
|
|
59
|
+
ele = self.element
|
|
60
|
+
ele._props["text"] = ref_ui.value
|
|
61
|
+
ele.update()
|
|
62
|
+
|
|
63
|
+
return self
|
|
64
|
+
|
|
65
|
+
def bind_icon(self, ref_ui: ReadonlyRef):
|
|
66
|
+
@effect
|
|
67
|
+
def _():
|
|
68
|
+
ele = self.element
|
|
69
|
+
ele._props["icon"] = ref_ui.value
|
|
70
|
+
ele.update()
|
|
71
|
+
|
|
72
|
+
return self
|
|
73
|
+
|
|
74
|
+
def bind_enabled(self, ref_ui: ReadonlyRef[bool]):
|
|
75
|
+
@effect
|
|
76
|
+
def _():
|
|
77
|
+
self.element.on_enabled_change(ref_ui.value)
|
|
78
|
+
|
|
79
|
+
return self
|
|
80
|
+
|
|
81
|
+
def bind_disable(self, ref_ui: ReadonlyRef[bool]):
|
|
82
|
+
@effect
|
|
83
|
+
def _():
|
|
84
|
+
self.element.on_enabled_change(not ref_ui.value)
|
|
85
|
+
|
|
86
|
+
return self
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Any,
|
|
3
|
+
)
|
|
4
|
+
from nicegui import ui
|
|
5
|
+
from .base import BindableUi
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CardBindableUi(BindableUi[ui.card]):
|
|
9
|
+
def __init__(
|
|
10
|
+
self,
|
|
11
|
+
) -> None:
|
|
12
|
+
element = ui.card()
|
|
13
|
+
|
|
14
|
+
super().__init__(element)
|
|
15
|
+
|
|
16
|
+
def __enter__(self):
|
|
17
|
+
self.element.__enter__()
|
|
18
|
+
return self
|
|
19
|
+
|
|
20
|
+
def __exit__(self, *_: Any):
|
|
21
|
+
self.element.__exit__(*_)
|
|
22
|
+
|
|
23
|
+
def tight(self):
|
|
24
|
+
"""Removes padding and gaps between nested elements."""
|
|
25
|
+
self.element._classes.clear()
|
|
26
|
+
self.element._style.clear()
|
|
27
|
+
return self
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class CardSectionBindableUi(BindableUi[ui.card_section]):
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
) -> None:
|
|
34
|
+
element = ui.card_section()
|
|
35
|
+
|
|
36
|
+
super().__init__(element)
|
|
37
|
+
|
|
38
|
+
def __enter__(self):
|
|
39
|
+
self.element.__enter__()
|
|
40
|
+
return self
|
|
41
|
+
|
|
42
|
+
def __exit__(self, *_: Any):
|
|
43
|
+
self.element.__exit__(*_)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class CardActionsBindableUi(BindableUi[ui.card_actions]):
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
) -> None:
|
|
50
|
+
element = ui.card_actions()
|
|
51
|
+
|
|
52
|
+
super().__init__(element)
|
|
53
|
+
|
|
54
|
+
def __enter__(self):
|
|
55
|
+
self.element.__enter__()
|
|
56
|
+
return self
|
|
57
|
+
|
|
58
|
+
def __exit__(self, *_: Any):
|
|
59
|
+
self.element.__exit__(*_)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Any,
|
|
3
|
+
Callable,
|
|
4
|
+
Optional,
|
|
5
|
+
TypeVar,
|
|
6
|
+
cast,
|
|
7
|
+
)
|
|
8
|
+
from signe import effect
|
|
9
|
+
from ex4nicegui.utils.signals import (
|
|
10
|
+
ReadonlyRef,
|
|
11
|
+
is_ref,
|
|
12
|
+
_TMaybeRef as TMaybeRef,
|
|
13
|
+
)
|
|
14
|
+
from nicegui import ui
|
|
15
|
+
from nicegui.elements.mixins.value_element import ValueElement
|
|
16
|
+
from .base import SingleValueBindableUi
|
|
17
|
+
from .utils import _convert_kws_ref2value
|
|
18
|
+
|
|
19
|
+
T = TypeVar("T")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class CheckboxBindableUi(SingleValueBindableUi[bool, ui.checkbox]):
|
|
23
|
+
@staticmethod
|
|
24
|
+
def _setup_(binder: "CheckboxBindableUi"):
|
|
25
|
+
def onValueChanged(e):
|
|
26
|
+
binder._ref.value = e.args # type: ignore
|
|
27
|
+
|
|
28
|
+
ele = cast(ValueElement, binder.element)
|
|
29
|
+
|
|
30
|
+
@effect
|
|
31
|
+
def _():
|
|
32
|
+
ele.value = binder.value
|
|
33
|
+
|
|
34
|
+
ele.on("update:modelValue", handler=onValueChanged)
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
text: TMaybeRef[str] = "",
|
|
39
|
+
*,
|
|
40
|
+
value: TMaybeRef[bool] = False,
|
|
41
|
+
on_change: Optional[Callable[..., Any]] = None,
|
|
42
|
+
) -> None:
|
|
43
|
+
kws = {"text": text, "value": value, "on_change": on_change}
|
|
44
|
+
|
|
45
|
+
value_kws = _convert_kws_ref2value(kws)
|
|
46
|
+
|
|
47
|
+
element = ui.checkbox(**value_kws)
|
|
48
|
+
|
|
49
|
+
super().__init__(value, element)
|
|
50
|
+
|
|
51
|
+
for key, value in kws.items():
|
|
52
|
+
if is_ref(value):
|
|
53
|
+
self.bind_prop(key, value) # type: ignore
|
|
54
|
+
|
|
55
|
+
CheckboxBindableUi._setup_(self)
|
|
56
|
+
|
|
57
|
+
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
58
|
+
if prop == "value":
|
|
59
|
+
return self.bind_value(ref_ui)
|
|
60
|
+
|
|
61
|
+
return super().bind_prop(prop, ref_ui)
|
|
62
|
+
|
|
63
|
+
def bind_value(self, ref_ui: ReadonlyRef[bool]):
|
|
64
|
+
@effect
|
|
65
|
+
def _():
|
|
66
|
+
self.element.on_value_change(ref_ui.value)
|
|
67
|
+
|
|
68
|
+
return self
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Any,
|
|
3
|
+
Callable,
|
|
4
|
+
Optional,
|
|
5
|
+
Union,
|
|
6
|
+
)
|
|
7
|
+
from signe import effect
|
|
8
|
+
from ex4nicegui.utils.signals import (
|
|
9
|
+
ReadonlyRef,
|
|
10
|
+
is_ref,
|
|
11
|
+
_TMaybeRef as TMaybeRef,
|
|
12
|
+
)
|
|
13
|
+
from nicegui import ui
|
|
14
|
+
from .base import SingleValueBindableUi
|
|
15
|
+
from .utils import _convert_kws_ref2value
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ColorPickerBindableUi(SingleValueBindableUi[str, ui.color_picker]):
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
color: TMaybeRef[str] = "",
|
|
22
|
+
*,
|
|
23
|
+
on_pick: Optional[Callable[..., Any]] = None,
|
|
24
|
+
value: TMaybeRef[bool] = False,
|
|
25
|
+
) -> None:
|
|
26
|
+
kws = {
|
|
27
|
+
"value": value,
|
|
28
|
+
"on_pick": on_pick,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
value_kws = _convert_kws_ref2value(kws)
|
|
32
|
+
|
|
33
|
+
with ui.card().tight():
|
|
34
|
+
element_menu = ui.color_picker(**value_kws)
|
|
35
|
+
self._element_picker = element_menu.default_slot.children[0]
|
|
36
|
+
self._element_picker.props(f'format-model="rgba"')
|
|
37
|
+
|
|
38
|
+
ui.button(on_click=element_menu.open, icon="colorize")
|
|
39
|
+
|
|
40
|
+
super().__init__(color, element_menu)
|
|
41
|
+
|
|
42
|
+
for key, value in kws.items():
|
|
43
|
+
if is_ref(value) and key != "color":
|
|
44
|
+
self.bind_prop(key, value) # type: ignore
|
|
45
|
+
|
|
46
|
+
self._ex_setup()
|
|
47
|
+
|
|
48
|
+
def _ex_setup(self):
|
|
49
|
+
ele = self._element_picker
|
|
50
|
+
|
|
51
|
+
@effect
|
|
52
|
+
def _():
|
|
53
|
+
ele._props["modelValue"] = self.value
|
|
54
|
+
|
|
55
|
+
def onModelValueChanged(e):
|
|
56
|
+
self._ref.value = e.args # type: ignore
|
|
57
|
+
|
|
58
|
+
ele.on("update:modelValue", handler=onModelValueChanged)
|
|
59
|
+
|
|
60
|
+
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
61
|
+
if prop == "value":
|
|
62
|
+
return self.bind_value(ref_ui)
|
|
63
|
+
|
|
64
|
+
return super().bind_prop(prop, ref_ui)
|
|
65
|
+
|
|
66
|
+
def bind_color(self, ref_ui: ReadonlyRef[str]):
|
|
67
|
+
@effect
|
|
68
|
+
def _():
|
|
69
|
+
self._element_picker._props["modelValue"] = ref_ui.value
|
|
70
|
+
|
|
71
|
+
return self
|
|
72
|
+
|
|
73
|
+
def bind_value(self, ref_ui: ReadonlyRef[bool]):
|
|
74
|
+
@effect
|
|
75
|
+
def _():
|
|
76
|
+
self._element_picker._props["value"] = ref_ui.value
|
|
77
|
+
|
|
78
|
+
return self
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class ColorPickerLazyBindableUi(ColorPickerBindableUi):
|
|
82
|
+
def __init__(
|
|
83
|
+
self,
|
|
84
|
+
color: TMaybeRef[str] = "",
|
|
85
|
+
*,
|
|
86
|
+
on_pick: Optional[Callable[..., Any]] = None,
|
|
87
|
+
value: TMaybeRef[bool] = False,
|
|
88
|
+
) -> None:
|
|
89
|
+
super().__init__(color, on_pick=on_pick, value=value)
|
|
90
|
+
|
|
91
|
+
def _ex_setup(self):
|
|
92
|
+
ele = self._element_picker
|
|
93
|
+
|
|
94
|
+
# @effect
|
|
95
|
+
# def _():
|
|
96
|
+
# ele._props["modelValue"] = self.value
|
|
97
|
+
|
|
98
|
+
def onModelValueChanged(e):
|
|
99
|
+
self._ref.value = e.args # type: ignore
|
|
100
|
+
|
|
101
|
+
ele.on("change", handler=onModelValueChanged)
|