ex4nicegui 0.6.6__py3-none-any.whl → 0.6.7__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 (34) hide show
  1. ex4nicegui/libs/gsap/.DS_Store +0 -0
  2. ex4nicegui/libs/gsap/gsap.mjs +6 -0
  3. ex4nicegui/reactive/EChartsComponent/ECharts.js +19 -9
  4. ex4nicegui/reactive/officials/aggrid.py +3 -3
  5. ex4nicegui/reactive/officials/base.py +10 -0
  6. ex4nicegui/reactive/officials/button.py +4 -4
  7. ex4nicegui/reactive/officials/checkbox.py +3 -3
  8. ex4nicegui/reactive/officials/circular_progress.py +3 -3
  9. ex4nicegui/reactive/officials/color_picker.py +4 -4
  10. ex4nicegui/reactive/officials/column.py +3 -2
  11. ex4nicegui/reactive/officials/date.py +4 -9
  12. ex4nicegui/reactive/officials/echarts.py +30 -12
  13. ex4nicegui/reactive/officials/expansion.py +3 -2
  14. ex4nicegui/reactive/officials/icon.py +4 -4
  15. ex4nicegui/reactive/officials/image.py +3 -3
  16. ex4nicegui/reactive/officials/input.py +4 -4
  17. ex4nicegui/reactive/officials/knob.py +3 -3
  18. ex4nicegui/reactive/officials/label.py +4 -3
  19. ex4nicegui/reactive/officials/linear_progress.py +4 -4
  20. ex4nicegui/reactive/officials/number.py +22 -4
  21. ex4nicegui/reactive/officials/radio.py +4 -4
  22. ex4nicegui/reactive/officials/select.py +4 -4
  23. ex4nicegui/reactive/officials/slider.py +3 -3
  24. ex4nicegui/reactive/officials/switch.py +3 -3
  25. ex4nicegui/reactive/officials/tab_panels.py +14 -2
  26. ex4nicegui/reactive/officials/table.py +5 -4
  27. ex4nicegui/reactive/officials/tabs.py +3 -2
  28. ex4nicegui/reactive/officials/textarea.py +3 -3
  29. ex4nicegui/reactive/q_pagination.py +3 -2
  30. {ex4nicegui-0.6.6.dist-info → ex4nicegui-0.6.7.dist-info}/METADATA +1245 -1124
  31. {ex4nicegui-0.6.6.dist-info → ex4nicegui-0.6.7.dist-info}/RECORD +61 -60
  32. {ex4nicegui-0.6.6.dist-info → ex4nicegui-0.6.7.dist-info}/WHEEL +1 -2
  33. ex4nicegui-0.6.6.dist-info/top_level.txt +0 -1
  34. {ex4nicegui-0.6.6.dist-info → ex4nicegui-0.6.7.dist-info}/LICENSE +0 -0
