ex4nicegui 0.5.2__tar.gz → 0.5.3__tar.gz
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-0.5.2 → ex4nicegui-0.5.3}/PKG-INFO +53 -33
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/README.md +52 -32
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/__init__.py +3 -1
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/gsap/__init__.py +2 -0
- ex4nicegui-0.5.3/ex4nicegui/gsap/timeline.js +56 -0
- ex4nicegui-0.5.3/ex4nicegui/gsap/timeline.py +78 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/__init__.py +6 -1
- ex4nicegui-0.5.3/ex4nicegui/reactive/officials/circular_progress.py +64 -0
- ex4nicegui-0.5.3/ex4nicegui/reactive/officials/column.py +36 -0
- ex4nicegui-0.5.3/ex4nicegui/reactive/officials/knob.py +75 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/number.py +1 -2
- ex4nicegui-0.5.3/ex4nicegui/reactive/officials/row.py +35 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/utils.py +40 -1
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/vfor.py +19 -39
- ex4nicegui-0.5.3/ex4nicegui/reactive/vmodel.py +210 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/utils/signals.py +12 -2
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui.egg-info/PKG-INFO +53 -33
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui.egg-info/SOURCES.txt +5 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui.egg-info/requires.txt +2 -1
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/setup.py +2 -2
- ex4nicegui-0.5.2/ex4nicegui/reactive/officials/column.py +0 -21
- ex4nicegui-0.5.2/ex4nicegui/reactive/officials/row.py +0 -21
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/LICENSE +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/dataSource.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/dataSourceFacade.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/containers.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/layouts.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/models.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/text.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/ui_aggrid.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/ui_date_picker.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/ui_date_picker.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/ui_echarts.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/ui_radio.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/ui_range.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/ui_select.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/ui_slider.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/elements/ui_table.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/index.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/protocols.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/bi/types.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/experimental_/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/experimental_/gridLayout/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/experimental_/gridLayout/index.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/gsap/gsap.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/gsap/wrapGsap.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/layout/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/layout/gridFlex/GridFlex.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/layout/gridFlex/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/layout/gridFlex/gridFlex.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/layout/gridFlex/utils.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/layout/rxFlex/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/layout/rxFlex/index.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/layout/rxFlex/types.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/d3/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/d3/d3-color.ems.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/d3/d3-dispatch.ems.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/d3/d3-drag.ems.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/d3/d3-ease.ems.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/d3/d3-interpolate.ems.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/d3/d3-selection.ems.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/d3/d3-timer.ems.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/d3/d3-transition.ems.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/d3/d3-zoom.ems.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/CSSPlugin.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/CSSRulePlugin.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/CustomEase.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/Draggable.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/EasePack.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/EaselPlugin.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/Flip.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/MotionPathPlugin.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/Observer.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/PixiPlugin.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/ScrollToPlugin.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/ScrollTrigger.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/TextPlugin.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/all.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/gsap-core.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/utils/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/utils/matrix.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/utils/paths.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/libs/gsap/utils/strings.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/EChartsComponent/ECharts.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/EChartsComponent/ECharts.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/EChartsComponent/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/UseDraggable/UseDraggable.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/UseDraggable/UseDraggable.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/UseDraggable/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/dropZone/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/dropZone/dropZone.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/dropZone/dropZone.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/fileWatcher.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/local_file_picker.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/mermaid/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/mermaid/mermaid.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/mermaid/mermaid.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/aggrid.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/base.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/button.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/card.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/checkbox.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/color_picker.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/date.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/drawer.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/echarts.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/expansion.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/grid.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/html.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/html.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/icon.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/image.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/input.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/label.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/linear_progress.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/radio.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/select.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/slider.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/switch.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/table.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/textarea.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/upload.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/officials/utils.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/q_pagination.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/rxui.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/useMouse/UseMouse.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/useMouse/UseMouse.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/useMouse/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/usePagination.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/reactive/vfor.js +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/tools/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/tools/debug.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/utils/__init__.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/utils/apiEffect.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/utils/clientScope.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/utils/common.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/utils/effect.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui/utils/scheduler.py +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui.egg-info/dependency_links.txt +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui.egg-info/not-zip-safe +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/ex4nicegui.egg-info/top_level.txt +0 -0
- {ex4nicegui-0.5.2 → ex4nicegui-0.5.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ex4nicegui
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.3
|
|
4
4
|
Summary: Extension library based on nicegui, providing data responsive,BI functionality modules
|
|
5
5
|
Home-page:
|
|
6
6
|
Author: carson_jia
|
|
@@ -386,16 +386,58 @@ ui.button("change b", on_click=change_b)
|
|
|
386
386
|
|
|
387
387
|
---
|
|
388
388
|
|
|
389
|
+
## functionality
|
|
390
|
+
|
|
391
|
+
### vmodel
|
|
392
|
+
Create two-way bindings on form input elements or components.
|
|
393
|
+
|
|
394
|
+
Bidirectional bindings are supported by default for `ref` simple value types
|
|
395
|
+
```python
|
|
396
|
+
from ex4nicegui import rxui, to_ref, deep_ref
|
|
397
|
+
|
|
398
|
+
data = to_ref("init")
|
|
399
|
+
|
|
400
|
+
rxui.label(lambda: f"{data.value=}")
|
|
401
|
+
# two-way binding
|
|
402
|
+
rxui.input(value=data)
|
|
403
|
+
```
|
|
404
|
+
- Simple value types are generally immutable values such as `str`, `int`, etc.
|
|
405
|
+
|
|
406
|
+
When using complex data structures, `deep_ref` is used to keep nested values responsive.
|
|
407
|
+
```python
|
|
408
|
+
data = deep_ref({"a": 1, "b": [1, 2, 3, 4]})
|
|
409
|
+
|
|
410
|
+
rxui.label(lambda: f"{data.value=!s}")
|
|
411
|
+
|
|
412
|
+
# No binding effect
|
|
413
|
+
rxui.input(value=data.value["a"])
|
|
414
|
+
|
|
415
|
+
# readonly binding
|
|
416
|
+
rxui.input(value=lambda: data.value["a"])
|
|
417
|
+
|
|
418
|
+
# two-way binding
|
|
419
|
+
rxui.input(value=rxui.vmodel(data.value["a"]))
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
- The first input box will be completely unresponsive because the code is equivalent to passing in a value `1` directly
|
|
423
|
+
- The second input box will get read responsiveness due to the use of a function.
|
|
424
|
+
- The third input box, wrapped in `rxui.vmodel`, can be bi-directionally bound.
|
|
425
|
+
|
|
426
|
+
Most use `vmodel` with `vfor`, see [todo list examples](./examples/todomvc/)
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
389
430
|
### vfor
|
|
390
431
|
Render list components based on list responsive data. Each component is updated on demand. Data items support dictionaries or objects of any type
|
|
391
432
|
|
|
392
433
|
```python
|
|
393
434
|
from nicegui import ui
|
|
394
435
|
from ex4nicegui.reactive import rxui
|
|
395
|
-
from ex4nicegui import
|
|
436
|
+
from ex4nicegui import deep_ref, ref_computed
|
|
437
|
+
from typing import Dict
|
|
396
438
|
|
|
397
439
|
# refs
|
|
398
|
-
items =
|
|
440
|
+
items = deep_ref(
|
|
399
441
|
[
|
|
400
442
|
{"id": 1, "message": "foo", "done": False},
|
|
401
443
|
{"id": 2, "message": "bar", "done": True},
|
|
@@ -411,7 +453,6 @@ def done_count_info():
|
|
|
411
453
|
def check():
|
|
412
454
|
for item in items.value:
|
|
413
455
|
item["done"] = not item["done"]
|
|
414
|
-
items.value = items.value
|
|
415
456
|
|
|
416
457
|
|
|
417
458
|
# ui
|
|
@@ -420,54 +461,33 @@ ui.button("check", on_click=check)
|
|
|
420
461
|
|
|
421
462
|
|
|
422
463
|
@rxui.vfor(items,key='id')
|
|
423
|
-
def _(store: rxui.VforStore):
|
|
464
|
+
def _(store: rxui.VforStore[Dict]):
|
|
424
465
|
# function to build the interface for each row of data
|
|
425
|
-
|
|
466
|
+
item = store.get() # Get responsive object with `store.get`
|
|
467
|
+
mes = rxui.vmodel(item.value['message'])
|
|
426
468
|
|
|
427
469
|
# Enter the content of the input box,
|
|
428
470
|
# you can see the title of the radio box changes synchronously
|
|
429
471
|
with ui.card():
|
|
430
|
-
|
|
431
|
-
|
|
472
|
+
with ui.row():
|
|
473
|
+
rxui.input(value=mes)
|
|
474
|
+
rxui.label(lambda: f"{mes.value=!s}")
|
|
475
|
+
rxui.checkbox(text=mes, value=rxui.vmodel(item.value['done']))
|
|
432
476
|
|
|
433
477
|
```
|
|
434
478
|
|
|
435
479
|
- `rxui.vfor` decorator to custom function
|
|
436
480
|
- The first argument is passed to the responsive list. Each item in the list can be a dictionary or other object (`dataclasses` etc.)
|
|
437
481
|
- Second parameter `key`: In order to be able to keep track of the identity of each node, and thus reuse and reorder existing elements, you can provide a unique key for the block corresponding to each element. The default(`None`) is to use the list element index.
|
|
438
|
-
- The custom function takes one argument. The current row's
|
|
482
|
+
- The custom function takes one argument. The current row's can be retrieved via `store.get`, which is a responsive object.
|
|
439
483
|
|
|
440
484
|
|
|
441
485
|
> vfor are created only when new data is added.
|
|
442
486
|
|
|
443
|
-
In the above example, you'll notice that when the checkbox is clicked, the text of the number of completed counts (`done_count_info`) doesn't change synchronously
|
|
444
|
-
|
|
445
|
-
This is because responsive data changes in the `vfor` function do not affect the data source list. This is a restriction to prevent writing overly complex bi-directional data flow response logic.
|
|
446
|
-
|
|
447
|
-
We should make changes to the data source list via events in the function
|
|
448
|
-
|
|
449
|
-
```python
|
|
450
|
-
...
|
|
451
|
-
|
|
452
|
-
@rxui.vfor(items, key="id")
|
|
453
|
-
def _(store: rxui.VforStore):
|
|
454
|
-
msg_ref = store.get("message")
|
|
455
|
-
|
|
456
|
-
def on_check_change(e):
|
|
457
|
-
items.value[store.row_index]["done"] = e.value
|
|
458
|
-
items.value = items.value
|
|
459
|
-
|
|
460
|
-
with ui.card():
|
|
461
|
-
rxui.input(value=msg_ref)
|
|
462
|
-
rxui.checkbox(text=msg_ref, value=store.get("done"),on_change=on_check_change)
|
|
463
|
-
|
|
464
|
-
```
|
|
465
487
|
|
|
466
488
|
---
|
|
467
489
|
|
|
468
490
|
|
|
469
|
-
## functionality
|
|
470
|
-
|
|
471
491
|
### Bind class names
|
|
472
492
|
|
|
473
493
|
All component classes provide `bind_classes` for binding `class`, supporting three different data structures.
|
|
@@ -383,16 +383,56 @@ ui.button("change b", on_click=change_b)
|
|
|
383
383
|
|
|
384
384
|
## 组件功能
|
|
385
385
|
|
|
386
|
+
### vmodel
|
|
387
|
+
在表单输入元素或组件上创建双向绑定。
|
|
388
|
+
|
|
389
|
+
简单值类型的 `ref` 默认支持双向绑定
|
|
390
|
+
```python
|
|
391
|
+
from ex4nicegui import rxui, to_ref, deep_ref
|
|
392
|
+
|
|
393
|
+
data = to_ref("init")
|
|
394
|
+
|
|
395
|
+
rxui.label(lambda: f"{data.value=}")
|
|
396
|
+
# 默认就是双向绑定
|
|
397
|
+
rxui.input(value=data)
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
- 简单值类型一般是 `str`,`int` 等不可变值类型
|
|
401
|
+
|
|
402
|
+
当使用复杂数据结构时,会使用 `deep_ref` 保持嵌套值的响应性
|
|
403
|
+
```python
|
|
404
|
+
data = deep_ref({"a": 1, "b": [1, 2, 3, 4]})
|
|
405
|
+
|
|
406
|
+
rxui.label(lambda: f"{data.value=!s}")
|
|
407
|
+
|
|
408
|
+
# 当前版本没有任何绑定效果.或许未来的版本可以解决
|
|
409
|
+
rxui.input(value=data.value["a"])
|
|
410
|
+
|
|
411
|
+
# 只读绑定.其他途径修改了 `data.value["a"]` ,此输入框会同步,但反过来不行
|
|
412
|
+
rxui.input(value=lambda: data.value["a"])
|
|
413
|
+
|
|
414
|
+
# 要使用 vmodel 才能双向绑定
|
|
415
|
+
rxui.input(value=rxui.vmodel(data.value["a"]))
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
- 第一个输入框将完全失去响应性,因为代码等价于直接传入一个数值`1`
|
|
419
|
+
- 第二个输入框由于使用函数,将得到读取响应性(第三个输入框输入值,将得到同步)
|
|
420
|
+
- 第三个输入框,使用 `rxui.vmodel` 包裹,即可实现双向绑定
|
|
421
|
+
|
|
422
|
+
多数在配合 `vfor` 时使用 `vmodel`,可参考 [todo list 案例](./examples/todomvc/)
|
|
423
|
+
|
|
424
|
+
|
|
386
425
|
### vfor
|
|
387
426
|
基于列表响应式数据,渲染列表组件。每项组件按需更新。数据项支持字典或任意类型对象
|
|
388
427
|
|
|
389
428
|
```python
|
|
390
429
|
from nicegui import ui
|
|
391
430
|
from ex4nicegui.reactive import rxui
|
|
392
|
-
from ex4nicegui import
|
|
431
|
+
from ex4nicegui import deep_ref, ref_computed
|
|
432
|
+
from typing import Dict
|
|
393
433
|
|
|
394
434
|
# refs
|
|
395
|
-
items =
|
|
435
|
+
items = deep_ref(
|
|
396
436
|
[
|
|
397
437
|
{"id": 1, "message": "foo", "done": False},
|
|
398
438
|
{"id": 2, "message": "bar", "done": True},
|
|
@@ -408,55 +448,35 @@ def done_count_info():
|
|
|
408
448
|
def check():
|
|
409
449
|
for item in items.value:
|
|
410
450
|
item["done"] = not item["done"]
|
|
411
|
-
items.value = items.value
|
|
412
451
|
|
|
413
452
|
|
|
414
453
|
# ui
|
|
415
454
|
rxui.label(done_count_info)
|
|
416
455
|
ui.button("check", on_click=check)
|
|
417
456
|
|
|
418
|
-
|
|
419
|
-
|
|
457
|
+
|
|
458
|
+
@rxui.vfor(items,key='id')
|
|
459
|
+
def _(store: rxui.VforStore[Dict]):
|
|
420
460
|
# 函数中构建每一行数据的界面
|
|
421
|
-
|
|
461
|
+
item = store.get() # 通过 store.get 获取对应行的响应式对象(相当于每行的数据 to_ref(...))
|
|
462
|
+
mes = rxui.vmodel(item.value['message']) # 复杂结构默认没有双向绑定,需要使用 `vmodel`
|
|
422
463
|
|
|
423
464
|
# 输入框输入内容,可以看到单选框的标题同步变化
|
|
424
465
|
with ui.card():
|
|
425
|
-
|
|
426
|
-
|
|
466
|
+
with ui.row():
|
|
467
|
+
rxui.input(value=mes)
|
|
468
|
+
rxui.label(lambda: f"{mes.value=!s}")
|
|
469
|
+
rxui.checkbox(text=mes, value=rxui.vmodel(item.value['done']))
|
|
427
470
|
|
|
428
471
|
```
|
|
429
472
|
|
|
430
473
|
- `rxui.vfor` 装饰器到自定义函数
|
|
431
474
|
- 第一个参数传入响应式列表。列表中每一项可以是字典或其他对象(`dataclasses` 等等)
|
|
432
475
|
- 第二个参数 `key`: 为了可以跟踪每个节点的标识,从而重用和重新排序现有的元素,你可以为每个元素对应的块提供一个唯一的 key 。默认情况使用列表元素索引。
|
|
433
|
-
- 自定义函数带有一个参数。通过 `store.get`
|
|
476
|
+
- 自定义函数带有一个参数。通过 `store.get` 可以获取当前行的响应式对象
|
|
434
477
|
|
|
435
478
|
> vfor 渲染的项目,只有在新增数据时,才会创建
|
|
436
479
|
|
|
437
|
-
上述的例子中,你会发现,当点击 checkbox 时,完成数量的文本(`done_count_info`)并没有同步变化
|
|
438
|
-
|
|
439
|
-
因为 `vfor` 函数中对响应式数据修改,不会影响数据源列表。这是为了防止写出过于复杂的双向数据流响应逻辑而限制。
|
|
440
|
-
|
|
441
|
-
我们应该在函数中通过事件,对数据源列表做修改
|
|
442
|
-
|
|
443
|
-
```python
|
|
444
|
-
...
|
|
445
|
-
|
|
446
|
-
@rxui.vfor(items, key="id")
|
|
447
|
-
def _(store: rxui.VforStore):
|
|
448
|
-
msg_ref = store.get("message")
|
|
449
|
-
|
|
450
|
-
def on_check_change(e):
|
|
451
|
-
items.value[store.row_index]["done"] = e.value
|
|
452
|
-
items.value = items.value
|
|
453
|
-
|
|
454
|
-
with ui.card():
|
|
455
|
-
rxui.input(value=msg_ref)
|
|
456
|
-
rxui.checkbox(text=msg_ref, value=store.get("done"),on_change=on_check_change)
|
|
457
|
-
|
|
458
|
-
```
|
|
459
|
-
|
|
460
480
|
|
|
461
481
|
---
|
|
462
482
|
|
|
@@ -17,10 +17,12 @@ from ex4nicegui.utils.signals import (
|
|
|
17
17
|
deep_ref,
|
|
18
18
|
is_setter_ref,
|
|
19
19
|
batch,
|
|
20
|
+
is_reactive,
|
|
20
21
|
)
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
__all__ = [
|
|
25
|
+
"is_reactive",
|
|
24
26
|
"rxui",
|
|
25
27
|
"ref_computed",
|
|
26
28
|
"effect",
|
|
@@ -41,4 +43,4 @@ __all__ = [
|
|
|
41
43
|
"is_setter_ref",
|
|
42
44
|
]
|
|
43
45
|
|
|
44
|
-
__version__ = "0.5.
|
|
46
|
+
__version__ = "0.5.3"
|
|
@@ -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")
|
|
@@ -44,7 +44,8 @@ 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
|
-
|
|
47
|
+
from .officials.knob import KnobBindableUi as knob
|
|
48
|
+
from .officials.circular_progress import CircularProgressBindableUi as circular_progress
|
|
48
49
|
from .q_pagination import PaginationBindableUi as q_pagination
|
|
49
50
|
|
|
50
51
|
from .local_file_picker import local_file_picker
|
|
@@ -56,11 +57,14 @@ 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
|
|
59
61
|
|
|
60
62
|
pagination = q_pagination
|
|
61
63
|
|
|
62
64
|
|
|
63
65
|
__all__ = [
|
|
66
|
+
"circular_progress",
|
|
67
|
+
"knob",
|
|
64
68
|
"UploadResult",
|
|
65
69
|
"local_file_picker",
|
|
66
70
|
"use_draggable",
|
|
@@ -70,6 +74,7 @@ __all__ = [
|
|
|
70
74
|
"FilesWatcher",
|
|
71
75
|
"vfor",
|
|
72
76
|
"VforStore",
|
|
77
|
+
"vmodel",
|
|
73
78
|
"html",
|
|
74
79
|
"aggird",
|
|
75
80
|
"button",
|
|
@@ -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
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Any,
|
|
3
|
+
)
|
|
4
|
+
from ex4nicegui.reactive.utils import ParameterClassifier
|
|
5
|
+
from ex4nicegui.utils.signals import (
|
|
6
|
+
_TMaybeRef as TMaybeRef,
|
|
7
|
+
)
|
|
8
|
+
from nicegui import ui
|
|
9
|
+
from .base import BindableUi
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ColumnBindableUi(BindableUi[ui.column]):
|
|
13
|
+
def __init__(self, *, wrap: TMaybeRef[bool] = True) -> None:
|
|
14
|
+
pc = ParameterClassifier(locals(), maybeRefs=["wrap"], events=[])
|
|
15
|
+
element = ui.column(**pc.get_values_kws())
|
|
16
|
+
|
|
17
|
+
super().__init__(element)
|
|
18
|
+
|
|
19
|
+
for key, value in pc.get_bindings().items():
|
|
20
|
+
self.bind_prop(key, value) # type: ignore
|
|
21
|
+
|
|
22
|
+
def bind_prop(self, prop: str, ref_ui: TMaybeRef):
|
|
23
|
+
if prop == "wrap":
|
|
24
|
+
return self.bind_wrap(ref_ui)
|
|
25
|
+
|
|
26
|
+
return super().bind_prop(prop, ref_ui)
|
|
27
|
+
|
|
28
|
+
def bind_wrap(self, ref_ui: TMaybeRef):
|
|
29
|
+
self.bind_classes({"wrap": ref_ui})
|
|
30
|
+
|
|
31
|
+
def __enter__(self):
|
|
32
|
+
self.element.__enter__()
|
|
33
|
+
return self
|
|
34
|
+
|
|
35
|
+
def __exit__(self, *_: Any):
|
|
36
|
+
self.element.__exit__(*_)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Any,
|
|
3
|
+
Callable,
|
|
4
|
+
Optional,
|
|
5
|
+
)
|
|
6
|
+
from ex4nicegui.reactive.utils import ParameterClassifier
|
|
7
|
+
from ex4nicegui.utils.apiEffect import ui_effect
|
|
8
|
+
|
|
9
|
+
from ex4nicegui.utils.signals import (
|
|
10
|
+
ReadonlyRef,
|
|
11
|
+
_TMaybeRef as TMaybeRef,
|
|
12
|
+
to_value,
|
|
13
|
+
)
|
|
14
|
+
from nicegui import ui
|
|
15
|
+
from .base import BindableUi, DisableableMixin
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class KnobBindableUi(
|
|
19
|
+
BindableUi[ui.knob],
|
|
20
|
+
DisableableMixin,
|
|
21
|
+
):
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
value: TMaybeRef[float] = 0.0,
|
|
25
|
+
*,
|
|
26
|
+
min: TMaybeRef[float] = 0.0, # pylint: disable=redefined-builtin
|
|
27
|
+
max: TMaybeRef[float] = 1.0, # pylint: disable=redefined-builtin
|
|
28
|
+
step: TMaybeRef[float] = 0.01,
|
|
29
|
+
color: Optional[TMaybeRef[str]] = "primary",
|
|
30
|
+
center_color: Optional[TMaybeRef[str]] = None,
|
|
31
|
+
track_color: Optional[TMaybeRef[str]] = None,
|
|
32
|
+
size: Optional[TMaybeRef[str]] = None,
|
|
33
|
+
show_value: TMaybeRef[bool] = False,
|
|
34
|
+
on_change: Optional[Callable[..., Any]] = None,
|
|
35
|
+
) -> None:
|
|
36
|
+
pc = ParameterClassifier(
|
|
37
|
+
locals(),
|
|
38
|
+
maybeRefs=[
|
|
39
|
+
"value",
|
|
40
|
+
"min",
|
|
41
|
+
"max",
|
|
42
|
+
"step",
|
|
43
|
+
"color",
|
|
44
|
+
"center_color",
|
|
45
|
+
"track_color",
|
|
46
|
+
"size",
|
|
47
|
+
"show_value",
|
|
48
|
+
],
|
|
49
|
+
v_model=("value", "on_change"),
|
|
50
|
+
events=["on_change"],
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
value_kws = pc.get_values_kws()
|
|
54
|
+
element = ui.knob(**value_kws)
|
|
55
|
+
super().__init__(element) # type: ignore
|
|
56
|
+
|
|
57
|
+
for key, value in pc.get_bindings().items():
|
|
58
|
+
self.bind_prop(key, value) # type: ignore
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def value(self):
|
|
62
|
+
return self.element.value
|
|
63
|
+
|
|
64
|
+
def bind_prop(self, prop: str, ref_ui: ReadonlyRef):
|
|
65
|
+
if prop == "value":
|
|
66
|
+
return self.bind_value(ref_ui)
|
|
67
|
+
|
|
68
|
+
return super().bind_prop(prop, ref_ui)
|
|
69
|
+
|
|
70
|
+
def bind_value(self, ref_ui: ReadonlyRef[float]):
|
|
71
|
+
@ui_effect
|
|
72
|
+
def _():
|
|
73
|
+
self.element.set_value(to_value(ref_ui))
|
|
74
|
+
|
|
75
|
+
return self
|
|
@@ -4,7 +4,6 @@ from typing import (
|
|
|
4
4
|
Optional,
|
|
5
5
|
TypeVar,
|
|
6
6
|
Dict,
|
|
7
|
-
Union,
|
|
8
7
|
)
|
|
9
8
|
from ex4nicegui.reactive.utils import ParameterClassifier
|
|
10
9
|
from ex4nicegui.utils.apiEffect import ui_effect
|
|
@@ -26,7 +25,7 @@ class NumberBindableUi(BindableUi[ui.number]):
|
|
|
26
25
|
label: Optional[TMaybeRef[str]] = None,
|
|
27
26
|
*,
|
|
28
27
|
placeholder: Optional[TMaybeRef[str]] = None,
|
|
29
|
-
value: TMaybeRef[
|
|
28
|
+
value: Optional[TMaybeRef[float]] = None,
|
|
30
29
|
min: Optional[TMaybeRef[float]] = None,
|
|
31
30
|
max: Optional[TMaybeRef[float]] = None,
|
|
32
31
|
step: Optional[TMaybeRef[float]] = None,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Any,
|
|
3
|
+
)
|
|
4
|
+
from ex4nicegui.reactive.utils import ParameterClassifier
|
|
5
|
+
from ex4nicegui.utils.signals import (
|
|
6
|
+
_TMaybeRef as TMaybeRef,
|
|
7
|
+
)
|
|
8
|
+
from nicegui import ui
|
|
9
|
+
from .base import BindableUi
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class RowBindableUi(BindableUi[ui.row]):
|
|
13
|
+
def __init__(self, *, wrap: TMaybeRef[bool] = True) -> None:
|
|
14
|
+
pc = ParameterClassifier(locals(), maybeRefs=["wrap"], events=[])
|
|
15
|
+
element = ui.row(**pc.get_values_kws())
|
|
16
|
+
|
|
17
|
+
super().__init__(element)
|
|
18
|
+
for key, value in pc.get_bindings().items():
|
|
19
|
+
self.bind_prop(key, value) # type: ignore
|
|
20
|
+
|
|
21
|
+
def bind_prop(self, prop: str, ref_ui: TMaybeRef):
|
|
22
|
+
if prop == "wrap":
|
|
23
|
+
return self.bind_wrap(ref_ui)
|
|
24
|
+
|
|
25
|
+
return super().bind_prop(prop, ref_ui)
|
|
26
|
+
|
|
27
|
+
def bind_wrap(self, ref_ui: TMaybeRef):
|
|
28
|
+
self.bind_classes({"wrap": ref_ui})
|
|
29
|
+
|
|
30
|
+
def __enter__(self):
|
|
31
|
+
self.element.__enter__()
|
|
32
|
+
return self
|
|
33
|
+
|
|
34
|
+
def __exit__(self, *_: Any):
|
|
35
|
+
self.element.__exit__(*_)
|