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.
- ex4nicegui/__init__.py +1 -1
- ex4nicegui/reactive/__index.py +1 -31
- ex4nicegui/reactive/officials/__init__.py +37 -0
- ex4nicegui/reactive/officials/aggrid.py +81 -0
- ex4nicegui/reactive/officials/base.py +167 -0
- ex4nicegui/reactive/officials/button.py +86 -0
- ex4nicegui/reactive/officials/card.py +59 -0
- ex4nicegui/reactive/officials/checkbox.py +68 -0
- ex4nicegui/reactive/officials/color_picker.py +101 -0
- ex4nicegui/reactive/officials/date.py +85 -0
- ex4nicegui/reactive/officials/drawer.py +88 -0
- ex4nicegui/reactive/officials/echarts.py +70 -0
- ex4nicegui/reactive/officials/html.py +66 -0
- ex4nicegui/reactive/officials/icon.py +62 -0
- ex4nicegui/reactive/officials/image.py +54 -0
- ex4nicegui/reactive/officials/input.py +116 -0
- ex4nicegui/reactive/officials/label.py +67 -0
- ex4nicegui/reactive/officials/radio.py +80 -0
- ex4nicegui/reactive/officials/row.py +21 -0
- ex4nicegui/reactive/officials/select.py +93 -0
- ex4nicegui/reactive/officials/slider.py +97 -0
- ex4nicegui/reactive/officials/switch.py +72 -0
- ex4nicegui/reactive/officials/table.py +144 -0
- ex4nicegui/reactive/officials/textarea.py +103 -0
- ex4nicegui/reactive/officials/upload.py +78 -0
- ex4nicegui/reactive/officials/utils.py +11 -0
- {ex4nicegui-0.2.3.dist-info → ex4nicegui-0.2.5.dist-info}/METADATA +1 -1
- ex4nicegui-0.2.5.dist-info/RECORD +56 -0
- ex4nicegui/reactive/officials.py +0 -1585
- ex4nicegui-0.2.3.dist-info/RECORD +0 -33
- {ex4nicegui-0.2.3.data → ex4nicegui-0.2.5.data}/data/ECharts/ECharts.js +0 -0
- {ex4nicegui-0.2.3.data → ex4nicegui-0.2.5.data}/data/UseDraggable/UseDraggable.js +0 -0
- {ex4nicegui-0.2.3.data → ex4nicegui-0.2.5.data}/data/useMouse/UseMouse.js +0 -0
- {ex4nicegui-0.2.3.dist-info → ex4nicegui-0.2.5.dist-info}/LICENSE +0 -0
- {ex4nicegui-0.2.3.dist-info → ex4nicegui-0.2.5.dist-info}/WHEEL +0 -0
- {ex4nicegui-0.2.3.dist-info → ex4nicegui-0.2.5.dist-info}/top_level.txt +0 -0
ex4nicegui/reactive/officials.py
DELETED
|
@@ -1,1585 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
import asyncio
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
from typing import (
|
|
6
|
-
Any,
|
|
7
|
-
Callable,
|
|
8
|
-
List,
|
|
9
|
-
Optional,
|
|
10
|
-
TypeVar,
|
|
11
|
-
Generic,
|
|
12
|
-
cast,
|
|
13
|
-
Dict,
|
|
14
|
-
Union,
|
|
15
|
-
overload,
|
|
16
|
-
)
|
|
17
|
-
from typing_extensions import Literal, Self
|
|
18
|
-
from signe import effect
|
|
19
|
-
from ex4nicegui.utils.signals import (
|
|
20
|
-
ReadonlyRef,
|
|
21
|
-
Ref,
|
|
22
|
-
ref_computed,
|
|
23
|
-
to_ref,
|
|
24
|
-
to_value,
|
|
25
|
-
is_ref,
|
|
26
|
-
_TMaybeRef as TMaybeRef,
|
|
27
|
-
)
|
|
28
|
-
import ex4nicegui.utils.common as utils_common
|
|
29
|
-
from nicegui import Tailwind, ui
|
|
30
|
-
from nicegui import events as ng_events
|
|
31
|
-
from nicegui.elements.mixins.text_element import TextElement
|
|
32
|
-
from nicegui.elements.mixins.value_element import ValueElement
|
|
33
|
-
from nicegui.elements.mixins.color_elements import (
|
|
34
|
-
TextColorElement,
|
|
35
|
-
QUASAR_COLORS,
|
|
36
|
-
TAILWIND_COLORS,
|
|
37
|
-
)
|
|
38
|
-
from nicegui.page_layout import Drawer
|
|
39
|
-
from ex4nicegui.reactive.ECharts.ECharts import echarts
|
|
40
|
-
|
|
41
|
-
T = TypeVar("T")
|
|
42
|
-
|
|
43
|
-
TWidget = TypeVar("TWidget")
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class BindableUi(Generic[TWidget]):
|
|
47
|
-
def __init__(self, element: TWidget) -> None:
|
|
48
|
-
self.__element = element
|
|
49
|
-
|
|
50
|
-
def props(self, add: Optional[str] = None, *, remove: Optional[str] = None):
|
|
51
|
-
cast(ui.element, self.element).props(add, remove=remove)
|
|
52
|
-
return self
|
|
53
|
-
|
|
54
|
-
def classes(
|
|
55
|
-
self,
|
|
56
|
-
add: Optional[str] = None,
|
|
57
|
-
*,
|
|
58
|
-
remove: Optional[str] = None,
|
|
59
|
-
replace: Optional[str] = None,
|
|
60
|
-
):
|
|
61
|
-
cast(ui.element, self.element).classes(add, remove=remove, replace=replace)
|
|
62
|
-
return self
|
|
63
|
-
|
|
64
|
-
def style(
|
|
65
|
-
self,
|
|
66
|
-
add: Optional[str] = None,
|
|
67
|
-
*,
|
|
68
|
-
remove: Optional[str] = None,
|
|
69
|
-
replace: Optional[str] = None,
|
|
70
|
-
):
|
|
71
|
-
cast(ui.element, self.element).style(add, remove=remove, replace=replace)
|
|
72
|
-
return self
|
|
73
|
-
|
|
74
|
-
@overload
|
|
75
|
-
def tailwind(self, *tailwind: Tailwind) -> Self:
|
|
76
|
-
...
|
|
77
|
-
|
|
78
|
-
@overload
|
|
79
|
-
def tailwind(self, *classes: str) -> Self:
|
|
80
|
-
...
|
|
81
|
-
|
|
82
|
-
def tailwind(self, *args):
|
|
83
|
-
cast(ui.element, self.element).tailwind(*args)
|
|
84
|
-
return self
|
|
85
|
-
|
|
86
|
-
def tooltip(self, text: str) -> Self:
|
|
87
|
-
cast(ui.element, self.element).tooltip(text)
|
|
88
|
-
return self
|
|
89
|
-
|
|
90
|
-
def add_slot(self, name: str, template: Optional[str] = None):
|
|
91
|
-
"""Add a slot to the element.
|
|
92
|
-
|
|
93
|
-
:param name: name of the slot
|
|
94
|
-
:param template: Vue template of the slot
|
|
95
|
-
:return: the slot
|
|
96
|
-
"""
|
|
97
|
-
return cast(ui.element, self.element).add_slot(name, template)
|
|
98
|
-
|
|
99
|
-
@property
|
|
100
|
-
def element(self):
|
|
101
|
-
return self.__element
|
|
102
|
-
|
|
103
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
104
|
-
if prop == "visible":
|
|
105
|
-
return self.bind_visible(ref_ui)
|
|
106
|
-
|
|
107
|
-
@effect
|
|
108
|
-
def _():
|
|
109
|
-
element = cast(ui.element, self.element)
|
|
110
|
-
element._props[prop] = ref_ui.value
|
|
111
|
-
element.update()
|
|
112
|
-
|
|
113
|
-
return self
|
|
114
|
-
|
|
115
|
-
def bind_visible(self, ref_ui: ReadonlyRef[bool]):
|
|
116
|
-
@effect
|
|
117
|
-
def _():
|
|
118
|
-
element = cast(ui.element, self.element)
|
|
119
|
-
element.set_visibility(ref_ui.value)
|
|
120
|
-
|
|
121
|
-
return self
|
|
122
|
-
|
|
123
|
-
def on(
|
|
124
|
-
self,
|
|
125
|
-
type: str,
|
|
126
|
-
handler: Optional[Callable[..., Any]] = None,
|
|
127
|
-
args: Optional[List[str]] = None,
|
|
128
|
-
*,
|
|
129
|
-
throttle: float = 0.0,
|
|
130
|
-
leading_events: bool = True,
|
|
131
|
-
trailing_events: bool = True,
|
|
132
|
-
):
|
|
133
|
-
ele = cast(ui.element, self.element)
|
|
134
|
-
ele.on(
|
|
135
|
-
type,
|
|
136
|
-
handler,
|
|
137
|
-
args,
|
|
138
|
-
throttle=throttle,
|
|
139
|
-
leading_events=leading_events,
|
|
140
|
-
trailing_events=trailing_events,
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
return self
|
|
144
|
-
|
|
145
|
-
def clear(self) -> None:
|
|
146
|
-
cast(ui.element, self.element).clear()
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
class SingleValueBindableUi(BindableUi[TWidget], Generic[T, TWidget]):
|
|
150
|
-
def __init__(self, value: TMaybeRef[T], element: TWidget) -> None:
|
|
151
|
-
super().__init__(element)
|
|
152
|
-
self._ref = to_ref(value)
|
|
153
|
-
|
|
154
|
-
@property
|
|
155
|
-
def value(self) -> T:
|
|
156
|
-
return self._ref.value
|
|
157
|
-
|
|
158
|
-
def bind_ref(self, ref: Ref[T]):
|
|
159
|
-
@effect
|
|
160
|
-
def _():
|
|
161
|
-
ref.value = self._ref.value
|
|
162
|
-
|
|
163
|
-
return self
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
def _bind_color(bindable_ui: SingleValueBindableUi, ref_ui: ReadonlyRef):
|
|
167
|
-
@effect
|
|
168
|
-
def _():
|
|
169
|
-
ele = cast(TextColorElement, bindable_ui.element)
|
|
170
|
-
color = ref_ui.value
|
|
171
|
-
|
|
172
|
-
if color in QUASAR_COLORS:
|
|
173
|
-
ele._props[ele.TEXT_COLOR_PROP] = color
|
|
174
|
-
elif color in TAILWIND_COLORS:
|
|
175
|
-
ele.classes(replace=f"text-{color}")
|
|
176
|
-
elif color is not None:
|
|
177
|
-
ele._style["color"] = color
|
|
178
|
-
ele.update()
|
|
179
|
-
|
|
180
|
-
return bindable_ui
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
class TextColorElementBindableUi(SingleValueBindableUi[T, TWidget]):
|
|
184
|
-
def __init__(self, value: T, element: TWidget) -> None:
|
|
185
|
-
super().__init__(value, element)
|
|
186
|
-
|
|
187
|
-
ele = cast(TextColorElement, element)
|
|
188
|
-
|
|
189
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
190
|
-
if prop == "name":
|
|
191
|
-
return self.bind_name(ref_ui)
|
|
192
|
-
|
|
193
|
-
if prop == "color":
|
|
194
|
-
return self.bind_color(ref_ui)
|
|
195
|
-
|
|
196
|
-
return super().bind_prop(prop, ref_ui)
|
|
197
|
-
|
|
198
|
-
def bind_color(self, ref_ui: ReadonlyRef):
|
|
199
|
-
return _bind_color(self, ref_ui)
|
|
200
|
-
|
|
201
|
-
def bind_name(self, ref_ui: ReadonlyRef):
|
|
202
|
-
@effect
|
|
203
|
-
def _():
|
|
204
|
-
ele = cast(TextColorElement, self.element)
|
|
205
|
-
ele._props["name"] = ref_ui.value
|
|
206
|
-
ele.update()
|
|
207
|
-
|
|
208
|
-
return self
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
def _convert_kws_ref2value(kws: Dict):
|
|
212
|
-
return {key: to_value(value) for key, value in kws.items()}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
class SelectBindableUi(SingleValueBindableUi[T, ui.select]):
|
|
216
|
-
@staticmethod
|
|
217
|
-
def _setup_(binder: "SelectBindableUi"):
|
|
218
|
-
def onValueChanged(e):
|
|
219
|
-
binder._ref.value = e.args["label"] # type: ignore
|
|
220
|
-
|
|
221
|
-
@effect
|
|
222
|
-
def _():
|
|
223
|
-
binder.element.value = binder.value
|
|
224
|
-
|
|
225
|
-
binder.element.on("update:modelValue", handler=onValueChanged)
|
|
226
|
-
|
|
227
|
-
def __init__(
|
|
228
|
-
self,
|
|
229
|
-
options: Union[TMaybeRef[List], TMaybeRef[Dict]],
|
|
230
|
-
*,
|
|
231
|
-
label: Optional[TMaybeRef[str]] = None,
|
|
232
|
-
value: TMaybeRef[Any] = None,
|
|
233
|
-
on_change: Optional[Callable[..., Any]] = None,
|
|
234
|
-
with_input: TMaybeRef[bool] = False,
|
|
235
|
-
multiple: TMaybeRef[bool] = False,
|
|
236
|
-
clearable: TMaybeRef[bool] = False,
|
|
237
|
-
) -> None:
|
|
238
|
-
kws = {
|
|
239
|
-
"options": options,
|
|
240
|
-
"label": label,
|
|
241
|
-
"value": value,
|
|
242
|
-
"on_change": on_change,
|
|
243
|
-
"with_input": with_input,
|
|
244
|
-
"multiple": multiple,
|
|
245
|
-
"clearable": clearable,
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
249
|
-
|
|
250
|
-
element = ui.select(**value_kws)
|
|
251
|
-
element.classes("min-w-[10rem]")
|
|
252
|
-
|
|
253
|
-
super().__init__(value, element)
|
|
254
|
-
|
|
255
|
-
for key, value in kws.items():
|
|
256
|
-
if is_ref(value):
|
|
257
|
-
self.bind_prop(key, value)
|
|
258
|
-
|
|
259
|
-
SelectBindableUi._setup_(self)
|
|
260
|
-
|
|
261
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
262
|
-
if prop == "value":
|
|
263
|
-
return self.bind_text(ref_ui)
|
|
264
|
-
|
|
265
|
-
if prop == "options":
|
|
266
|
-
return self.bind_options(ref_ui)
|
|
267
|
-
|
|
268
|
-
return super().bind_prop(prop, ref_ui)
|
|
269
|
-
|
|
270
|
-
def bind_options(self, ref_ui: ReadonlyRef):
|
|
271
|
-
@effect
|
|
272
|
-
def _():
|
|
273
|
-
self.element.options = ref_ui.value
|
|
274
|
-
self.element.update()
|
|
275
|
-
|
|
276
|
-
return self
|
|
277
|
-
|
|
278
|
-
def bind_text(self, ref_ui: ReadonlyRef):
|
|
279
|
-
@effect
|
|
280
|
-
def _():
|
|
281
|
-
cast(ValueElement, self.element).on_value_change(ref_ui.value)
|
|
282
|
-
|
|
283
|
-
return self
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
class RadioBindableUi(SingleValueBindableUi[bool, ui.radio]):
|
|
287
|
-
@staticmethod
|
|
288
|
-
def _setup_(binder: "RadioBindableUi"):
|
|
289
|
-
def onValueChanged(e):
|
|
290
|
-
binder._ref.value = binder.element.options[e.args] # type: ignore
|
|
291
|
-
|
|
292
|
-
@effect
|
|
293
|
-
def _():
|
|
294
|
-
binder.element.value = binder.value
|
|
295
|
-
|
|
296
|
-
binder.element.on("update:modelValue", handler=onValueChanged)
|
|
297
|
-
|
|
298
|
-
def __init__(
|
|
299
|
-
self,
|
|
300
|
-
options: Union[TMaybeRef[List], TMaybeRef[Dict]],
|
|
301
|
-
*,
|
|
302
|
-
value: TMaybeRef[Any] = None,
|
|
303
|
-
on_change: Optional[Callable[..., Any]] = None,
|
|
304
|
-
) -> None:
|
|
305
|
-
kws = {"options": options, "value": value, "on_change": on_change}
|
|
306
|
-
|
|
307
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
308
|
-
|
|
309
|
-
element = ui.radio(**value_kws)
|
|
310
|
-
|
|
311
|
-
super().__init__(value, element)
|
|
312
|
-
|
|
313
|
-
for key, value in kws.items():
|
|
314
|
-
if is_ref(value):
|
|
315
|
-
self.bind_prop(key, value)
|
|
316
|
-
|
|
317
|
-
RadioBindableUi._setup_(self)
|
|
318
|
-
|
|
319
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
320
|
-
if prop == "value":
|
|
321
|
-
return self.bind_value(ref_ui)
|
|
322
|
-
|
|
323
|
-
if prop == "options":
|
|
324
|
-
return self.bind_options(ref_ui)
|
|
325
|
-
|
|
326
|
-
return super().bind_prop(prop, ref_ui)
|
|
327
|
-
|
|
328
|
-
def bind_options(self, ref_ui: ReadonlyRef):
|
|
329
|
-
@effect
|
|
330
|
-
def _():
|
|
331
|
-
self.element.options = ref_ui.value
|
|
332
|
-
self.element.update()
|
|
333
|
-
|
|
334
|
-
return self
|
|
335
|
-
|
|
336
|
-
def bind_value(self, ref_ui: ReadonlyRef):
|
|
337
|
-
@effect
|
|
338
|
-
def _():
|
|
339
|
-
cast(ValueElement, self.element).on_value_change(ref_ui.value)
|
|
340
|
-
|
|
341
|
-
return self
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
class SwitchBindableUi(SingleValueBindableUi[bool, ui.switch]):
|
|
345
|
-
@staticmethod
|
|
346
|
-
def _setup_(binder: "SwitchBindableUi"):
|
|
347
|
-
def onValueChanged(e):
|
|
348
|
-
ele._send_update_on_value_change = ele.LOOPBACK
|
|
349
|
-
cur_value = ele._event_args_to_value(e)
|
|
350
|
-
ele.set_value(cur_value)
|
|
351
|
-
ele._send_update_on_value_change = True
|
|
352
|
-
binder._ref.value = cur_value
|
|
353
|
-
|
|
354
|
-
ele = cast(ValueElement, binder.element)
|
|
355
|
-
|
|
356
|
-
@effect
|
|
357
|
-
def _():
|
|
358
|
-
ele.value = binder.value
|
|
359
|
-
|
|
360
|
-
ele.on("update:modelValue", onValueChanged, [None], throttle=0) # type: ignore
|
|
361
|
-
|
|
362
|
-
def __init__(
|
|
363
|
-
self,
|
|
364
|
-
text: TMaybeRef[str] = "",
|
|
365
|
-
*,
|
|
366
|
-
value: TMaybeRef[bool] = False,
|
|
367
|
-
on_change: Optional[Callable[..., Any]] = None,
|
|
368
|
-
) -> None:
|
|
369
|
-
kws = {"text": text, "value": value, "on_change": on_change}
|
|
370
|
-
|
|
371
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
372
|
-
|
|
373
|
-
element = ui.switch(**value_kws)
|
|
374
|
-
|
|
375
|
-
super().__init__(value, element)
|
|
376
|
-
|
|
377
|
-
for key, value in kws.items():
|
|
378
|
-
if is_ref(value):
|
|
379
|
-
self.bind_prop(key, value) # type: ignore
|
|
380
|
-
|
|
381
|
-
SwitchBindableUi._setup_(self)
|
|
382
|
-
|
|
383
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
384
|
-
if prop == "value":
|
|
385
|
-
return self.bind_value(ref_ui)
|
|
386
|
-
|
|
387
|
-
return super().bind_prop(prop, ref_ui)
|
|
388
|
-
|
|
389
|
-
def bind_value(self, ref_ui: ReadonlyRef[bool]):
|
|
390
|
-
@effect
|
|
391
|
-
def _():
|
|
392
|
-
self.element.on_value_change(ref_ui.value)
|
|
393
|
-
|
|
394
|
-
return self
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
class CheckboxBindableUi(SingleValueBindableUi[bool, ui.checkbox]):
|
|
398
|
-
@staticmethod
|
|
399
|
-
def _setup_(binder: "CheckboxBindableUi"):
|
|
400
|
-
def onValueChanged(e):
|
|
401
|
-
binder._ref.value = e.args # type: ignore
|
|
402
|
-
|
|
403
|
-
ele = cast(ValueElement, binder.element)
|
|
404
|
-
|
|
405
|
-
@effect
|
|
406
|
-
def _():
|
|
407
|
-
ele.value = binder.value
|
|
408
|
-
|
|
409
|
-
ele.on("update:modelValue", handler=onValueChanged)
|
|
410
|
-
|
|
411
|
-
def __init__(
|
|
412
|
-
self,
|
|
413
|
-
text: str = "",
|
|
414
|
-
*,
|
|
415
|
-
value: bool = False,
|
|
416
|
-
on_change: Optional[Callable[..., Any]] = None,
|
|
417
|
-
) -> None:
|
|
418
|
-
kws = {"text": text, "value": value, "on_change": on_change}
|
|
419
|
-
|
|
420
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
421
|
-
|
|
422
|
-
element = ui.checkbox(**value_kws)
|
|
423
|
-
|
|
424
|
-
super().__init__(value, element)
|
|
425
|
-
|
|
426
|
-
for key, value in kws.items():
|
|
427
|
-
if is_ref(value):
|
|
428
|
-
self.bind_prop(key, value) # type: ignore
|
|
429
|
-
|
|
430
|
-
CheckboxBindableUi._setup_(self)
|
|
431
|
-
|
|
432
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
433
|
-
if prop == "value":
|
|
434
|
-
return self.bind_value(ref_ui)
|
|
435
|
-
|
|
436
|
-
return super().bind_prop(prop, ref_ui)
|
|
437
|
-
|
|
438
|
-
def bind_value(self, ref_ui: ReadonlyRef[bool]):
|
|
439
|
-
@effect
|
|
440
|
-
def _():
|
|
441
|
-
self.element.on_value_change(ref_ui.value)
|
|
442
|
-
|
|
443
|
-
return self
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
class DateBindableUi(SingleValueBindableUi[Optional[str], ui.date]):
|
|
447
|
-
def __init__(
|
|
448
|
-
self,
|
|
449
|
-
value: TMaybeRef[Optional[str]] = None,
|
|
450
|
-
*,
|
|
451
|
-
mask: TMaybeRef[str] = "YYYY-MM-DD",
|
|
452
|
-
on_change: Optional[Callable[..., Any]] = None,
|
|
453
|
-
) -> None:
|
|
454
|
-
kws = {
|
|
455
|
-
"value": value,
|
|
456
|
-
"mask": mask,
|
|
457
|
-
"on_change": on_change,
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
461
|
-
|
|
462
|
-
element = ui.date(**value_kws)
|
|
463
|
-
|
|
464
|
-
super().__init__(value, element)
|
|
465
|
-
|
|
466
|
-
for key, value in kws.items():
|
|
467
|
-
if is_ref(value) and key != "value":
|
|
468
|
-
self.bind_prop(key, value) # type: ignore
|
|
469
|
-
|
|
470
|
-
self._ex_setup()
|
|
471
|
-
|
|
472
|
-
def _ex_setup(self):
|
|
473
|
-
ele = self.element
|
|
474
|
-
|
|
475
|
-
@effect
|
|
476
|
-
def _():
|
|
477
|
-
ele.value = self.value
|
|
478
|
-
|
|
479
|
-
def onModelValueChanged(e):
|
|
480
|
-
self._ref.value = e.args[0] or "" # type: ignore
|
|
481
|
-
|
|
482
|
-
ele.on("update:modelValue", handler=onModelValueChanged)
|
|
483
|
-
|
|
484
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
485
|
-
if prop == "value":
|
|
486
|
-
return self.bind_value(ref_ui)
|
|
487
|
-
|
|
488
|
-
return super().bind_prop(prop, ref_ui)
|
|
489
|
-
|
|
490
|
-
def bind_value(self, ref_ui: ReadonlyRef[bool]):
|
|
491
|
-
@effect
|
|
492
|
-
def _():
|
|
493
|
-
self.element.on_value_change(ref_ui.value)
|
|
494
|
-
|
|
495
|
-
return self
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
class InputBindableUi(SingleValueBindableUi[str, ui.input]):
|
|
499
|
-
def __init__(
|
|
500
|
-
self,
|
|
501
|
-
label: Optional[TMaybeRef[str]] = None,
|
|
502
|
-
*,
|
|
503
|
-
placeholder: Optional[TMaybeRef[str]] = None,
|
|
504
|
-
value: TMaybeRef[str] = "",
|
|
505
|
-
password: TMaybeRef[bool] = False,
|
|
506
|
-
password_toggle_button: TMaybeRef[bool] = False,
|
|
507
|
-
on_change: Optional[Callable[..., Any]] = None,
|
|
508
|
-
autocomplete: Optional[TMaybeRef[List[str]]] = None,
|
|
509
|
-
validation: Dict[str, Callable[..., bool]] = {},
|
|
510
|
-
) -> None:
|
|
511
|
-
kws = {
|
|
512
|
-
"label": label,
|
|
513
|
-
"placeholder": placeholder,
|
|
514
|
-
"value": value,
|
|
515
|
-
"password": password,
|
|
516
|
-
"password_toggle_button": password_toggle_button,
|
|
517
|
-
"autocomplete": autocomplete,
|
|
518
|
-
"validation": validation,
|
|
519
|
-
"on_change": on_change,
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
523
|
-
|
|
524
|
-
element = ui.input(**value_kws)
|
|
525
|
-
|
|
526
|
-
super().__init__(value, element)
|
|
527
|
-
|
|
528
|
-
for key, value in kws.items():
|
|
529
|
-
if is_ref(value) and key != "value":
|
|
530
|
-
self.bind_prop(key, value) # type: ignore
|
|
531
|
-
|
|
532
|
-
self._ex_setup()
|
|
533
|
-
|
|
534
|
-
def _ex_setup(self):
|
|
535
|
-
ele = self.element
|
|
536
|
-
|
|
537
|
-
@effect
|
|
538
|
-
def _():
|
|
539
|
-
ele.value = self.value
|
|
540
|
-
|
|
541
|
-
def onModelValueChanged(e):
|
|
542
|
-
self._ref.value = e.args or "" # type: ignore
|
|
543
|
-
|
|
544
|
-
ele.on("update:modelValue", handler=onModelValueChanged)
|
|
545
|
-
|
|
546
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
547
|
-
if prop == "value":
|
|
548
|
-
return self.bind_value(ref_ui)
|
|
549
|
-
|
|
550
|
-
return super().bind_prop(prop, ref_ui)
|
|
551
|
-
|
|
552
|
-
def bind_value(self, ref_ui: ReadonlyRef[bool]):
|
|
553
|
-
@effect
|
|
554
|
-
def _():
|
|
555
|
-
self.element.on_value_change(ref_ui.value)
|
|
556
|
-
|
|
557
|
-
return self
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
class LazyInputBindableUi(InputBindableUi):
|
|
561
|
-
def __init__(
|
|
562
|
-
self,
|
|
563
|
-
label: Optional[TMaybeRef[str]] = None,
|
|
564
|
-
*,
|
|
565
|
-
placeholder: Optional[TMaybeRef[str]] = None,
|
|
566
|
-
value: TMaybeRef[str] = "",
|
|
567
|
-
password: TMaybeRef[bool] = False,
|
|
568
|
-
password_toggle_button: TMaybeRef[bool] = False,
|
|
569
|
-
on_change: Optional[Callable[..., Any]] = None,
|
|
570
|
-
autocomplete: Optional[TMaybeRef[List[str]]] = None,
|
|
571
|
-
validation: Dict[str, Callable[..., bool]] = {},
|
|
572
|
-
) -> None:
|
|
573
|
-
super().__init__(
|
|
574
|
-
label,
|
|
575
|
-
placeholder=placeholder,
|
|
576
|
-
value=value,
|
|
577
|
-
password=password,
|
|
578
|
-
password_toggle_button=password_toggle_button,
|
|
579
|
-
on_change=on_change,
|
|
580
|
-
autocomplete=autocomplete,
|
|
581
|
-
validation=validation,
|
|
582
|
-
)
|
|
583
|
-
|
|
584
|
-
def _ex_setup(self):
|
|
585
|
-
ele = self.element
|
|
586
|
-
|
|
587
|
-
@effect
|
|
588
|
-
def _():
|
|
589
|
-
ele.value = self.value
|
|
590
|
-
|
|
591
|
-
def onValueChanged():
|
|
592
|
-
self._ref.value = ele.value or ""
|
|
593
|
-
|
|
594
|
-
ele.on("blur", onValueChanged)
|
|
595
|
-
ele.on("keyup.enter", onValueChanged)
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
_TSliderValue = TypeVar("_TSliderValue", float, int, None)
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
class SliderBindableUi(SingleValueBindableUi[Optional[_TSliderValue], ui.slider]):
|
|
602
|
-
def __init__(
|
|
603
|
-
self,
|
|
604
|
-
min: TMaybeRef[_TSliderValue],
|
|
605
|
-
max: TMaybeRef[_TSliderValue],
|
|
606
|
-
step: TMaybeRef[_TSliderValue] = 1.0,
|
|
607
|
-
value: Optional[TMaybeRef[_TSliderValue]] = None,
|
|
608
|
-
on_change: Optional[Callable[..., Any]] = None,
|
|
609
|
-
) -> None:
|
|
610
|
-
kws = {
|
|
611
|
-
"min": min,
|
|
612
|
-
"max": max,
|
|
613
|
-
"step": step,
|
|
614
|
-
"value": value,
|
|
615
|
-
"on_change": on_change,
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
619
|
-
|
|
620
|
-
element = ui.slider(**value_kws).props("label label-always switch-label-side")
|
|
621
|
-
|
|
622
|
-
super().__init__(value, element) # type: ignore
|
|
623
|
-
|
|
624
|
-
for key, value in kws.items():
|
|
625
|
-
if is_ref(value) and key != "value":
|
|
626
|
-
self.bind_prop(key, value) # type: ignore
|
|
627
|
-
|
|
628
|
-
self._ex_setup()
|
|
629
|
-
|
|
630
|
-
def _ex_setup(self):
|
|
631
|
-
ele = self.element
|
|
632
|
-
|
|
633
|
-
@effect
|
|
634
|
-
def _():
|
|
635
|
-
ele.value = self.value
|
|
636
|
-
|
|
637
|
-
def onModelValueChanged(e):
|
|
638
|
-
self._ref.value = e.args # type: ignore
|
|
639
|
-
|
|
640
|
-
ele.on("update:modelValue", handler=onModelValueChanged)
|
|
641
|
-
|
|
642
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
643
|
-
if prop == "value":
|
|
644
|
-
return self.bind_value(ref_ui)
|
|
645
|
-
|
|
646
|
-
return super().bind_prop(prop, ref_ui)
|
|
647
|
-
|
|
648
|
-
def bind_value(self, ref_ui: ReadonlyRef[float]):
|
|
649
|
-
@effect
|
|
650
|
-
def _():
|
|
651
|
-
self.element.on_value_change(ref_ui.value)
|
|
652
|
-
|
|
653
|
-
return self
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
class LazySliderBindableUi(SliderBindableUi):
|
|
657
|
-
def __init__(
|
|
658
|
-
self,
|
|
659
|
-
min: TMaybeRef[_TSliderValue],
|
|
660
|
-
max: TMaybeRef[_TSliderValue],
|
|
661
|
-
step: TMaybeRef[_TSliderValue] = 1,
|
|
662
|
-
value: TMaybeRef[_TSliderValue | None] = None,
|
|
663
|
-
on_change: Callable[..., Any] | None = None,
|
|
664
|
-
) -> None:
|
|
665
|
-
super().__init__(min, max, step, value, on_change)
|
|
666
|
-
|
|
667
|
-
def _ex_setup(self):
|
|
668
|
-
ele = self.element
|
|
669
|
-
|
|
670
|
-
@effect
|
|
671
|
-
def _():
|
|
672
|
-
ele.value = self.value
|
|
673
|
-
|
|
674
|
-
def onValueChanged():
|
|
675
|
-
self._ref.value = ele.value
|
|
676
|
-
|
|
677
|
-
ele.on("change", onValueChanged)
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
class TextareaBindableUi(SingleValueBindableUi[str, ui.textarea]):
|
|
681
|
-
def __init__(
|
|
682
|
-
self,
|
|
683
|
-
label: Optional[TMaybeRef[str]] = None,
|
|
684
|
-
*,
|
|
685
|
-
placeholder: Optional[TMaybeRef[str]] = None,
|
|
686
|
-
value: TMaybeRef[str] = "",
|
|
687
|
-
on_change: Optional[Callable[..., Any]] = None,
|
|
688
|
-
validation: Dict[str, Callable[..., bool]] = {},
|
|
689
|
-
) -> None:
|
|
690
|
-
kws = {
|
|
691
|
-
"label": label,
|
|
692
|
-
"placeholder": placeholder,
|
|
693
|
-
"value": value,
|
|
694
|
-
"validation": validation,
|
|
695
|
-
"on_change": on_change,
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
699
|
-
|
|
700
|
-
element = ui.textarea(**value_kws)
|
|
701
|
-
|
|
702
|
-
super().__init__(value, element)
|
|
703
|
-
|
|
704
|
-
for key, value in kws.items():
|
|
705
|
-
if is_ref(value) and key != "value":
|
|
706
|
-
self.bind_prop(key, value) # type: ignore
|
|
707
|
-
|
|
708
|
-
self._ex_setup()
|
|
709
|
-
|
|
710
|
-
def _ex_setup(self):
|
|
711
|
-
ele = self.element
|
|
712
|
-
|
|
713
|
-
@effect
|
|
714
|
-
def _():
|
|
715
|
-
ele.value = self.value
|
|
716
|
-
|
|
717
|
-
def onModelValueChanged(e):
|
|
718
|
-
self._ref.value = e.args # type: ignore
|
|
719
|
-
|
|
720
|
-
ele.on("update:modelValue", handler=onModelValueChanged)
|
|
721
|
-
|
|
722
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
723
|
-
if prop == "value":
|
|
724
|
-
return self.bind_value(ref_ui)
|
|
725
|
-
|
|
726
|
-
return super().bind_prop(prop, ref_ui)
|
|
727
|
-
|
|
728
|
-
def bind_value(self, ref_ui: ReadonlyRef[bool]):
|
|
729
|
-
@effect
|
|
730
|
-
def _():
|
|
731
|
-
self.element.on_value_change(ref_ui.value)
|
|
732
|
-
|
|
733
|
-
return self
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
class LazyTextareaBindableUi(TextareaBindableUi):
|
|
737
|
-
def __init__(
|
|
738
|
-
self,
|
|
739
|
-
label: Optional[TMaybeRef[str]] = None,
|
|
740
|
-
*,
|
|
741
|
-
placeholder: Optional[TMaybeRef[str]] = None,
|
|
742
|
-
value: TMaybeRef[str] = "",
|
|
743
|
-
on_change: Optional[Callable[..., Any]] = None,
|
|
744
|
-
validation: Dict[str, Callable[..., bool]] = {},
|
|
745
|
-
) -> None:
|
|
746
|
-
super().__init__(
|
|
747
|
-
label,
|
|
748
|
-
placeholder=placeholder,
|
|
749
|
-
value=value,
|
|
750
|
-
on_change=on_change,
|
|
751
|
-
validation=validation,
|
|
752
|
-
)
|
|
753
|
-
|
|
754
|
-
def _ex_setup(self):
|
|
755
|
-
ele = self.element
|
|
756
|
-
|
|
757
|
-
@effect
|
|
758
|
-
def _():
|
|
759
|
-
ele.value = self.value
|
|
760
|
-
|
|
761
|
-
def onValueChanged():
|
|
762
|
-
self._ref.value = ele.value
|
|
763
|
-
|
|
764
|
-
ele.on("blur", onValueChanged)
|
|
765
|
-
ele.on("keyup.enter", onValueChanged)
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
class LabelBindableUi(SingleValueBindableUi[str, ui.label]):
|
|
769
|
-
@staticmethod
|
|
770
|
-
def _setup_(binder: "LabelBindableUi"):
|
|
771
|
-
def onValueChanged(e):
|
|
772
|
-
binder._ref.value = e.args["label"] # type: ignore
|
|
773
|
-
|
|
774
|
-
@effect
|
|
775
|
-
def _():
|
|
776
|
-
binder.element.text = binder.value
|
|
777
|
-
|
|
778
|
-
binder.element.on("update:modelValue", handler=onValueChanged)
|
|
779
|
-
|
|
780
|
-
def __init__(
|
|
781
|
-
self,
|
|
782
|
-
text: TMaybeRef[str] = "",
|
|
783
|
-
) -> None:
|
|
784
|
-
kws = {
|
|
785
|
-
"text": text,
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
789
|
-
|
|
790
|
-
element = ui.label(**value_kws)
|
|
791
|
-
|
|
792
|
-
super().__init__(text, element)
|
|
793
|
-
|
|
794
|
-
for key, value in kws.items():
|
|
795
|
-
if is_ref(value):
|
|
796
|
-
self.bind_prop(key, value) # type: ignore
|
|
797
|
-
|
|
798
|
-
LabelBindableUi._setup_(self)
|
|
799
|
-
|
|
800
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
801
|
-
if prop == "text":
|
|
802
|
-
return self.bind_text(ref_ui)
|
|
803
|
-
|
|
804
|
-
if prop == "color":
|
|
805
|
-
return self.bind_color(ref_ui)
|
|
806
|
-
|
|
807
|
-
return super().bind_prop(prop, ref_ui)
|
|
808
|
-
|
|
809
|
-
def bind_color(self, ref_ui: ReadonlyRef):
|
|
810
|
-
@effect
|
|
811
|
-
def _():
|
|
812
|
-
ele = self.element
|
|
813
|
-
color = ref_ui.value
|
|
814
|
-
ele._style["color"] = color
|
|
815
|
-
ele.update()
|
|
816
|
-
|
|
817
|
-
def bind_text(self, ref_ui: ReadonlyRef):
|
|
818
|
-
@effect
|
|
819
|
-
def _():
|
|
820
|
-
self.element.on_text_change(str(ref_ui.value))
|
|
821
|
-
# self.element.update()
|
|
822
|
-
|
|
823
|
-
return self
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
class IconBindableUi(SingleValueBindableUi[str, ui.icon]):
|
|
827
|
-
def __init__(
|
|
828
|
-
self,
|
|
829
|
-
name: TMaybeRef[str],
|
|
830
|
-
*,
|
|
831
|
-
size: Optional[TMaybeRef[str]] = None,
|
|
832
|
-
color: Optional[TMaybeRef[str]] = None,
|
|
833
|
-
) -> None:
|
|
834
|
-
kws = {
|
|
835
|
-
"name": name,
|
|
836
|
-
"size": size,
|
|
837
|
-
"color": color,
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
841
|
-
|
|
842
|
-
element = ui.icon(**value_kws)
|
|
843
|
-
|
|
844
|
-
super().__init__(name, element)
|
|
845
|
-
|
|
846
|
-
for key, value in kws.items():
|
|
847
|
-
if is_ref(value):
|
|
848
|
-
self.bind_prop(key, value) # type: ignore
|
|
849
|
-
|
|
850
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
851
|
-
if prop == "name":
|
|
852
|
-
return self.bind_name(ref_ui)
|
|
853
|
-
|
|
854
|
-
if prop == "color":
|
|
855
|
-
return self.bind_color(ref_ui)
|
|
856
|
-
|
|
857
|
-
return super().bind_prop(prop, ref_ui)
|
|
858
|
-
|
|
859
|
-
def bind_color(self, ref_ui: ReadonlyRef):
|
|
860
|
-
return _bind_color(self, ref_ui)
|
|
861
|
-
|
|
862
|
-
def bind_name(self, ref_ui: ReadonlyRef):
|
|
863
|
-
@effect
|
|
864
|
-
def _():
|
|
865
|
-
ele = cast(TextColorElement, self.element)
|
|
866
|
-
ele._props["name"] = ref_ui.value
|
|
867
|
-
ele.update()
|
|
868
|
-
|
|
869
|
-
return self
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
class ButtonBindableUi(SingleValueBindableUi[str, ui.button]):
|
|
873
|
-
def __init__(
|
|
874
|
-
self,
|
|
875
|
-
text: TMaybeRef[str] = "",
|
|
876
|
-
*,
|
|
877
|
-
on_click: Optional[Callable[..., Any]] = None,
|
|
878
|
-
color: Optional[TMaybeRef[str]] = "primary",
|
|
879
|
-
icon: Optional[TMaybeRef[str]] = None,
|
|
880
|
-
) -> None:
|
|
881
|
-
kws = {
|
|
882
|
-
"text": text,
|
|
883
|
-
"color": color,
|
|
884
|
-
"icon": icon,
|
|
885
|
-
"on_click": on_click,
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
889
|
-
|
|
890
|
-
element = ui.button(**value_kws)
|
|
891
|
-
|
|
892
|
-
super().__init__(text, element)
|
|
893
|
-
|
|
894
|
-
for key, value in kws.items():
|
|
895
|
-
if is_ref(value):
|
|
896
|
-
self.bind_prop(key, value) # type: ignore
|
|
897
|
-
|
|
898
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
899
|
-
if prop == "text":
|
|
900
|
-
return self.bind_text(ref_ui)
|
|
901
|
-
if prop == "icon":
|
|
902
|
-
return self.bind_icon(ref_ui)
|
|
903
|
-
if prop == "color":
|
|
904
|
-
return self.bind_color(ref_ui)
|
|
905
|
-
|
|
906
|
-
return super().bind_prop(prop, ref_ui)
|
|
907
|
-
|
|
908
|
-
def bind_color(self, ref_ui: ReadonlyRef):
|
|
909
|
-
return _bind_color(self, ref_ui)
|
|
910
|
-
|
|
911
|
-
def bind_text(self, ref_ui: ReadonlyRef):
|
|
912
|
-
@effect
|
|
913
|
-
def _():
|
|
914
|
-
ele = self.element
|
|
915
|
-
ele._props["text"] = ref_ui.value
|
|
916
|
-
ele.update()
|
|
917
|
-
|
|
918
|
-
return self
|
|
919
|
-
|
|
920
|
-
def bind_icon(self, ref_ui: ReadonlyRef):
|
|
921
|
-
@effect
|
|
922
|
-
def _():
|
|
923
|
-
ele = self.element
|
|
924
|
-
ele._props["icon"] = ref_ui.value
|
|
925
|
-
ele.update()
|
|
926
|
-
|
|
927
|
-
return self
|
|
928
|
-
|
|
929
|
-
def bind_enabled(self, ref_ui: ReadonlyRef[bool]):
|
|
930
|
-
@effect
|
|
931
|
-
def _():
|
|
932
|
-
self.element.on_enabled_change(ref_ui.value)
|
|
933
|
-
|
|
934
|
-
return self
|
|
935
|
-
|
|
936
|
-
def bind_disable(self, ref_ui: ReadonlyRef[bool]):
|
|
937
|
-
@effect
|
|
938
|
-
def _():
|
|
939
|
-
self.element.on_enabled_change(not ref_ui.value)
|
|
940
|
-
|
|
941
|
-
return self
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
class ColorPickerBindableUi(SingleValueBindableUi[str, ui.color_picker]):
|
|
945
|
-
def __init__(
|
|
946
|
-
self,
|
|
947
|
-
color: TMaybeRef[str] = "",
|
|
948
|
-
*,
|
|
949
|
-
on_pick: Optional[Callable[..., Any]] = None,
|
|
950
|
-
value: TMaybeRef[bool] = False,
|
|
951
|
-
) -> None:
|
|
952
|
-
kws = {
|
|
953
|
-
"value": value,
|
|
954
|
-
"on_pick": on_pick,
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
958
|
-
|
|
959
|
-
with ui.card().tight():
|
|
960
|
-
element_menu = ui.color_picker(**value_kws)
|
|
961
|
-
self._element_picker = element_menu.default_slot.children[0]
|
|
962
|
-
self._element_picker.props(f'format-model="rgba"')
|
|
963
|
-
|
|
964
|
-
ui.button(on_click=element_menu.open, icon="colorize")
|
|
965
|
-
|
|
966
|
-
super().__init__(color, element_menu)
|
|
967
|
-
|
|
968
|
-
for key, value in kws.items():
|
|
969
|
-
if is_ref(value) and key != "color":
|
|
970
|
-
self.bind_prop(key, value) # type: ignore
|
|
971
|
-
|
|
972
|
-
self._ex_setup()
|
|
973
|
-
|
|
974
|
-
def _ex_setup(self):
|
|
975
|
-
ele = self._element_picker
|
|
976
|
-
|
|
977
|
-
@effect
|
|
978
|
-
def _():
|
|
979
|
-
ele._props["modelValue"] = self.value
|
|
980
|
-
|
|
981
|
-
def onModelValueChanged(e):
|
|
982
|
-
self._ref.value = e.args # type: ignore
|
|
983
|
-
|
|
984
|
-
ele.on("update:modelValue", handler=onModelValueChanged)
|
|
985
|
-
|
|
986
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
987
|
-
if prop == "value":
|
|
988
|
-
return self.bind_value(ref_ui)
|
|
989
|
-
|
|
990
|
-
return super().bind_prop(prop, ref_ui)
|
|
991
|
-
|
|
992
|
-
def bind_color(self, ref_ui: ReadonlyRef[str]):
|
|
993
|
-
@effect
|
|
994
|
-
def _():
|
|
995
|
-
self._element_picker._props["modelValue"] = ref_ui.value
|
|
996
|
-
|
|
997
|
-
return self
|
|
998
|
-
|
|
999
|
-
def bind_value(self, ref_ui: ReadonlyRef[bool]):
|
|
1000
|
-
@effect
|
|
1001
|
-
def _():
|
|
1002
|
-
self._element_picker._props["value"] = ref_ui.value
|
|
1003
|
-
|
|
1004
|
-
return self
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
class ColorPickerLazyBindableUi(ColorPickerBindableUi):
|
|
1008
|
-
def __init__(
|
|
1009
|
-
self,
|
|
1010
|
-
color: TMaybeRef[str] = "",
|
|
1011
|
-
*,
|
|
1012
|
-
on_pick: Callable[..., Any] | None = None,
|
|
1013
|
-
value: TMaybeRef[bool] = False,
|
|
1014
|
-
) -> None:
|
|
1015
|
-
super().__init__(color, on_pick=on_pick, value=value)
|
|
1016
|
-
|
|
1017
|
-
def _ex_setup(self):
|
|
1018
|
-
ele = self._element_picker
|
|
1019
|
-
|
|
1020
|
-
# @effect
|
|
1021
|
-
# def _():
|
|
1022
|
-
# ele._props["modelValue"] = self.value
|
|
1023
|
-
|
|
1024
|
-
def onModelValueChanged(e):
|
|
1025
|
-
self._ref.value = e.args # type: ignore
|
|
1026
|
-
|
|
1027
|
-
ele.on("change", handler=onModelValueChanged)
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
_TAggridValue = Dict
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
class AggridBindableUi(BindableUi[ui.aggrid]):
|
|
1034
|
-
def __init__(
|
|
1035
|
-
self,
|
|
1036
|
-
options: TMaybeRef[Dict],
|
|
1037
|
-
*,
|
|
1038
|
-
html_columns: TMaybeRef[List[int]] = [],
|
|
1039
|
-
theme: TMaybeRef[str] = "balham",
|
|
1040
|
-
) -> None:
|
|
1041
|
-
kws = {
|
|
1042
|
-
"options": options,
|
|
1043
|
-
"html_columns": html_columns,
|
|
1044
|
-
"theme": theme,
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
1048
|
-
|
|
1049
|
-
element = ui.aggrid(**value_kws)
|
|
1050
|
-
|
|
1051
|
-
super().__init__(element)
|
|
1052
|
-
|
|
1053
|
-
for key, value in kws.items():
|
|
1054
|
-
if is_ref(value):
|
|
1055
|
-
self.bind_prop(key, value) # type: ignore
|
|
1056
|
-
|
|
1057
|
-
@staticmethod
|
|
1058
|
-
def from_pandas(df: TMaybeRef):
|
|
1059
|
-
if is_ref(df):
|
|
1060
|
-
|
|
1061
|
-
@ref_computed
|
|
1062
|
-
def cp_convert_df():
|
|
1063
|
-
return utils_common.convert_dataframe(df.value)
|
|
1064
|
-
|
|
1065
|
-
@ref_computed
|
|
1066
|
-
def cp_options():
|
|
1067
|
-
columnDefs = [
|
|
1068
|
-
{"headerName": col, "field": col}
|
|
1069
|
-
for col in cp_convert_df.value.columns
|
|
1070
|
-
]
|
|
1071
|
-
rowData = cp_convert_df.value.to_dict("records")
|
|
1072
|
-
data = {"columnDefs": columnDefs, "rowData": rowData}
|
|
1073
|
-
return data
|
|
1074
|
-
|
|
1075
|
-
return AggridBindableUi(cp_options)
|
|
1076
|
-
|
|
1077
|
-
columnDefs = [{"headerName": col, "field": col} for col in df.columns] # type: ignore
|
|
1078
|
-
rowData = df.to_dict("records") # type: ignore
|
|
1079
|
-
options = {"columnDefs": columnDefs, "rowData": rowData}
|
|
1080
|
-
return AggridBindableUi(options)
|
|
1081
|
-
|
|
1082
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
1083
|
-
if prop == "options":
|
|
1084
|
-
return self.bind_options(ref_ui)
|
|
1085
|
-
|
|
1086
|
-
return super().bind_prop(prop, ref_ui)
|
|
1087
|
-
|
|
1088
|
-
def bind_options(self, ref_ui: ReadonlyRef[List[Dict]]):
|
|
1089
|
-
@effect
|
|
1090
|
-
def _():
|
|
1091
|
-
ele = self.element
|
|
1092
|
-
data = ref_ui.value
|
|
1093
|
-
ele._props["options"].update(data)
|
|
1094
|
-
ele.update()
|
|
1095
|
-
|
|
1096
|
-
return self
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
class TableBindableUi(BindableUi[ui.table]):
|
|
1100
|
-
def __init__(
|
|
1101
|
-
self,
|
|
1102
|
-
columns: TMaybeRef[List[Dict]],
|
|
1103
|
-
rows: TMaybeRef[List[Dict]],
|
|
1104
|
-
row_key: TMaybeRef[str] = "id",
|
|
1105
|
-
title: Optional[TMaybeRef[str]] = None,
|
|
1106
|
-
selection: Optional[TMaybeRef[Literal["single", "multiple"]]] = None,
|
|
1107
|
-
pagination: Optional[TMaybeRef[int]] = 15,
|
|
1108
|
-
on_select: Optional[Callable[..., Any]] = None,
|
|
1109
|
-
) -> None:
|
|
1110
|
-
kws = {
|
|
1111
|
-
"columns": columns,
|
|
1112
|
-
"rows": rows,
|
|
1113
|
-
"row_key": row_key,
|
|
1114
|
-
"title": title,
|
|
1115
|
-
"selection": selection,
|
|
1116
|
-
"pagination": pagination,
|
|
1117
|
-
"on_select": on_select,
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
1121
|
-
|
|
1122
|
-
element = ui.table(**value_kws)
|
|
1123
|
-
|
|
1124
|
-
super().__init__(element)
|
|
1125
|
-
|
|
1126
|
-
for key, value in kws.items():
|
|
1127
|
-
if is_ref(value):
|
|
1128
|
-
self.bind_prop(key, value) # type: ignore
|
|
1129
|
-
|
|
1130
|
-
@staticmethod
|
|
1131
|
-
def from_pandas(df: TMaybeRef):
|
|
1132
|
-
if is_ref(df):
|
|
1133
|
-
|
|
1134
|
-
@ref_computed
|
|
1135
|
-
def cp_convert_df():
|
|
1136
|
-
return utils_common.convert_dataframe(df.value)
|
|
1137
|
-
|
|
1138
|
-
@ref_computed
|
|
1139
|
-
def cp_rows():
|
|
1140
|
-
return cp_convert_df.value.to_dict("records")
|
|
1141
|
-
|
|
1142
|
-
@ref_computed
|
|
1143
|
-
def cp_cols():
|
|
1144
|
-
return [
|
|
1145
|
-
{
|
|
1146
|
-
"name": col,
|
|
1147
|
-
"label": col,
|
|
1148
|
-
"field": col,
|
|
1149
|
-
}
|
|
1150
|
-
for col in cp_convert_df.value.columns
|
|
1151
|
-
]
|
|
1152
|
-
|
|
1153
|
-
return TableBindableUi(cp_cols, cp_rows)
|
|
1154
|
-
|
|
1155
|
-
df = utils_common.convert_dataframe(df)
|
|
1156
|
-
rows = df.to_dict("records")
|
|
1157
|
-
|
|
1158
|
-
cols = [
|
|
1159
|
-
{
|
|
1160
|
-
"name": col,
|
|
1161
|
-
"label": col,
|
|
1162
|
-
"field": col,
|
|
1163
|
-
}
|
|
1164
|
-
for col in df.columns
|
|
1165
|
-
]
|
|
1166
|
-
return TableBindableUi(cols, rows)
|
|
1167
|
-
|
|
1168
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
1169
|
-
if prop == "dataframe":
|
|
1170
|
-
return self.bind_dataframe(ref_ui)
|
|
1171
|
-
|
|
1172
|
-
if prop == "rows":
|
|
1173
|
-
return self.bind_rows(ref_ui)
|
|
1174
|
-
|
|
1175
|
-
if prop == "columns":
|
|
1176
|
-
return self.bind_columns(ref_ui)
|
|
1177
|
-
|
|
1178
|
-
return super().bind_prop(prop, ref_ui)
|
|
1179
|
-
|
|
1180
|
-
def bind_dataframe(self, ref_df: ReadonlyRef):
|
|
1181
|
-
@ref_computed
|
|
1182
|
-
def cp_converted_df():
|
|
1183
|
-
df = ref_df.value
|
|
1184
|
-
return utils_common.convert_dataframe(df)
|
|
1185
|
-
|
|
1186
|
-
@ref_computed
|
|
1187
|
-
def cp_rows():
|
|
1188
|
-
return cp_converted_df.value.to_dict("records")
|
|
1189
|
-
|
|
1190
|
-
@ref_computed
|
|
1191
|
-
def cp_cols():
|
|
1192
|
-
return [
|
|
1193
|
-
{
|
|
1194
|
-
"name": col,
|
|
1195
|
-
"label": col,
|
|
1196
|
-
"field": col,
|
|
1197
|
-
}
|
|
1198
|
-
for col in cp_converted_df.value.columns
|
|
1199
|
-
]
|
|
1200
|
-
|
|
1201
|
-
self.bind_rows(cp_rows).bind_columns(cp_cols)
|
|
1202
|
-
|
|
1203
|
-
return self
|
|
1204
|
-
|
|
1205
|
-
def bind_rows(self, ref_ui: ReadonlyRef[List[Dict]]):
|
|
1206
|
-
@effect
|
|
1207
|
-
def _():
|
|
1208
|
-
ele = self.element
|
|
1209
|
-
ele._props["rows"] = ref_ui.value
|
|
1210
|
-
ele.update()
|
|
1211
|
-
|
|
1212
|
-
return self
|
|
1213
|
-
|
|
1214
|
-
def bind_columns(self, ref_ui: ReadonlyRef[List[Dict]]):
|
|
1215
|
-
@effect
|
|
1216
|
-
def _():
|
|
1217
|
-
ele = self.element
|
|
1218
|
-
ele._props["columns"] = ref_ui.value
|
|
1219
|
-
ele.update()
|
|
1220
|
-
|
|
1221
|
-
return self
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
_TDrawerSide = Literal["left", "right"]
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
class DrawerBindableUi(SingleValueBindableUi[bool, Drawer]):
|
|
1228
|
-
def __init__(
|
|
1229
|
-
self,
|
|
1230
|
-
side: TMaybeRef[_TDrawerSide] = "left",
|
|
1231
|
-
overlay: TMaybeRef[bool] = False,
|
|
1232
|
-
*,
|
|
1233
|
-
value: TMaybeRef[bool] = True,
|
|
1234
|
-
fixed: TMaybeRef[bool] = False,
|
|
1235
|
-
bordered: TMaybeRef[bool] = True,
|
|
1236
|
-
elevated: TMaybeRef[bool] = False,
|
|
1237
|
-
top_corner: TMaybeRef[bool] = False,
|
|
1238
|
-
bottom_corner: TMaybeRef[bool] = False,
|
|
1239
|
-
) -> None:
|
|
1240
|
-
kws = {
|
|
1241
|
-
"side": side,
|
|
1242
|
-
"overlay": overlay,
|
|
1243
|
-
"value": value,
|
|
1244
|
-
"fixed": fixed,
|
|
1245
|
-
"bordered": bordered,
|
|
1246
|
-
"elevated": elevated,
|
|
1247
|
-
"top_corner": top_corner,
|
|
1248
|
-
"bottom_corner": bottom_corner,
|
|
1249
|
-
}
|
|
1250
|
-
|
|
1251
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
1252
|
-
del value_kws["side"]
|
|
1253
|
-
del value_kws["overlay"]
|
|
1254
|
-
|
|
1255
|
-
element = None
|
|
1256
|
-
|
|
1257
|
-
if to_value(side) == "left":
|
|
1258
|
-
element = ui.left_drawer(**value_kws)
|
|
1259
|
-
else:
|
|
1260
|
-
element = ui.right_drawer(**value_kws)
|
|
1261
|
-
|
|
1262
|
-
element.style(f"background-color:rgba(25, 118, 210,0.3)")
|
|
1263
|
-
element.classes("flex flex-col gap-4")
|
|
1264
|
-
|
|
1265
|
-
init_value = (
|
|
1266
|
-
element._props["model-value"]
|
|
1267
|
-
if "model-value" in element._props
|
|
1268
|
-
else element._props["show-if-above"]
|
|
1269
|
-
)
|
|
1270
|
-
|
|
1271
|
-
super().__init__(value, element)
|
|
1272
|
-
|
|
1273
|
-
@effect
|
|
1274
|
-
def _():
|
|
1275
|
-
value = "true" if self.value else "false"
|
|
1276
|
-
element.props(f":model-value={value}")
|
|
1277
|
-
|
|
1278
|
-
def on_update(e):
|
|
1279
|
-
self._ref.value = e.args
|
|
1280
|
-
|
|
1281
|
-
element.on("update:modelValue", on_update)
|
|
1282
|
-
|
|
1283
|
-
for key, value in kws.items():
|
|
1284
|
-
if is_ref(value):
|
|
1285
|
-
self.bind_prop(key, value) # type: ignore
|
|
1286
|
-
|
|
1287
|
-
def toggle(self):
|
|
1288
|
-
self.element.toggle()
|
|
1289
|
-
return self
|
|
1290
|
-
|
|
1291
|
-
def __enter__(self):
|
|
1292
|
-
self.element.__enter__()
|
|
1293
|
-
return self
|
|
1294
|
-
|
|
1295
|
-
def __exit__(self, *_: Any):
|
|
1296
|
-
self.element.__exit__(*_)
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
class EChartsBindableUi(BindableUi[echarts]):
|
|
1300
|
-
def __init__(
|
|
1301
|
-
self,
|
|
1302
|
-
options: TMaybeRef[Dict],
|
|
1303
|
-
) -> None:
|
|
1304
|
-
kws = {
|
|
1305
|
-
"options": options,
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
1309
|
-
|
|
1310
|
-
element = echarts(**value_kws)
|
|
1311
|
-
|
|
1312
|
-
super().__init__(element)
|
|
1313
|
-
|
|
1314
|
-
for key, value in kws.items():
|
|
1315
|
-
if is_ref(value):
|
|
1316
|
-
self.bind_prop(key, value) # type: ignore
|
|
1317
|
-
|
|
1318
|
-
@staticmethod
|
|
1319
|
-
def _pyecharts2opts(chart):
|
|
1320
|
-
import simplejson as json
|
|
1321
|
-
from pyecharts.charts.chart import Base
|
|
1322
|
-
|
|
1323
|
-
if isinstance(chart, Base):
|
|
1324
|
-
return json.loads(chart.dump_options())
|
|
1325
|
-
|
|
1326
|
-
return {}
|
|
1327
|
-
|
|
1328
|
-
@staticmethod
|
|
1329
|
-
def from_pyecharts(chart: TMaybeRef):
|
|
1330
|
-
if is_ref(chart):
|
|
1331
|
-
|
|
1332
|
-
@ref_computed
|
|
1333
|
-
def chart_opt():
|
|
1334
|
-
return EChartsBindableUi._pyecharts2opts(chart.value)
|
|
1335
|
-
|
|
1336
|
-
return EChartsBindableUi(chart_opt)
|
|
1337
|
-
|
|
1338
|
-
return EChartsBindableUi(EChartsBindableUi._pyecharts2opts(chart))
|
|
1339
|
-
|
|
1340
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
1341
|
-
if prop == "options":
|
|
1342
|
-
return self.bind_options(ref_ui)
|
|
1343
|
-
|
|
1344
|
-
return super().bind_prop(prop, ref_ui)
|
|
1345
|
-
|
|
1346
|
-
def bind_options(self, ref_ui: ReadonlyRef[Dict]):
|
|
1347
|
-
@effect
|
|
1348
|
-
def _():
|
|
1349
|
-
ele = self.element
|
|
1350
|
-
ele.update_options(ref_ui.value)
|
|
1351
|
-
ele.update()
|
|
1352
|
-
|
|
1353
|
-
return self
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
class RowBindableUi(BindableUi[ui.row]):
|
|
1357
|
-
def __init__(
|
|
1358
|
-
self,
|
|
1359
|
-
) -> None:
|
|
1360
|
-
element = ui.row()
|
|
1361
|
-
|
|
1362
|
-
super().__init__(element)
|
|
1363
|
-
|
|
1364
|
-
def __enter__(self):
|
|
1365
|
-
self.element.__enter__()
|
|
1366
|
-
return self
|
|
1367
|
-
|
|
1368
|
-
def __exit__(self, *_: Any):
|
|
1369
|
-
self.element.__exit__(*_)
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
class CardBindableUi(BindableUi[ui.card]):
|
|
1373
|
-
def __init__(
|
|
1374
|
-
self,
|
|
1375
|
-
) -> None:
|
|
1376
|
-
element = ui.card()
|
|
1377
|
-
|
|
1378
|
-
super().__init__(element)
|
|
1379
|
-
|
|
1380
|
-
def __enter__(self):
|
|
1381
|
-
self.element.__enter__()
|
|
1382
|
-
return self
|
|
1383
|
-
|
|
1384
|
-
def __exit__(self, *_: Any):
|
|
1385
|
-
self.element.__exit__(*_)
|
|
1386
|
-
|
|
1387
|
-
def tight(self):
|
|
1388
|
-
"""Removes padding and gaps between nested elements."""
|
|
1389
|
-
self.element._classes.clear()
|
|
1390
|
-
self.element._style.clear()
|
|
1391
|
-
return self
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
class CardSectionBindableUi(BindableUi[ui.card_section]):
|
|
1395
|
-
def __init__(
|
|
1396
|
-
self,
|
|
1397
|
-
) -> None:
|
|
1398
|
-
element = ui.card_section()
|
|
1399
|
-
|
|
1400
|
-
super().__init__(element)
|
|
1401
|
-
|
|
1402
|
-
def __enter__(self):
|
|
1403
|
-
self.element.__enter__()
|
|
1404
|
-
return self
|
|
1405
|
-
|
|
1406
|
-
def __exit__(self, *_: Any):
|
|
1407
|
-
self.element.__exit__(*_)
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
class CardActionsBindableUi(BindableUi[ui.card_actions]):
|
|
1411
|
-
def __init__(
|
|
1412
|
-
self,
|
|
1413
|
-
) -> None:
|
|
1414
|
-
element = ui.card_actions()
|
|
1415
|
-
|
|
1416
|
-
super().__init__(element)
|
|
1417
|
-
|
|
1418
|
-
def __enter__(self):
|
|
1419
|
-
self.element.__enter__()
|
|
1420
|
-
return self
|
|
1421
|
-
|
|
1422
|
-
def __exit__(self, *_: Any):
|
|
1423
|
-
self.element.__exit__(*_)
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
class HtmlBindableUi(SingleValueBindableUi[str, ui.html]):
|
|
1427
|
-
@staticmethod
|
|
1428
|
-
def _setup_(binder: "HtmlBindableUi"):
|
|
1429
|
-
first = True
|
|
1430
|
-
|
|
1431
|
-
@effect
|
|
1432
|
-
def _():
|
|
1433
|
-
nonlocal first
|
|
1434
|
-
|
|
1435
|
-
async def task():
|
|
1436
|
-
pass
|
|
1437
|
-
await ui.run_javascript(
|
|
1438
|
-
f"getElement({binder.element.id}).innerText= '{binder.value}' ",
|
|
1439
|
-
respond=False,
|
|
1440
|
-
)
|
|
1441
|
-
|
|
1442
|
-
if not first:
|
|
1443
|
-
asyncio.run(task())
|
|
1444
|
-
else:
|
|
1445
|
-
first = False
|
|
1446
|
-
|
|
1447
|
-
def __init__(
|
|
1448
|
-
self,
|
|
1449
|
-
content: TMaybeRef[str] = "",
|
|
1450
|
-
) -> None:
|
|
1451
|
-
kws = {
|
|
1452
|
-
"content": content,
|
|
1453
|
-
}
|
|
1454
|
-
|
|
1455
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
1456
|
-
|
|
1457
|
-
element = ui.html(**value_kws)
|
|
1458
|
-
|
|
1459
|
-
super().__init__(content, element)
|
|
1460
|
-
|
|
1461
|
-
for key, value in kws.items():
|
|
1462
|
-
if is_ref(value):
|
|
1463
|
-
self.bind_prop(key, value) # type: ignore
|
|
1464
|
-
|
|
1465
|
-
HtmlBindableUi._setup_(self)
|
|
1466
|
-
|
|
1467
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
1468
|
-
if prop == "color":
|
|
1469
|
-
return self.bind_color(ref_ui)
|
|
1470
|
-
|
|
1471
|
-
return super().bind_prop(prop, ref_ui)
|
|
1472
|
-
|
|
1473
|
-
def bind_color(self, ref_ui: ReadonlyRef):
|
|
1474
|
-
@effect
|
|
1475
|
-
def _():
|
|
1476
|
-
ele = self.element
|
|
1477
|
-
color = ref_ui.value
|
|
1478
|
-
ele._style["color"] = color
|
|
1479
|
-
ele.update()
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
class ImageBindableUi(SingleValueBindableUi[Union[str, Path], ui.image]):
|
|
1483
|
-
@staticmethod
|
|
1484
|
-
def _setup_(binder: "ImageBindableUi"):
|
|
1485
|
-
@effect
|
|
1486
|
-
def _():
|
|
1487
|
-
binder.element.on_source_change(binder.value)
|
|
1488
|
-
|
|
1489
|
-
def __init__(
|
|
1490
|
-
self,
|
|
1491
|
-
source: Union[TMaybeRef[str], TMaybeRef[Path]] = "",
|
|
1492
|
-
) -> None:
|
|
1493
|
-
kws = {
|
|
1494
|
-
"source": source,
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
1498
|
-
|
|
1499
|
-
element = ui.image(**value_kws)
|
|
1500
|
-
|
|
1501
|
-
super().__init__(source, element) # type: ignore
|
|
1502
|
-
|
|
1503
|
-
for key, value in kws.items():
|
|
1504
|
-
if is_ref(value):
|
|
1505
|
-
self.bind_prop(key, value) # type: ignore
|
|
1506
|
-
|
|
1507
|
-
# ImageBindableUi._setup_(self)
|
|
1508
|
-
|
|
1509
|
-
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
1510
|
-
if prop == "source":
|
|
1511
|
-
return self.bind_source(ref_ui)
|
|
1512
|
-
|
|
1513
|
-
return super().bind_prop(prop, ref_ui)
|
|
1514
|
-
|
|
1515
|
-
def bind_source(self, ref_ui: ReadonlyRef[Union[str, Path]]):
|
|
1516
|
-
@effect
|
|
1517
|
-
def _():
|
|
1518
|
-
ele = self.element
|
|
1519
|
-
source = ref_ui.value
|
|
1520
|
-
ele.on_source_change(source)
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
class UploadResult:
|
|
1524
|
-
def __init__(self, content: bytes = bytes(), name="", type=""):
|
|
1525
|
-
self.content = content
|
|
1526
|
-
self.name = name
|
|
1527
|
-
self.type = type
|
|
1528
|
-
|
|
1529
|
-
def get_bytes(self):
|
|
1530
|
-
return self.content
|
|
1531
|
-
|
|
1532
|
-
@property
|
|
1533
|
-
def ready(self):
|
|
1534
|
-
return len(self.content) > 0
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
class UploadBindableUi(SingleValueBindableUi[UploadResult, ui.upload]):
|
|
1538
|
-
@staticmethod
|
|
1539
|
-
def _setup_(binder: "UploadBindableUi"):
|
|
1540
|
-
def on_upload(e: ng_events.UploadEventArguments):
|
|
1541
|
-
binder._ref.value = UploadResult(e.content.read(), e.name, e.type)
|
|
1542
|
-
|
|
1543
|
-
binder._on_upload_callbacks.append(on_upload)
|
|
1544
|
-
|
|
1545
|
-
def __init__(
|
|
1546
|
-
self,
|
|
1547
|
-
multiple: TMaybeRef[bool] = False,
|
|
1548
|
-
max_file_size: Optional[TMaybeRef[int]] = None,
|
|
1549
|
-
max_total_size: Optional[TMaybeRef[int]] = None,
|
|
1550
|
-
max_files: Optional[TMaybeRef[int]] = None,
|
|
1551
|
-
on_upload: Optional[Callable[..., Any]] = None,
|
|
1552
|
-
on_rejected: Optional[Callable[..., Any]] = None,
|
|
1553
|
-
label: TMaybeRef[str] = "",
|
|
1554
|
-
auto_upload: TMaybeRef[bool] = False,
|
|
1555
|
-
) -> None:
|
|
1556
|
-
kws = {
|
|
1557
|
-
"multiple": multiple,
|
|
1558
|
-
"max_file_size": max_file_size,
|
|
1559
|
-
"max_total_size": max_total_size,
|
|
1560
|
-
"max_files": max_files,
|
|
1561
|
-
"on_rejected": on_rejected,
|
|
1562
|
-
"label": label,
|
|
1563
|
-
"auto_upload": auto_upload,
|
|
1564
|
-
}
|
|
1565
|
-
|
|
1566
|
-
value_kws = _convert_kws_ref2value(kws)
|
|
1567
|
-
|
|
1568
|
-
self._on_upload_callbacks = []
|
|
1569
|
-
|
|
1570
|
-
def _on_upload(e: ng_events.UploadEventArguments):
|
|
1571
|
-
for fn in self._on_upload_callbacks:
|
|
1572
|
-
fn(e)
|
|
1573
|
-
|
|
1574
|
-
if on_upload:
|
|
1575
|
-
self._on_upload_callbacks.append(on_upload)
|
|
1576
|
-
|
|
1577
|
-
element = ui.upload(**value_kws, on_upload=_on_upload)
|
|
1578
|
-
|
|
1579
|
-
super().__init__(UploadResult(), element) # type: ignore
|
|
1580
|
-
|
|
1581
|
-
for key, value in kws.items():
|
|
1582
|
-
if is_ref(value):
|
|
1583
|
-
self.bind_prop(key, value) # type: ignore
|
|
1584
|
-
|
|
1585
|
-
UploadBindableUi._setup_(self)
|