ex4nicegui 0.5.1__py3-none-any.whl → 0.5.3__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 (43) hide show
  1. ex4nicegui/__init__.py +3 -6
  2. ex4nicegui/bi/dataSourceFacade.py +16 -61
  3. ex4nicegui/bi/elements/text.py +1 -1
  4. ex4nicegui/bi/elements/ui_aggrid.py +2 -2
  5. ex4nicegui/bi/elements/ui_echarts.py +3 -3
  6. ex4nicegui/bi/elements/ui_slider.py +1 -1
  7. ex4nicegui/bi/elements/ui_table.py +2 -2
  8. ex4nicegui/bi/protocols.py +0 -1
  9. ex4nicegui/bi/types.py +0 -1
  10. ex4nicegui/experimental_/__init__.py +4 -0
  11. ex4nicegui/experimental_/gridLayout/__init__.py +7 -0
  12. ex4nicegui/gsap/__init__.py +11 -0
  13. ex4nicegui/gsap/timeline.js +56 -0
  14. ex4nicegui/gsap/timeline.py +78 -0
  15. ex4nicegui/layout/__init__.py +13 -2
  16. ex4nicegui/layout/gridFlex/__init__.py +1 -1
  17. ex4nicegui/layout/gridFlex/gridFlex.py +1 -3
  18. ex4nicegui/layout/rxFlex/__init__.py +0 -1
  19. ex4nicegui/layout/rxFlex/index.py +16 -6
  20. ex4nicegui/reactive/__init__.py +57 -2
  21. ex4nicegui/reactive/fileWatcher.py +1 -1
  22. ex4nicegui/reactive/local_file_picker.py +1 -1
  23. ex4nicegui/reactive/officials/button.py +0 -1
  24. ex4nicegui/reactive/officials/circular_progress.py +64 -0
  25. ex4nicegui/reactive/officials/column.py +19 -4
  26. ex4nicegui/reactive/officials/html.py +1 -1
  27. ex4nicegui/reactive/officials/knob.py +75 -0
  28. ex4nicegui/reactive/officials/label.py +0 -1
  29. ex4nicegui/reactive/officials/number.py +1 -2
  30. ex4nicegui/reactive/officials/row.py +18 -4
  31. ex4nicegui/reactive/q_pagination.py +33 -29
  32. ex4nicegui/reactive/usePagination.py +6 -4
  33. ex4nicegui/reactive/utils.py +42 -3
  34. ex4nicegui/reactive/vfor.py +19 -39
  35. ex4nicegui/reactive/vmodel.py +210 -0
  36. ex4nicegui/tools/__init__.py +0 -1
  37. ex4nicegui/tools/debug.py +1 -1
  38. ex4nicegui/utils/signals.py +12 -2
  39. {ex4nicegui-0.5.1.dist-info → ex4nicegui-0.5.3.dist-info}/METADATA +60 -34
  40. {ex4nicegui-0.5.1.dist-info → ex4nicegui-0.5.3.dist-info}/RECORD +43 -38
  41. {ex4nicegui-0.5.1.dist-info → ex4nicegui-0.5.3.dist-info}/LICENSE +0 -0
  42. {ex4nicegui-0.5.1.dist-info → ex4nicegui-0.5.3.dist-info}/WHEEL +0 -0
  43. {ex4nicegui-0.5.1.dist-info → ex4nicegui-0.5.3.dist-info}/top_level.txt +0 -0
ex4nicegui/__init__.py CHANGED
@@ -17,15 +17,12 @@ from ex4nicegui.utils.signals import (
17
17
  deep_ref,
18
18
  is_setter_ref,
19
19
  batch,
20
- )
21
- from ex4nicegui import tools
22
- from signe import batch
23
- from ex4nicegui.experimental_ import (
24
- gridLayout as exp_ui,
20
+ is_reactive,
25
21
  )
26
22
 
27
23
 
