ex4nicegui 0.6.7__py3-none-any.whl → 0.6.9__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.
Files changed (75) hide show
  1. ex4nicegui/__init__.py +12 -6
  2. ex4nicegui/gsap/__init__.py +11 -0
  3. ex4nicegui/helper/__init__.py +4 -0
  4. ex4nicegui/helper/client_instance_locker.py +31 -0
  5. ex4nicegui/reactive/__init__.py +4 -0
  6. ex4nicegui/reactive/base.py +426 -0
  7. ex4nicegui/reactive/deferredTask.py +3 -2
  8. ex4nicegui/reactive/local_file_picker.py +1 -2
  9. ex4nicegui/reactive/mixins/backgroundColor.py +41 -0
  10. ex4nicegui/reactive/mixins/disableable.py +44 -0
  11. ex4nicegui/reactive/mixins/textColor.py +66 -0
  12. ex4nicegui/reactive/officials/aggrid.py +4 -4
  13. ex4nicegui/reactive/officials/base.py +4 -351
  14. ex4nicegui/reactive/officials/button.py +36 -3
  15. ex4nicegui/reactive/officials/checkbox.py +2 -3
  16. ex4nicegui/reactive/officials/chip.py +102 -0
  17. ex4nicegui/reactive/officials/circular_progress.py +6 -5
  18. ex4nicegui/reactive/officials/color_picker.py +3 -4
  19. ex4nicegui/reactive/officials/column.py +1 -1
  20. ex4nicegui/reactive/officials/date.py +2 -3
  21. ex4nicegui/reactive/officials/drawer.py +2 -3
  22. ex4nicegui/reactive/officials/echarts.py +2 -3
  23. ex4nicegui/reactive/officials/expansion.py +2 -3
  24. ex4nicegui/reactive/officials/grid.py +4 -3
  25. ex4nicegui/reactive/officials/html.py +1 -3
  26. ex4nicegui/reactive/officials/icon.py +5 -9
  27. ex4nicegui/reactive/officials/image.py +2 -4
  28. ex4nicegui/reactive/officials/input.py +4 -6
  29. ex4nicegui/reactive/officials/knob.py +6 -4
  30. ex4nicegui/reactive/officials/label.py +3 -10
  31. ex4nicegui/reactive/officials/linear_progress.py +5 -9
  32. ex4nicegui/reactive/officials/number.py +3 -6
  33. ex4nicegui/reactive/officials/radio.py +3 -5
  34. ex4nicegui/reactive/officials/row.py +1 -1
  35. ex4nicegui/reactive/officials/select.py +3 -5
  36. ex4nicegui/reactive/officials/slider.py +4 -6
  37. ex4nicegui/reactive/officials/switch.py +2 -4
  38. ex4nicegui/reactive/officials/tab.py +1 -1
  39. ex4nicegui/reactive/officials/tab_panel.py +1 -1
  40. ex4nicegui/reactive/officials/tab_panels.py +109 -3
  41. ex4nicegui/reactive/officials/table.py +7 -6
  42. ex4nicegui/reactive/officials/tabs.py +1 -1
  43. ex4nicegui/reactive/officials/textarea.py +3 -5
  44. ex4nicegui/reactive/officials/upload.py +2 -2
  45. ex4nicegui/reactive/q_pagination.py +2 -2
  46. ex4nicegui/reactive/scopedStyle.js +55 -0
  47. ex4nicegui/reactive/scopedStyle.py +25 -0
  48. ex4nicegui/reactive/services/pandas_service.py +31 -0
  49. ex4nicegui/reactive/{utils.py → services/reactive_service.py} +9 -67
  50. ex4nicegui/reactive/systems/color_system.py +157 -0
  51. ex4nicegui/reactive/systems/object_system.py +33 -0
  52. ex4nicegui/reactive/systems/reactive_system.py +21 -0
  53. ex4nicegui/reactive/useMouse/UseMouse.py +4 -4
  54. ex4nicegui/reactive/usePagination.py +1 -1
  55. ex4nicegui/reactive/vfor.py +1 -2
  56. ex4nicegui/reactive/vmodel.py +1 -1
  57. ex4nicegui/utils/apiEffect.py +5 -1
  58. ex4nicegui/utils/effect.py +3 -2
  59. ex4nicegui/utils/refComputed.py +147 -0
  60. ex4nicegui/utils/refWrapper.py +57 -0
  61. ex4nicegui/utils/scheduler.py +20 -4
  62. ex4nicegui/utils/signals.py +51 -192
  63. ex4nicegui/utils/types.py +16 -0
  64. ex4nicegui/version.py +3 -0
  65. {ex4nicegui-0.6.7.dist-info → ex4nicegui-0.6.9.dist-info}/METADATA +61 -4
  66. {ex4nicegui-0.6.7.dist-info → ex4nicegui-0.6.9.dist-info}/RECORD +68 -58
  67. ex4nicegui/reactive/EChartsComponent/__init__.py +0 -0
  68. ex4nicegui/reactive/UseDraggable/__init__.py +0 -0
  69. ex4nicegui/reactive/dropZone/__init__.py +0 -0
  70. ex4nicegui/reactive/mermaid/__init__.py +0 -0
  71. ex4nicegui/reactive/officials/__init__.py +0 -1
  72. ex4nicegui/reactive/officials/utils.py +0 -11
  73. ex4nicegui/reactive/useMouse/__init__.py +0 -0
  74. {ex4nicegui-0.6.7.dist-info → ex4nicegui-0.6.9.dist-info}/LICENSE +0 -0
  75. {ex4nicegui-0.6.7.dist-info → ex4nicegui-0.6.9.dist-info}/WHEEL +0 -0
