instaui 0.1.15__py2.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.
- instaui/__init__.py +9 -0
- instaui/_helper/observable_helper.py +45 -0
- instaui/arco/__init__.py +191 -0
- instaui/arco/_settings.py +25 -0
- instaui/arco/_use_tools/locale.py +50 -0
- instaui/arco/component_types.py +1019 -0
- instaui/arco/components/_utils.py +22 -0
- instaui/arco/components/affix.py +29 -0
- instaui/arco/components/alert.py +42 -0
- instaui/arco/components/anchor.py +42 -0
- instaui/arco/components/auto_complete.py +96 -0
- instaui/arco/components/avatar.py +55 -0
- instaui/arco/components/back_top.py +14 -0
- instaui/arco/components/badge.py +14 -0
- instaui/arco/components/breadcrumb.py +14 -0
- instaui/arco/components/button.py +43 -0
- instaui/arco/components/calendar.py +47 -0
- instaui/arco/components/card.py +14 -0
- instaui/arco/components/carousel.py +33 -0
- instaui/arco/components/cascader.py +111 -0
- instaui/arco/components/checkbox.py +32 -0
- instaui/arco/components/collapse.py +31 -0
- instaui/arco/components/color_picker.py +45 -0
- instaui/arco/components/comment.py +14 -0
- instaui/arco/components/config_provider.py +13 -0
- instaui/arco/components/date_picker.py +111 -0
- instaui/arco/components/descriptions.py +14 -0
- instaui/arco/components/divider.py +13 -0
- instaui/arco/components/drawer.py +98 -0
- instaui/arco/components/dropdown.py +45 -0
- instaui/arco/components/empty.py +14 -0
- instaui/arco/components/form.py +55 -0
- instaui/arco/components/icon.py +17 -0
- instaui/arco/components/image.py +33 -0
- instaui/arco/components/input.py +102 -0
- instaui/arco/components/input_number.py +97 -0
- instaui/arco/components/input_password.py +38 -0
- instaui/arco/components/input_search.py +37 -0
- instaui/arco/components/input_tag.py +110 -0
- instaui/arco/components/layout.py +13 -0
- instaui/arco/components/layout_content.py +6 -0
- instaui/arco/components/layout_footer.py +6 -0
- instaui/arco/components/layout_header.py +6 -0
- instaui/arco/components/layout_sider.py +53 -0
- instaui/arco/components/link.py +36 -0
- instaui/arco/components/list.py +68 -0
- instaui/arco/components/mention.py +97 -0
- instaui/arco/components/menu.py +88 -0
- instaui/arco/components/modal.py +97 -0
- instaui/arco/components/overflow_list.py +29 -0
- instaui/arco/components/page_header.py +29 -0
- instaui/arco/components/pagination.py +45 -0
- instaui/arco/components/pop_confirm.py +58 -0
- instaui/arco/components/popover.py +32 -0
- instaui/arco/components/progress.py +14 -0
- instaui/arco/components/radio.py +40 -0
- instaui/arco/components/radio_group.py +42 -0
- instaui/arco/components/rate.py +45 -0
- instaui/arco/components/resize_box.py +62 -0
- instaui/arco/components/result.py +14 -0
- instaui/arco/components/select.py +182 -0
- instaui/arco/components/skeleton.py +14 -0
- instaui/arco/components/slider.py +38 -0
- instaui/arco/components/space.py +14 -0
- instaui/arco/components/spin.py +14 -0
- instaui/arco/components/split.py +76 -0
- instaui/arco/components/statistic.py +14 -0
- instaui/arco/components/steps.py +32 -0
- instaui/arco/components/switch.py +57 -0
- instaui/arco/components/tab_pane.py +12 -0
- instaui/arco/components/table.py +276 -0
- instaui/arco/components/tabs.py +101 -0
- instaui/arco/components/tag.py +42 -0
- instaui/arco/components/textarea.py +84 -0
- instaui/arco/components/time_picker.py +76 -0
- instaui/arco/components/timeline.py +14 -0
- instaui/arco/components/tooltip.py +29 -0
- instaui/arco/components/transfer.py +58 -0
- instaui/arco/components/tree.py +120 -0
- instaui/arco/components/tree_select.py +86 -0
- instaui/arco/components/trigger.py +58 -0
- instaui/arco/components/typography.py +142 -0
- instaui/arco/components/upload.py +71 -0
- instaui/arco/components/verification_code.py +58 -0
- instaui/arco/components/watermark.py +14 -0
- instaui/arco/locales/__init__.py +4 -0
- instaui/arco/locales/_index.py +31 -0
- instaui/arco/locales/en_us.py +227 -0
- instaui/arco/locales/zh_cn.py +224 -0
- instaui/arco/setup.py +36 -0
- instaui/arco/static/instaui-arco.css +1 -0
- instaui/arco/static/instaui-arco.js +55771 -0
- instaui/arco/types.py +24 -0
- instaui/boot_info.py +43 -0
- instaui/common/jsonable.py +37 -0
- instaui/components/__init__.py +0 -0
- instaui/components/column.py +26 -0
- instaui/components/component.py +47 -0
- instaui/components/content.py +34 -0
- instaui/components/directive.py +55 -0
- instaui/components/element.py +573 -0
- instaui/components/grid.py +213 -0
- instaui/components/html/__init__.py +49 -0
- instaui/components/html/_mixins.py +34 -0
- instaui/components/html/_preset.py +4 -0
- instaui/components/html/button.py +38 -0
- instaui/components/html/checkbox.py +35 -0
- instaui/components/html/date.py +28 -0
- instaui/components/html/div.py +7 -0
- instaui/components/html/form.py +7 -0
- instaui/components/html/heading.py +51 -0
- instaui/components/html/input.py +28 -0
- instaui/components/html/label.py +21 -0
- instaui/components/html/li.py +17 -0
- instaui/components/html/link.py +31 -0
- instaui/components/html/number.py +34 -0
- instaui/components/html/paragraph.py +29 -0
- instaui/components/html/range.py +48 -0
- instaui/components/html/select.py +69 -0
- instaui/components/html/span.py +19 -0
- instaui/components/html/table.py +36 -0
- instaui/components/html/textarea.py +28 -0
- instaui/components/html/ul.py +20 -0
- instaui/components/label.py +5 -0
- instaui/components/markdown/markdown.js +33 -0
- instaui/components/markdown/markdown.py +41 -0
- instaui/components/markdown/static/github-markdown.css +12 -0
- instaui/components/markdown/static/marked.esm.js +2579 -0
- instaui/components/match.py +108 -0
- instaui/components/row.py +17 -0
- instaui/components/shiki_code/shiki_code.js +126 -0
- instaui/components/shiki_code/shiki_code.py +99 -0
- instaui/components/shiki_code/static/langs/css.mjs +5 -0
- instaui/components/shiki_code/static/langs/markdown.mjs +5 -0
- instaui/components/shiki_code/static/langs/python.mjs +5 -0
- instaui/components/shiki_code/static/langs/shell.mjs +2 -0
- instaui/components/shiki_code/static/langs/shellscript.mjs +5 -0
- instaui/components/shiki_code/static/shiki-core.js +5784 -0
- instaui/components/shiki_code/static/shiki-style.css +179 -0
- instaui/components/shiki_code/static/shiki-transformers.js +461 -0
- instaui/components/shiki_code/static/themes/vitesse-dark.mjs +2 -0
- instaui/components/shiki_code/static/themes/vitesse-light.mjs +2 -0
- instaui/components/slot.py +81 -0
- instaui/components/transition_group.py +9 -0
- instaui/components/value_element.py +52 -0
- instaui/components/vfor.py +142 -0
- instaui/components/vif.py +42 -0
- instaui/consts.py +23 -0
- instaui/dependencies/component_dependency.py +22 -0
- instaui/dependencies/plugin_dependency.py +28 -0
- instaui/event/event_mixin.py +12 -0
- instaui/event/js_event.py +82 -0
- instaui/event/vue_event.py +66 -0
- instaui/event/web_event.py +123 -0
- instaui/experimental/__init__.py +3 -0
- instaui/experimental/debug.py +48 -0
- instaui/extra_libs/_echarts.py +3 -0
- instaui/extra_libs/_import_error.py +9 -0
- instaui/extra_libs/_mermaid.py +3 -0
- instaui/extra_libs/_shiki_code.py +3 -0
- instaui/fastapi_server/_utils.py +42 -0
- instaui/fastapi_server/_uvicorn.py +37 -0
- instaui/fastapi_server/debug_mode_router.py +60 -0
- instaui/fastapi_server/dependency_router.py +28 -0
- instaui/fastapi_server/event_router.py +58 -0
- instaui/fastapi_server/middlewares.py +19 -0
- instaui/fastapi_server/request_context.py +19 -0
- instaui/fastapi_server/resource.py +30 -0
- instaui/fastapi_server/server.py +308 -0
- instaui/fastapi_server/watch_router.py +53 -0
- instaui/handlers/_utils.py +88 -0
- instaui/handlers/event_handler.py +60 -0
- instaui/handlers/watch_handler.py +61 -0
- instaui/html_tools.py +94 -0
- instaui/inject.py +33 -0
- instaui/js/__init__.py +4 -0
- instaui/js/js_output.py +15 -0
- instaui/js/lambda_func.py +35 -0
- instaui/launch_collector.py +52 -0
- instaui/page_info.py +13 -0
- instaui/runtime/__init__.py +29 -0
- instaui/runtime/_app.py +234 -0
- instaui/runtime/_inner_helper.py +9 -0
- instaui/runtime/_link_manager.py +89 -0
- instaui/runtime/context.py +47 -0
- instaui/runtime/dataclass.py +30 -0
- instaui/runtime/resource.py +65 -0
- instaui/runtime/scope.py +133 -0
- instaui/runtime/ui_state_scope.py +15 -0
- instaui/settings/__init__.py +4 -0
- instaui/settings/__settings.py +13 -0
- instaui/shadcn_classless/_index.py +42 -0
- instaui/shadcn_classless/static/shadcn-classless.css +403 -0
- instaui/skip.py +12 -0
- instaui/spa_router/__init__.py +26 -0
- instaui/spa_router/_components.py +35 -0
- instaui/spa_router/_file_base_utils.py +273 -0
- instaui/spa_router/_functions.py +122 -0
- instaui/spa_router/_install.py +11 -0
- instaui/spa_router/_route_model.py +117 -0
- instaui/spa_router/_router_box.py +40 -0
- instaui/spa_router/_router_output.py +22 -0
- instaui/spa_router/_router_param_var.py +51 -0
- instaui/spa_router/_types.py +4 -0
- instaui/spa_router/templates/page_routes +60 -0
- instaui/static/insta-ui.css +1 -0
- instaui/static/insta-ui.esm-browser.prod.js +3717 -0
- instaui/static/insta-ui.ico +0 -0
- instaui/static/insta-ui.js.map +1 -0
- instaui/static/instaui-tools-browser.js +511 -0
- instaui/static/templates/debug/sse.html +117 -0
- instaui/static/templates/web.html +74 -0
- instaui/static/templates/webview.html +78 -0
- instaui/static/templates/zero.html +71 -0
- instaui/static/vue.esm-browser.prod.js +9 -0
- instaui/static/vue.global.prod.js +9 -0
- instaui/static/vue.runtime.esm-browser.prod.js +5 -0
- instaui/systems/file_system.py +6 -0
- instaui/systems/func_system.py +119 -0
- instaui/systems/js_system.py +22 -0
- instaui/systems/module_system.py +46 -0
- instaui/systems/pydantic_system.py +27 -0
- instaui/systems/string_system.py +10 -0
- instaui/tailwind/__init__.py +6 -0
- instaui/tailwind/_index.py +24 -0
- instaui/tailwind/static/tailwindcss-v3.min.js +62 -0
- instaui/tailwind/static/tailwindcss-v4.min.js +8 -0
- instaui/template/__init__.py +4 -0
- instaui/template/_utils.py +23 -0
- instaui/template/env.py +7 -0
- instaui/template/web_template.py +49 -0
- instaui/template/webview_template.py +48 -0
- instaui/template/zero_template.py +105 -0
- instaui/ui/__init__.py +144 -0
- instaui/ui/__init__.pyi +149 -0
- instaui/ui/events.py +25 -0
- instaui/ui_functions/input_slient_data.py +16 -0
- instaui/ui_functions/server.py +15 -0
- instaui/ui_functions/str_format.py +36 -0
- instaui/ui_functions/ui_page.py +16 -0
- instaui/ui_functions/ui_types.py +13 -0
- instaui/ui_functions/url_location.py +33 -0
- instaui/vars/_types.py +8 -0
- instaui/vars/data.py +68 -0
- instaui/vars/element_ref.py +40 -0
- instaui/vars/event_context.py +49 -0
- instaui/vars/event_extend.py +0 -0
- instaui/vars/js_computed.py +117 -0
- instaui/vars/mixin_types/common_type.py +5 -0
- instaui/vars/mixin_types/element_binding.py +16 -0
- instaui/vars/mixin_types/observable.py +7 -0
- instaui/vars/mixin_types/pathable.py +14 -0
- instaui/vars/mixin_types/py_binding.py +13 -0
- instaui/vars/mixin_types/str_format_binding.py +8 -0
- instaui/vars/mixin_types/var_type.py +5 -0
- instaui/vars/path_var.py +90 -0
- instaui/vars/ref.py +103 -0
- instaui/vars/slot_prop.py +46 -0
- instaui/vars/state.py +97 -0
- instaui/vars/types.py +24 -0
- instaui/vars/vfor_item.py +204 -0
- instaui/vars/vue_computed.py +81 -0
- instaui/vars/web_computed.py +209 -0
- instaui/vars/web_view_computed.py +1 -0
- instaui/version.py +3 -0
- instaui/watch/_types.py +4 -0
- instaui/watch/_utils.py +3 -0
- instaui/watch/js_watch.py +110 -0
- instaui/watch/vue_watch.py +77 -0
- instaui/watch/web_watch.py +181 -0
- instaui/webview/__init__.py +2 -0
- instaui/webview/_utils.py +8 -0
- instaui/webview/api.py +72 -0
- instaui/webview/func.py +114 -0
- instaui/webview/index.py +161 -0
- instaui/webview/resource.py +172 -0
- instaui/zero/__init__.py +3 -0
- instaui/zero/func.py +123 -0
- instaui/zero/scope.py +109 -0
- instaui-0.1.15.dist-info/METADATA +152 -0
- instaui-0.1.15.dist-info/RECORD +283 -0
- instaui-0.1.15.dist-info/WHEEL +5 -0
- instaui-0.1.15.dist-info/licenses/LICENSE +21 -0
instaui/vars/state.py
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
from typing import Dict, Tuple, TypeVar
|
2
|
+
|
3
|
+
from instaui import ui
|
4
|
+
from instaui.vars.mixin_types.py_binding import CanInputMixin, CanOutputMixin
|
5
|
+
from instaui.vars.mixin_types.observable import ObservableMixin
|
6
|
+
from instaui.vars.mixin_types.element_binding import ElementBindingMixin
|
7
|
+
from instaui.vars.mixin_types.pathable import CanPathPropMixin
|
8
|
+
from instaui.vars.mixin_types.str_format_binding import StrFormatBindingMixin
|
9
|
+
from instaui.common.jsonable import Jsonable
|
10
|
+
|
11
|
+
from pydantic import BaseModel, RootModel
|
12
|
+
|
13
|
+
_T = TypeVar("_T")
|
14
|
+
|
15
|
+
|
16
|
+
_ProxyModel = RootModel
|
17
|
+
|
18
|
+
|
19
|
+
class RefProxy(
|
20
|
+
CanInputMixin,
|
21
|
+
ObservableMixin,
|
22
|
+
CanOutputMixin,
|
23
|
+
CanPathPropMixin,
|
24
|
+
StrFormatBindingMixin,
|
25
|
+
ElementBindingMixin,
|
26
|
+
Jsonable,
|
27
|
+
):
|
28
|
+
def __init__(self, instance: BaseModel) -> None:
|
29
|
+
data = instance.model_dump()
|
30
|
+
self._ref_ = ui.ref(data)
|
31
|
+
self._prop_names_ = set(data.keys()) if isinstance(data, dict) else set()
|
32
|
+
|
33
|
+
def __getattribute__(self, name):
|
34
|
+
if name not in super().__getattribute__("_prop_names_"):
|
35
|
+
return super().__getattribute__(name)
|
36
|
+
|
37
|
+
return super().__getattribute__("_ref_")[name]
|
38
|
+
|
39
|
+
def __getitem__(self, name):
|
40
|
+
return super().__getattribute__("_ref_")[name]
|
41
|
+
|
42
|
+
def inverse(self):
|
43
|
+
return super().__getattribute__("_ref_").inverse()
|
44
|
+
|
45
|
+
def __add__(self, other: str):
|
46
|
+
return super().__getattribute__("_ref_") + other
|
47
|
+
|
48
|
+
def __radd__(self, other: str):
|
49
|
+
return other + super().__getattribute__("_ref_")
|
50
|
+
|
51
|
+
def _to_element_binding_config(self) -> Dict:
|
52
|
+
return super().__getattribute__("_ref_")._to_element_binding_config()
|
53
|
+
|
54
|
+
def _to_input_config(self):
|
55
|
+
return super().__getattribute__("_ref_")._to_input_config()
|
56
|
+
|
57
|
+
def _to_observable_config(self):
|
58
|
+
return super().__getattribute__("_ref_")._to_observable_config()
|
59
|
+
|
60
|
+
def _to_path_prop_binding_config(self) -> Dict:
|
61
|
+
return super().__getattribute__("_ref_")._to_path_prop_binding_config()
|
62
|
+
|
63
|
+
def _to_output_config(self):
|
64
|
+
return super().__getattribute__("_ref_")._to_output_config()
|
65
|
+
|
66
|
+
def _to_str_format_binding(self, order: int) -> Tuple[str, str]:
|
67
|
+
return super().__getattribute__("_ref_")._to_str_format_binding(order)
|
68
|
+
|
69
|
+
def _to_json_dict(self):
|
70
|
+
return super().__getattribute__("_ref_")._to_json_dict()
|
71
|
+
|
72
|
+
|
73
|
+
class StateModel(BaseModel, Jsonable):
|
74
|
+
pass
|
75
|
+
|
76
|
+
def _to_json_dict(self):
|
77
|
+
return self.model_dump()
|
78
|
+
|
79
|
+
|
80
|
+
def state(value: _T) -> _T:
|
81
|
+
"""
|
82
|
+
Creates a reactive state object that tracks changes and notifies dependencies.
|
83
|
+
|
84
|
+
Args:
|
85
|
+
value (_T): The initial value to wrap in a reactive state container.
|
86
|
+
Can be any type (primitive, object, or complex data structure).
|
87
|
+
|
88
|
+
# Example:
|
89
|
+
.. code-block:: python
|
90
|
+
from instaui import ui,html
|
91
|
+
count = ui.state(0)
|
92
|
+
|
93
|
+
html.number(count)
|
94
|
+
ui.label(count)
|
95
|
+
"""
|
96
|
+
obj = RefProxy(_ProxyModel(value)) # type: ignore
|
97
|
+
return obj # type: ignore
|
instaui/vars/types.py
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
from typing import Any, Union
|
2
|
+
from .ref import Ref
|
3
|
+
from .js_computed import JsComputed
|
4
|
+
from .vue_computed import VueComputed
|
5
|
+
from .web_computed import WebComputed
|
6
|
+
|
7
|
+
|
8
|
+
from ._types import _T_Value
|
9
|
+
from .mixin_types.element_binding import ElementBindingMixin
|
10
|
+
|
11
|
+
|
12
|
+
TRefOrComputed = Union[
|
13
|
+
Ref[_T_Value],
|
14
|
+
VueComputed,
|
15
|
+
JsComputed,
|
16
|
+
WebComputed[Any, _T_Value],
|
17
|
+
]
|
18
|
+
TMaybeRef = Union[
|
19
|
+
ElementBindingMixin[_T_Value],
|
20
|
+
WebComputed,
|
21
|
+
VueComputed,
|
22
|
+
JsComputed,
|
23
|
+
_T_Value,
|
24
|
+
]
|
@@ -0,0 +1,204 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import Dict, Generic, Tuple, TypeVar, TYPE_CHECKING, Union, cast
|
3
|
+
from contextlib import contextmanager
|
4
|
+
|
5
|
+
from instaui.common.jsonable import Jsonable
|
6
|
+
from instaui.vars.mixin_types.element_binding import ElementBindingMixin
|
7
|
+
from instaui.vars.mixin_types.py_binding import CanInputMixin, CanOutputMixin
|
8
|
+
from instaui.vars.mixin_types.pathable import CanPathPropMixin
|
9
|
+
from instaui.vars.mixin_types.str_format_binding import StrFormatBindingMixin
|
10
|
+
from instaui.vars.mixin_types.observable import ObservableMixin
|
11
|
+
from instaui.vars.path_var import PathVar
|
12
|
+
|
13
|
+
if TYPE_CHECKING:
|
14
|
+
from instaui.components.vfor import VFor
|
15
|
+
|
16
|
+
_T = TypeVar("_T")
|
17
|
+
|
18
|
+
|
19
|
+
class VForItemProxy(
|
20
|
+
PathVar,
|
21
|
+
CanInputMixin,
|
22
|
+
ObservableMixin,
|
23
|
+
CanOutputMixin,
|
24
|
+
CanPathPropMixin,
|
25
|
+
StrFormatBindingMixin,
|
26
|
+
ElementBindingMixin,
|
27
|
+
Jsonable,
|
28
|
+
Generic[_T],
|
29
|
+
):
|
30
|
+
def __init__(self, vfor_item: VForItem[_T]):
|
31
|
+
self._vfor_item = vfor_item
|
32
|
+
|
33
|
+
def __getattr__(self, name: str):
|
34
|
+
return self._vfor_item[name]
|
35
|
+
|
36
|
+
def __getitem__(self, name):
|
37
|
+
return super().__getattribute__("_vfor_item")[name]
|
38
|
+
|
39
|
+
def _to_element_binding_config(self) -> Dict:
|
40
|
+
return super().__getattribute__("_vfor_item")._to_element_binding_config()
|
41
|
+
|
42
|
+
def _to_input_config(self):
|
43
|
+
return super().__getattribute__("_vfor_item")._to_input_config()
|
44
|
+
|
45
|
+
def _to_path_prop_binding_config(self) -> Dict:
|
46
|
+
return super().__getattribute__("_vfor_item")._to_path_prop_binding_config()
|
47
|
+
|
48
|
+
def _to_output_config(self):
|
49
|
+
return super().__getattribute__("_vfor_item")._to_output_config()
|
50
|
+
|
51
|
+
def _to_str_format_binding(self, order: int) -> Tuple[str, str]:
|
52
|
+
return super().__getattribute__("_vfor_item")._to_str_format_binding(order)
|
53
|
+
|
54
|
+
def _to_pathable_binding_config(self) -> Dict:
|
55
|
+
return super().__getattribute__("_vfor_item")._to_pathable_binding_config()
|
56
|
+
|
57
|
+
def _to_observable_config(self):
|
58
|
+
return super().__getattribute__("_vfor_item")._to_observable_config()
|
59
|
+
|
60
|
+
def _to_json_dict(self):
|
61
|
+
return super().__getattribute__("_vfor_item")._to_json_dict()
|
62
|
+
|
63
|
+
|
64
|
+
class VForItem(
|
65
|
+
PathVar,
|
66
|
+
CanInputMixin,
|
67
|
+
ObservableMixin,
|
68
|
+
CanOutputMixin,
|
69
|
+
CanPathPropMixin,
|
70
|
+
ElementBindingMixin[_T],
|
71
|
+
StrFormatBindingMixin,
|
72
|
+
Generic[_T],
|
73
|
+
):
|
74
|
+
VAR_Type = "vf"
|
75
|
+
|
76
|
+
def __init__(self, vfor: VFor):
|
77
|
+
super().__init__()
|
78
|
+
self._vfor = vfor
|
79
|
+
|
80
|
+
@property
|
81
|
+
def dict_key(self):
|
82
|
+
return self._vfor.current[1]
|
83
|
+
|
84
|
+
@property
|
85
|
+
def dict_value(self):
|
86
|
+
return self._vfor.current[0]
|
87
|
+
|
88
|
+
@property
|
89
|
+
def proxy(self):
|
90
|
+
return cast(_T, VForItemProxy(self))
|
91
|
+
|
92
|
+
def _to_binding_config(self) -> Union[Jsonable, Dict]:
|
93
|
+
return self._to_json_dict()
|
94
|
+
|
95
|
+
def _to_element_binding_config(self):
|
96
|
+
return self._to_json_dict()
|
97
|
+
|
98
|
+
def _to_input_config(self):
|
99
|
+
return self._to_json_dict()
|
100
|
+
|
101
|
+
def _to_output_config(self):
|
102
|
+
return self._to_json_dict()
|
103
|
+
|
104
|
+
def _to_path_prop_binding_config(self) -> Dict:
|
105
|
+
return self._to_json_dict()
|
106
|
+
|
107
|
+
def _to_pathable_binding_config(self) -> Dict:
|
108
|
+
return self._to_json_dict()
|
109
|
+
|
110
|
+
def _to_observable_config(self):
|
111
|
+
return self._to_json_dict()
|
112
|
+
|
113
|
+
def _to_json_dict(self):
|
114
|
+
data: Dict = {
|
115
|
+
"type": self.VAR_Type,
|
116
|
+
"fid": self._vfor._fid,
|
117
|
+
}
|
118
|
+
|
119
|
+
return data
|
120
|
+
|
121
|
+
|
122
|
+
class VForIndex(
|
123
|
+
CanInputMixin,
|
124
|
+
CanPathPropMixin,
|
125
|
+
ElementBindingMixin,
|
126
|
+
StrFormatBindingMixin,
|
127
|
+
):
|
128
|
+
def __init__(self, vfor: VFor):
|
129
|
+
super().__init__()
|
130
|
+
self._vfor = vfor
|
131
|
+
|
132
|
+
def _to_element_binding_config(self):
|
133
|
+
return self._to_json_dict()
|
134
|
+
|
135
|
+
def _to_input_config(self):
|
136
|
+
return self._to_json_dict()
|
137
|
+
|
138
|
+
def _to_path_prop_binding_config(self) -> Dict:
|
139
|
+
return self._to_json_dict()
|
140
|
+
|
141
|
+
def _to_json_dict(self):
|
142
|
+
return {
|
143
|
+
"type": "vf-i",
|
144
|
+
"fid": self._vfor._fid,
|
145
|
+
}
|
146
|
+
|
147
|
+
|
148
|
+
class VForDict(
|
149
|
+
CanInputMixin,
|
150
|
+
CanOutputMixin,
|
151
|
+
StrFormatBindingMixin,
|
152
|
+
ElementBindingMixin,
|
153
|
+
Jsonable,
|
154
|
+
):
|
155
|
+
def __init__(self, vfor: VFor):
|
156
|
+
self._vfor = vfor
|
157
|
+
|
158
|
+
@property
|
159
|
+
def dict_key(self):
|
160
|
+
return self._vfor.current[1]
|
161
|
+
|
162
|
+
@property
|
163
|
+
def dict_value(self):
|
164
|
+
return self._vfor.current[0]
|
165
|
+
|
166
|
+
@contextmanager
|
167
|
+
def with_index(self):
|
168
|
+
self.__enter__()
|
169
|
+
yield self, cast(int, VForIndex(self._vfor))
|
170
|
+
|
171
|
+
def __enter__(self):
|
172
|
+
self._vfor.__enter__()
|
173
|
+
return self
|
174
|
+
|
175
|
+
def __exit__(self, *_) -> None:
|
176
|
+
return self._vfor.__exit__(*_)
|
177
|
+
|
178
|
+
def _to_element_binding_config(self) -> Dict:
|
179
|
+
return self.dict_value._to_element_binding_config()
|
180
|
+
|
181
|
+
def _to_input_config(self):
|
182
|
+
return self.dict_value._to_input_config()
|
183
|
+
|
184
|
+
def _to_output_config(self):
|
185
|
+
return self.dict_value._to_output_config()
|
186
|
+
|
187
|
+
def _to_json_dict(self):
|
188
|
+
return self.dict_value._to_json_dict()
|
189
|
+
|
190
|
+
|
191
|
+
class VForWithIndex(Generic[_T]):
|
192
|
+
def __init__(self, vfor: VFor[_T]):
|
193
|
+
self._vfor = vfor
|
194
|
+
|
195
|
+
def __enter__(self):
|
196
|
+
self._vfor.__enter__()
|
197
|
+
return cast(_T, self._vfor.current.proxy), cast(int, VForIndex(self._vfor))
|
198
|
+
|
199
|
+
def __exit__(self, *_) -> None:
|
200
|
+
return self._vfor.__exit__(*_)
|
201
|
+
|
202
|
+
|
203
|
+
TVForItem = VForItem
|
204
|
+
TVForIndex = VForIndex
|
@@ -0,0 +1,81 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import Any, Dict, Mapping, Optional, Union
|
3
|
+
|
4
|
+
from instaui.common.jsonable import Jsonable
|
5
|
+
|
6
|
+
from instaui.runtime._app import get_current_scope
|
7
|
+
from instaui.vars.path_var import PathVar
|
8
|
+
from instaui.vars.mixin_types.var_type import VarMixin
|
9
|
+
from instaui.vars.mixin_types.element_binding import ElementBindingMixin
|
10
|
+
from instaui.vars.mixin_types.py_binding import CanInputMixin
|
11
|
+
from instaui.vars.mixin_types.pathable import CanPathPropMixin
|
12
|
+
from instaui.vars.mixin_types.str_format_binding import StrFormatBindingMixin
|
13
|
+
from instaui.vars.mixin_types.observable import ObservableMixin
|
14
|
+
|
15
|
+
|
16
|
+
class VueComputed(
|
17
|
+
Jsonable,
|
18
|
+
PathVar,
|
19
|
+
VarMixin,
|
20
|
+
CanInputMixin,
|
21
|
+
ObservableMixin,
|
22
|
+
CanPathPropMixin,
|
23
|
+
StrFormatBindingMixin,
|
24
|
+
ElementBindingMixin,
|
25
|
+
):
|
26
|
+
BIND_TYPE = "var"
|
27
|
+
|
28
|
+
def __init__(
|
29
|
+
self,
|
30
|
+
fn_code: str,
|
31
|
+
bindings: Optional[Mapping[str, Union[ElementBindingMixin, Any]]] = None,
|
32
|
+
) -> None:
|
33
|
+
self.code = fn_code
|
34
|
+
scope = get_current_scope()
|
35
|
+
scope.register_vue_computed(self)
|
36
|
+
|
37
|
+
self._sid = scope.id
|
38
|
+
self._id = scope.generate_vars_id()
|
39
|
+
|
40
|
+
if bindings:
|
41
|
+
const_bind = []
|
42
|
+
self.bind = {}
|
43
|
+
|
44
|
+
for k, v in bindings.items():
|
45
|
+
is_binding = isinstance(v, ElementBindingMixin)
|
46
|
+
self.bind[k] = v._to_element_binding_config() if is_binding else v
|
47
|
+
const_bind.append(int(not is_binding))
|
48
|
+
|
49
|
+
if any(i == 1 for i in const_bind):
|
50
|
+
self.const = const_bind
|
51
|
+
|
52
|
+
def __to_binding_config(self):
|
53
|
+
return {
|
54
|
+
"type": self.BIND_TYPE,
|
55
|
+
"id": self._id,
|
56
|
+
"sid": self._sid,
|
57
|
+
}
|
58
|
+
|
59
|
+
def _to_input_config(self):
|
60
|
+
return self.__to_binding_config()
|
61
|
+
|
62
|
+
def _to_path_prop_binding_config(self) -> Dict:
|
63
|
+
return self.__to_binding_config()
|
64
|
+
|
65
|
+
def _to_element_binding_config(self):
|
66
|
+
return self.__to_binding_config()
|
67
|
+
|
68
|
+
def _to_pathable_binding_config(self) -> Dict:
|
69
|
+
return self.__to_binding_config()
|
70
|
+
|
71
|
+
def _to_observable_config(self):
|
72
|
+
return self.__to_binding_config()
|
73
|
+
|
74
|
+
def _to_json_dict(self):
|
75
|
+
data = super()._to_json_dict()
|
76
|
+
data["sid"] = self._sid
|
77
|
+
data["id"] = self._id
|
78
|
+
return data
|
79
|
+
|
80
|
+
|
81
|
+
TVueComputed = VueComputed
|
@@ -0,0 +1,209 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
import inspect
|
3
|
+
from typing import (
|
4
|
+
Any,
|
5
|
+
Callable,
|
6
|
+
Dict,
|
7
|
+
Generic,
|
8
|
+
Optional,
|
9
|
+
Sequence,
|
10
|
+
TypeVar,
|
11
|
+
)
|
12
|
+
from typing_extensions import ParamSpec
|
13
|
+
|
14
|
+
from instaui.common.jsonable import Jsonable
|
15
|
+
from instaui.runtime._app import get_app_slot, get_current_scope
|
16
|
+
from instaui.handlers import watch_handler
|
17
|
+
|
18
|
+
from instaui.vars.path_var import PathVar
|
19
|
+
from instaui.vars.mixin_types.py_binding import CanInputMixin, CanOutputMixin
|
20
|
+
from instaui.vars.mixin_types.element_binding import ElementBindingMixin
|
21
|
+
from instaui.vars.mixin_types.pathable import CanPathPropMixin
|
22
|
+
from instaui.vars.mixin_types.str_format_binding import StrFormatBindingMixin
|
23
|
+
from instaui.vars.mixin_types.observable import ObservableMixin
|
24
|
+
from instaui.vars.mixin_types.common_type import TObservableInput
|
25
|
+
from instaui._helper import observable_helper
|
26
|
+
|
27
|
+
_SYNC_TYPE = "sync"
|
28
|
+
_ASYNC_TYPE = "async"
|
29
|
+
|
30
|
+
P = ParamSpec("P")
|
31
|
+
R = TypeVar("R")
|
32
|
+
|
33
|
+
|
34
|
+
class WebComputed(
|
35
|
+
Jsonable,
|
36
|
+
PathVar,
|
37
|
+
CanInputMixin,
|
38
|
+
ObservableMixin,
|
39
|
+
CanPathPropMixin,
|
40
|
+
StrFormatBindingMixin,
|
41
|
+
ElementBindingMixin[R],
|
42
|
+
Generic[P, R],
|
43
|
+
):
|
44
|
+
BIND_TYPE = "var"
|
45
|
+
|
46
|
+
def __init__(
|
47
|
+
self,
|
48
|
+
func: Callable[P, R],
|
49
|
+
inputs: Optional[Sequence[TObservableInput]] = None,
|
50
|
+
extend_outputs: Optional[Sequence[CanOutputMixin]] = None,
|
51
|
+
init_value: Optional[R] = None,
|
52
|
+
evaluating: Optional[CanOutputMixin] = None,
|
53
|
+
deep_compare_on_input: bool = False,
|
54
|
+
debug_info: Optional[Dict] = None,
|
55
|
+
) -> None:
|
56
|
+
scope = get_current_scope()
|
57
|
+
|
58
|
+
self._sid = scope.id
|
59
|
+
self._id = scope.generate_vars_id()
|
60
|
+
get_current_scope().register_web_computed(self)
|
61
|
+
|
62
|
+
self._org_inputs = inputs or []
|
63
|
+
|
64
|
+
self._inputs, self._is_slient_inputs, self._is_data = (
|
65
|
+
observable_helper.analyze_observable_inputs(list(inputs or []))
|
66
|
+
)
|
67
|
+
self._outputs = [output._to_output_config() for output in extend_outputs or []]
|
68
|
+
self._fn = func
|
69
|
+
self._init_value = init_value
|
70
|
+
self._evaluating = evaluating
|
71
|
+
self._deep_compare_on_input = deep_compare_on_input
|
72
|
+
self.__be_used = False
|
73
|
+
|
74
|
+
if debug_info is not None:
|
75
|
+
self.debug = debug_info
|
76
|
+
|
77
|
+
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R:
|
78
|
+
return self._fn(*args, **kwargs)
|
79
|
+
|
80
|
+
def _to_json_dict(self):
|
81
|
+
data = super()._to_json_dict()
|
82
|
+
|
83
|
+
app = get_app_slot()
|
84
|
+
|
85
|
+
hkey = watch_handler.create_handler_key(
|
86
|
+
page_path=app.page_path,
|
87
|
+
handler=self._fn,
|
88
|
+
)
|
89
|
+
|
90
|
+
watch_handler.register_handler(hkey, self._fn, len(self._outputs) + 1)
|
91
|
+
|
92
|
+
data["id"] = self._id
|
93
|
+
data["sid"] = self._sid
|
94
|
+
|
95
|
+
if self._inputs:
|
96
|
+
data["inputs"] = self._inputs
|
97
|
+
|
98
|
+
if self._outputs:
|
99
|
+
data["outputs"] = self._outputs
|
100
|
+
|
101
|
+
if sum(self._is_slient_inputs) > 0:
|
102
|
+
data["slient"] = self._is_slient_inputs
|
103
|
+
|
104
|
+
if sum(self._is_data) > 0:
|
105
|
+
data["data"] = self._is_data
|
106
|
+
|
107
|
+
data["fType"] = (
|
108
|
+
_ASYNC_TYPE if inspect.iscoroutinefunction(self._fn) else _SYNC_TYPE
|
109
|
+
)
|
110
|
+
data["key"] = hkey
|
111
|
+
if self._init_value is not None:
|
112
|
+
data["init"] = self._init_value
|
113
|
+
|
114
|
+
if self._evaluating:
|
115
|
+
data["running"] = self._evaluating._to_output_config()
|
116
|
+
|
117
|
+
if self._deep_compare_on_input is not False:
|
118
|
+
data["deepEqOnInput"] = 1
|
119
|
+
|
120
|
+
return data
|
121
|
+
|
122
|
+
def __to_binding_config(self):
|
123
|
+
return {
|
124
|
+
"type": self.BIND_TYPE,
|
125
|
+
"id": self._id,
|
126
|
+
"sid": self._sid,
|
127
|
+
}
|
128
|
+
|
129
|
+
def _to_pathable_binding_config(self) -> Dict:
|
130
|
+
return self.__to_binding_config()
|
131
|
+
|
132
|
+
def _to_path_prop_binding_config(self) -> Dict:
|
133
|
+
return self.__to_binding_config()
|
134
|
+
|
135
|
+
def _to_input_config(self):
|
136
|
+
return self.__to_binding_config()
|
137
|
+
|
138
|
+
def _to_element_binding_config(self):
|
139
|
+
return self.__to_binding_config()
|
140
|
+
|
141
|
+
def _to_observable_config(self):
|
142
|
+
return self.__to_binding_config()
|
143
|
+
|
144
|
+
def _mark_used(self):
|
145
|
+
if self.__be_used:
|
146
|
+
return
|
147
|
+
|
148
|
+
self.__be_used = True
|
149
|
+
for input_ in self._org_inputs:
|
150
|
+
if isinstance(input_, ElementBindingMixin):
|
151
|
+
input_._mark_used()
|
152
|
+
|
153
|
+
def _is_used(self):
|
154
|
+
return self.__be_used
|
155
|
+
|
156
|
+
|
157
|
+
def web_computed(
|
158
|
+
*,
|
159
|
+
inputs: Optional[Sequence] = None,
|
160
|
+
extend_outputs: Optional[Sequence] = None,
|
161
|
+
init_value: Optional[Any] = None,
|
162
|
+
evaluating: Optional[Any] = None,
|
163
|
+
deep_compare_on_input: bool = False,
|
164
|
+
debug_info: Optional[Dict] = None,
|
165
|
+
):
|
166
|
+
"""
|
167
|
+
Creates a computed property decorator for reactive programming with dependency tracking.
|
168
|
+
|
169
|
+
This decorator factory wraps functions to create reactive computed properties that:
|
170
|
+
- Automatically re-evaluate when dependencies (inputs) change
|
171
|
+
- Cache results for performance optimization
|
172
|
+
- Support both synchronous and asynchronous computation patterns
|
173
|
+
|
174
|
+
Args:
|
175
|
+
inputs (Optional[Sequence], optional): Collection of reactive sources that trigger recomputation
|
176
|
+
when changed. These can be state objects or other computed properties.
|
177
|
+
extend_outputs (Optional[Sequence], optional): Additional outputs to notify when this computed value updates.
|
178
|
+
init_value (Optional[Any], optional): Initial value to return before first successful evaluation.
|
179
|
+
evaluating (Optional[Any], optional): Temporary value returned during asynchronous computation.
|
180
|
+
|
181
|
+
# Example:
|
182
|
+
.. code-block:: python
|
183
|
+
from instaui import ui,html
|
184
|
+
|
185
|
+
a = ui.state(0)
|
186
|
+
|
187
|
+
@ui.computed(inputs=[a])
|
188
|
+
def plus_one(a):
|
189
|
+
return a + 1
|
190
|
+
|
191
|
+
html.number(a)
|
192
|
+
ui.label(plus_one)
|
193
|
+
"""
|
194
|
+
|
195
|
+
def wrapper(func: Callable[P, R]):
|
196
|
+
return WebComputed(
|
197
|
+
func,
|
198
|
+
inputs=inputs,
|
199
|
+
extend_outputs=extend_outputs,
|
200
|
+
init_value=init_value,
|
201
|
+
evaluating=evaluating,
|
202
|
+
deep_compare_on_input=deep_compare_on_input,
|
203
|
+
debug_info=debug_info,
|
204
|
+
)
|
205
|
+
|
206
|
+
return wrapper
|
207
|
+
|
208
|
+
|
209
|
+
TComputed = WebComputed
|
@@ -0,0 +1 @@
|
|
1
|
+
from __future__ import annotations
|
instaui/version.py
ADDED
instaui/watch/_types.py
ADDED
instaui/watch/_utils.py
ADDED