ex4nicegui 0.7.0__py3-none-any.whl → 0.8.0__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 (44) hide show
  1. ex4nicegui/reactive/EChartsComponent/ECharts.js +2 -3
  2. ex4nicegui/reactive/EChartsComponent/ECharts.py +2 -4
  3. ex4nicegui/reactive/__init__.py +6 -0
  4. ex4nicegui/reactive/base.py +3 -1
  5. ex4nicegui/reactive/mermaid/mermaid.py +2 -5
  6. ex4nicegui/reactive/mixins/backgroundColor.py +1 -1
  7. ex4nicegui/reactive/mixins/flexLayout.py +51 -0
  8. ex4nicegui/reactive/mixins/textColor.py +1 -1
  9. ex4nicegui/reactive/mixins/value_element.py +27 -0
  10. ex4nicegui/reactive/officials/avatar.py +86 -0
  11. ex4nicegui/reactive/officials/badge.py +102 -0
  12. ex4nicegui/reactive/officials/card.py +32 -2
  13. ex4nicegui/reactive/officials/checkbox.py +7 -12
  14. ex4nicegui/reactive/officials/chip.py +12 -3
  15. ex4nicegui/reactive/officials/circular_progress.py +7 -11
  16. ex4nicegui/reactive/officials/color_picker.py +4 -10
  17. ex4nicegui/reactive/officials/column.py +19 -11
  18. ex4nicegui/reactive/officials/date.py +4 -11
  19. ex4nicegui/reactive/officials/dialog.py +4 -11
  20. ex4nicegui/reactive/officials/echarts.py +10 -8
  21. ex4nicegui/reactive/officials/expansion.py +4 -11
  22. ex4nicegui/reactive/officials/icon.py +2 -8
  23. ex4nicegui/reactive/officials/image.py +1 -1
  24. ex4nicegui/reactive/officials/input.py +13 -14
  25. ex4nicegui/reactive/officials/knob.py +4 -13
  26. ex4nicegui/reactive/officials/label.py +6 -4
  27. ex4nicegui/reactive/officials/linear_progress.py +6 -11
  28. ex4nicegui/reactive/officials/number.py +8 -12
  29. ex4nicegui/reactive/officials/radio.py +5 -13
  30. ex4nicegui/reactive/officials/row.py +18 -11
  31. ex4nicegui/reactive/officials/select.py +2 -2
  32. ex4nicegui/reactive/officials/slider.py +4 -12
  33. ex4nicegui/reactive/officials/switch.py +5 -13
  34. ex4nicegui/reactive/officials/tab_panels.py +4 -8
  35. ex4nicegui/reactive/officials/tabs.py +4 -9
  36. ex4nicegui/reactive/officials/textarea.py +4 -10
  37. ex4nicegui/reactive/officials/toggle.py +88 -0
  38. ex4nicegui/reactive/officials/tooltip.py +1 -1
  39. ex4nicegui/reactive/systems/reactive_system.py +2 -2
  40. ex4nicegui/reactive/view_model.py +4 -4
  41. {ex4nicegui-0.7.0.dist-info → ex4nicegui-0.8.0.dist-info}/METADATA +157 -118
  42. {ex4nicegui-0.7.0.dist-info → ex4nicegui-0.8.0.dist-info}/RECORD +44 -39
  43. {ex4nicegui-0.7.0.dist-info → ex4nicegui-0.8.0.dist-info}/LICENSE +0 -0
  44. {ex4nicegui-0.7.0.dist-info → ex4nicegui-0.8.0.dist-info}/WHEEL +0 -0
@@ -1,3 +1,4 @@
1
+ import 'echarts'
1
2
  import { convertDynamicProperties } from "../../static/utils/dynamic_properties.js";
2
3
 