@@ -0,0 +1,66 @@
1
+ from typing import (
2
+ Any,
3
+ Callable,
4
+ Dict,
5
+ Protocol,
6
+ )
7
+
8
+ import signe
9
+ from ex4nicegui.utils.signals import (
10
+ TGetterOrReadonlyRef,
11
+ WatchedState,
12
+ )
13
+ from nicegui import ui
14
+ from ex4nicegui.reactive.systems import color_system
15
+
16
+
17
+ class TextColorableMixin(Protocol):
18
+ _ui_signal_on: Callable[[Callable[[TGetterOrReadonlyRef[str]], Any]], signe.Effect]
19
+
20
+ @property
21
+ def element(self) -> ui.element:
22
+ ...
23
+
24
+ def _bind_text_color(self, ref_ui: TGetterOrReadonlyRef[str]):
25
+ @self._ui_signal_on(ref_ui) # type: ignore
26
+ def _(state: WatchedState):
27
+ if state.previous is not None:
28
+ color_system.remove_text_color(self.element, state.previous)
29
+
30
+ color_system.add_text_color(self.element, state.current)
31
+
32
+ self.element.update()
33
+
34
+ def bind_color(self, ref_ui: TGetterOrReadonlyRef[str]):
35
+ """bind text color to the element
36
+
37
+ Args:
38
+ ref_ui (TGetterOrReadonlyRef[str]): a reference to the color value
39
+
40
+ """
41
+ self._bind_text_color(ref_ui)
42
+ return self
43
+
44
+
45
+ class HtmlTextColorableMixin(Protocol):
46
+ _ui_signal_on: Callable[[Callable[[TGetterOrReadonlyRef[str]], Any]], signe.Effect]
47
+
48
+ @property
49
+ def element(self) -> ui.element:
50
+ ...
51
+
52
+ def bind_style(self, style: Dict[str, TGetterOrReadonlyRef[Any]]):
53
+ ...
54
+
55
+ def _bind_text_color(self, ref_ui: TGetterOrReadonlyRef[str]):
56
+ return self.bind_style({"color": ref_ui})
57
+
58
+ def bind_color(self, ref_ui: TGetterOrReadonlyRef[str]):
59
+ """bind text color to the element
60
+
61
+ Args:
62
+ ref_ui (TGetterOrReadonlyRef[str]): a reference to the color value
63
+
64
+ """
65
+ self._bind_text_color(ref_ui)
66
+ return self
@@ -9,13 +9,13 @@ from ex4nicegui.utils.signals import (
9
9
  is_ref,
10
10
  ref_computed,
11
11
  to_value,
12
- _TMaybeRef as TMaybeRef,
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.utils import ParameterClassifier, dataframe2col_str
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
- @ui_effect
88
+ @self._ui_effect
89
89
  def _():
90
90
  ele = self.element
91
91
  data = to_value(ref_ui)
@@ -1,352 +1,5 @@
1
- from __future__ import annotations
2
-
3
- from typing import (
4
- Any,
5
- Callable,
6
- Dict,
7
- List,
8
- Optional,
9
- Protocol,
10
- TypeVar,
11
- Generic,
12
- Union,
13
- cast,
14
- Literal,
1
+ from ex4nicegui.reactive.base import (
2
+ BindableUi, # noqa: F401
3
+ DisableableMixin, # noqa: F401
4
+ DisableableBindableUi, # noqa: F401
15
5
  )
16
-
17
- from typing_extensions import Self
18
- from ex4nicegui.utils.apiEffect import ui_effect
19
- import signe
20
- from ex4nicegui.utils.signals import (
21
- TGetterOrReadonlyRef,
22
- effect,
23
- to_value,
24
- is_ref,
25
- WatchedState,
26
- on,
27
- )
28
- from nicegui import Tailwind, ui
29
- from nicegui.elements.mixins.color_elements import (
30
- TextColorElement,
31
- QUASAR_COLORS,
32
- TAILWIND_COLORS,
33
- )
34
- from nicegui.elements.mixins.text_element import TextElement
35
- from nicegui.elements.mixins.disableable_element import DisableableElement
36
-
37
-
38
- T = TypeVar("T")
39
-
40
-
41
- TWidget = TypeVar("TWidget", bound=ui.element)
42
-
43
- _T_bind_classes_type_dict = Dict[str, TGetterOrReadonlyRef[bool]]
44
- _T_bind_classes_type_ref_dict = TGetterOrReadonlyRef[Dict[str, bool]]
45
- _T_bind_classes_type_array = List[TGetterOrReadonlyRef[str]]
46
-
47
-
48
- _T_bind_classes_type = Union[
49
- _T_bind_classes_type_dict, _T_bind_classes_type_ref_dict, _T_bind_classes_type_array
50
- ]
51
-
52
-
53
- class BindableUi(Generic[TWidget]):
54
- def __init__(self, element: TWidget) -> None:
55
- self._element = element
56
- self.tailwind = Tailwind(cast(ui.element, self._element))
57
-
58
- def _ui_effect(self, fn: Callable):
59
- return ui_effect(fn)
60
-
61
- def props(self, add: Optional[str] = None, *, remove: Optional[str] = None):
62
- cast(ui.element, self.element).props(add, remove=remove)
63
- return self
64
-
65
- def classes(
66
- self,
67
- add: Optional[str] = None,
68
- *,
69
- remove: Optional[str] = None,
70
- replace: Optional[str] = None,
71
- ):
72
- cast(ui.element, self.element).classes(add, remove=remove, replace=replace)
73
- return self
74
-
75
- def style(
76
- self,
77
- add: Optional[str] = None,
78
- *,
79
- remove: Optional[str] = None,
80
- replace: Optional[str] = None,
81
- ):
82
- cast(ui.element, self.element).style(add, remove=remove, replace=replace)
83
- return self
84
-
85
- def __enter__(self) -> Self:
86
- self.element.__enter__()
87
- return self
88
-
89
- def __exit__(self, *_):
90
- self.element.default_slot.__exit__(*_)
91
-
92
- def tooltip(self, text: str) -> Self:
93
- cast(ui.element, self.element).tooltip(text)
94
- return self
95
-
96
- def add_slot(self, name: str, template: Optional[str] = None):
97
- """Add a slot to the element.
98
-
99
- :param name: name of the slot
100
- :param template: Vue template of the slot
101
- :return: the slot
102
- """
103
- return cast(ui.element, self.element).add_slot(name, template)
104
-
105
- @property
106
- def element(self):
107
- return self._element
108
-
109
- def delete(self) -> None:
110
- """Delete the element."""
111
- self.delete()
112
-
113
- def move(
114
- self, target_container: Optional[ui.element] = None, target_index: int = -1
115
- ):
116
- """Move the element to another container.
117
-
118
- :param target_container: container to move the element to (default: the parent container)
119
- :param target_index: index within the target slot (default: append to the end)
120
- """
121
- return self.move(target_container, target_index)
122
-
123
- def remove(self, element: Union[ui.element, int]) -> None:
124
- """Remove a child element.
125
-
126
- :param element: either the element instance or its ID
127
- """
128
- return self.element.remove(element)
129
-
130
- def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef[Any]):
131
- """data binding is manipulating an element's property
132
-
133
- @see - https://github.com/CrystalWindSnake/ex4nicegui/blob/main/README.en.md#bind_prop
134
- @中文文档 - https://gitee.com/carson_add/ex4nicegui/tree/main/#bind_prop
135
-
136
- Args:
137
- prop (str): property name
138
- ref_ui (TGetterOrReadonlyRef[Any]): a reference to the value to bind to
139
-
140
- """
141
- if prop == "visible":
142
- return self.bind_visible(ref_ui)
143
-
144
- if prop == "text" and isinstance(self.element, TextElement):
145
-
146
- @self._ui_effect
147
- def _():
148
- cast(TextElement, self.element).set_text(to_value(ref_ui))
149
- self.element.update()
150
-
151
- @self._ui_effect
152
- def _():
153
- element = cast(ui.element, self.element)
154
- element._props[prop] = to_value(ref_ui)
155
- element.update()
156
-
157
- return self
158
-
159
- def bind_visible(self, ref_ui: TGetterOrReadonlyRef[bool]):
160
- @self._ui_effect
161
- def _():
162
- element = cast(ui.element, self.element)
163
- element.set_visibility(to_value(ref_ui))
164
-
165
- return self
166
-
167
- def bind_not_visible(self, ref_ui: TGetterOrReadonlyRef[bool]):
168
- return self.bind_visible(lambda: not to_value(ref_ui))
169
-
170
- def on(
171
- self,
172
- type: str,
173
- handler: Optional[Callable[..., Any]] = None,
174
- args: Optional[List[str]] = None,
175
- *,
176
- throttle: float = 0.0,
177
- leading_events: bool = True,
178
- trailing_events: bool = True,
179
- ):
180
- ele = cast(ui.element, self.element)
181
- ele.on(
182
- type,
183
- handler,
184
- args,
185
- throttle=throttle,
186
- leading_events=leading_events,
187
- trailing_events=trailing_events,
188
- )
189
-
190
- return self
191
-
192
- def clear(self) -> None:
193
- cast(ui.element, self.element).clear()
194
-
195
- def bind_classes(self, classes: _T_bind_classes_type):
196
- """data binding is manipulating an element's class list
197
-
198
- @see - https://github.com/CrystalWindSnake/ex4nicegui/blob/main/README.en.md#bind-class-names
199
- @中文文档 - https://gitee.com/carson_add/ex4nicegui/tree/main/#%E7%BB%91%E5%AE%9A%E7%B1%BB%E5%90%8D
200
-
201
- Args:
202
- classes (_T_bind_classes_type):
203
- """
204
- if isinstance(classes, dict):
205
- for name, ref_obj in classes.items():
206
-
207
- @self._ui_effect
208
- def _(name=name, ref_obj=ref_obj):
209
- if to_value(ref_obj):
210
- self.classes(add=name)
211
- else:
212
- self.classes(remove=name)
213
-
214
- elif is_ref(classes) or isinstance(classes, Callable):
215
- ref_obj = to_value(classes) # type: ignore
216
- assert isinstance(ref_obj, dict)
217
-
218
- @effect
219
- def _():
220
- for name, value in cast(Dict, to_value(classes)).items(): # type: ignore
221
- if value:
222
- self.classes(add=name)
223
- else:
224
- self.classes(remove=name)
225
- elif isinstance(classes, list):
226
- for ref_name in classes:
227
- if is_ref(ref_name) or isinstance(ref_name, Callable):
228
-
229
- @on(ref_name)
230
- def _(state: WatchedState):
231
- self.classes(add=state.current, remove=state.previous)
232
- else:
233
- self.classes(ref_name) # type: ignore
234
-
235
- return self
236
-
237
- def bind_style(self, style: Dict[str, TGetterOrReadonlyRef[Any]]):
238
- """data binding is manipulating an element's style
239
-
240
- @see - https://github.com/CrystalWindSnake/ex4nicegui/blob/main/README.en.md#bind-style
241
- @中文文档 - https://gitee.com/carson_add/ex4nicegui/tree/main/#bind-style
242
-
243
- Args:
244
- style (Dict[str, Union[ReadonlyRef[str], Ref[str]]]): _description_
245
- """
246
- if isinstance(style, dict):
247
- for name, ref_obj in style.items():
248
- if is_ref(ref_obj) or isinstance(ref_obj, Callable):
249
-
250
- @self._ui_effect
251
- def _(name=name, ref_obj=ref_obj):
252
- self.element._style[name] = str(to_value(ref_obj))
253
- self.element.update()
254
-
255
- return self
256
-
257
- def update(self):
258
- """Update the element on the client side."""
259
- self.element.update()
260
-
261
-
262
- # class SingleValueBindableUi(BindableUi[TWidget], Generic[T, TWidget]):
263
- # def __init__(self, value: TMaybeRef[T], element: TWidget) -> None:
264
- # super().__init__(element)
265
- # self._ref = to_ref(value)
266
-
267
- # @property
268
- # def value(self) -> T:
269
- # return self._ref.value # type: ignore
270
-
271
- # def bind_ref(self, ref: TRef[T]):
272
- # @effect
273
- # def _():
274
- # ref.value = self._ref.value # type: ignore
275
-
276
- # return self
277
-
278
-
279
- _T_DisableableBinder = TypeVar("_T_DisableableBinder", bound=DisableableElement)
280
-
281
-
282
- class DisableableMixin(Protocol):
283
- _ui_effect: Callable[[Callable[..., Any]], signe.Effect[None]]
284
-
285
- @property
286
- def element(self) -> DisableableElement:
287
- ...
288
-
289
- def bind_enabled(self, ref_ui: TGetterOrReadonlyRef[bool]):
290
- @self._ui_effect
291
- def _():
292
- value = to_value(ref_ui)
293
- self.element.set_enabled(value)
294
- self.element._handle_enabled_change(value)
295
-
296
- return self
297
-
298
- def bind_disable(self, ref_ui: TGetterOrReadonlyRef[bool]):
299
- @self._ui_effect
300
- def _():
301
- value = not to_value(ref_ui)
302
- self.element.set_enabled(value)
303
- self.element._handle_enabled_change(value)
304
-
305
- return self
306
-
307
-
308
- 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,17 +3,28 @@ from typing import (
3
3
  Callable,
4
4
  Optional,
5
5
  )
6
- from ex4nicegui.reactive.utils import ParameterClassifier
6
+ from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
7
7
  from ex4nicegui.utils.signals import (
8
8
  TGetterOrReadonlyRef,
9
9
  _TMaybeRef as TMaybeRef,
10
10
  to_value,
11
11
  )
12
12
  from nicegui import ui
13
- from .base import BindableUi, DisableableMixin
13
+ from .base import (
14
+ BindableUi,
15
+ DisableableMixin,
16
+ )
17
+
18
+ from ex4nicegui.reactive.mixins.backgroundColor import BackgroundColorableMixin
19
+ from ex4nicegui.reactive.mixins.textColor import TextColorableMixin
14
20
 
15
21
 
16
- class ButtonBindableUi(BindableUi[ui.button], DisableableMixin):
22
+ class ButtonBindableUi(
23
+ BindableUi[ui.button],
24
+ DisableableMixin,
25
+ BackgroundColorableMixin,
26
+ TextColorableMixin,
27
+ ):
17
28
  def __init__(
18
29
  self,
19
30
  text: TMaybeRef[str] = "",
@@ -38,9 +49,31 @@ class ButtonBindableUi(BindableUi[ui.button], DisableableMixin):
38
49
  return self.bind_text(ref_ui)
39
50
  if prop == "icon":
40
51
  return self.bind_icon(ref_ui)
52
+ if prop == "color":
53
+ return self.bind_color(ref_ui)
41
54
 
42
55
  return super().bind_prop(prop, ref_ui)
43
56
 
57
+ def bind_color(self, ref_ui: TGetterOrReadonlyRef[str]):
58
+ """Binds the background color of the button.
59
+
60
+ Args:
61
+ ref_ui (TGetterOrReadonlyRef[str]): Getter or readonly reference to the color.
62
+
63
+ """
64
+ BackgroundColorableMixin.bind_color(self, ref_ui)
65
+ return self
66
+
67
+ def bind_text_color(self, ref_ui: TGetterOrReadonlyRef[str]):
68
+ """Binds the text color of the button.
69
+
70
+ Args:
71
+ ref_ui (TGetterOrReadonlyRef[str]): Getter or readonly reference to the color.
72
+
73
+ """
74
+ TextColorableMixin.bind_color(self, ref_ui)
75
+ return self
76
+
44
77
  def bind_text(self, ref_ui: TGetterOrReadonlyRef):
45
78
  @self._ui_effect
46
79
  def _():
@@ -4,8 +4,7 @@ from typing import (
4
4
  Optional,
5
5
  TypeVar,
6
6
  )
7
- from ex4nicegui.reactive.utils import ParameterClassifier
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
- @ui_effect
53
+ @self._ui_effect
55
54
  def _():
56
55
  self.element.set_value(to_value(ref_ui))
57
56
  self.element.update()
@@ -0,0 +1,102 @@
1
+ from typing import Any, Callable, Optional
2
+ from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
3
+ from ex4nicegui.utils.signals import (
4
+ TGetterOrReadonlyRef,
5
+ to_value,
6
+ _TMaybeRef as TMaybeRef,
7
+ )
8
+ from nicegui import ui
9
+ from .base import BindableUi
10
+ from ex4nicegui.reactive.mixins.backgroundColor import BackgroundColorableMixin
11
+ from ex4nicegui.reactive.mixins.textColor import TextColorableMixin
12
+
13
+
14
+ class ChipBindableUi(
15
+ BindableUi[ui.chip],
16
+ BackgroundColorableMixin,
17
+ TextColorableMixin,
18
+ ):
19
+ def __init__(
20
+ self,
21
+ text: TMaybeRef[str] = "",
22
+ *,
23
+ icon: Optional[TMaybeRef[str]] = None,
24
+ color: Optional[TMaybeRef[str]] = "primary",
25
+ text_color: Optional[TMaybeRef[str]] = None,
26
+ on_click: Optional[Callable[..., Any]] = None,
27
+ selectable: TMaybeRef[bool] = False,
28
+ selected: TMaybeRef[bool] = False,
29
+ on_selection_change: Optional[Callable[..., Any]] = None,
30
+ removable: TMaybeRef[bool] = False,
31
+ on_value_change: Optional[Callable[..., Any]] = None,
32
+ ) -> None:
33
+ pc = ParameterClassifier(
34
+ locals(),
35
+ maybeRefs=[
36
+ "text",
37
+ "icon",
38
+ "color",
39
+ "text_color",
40
+ "selectable",
41
+ "selected",
42
+ "removable",
43
+ ],
44
+ events=["on_click", "on_selection_change", "on_value_change"],
45
+ )
46
+
47
+ element = ui.chip(**pc.get_values_kws())
48
+ super().__init__(element)
49
+
50
+ for key, value in pc.get_bindings().items():
51
+ self.bind_prop(key, value) # type: ignore
52
+
53
+ @property
54
+ def text(self):
55
+ return self.element.text
56
+
57
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
58
+ if prop == "text":
59
+ return self.bind_text(ref_ui)
60
+
61
+ if prop == "color":
62
+ return self.bind_color(ref_ui)
63
+ if prop == "text-color":
64
+ return self.bind_text_color(ref_ui)
65
+
66
+ return super().bind_prop(prop, ref_ui)
67
+
68
+ def bind_color(self, color: TGetterOrReadonlyRef):
69
+ """Binds the background color property of the chip to a ui element.
70
+
71
+ Args:
72
+ color (TGetterOrReadonlyRef): background color ui element or getter function
73
+
74
+ """
75
+ BackgroundColorableMixin.bind_color(self, color)
76
+ return self
77
+
78
+ def bind_text_color(self, color: TGetterOrReadonlyRef):
79
+ """Binds the text color property of the chip to a ui element.
80
+
81
+ Args:
82
+ color (TGetterOrReadonlyRef): text color ui element or getter function
83
+
84
+
85
+ """
86
+ TextColorableMixin.bind_color(self, color)
87
+ return self
88
+
89
+ def bind_text(self, text: TGetterOrReadonlyRef):
90
+ """Binds the text property of the chip to a ui element.
91
+
92
+ Args:
93
+ text (TGetterOrReadonlyRef): text ui element or getter function
94
+
95
+ """
96
+
97
+ @self._ui_effect
98
+ def _():
99
+ self.element.set_text(str(to_value(text)))
100
+ self.element.update()
101
+
102
+ return self
@@ -1,8 +1,7 @@
1
1
  from typing import (
2
2
  Optional,
3
3
  )
4
- from ex4nicegui.reactive.utils import ParameterClassifier
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,
@@ -11,11 +10,11 @@ from ex4nicegui.utils.signals import (
11
10
  )
12
11
  from nicegui import ui
13
12
  from .base import BindableUi, DisableableMixin
13
+ from ex4nicegui.reactive.mixins.backgroundColor import BackgroundColorableMixin
14
14
 
15
15
 
16
16
  class CircularProgressBindableUi(
17
- BindableUi[ui.circular_progress],
18
- DisableableMixin,
17
+ BindableUi[ui.circular_progress], DisableableMixin, BackgroundColorableMixin
19
18
  ):
20
19
  def __init__(
21
20
  self,
@@ -53,11 +52,13 @@ class CircularProgressBindableUi(
53
52
  def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
54
53
  if prop == "value":
55
54
  return self.bind_value(ref_ui)
55
+ if prop == "color":
56
+ return self.bind_color(ref_ui)
56
57
 
57
58
  return super().bind_prop(prop, ref_ui)
58
59
 
59
60
  def bind_value(self, ref_ui: TGetterOrReadonlyRef[float]):
60
- @ui_effect
61
+ @self._ui_effect
61
62
  def _():
62
63
  self.element.set_value(to_value(ref_ui))
63
64
 
@@ -4,8 +4,7 @@ from typing import (
4
4
  Optional,
5
5
  cast,
6
6
  )
7
- from ex4nicegui.reactive.utils import ParameterClassifier
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
- @ui_effect
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
- @ui_effect
85
+ @self._ui_effect
87
86
  def _():
88
87
  self.element.set_value(to_value(ref_ui))
89
88