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.
Files changed (36) hide show
  1. ex4nicegui/__init__.py +1 -1
  2. ex4nicegui/reactive/__index.py +1 -31
  3. ex4nicegui/reactive/officials/__init__.py +37 -0
  4. ex4nicegui/reactive/officials/aggrid.py +81 -0
  5. ex4nicegui/reactive/officials/base.py +167 -0
  6. ex4nicegui/reactive/officials/button.py +86 -0
  7. ex4nicegui/reactive/officials/card.py +59 -0
  8. ex4nicegui/reactive/officials/checkbox.py +68 -0
  9. ex4nicegui/reactive/officials/color_picker.py +101 -0
  10. ex4nicegui/reactive/officials/date.py +85 -0
  11. ex4nicegui/reactive/officials/drawer.py +88 -0
  12. ex4nicegui/reactive/officials/echarts.py +70 -0
  13. ex4nicegui/reactive/officials/html.py +66 -0
  14. ex4nicegui/reactive/officials/icon.py +62 -0
  15. ex4nicegui/reactive/officials/image.py +54 -0
  16. ex4nicegui/reactive/officials/input.py +116 -0
  17. ex4nicegui/reactive/officials/label.py +67 -0
  18. ex4nicegui/reactive/officials/radio.py +80 -0
  19. ex4nicegui/reactive/officials/row.py +21 -0
  20. ex4nicegui/reactive/officials/select.py +93 -0
  21. ex4nicegui/reactive/officials/slider.py +97 -0
  22. ex4nicegui/reactive/officials/switch.py +72 -0
  23. ex4nicegui/reactive/officials/table.py +144 -0
  24. ex4nicegui/reactive/officials/textarea.py +103 -0
  25. ex4nicegui/reactive/officials/upload.py +78 -0
  26. ex4nicegui/reactive/officials/utils.py +11 -0
  27. {ex4nicegui-0.2.3.dist-info → ex4nicegui-0.2.5.dist-info}/METADATA +1 -1
  28. ex4nicegui-0.2.5.dist-info/RECORD +56 -0
  29. ex4nicegui/reactive/officials.py +0 -1585
  30. ex4nicegui-0.2.3.dist-info/RECORD +0 -33
  31. {ex4nicegui-0.2.3.data → ex4nicegui-0.2.5.data}/data/ECharts/ECharts.js +0 -0
  32. {ex4nicegui-0.2.3.data → ex4nicegui-0.2.5.data}/data/UseDraggable/UseDraggable.js +0 -0
  33. {ex4nicegui-0.2.3.data → ex4nicegui-0.2.5.data}/data/useMouse/UseMouse.js +0 -0
  34. {ex4nicegui-0.2.3.dist-info → ex4nicegui-0.2.5.dist-info}/LICENSE +0 -0
  35. {ex4nicegui-0.2.3.dist-info → ex4nicegui-0.2.5.dist-info}/WHEEL +0 -0
  36. {ex4nicegui-0.2.3.dist-info → ex4nicegui-0.2.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,85 @@
1
+ from typing import Any, Callable, List, Optional, TypeVar, cast
2
+ from typing_extensions import TypedDict
3
+ from signe import effect
4
+ from ex4nicegui.utils.signals import (
5
+ ReadonlyRef,
6
+ is_ref,
7
+ _TMaybeRef as TMaybeRef,
8
+ )
9
+ from nicegui import ui
10
+ from .base import SingleValueBindableUi
11
+ from .utils import _convert_kws_ref2value
12
+
13
+
14
+ _TDateRange = TypedDict("_TDateRange", {"from": str, "to": str})
15
+
16
+ _TDateValue = TypeVar(
17
+ "_TDateValue", str, List[str], _TDateRange, List[_TDateRange], None
18
+ )
19
+
20
+
21
+ class DateBindableUi(SingleValueBindableUi[_TDateValue, ui.date]):
22
+ def __init__(
23
+ self,
24
+ value: Optional[TMaybeRef[_TDateValue]] = None,
25
+ *,
26
+ mask: TMaybeRef[str] = "YYYY-MM-DD",
27
+ on_change: Optional[Callable[..., Any]] = None,
28
+ ) -> None:
29
+ """Date Input
30
+
31
+ This element is based on Quasar's `QDate <https://quasar.dev/vue-components/date>`_ component.
32
+ The date is a string in the format defined by the `mask` parameter.
33
+
34
+ You can also use the `range` or `multiple` props to select a range of dates or multiple dates::
35
+
36
+ ui.date({'from': '2023-01-01', 'to': '2023-01-05'}).props('range')
37
+ ui.date(['2023-01-01', '2023-01-02', '2023-01-03']).props('multiple')
38
+ ui.date([{'from': '2023-01-01', 'to': '2023-01-05'}, '2023-01-07']).props('multiple range')
39
+
40
+ :param value: the initial date
41
+ :param mask: the format of the date string (default: 'YYYY-MM-DD')
42
+ :param on_change: callback to execute when changing the date
43
+ """
44
+ kws = {
45
+ "value": value,
46
+ "mask": mask,
47
+ "on_change": on_change,
48
+ }
49
+
50
+ value_kws = _convert_kws_ref2value(kws)
51
+
52
+ element = ui.date(**value_kws)
53
+
54
+ super().__init__(value, element) # type: ignore
55
+
56
+ for key, value in kws.items():
57
+ if is_ref(value) and key != "value":
58
+ self.bind_prop(key, value) # type: ignore
59
+
60
+ self._ex_setup()
61
+
62
+ def _ex_setup(self):
63
+ ele = self.element
64
+
65
+ @effect
66
+ def _():
67
+ ele.value = self.value
68
+
69
+ def onModelValueChanged(e):
70
+ self._ref.value = e.args[0] or "" # type: ignore
71
+
72
+ ele.on("update:modelValue", handler=onModelValueChanged)
73
+
74
+ def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
75
+ if prop == "value":
76
+ return self.bind_value(ref_ui)
77
+
78
+ return super().bind_prop(prop, ref_ui)
79
+
80
+ def bind_value(self, ref_ui: ReadonlyRef[bool]):
81
+ @effect
82
+ def _():
83
+ self.element.on_value_change(ref_ui.value)
84
+
85
+ return self
@@ -0,0 +1,88 @@
1
+ from typing import (
2
+ Any,
3
+ )
4
+ from typing_extensions import Literal
5
+ from signe import effect
6
+ from ex4nicegui.utils.signals import (
7
+ to_value,
8
+ is_ref,
9
+ _TMaybeRef as TMaybeRef,
10
+ )
11
+ from nicegui import ui
12
+ from nicegui.page_layout import Drawer
13
+ from .base import SingleValueBindableUi
14
+ from .utils import _convert_kws_ref2value
15
+
16
+ _TDrawerSide = Literal["left", "right"]
17
+
18
+
19
+ class DrawerBindableUi(SingleValueBindableUi[bool, Drawer]):
20
+ def __init__(
21
+ self,
22
+ side: TMaybeRef[_TDrawerSide] = "left",
23
+ overlay: TMaybeRef[bool] = False,
24
+ *,
25
+ value: TMaybeRef[bool] = True,
26
+ fixed: TMaybeRef[bool] = False,
27
+ bordered: TMaybeRef[bool] = True,
28
+ elevated: TMaybeRef[bool] = False,
29
+ top_corner: TMaybeRef[bool] = False,
30
+ bottom_corner: TMaybeRef[bool] = False,
31
+ ) -> None:
32
+ kws = {
33
+ "side": side,
34
+ "overlay": overlay,
35
+ "value": value,
36
+ "fixed": fixed,
37
+ "bordered": bordered,
38
+ "elevated": elevated,
39
+ "top_corner": top_corner,
40
+ "bottom_corner": bottom_corner,
41
+ }
42
+
43
+ value_kws = _convert_kws_ref2value(kws)
44
+ del value_kws["side"]
45
+ del value_kws["overlay"]
46
+
47
+ element = None
48
+
49
+ if to_value(side) == "left":
50
+ element = ui.left_drawer(**value_kws)
51
+ else:
52
+ element = ui.right_drawer(**value_kws)
53
+
54
+ element.style(f"background-color:rgba(25, 118, 210,0.3)")
55
+ element.classes("flex flex-col gap-4")
56
+
57
+ init_value = (
58
+ element._props["model-value"]
59
+ if "model-value" in element._props
60
+ else element._props["show-if-above"]
61
+ )
62
+
63
+ super().__init__(value, element)
64
+
65
+ @effect
66
+ def _():
67
+ value = "true" if self.value else "false"
68
+ element.props(f":model-value={value}")
69
+
70
+ def on_update(e):
71
+ self._ref.value = e.args
72
+
73
+ element.on("update:modelValue", on_update)
74
+
75
+ for key, value in kws.items():
76
+ if is_ref(value):
77
+ self.bind_prop(key, value) # type: ignore
78
+
79
+ def toggle(self):
80
+ self.element.toggle()
81
+ return self
82
+
83
+ def __enter__(self):
84
+ self.element.__enter__()
85
+ return self
86
+
87
+ def __exit__(self, *_: Any):
88
+ self.element.__exit__(*_)
@@ -0,0 +1,70 @@
1
+ from typing import (
2
+ Dict,
3
+ )
4
+ from signe import effect
5
+ from ex4nicegui.utils.signals import (
6
+ ReadonlyRef,
7
+ is_ref,
8
+ ref_computed,
9
+ _TMaybeRef as TMaybeRef,
10
+ )
11
+ from .base import BindableUi
12
+ from .utils import _convert_kws_ref2value
13
+ from ex4nicegui.reactive.ECharts.ECharts import echarts
14
+
15
+
16
+ class EChartsBindableUi(BindableUi[echarts]):
17
+ def __init__(
18
+ self,
19
+ options: TMaybeRef[Dict],
20
+ ) -> None:
21
+ kws = {
22
+ "options": options,
23
+ }
24
+
25
+ value_kws = _convert_kws_ref2value(kws)
26
+
27
+ element = echarts(**value_kws)
28
+
29
+ super().__init__(element)
30
+
31
+ for key, value in kws.items():
32
+ if is_ref(value):
33
+ self.bind_prop(key, value) # type: ignore
34
+
35
+ @staticmethod
36
+ def _pyecharts2opts(chart):
37
+ import simplejson as json
38
+ from pyecharts.charts.chart import Base
39
+
40
+ if isinstance(chart, Base):
41
+ return json.loads(chart.dump_options())
42
+
43
+ return {}
44
+
45
+ @staticmethod
46
+ def from_pyecharts(chart: TMaybeRef):
47
+ if is_ref(chart):
48
+
49
+ @ref_computed
50
+ def chart_opt():
51
+ return EChartsBindableUi._pyecharts2opts(chart.value)
52
+
53
+ return EChartsBindableUi(chart_opt)
54
+
55
+ return EChartsBindableUi(EChartsBindableUi._pyecharts2opts(chart))
56
+
57
+ def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
58
+ if prop == "options":
59
+ return self.bind_options(ref_ui)
60
+
61
+ return super().bind_prop(prop, ref_ui)
62
+
63
+ def bind_options(self, ref_ui: ReadonlyRef[Dict]):
64
+ @effect
65
+ def _():
66
+ ele = self.element
67
+ ele.update_options(ref_ui.value)
68
+ ele.update()
69
+
70
+ return self
@@ -0,0 +1,66 @@
1
+ import asyncio
2
+ from signe import effect
3
+ from ex4nicegui.utils.signals import (
4
+ ReadonlyRef,
5
+ is_ref,
6
+ _TMaybeRef as TMaybeRef,
7
+ )
8
+ from nicegui import ui
9
+ from .base import SingleValueBindableUi
10
+ from .utils import _convert_kws_ref2value
11
+
12
+
13
+ class HtmlBindableUi(SingleValueBindableUi[str, ui.html]):
14
+ @staticmethod
15
+ def _setup_(binder: "HtmlBindableUi"):
16
+ first = True
17
+
18
+ @effect
19
+ def _():
20
+ nonlocal first
21
+
22
+ async def task():
23
+ pass
24
+ await ui.run_javascript(
25
+ f"getElement({binder.element.id}).innerText= '{binder.value}' ",
26
+ respond=False,
27
+ )
28
+
29
+ if not first:
30
+ asyncio.run(task())
31
+ else:
32
+ first = False
33
+
34
+ def __init__(
35
+ self,
36
+ content: TMaybeRef[str] = "",
37
+ ) -> None:
38
+ kws = {
39
+ "content": content,
40
+ }
41
+
42
+ value_kws = _convert_kws_ref2value(kws)
43
+
44
+ element = ui.html(**value_kws)
45
+
46
+ super().__init__(content, element)
47
+
48
+ for key, value in kws.items():
49
+ if is_ref(value):
50
+ self.bind_prop(key, value) # type: ignore
51
+
52
+ HtmlBindableUi._setup_(self)
53
+
54
+ def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
55
+ if prop == "color":
56
+ return self.bind_color(ref_ui)
57
+
58
+ return super().bind_prop(prop, ref_ui)
59
+
60
+ def bind_color(self, ref_ui: ReadonlyRef):
61
+ @effect
62
+ def _():
63
+ ele = self.element
64
+ color = ref_ui.value
65
+ ele._style["color"] = color
66
+ ele.update()
@@ -0,0 +1,62 @@
1
+ from typing import (
2
+ Optional,
3
+ cast,
4
+ )
5
+ from signe import effect
6
+ from ex4nicegui.utils.signals import (
7
+ ReadonlyRef,
8
+ is_ref,
9
+ _TMaybeRef as TMaybeRef,
10
+ )
11
+ from nicegui import ui
12
+ from nicegui.elements.mixins.color_elements import (
13
+ TextColorElement,
14
+ )
15
+ from .base import SingleValueBindableUi, _bind_color
16
+ from .utils import _convert_kws_ref2value
17
+
18
+
19
+ class IconBindableUi(SingleValueBindableUi[str, ui.icon]):
20
+ def __init__(
21
+ self,
22
+ name: TMaybeRef[str],
23
+ *,
24
+ size: Optional[TMaybeRef[str]] = None,
25
+ color: Optional[TMaybeRef[str]] = None,
26
+ ) -> None:
27
+ kws = {
28
+ "name": name,
29
+ "size": size,
30
+ "color": color,
31
+ }
32
+
33
+ value_kws = _convert_kws_ref2value(kws)
34
+
35
+ element = ui.icon(**value_kws)
36
+
37
+ super().__init__(name, 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 == "name":
45
+ return self.bind_name(ref_ui)
46
+
47
+ if prop == "color":
48
+ return self.bind_color(ref_ui)
49
+
50
+ return super().bind_prop(prop, ref_ui)
51
+
52
+ def bind_color(self, ref_ui: ReadonlyRef):
53
+ return _bind_color(self, ref_ui)
54
+
55
+ def bind_name(self, ref_ui: ReadonlyRef):
56
+ @effect
57
+ def _():
58
+ ele = cast(TextColorElement, self.element)
59
+ ele._props["name"] = ref_ui.value
60
+ ele.update()
61
+
62
+ return self
@@ -0,0 +1,54 @@
1
+ from pathlib import Path
2
+ from typing import (
3
+ Union,
4
+ )
5
+ from signe import effect
6
+ from ex4nicegui.utils.signals import (
7
+ ReadonlyRef,
8
+ is_ref,
9
+ _TMaybeRef as TMaybeRef,
10
+ )
11
+ from nicegui import ui
12
+ from .base import SingleValueBindableUi
13
+ from .utils import _convert_kws_ref2value
14
+
15
+
16
+ class ImageBindableUi(SingleValueBindableUi[Union[str, Path], ui.image]):
17
+ @staticmethod
18
+ def _setup_(binder: "ImageBindableUi"):
19
+ @effect
20
+ def _():
21
+ binder.element.on_source_change(binder.value)
22
+
23
+ def __init__(
24
+ self,
25
+ source: Union[TMaybeRef[str], TMaybeRef[Path]] = "",
26
+ ) -> None:
27
+ kws = {
28
+ "source": source,
29
+ }
30
+
31
+ value_kws = _convert_kws_ref2value(kws)
32
+
33
+ element = ui.image(**value_kws)
34
+
35
+ super().__init__(source, element) # type: ignore
36
+
37
+ for key, value in kws.items():
38
+ if is_ref(value):
39
+ self.bind_prop(key, value) # type: ignore
40
+
41
+ # ImageBindableUi._setup_(self)
42
+
43
+ def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
44
+ if prop == "source":
45
+ return self.bind_source(ref_ui)
46
+
47
+ return super().bind_prop(prop, ref_ui)
48
+
49
+ def bind_source(self, ref_ui: ReadonlyRef[Union[str, Path]]):
50
+ @effect
51
+ def _():
52
+ ele = self.element
53
+ source = ref_ui.value
54
+ ele.on_source_change(source)
@@ -0,0 +1,116 @@
1
+ from typing import (
2
+ Any,
3
+ Callable,
4
+ List,
5
+ Optional,
6
+ Dict,
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 .base import SingleValueBindableUi
16
+ from .utils import _convert_kws_ref2value
17
+
18
+
19
+ class InputBindableUi(SingleValueBindableUi[str, ui.input]):
20
+ def __init__(
21
+ self,
22
+ label: Optional[TMaybeRef[str]] = None,
23
+ *,
24
+ placeholder: Optional[TMaybeRef[str]] = None,
25
+ value: TMaybeRef[str] = "",
26
+ password: TMaybeRef[bool] = False,
27
+ password_toggle_button: TMaybeRef[bool] = False,
28
+ on_change: Optional[Callable[..., Any]] = None,
29
+ autocomplete: Optional[TMaybeRef[List[str]]] = None,
30
+ validation: Dict[str, Callable[..., bool]] = {},
31
+ ) -> None:
32
+ kws = {
33
+ "label": label,
34
+ "placeholder": placeholder,
35
+ "value": value,
36
+ "password": password,
37
+ "password_toggle_button": password_toggle_button,
38
+ "autocomplete": autocomplete,
39
+ "validation": validation,
40
+ "on_change": on_change,
41
+ }
42
+
43
+ value_kws = _convert_kws_ref2value(kws)
44
+
45
+ element = ui.input(**value_kws)
46
+
47
+ super().__init__(value, element)
48
+
49
+ for key, value in kws.items():
50
+ if is_ref(value) and key != "value":
51
+ self.bind_prop(key, value) # type: ignore
52
+
53
+ self._ex_setup()
54
+
55
+ def _ex_setup(self):
56
+ ele = self.element
57
+
58
+ @effect
59
+ def _():
60
+ ele.value = self.value
61
+
62
+ def onModelValueChanged(e):
63
+ self._ref.value = e.args or "" # type: ignore
64
+
65
+ ele.on("update:modelValue", handler=onModelValueChanged)
66
+
67
+ def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
68
+ if prop == "value":
69
+ return self.bind_value(ref_ui)
70
+
71
+ return super().bind_prop(prop, ref_ui)
72
+
73
+ def bind_value(self, ref_ui: ReadonlyRef[bool]):
74
+ @effect
75
+ def _():
76
+ self.element.on_value_change(ref_ui.value)
77
+
78
+ return self
79
+
80
+
81
+ class LazyInputBindableUi(InputBindableUi):
82
+ def __init__(
83
+ self,
84
+ label: Optional[TMaybeRef[str]] = None,
85
+ *,
86
+ placeholder: Optional[TMaybeRef[str]] = None,
87
+ value: TMaybeRef[str] = "",
88
+ password: TMaybeRef[bool] = False,
89
+ password_toggle_button: TMaybeRef[bool] = False,
90
+ on_change: Optional[Callable[..., Any]] = None,
91
+ autocomplete: Optional[TMaybeRef[List[str]]] = None,
92
+ validation: Dict[str, Callable[..., bool]] = {},
93
+ ) -> None:
94
+ super().__init__(
95
+ label,
96
+ placeholder=placeholder,
97
+ value=value,
98
+ password=password,
99
+ password_toggle_button=password_toggle_button,
100
+ on_change=on_change,
101
+ autocomplete=autocomplete,
102
+ validation=validation,
103
+ )
104
+
105
+ def _ex_setup(self):
106
+ ele = self.element
107
+
108
+ @effect
109
+ def _():
110
+ ele.value = self.value
111
+
112
+ def onValueChanged():
113
+ self._ref.value = ele.value or ""
114
+
115
+ ele.on("blur", onValueChanged)
116
+ ele.on("keyup.enter", onValueChanged)
@@ -0,0 +1,67 @@
1
+ from signe import effect
2
+ from ex4nicegui.utils.signals import (
3
+ ReadonlyRef,
4
+ is_ref,
5
+ _TMaybeRef as TMaybeRef,
6
+ )
7
+ from nicegui import ui
8
+ from .base import SingleValueBindableUi
9
+ from .utils import _convert_kws_ref2value
10
+
11
+
12
+ class LabelBindableUi(SingleValueBindableUi[str, ui.label]):
13
+ @staticmethod
14
+ def _setup_(binder: "LabelBindableUi"):
15
+ def onValueChanged(e):
16
+ binder._ref.value = e.args["label"] # type: ignore
17
+
18
+ @effect
19
+ def _():
20
+ binder.element.text = binder.value
21
+
22
+ binder.element.on("update:modelValue", handler=onValueChanged)
23
+
24
+ def __init__(
25
+ self,
26
+ text: TMaybeRef[str] = "",
27
+ ) -> None:
28
+ kws = {
29
+ "text": text,
30
+ }
31
+
32
+ value_kws = _convert_kws_ref2value(kws)
33
+
34
+ element = ui.label(**value_kws)
35
+
36
+ super().__init__(text, element)
37
+
38
+ for key, value in kws.items():
39
+ if is_ref(value):
40
+ self.bind_prop(key, value) # type: ignore
41
+
42
+ LabelBindableUi._setup_(self)
43
+
44
+ def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
45
+ if prop == "text":
46
+ return self.bind_text(ref_ui)
47
+
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
+ @effect
55
+ def _():
56
+ ele = self.element
57
+ color = ref_ui.value
58
+ ele._style["color"] = color
59
+ ele.update()
60
+
61
+ def bind_text(self, ref_ui: ReadonlyRef):
62
+ @effect
63
+ def _():
64
+ self.element.on_text_change(str(ref_ui.value))
65
+ # self.element.update()
66
+
67
+ return self
@@ -0,0 +1,80 @@
1
+ from typing import (
2
+ Any,
3
+ Callable,
4
+ List,
5
+ Optional,
6
+ TypeVar,
7
+ cast,
8
+ Dict,
9
+ Union,
10
+ )
11
+ from signe import effect
12
+ from ex4nicegui.utils.signals import (
13
+ ReadonlyRef,
14
+ is_ref,
15
+ _TMaybeRef as TMaybeRef,
16
+ )
17
+ from nicegui import ui
18
+ from nicegui.elements.mixins.value_element import ValueElement
19
+ from .base import SingleValueBindableUi
20
+ from .utils import _convert_kws_ref2value
21
+
22
+ T = TypeVar("T")
23
+
24
+
25
+ class RadioBindableUi(SingleValueBindableUi[bool, ui.radio]):
26
+ @staticmethod
27
+ def _setup_(binder: "RadioBindableUi"):
28
+ def onValueChanged(e):
29
+ binder._ref.value = binder.element.options[e.args] # type: ignore
30
+
31
+ @effect
32
+ def _():
33
+ binder.element.value = binder.value
34
+
35
+ binder.element.on("update:modelValue", handler=onValueChanged)
36
+
37
+ def __init__(
38
+ self,
39
+ options: Union[TMaybeRef[List], TMaybeRef[Dict]],
40
+ *,
41
+ value: TMaybeRef[Any] = None,
42
+ on_change: Optional[Callable[..., Any]] = None,
43
+ ) -> None:
44
+ kws = {"options": options, "value": value, "on_change": on_change}
45
+
46
+ value_kws = _convert_kws_ref2value(kws)
47
+
48
+ element = ui.radio(**value_kws)
49
+
50
+ super().__init__(value, element)
51
+
52
+ for key, value in kws.items():
53
+ if is_ref(value):
54
+ self.bind_prop(key, value)
55
+
56
+ RadioBindableUi._setup_(self)
57
+
58
+ def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
59
+ if prop == "value":
60
+ return self.bind_value(ref_ui)
61
+
62
+ if prop == "options":
63
+ return self.bind_options(ref_ui)
64
+
65
+ return super().bind_prop(prop, ref_ui)
66
+
67
+ def bind_options(self, ref_ui: ReadonlyRef):
68
+ @effect
69
+ def _():
70
+ self.element.options = ref_ui.value
71
+ self.element.update()
72
+
73
+ return self
74
+
75
+ def bind_value(self, ref_ui: ReadonlyRef):
76
+ @effect
77
+ def _():
78
+ cast(ValueElement, self.element).on_value_change(ref_ui.value)
79
+
80
+ return self