ex4nicegui 0.6.9__py3-none-any.whl → 0.7.1__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/bi/dataSourceFacade.py +20 -20
- ex4nicegui/bi/index.py +20 -23
- ex4nicegui/reactive/EChartsComponent/ECharts.py +9 -8
- ex4nicegui/reactive/__init__.py +14 -0
- ex4nicegui/reactive/base.py +64 -55
- ex4nicegui/reactive/mixins/backgroundColor.py +5 -5
- ex4nicegui/reactive/mixins/disableable.py +8 -8
- ex4nicegui/reactive/mixins/textColor.py +10 -10
- ex4nicegui/reactive/officials/aggrid.py +5 -5
- ex4nicegui/reactive/officials/avatar.py +86 -0
- ex4nicegui/reactive/officials/badge.py +102 -0
- ex4nicegui/reactive/officials/button.py +15 -15
- ex4nicegui/reactive/officials/checkbox.py +6 -7
- ex4nicegui/reactive/officials/chip.py +6 -7
- ex4nicegui/reactive/officials/circular_progress.py +7 -7
- ex4nicegui/reactive/officials/color_picker.py +8 -8
- ex4nicegui/reactive/officials/column.py +5 -5
- ex4nicegui/reactive/officials/date.py +6 -6
- ex4nicegui/reactive/officials/dialog.py +49 -0
- ex4nicegui/reactive/officials/echarts.py +49 -51
- ex4nicegui/reactive/officials/expansion.py +6 -6
- ex4nicegui/reactive/officials/icon.py +7 -13
- ex4nicegui/reactive/officials/image.py +6 -6
- ex4nicegui/reactive/officials/input.py +10 -11
- ex4nicegui/reactive/officials/knob.py +7 -7
- ex4nicegui/reactive/officials/label.py +11 -9
- ex4nicegui/reactive/officials/linear_progress.py +7 -7
- ex4nicegui/reactive/officials/number.py +10 -10
- ex4nicegui/reactive/officials/radio.py +10 -10
- ex4nicegui/reactive/officials/row.py +5 -5
- ex4nicegui/reactive/officials/select.py +11 -10
- ex4nicegui/reactive/officials/slider.py +6 -6
- ex4nicegui/reactive/officials/switch.py +6 -7
- ex4nicegui/reactive/officials/tab.py +0 -12
- ex4nicegui/reactive/officials/tab_panels.py +5 -5
- ex4nicegui/reactive/officials/table.py +13 -13
- ex4nicegui/reactive/officials/tabs.py +5 -5
- ex4nicegui/reactive/officials/textarea.py +6 -6
- ex4nicegui/reactive/officials/toggle.py +88 -0
- ex4nicegui/reactive/officials/tooltip.py +40 -0
- ex4nicegui/reactive/q_pagination.py +5 -5
- ex4nicegui/reactive/systems/reactive_system.py +2 -2
- 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/signals.py +23 -21
- {ex4nicegui-0.6.9.dist-info → ex4nicegui-0.7.1.dist-info}/METADATA +223 -48
- {ex4nicegui-0.6.9.dist-info → ex4nicegui-0.7.1.dist-info}/RECORD +51 -45
- {ex4nicegui-0.6.9.dist-info → ex4nicegui-0.7.1.dist-info}/LICENSE +0 -0
- {ex4nicegui-0.6.9.dist-info → ex4nicegui-0.7.1.dist-info}/WHEEL +0 -0
|
@@ -228,26 +228,26 @@ class DataSourceFacade(Generic[_TData]):
|
|
|
228
228
|
|
|
229
229
|
Support pyecharts
|
|
230
230
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
231
|
+
.. code-block:: python
|
|
232
|
+
import pandas as pd
|
|
233
|
+
from ex4nicegui import bi
|
|
234
|
+
from pyecharts.charts import Bar
|
|
235
|
+
|
|
236
|
+
df = pd.DataFrame({"name": list("abcdc"), "value": range(5)})
|
|
237
|
+
ds = bi.data_source(df)
|
|
238
|
+
|
|
239
|
+
@ds.ui_echarts
|
|
240
|
+
def bar(data: pd.DataFrame):
|
|
241
|
+
c = (
|
|
242
|
+
Bar()
|
|
243
|
+
.add_xaxis(data["name"].tolist())
|
|
244
|
+
.add_yaxis("value", data["value"].tolist())
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
return c
|
|
248
|
+
|
|
249
|
+
bar.classes("h-[20rem]")
|
|
250
|
+
|
|
251
251
|
|
|
252
252
|
"""
|
|
253
253
|
return ui_echarts(self, fn)
|
ex4nicegui/bi/index.py
CHANGED
|
@@ -24,43 +24,40 @@ def data_source(data: Union[Callable[..., _TData], _TData]) -> DataSourceFacade[
|
|
|
24
24
|
|
|
25
25
|
## Examples
|
|
26
26
|
|
|
27
|
-
---
|
|
28
|
-
|
|
29
27
|
pandas dataframe source:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
|
|
29
|
+
.. code-block:: python
|
|
30
|
+
df = pd.DataFrame({"name": list("abcdc"), "value": range(5)})
|
|
31
|
+
ds = bi.data_source(df)
|
|
32
|
+
|
|
34
33
|
|
|
35
34
|
---
|
|
36
35
|
|
|
37
36
|
Link multiple data sources
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
ds = bi.data_source(df)
|
|
38
|
+
.. code-block:: python
|
|
39
|
+
df = pd.DataFrame({"name": list("abcdc"), "value": range(5)})
|
|
40
|
+
ds = bi.data_source(df)
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
@bi.data_source
|
|
43
|
+
def ds_other():
|
|
44
|
+
# ds.filtered_data is DataFrame after filtering
|
|
45
|
+
where = ds.filtered_data[''].isin(['b','c','d'])
|
|
46
|
+
return ds.filtered_data[where]
|
|
49
47
|
|
|
50
|
-
```
|
|
51
48
|
|
|
52
49
|
---
|
|
53
50
|
|
|
54
51
|
Now, when `ds` changes, it will trigger changes to `ds_other` and thus drive the related interface components to change.
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
.. code-block:: python
|
|
54
|
+
# select box of data source 'ds'
|
|
55
|
+
# it change will trigger changes to table
|
|
56
|
+
ds.ui_select('name')
|
|
57
|
+
|
|
58
|
+
# table of data 'ds_other'
|
|
59
|
+
ds_other.ui_aggrid()
|
|
60
60
|
|
|
61
|
-
# table of data 'ds_other'
|
|
62
|
-
ds_other.ui_aggrid()
|
|
63
|
-
```
|
|
64
61
|
|
|
65
62
|
|
|
66
63
|
"""
|
|
@@ -64,14 +64,15 @@ class echarts(Element, component="ECharts.js", libraries=libraries): # type: ig
|
|
|
64
64
|
Args:
|
|
65
65
|
options (dict): chart setting options dict
|
|
66
66
|
opts (Optional[dict], optional): update options. Defaults to None.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
67
|
+
|
|
68
|
+
.. code-block:: python
|
|
69
|
+
{
|
|
70
|
+
'notMerge':False,
|
|
71
|
+
'lazyUpdate':False,
|
|
72
|
+
'silent':False,
|
|
73
|
+
'replaceMerge': None,
|
|
74
|
+
}
|
|
75
|
+
|
|
75
76
|
[open echarts setOption docs](https://echarts.apache.org/zh/api.html#echartsInstance.setOption)
|
|
76
77
|
|
|
77
78
|
"""
|
ex4nicegui/reactive/__init__.py
CHANGED
|
@@ -54,6 +54,10 @@ from .officials.element import ElementBindableUi as element
|
|
|
54
54
|
from .officials.tab_panels import LazyTabPanelsBindableUi as lazy_tab_panels
|
|
55
55
|
from .q_pagination import PaginationBindableUi as q_pagination
|
|
56
56
|
from .officials.chip import ChipBindableUi as chip
|
|
57
|
+
from .officials.tooltip import TooltipBindableUi as tooltip
|
|
58
|
+
from .officials.toggle import ToggleBindableUi as toggle
|
|
59
|
+
from .officials.avatar import AvatarBindableUi as avatar
|
|
60
|
+
from .officials.badge import BadgeBindableUi as badge
|
|
57
61
|
|
|
58
62
|
from .local_file_picker import local_file_picker
|
|
59
63
|
from .UseDraggable.UseDraggable import use_draggable
|
|
@@ -63,8 +67,10 @@ from .usePagination import PaginationRef as use_pagination
|
|
|
63
67
|
from .dropZone.dropZone import use_drag_zone
|
|
64
68
|
from .fileWatcher import FilesWatcher
|
|
65
69
|
from .mermaid.mermaid import Mermaid as mermaid
|
|
70
|
+
from .officials.dialog import DialogBindableUi as dialog
|
|
66
71
|
from .vfor import vfor, VforStore
|
|
67
72
|
from .vmodel import vmodel
|
|
73
|
+
from .view_model import ViewModel, var, cached_var
|
|
68
74
|
|
|
69
75
|
pagination = q_pagination
|
|
70
76
|
|
|
@@ -88,6 +94,9 @@ __all__ = [
|
|
|
88
94
|
"vfor",
|
|
89
95
|
"VforStore",
|
|
90
96
|
"vmodel",
|
|
97
|
+
"ViewModel",
|
|
98
|
+
"var",
|
|
99
|
+
"cached_var",
|
|
91
100
|
"html",
|
|
92
101
|
"aggrid",
|
|
93
102
|
"button",
|
|
@@ -124,4 +133,9 @@ __all__ = [
|
|
|
124
133
|
"pagination",
|
|
125
134
|
"mermaid",
|
|
126
135
|
"chip",
|
|
136
|
+
"dialog",
|
|
137
|
+
"tooltip",
|
|
138
|
+
"toggle",
|
|
139
|
+
"avatar",
|
|
140
|
+
"badge",
|
|
127
141
|
]
|
ex4nicegui/reactive/base.py
CHANGED
|
@@ -24,6 +24,7 @@ from ex4nicegui.utils.signals import (
|
|
|
24
24
|
on,
|
|
25
25
|
)
|
|
26
26
|
from ex4nicegui.utils.clientScope import new_scope
|
|
27
|
+
from ex4nicegui.utils.types import _TMaybeRef as TMaybeRef
|
|
27
28
|
from nicegui import Tailwind, ui
|
|
28
29
|
from nicegui.elements.mixins.text_element import TextElement
|
|
29
30
|
from ex4nicegui.reactive.services.reactive_service import inject_handle_delete
|
|
@@ -72,7 +73,9 @@ class BindableUi(Generic[TWidget]):
|
|
|
72
73
|
|
|
73
74
|
@property
|
|
74
75
|
def _ui_signal_on(self):
|
|
75
|
-
|
|
76
|
+
"""equivalent to `on`, but with the effect scope,and with `onchanges`=True and `deep` = False"""
|
|
77
|
+
|
|
78
|
+
return partial(on, scope=self._effect_scope, onchanges=True, deep=False)
|
|
76
79
|
|
|
77
80
|
def props(self, add: Optional[str] = None, *, remove: Optional[str] = None):
|
|
78
81
|
cast(ui.element, self.element).props(add, remove=remove)
|
|
@@ -105,8 +108,12 @@ class BindableUi(Generic[TWidget]):
|
|
|
105
108
|
def __exit__(self, *_):
|
|
106
109
|
self.element.default_slot.__exit__(*_)
|
|
107
110
|
|
|
108
|
-
def tooltip(self, text: str) -> Self:
|
|
109
|
-
|
|
111
|
+
def tooltip(self, text: TMaybeRef[str]) -> Self:
|
|
112
|
+
from ex4nicegui.reactive.officials.tooltip import TooltipBindableUi
|
|
113
|
+
|
|
114
|
+
with self:
|
|
115
|
+
TooltipBindableUi(text)
|
|
116
|
+
|
|
110
117
|
return self
|
|
111
118
|
|
|
112
119
|
def add_slot(self, name: str, template: Optional[str] = None):
|
|
@@ -143,7 +150,7 @@ class BindableUi(Generic[TWidget]):
|
|
|
143
150
|
"""
|
|
144
151
|
return self.element.remove(element)
|
|
145
152
|
|
|
146
|
-
def bind_prop(self, prop: str,
|
|
153
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef[Any]):
|
|
147
154
|
"""data binding is manipulating an element's property
|
|
148
155
|
|
|
149
156
|
@see - https://github.com/CrystalWindSnake/ex4nicegui/blob/main/README.en.md#bind_prop
|
|
@@ -151,37 +158,37 @@ class BindableUi(Generic[TWidget]):
|
|
|
151
158
|
|
|
152
159
|
Args:
|
|
153
160
|
prop (str): property name
|
|
154
|
-
|
|
161
|
+
value (TGetterOrReadonlyRef[Any]): a reference to the value to bind to
|
|
155
162
|
|
|
156
163
|
"""
|
|
157
164
|
if prop == "visible":
|
|
158
|
-
return self.bind_visible(
|
|
165
|
+
return self.bind_visible(value)
|
|
159
166
|
|
|
160
167
|
if prop == "text" and isinstance(self.element, TextElement):
|
|
161
168
|
|
|
162
169
|
@self._ui_effect
|
|
163
170
|
def _():
|
|
164
|
-
cast(TextElement, self.element).set_text(to_value(
|
|
171
|
+
cast(TextElement, self.element).set_text(to_value(value))
|
|
165
172
|
self.element.update()
|
|
166
173
|
|
|
167
174
|
@self._ui_effect
|
|
168
175
|
def _():
|
|
169
176
|
element = cast(ui.element, self.element)
|
|
170
|
-
element._props[prop] = to_value(
|
|
177
|
+
element._props[prop] = to_value(value)
|
|
171
178
|
element.update()
|
|
172
179
|
|
|
173
180
|
return self
|
|
174
181
|
|
|
175
|
-
def bind_visible(self,
|
|
182
|
+
def bind_visible(self, value: TGetterOrReadonlyRef[bool]):
|
|
176
183
|
@self._ui_effect
|
|
177
184
|
def _():
|
|
178
185
|
element = cast(ui.element, self.element)
|
|
179
|
-
element.set_visibility(to_value(
|
|
186
|
+
element.set_visibility(to_value(value))
|
|
180
187
|
|
|
181
188
|
return self
|
|
182
189
|
|
|
183
|
-
def bind_not_visible(self,
|
|
184
|
-
return self.bind_visible(lambda: not to_value(
|
|
190
|
+
def bind_not_visible(self, value: TGetterOrReadonlyRef[bool]):
|
|
191
|
+
return self.bind_visible(lambda: not to_value(value))
|
|
185
192
|
|
|
186
193
|
def on(
|
|
187
194
|
self,
|
|
@@ -209,22 +216,22 @@ class BindableUi(Generic[TWidget]):
|
|
|
209
216
|
cast(ui.element, self.element).clear()
|
|
210
217
|
|
|
211
218
|
@overload
|
|
212
|
-
def bind_classes(self, classes: Dict[str, TGetterOrReadonlyRef[bool]]):
|
|
219
|
+
def bind_classes(self, classes: Dict[str, TGetterOrReadonlyRef[bool]]) -> Self:
|
|
213
220
|
...
|
|
214
221
|
|
|
215
222
|
@overload
|
|
216
|
-
def bind_classes(self, classes: TGetterOrReadonlyRef[Dict[str, bool]]):
|
|
223
|
+
def bind_classes(self, classes: TGetterOrReadonlyRef[Dict[str, bool]]) -> Self:
|
|
217
224
|
...
|
|
218
225
|
|
|
219
226
|
@overload
|
|
220
|
-
def bind_classes(self, classes: List[TGetterOrReadonlyRef[str]]):
|
|
227
|
+
def bind_classes(self, classes: List[TGetterOrReadonlyRef[str]]) -> Self:
|
|
221
228
|
...
|
|
222
229
|
|
|
223
230
|
@overload
|
|
224
|
-
def bind_classes(self, classes: TGetterOrReadonlyRef[str]):
|
|
231
|
+
def bind_classes(self, classes: TGetterOrReadonlyRef[str]) -> Self:
|
|
225
232
|
...
|
|
226
233
|
|
|
227
|
-
def bind_classes(self, classes: _T_bind_classes_type):
|
|
234
|
+
def bind_classes(self, classes: _T_bind_classes_type) -> Self:
|
|
228
235
|
"""data binding is manipulating an element's class list
|
|
229
236
|
|
|
230
237
|
@see - https://github.com/CrystalWindSnake/ex4nicegui/blob/main/README.en.md#bind-class-names
|
|
@@ -237,30 +244,30 @@ class BindableUi(Generic[TWidget]):
|
|
|
237
244
|
|
|
238
245
|
bind class names with dict,value is bool ref, for example:
|
|
239
246
|
|
|
240
|
-
|
|
247
|
+
.. code-block:: python
|
|
241
248
|
bg_color = to_ref(True)
|
|
242
249
|
has_error = to_ref(False)
|
|
243
250
|
|
|
244
251
|
rxui.label('Hello').bind_classes({'bg-blue':bg_color, 'text-red':has_error})
|
|
245
|
-
|
|
252
|
+
|
|
246
253
|
|
|
247
254
|
bind list of class names with ref
|
|
248
255
|
|
|
249
|
-
|
|
256
|
+
.. code-block:: python
|
|
250
257
|
color = to_ref('red')
|
|
251
258
|
bg_color = lambda: f"bg-{color.value}"
|
|
252
259
|
|
|
253
260
|
rxui.label('Hello').bind_classes([bg_color])
|
|
254
|
-
|
|
261
|
+
|
|
255
262
|
|
|
256
263
|
bind single class name with ref
|
|
257
264
|
|
|
258
|
-
|
|
265
|
+
.. code-block:: python
|
|
259
266
|
color = to_ref('red')
|
|
260
267
|
bg_color = lambda: f"bg-{color.value}"
|
|
261
268
|
|
|
262
269
|
rxui.label('Hello').bind_classes(bg_color)
|
|
263
|
-
|
|
270
|
+
|
|
264
271
|
|
|
265
272
|
"""
|
|
266
273
|
if isinstance(classes, dict):
|
|
@@ -316,17 +323,18 @@ class BindableUi(Generic[TWidget]):
|
|
|
316
323
|
|
|
317
324
|
|
|
318
325
|
## usage
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
326
|
+
|
|
327
|
+
.. code-block:: python
|
|
328
|
+
bg_color = to_ref("blue")
|
|
329
|
+
text_color = to_ref("red")
|
|
330
|
+
|
|
331
|
+
rxui.label("test").bind_style(
|
|
332
|
+
{
|
|
333
|
+
"background-color": bg_color,
|
|
334
|
+
"color": text_color,
|
|
335
|
+
}
|
|
336
|
+
)
|
|
337
|
+
|
|
330
338
|
"""
|
|
331
339
|
if isinstance(style, dict):
|
|
332
340
|
for name, ref_obj in style.items():
|
|
@@ -350,27 +358,28 @@ class BindableUi(Generic[TWidget]):
|
|
|
350
358
|
style (Union[str, Path]): path to css file or inline style string
|
|
351
359
|
|
|
352
360
|
## usage
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
361
|
+
|
|
362
|
+
.. code-block:: python
|
|
363
|
+
# all children of the element will have red outline, excluding itself
|
|
364
|
+
with rxui.row().scoped_style("*", "outline: 1px solid red;") as row:
|
|
365
|
+
ui.label("Hello")
|
|
366
|
+
ui.label("World")
|
|
367
|
+
|
|
368
|
+
# all children of the element will have red outline, including the element itself
|
|
369
|
+
with rxui.row().scoped_style(":self *", "outline: 1px solid red;") as row:
|
|
370
|
+
ui.label("Hello")
|
|
371
|
+
ui.label("World")
|
|
372
|
+
|
|
373
|
+
# all children of the element will have red outline when element is hovered
|
|
374
|
+
with rxui.row().scoped_style(":hover *", "outline: 1px solid red;") as row:
|
|
375
|
+
ui.label("Hello")
|
|
376
|
+
ui.label("World")
|
|
377
|
+
|
|
378
|
+
# all children of the element and itself will have red outline when element is hovered
|
|
379
|
+
with rxui.row().scoped_style(":self:hover *", "outline: 1px solid red;") as row:
|
|
380
|
+
ui.label("Hello")
|
|
381
|
+
ui.label("World")
|
|
382
|
+
|
|
374
383
|
"""
|
|
375
384
|
|
|
376
385
|
is_css_file = isinstance(style, Path)
|
|
@@ -20,8 +20,8 @@ class BackgroundColorableMixin(Protocol):
|
|
|
20
20
|
def element(self) -> ui.element:
|
|
21
21
|
...
|
|
22
22
|
|
|
23
|
-
def _bind_background_color(self,
|
|
24
|
-
@self._ui_signal_on(
|
|
23
|
+
def _bind_background_color(self, value: TGetterOrReadonlyRef[str]):
|
|
24
|
+
@self._ui_signal_on(value, onchanges=False) # type: ignore
|
|
25
25
|
def _(state: WatchedState):
|
|
26
26
|
if state.previous is not None:
|
|
27
27
|
color_system.remove_background_color(self.element, state.previous)
|
|
@@ -30,12 +30,12 @@ class BackgroundColorableMixin(Protocol):
|
|
|
30
30
|
|
|
31
31
|
self.element.update()
|
|
32
32
|
|
|
33
|
-
def bind_color(self,
|
|
33
|
+
def bind_color(self, color: TGetterOrReadonlyRef[str]):
|
|
34
34
|
"""bind color to the element
|
|
35
35
|
|
|
36
36
|
Args:
|
|
37
|
-
|
|
37
|
+
color (TGetterOrReadonlyRef[str]): a reference to the color value
|
|
38
38
|
|
|
39
39
|
"""
|
|
40
|
-
self._bind_background_color(
|
|
40
|
+
self._bind_background_color(color)
|
|
41
41
|
return self
|
|
@@ -25,20 +25,20 @@ class DisableableMixin(Protocol):
|
|
|
25
25
|
def element(self) -> DisableableElement:
|
|
26
26
|
...
|
|
27
27
|
|
|
28
|
-
def bind_enabled(self,
|
|
28
|
+
def bind_enabled(self, value: TGetterOrReadonlyRef[bool]):
|
|
29
29
|
@self._ui_effect
|
|
30
30
|
def _():
|
|
31
|
-
|
|
32
|
-
self.element.set_enabled(
|
|
33
|
-
self.element._handle_enabled_change(
|
|
31
|
+
raw_value = to_value(value)
|
|
32
|
+
self.element.set_enabled(raw_value)
|
|
33
|
+
self.element._handle_enabled_change(raw_value)
|
|
34
34
|
|
|
35
35
|
return self
|
|
36
36
|
|
|
37
|
-
def bind_disable(self,
|
|
37
|
+
def bind_disable(self, value: TGetterOrReadonlyRef[bool]):
|
|
38
38
|
@self._ui_effect
|
|
39
39
|
def _():
|
|
40
|
-
|
|
41
|
-
self.element.set_enabled(
|
|
42
|
-
self.element._handle_enabled_change(
|
|
40
|
+
raw_value = not to_value(value)
|
|
41
|
+
self.element.set_enabled(raw_value)
|
|
42
|
+
self.element._handle_enabled_change(raw_value)
|
|
43
43
|
|
|
44
44
|
return self
|
|
@@ -21,8 +21,8 @@ class TextColorableMixin(Protocol):
|
|
|
21
21
|
def element(self) -> ui.element:
|
|
22
22
|
...
|
|
23
23
|
|
|
24
|
-
def _bind_text_color(self,
|
|
25
|
-
@self._ui_signal_on(
|
|
24
|
+
def _bind_text_color(self, color: TGetterOrReadonlyRef[str]):
|
|
25
|
+
@self._ui_signal_on(color, onchanges=False) # type: ignore
|
|
26
26
|
def _(state: WatchedState):
|
|
27
27
|
if state.previous is not None:
|
|
28
28
|
color_system.remove_text_color(self.element, state.previous)
|
|
@@ -31,14 +31,14 @@ class TextColorableMixin(Protocol):
|
|
|
31
31
|
|
|
32
32
|
self.element.update()
|
|
33
33
|
|
|
34
|
-
def bind_color(self,
|
|
34
|
+
def bind_color(self, color: TGetterOrReadonlyRef[str]):
|
|
35
35
|
"""bind text color to the element
|
|
36
36
|
|
|
37
37
|
Args:
|
|
38
|
-
|
|
38
|
+
color (TGetterOrReadonlyRef[str]): a reference to the color value
|
|
39
39
|
|
|
40
40
|
"""
|
|
41
|
-
self._bind_text_color(
|
|
41
|
+
self._bind_text_color(color)
|
|
42
42
|
return self
|
|
43
43
|
|
|
44
44
|
|
|
@@ -52,15 +52,15 @@ class HtmlTextColorableMixin(Protocol):
|
|
|
52
52
|
def bind_style(self, style: Dict[str, TGetterOrReadonlyRef[Any]]):
|
|
53
53
|
...
|
|
54
54
|
|
|
55
|
-
def _bind_text_color(self,
|
|
56
|
-
return self.bind_style({"color":
|
|
55
|
+
def _bind_text_color(self, value: TGetterOrReadonlyRef[str]):
|
|
56
|
+
return self.bind_style({"color": value})
|
|
57
57
|
|
|
58
|
-
def bind_color(self,
|
|
58
|
+
def bind_color(self, color: TGetterOrReadonlyRef[str]):
|
|
59
59
|
"""bind text color to the element
|
|
60
60
|
|
|
61
61
|
Args:
|
|
62
|
-
|
|
62
|
+
color (TGetterOrReadonlyRef[str]): a reference to the color value
|
|
63
63
|
|
|
64
64
|
"""
|
|
65
|
-
self._bind_text_color(
|
|
65
|
+
self._bind_text_color(color)
|
|
66
66
|
return self
|
|
@@ -78,17 +78,17 @@ class AggridBindableUi(BindableUi[ui.aggrid]):
|
|
|
78
78
|
options = {"columnDefs": columnDefs, "rowData": rowData}
|
|
79
79
|
return cls(options, **org_kws)
|
|
80
80
|
|
|
81
|
-
def bind_prop(self, prop: str,
|
|
81
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef[Any]):
|
|
82
82
|
if prop == "options":
|
|
83
|
-
return self.bind_options(
|
|
83
|
+
return self.bind_options(value)
|
|
84
84
|
|
|
85
|
-
return super().bind_prop(prop,
|
|
85
|
+
return super().bind_prop(prop, value)
|
|
86
86
|
|
|
87
|
-
def bind_options(self,
|
|
87
|
+
def bind_options(self, options: TGetterOrReadonlyRef[List[Dict]]):
|
|
88
88
|
@self._ui_effect
|
|
89
89
|
def _():
|
|
90
90
|
ele = self.element
|
|
91
|
-
data = to_value(
|
|
91
|
+
data = to_value(options)
|
|
92
92
|
ele._props["options"].update(data)
|
|
93
93
|
ele.update()
|
|
94
94
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
|
|
3
|
+
from ex4nicegui.utils.signals import (
|
|
4
|
+
TGetterOrReadonlyRef,
|
|
5
|
+
_TMaybeRef as TMaybeRef,
|
|
6
|
+
)
|
|
7
|
+
from nicegui import ui
|
|
8
|
+
from .base import BindableUi
|
|
9
|
+
from ex4nicegui.reactive.mixins.backgroundColor import BackgroundColorableMixin
|
|
10
|
+
from ex4nicegui.reactive.mixins.textColor import TextColorableMixin
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AvatarBindableUi(
|
|
14
|
+
BindableUi[ui.avatar], TextColorableMixin, BackgroundColorableMixin
|
|
15
|
+
):
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
icon: Optional[TMaybeRef[str]] = None,
|
|
19
|
+
*,
|
|
20
|
+
color: Optional[TMaybeRef[str]] = "primary",
|
|
21
|
+
text_color: Optional[TMaybeRef[str]] = None,
|
|
22
|
+
size: Optional[TMaybeRef[str]] = None,
|
|
23
|
+
font_size: Optional[TMaybeRef[str]] = None,
|
|
24
|
+
square: TMaybeRef[bool] = False,
|
|
25
|
+
rounded: TMaybeRef[bool] = False,
|
|
26
|
+
) -> None:
|
|
27
|
+
"""Avatar
|
|
28
|
+
|
|
29
|
+
A avatar element wrapping Quasar's
|
|
30
|
+
`QAvatar <https://quasar.dev/vue-components/avatar>`_ component.
|
|
31
|
+
|
|
32
|
+
:param icon: name of the icon or image path with "img:" prefix (e.g. "map", "img:path/to/image.png")
|
|
33
|
+
:param color: background color (either a Quasar, Tailwind, or CSS color or `None`, default: "primary")
|
|
34
|
+
:param text_color: color name from the Quasar Color Palette (e.g. "primary", "teal-10")
|
|
35
|
+
:param size: size in CSS units, including unit name or standard size name (xs|sm|md|lg|xl) (e.g. "16px", "2rem")
|
|
36
|
+
:param font_size: size in CSS units, including unit name, of the content (icon, text) (e.g. "18px", "2rem")
|
|
37
|
+
:param square: removes border-radius so borders are squared (default: False)
|
|
38
|
+
:param rounded: applies a small standard border-radius for a squared shape of the component (default: False)
|
|
39
|
+
"""
|
|
40
|
+
pc = ParameterClassifier(
|
|
41
|
+
locals(),
|
|
42
|
+
maybeRefs=[
|
|
43
|
+
"icon",
|
|
44
|
+
"color",
|
|
45
|
+
"text_color",
|
|
46
|
+
"size",
|
|
47
|
+
"font_size",
|
|
48
|
+
"square",
|
|
49
|
+
"rounded",
|
|
50
|
+
],
|
|
51
|
+
events=[],
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
init_kws = pc.get_values_kws()
|
|
55
|
+
element = ui.avatar(**init_kws)
|
|
56
|
+
super().__init__(element)
|
|
57
|
+
|
|
58
|
+
for key, value in pc.get_bindings().items():
|
|
59
|
+
self.bind_prop(key, value) # type: ignore
|
|
60
|
+
|
|
61
|
+
def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
|
|
62
|
+
if prop == "color":
|
|
63
|
+
return self.bind_color(value)
|
|
64
|
+
if prop == "text-color":
|
|
65
|
+
return self.bind_text_color(value)
|
|
66
|
+
|
|
67
|
+
return super().bind_prop(prop, value)
|
|
68
|
+
|
|
69
|
+
def bind_color(self, color: TGetterOrReadonlyRef):
|
|
70
|
+
"""Binds the background color property of the chip to a ui element.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
color (TGetterOrReadonlyRef): background color ui element or getter function
|
|
74
|
+
|
|
75
|
+
"""
|
|
76
|
+
BackgroundColorableMixin.bind_color(self, color)
|
|
77
|
+
return self
|
|
78
|
+
|
|
79
|
+
def bind_text_color(self, color: TGetterOrReadonlyRef):
|
|
80
|
+
"""Binds the text color property of the chip to a ui element.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
color (TGetterOrReadonlyRef): text color ui element or getter function
|
|
84
|
+
"""
|
|
85
|
+
TextColorableMixin.bind_color(self, color)
|
|
86
|
+
return self
|