ex4nicegui 0.7.0__py3-none-any.whl → 0.7.1__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/reactive/__init__.py +6 -0
  2. ex4nicegui/reactive/base.py +3 -1
  3. ex4nicegui/reactive/mixins/backgroundColor.py +1 -1
  4. ex4nicegui/reactive/mixins/textColor.py +1 -1
  5. ex4nicegui/reactive/officials/avatar.py +86 -0
  6. ex4nicegui/reactive/officials/badge.py +102 -0
  7. ex4nicegui/reactive/officials/checkbox.py +1 -2
  8. ex4nicegui/reactive/officials/chip.py +1 -2
  9. ex4nicegui/reactive/officials/circular_progress.py +1 -1
  10. ex4nicegui/reactive/officials/color_picker.py +1 -1
  11. ex4nicegui/reactive/officials/date.py +1 -1
  12. ex4nicegui/reactive/officials/dialog.py +1 -1
  13. ex4nicegui/reactive/officials/echarts.py +1 -1
  14. ex4nicegui/reactive/officials/expansion.py +1 -1
  15. ex4nicegui/reactive/officials/icon.py +2 -8
  16. ex4nicegui/reactive/officials/image.py +1 -1
  17. ex4nicegui/reactive/officials/input.py +2 -3
  18. ex4nicegui/reactive/officials/knob.py +1 -1
  19. ex4nicegui/reactive/officials/label.py +6 -4
  20. ex4nicegui/reactive/officials/linear_progress.py +1 -1
  21. ex4nicegui/reactive/officials/number.py +2 -2
  22. ex4nicegui/reactive/officials/radio.py +2 -2
  23. ex4nicegui/reactive/officials/select.py +2 -2
  24. ex4nicegui/reactive/officials/slider.py +1 -1
  25. ex4nicegui/reactive/officials/switch.py +1 -2
  26. ex4nicegui/reactive/officials/textarea.py +1 -1
  27. ex4nicegui/reactive/officials/toggle.py +88 -0
  28. ex4nicegui/reactive/officials/tooltip.py +1 -1
  29. ex4nicegui/reactive/systems/reactive_system.py +2 -2
  30. ex4nicegui/reactive/view_model.py +4 -4
  31. {ex4nicegui-0.7.0.dist-info → ex4nicegui-0.7.1.dist-info}/METADATA +5 -1
  32. {ex4nicegui-0.7.0.dist-info → ex4nicegui-0.7.1.dist-info}/RECORD +34 -31
  33. {ex4nicegui-0.7.0.dist-info → ex4nicegui-0.7.1.dist-info}/LICENSE +0 -0
  34. {ex4nicegui-0.7.0.dist-info → ex4nicegui-0.7.1.dist-info}/WHEEL +0 -0
@@ -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)
@@ -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)
@@ -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,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
@@ -50,9 +50,8 @@ class CheckboxBindableUi(BindableUi[ui.checkbox], DisableableMixin):
50
50
  return super().bind_prop(prop, value)
51
51
 
52
52
  def bind_value(self, value: TGetterOrReadonlyRef[bool]):
53
- @self._ui_effect
53
+ @self._ui_signal_on(value)
54
54
  def _():
55
55
  self.element.set_value(to_value(value))
56
- self.element.update()
57
56
 
58
57
  return self