3
4
  function collectMapRegisterTask() {
@@ -54,10 +55,8 @@ const mapRegisterTasks = collectMapRegisterTask();
54
55
  export default {
55
56
  template: "<div></div>",
56
57
  async mounted() {
57
- await this.$nextTick(); // wait for Tailwind classes to be applied
58
-
58
+ await new Promise((resolve) => setTimeout(resolve, 0)); // wait for Tailwind classes to be applied
59
59
  this.chart = echarts.init(this.$el, this.theme);
60
-
61
60
  this.resizeObs = new ResizeObserver(this.chart.resize)
62
61
 
63
62
  // Prevent interruption of chart animations due to resize operations.
@@ -23,7 +23,7 @@ NG_ROOT = Path(nicegui.__file__).parent / "elements"
23
23
  libraries = [NG_ROOT / "lib/echarts/echarts.min.js"]
24
24
 
25
25
 
26
- class echarts(Element, component="ECharts.js", libraries=libraries): # type: ignore
26
+ class echarts(Element, component="ECharts.js", dependencies=libraries): # type: ignore
27
27
  def __init__(
28
28
  self,
29
29
  options: Optional[dict] = None,
@@ -112,7 +112,7 @@ class echarts(Element, component="ECharts.js", libraries=libraries): # type: ig
112
112
  self.run_method("echarts_on", ui_event_name, query)
113
113
 
114
114
  def run_chart_method(
115
- self, name: str, *args, timeout: float = 1, check_interval: float = 0.01
115
+ self, name: str, *args, timeout: float = 1
116
116
  ) -> AwaitableResponse:
117
117
  """Run a method of the JSONEditor instance.
118
118
 
@@ -124,7 +124,6 @@ class echarts(Element, component="ECharts.js", libraries=libraries): # type: ig
124
124
  :param name: name of the method (a prefix ":" indicates that the arguments are JavaScript expressions)
125
125
  :param args: arguments to pass to the method (Python objects or JavaScript expressions)
126
126
  :param timeout: timeout in seconds (default: 1 second)
127
- :param check_interval: interval in seconds to check for a response (default: 0.01 seconds)
128
127
 
129
128
  :return: AwaitableResponse that can be awaited to get the result of the method call
130
129
  """
@@ -133,5 +132,4 @@ class echarts(Element, component="ECharts.js", libraries=libraries): # type: ig
133
132
  name,
134
133
  *args,
135
134
  timeout=timeout,
136
- check_interval=check_interval,
137
135
  )
@@ -55,6 +55,9 @@ 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
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
58
61
 
59
62
  from .local_file_picker import local_file_picker
60
63
  from .UseDraggable.UseDraggable import use_draggable
@@ -132,4 +135,7 @@ __all__ = [
132
135
  "chip",
133
136
  "dialog",
134
137
  "tooltip",
138
+ "toggle",
139
+ "avatar",
140
+ "badge",
135
141
  ]
@@ -73,7 +73,9 @@ class BindableUi(Generic[TWidget]):
73
73
 
74
74
  @property
75
75
  def _ui_signal_on(self):
76
- return partial(on, scope=self._effect_scope)
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)
77
79
 
78
80
  def props(self, add: Optional[str] = None, *, remove: Optional[str] = None):
79
81
  cast(ui.element, self.element).props(add, remove=remove)
@@ -10,11 +10,9 @@ NG_ROOT = Path(nicegui.__file__).parent / "elements"
10
10
 
11
11
  EX4_LIBS_ROOT = Path(__file__).parent.parent.parent / "libs"
12
12
 
13
- exposed_libraries = [
13
+ dependencies = [
14
14
  NG_ROOT / "lib/mermaid/mermaid.esm.min.mjs",
15
15
  EX4_LIBS_ROOT / "d3/*.js",
16
- ]
17
- extra_libraries = [
18
16
  NG_ROOT / "lib/mermaid/*.js",
19
17
  ]
20
18
 
@@ -27,8 +25,7 @@ class NodeClickEventArguments(UiEventArguments):
27
25
  class Mermaid( # type: ignore
28
26
  ContentElement,
29
27
  component="mermaid.js",
30
- exposed_libraries=exposed_libraries, # type: ignore
31
- extra_libraries=extra_libraries, # type: ignore
28
+ dependencies=dependencies, # type: ignore
32
29
  ):
33
30
  CONTENT_PROP = "content"
34
31
 
@@ -21,7 +21,7 @@ class BackgroundColorableMixin(Protocol):
21
21
  ...
22
22
 
23
23
  def _bind_background_color(self, value: TGetterOrReadonlyRef[str]):
24
- @self._ui_signal_on(value) # type: ignore
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)
@@ -0,0 +1,51 @@
1
+ from typing import (
2
+ Any,
3
+ Callable,
4
+ Protocol,
5
+ )
6
+ from typing_extensions import Self
7
+ import signe
8
+ from ex4nicegui.utils.signals import to_value, TMaybeRef
9
+ from nicegui import ui
10
+
11
+
12
+ class FlexWrapMixin(Protocol):
13
+ _ui_signal_on: Callable[[Callable[..., Any]], signe.Effect[None]]
14
+
15
+ @property
16
+ def element(self) -> ui.element:
17
+ ...
18
+
19
+ def bind_style(self, classes) -> Self:
20
+ ...
21
+
22
+ def bind_wrap(self, value: TMaybeRef[bool]) -> Self:
23
+ return self.bind_style(
24
+ {"flex-wrap": lambda: "wrap" if to_value(value) else "nowrap"}
25
+ )
26
+
27
+ def _bind_specified_props(self, prop: str, value: TMaybeRef[Any]):
28
+ if prop == "wrap":
29
+ return self.bind_wrap(value)
30
+
31
+ return None
32
+
33
+
34
+ class FlexAlignItemsMixin(Protocol):
35
+ _ui_signal_on: Callable[[Callable[..., Any]], signe.Effect[None]]
36
+
37
+ @property
38
+ def element(self) -> ui.element:
39
+ ...
40
+
41
+ def bind_classes(self, classes) -> Self:
42
+ ...
43
+
44
+ def bind_align_items(self, value: TMaybeRef[str]):
45
+ return self.bind_classes(lambda: f"items-{to_value(value)}")
46
+
47
+ def _bind_specified_props(self, prop: str, value: TMaybeRef[Any]):
48
+ if prop == "align-items":
49
+ return self.bind_align_items(value)
50
+
51
+ return None
@@ -22,7 +22,7 @@ class TextColorableMixin(Protocol):
22
22
  ...
23
23
 
24
24
  def _bind_text_color(self, color: TGetterOrReadonlyRef[str]):
25
- @self._ui_signal_on(color) # type: ignore
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)
@@ -0,0 +1,27 @@
1
+ from typing import Any, Callable, Protocol, Generic, TypeVar
2
+ import signe
3
+ from ex4nicegui.utils.signals import to_value, TMaybeRef
4
+ from nicegui.elements.mixins.value_element import ValueElement
5
+
6
+ T = TypeVar("T", contravariant=True)
7
+
8
+
9
+ class ValueElementMixin(Protocol, Generic[T]):
10
+ _ui_signal_on: Callable[[Callable[..., Any]], signe.Effect[None]]
11
+
12
+ @property
13
+ def element(self) -> ValueElement:
14
+ ...
15
+
16
+ def bind_value(self, value: TMaybeRef[T]):
17
+ @self._ui_signal_on(value) # type: ignore
18
+ def _():
19
+ self.element.set_value(to_value(value))
20
+
21
+ return self
22
+
23
+ def _bind_specified_props(self, prop: str, value: TMaybeRef[T]):
24
+ if prop == "value":
25
+ return self.bind_value(value)
26
+
27
+ return None
@@ -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
@@ -0,0 +1,102 @@
1
+ from typing import 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 BadgeBindableUi(
15
+ BindableUi[ui.badge],
16
+ BackgroundColorableMixin,
17
+ TextColorableMixin,
18
+ ):
19
+ def __init__(
20
+ self,
21
+ text: TMaybeRef[str] = "",
22
+ *,
23
+ color: Optional[TMaybeRef[str]] = "primary",
24
+ text_color: Optional[TMaybeRef[str]] = None,
25
+ outline: TMaybeRef[bool] = False,
26
+ ) -> None:
27
+ """Badge
28
+
29
+ A badge element wrapping Quasar's
30
+ `QBadge <https://quasar.dev/vue-components/badge>`_ component.
31
+
32
+ :param text: the initial value of the text field
33
+ :param color: the color name for component (either a Quasar, Tailwind, or CSS color or `None`, default: "primary")
34
+ :param text_color: text color (either a Quasar, Tailwind, or CSS color or `None`, default: `None`)
35
+ :param outline: use 'outline' design (colored text and borders only) (default: False)
36
+ """
37
+ pc = ParameterClassifier(
38
+ locals(),
39
+ maybeRefs=[
40
+ "text",
41
+ "color",
42
+ "text_color",
43
+ "outline",
44
+ ],
45
+ events=[],
46
+ )
47
+
48
+ element = ui.badge(**pc.get_values_kws())
49
+ super().__init__(element)
50
+
51
+ for key, value in pc.get_bindings().items():
52
+ self.bind_prop(key, value) # type: ignore
53
+
54
+ @property
55
+ def text(self):
56
+ return self.element.text
57
+
58
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
59
+ if prop == "text":
60
+ return self.bind_text(value)
61
+
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
+
86
+ """
87
+ TextColorableMixin.bind_color(self, color)
88
+ return self
89
+
90
+ def bind_text(self, text: TGetterOrReadonlyRef):
91
+ """Binds the text property of the chip to a ui element.
92
+
93
+ Args:
94
+ text (TGetterOrReadonlyRef): text ui element or getter function
95
+
96
+ """
97
+
98
+ @self._ui_signal_on(text)
99
+ def _():
100
+ self.element.set_text(str(to_value(text)))
101
+
102
+ return self
@@ -1,18 +1,48 @@
1
1
  from typing import (
2
2
  Any,
3
+ Literal,
4
+ Optional,
3
5
  )
4
6
  from nicegui import ui
5
7
  from .base import BindableUi
8
+ from ex4nicegui.reactive.mixins.flexLayout import FlexAlignItemsMixin
9
+ from ex4nicegui.utils.signals import TMaybeRef
10
+ from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
6
11
 
7
12
 
8
- class CardBindableUi(BindableUi[ui.card]):
13
+ class CardBindableUi(BindableUi[ui.card], FlexAlignItemsMixin):
9
14
  def __init__(
10
15
  self,
16
+ align_items: Optional[
17
+ TMaybeRef[Literal["start", "end", "center", "baseline", "stretch"]]
18
+ ] = None,
11
19
  ) -> None:
12
- element = ui.card()
20
+ """Card
21
+
22
+ This element is based on Quasar's `QCard <https://quasar.dev/vue-components/card>`_ component.
23
+ It provides a container with a dropped shadow.
24
+
25
+ Note:
26
+ In contrast to this element,
27
+ the original QCard has no padding by default and hides outer borders and shadows of nested elements.
28
+ If you want the original behavior, use the `tight` method.
29
+
30
+ :param align_items: alignment of the items in the card ("start", "end", "center", "baseline", or "stretch"; default: `None`)
31
+ """
32
+ pc = ParameterClassifier(locals(), maybeRefs=["wrap", "align_items"], events=[])
33
+ element = ui.card(**pc.get_values_kws())
13
34
 
14
35
  super().__init__(element)
15
36
 
37
+ for key, value in pc.get_bindings().items():
38
+ self.bind_prop(key, value) # type: ignore
39
+
40
+ def bind_prop(self, prop: str, value: TMaybeRef):
41
+ if FlexAlignItemsMixin._bind_specified_props(self, prop, value):
42
+ return self
43
+
44
+ return super().bind_prop(prop, value)
45
+
16
46
  def __enter__(self):
17
47
  self.element.__enter__()
18
48
  return self
@@ -8,15 +8,18 @@ from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
8
8
  from ex4nicegui.utils.signals import (
9
9
  TGetterOrReadonlyRef,
10
10
  _TMaybeRef as TMaybeRef,
11
- to_value,
12
11
  )
13
12
  from nicegui import ui
14
13
  from .base import BindableUi, DisableableMixin
14
+ from ex4nicegui.reactive.mixins.value_element import ValueElementMixin
15
+
15
16
 
16
17
  T = TypeVar("T")
17
18
 
18
19
 
19
- class CheckboxBindableUi(BindableUi[ui.checkbox], DisableableMixin):
20
+ class CheckboxBindableUi(
21
+ BindableUi[ui.checkbox], DisableableMixin, ValueElementMixin[bool]
22
+ ):
20
23
  def __init__(
21
24
  self,
22
25
  text: TMaybeRef[str] = "",
@@ -44,15 +47,7 @@ class CheckboxBindableUi(BindableUi[ui.checkbox], DisableableMixin):
44
47
  return self.element.value
45
48
 
46
49
  def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
47
- if prop == "value":
48
- return self.bind_value(value)
50
+ if ValueElementMixin._bind_specified_props(self, prop, value):
51
+ return self
49
52
 
50
53
  return super().bind_prop(prop, value)
51
-
52
- def bind_value(self, value: TGetterOrReadonlyRef[bool]):
53
- @self._ui_effect
54
- def _():
55
- self.element.set_value(to_value(value))
56
- self.element.update()
57
-
58
- return self
@@ -9,12 +9,14 @@ from nicegui import ui
9
9
  from .base import BindableUi
10
10
  from ex4nicegui.reactive.mixins.backgroundColor import BackgroundColorableMixin
11
11
  from ex4nicegui.reactive.mixins.textColor import TextColorableMixin
12
+ from ex4nicegui.reactive.mixins.value_element import ValueElementMixin
12
13
 
13
14
 
14
15
  class ChipBindableUi(
15
16
  BindableUi[ui.chip],
16
17
  BackgroundColorableMixin,
17
18
  TextColorableMixin,
19
+ ValueElementMixin[bool],
18
20
  ):
19
21
  def __init__(
20
22
  self,
@@ -29,6 +31,7 @@ class ChipBindableUi(
29
31
  on_selection_change: Optional[Callable[..., Any]] = None,
30
32
  removable: TMaybeRef[bool] = False,
31
33
  on_value_change: Optional[Callable[..., Any]] = None,
34
+ value: TMaybeRef[bool] = True,
32
35
  ) -> None:
33
36
  pc = ParameterClassifier(
34
37
  locals(),
@@ -40,11 +43,15 @@ class ChipBindableUi(
40
43
  "selectable",
41
44
  "selected",
42
45
  "removable",
46
+ "value",
43
47
  ],
48
+ v_model=("value", "on_value_change"),
44
49
  events=["on_click", "on_selection_change", "on_value_change"],
45
50
  )
46
51
 
47
- element = ui.chip(**pc.get_values_kws())
52
+ kws = pc.get_values_kws()
53
+ kws.pop("value", None)
54
+ element = ui.chip(**kws)
48
55
  super().__init__(element)
49
56
 
50
57
  for key, value in pc.get_bindings().items():
@@ -55,6 +62,9 @@ class ChipBindableUi(
55
62
  return self.element.text
56
63
 
57
64
  def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
65
+ if ValueElementMixin._bind_specified_props(self, prop, value):
66
+ return self
67
+
58
68
  if prop == "text":
59
69
  return self.bind_text(value)
60
70
 
@@ -94,9 +104,8 @@ class ChipBindableUi(
94
104
 
95
105
  """
96
106
 
97
- @self._ui_effect
107
+ @self._ui_signal_on(text)
98
108
  def _():
99
109
  self.element.set_text(str(to_value(text)))
100
- self.element.update()
101
110
 
102
111
  return self
@@ -6,15 +6,18 @@ from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
6
6
  from ex4nicegui.utils.signals import (
7
7
  TGetterOrReadonlyRef,
8
8
  _TMaybeRef as TMaybeRef,
9
- to_value,
10
9
  )
11
10
  from nicegui import ui
12
11
  from .base import BindableUi, DisableableMixin
13
12
  from ex4nicegui.reactive.mixins.backgroundColor import BackgroundColorableMixin
13
+ from ex4nicegui.reactive.mixins.value_element import ValueElementMixin
14
14
 
15
15
 
16
16
  class CircularProgressBindableUi(
17
- BindableUi[ui.circular_progress], DisableableMixin, BackgroundColorableMixin
17
+ BindableUi[ui.circular_progress],
18
+ DisableableMixin,
19
+ BackgroundColorableMixin,
20
+ ValueElementMixin[float],
18
21
  ):
19
22
  def __init__(
20
23
  self,
@@ -50,16 +53,9 @@ class CircularProgressBindableUi(
50
53
  return self.element.value
51
54
 
52
55
  def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
53
- if prop == "value":
54
- return self.bind_value(value)
56
+ if ValueElementMixin._bind_specified_props(self, prop, value):
57
+ return self
55
58
  if prop == "color":
56
59
  return self.bind_color(value)
57
60
 
58
61
  return super().bind_prop(prop, value)
59
-
60
- def bind_value(self, value: TGetterOrReadonlyRef[float]):
61
- @self._ui_effect
62
- def _():
63
- self.element.set_value(to_value(value))
64
-
65
- return self
@@ -5,6 +5,7 @@ from typing import (
5
5
  cast,
6
6
  )
7
7
  from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
8
+ from ex4nicegui.reactive.mixins.value_element import ValueElementMixin
8
9
 
9
10
  from ex4nicegui.utils.signals import (
10
11
  TGetterOrReadonlyRef,
@@ -18,7 +19,7 @@ from nicegui.events import handle_event
18
19
  from .base import BindableUi
19
20
 
20
21
 
21
- class ColorPickerBindableUi(BindableUi[ui.color_picker]):
22
+ class ColorPickerBindableUi(BindableUi[ui.color_picker], ValueElementMixin[bool]):
22
23
  def __init__(
23
24
  self,
24
25
  color: TMaybeRef[str] = "",
@@ -69,8 +70,8 @@ class ColorPickerBindableUi(BindableUi[ui.color_picker]):
69
70
  return self.element.value
70
71
 
71
72
  def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
72
- if prop == "value":
73
- return self.bind_value(value)
73
+ if ValueElementMixin._bind_specified_props(self, prop, value):
74
+ return self
74
75
 
75
76
  return super().bind_prop(prop, value)
76
77
 
@@ -81,13 +82,6 @@ class ColorPickerBindableUi(BindableUi[ui.color_picker]):
81
82
 
82
83
  return self
83
84
 
84
- def bind_value(self, value: TGetterOrReadonlyRef[bool]):
85
- @self._ui_effect
86
- def _():
87
- self.element.set_value(to_value(value))
88
-
89
- return self
90
-
91
85
 
92
86
  class ColorPickerLazyBindableUi(ColorPickerBindableUi):
93
87
  def __init__(
@@ -1,18 +1,27 @@
1
1
  from typing import (
2
2
  Any,
3
+ Literal,
4
+ Optional,
3
5
  )
4
6
  from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
7
+ from ex4nicegui.reactive.mixins.flexLayout import FlexAlignItemsMixin, FlexWrapMixin
5
8
  from ex4nicegui.utils.signals import (
6
- TGetterOrReadonlyRef,
7
- _TMaybeRef as TMaybeRef,
9
+ TMaybeRef,
8
10
  )
9
11
  from nicegui import ui
10
12
  from .base import BindableUi
11
13
 
12
14
 
13
- class ColumnBindableUi(BindableUi[ui.column]):
14
- def __init__(self, *, wrap: TMaybeRef[bool] = True) -> None:
15
- pc = ParameterClassifier(locals(), maybeRefs=["wrap"], events=[])
15
+ class ColumnBindableUi(BindableUi[ui.column], FlexAlignItemsMixin, FlexWrapMixin):
16
+ def __init__(
17
+ self,
18
+ *,
19
+ wrap: TMaybeRef[bool] = True,
20
+ align_items: Optional[
21
+ TMaybeRef[Literal["start", "end", "center", "baseline", "stretch"]]
22
+ ] = None,
23
+ ) -> None:
24
+ pc = ParameterClassifier(locals(), maybeRefs=["wrap", "align_items"], events=[])
16
25
  element = ui.column(**pc.get_values_kws())
17
26
 
18
27
  super().__init__(element)
@@ -20,15 +29,14 @@ class ColumnBindableUi(BindableUi[ui.column]):
20
29
  for key, value in pc.get_bindings().items():
21
30
  self.bind_prop(key, value) # type: ignore
22
31
 
23
- def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
24
- if prop == "wrap":
25
- return self.bind_wrap(value)
32
+ def bind_prop(self, prop: str, value: TMaybeRef):
33
+ if FlexAlignItemsMixin._bind_specified_props(self, prop, value):
34
+ return self
35
+ if FlexWrapMixin._bind_specified_props(self, prop, value):
36
+ return self
26
37
 
27
38
  return super().bind_prop(prop, value)
28
39
 
29
- def bind_wrap(self, value: TGetterOrReadonlyRef):
30
- self.bind_classes({"wrap": value})
31
-
32
40
  def __enter__(self):
33
41
  self.element.__enter__()
34
42
  return self