28
24
  __all__ = [
25
+ "is_reactive",
29
26
  "rxui",
30
27
  "ref_computed",
31
28
  "effect",
@@ -46,4 +43,4 @@ __all__ = [
46
43
  "is_setter_ref",
47
44
  ]
48
45
 
49
- __version__ = "0.5.1"
46
+ __version__ = "0.5.3"
@@ -21,7 +21,6 @@ from .elements.ui_range import ui_range
21
21
  from .elements.ui_echarts import ui_echarts
22
22
  from .elements.ui_aggrid import ui_aggrid
23
23
  from .elements.ui_table import ui_table
24
- from ex4nicegui.bi import types as bi_types
25
24
 
26
25
  if TYPE_CHECKING:
27
26
  from ex4nicegui.bi.elements.models import (
@@ -43,9 +42,7 @@ class DataSourceFacade(Generic[_TData]):
43
42
  @property
44
43
  def filtered_data(self) -> _TData:
45
44
  """Data after filtering"""
46
- return cast(
47
- _TData, self._dataSource.filtered_data
48
- )
45
+ return cast(_TData, self._dataSource.filtered_data)
49
46
 
50
47
  def reload(self, data, reset_filters=True):
51
48
  """Reload the data source with the provided new data.
@@ -59,9 +56,7 @@ class DataSourceFacade(Generic[_TData]):
59
56
  if reset_filters:
60
57
  self.remove_filters()
61
58
 
62
- def remove_filters(
63
- self, *components: UiResult
64
- ):
59
+ def remove_filters(self, *components: UiResult):
65
60
  """Remove the filter from the data source"""
66
61
  if len(components) == 0:
67
62
  # remove all
@@ -73,9 +68,7 @@ class DataSourceFacade(Generic[_TData]):
73
68
  self,
74
69
  column: str,
75
70
  *,
76
- sort_options: Optional[
77
- bi_types._TDuplicates_column_values_sort_options
78
- ] = None,
71
+ sort_options: Optional[bi_types._TDuplicates_column_values_sort_options] = None,
79
72
  exclude_null_value=False,
80
73
  clearable=True,
81
74
  multiple=True,
@@ -97,11 +90,7 @@ class DataSourceFacade(Generic[_TData]):
97
90
  Returns:
98
91
  SelectResult: An instance of a user interface select box.
99
92
  """
100
- kws = {
101
- key: value
102
- for key, value in locals().items()
103
- if key not in ("kwargs")
104
- }
93
+ kws = {key: value for key, value in locals().items() if key not in ("kwargs")}
105
94
  kws.update(kwargs)
106
95
  return ui_select(**kws)
107
96
 
@@ -124,11 +113,7 @@ class DataSourceFacade(Generic[_TData]):
124
113
  Returns:
125
114
  ui.aggrid: aggrid table.
126
115
  """
127
- kws = {
128
- key: value
129
- for key, value in locals().items()
130
- if key not in ("kwargs")
131
- }
116
+ kws = {key: value for key, value in locals().items() if key not in ("kwargs")}
132
117
  kws.update(kwargs)
133
118
  return ui_aggrid(**kws)
134
119
 
@@ -152,11 +137,7 @@ class DataSourceFacade(Generic[_TData]):
152
137
  Returns:
153
138
  ui.table: ui.table.
154
139
  """
155
- kws = {
156
- key: value
157
- for key, value in locals().items()
158
- if key not in ("kwargs")
159
- }
140
+ kws = {key: value for key, value in locals().items() if key not in ("kwargs")}
160
141
  kws.update(kwargs)
161
142
  return ui_table(**kws)
162
143
 
@@ -164,14 +145,10 @@ class DataSourceFacade(Generic[_TData]):
164
145
  self,
165
146
  column: str,
166
147
  *,
167
- sort_options: Optional[
168
- bi_types._TDuplicates_column_values_sort_options
169
- ] = None,
148
+ sort_options: Optional[bi_types._TDuplicates_column_values_sort_options] = None,
170
149
  exclude_null_value=False,
171
150
  hide_filtered=True,
172
- custom_options_map: Optional[
173
- Union[Dict, Callable[[Any], Any]]
174
- ] = None,
151
+ custom_options_map: Optional[Union[Dict, Callable[[Any], Any]]] = None,
175
152
  **kwargs,
176
153
  ):
177
154
  """
@@ -189,11 +166,7 @@ class DataSourceFacade(Generic[_TData]):
189
166
  Returns:
190
167
  RadioResult: An radio Selection.
191
168
  """
192
- kws = {
193
- key: value
194
- for key, value in locals().items()
195
- if key not in ("kwargs")
196
- }
169
+ kws = {key: value for key, value in locals().items() if key not in ("kwargs")}
197
170
  kws.update(kwargs)
198
171
  return ui_radio(**kws)
199
172
 
@@ -213,11 +186,7 @@ class DataSourceFacade(Generic[_TData]):
213
186
  Returns:
214
187
  ui.radio: An Slider.
215
188
  """
216
- kws = {
217
- key: value
218
- for key, value in locals().items()
219
- if key not in ("kwargs")
220
- }
189
+ kws = {key: value for key, value in locals().items() if key not in ("kwargs")}
221
190
  kws.update(kwargs)
222
191
  return ui_slider(**kws)
223
192
 
@@ -237,19 +206,13 @@ class DataSourceFacade(Generic[_TData]):
237
206
  Returns:
238
207
  QRange: An Range.
239
208
  """
240
- kws = {
241
- key: value
242
- for key, value in locals().items()
243
- if key not in ("kwargs")
244
- }
209
+ kws = {key: value for key, value in locals().items() if key not in ("kwargs")}
245
210
  kws.update(kwargs)
246
211
  return ui_range(**kws)
247
212
 
248
213
  def ui_echarts(
249
214
  self,
250
- fn: Callable[
251
- [Any], Union[Dict, "pyecharts.Base"]
252
- ], # pyright: ignore
215
+ fn: Callable[[Any], Union[Dict, "pyecharts.Base"]], # pyright: ignore # noqa: F821
253
216
  ):
254
217
  """Create charts
255
218
 
@@ -295,15 +258,7 @@ class DataSourceFacade(Generic[_TData]):
295
258
  filter: bi_types._TFilterCallback[_TData],
296
259
  ):
297
260
  ele_id = element.id
298
- key = self._dataSource.get_component_info_key(
299
- ele_id
300
- )
301
- if not self._dataSource._component_map.has_record(
302
- key
303
- ):
304
- self._dataSource._register_component(
305
- ele_id
306
- )
307
- self._dataSource.send_filter(
308
- ele_id, Filter(filter)
309
- )
261
+ key = self._dataSource.get_component_info_key(ele_id)
262
+ if not self._dataSource._component_map.has_record(key):
263
+ self._dataSource._register_component(ele_id)
264
+ self._dataSource.send_filter(ele_id, Filter(filter))
@@ -1,4 +1,4 @@
1
- from typing import Callable, Any, Union
1
+ from typing import Callable, Any
2
2
  from nicegui import ui
3
3
  from ex4nicegui.utils.signals import effect
4
4
 
@@ -1,5 +1,5 @@
1
1
  from __future__ import annotations
2
- from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Union
2
+ from typing import TYPE_CHECKING, Callable, Dict, Optional, Union
3
3
  from nicegui import ui
4
4
  from ex4nicegui.bi.dataSource import DataSource
5
5
  from .models import UiResult
@@ -60,7 +60,7 @@ def ui_aggrid(
60
60
  cp._props["options"] = options
61
61
  cp.update()
62
62
 
63
- info = self._dataSource._register_component(cp.id, on_source_update)
63
+ self._dataSource._register_component(cp.id, on_source_update)
64
64
 
65
65
  on_source_update()
66
66
 
@@ -1,5 +1,5 @@
1
1
  from __future__ import annotations
2
- from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Union, cast
2
+ from typing import TYPE_CHECKING, Any, Callable, Dict, Union, cast
3
3
  from nicegui.events import UiEventArguments
4
4
  from ex4nicegui.reactive import rxui
5
5
  from ex4nicegui.reactive.EChartsComponent.ECharts import (
@@ -36,7 +36,7 @@ class EChartsResult(UiResult[echarts]):
36
36
 
37
37
  def ui_echarts(
38
38
  self: DataSourceFacade,
39
- fn: Callable[[Any], Union[Dict, "pyecharts.Base"]], # pyright: ignore
39
+ fn: Callable[[Any], Union[Dict, "pyecharts.Base"]], # pyright: ignore # noqa: F821
40
40
  **kwargs,
41
41
  ):
42
42
  def create_options(data):
@@ -60,7 +60,7 @@ def ui_echarts(
60
60
  options = create_options(data)
61
61
  cp.element.update_options(options)
62
62
 
63
- info = self._dataSource._register_component(ele_id, on_source_update)
63
+ self._dataSource._register_component(ele_id, on_source_update)
64
64
 
65
65
  cp.element.update_options(
66
66
  create_options(self._dataSource.get_filtered_data(cp.element))
@@ -28,7 +28,7 @@ class SliderResult(UiResult[ui.slider]):
28
28
 
29
29
  def _reset_state(self):
30
30
  min = self._init_data["min"]
31
- max = self._init_data["max"]
31
+ max = self._init_data["max"] # noqa: F841
32
32
  self._ref_value.value = min
33
33
  self.element.set_value(min)
34
34
 
@@ -1,5 +1,5 @@
1
1
  from __future__ import annotations
2
- from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union
2
+ from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Union
3
3
  from nicegui import ui
4
4
  from ex4nicegui.bi.dataSource import DataSource
5
5
  from .models import UiResult
@@ -52,7 +52,7 @@ def ui_table(
52
52
  cp.columns = _merge_columns(fixed_columns, opts["columns"])
53
53
  cp.update()
54
54
 
55
- info = self._dataSource._register_component(cp.id, on_source_update)
55
+ self._dataSource._register_component(cp.id, on_source_update)
56
56
 
57
57
  on_source_update()
58
58
 
@@ -5,7 +5,6 @@ from ex4nicegui.bi.types import (
5
5
  _TFilterCallback,
6
6
  _TDuplicates_column_values_sort_options,
7
7
  )
8
- from .types import _TFilterCallback
9
8
  from ex4nicegui.utils import common as utils_common
10
9
 
11
10
 
ex4nicegui/bi/types.py CHANGED
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
  from typing import Callable, Dict, Literal, TypeVar
3
- from typing import TYPE_CHECKING
4
3
 
5
4
 
6
5
  _TData = TypeVar("_TData")
@@ -1 +1,5 @@
1
1
  from . import gridLayout as exp_ui
2
+
3
+ __all__ = [
4
+ "exp_ui",
5
+ ]
@@ -1 +1,8 @@
1
1
  from .index import column, row, item, grid_flex
2
+
3
+ __all__ = [
4
+ "column",
5
+ "row",
6
+ "item",
7
+ "grid_flex",
8
+ ]
@@ -1 +1,12 @@
1
1
  from .gsap import set_defaults, from_, to, new, run_script
2
+ from .timeline import Timeline as timeline
3
+
4
+
5
+ __all__ = [
6
+ "set_defaults",
7
+ "from_",
8
+ "to",
9
+ "new",
10
+ "run_script",
11
+ "timeline",
12
+ ]
@@ -0,0 +1,56 @@
1
+ import { gsap } from "gsap";
2
+ import { convertDynamicProperties } from "../../static/utils/dynamic_properties.js";
3
+
4
+
5
+ export default {
6
+ template: `<template></template>`,
7
+ data() {
8
+
9
+ const tl = gsap.timeline(this.defaults)
10
+ this.tl = tl
11
+
12
+ return {
13
+ }
14
+
15
+ },
16
+ mounted() {
17
+ document.addEventListener('DOMContentLoaded', () => {
18
+ /**
19
+ * @type any[]
20
+ */
21
+ const tasks = this.tasks
22
+ tasks.forEach(t => {
23
+ this[t.method](t.targets, t.vars, t.position)
24
+ })
25
+
26
+ this.scriptTasks.forEach(script => {
27
+ const fn = new Function('return ' + script)()
28
+ fn(this.tl, gsap)
29
+ })
30
+
31
+ })
32
+ },
33
+
34
+ methods: {
35
+ from(targets, vars, position) {
36
+ convertDynamicProperties(vars, false)
37
+ this.tl.from(targets, vars, position)
38
+ },
39
+ to(targets, vars, position) {
40
+ convertDynamicProperties(vars, false)
41
+ this.tl.to(targets, vars, position)
42
+ },
43
+ runScript(script) {
44
+ const fn = new Function('return ' + script)()
45
+ fn(this.tl, gsap)
46
+ },
47
+ callTimeline(name, ...args) {
48
+ this.tl[name](...args)
49
+ }
50
+ },
51
+ props: {
52
+ defaults: Object,
53
+ tasks: Array,
54
+ scriptTasks: Array,
55
+ },
56
+ };
@@ -0,0 +1,78 @@
1
+ import os
2
+ from pathlib import Path
3
+ from typing import Dict, Optional, Union
4
+ from nicegui.element import Element
5
+ from nicegui import context as ng_context
6
+
7
+
8
+ class Timeline(
9
+ Element,
10
+ component="timeline.js",
11
+ exposed_libraries=["../libs/gsap/gsap.mjs"],
12
+ extra_libraries=["../libs/gsap/*.js", "../libs/gsap/utils/*.js"],
13
+ ):
14
+ def __init__(
15
+ self,
16
+ defaults: Optional[Dict] = None,
17
+ ) -> None:
18
+ super().__init__()
19
+ self._props["defaults"] = defaults or {}
20
+ self._props["tasks"] = []
21
+ self._props["scriptTasks"] = []
22
+
23
+ def from_(self, targets: str, vars: Dict, position: Optional[str] = None):
24
+ self.__try_run_task("from", targets, vars, position)
25
+ return self
26
+
27
+ def to(self, targets: str, vars: Dict, position: Optional[str] = None):
28
+ self.__try_run_task("to", targets, vars, position)
29
+ return self
30
+
31
+ def run_script(self, script: Union[str, Path]):
32
+ if isinstance(script, Path):
33
+ script = script.read_text("utf8")
34
+
35
+ script = os.linesep.join([s for s in script.splitlines() if s])
36
+ self.__try_run_script_task(script)
37
+ return self
38
+
39
+ def __try_run_script_task(self, script: str):
40
+ def fn():
41
+ self.run_method("runScript", script)
42
+
43
+ if ng_context.get_client().has_socket_connection:
44
+ fn()
45
+ else:
46
+ tasks = self._props["scriptTasks"]
47
+ tasks.append(script)
48
+
49
+ def __try_run_task(
50
+ self, name: str, targets: str, vars: Dict, position: Optional[str] = None
51
+ ):
52
+ def fn():
53
+ self.run_method(name, targets, vars)
54
+
55
+ if ng_context.get_client().has_socket_connection:
56
+ fn()
57
+ else:
58
+ tasks = self._props["tasks"]
59
+ tasks.append(
60
+ {"method": name, "targets": targets, "vars": vars, "position": position}
61
+ )
62
+
63
+ def pause(self):
64
+ self.run_method("callTimeline", "pause")
65
+
66
+ def play(self):
67
+ self.run_method("callTimeline", "play")
68
+
69
+ def resume(
70
+ self,
71
+ ):
72
+ self.run_method("callTimeline", "resume")
73
+
74
+ def seek(self, position: Optional[str] = None, suppressEvents=True):
75
+ self.run_method("callTimeline", "seek", position, suppressEvents)
76
+
77
+ def reverse(self):
78
+ self.run_method("callTimeline", "reverse")
@@ -1,2 +1,13 @@
1
- from .gridFlex import *
2
- from .rxFlex import *
1
+ from .gridFlex.gridFlex import grid_flex, grid_box, mark_area, item_position, GridFlex
2
+ from .rxFlex.index import rx_column, rx_row
3
+
4
+
5
+ __all__ = [
6
+ "grid_flex",
7
+ "grid_box",
8
+ "mark_area",
9
+ "item_position",
10
+ "GridFlex",
11
+ "rx_column",
12
+ "rx_row",
13
+ ]
@@ -1 +1 @@
1
- from .gridFlex import grid_flex, grid_box, mark_area, item_position, GridFlex
1
+
@@ -1,9 +1,7 @@
1
- from typing import Dict, Optional
1
+ from typing import Dict, Optional, Union, Literal
2
2
  from nicegui import ui
3
3
  from nicegui.element import Element
4
4
 
5
- from typing_extensions import Literal
6
- from typing import Optional, Union
7
5
  from . import utils
8
6
 
9
7
 
@@ -1 +0,0 @@
1
- from .index import rx_column, rx_row
@@ -1,9 +1,19 @@
1
- from typing import Callable, List, Optional, Union, TypeVar, Generic
2
- from typing_extensions import Literal
3
-
4
- from ex4nicegui.layout import grid_box, mark_area
5
- from nicegui import ui, app
6
- from .types import *
1
+ from typing import Callable, Union, TypeVar
2
+
3
+ from nicegui import ui
4
+ from .types import (
5
+ TColumn_Horizontal,
6
+ TColumn_Vertical,
7
+ TColumn_Item_Horizontal,
8
+ Column_Item_Horizontal_map,
9
+ Column_Horizontal_map,
10
+ Column_Vertical_map,
11
+ TRow_Horizontal,
12
+ TRow_Vertical,
13
+ TRow_Item_Vertical,
14
+ Row_Vertical_map,
15
+ Row_Horizontal_map,
16
+ )
7
17
 
8
18
  _T_itemWraper_add_var = TypeVar("_T_itemWraper_add_var")
9
19
 
@@ -44,10 +44,11 @@ from .officials.number import NumberBindableUi as number
44
44
  from .officials.grid import GridBindableUi as grid
45
45
  from .officials.expansion import ExpansionBindableUi as expansion
46
46
  from .officials.linear_progress import LinearProgressBindableUi as linear_progress
47
+ from .officials.knob import KnobBindableUi as knob
48
+ from .officials.circular_progress import CircularProgressBindableUi as circular_progress
49
+ from .q_pagination import PaginationBindableUi as q_pagination
47
50
 
48
- from .q_pagination import QPagination as q_pagination
49
51
  from .local_file_picker import local_file_picker
50
- from ex4nicegui.utils.signals import ref_computed, effect
51
52
  from .UseDraggable.UseDraggable import use_draggable
52
53
  from .useMouse.UseMouse import use_mouse
53
54
 
@@ -56,3 +57,57 @@ from .dropZone.dropZone import use_drag_zone
56
57
  from .fileWatcher import FilesWatcher
57
58
  from .mermaid.mermaid import Mermaid as mermaid
58
59
  from .vfor import vfor, VforStore
60
+ from .vmodel import vmodel
61
+
62
+ pagination = q_pagination
63
+
64
+
65
+ __all__ = [
66
+ "circular_progress",
67
+ "knob",
68
+ "UploadResult",
69
+ "local_file_picker",
70
+ "use_draggable",
71
+ "use_mouse",
72
+ "use_pagination",
73
+ "use_drag_zone",
74
+ "FilesWatcher",
75
+ "vfor",
76
+ "VforStore",
77
+ "vmodel",
78
+ "html",
79
+ "aggird",
80
+ "button",
81
+ "card",
82
+ "card_actions",
83
+ "card_section",
84
+ "checkbox",
85
+ "color_picker",
86
+ "lazy_color_picker",
87
+ "date",
88
+ "drawer",
89
+ "echarts",
90
+ "icon",
91
+ "image",
92
+ "input",
93
+ "lazy_input",
94
+ "label",
95
+ "radio",
96
+ "row",
97
+ "select",
98
+ "slider",
99
+ "lazy_slider",
100
+ "switch",
101
+ "table",
102
+ "textarea",
103
+ "lazy_textarea",
104
+ "upload",
105
+ "column",
106
+ "number",
107
+ "grid",
108
+ "expansion",
109
+ "linear_progress",
110
+ "q_pagination",
111
+ "pagination",
112
+ "mermaid",
113
+ ]
@@ -34,7 +34,7 @@ class FilesWatcher:
34
34
  ):
35
35
  for fn in self.callbacks:
36
36
  fn(file)
37
- except RuntimeError as e:
37
+ except RuntimeError:
38
38
  return
39
39
 
40
40
  if asyncio.get_event_loop().is_running():
@@ -1,4 +1,4 @@
1
- from typing import Any, Callable, Optional, cast, List
1
+ from typing import Callable, Optional, List
2
2
  from typing_extensions import Literal
3
3
  from signe import signal, effect, computed
4
4
  from nicegui import ui, Tailwind
@@ -4,7 +4,6 @@ from typing import (
4
4
  Optional,
5
5
  )
6
6
  from ex4nicegui.reactive.utils import ParameterClassifier
7
- from ex4nicegui.utils.apiEffect import ui_effect
8
7
  from ex4nicegui.utils.signals import (
9
8
  ReadonlyRef,
10
9
  _TMaybeRef as TMaybeRef,
@@ -0,0 +1,64 @@
1
+ from typing import (
2
+ Optional,
3
+ )
4
+ from ex4nicegui.reactive.utils import ParameterClassifier
5
+ from ex4nicegui.utils.apiEffect import ui_effect
6
+
7
+ from ex4nicegui.utils.signals import (
8
+ ReadonlyRef,
9
+ _TMaybeRef as TMaybeRef,
10
+ to_value,
11
+ )
12
+ from nicegui import ui
13
+ from .base import BindableUi, DisableableMixin
14
+
15
+
16
+ class CircularProgressBindableUi(
17
+ BindableUi[ui.circular_progress],
18
+ DisableableMixin,
19
+ ):
20
+ def __init__(
21
+ self,
22
+ value: TMaybeRef[float] = 0.0,
23
+ *,
24
+ min: TMaybeRef[float] = 0.0, # pylint: disable=redefined-builtin
25
+ max: TMaybeRef[float] = 1.0, # pylint: disable=redefined-builtin
26
+ size: Optional[TMaybeRef[str]] = "xl",
27
+ show_value: TMaybeRef[bool] = True,
28
+ color: Optional[TMaybeRef[str]] = "primary",
29
+ ) -> None:
30
+ pc = ParameterClassifier(
31
+ locals(),
32
+ maybeRefs=[
33
+ "value",
34
+ "min",
35
+ "max",
36
+ "color",
37
+ "size",
38
+ "show_value",
39
+ ],
40
+ )
41
+
42
+ value_kws = pc.get_values_kws()
43
+ element = ui.circular_progress(**value_kws)
44
+ super().__init__(element) # type: ignore
45
+
46
+ for key, value in pc.get_bindings().items():
47
+ self.bind_prop(key, value) # type: ignore
48
+
49
+ @property
50
+ def value(self):
51
+ return self.element.value
52
+
53
+ def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
54
+ if prop == "value":
55
+ return self.bind_value(ref_ui)
56
+
57
+ return super().bind_prop(prop, ref_ui)
58
+
59
+ def bind_value(self, ref_ui: ReadonlyRef[float]):
60
+ @ui_effect
61
+ def _():
62
+ self.element.set_value(to_value(ref_ui))
63
+
64
+ return self