@@ -94,9 +94,8 @@ class ChipBindableUi(
94
94
 
95
95
  """
96
96
 
97
- @self._ui_effect
97
+ @self._ui_signal_on(text)
98
98
  def _():
99
99
  self.element.set_text(str(to_value(text)))
100
- self.element.update()
101
100
 
102
101
  return self
@@ -58,7 +58,7 @@ class CircularProgressBindableUi(
58
58
  return super().bind_prop(prop, value)
59
59
 
60
60
  def bind_value(self, value: TGetterOrReadonlyRef[float]):
61
- @self._ui_effect
61
+ @self._ui_signal_on(value)
62
62
  def _():
63
63
  self.element.set_value(to_value(value))
64
64
 
@@ -82,7 +82,7 @@ class ColorPickerBindableUi(BindableUi[ui.color_picker]):
82
82
  return self
83
83
 
84
84
  def bind_value(self, value: TGetterOrReadonlyRef[bool]):
85
- @self._ui_effect
85
+ @self._ui_signal_on(value)
86
86
  def _():
87
87
  self.element.set_value(to_value(value))
88
88
 
@@ -69,7 +69,7 @@ class DateBindableUi(BindableUi[ui.date]):
69
69
  return super().bind_prop(prop, value)
70
70
 
71
71
  def bind_value(self, value: TGetterOrReadonlyRef[bool]):
72
- @self._ui_effect
72
+ @self._ui_signal_on(value)
73
73
  def _():
74
74
  self.element.set_value(to_value(value))
75
75
 
@@ -42,7 +42,7 @@ class DialogBindableUi(BindableUi[ui.dialog]):
42
42
  return super().bind_prop(prop, value)
43
43
 
44
44
  def bind_value(self, value: TGetterOrReadonlyRef[float]):
45
- @self._ui_effect
45
+ @self._ui_signal_on(value)
46
46
  def _():
47
47
  self.element.set_value(to_value(value))
48
48
 
@@ -139,7 +139,7 @@ class EChartsBindableUi(BindableUi[echarts]):
139
139
  return super().bind_prop(prop, value)
140
140
 
141
141
  def bind_options(self, options: TGetterOrReadonlyRef[Dict]):
142
- @self._ui_signal_on(options)
142
+ @self._ui_signal_on(options, deep=True)
143
143
  def _():
144
144
  ele = self.element
145
145
  ele.update_options(to_raw(to_value(options)), self.__update_setting)
@@ -52,7 +52,7 @@ class ExpansionBindableUi(BindableUi[ui.expansion]):
52
52
  return super().bind_prop(prop, value)
53
53
 
54
54
  def bind_value(self, value: TGetterOrReadonlyRef):
55
- @self._ui_effect
55
+ @self._ui_signal_on(value)
56
56
  def _():
57
57
  self.element.set_value(to_value(value))
58
58
 
@@ -1,6 +1,5 @@
1
1
  from typing import (
2
2
  Optional,
3
- cast,
4
3
  )
5
4
  from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
6
5
  from ex4nicegui.utils.signals import (
@@ -9,9 +8,6 @@ from ex4nicegui.utils.signals import (
9
8
  to_value,
10
9
  )
11
10
  from nicegui import ui
12
- from nicegui.elements.mixins.color_elements import (
13
- TextColorElement,
14
- )
15
11
  from .base import BindableUi
16
12
  from ex4nicegui.reactive.mixins.textColor import TextColorableMixin
17
13
 
@@ -44,10 +40,8 @@ class IconBindableUi(BindableUi[ui.icon], TextColorableMixin):
44
40
  return super().bind_prop(prop, value)
45
41
 
46
42
  def bind_name(self, name: TGetterOrReadonlyRef):
47
- @self._ui_effect
43
+ @self._ui_signal_on(name)
48
44
  def _():
49
- ele = cast(TextColorElement, self.element)
50
- ele._props["name"] = to_value(name)
51
- ele.update()
45
+ self.element.set_name(to_value(name))
52
46
 
53
47
  return self
@@ -32,6 +32,6 @@ class ImageBindableUi(BindableUi[ui.image]):
32
32
  return super().bind_prop(prop, value)
33
33
 
34
34
  def bind_source(self, source: TGetterOrReadonlyRef[Union[str, Path]]):
35
- @self._ui_effect
35
+ @self._ui_signal_on(source, deep=False)
36
36
  def _():
37
37
  self.element.set_source(to_value(source))
@@ -60,15 +60,14 @@ class InputBindableUi(BindableUi[ui.input], DisableableMixin):
60
60
  return super().bind_prop(prop, value)
61
61
 
62
62
  def bind_value(self, value: TGetterOrReadonlyRef[str]):
63
- @self._ui_effect
63
+ @self._ui_signal_on(value)
64
64
  def _():
65
65
  self.element.set_value(to_value(value))
66
- self.element.update()
67
66
 
68
67
  return self
69
68
 
70
69
  def bind_password(self, password: TGetterOrReadonlyRef[bool]):
71
- @self._ui_effect
70
+ @self._ui_signal_on(password)
72
71
  def _():
73
72
  self.element._props["type"] = "password" if to_value(password) else "text"
74
73
  self.element.update()
@@ -70,7 +70,7 @@ class KnobBindableUi(
70
70
  return super().bind_prop(prop, value)
71
71
 
72
72
  def bind_value(self, value: TGetterOrReadonlyRef[float]):
73
- @self._ui_effect
73
+ @self._ui_signal_on(value)
74
74
  def _():
75
75
  self.element.set_value(to_value(value))
76
76
 
@@ -3,6 +3,7 @@ from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
3
3
  from ex4nicegui.utils.signals import (
4
4
  TGetterOrReadonlyRef,
5
5
  to_value,
6
+ to_raw,
6
7
  _TMaybeRef as TMaybeRef,
7
8
  )
8
9
  from nicegui import ui
@@ -17,7 +18,9 @@ class LabelBindableUi(BindableUi[ui.label], HtmlTextColorableMixin):
17
18
  ) -> None:
18
19
  pc = ParameterClassifier(locals(), maybeRefs=["text"], events=[])
19
20
 
20
- element = ui.label(**pc.get_values_kws())
21
+ init_kws = pc.get_values_kws()
22
+ init_kws.update({"text": str(init_kws.get("text", ""))})
23
+ element = ui.label(**init_kws)
21
24
  super().__init__(element)
22
25
 
23
26
  for key, value in pc.get_bindings().items():
@@ -37,9 +40,8 @@ class LabelBindableUi(BindableUi[ui.label], HtmlTextColorableMixin):
37
40
  return super().bind_prop(prop, value)
38
41
 
39
42
  def bind_text(self, text: TGetterOrReadonlyRef):
40
- @self._ui_effect
43
+ @self._ui_signal_on(text, deep=True)
41
44
  def _():
42
- self.element.set_text(str(to_value(text)))
43
- self.element.update()
45
+ self.element.set_text(str(to_raw(to_value(text))))
44
46
 
45
47
  return self
@@ -56,7 +56,7 @@ class LinearProgressBindableUi(BindableUi[ui.linear_progress], TextColorableMixi
56
56
  return super().bind_prop(prop, value)
57
57
 
58
58
  def bind_value(self, value: TGetterOrReadonlyRef):
59
- @self._ui_effect
59
+ @self._ui_signal_on(value)
60
60
  def _():
61
61
  self.element.set_value(to_value(value))
62
62
 
@@ -80,14 +80,14 @@ class NumberBindableUi(BindableUi[ui.number]):
80
80
  return super().bind_prop(prop, value)
81
81
 
82
82
  def bind_value(self, value: TGetterOrReadonlyRef[float]):
83
- @self._ui_effect
83
+ @self._ui_signal_on(value)
84
84
  def _():
85
85
  self.element.set_value(to_value(value))
86
86
 
87
87
  return self
88
88
 
89
89
  def _bind_precision(self, precision: TGetterOrReadonlyRef[int]):
90
- @self._ui_signal_on(precision, onchanges=True)
90
+ @self._ui_signal_on(precision)
91
91
  def _():
92
92
  self.element.precision = to_value(precision)
93
93
  self.element.sanitize()
@@ -61,14 +61,14 @@ class RadioBindableUi(BindableUi[ui.radio]):
61
61
  return super().bind_prop(prop, value)
62
62
 
63
63
  def bind_options(self, options: TGetterOrReadonlyRef):
64
- @self._ui_effect
64
+ @self._ui_signal_on(options, deep=True)
65
65
  def _():
66
66
  self.element.set_options(to_value(options))
67
67
 
68
68
  return self
69
69
 
70
70
  def bind_value(self, value: TGetterOrReadonlyRef):
71
- @self._ui_effect
71
+ @self._ui_signal_on(value)
72
72
  def _():
73
73
  cast(ValueElement, self.element).set_value(to_value(value))
74
74
 
@@ -84,14 +84,14 @@ class SelectBindableUi(BindableUi[ui.select]):
84
84
  return super().bind_prop(prop, value)
85
85
 
86
86
  def bind_options(self, options: TGetterOrReadonlyRef):
87
- @self._ui_effect()
87
+ @self._ui_signal_on(options, deep=True)
88
88
  def _():
89
89
  self.element.set_options(to_value(options))
90
90
 
91
91
  return self
92
92
 
93
93
  def bind_value(self, value: TGetterOrReadonlyRef):
94
- @self._ui_effect()
94
+ @self._ui_signal_on(value, deep=True)
95
95
  def _():
96
96
  cast(ValueElement, self.element).set_value(to_raw(to_value(value)) or None)
97
97
 
@@ -65,7 +65,7 @@ class SliderBindableUi(
65
65
  return super().bind_prop(prop, value)
66
66
 
67
67
  def bind_value(self, value: TGetterOrReadonlyRef[float]):
68
- @self._ui_effect
68
+ @self._ui_signal_on(value)
69
69
  def _():
70
70
  self.element.set_value(to_value(value))
71
71
  self.element.update()
@@ -35,7 +35,6 @@ class SwitchBindableUi(BindableUi[ui.switch]):
35
35
  )
36
36
 
37
37
  value_kws = pc.get_values_kws()
38
- value_kws.update({"value": 0 if value is None else value})
39
38
 
40
39
  element = ui.switch(**value_kws)
41
40
  super().__init__(element) # type: ignore
@@ -54,7 +53,7 @@ class SwitchBindableUi(BindableUi[ui.switch]):
54
53
  return super().bind_prop(prop, value)
55
54
 
56
55
  def bind_value(self, value: TGetterOrReadonlyRef[bool]):
57
- @self._ui_effect
56
+ @self._ui_signal_on(value)
58
57
  def _():
59
58
  self.element.set_value(to_value(value))
60
59
 
@@ -59,7 +59,7 @@ class TextareaBindableUi(BindableUi[ui.textarea]):
59
59
  return super().bind_prop(prop, value)
60
60
 
61
61
  def bind_value(self, value: TGetterOrReadonlyRef[str]):
62
- @self._ui_effect
62
+ @self._ui_signal_on(value)
63
63
  def _():
64
64
  self.element.set_value(to_value(value))
65
65
 
@@ -0,0 +1,88 @@
1
+ from typing import (
2
+ Any,
3
+ Callable,
4
+ List,
5
+ Optional,
6
+ TypeVar,
7
+ Dict,
8
+ Union,
9
+ )
10
+ from ex4nicegui.reactive.services.reactive_service import ParameterClassifier
11
+ from ex4nicegui.utils.signals import (
12
+ TGetterOrReadonlyRef,
13
+ _TMaybeRef as TMaybeRef,
14
+ to_value,
15
+ to_raw,
16
+ )
17
+ from nicegui import ui
18
+ from .base import BindableUi
19
+
20
+ T = TypeVar("T")
21
+
22
+
23
+ class ToggleBindableUi(BindableUi[ui.toggle]):
24
+ def __init__(
25
+ self,
26
+ options: Union[TMaybeRef[List], TMaybeRef[Dict]],
27
+ *,
28
+ value: TMaybeRef[Any] = None,
29
+ on_change: Optional[Callable[..., Any]] = None,
30
+ clearable: TMaybeRef[bool] = False,
31
+ ) -> None:
32
+ """Toggle
33
+
34
+ This element is based on Quasar's `QBtnToggle <https://quasar.dev/vue-components/button-toggle>`_ component.
35
+
36
+ The options can be specified as a list of values, or as a dictionary mapping values to labels.
37
+ After manipulating the options, call `update()` to update the options in the UI.
38
+
39
+ :param options: a list ['value1', ...] or dictionary `{'value1':'label1', ...}` specifying the options
40
+ :param value: the initial value
41
+ :param on_change: callback to execute when selection changes
42
+ :param clearable: whether the toggle can be cleared by clicking the selected option
43
+ """
44
+ pc = ParameterClassifier(
45
+ locals(),
46
+ maybeRefs=[
47
+ "options",
48
+ "value",
49
+ "clearable",
50
+ ],
51
+ v_model=("value", "on_change"),
52
+ events=["on_change"],
53
+ )
54
+
55
+ value_kws = pc.get_values_kws()
56
+
57
+ element = ui.toggle(**value_kws)
58
+ super().__init__(element) # type: ignore
59
+
60
+ for key, value in pc.get_bindings().items():
61
+ self.bind_prop(key, value) # type: ignore
62
+
63
+ @property
64
+ def value(self):
65
+ return self.element.value
66
+
67
+ def bind_prop(self, prop: str, value: TGetterOrReadonlyRef):
68
+ if prop == "value":
69
+ return self.bind_value(value)
70
+
71
+ if prop == "options":
72
+ return self.bind_options(value)
73
+
74
+ return super().bind_prop(prop, value)
75
+
76
+ def bind_options(self, options: TGetterOrReadonlyRef):
77
+ @self._ui_signal_on(options, deep=True)
78
+ def _():
79
+ self.element.set_options(to_value(options))
80
+
81
+ return self
82
+
83
+ def bind_value(self, value: TGetterOrReadonlyRef):
84
+ @self._ui_signal_on(value, deep=True)
85
+ def _():
86
+ self.element.set_value(to_raw(to_value(value)) or None)
87
+
88
+ return self
@@ -33,7 +33,7 @@ class TooltipBindableUi(BindableUi[ui.tooltip]):
33
33
  return super().bind_prop(prop, value)
34
34
 
35
35
  def bind_text(self, text: TGetterOrReadonlyRef):
36
- @self._ui_effect
36
+ @self._ui_signal_on(text)
37
37
  def _():
38
38
  self.element.set_text(str(to_value(text)))
39
39
 
@@ -1,9 +1,9 @@
1
1
  from typing import Callable, Dict
2
- from ex4nicegui.utils.signals import to_value
2
+ from ex4nicegui.utils.signals import to_value, to_raw
3
3
 
4
4
 
5
5
  def convert_kws_ref2value(kws: Dict) -> Dict:
6
- return {key: to_value(value) for key, value in kws.items()}
6
+ return {key: to_raw(to_value(value)) for key, value in kws.items()}
7
7
 
8
8
 
9
9
  def inject_method(obj, method_name: str, new_handle: Callable):
@@ -24,7 +24,7 @@ class ViewModel(NoProxy):
24
24
 
25
25
  @see - https://github.com/CrystalWindSnake/ex4nicegui/blob/main/README.en.md#ViewModel
26
26
 
27
- @中文文档 - https://gitee.com/carson_add/ex4nicegui/tree/main/#ViewModel
27
+ @中文文档 - https://gitee.com/carson_add/ex4nicegui/tree/main/#viewmodel
28
28
 
29
29
  Example:
30
30
  .. code-block:: python
@@ -151,9 +151,9 @@ def cached_var(func: Callable[..., _T]) -> ReadonlyRef[_T]:
151
151
  class MyVm(rxui.ViewModel):
152
152
  name = rxui.var("John")
153
153
 
154
- @rxui.cached_var
155
- def uppper_name(self):
156
- return self.name.value.upper()
154
+ @rxui.cached_var
155
+ def uppper_name(self):
156
+ return self.name.value.upper()
157
157
 
158
158
  """
159
159
  setattr(func, _CACHED_VARS_FLAG, None)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ex4nicegui
3
- Version: 0.7.0
3
+ Version: 0.7.1
4
4
  Summary: Extension library based on nicegui, providing data responsive,BI functionality modules
5
5
  Home-page: https://github.com/CrystalWindSnake/ex4nicegui
6
6
  License: MIT
@@ -38,6 +38,10 @@ Description-Content-Type: text/markdown
38
38
  对 [nicegui](https://github.com/zauberzeug/nicegui) 做的扩展库。内置响应式组件,完全实现数据响应式界面编程。
39
39
 
40
40
 
41
+ ![todo-app](https://github.com/CrystalWindSnake/ex4nicegui-examples/blob/main/asset/todo-app.02.gif)
42
+
43
+ [查看更多示例](https://github.com/CrystalWindSnake/ex4nicegui-examples)
44
+
41
45
  ## 教程
42
46
  [头条文章-秒杀官方实现,python界面库,去掉90%事件代码的nicegui](https://www.toutiao.com/item/7253786340574265860/)
43
47
 
@@ -70,8 +70,8 @@ ex4nicegui/libs/gsap/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
70
70
  ex4nicegui/libs/gsap/utils/matrix.js,sha256=77scrxbQZXx4ex5HkvnT9IkhMG1rQoDNp4TSYgUeYVk,15235
71
71
  ex4nicegui/libs/gsap/utils/paths.js,sha256=2SPaRHQ7zgba9cH8hGhkTYPCZdrrEhE2qhh6ECAEvSA,49314
72
72
  ex4nicegui/libs/gsap/utils/strings.js,sha256=47G9slz5ltG9mDSwrfQDtWzzdV5QJ-AIMLRMNK0VSiM,10472
73
- ex4nicegui/reactive/__init__.py,sha256=Wokz5KhIb_E-v-TtdyVpZDpMyFE-QiCU-NlPOEVGKxQ,4132
74
- ex4nicegui/reactive/base.py,sha256=vNZyM18wwXuzUAEsoJZq1F9ogAHO9sPUbNMxshThJ4I,13907
73
+ ex4nicegui/reactive/__init__.py,sha256=nBMnascxWCEfozKNx8DyXGVGE8e3B0dMrv999g8Qvd4,4347
74
+ ex4nicegui/reactive/base.py,sha256=iqkGcy7BCfZOoMGaq74EYjdI6S44EGzagqIo2sUKGGw,14043
75
75
  ex4nicegui/reactive/deferredTask.py,sha256=g78TTG1EIkBxjPih01xmrCZw9OxQG93veSVSELWKfcU,987
76
76
  ex4nicegui/reactive/dropZone/dropZone.js,sha256=7rSpFJX-Fk_W_NGZhOTyuEw0bzR-YUc8ZYPzQG9KzE0,2713
77
77
  ex4nicegui/reactive/dropZone/dropZone.py,sha256=hg9UKTayff8v8Ek-n38h_3wX1Qmiotvdyv1Hsqilh5Y,2590
@@ -86,46 +86,49 @@ ex4nicegui/reactive/fileWatcher.py,sha256=gjeZhgar02f-qGQa47Tj5SMaCP_ftRtSU898XU
86
86
  ex4nicegui/reactive/local_file_picker.py,sha256=MoInXSauFdCuhYi_CmNKZwxAtsOqXh8roWWdqNwjPBY,6199
87
87
  ex4nicegui/reactive/mermaid/mermaid.js,sha256=Ds5VevGWZE1_N0WKf-uITd8xSCO9gQzVUsmb80EajNY,2308
88
88
  ex4nicegui/reactive/mermaid/mermaid.py,sha256=uP321QiNj_S5E5I2KF9h03WlSFdRITE8tvObGdk6m7M,2144
89
- ex4nicegui/reactive/mixins/backgroundColor.py,sha256=5d4v06_dypEFjkHvYfLOKLKa1qSLySMFUUesqf12vEg,1118
89
+ ex4nicegui/reactive/mixins/backgroundColor.py,sha256=ReW-clrdjqYLVXjrx8lo9h3JAvXPXpOJDl3b6GuBovA,1135
90
90
  ex4nicegui/reactive/mixins/disableable.py,sha256=bqhhU5XTT3E60-I0dr_mT0Gk9uX5-aKouAsu6MwCeV0,1133
91
- ex4nicegui/reactive/mixins/textColor.py,sha256=a-ZNbI2KE0S_pmIYvfKpGbRUAI_wY0SLc888qG7WJsE,1806
91
+ ex4nicegui/reactive/mixins/textColor.py,sha256=_OsiuybNyNX1qNdk-9DwhcdovtvvNCDKA_UsmDrejeU,1823
92
92
  ex4nicegui/reactive/officials/aggrid.py,sha256=GWxDfTzhcnlyzPhLzBI5ay6RtPcE2zOCMwZhMX5WBck,2973
93
+ ex4nicegui/reactive/officials/avatar.py,sha256=bAZ73B4wQWchGVFblc7r1QItrml9_VIwKQT-Lqtx1eA,3323
94
+ ex4nicegui/reactive/officials/badge.py,sha256=0OFKCfjdoZZf2v-MwZPLC5C-2TU4-dCACGOwAZlQDdg,3212
93
95
  ex4nicegui/reactive/officials/base.py,sha256=SVJz0UYPvlpSHN193X-EFCNT-lAP2LYEo8HJBQ0i8Tg,153
94
96
  ex4nicegui/reactive/officials/button.py,sha256=C1x-gwCKH6VWk0QqY2pUebAsaLLkMBx8GInk9KZg1K0,2666
95
97
  ex4nicegui/reactive/officials/card.py,sha256=8-tBwm3xfVybolQ87i8lAYUpBV6FdaVdeSH6xu0736U,1275
96
- ex4nicegui/reactive/officials/checkbox.py,sha256=ghO987s_xrOXbrnksbtM4kP8_mP4ggVKsQKrgPku9ac,1560
97
- ex4nicegui/reactive/officials/chip.py,sha256=ybAEAfBUnaEXw0eFLE3hTL4EaWIeMPATsCRDIuJgPH4,3180
98
- ex4nicegui/reactive/officials/circular_progress.py,sha256=0NAaLN0ytrS1S8EGmJQxci5ZDJ8JAY2ZwIxhQKCxtT4,1958
99
- ex4nicegui/reactive/officials/color_picker.py,sha256=Wz2RY68E55FDUavn8xXRAR4SX3wR-otnPTMSiNXW6w4,3413
98
+ ex4nicegui/reactive/officials/checkbox.py,sha256=EXxB79vTyFeJgrtGZ7sm-bj1gd3vwMZ5vUVfCG-IPKo,1535
99
+ ex4nicegui/reactive/officials/chip.py,sha256=3w3xI5-97nzPvNggO17MFXXlfokhJDWD3YdsrNC4o54,3154
100
+ ex4nicegui/reactive/officials/circular_progress.py,sha256=9obEbKzFGCx5yzGQ5-cKNr4mUq7T3uZXUqXiukW2no4,1968
101
+ ex4nicegui/reactive/officials/color_picker.py,sha256=RfGDHS3eW9aXF33Xip9VQxVHckAiVtlCtjyC6Ulh-QU,3423
100
102
  ex4nicegui/reactive/officials/column.py,sha256=RwmjQBTRN4x1vfm-ylfR1r1GjmsLY-3rNf1SqyMLjKI,1104
101
- ex4nicegui/reactive/officials/date.py,sha256=yiL8v0IJFfiX1rtw-MNHdqjuvz6AS00y4YV_KzjoaY0,2510
102
- ex4nicegui/reactive/officials/dialog.py,sha256=1M2mTpb3NQ6GWjibwKZf_brdEXGYZUmC-36BX_Vc9sk,1375
103
+ ex4nicegui/reactive/officials/date.py,sha256=-A-AOhiAoSXIygo6WOVM4_Jt5ksrnvtmSJZCFcJIgYk,2520
104
+ ex4nicegui/reactive/officials/dialog.py,sha256=weF06DNFmoTK62tmxS7f4IhT6QHezU2YBznro_EIw4k,1385
103
105
  ex4nicegui/reactive/officials/drawer.py,sha256=_Ro6stOh8U3igYMeDwI4omBgi1nld5berrAk9Dv5RVw,2346
104
- ex4nicegui/reactive/officials/echarts.py,sha256=QxCl_3e2GxXupXmICwlBXF9a0pMpZzCXGdxPmiqYMeI,10224
106
+ ex4nicegui/reactive/officials/echarts.py,sha256=2CV0Yed57ItVXdQ7gcHIbq5yceoVmgnoipJ-RpIsgnA,10235
105
107
  ex4nicegui/reactive/officials/element.py,sha256=-qsHcxfF3fMfU0sJlKtTksX_wYPMIPJ_AgFcZbbI754,412
106
- ex4nicegui/reactive/officials/expansion.py,sha256=OsrVttwuZXqAUYRIXI2QZnvqIJmEcu3Sfj_Iwqu_PKQ,1893
108
+ ex4nicegui/reactive/officials/expansion.py,sha256=ARQTsDkUQ-xZgCPgwGCRXqjpXhGzmJQgk95yYGKg6DU,1903
107
109
  ex4nicegui/reactive/officials/grid.py,sha256=Bq83jejsxQSYVc9O1IE6JUgUndUm1uexb4fq9EZWjHQ,921
108
110
  ex4nicegui/reactive/officials/html.js,sha256=lyvRAdMKZGOc7MPEapeU6WbOzq_MVzqzUJEhKuC8zWc,119
109
111
  ex4nicegui/reactive/officials/html.py,sha256=XrOpGoAJDo8dtTnZVLSmi7H5iHffmYpeZ94lXxHjBwI,629
110
- ex4nicegui/reactive/officials/icon.py,sha256=oOl5_geE2cXrXKyxA4XK-F4AYxNmTtWWFx0WR_36nEk,1536
111
- ex4nicegui/reactive/officials/image.py,sha256=a-iKjrkj672JspLCENXA1b9ABNwPO1D28WEgt5mmvwk,1118
112
- ex4nicegui/reactive/officials/input.py,sha256=E6YjkEhmYHrBXBUXu0vH30wJbczD7eSMrRNZpdeGkJE,4042
113
- ex4nicegui/reactive/officials/knob.py,sha256=WTTPEG7xOwfDC6GQ0BGzrFLIYyaUNeqzfwqystRs0xg,2315
114
- ex4nicegui/reactive/officials/label.py,sha256=SwU603HlLHULlhyvSo6-VLV_3MuWuhtHMQaUyfLWlLo,1327
115
- ex4nicegui/reactive/officials/linear_progress.py,sha256=7suAd_rLRkrviTkcuIt9LwkBr4YC57FeWeGgwTCStHQ,2107
116
- ex4nicegui/reactive/officials/number.py,sha256=xSqPXn07-ZLPPZ0lVhsXA-KpnWhSKWNcJIMqJsJQ58Q,2789
117
- ex4nicegui/reactive/officials/radio.py,sha256=u0jDUukowf4sCy2HERcmuI_OWea5aNl5FGWCACoGy4s,1941
112
+ ex4nicegui/reactive/officials/icon.py,sha256=Um1yS681pcbsZ4o7GU_2w1NCfwFVXNu1a4asB2hzYUg,1374
113
+ ex4nicegui/reactive/officials/image.py,sha256=ySu2gqVQIuLMUTItcp233Iqnx86P0q0MU8EVq07yuMk,1141
114
+ ex4nicegui/reactive/officials/input.py,sha256=zQ4LaN15AuQvqTOpv5L186zu3lsMJpwLJ25HWMYaIck,4030
115
+ ex4nicegui/reactive/officials/knob.py,sha256=Y2CtMvo0W_zZCqqjx_w1pyfCG9ZHBTLEVbUQpeEZ43U,2325
116
+ ex4nicegui/reactive/officials/label.py,sha256=kCair4NpFB7bvsPukMFcDBqDXk2BxOLzBQXSNx5EWuw,1428
117
+ ex4nicegui/reactive/officials/linear_progress.py,sha256=SthaOJJuJF4LbIlzTvUJRWziOJtIFMyhdjCWmPGcn2U,2117
118
+ ex4nicegui/reactive/officials/number.py,sha256=8Lk1yrbPskJathnlo7J_KssJSHZXYH9Pe4GMfbk4gzo,2783
119
+ ex4nicegui/reactive/officials/radio.py,sha256=9vQf__Uz-ED9yPZj2MLhsQKbHD_PNlm4DvPl-Xi8xV8,1974
118
120
  ex4nicegui/reactive/officials/row.py,sha256=GBz0VW34rOqvGgsA0vA_93WSa2i1F9Lt7jf2UrRevDs,1044
119
- ex4nicegui/reactive/officials/select.py,sha256=gwg_5JpzQxrBQM33EV0wXcZdq-d9_i4vKQ8egNH-dsU,3013
120
- ex4nicegui/reactive/officials/slider.py,sha256=qX1IZWG88gtE1MRpc1InCEa4MohqCwUEweopblm1ldY,2966
121
- ex4nicegui/reactive/officials/switch.py,sha256=lpqHYl3IvE4igcB8_XEZPZ7XPxIcH5BplzkLrLr7PQo,1601
121
+ ex4nicegui/reactive/officials/select.py,sha256=zA9OG6Sll0g6yC15-YtOO5mGioua60yQIQvb2TfgSKM,3053
122
+ ex4nicegui/reactive/officials/slider.py,sha256=ru_7bEi-HrdQrrevC7AGyeiI_45kFPhMgNJgjwIsbj4,2976
123
+ ex4nicegui/reactive/officials/switch.py,sha256=TpGotdstKmOVpuCwngtV_KcB401nw7o5oarVnqgX6n4,1543
122
124
  ex4nicegui/reactive/officials/tab.py,sha256=nyB7Ksc_tWG-RaAXiu3TTIJvkNeSa9AZdwHXuL2SsOE,1433
123
125
  ex4nicegui/reactive/officials/tab_panel.py,sha256=Y05XTIOE6qXYZjcCoVIPm9lruyR7av58McRLmPc2yxg,650
124
126
  ex4nicegui/reactive/officials/tab_panels.py,sha256=YSe346Pa_BWPvYbJrxB4Mzc7c6IGcip6oc7LcSg2vbk,6044
125
127
  ex4nicegui/reactive/officials/table.py,sha256=B_nX19UxwyxGKsxLuu2x4UNwxsapjTBw70RMBWDI8w0,6206
126
128
  ex4nicegui/reactive/officials/tabs.py,sha256=1aLFnpKgBJMBE-e842Uldq80XOCVvdoH1uUeN1OUmWI,1296
127
- ex4nicegui/reactive/officials/textarea.py,sha256=5pSDr11NkGMYBlOZNhtPwJwASAFEdeTZjmIVz-aDa_s,3038
128
- ex4nicegui/reactive/officials/tooltip.py,sha256=8a3E7PfUSL3G8VNlxYU34myGNuUQddUWQzTo4F--ddE,1127
129
+ ex4nicegui/reactive/officials/textarea.py,sha256=3sRrTL7BMcQg9QfsxvvVChVYIj_klRk8Lh0Sppp7pCg,3048
130
+ ex4nicegui/reactive/officials/toggle.py,sha256=H0NLosMcKbTkH94yV4h4b_WOuCStZpOJMlkYgOqpyYY,2663
131
+ ex4nicegui/reactive/officials/tooltip.py,sha256=lkDOf5Z6vpDsO9Y-nsRRwdhmYVFb9YrWv7lQUNY4_Ho,1136
129
132
  ex4nicegui/reactive/officials/upload.py,sha256=5SX2CFkf3s_4bPcnx0bmKRA4eYVlm0S8RBeQ7qHnqck,2395
130
133
  ex4nicegui/reactive/q_pagination.py,sha256=nUszZ4fvCf4leQ1DpS70laCDf40RprbOex7SISbAEek,1555
131
134
  ex4nicegui/reactive/rxui.py,sha256=gZ8ZEjGuJFKcedEZhcm4PIZguNkY-Wv5yQx80QnsBKI,31
@@ -135,7 +138,7 @@ ex4nicegui/reactive/services/pandas_service.py,sha256=XOoy6tZr4TpTyhewAH59eiSwVF
135
138
  ex4nicegui/reactive/services/reactive_service.py,sha256=cgw7Qirc70avsgvGuMT4RCT_mFouJb1-KR3dWOgucX8,2742
136
139
  ex4nicegui/reactive/systems/color_system.py,sha256=qXRTczxfILduHAVlNJqLSed-0x-LN6TyBSegYwW9vfk,4352
137
140
  ex4nicegui/reactive/systems/object_system.py,sha256=bja9YNb4v5fVZl5gJvVA4HbwRssRp-2yFy3JBzNeKxA,752
138
- ex4nicegui/reactive/systems/reactive_system.py,sha256=EYDshl4UR9VheNcxcNHc231Dwko9VudilfMIxCD_uOk,685
141
+ ex4nicegui/reactive/systems/reactive_system.py,sha256=wyCSPdGuH1jOOkb2mXWRYVpdebjSm0qi9fuiVAkw5tA,701
139
142
  ex4nicegui/reactive/transitionGroup.js,sha256=rbfNU3Jrz9WFDQih3BgZOgC1MBr6j9cODZ9XggMAaTs,898
140
143
  ex4nicegui/reactive/transitionGroup.py,sha256=VWyYL3QUfX6YQXuxwBFF4sJ4P5VP1S-bCjLKUr28KEY,597
141
144
  ex4nicegui/reactive/UseDraggable/UseDraggable.js,sha256=xZm_g_L2lamxAjiAeGPDR0CNmjlvgzuiJ6gH77pNrg4,5473
@@ -145,7 +148,7 @@ ex4nicegui/reactive/useMouse/UseMouse.py,sha256=cFNlso7_BneyAfGmWbl-N9vQwGleV2Ar
145
148
  ex4nicegui/reactive/usePagination.py,sha256=8YLqcZ_ecuX0FdQ0ct-XdEFfMAVkubAS_K02YOhg5oo,2584
146
149
  ex4nicegui/reactive/vfor.js,sha256=sCy3KR5Aeyx68yh9VI6I9Vj7bnVuir_LUYKZBe_ePTg,908
147
150
  ex4nicegui/reactive/vfor.py,sha256=5gu6a1k0qFP_0M4xEUpZZJgLFogDTAhQORaym42EiEg,7817
148
- ex4nicegui/reactive/view_model.py,sha256=M36l2UBerErs5JK6I2jkKyj91mrLxOcFejzbBlfXP-0,4379
151
+ ex4nicegui/reactive/view_model.py,sha256=i1tyoqzX-6aCWMEfyjVgKEodtvaVHGKfwixRSf5Coos,4391
149
152
  ex4nicegui/reactive/vmodel.py,sha256=ymrUpC_68jaHF76ivKmgz-C4Xl6i65c_41uMc0ffEhY,5936
150
153
  ex4nicegui/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
151
154
  ex4nicegui/tools/debug.py,sha256=h9iYHxw7jWWvmiExSpGi2hQl1PfhPZgC2KNS_GTuHSw,4868
@@ -161,7 +164,7 @@ ex4nicegui/utils/scheduler.py,sha256=1gyq7Y2BkbwmPK_Q9kpRpc1MOC9H7xcpxuix-RZhN9k
161
164
  ex4nicegui/utils/signals.py,sha256=Q2aaYct1U1DAW4neLiq1_iUdBGiPLNxpXQcuW1KiaDg,7106
162
165
  ex4nicegui/utils/types.py,sha256=pE5WOSbcTHxaAhnT24FaZEd1B2Z_lTcsd46w0OKiMyc,359
163
166
  ex4nicegui/version.py,sha256=NE7u1piESstg3xCtf5hhV4iedGs2qJQw9SiC3ZSpiio,90
164
- ex4nicegui-0.7.0.dist-info/LICENSE,sha256=0KDDElS2dl-HIsWvbpy8ywbLzJMBFzXLev57LnMIZXs,1094
165
- ex4nicegui-0.7.0.dist-info/METADATA,sha256=UwWpQE5SWENPA4E-mI0Z8a8xJI72g_zdUBNVeSQpiF8,34891
166
- ex4nicegui-0.7.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
167
- ex4nicegui-0.7.0.dist-info/RECORD,,
167
+ ex4nicegui-0.7.1.dist-info/LICENSE,sha256=0KDDElS2dl-HIsWvbpy8ywbLzJMBFzXLev57LnMIZXs,1094
168
+ ex4nicegui-0.7.1.dist-info/METADATA,sha256=8Z8DoS3ZEBcB5R1vn5-aEHNTqmNEkjwyihqPlwXyxj0,35072
169
+ ex4nicegui-0.7.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
170
+ ex4nicegui-0.7.1.dist-info/RECORD,,