Binary file
@@ -0,0 +1,6 @@
1
+ import { gsap, Power0, Power1, Power2, Power3, Power4, Linear, Quad, Cubic, Quart, Quint, Strong, Elastic, Back, SteppedEase, Bounce, Sine, Expo, Circ, TweenLite, TimelineLite, TimelineMax } from "./gsap-core.js";
2
+ import { CSSPlugin } from "./CSSPlugin.js";
3
+ var gsapWithCSS = gsap.registerPlugin(CSSPlugin) || gsap,
4
+ // to protect from tree shaking
5
+ TweenMaxWithCSS = gsapWithCSS.core.Tween;
6
+ export { gsapWithCSS as gsap, gsapWithCSS as default, CSSPlugin, TweenMaxWithCSS as TweenMax, TweenLite, TimelineMax, TimelineLite, Power0, Power1, Power2, Power3, Power4, Linear, Quad, Cubic, Quart, Quint, Strong, Elastic, Back, SteppedEase, Bounce, Sine, Expo, Circ };
@@ -5,13 +5,23 @@ function collectMapRegisterTask() {
5
5
 
6
6
  if (typeof window.ex4ngEchartsMapTasks !== "undefined") {
7
7
 
8
- for (const [mapName, src] of window.ex4ngEchartsMapTasks.entries()) {
9
-
8
+ for (const [mapName, opt] of window.ex4ngEchartsMapTasks.entries()) {
9
+ const { src, type: mapDataType, specialAreas } = opt;
10
10
  const registerPromise = new Promise((resolve, reject) => {
11
11
  fetch(src)
12
- .then((response) => response.json())
12
+ .then((response) => {
13
+ if (mapDataType === "genJSON") {
14
+ return response.json();
15
+ }
16
+
17
+ return response.text();
18
+ })
13
19
  .then((data) => {
14
- echarts.registerMap(mapName, data);
20
+ if (mapDataType === "svg") {
21
+ data = { svg: data }
22
+ }
23
+
24
+ echarts.registerMap(mapName, data, specialAreas);
15
25
  resolve();
16
26
  });
17
27
 
@@ -46,10 +56,6 @@ export default {
46
56
  async mounted() {
47
57
  await this.$nextTick(); // wait for Tailwind classes to be applied
48
58
 
49
- if (hasMapOrGeo(this.options)) {
50
- await Promise.all(Array.from(mapRegisterTasks.values()));
51
- }
52
-
53
59
  this.chart = echarts.init(this.$el, this.theme);
54
60
 
55
61
  this.resizeObs = new ResizeObserver(this.chart.resize)
@@ -63,10 +69,14 @@ export default {
63
69
  this.chart.on("finished", createResizeObserver);
64
70
 
65
71
  if (this.options) {
72
+ if (hasMapOrGeo(this.options)) {
73
+ await Promise.all(Array.from(mapRegisterTasks.values()));
74
+ }
66
75
  this.update_chart();
67
76
  } else {
68
77
  const fn = new Function('return ' + this.code)()
69
- fn(this.chart)
78
+ await Promise.all(Array.from(mapRegisterTasks.values()));
79
+ fn(this.chart, echarts)
70
80
  this.$emit("__update_options_from_client", this.chart.getOption())
71
81
  }
72
82
  this.chart.getZr().on("click", (e) => {
@@ -6,11 +6,11 @@ from typing import (
6
6
  Optional,
7
7
  )
8
8
  from ex4nicegui.utils.signals import (
9
- ReadonlyRef,
10
9
  is_ref,
11
10
  ref_computed,
12
11
  to_value,
13
12
  _TMaybeRef as TMaybeRef,
13
+ TGetterOrReadonlyRef,
14
14
  )
15
15
  from ex4nicegui.utils.apiEffect import ui_effect
16
16
  from nicegui import ui
@@ -78,13 +78,13 @@ 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, ref_ui: ReadonlyRef[Any]):
81
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef[Any]):
82
82
  if prop == "options":
83
83
  return self.bind_options(ref_ui)
84
84
 
85
85
  return super().bind_prop(prop, ref_ui)
86
86
 
87
- def bind_options(self, ref_ui: ReadonlyRef[List[Dict]]):
87
+ def bind_options(self, ref_ui: TGetterOrReadonlyRef[List[Dict]]):
88
88
  @ui_effect
89
89
  def _():
90
90
  ele = self.element
@@ -128,6 +128,16 @@ class BindableUi(Generic[TWidget]):
128
128
  return self.element.remove(element)
129
129
 
130
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
+ """
131
141
  if prop == "visible":
132
142
  return self.bind_visible(ref_ui)
133
143
 
@@ -5,7 +5,7 @@ from typing import (
5
5
  )
6
6
  from ex4nicegui.reactive.utils import ParameterClassifier
7
7
  from ex4nicegui.utils.signals import (
8
- ReadonlyRef,
8
+ TGetterOrReadonlyRef,
9
9
  _TMaybeRef as TMaybeRef,
10
10
  to_value,
11
11
  )
@@ -33,7 +33,7 @@ class ButtonBindableUi(BindableUi[ui.button], DisableableMixin):
33
33
  for key, value in pc.get_bindings().items():
34
34
  self.bind_prop(key, value) # type: ignore
35
35
 
36
- def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
36
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
37
37
  if prop == "text":
38
38
  return self.bind_text(ref_ui)
39
39
  if prop == "icon":
@@ -41,7 +41,7 @@ class ButtonBindableUi(BindableUi[ui.button], DisableableMixin):
41
41
 
42
42
  return super().bind_prop(prop, ref_ui)
43
43
 
44
- def bind_text(self, ref_ui: ReadonlyRef):
44
+ def bind_text(self, ref_ui: TGetterOrReadonlyRef):
45
45
  @self._ui_effect
46
46
  def _():
47
47
  ele = self.element
@@ -50,7 +50,7 @@ class ButtonBindableUi(BindableUi[ui.button], DisableableMixin):
50
50
 
51
51
  return self
52
52
 
53
- def bind_icon(self, ref_ui: ReadonlyRef):
53
+ def bind_icon(self, ref_ui: TGetterOrReadonlyRef[str]):
54
54
  @self._ui_effect
55
55
  def _():
56
56
  ele = self.element
@@ -7,7 +7,7 @@ from typing import (
7
7
  from ex4nicegui.reactive.utils import ParameterClassifier
8
8
  from ex4nicegui.utils.apiEffect import ui_effect
9
9
  from ex4nicegui.utils.signals import (
10
- ReadonlyRef,
10
+ TGetterOrReadonlyRef,
11
11
  _TMaybeRef as TMaybeRef,
12
12
  to_value,
13
13
  )
@@ -44,13 +44,13 @@ class CheckboxBindableUi(BindableUi[ui.checkbox], DisableableMixin):
44
44
  def value(self):
45
45
  return self.element.value
46
46
 
47
- def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
47
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
48
48
  if prop == "value":
49
49
  return self.bind_value(ref_ui)
50
50
 
51
51
  return super().bind_prop(prop, ref_ui)
52
52
 
53
- def bind_value(self, ref_ui: ReadonlyRef[bool]):
53
+ def bind_value(self, ref_ui: TGetterOrReadonlyRef[bool]):
54
54
  @ui_effect
55
55
  def _():
56
56
  self.element.set_value(to_value(ref_ui))
@@ -5,7 +5,7 @@ from ex4nicegui.reactive.utils import ParameterClassifier
5
5
  from ex4nicegui.utils.apiEffect import ui_effect
6
6
 
7
7
  from ex4nicegui.utils.signals import (
8
- ReadonlyRef,
8
+ TGetterOrReadonlyRef,
9
9
  _TMaybeRef as TMaybeRef,
10
10
  to_value,
11
11
  )
@@ -50,13 +50,13 @@ class CircularProgressBindableUi(
50
50
  def value(self):
51
51
  return self.element.value
52
52
 
53
- def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
53
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
54
54
  if prop == "value":
55
55
  return self.bind_value(ref_ui)
56
56
 
57
57
  return super().bind_prop(prop, ref_ui)
58
58
 
59
- def bind_value(self, ref_ui: ReadonlyRef[float]):
59
+ def bind_value(self, ref_ui: TGetterOrReadonlyRef[float]):
60
60
  @ui_effect
61
61
  def _():
62
62
  self.element.set_value(to_value(ref_ui))
@@ -8,7 +8,7 @@ from ex4nicegui.reactive.utils import ParameterClassifier
8
8
  from ex4nicegui.utils.apiEffect import ui_effect
9
9
 
10
10
  from ex4nicegui.utils.signals import (
11
- ReadonlyRef,
11
+ TGetterOrReadonlyRef,
12
12
  Ref,
13
13
  _TMaybeRef as TMaybeRef,
14
14
  is_setter_ref,
@@ -69,20 +69,20 @@ class ColorPickerBindableUi(BindableUi[ui.color_picker]):
69
69
  def value(self):
70
70
  return self.element.value
71
71
 
72
- def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
72
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
73
73
  if prop == "value":
74
74
  return self.bind_value(ref_ui)
75
75
 
76
76
  return super().bind_prop(prop, ref_ui)
77
77
 
78
- def bind_color(self, ref_ui: ReadonlyRef[str]):
78
+ def bind_color(self, ref_ui: TGetterOrReadonlyRef[str]):
79
79
  @ui_effect
80
80
  def _():
81
81
  self.element.set_color(to_value(ref_ui))
82
82
 
83
83
  return self
84
84
 
85
- def bind_value(self, ref_ui: ReadonlyRef[bool]):
85
+ def bind_value(self, ref_ui: TGetterOrReadonlyRef[bool]):
86
86
  @ui_effect
87
87
  def _():
88
88
  self.element.set_value(to_value(ref_ui))
@@ -3,6 +3,7 @@ from typing import (
3
3
  )
4
4
  from ex4nicegui.reactive.utils import ParameterClassifier
5
5
  from ex4nicegui.utils.signals import (
6
+ TGetterOrReadonlyRef,
6
7
  _TMaybeRef as TMaybeRef,
7
8
  )
8
9
  from nicegui import ui
@@ -19,13 +20,13 @@ class ColumnBindableUi(BindableUi[ui.column]):
19
20
  for key, value in pc.get_bindings().items():
20
21
  self.bind_prop(key, value) # type: ignore
21
22
 
22
- def bind_prop(self, prop: str, ref_ui: TMaybeRef):
23
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
23
24
  if prop == "wrap":
24
25
  return self.bind_wrap(ref_ui)
25
26
 
26
27
  return super().bind_prop(prop, ref_ui)
27
28
 
28
- def bind_wrap(self, ref_ui: TMaybeRef):
29
+ def bind_wrap(self, ref_ui: TGetterOrReadonlyRef):
29
30
  self.bind_classes({"wrap": ref_ui})
30
31
 
31
32
  def __enter__(self):
@@ -4,7 +4,7 @@ from ex4nicegui.reactive.utils import ParameterClassifier
4
4
  from ex4nicegui.utils.apiEffect import ui_effect
5
5
 
6
6
  from ex4nicegui.utils.signals import (
7
- ReadonlyRef,
7
+ TGetterOrReadonlyRef,
8
8
  _TMaybeRef as TMaybeRef,
9
9
  to_value,
10
10
  )
@@ -45,13 +45,8 @@ class DateBindableUi(BindableUi[ui.date]):
45
45
  pc = ParameterClassifier(
46
46
  locals(),
47
47
  maybeRefs=[
48
- "label",
49
48
  "value",
50
- "placeholder",
51
- "password",
52
- "password_toggle_button",
53
- "autocomplete",
54
- "validation",
49
+ "mask",
55
50
  ],
56
51
  v_model=("value", "on_change"),
57
52
  events=["on_change"],
@@ -68,13 +63,13 @@ class DateBindableUi(BindableUi[ui.date]):
68
63
  def value(self):
69
64
  return self.element.value
70
65
 
71
- def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
66
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
72
67
  if prop == "value":
73
68
  return self.bind_value(ref_ui)
74
69
 
75
70
  return super().bind_prop(prop, ref_ui)
76
71
 
77
- def bind_value(self, ref_ui: ReadonlyRef[bool]):
72
+ def bind_value(self, ref_ui: TGetterOrReadonlyRef[bool]):
78
73
  @ui_effect
79
74
  def _():
80
75
  self.element.set_value(to_value(ref_ui))
@@ -1,8 +1,8 @@
1
1
  from pathlib import Path
2
- from typing import Any, Callable, Dict, List, Union, cast, Optional
2
+ from typing import Any, Callable, Dict, List, Union, cast, Optional, Literal
3
3
  from ex4nicegui.reactive.utils import ParameterClassifier
4
4
  from ex4nicegui.utils.signals import (
5
- ReadonlyRef,
5
+ TGetterOrReadonlyRef,
6
6
  is_ref,
7
7
  ref_computed,
8
8
  _TMaybeRef as TMaybeRef,
@@ -17,6 +17,7 @@ from ex4nicegui.reactive.EChartsComponent.events import EChartsMouseEventArgumen
17
17
 
18
18
  from nicegui.awaitable_response import AwaitableResponse
19
19
  from nicegui import ui, app
20
+ import orjson as json
20
21
 
21
22
 
22
23
  class EChartsBindableUi(BindableUi[echarts]):
@@ -46,7 +47,14 @@ class EChartsBindableUi(BindableUi[echarts]):
46
47
  self.bind_prop(key, value) # type: ignore
47
48
 
48
49
  @classmethod
49
- def register_map(cls, map_name: str, src: Union[str, Path]):
50
+ def register_map(
51
+ cls,
52
+ map_name: str,
53
+ src: Union[str, Path],
54
+ *,
55
+ type: Literal["geoJSON", "svg"] = "geoJSON",
56
+ special_areas: Optional[Dict[str, Any]] = None,
57
+ ):
50
58
  """Registers available maps. This can only be used after including geo component or chart series of map.
51
59
 
52
60
  @see - https://github.com/CrystalWindSnake/ex4nicegui/blob/main/README.en.md#rxuiechartsregister_map
@@ -55,6 +63,8 @@ class EChartsBindableUi(BindableUi[echarts]):
55
63
  Args:
56
64
  map_name (str): Map name, referring to map value set in geo component or map.
57
65
  src (Union[str, Path]): Map data. If str, it should be a network address. If path, it should be a valid file.
66
+ type (Literal["geoJSON", "svg"], optional): Map data type. Defaults to "geoJSON".
67
+ special_areas (Optional[Dict[str, Any]], optional): Special areas. Defaults to None.
58
68
  """
59
69
  if isinstance(src, Path):
60
70
  src = app.add_static_file(local_file=src)
@@ -63,13 +73,21 @@ class EChartsBindableUi(BindableUi[echarts]):
63
73
 
64
74
  ui.add_body_html(
65
75
  rf"""
66
- <script>
67
- if (typeof window.ex4ngEchartsMapTasks === "undefined") {{
68
- window.ex4ngEchartsMapTasks = new Map();
69
- }}
70
-
71
- window.ex4ngEchartsMapTasks.set('{map_name}', '{src}');
72
- </script>
76
+ <script>
77
+ (function () {{
78
+ if (typeof window.ex4ngEchartsMapTasks === "undefined") {{
79
+ window.ex4ngEchartsMapTasks = new Map();
80
+ }}
81
+
82
+ const value = {{
83
+ src: '{src}',
84
+ type: '{type}',
85
+ specialAreas: {json.dumps(special_areas).decode('utf-8')}
86
+ }}
87
+
88
+ window.ex4ngEchartsMapTasks.set('{map_name}', value);
89
+ }})()
90
+ </script>
73
91
  """
74
92
  )
75
93
 
@@ -116,13 +134,13 @@ class EChartsBindableUi(BindableUi[echarts]):
116
134
  code = code.read_text("utf8")
117
135
  return cls(code=code)
118
136
 
119
- def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
137
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
120
138
  if prop == "options":
121
139
  return self.bind_options(ref_ui)
122
140
 
123
141
  return super().bind_prop(prop, ref_ui)
124
142
 
125
- def bind_options(self, ref_ui: ReadonlyRef[Dict]):
143
+ def bind_options(self, ref_ui: TGetterOrReadonlyRef[Dict]):
126
144
  @on(ref_ui)
127
145
  def _():
128
146
  ele = self.element
@@ -3,6 +3,7 @@ from nicegui import ui
3
3
  from ex4nicegui.reactive.utils import ParameterClassifier
4
4
  from ex4nicegui.utils.apiEffect import ui_effect
5
5
  from ex4nicegui.utils.signals import (
6
+ TGetterOrReadonlyRef,
6
7
  _TMaybeRef as TMaybeRef,
7
8
  to_value,
8
9
  )
@@ -45,13 +46,13 @@ class ExpansionBindableUi(BindableUi[ui.expansion]):
45
46
  def value(self):
46
47
  return self.element.value
47
48
 
48
- def bind_prop(self, prop: str, ref_ui: TMaybeRef):
49
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
49
50
  if prop == "value":
50
51
  return self.bind_value(ref_ui)
51
52
 
52
53
  return super().bind_prop(prop, ref_ui)
53
54
 
54
- def bind_value(self, ref_ui: TMaybeRef):
55
+ def bind_value(self, ref_ui: TGetterOrReadonlyRef):
55
56
  @ui_effect
56
57
  def _():
57
58
  self.element.set_value(to_value(ref_ui))
@@ -6,7 +6,7 @@ from ex4nicegui.reactive.utils import ParameterClassifier
6
6
  from ex4nicegui.utils.apiEffect import ui_effect
7
7
 
8
8
  from ex4nicegui.utils.signals import (
9
- ReadonlyRef,
9
+ TGetterOrReadonlyRef,
10
10
  _TMaybeRef as TMaybeRef,
11
11
  to_value,
12
12
  )
@@ -35,7 +35,7 @@ class IconBindableUi(BindableUi[ui.icon]):
35
35
  for key, value in pc.get_bindings().items():
36
36
  self.bind_prop(key, value) # type: ignore
37
37
 
38
- def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
38
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
39
39
  if prop == "name":
40
40
  return self.bind_name(ref_ui)
41
41
 
@@ -44,10 +44,10 @@ class IconBindableUi(BindableUi[ui.icon]):
44
44
 
45
45
  return super().bind_prop(prop, ref_ui)
46
46
 
47
- def bind_color(self, ref_ui: ReadonlyRef):
47
+ def bind_color(self, ref_ui: TGetterOrReadonlyRef):
48
48
  return _bind_color(self, ref_ui)
49
49
 
50
- def bind_name(self, ref_ui: ReadonlyRef):
50
+ def bind_name(self, ref_ui: TGetterOrReadonlyRef):
51
51
  @ui_effect
52
52
  def _():
53
53
  ele = cast(TextColorElement, self.element)
@@ -6,7 +6,7 @@ from ex4nicegui.reactive.utils import ParameterClassifier
6
6
  from ex4nicegui.utils.apiEffect import ui_effect
7
7
 
8
8
  from ex4nicegui.utils.signals import (
9
- ReadonlyRef,
9
+ TGetterOrReadonlyRef,
10
10
  _TMaybeRef as TMaybeRef,
11
11
  to_value,
12
12
  )
@@ -27,13 +27,13 @@ class ImageBindableUi(BindableUi[ui.image]):
27
27
  for key, value in pc.get_bindings().items():
28
28
  self.bind_prop(key, value) # type: ignore
29
29
 
30
- def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
30
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
31
31
  if prop == "source":
32
32
  return self.bind_source(ref_ui)
33
33
 
34
34
  return super().bind_prop(prop, ref_ui)
35
35
 
36
- def bind_source(self, ref_ui: ReadonlyRef[Union[str, Path]]):
36
+ def bind_source(self, ref_ui: TGetterOrReadonlyRef[Union[str, Path]]):
37
37
  @ui_effect
38
38
  def _():
39
39
  self.element.set_source(to_value(ref_ui))
@@ -3,7 +3,7 @@ from ex4nicegui.utils.apiEffect import ui_effect
3
3
 
4
4
 
5
5
  from ex4nicegui.utils.signals import (
6
- ReadonlyRef,
6
+ TGetterOrReadonlyRef,
7
7
  Ref,
8
8
  _TMaybeRef as TMaybeRef,
9
9
  effect,
@@ -53,7 +53,7 @@ class InputBindableUi(BindableUi[ui.input], DisableableMixin):
53
53
  for key, value in pc.get_bindings().items():
54
54
  self.bind_prop(key, value) # type: ignore
55
55
 
56
- def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
56
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
57
57
  if prop == "value":
58
58
  return self.bind_value(ref_ui)
59
59
  if prop == "password":
@@ -61,7 +61,7 @@ class InputBindableUi(BindableUi[ui.input], DisableableMixin):
61
61
 
62
62
  return super().bind_prop(prop, ref_ui)
63
63
 
64
- def bind_value(self, ref_ui: ReadonlyRef[str]):
64
+ def bind_value(self, ref_ui: TGetterOrReadonlyRef[str]):
65
65
  @ui_effect
66
66
  def _():
67
67
  self.element.set_value(to_value(ref_ui))
@@ -69,7 +69,7 @@ class InputBindableUi(BindableUi[ui.input], DisableableMixin):
69
69
 
70
70
  return self
71
71
 
72
- def bind_password(self, ref_ui: ReadonlyRef[bool]):
72
+ def bind_password(self, ref_ui: TGetterOrReadonlyRef[bool]):
73
73
  @ui_effect
74
74
  def _():
75
75
  self.element._props["type"] = "password" if to_value(ref_ui) else "text"
@@ -7,9 +7,9 @@ from ex4nicegui.reactive.utils import ParameterClassifier
7
7
  from ex4nicegui.utils.apiEffect import ui_effect
8
8
 
9
9
  from ex4nicegui.utils.signals import (
10
- ReadonlyRef,
11
10
  _TMaybeRef as TMaybeRef,
12
11
  to_value,
12
+ TGetterOrReadonlyRef,
13
13
  )
14
14
  from nicegui import ui
15
15
  from .base import BindableUi, DisableableMixin
@@ -61,13 +61,13 @@ class KnobBindableUi(
61
61
  def value(self):
62
62
  return self.element.value
63
63
 
64
- def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
64
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
65
65
  if prop == "value":
66
66
  return self.bind_value(ref_ui)
67
67
 
68
68
  return super().bind_prop(prop, ref_ui)
69
69
 
70
- def bind_value(self, ref_ui: ReadonlyRef[float]):
70
+ def bind_value(self, ref_ui: TGetterOrReadonlyRef[float]):
71
71
  @ui_effect
72
72
  def _():
73
73
  self.element.set_value(to_value(ref_ui))
@@ -1,6 +1,7 @@
1
1
  from typing import Any
2
2
  from ex4nicegui.reactive.utils import ParameterClassifier
3
3
  from ex4nicegui.utils.signals import (
4
+ TGetterOrReadonlyRef,
4
5
  to_value,
5
6
  _TMaybeRef as TMaybeRef,
6
7
  )
@@ -25,7 +26,7 @@ class LabelBindableUi(BindableUi[ui.label]):
25
26
  def text(self):
26
27
  return self.element.text
27
28
 
28
- def bind_prop(self, prop: str, ref_ui: TMaybeRef):
29
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
29
30
  if prop == "text":
30
31
  return self.bind_text(ref_ui)
31
32
 
@@ -34,7 +35,7 @@ class LabelBindableUi(BindableUi[ui.label]):
34
35
 
35
36
  return super().bind_prop(prop, ref_ui)
36
37
 
37
- def bind_color(self, ref_ui: TMaybeRef):
38
+ def bind_color(self, ref_ui: TGetterOrReadonlyRef):
38
39
  @self._ui_effect
39
40
  def _():
40
41
  ele = self.element
@@ -42,7 +43,7 @@ class LabelBindableUi(BindableUi[ui.label]):
42
43
  ele._style["color"] = color
43
44
  ele.update()
44
45
 
45
- def bind_text(self, ref_ui: TMaybeRef):
46
+ def bind_text(self, ref_ui: TGetterOrReadonlyRef):
46
47
  @self._ui_effect
47
48
  def _():
48
49
  self.element.set_text(str(to_value(ref_ui)))
@@ -5,7 +5,7 @@ from ex4nicegui.reactive.utils import ParameterClassifier
5
5
  from ex4nicegui.utils.apiEffect import ui_effect
6
6
 
7
7
  from ex4nicegui.utils.signals import (
8
- ReadonlyRef,
8
+ TGetterOrReadonlyRef,
9
9
  _TMaybeRef as TMaybeRef,
10
10
  to_value,
11
11
  )
@@ -47,7 +47,7 @@ class LinearProgressBindableUi(BindableUi[ui.linear_progress]):
47
47
  def value(self):
48
48
  return self.element.value
49
49
 
50
- def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
50
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
51
51
  if prop == "value":
52
52
  return self.bind_value(ref_ui)
53
53
 
@@ -56,10 +56,10 @@ class LinearProgressBindableUi(BindableUi[ui.linear_progress]):
56
56
 
57
57
  return super().bind_prop(prop, ref_ui)
58
58
 
59
- def bind_color(self, ref_ui: ReadonlyRef):
59
+ def bind_color(self, ref_ui: TGetterOrReadonlyRef):
60
60
  return _bind_color(self, ref_ui)
61
61
 
62
- def bind_value(self, ref_ui: ReadonlyRef):
62
+ def bind_value(self, ref_ui: TGetterOrReadonlyRef):
63
63
  @ui_effect
64
64
  def _():
65
65
  self.element.set_value(to_value(ref_ui))
@@ -10,9 +10,10 @@ from ex4nicegui.reactive.utils import ParameterClassifier
10
10
  from ex4nicegui.utils.apiEffect import ui_effect
11
11
 
12
12
  from ex4nicegui.utils.signals import (
13
- ReadonlyRef,
13
+ TGetterOrReadonlyRef,
14
14
  _TMaybeRef as TMaybeRef,
15
15
  to_value,
16
+ on,
16
17
  )
17
18
  from nicegui import ui
18
19
  from .base import BindableUi
@@ -20,6 +21,10 @@ from .base import BindableUi
20
21
  T = TypeVar("T")
21
22
 
22
23
 
24
+ def _default_vmodel_args_getter(e):
25
+ return e.sender.value
26
+
27
+
23
28
  class NumberBindableUi(BindableUi[ui.number]):
24
29
  def __init__(
25
30
  self,
@@ -29,6 +34,7 @@ class NumberBindableUi(BindableUi[ui.number]):
29
34
  value: Optional[Union[TMaybeRef[float], TMaybeRef[int]]] = None,
30
35
  min: Optional[TMaybeRef[float]] = None,
31
36
  max: Optional[TMaybeRef[float]] = None,
37
+ precision: Optional[TMaybeRef[int]] = None,
32
38
  step: Optional[TMaybeRef[float]] = None,
33
39
  prefix: Optional[TMaybeRef[str]] = None,
34
40
  suffix: Optional[TMaybeRef[str]] = None,
@@ -44,6 +50,7 @@ class NumberBindableUi(BindableUi[ui.number]):
44
50
  "value",
45
51
  "min",
46
52
  "max",
53
+ "precision",
47
54
  "step",
48
55
  "prefix",
49
56
  "suffix",
@@ -52,10 +59,10 @@ class NumberBindableUi(BindableUi[ui.number]):
52
59
  ],
53
60
  v_model=("value", "on_change"),
54
61
  events=["on_change"],
62
+ v_model_arg_getter=_default_vmodel_args_getter,
55
63
  )
56
64
 
57
65
  value_kws = pc.get_values_kws()
58
-
59
66
  element = ui.number(**value_kws)
60
67
  super().__init__(element) # type: ignore
61
68
 
@@ -66,15 +73,26 @@ class NumberBindableUi(BindableUi[ui.number]):
66
73
  def value(self):
67
74
  return self.element.value
68
75
 
69
- def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
76
+ def bind_prop(self, prop: str, ref_ui: TGetterOrReadonlyRef):
70
77
  if prop == "value":
71
78
  return self.bind_value(ref_ui)
72
79
 
80
+ if prop == "precision":
81
+ return self._bind_precision(ref_ui)
82
+
73
83
  return super().bind_prop(prop, ref_ui)
74
84
 
75
- def bind_value(self, ref_ui: ReadonlyRef[float]):
85
+ def bind_value(self, ref_ui: TGetterOrReadonlyRef[float]):
76
86
  @ui_effect
77
87
  def _():
78
88
  self.element.set_value(to_value(ref_ui))
79
89
 
80
90
  return self
91
+
92
+ def _bind_precision(self, ref_ui: TGetterOrReadonlyRef[int]):
93
+ @on(ref_ui, onchanges=True)
94
+ def _():
95
+ self.element.precision = to_value(ref_ui)
96
+ self.element.sanitize()
97
+
98
+ return self