instaui 0.1.8__py3-none-any.whl → 0.1.10__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/_helper/observable_helper.py +11 -1
- instaui/arco/components/select.py +4 -1
- instaui/arco/static/instaui-arco.css +1 -1
- instaui/arco/static/instaui-arco.js +55771 -55771
- instaui/components/echarts/echarts.js +7 -5
- instaui/components/echarts/echarts.py +1 -1
- instaui/components/element.py +12 -22
- instaui/components/grid.py +63 -11
- instaui/components/html/paragraph.py +10 -0
- instaui/components/html/select.py +0 -5
- instaui/components/html/table.py +1 -1
- instaui/components/label.py +5 -0
- instaui/components/row.py +0 -3
- instaui/components/shiki_code/static/shiki-style.css +179 -179
- instaui/event/js_event.py +24 -0
- instaui/event/vue_event.py +66 -0
- instaui/event/web_event.py +36 -25
- instaui/experimental/__init__.py +1 -2
- instaui/handlers/_utils.py +27 -5
- instaui/shadcn_classless/static/shadcn-classless.css +403 -403
- instaui/spa_router/_file_base_utils.py +20 -16
- instaui/static/insta-ui.css +1 -1
- instaui/static/insta-ui.esm-browser.prod.js +3683 -3663
- instaui/static/insta-ui.js.map +1 -1
- instaui/systems/func_system.py +15 -0
- instaui/template/webview_template.py +0 -2
- instaui/ui/__init__.py +5 -1
- instaui/ui/__init__.pyi +5 -1
- instaui/ui_functions/ui_page.py +3 -3
- instaui/vars/js_computed.py +25 -1
- instaui/vars/state.py +15 -0
- instaui/vars/web_computed.py +42 -0
- instaui/watch/js_watch.py +37 -1
- instaui/watch/web_watch.py +53 -0
- instaui/webview/__init__.py +1 -0
- instaui/webview/index.py +0 -1
- instaui-0.1.10.dist-info/METADATA +153 -0
- {instaui-0.1.8.dist-info → instaui-0.1.10.dist-info}/RECORD +70 -73
- {instaui-0.1.8.dist-info → instaui-0.1.10.dist-info}/WHEEL +1 -1
- instaui/experimental/link_sql/__init__.py +0 -3
- instaui/experimental/link_sql/_base.py +0 -23
- instaui/experimental/link_sql/_duckdb.py +0 -221
- instaui/experimental/link_sql/_types.py +0 -15
- instaui/experimental/link_sql/data_source.js +0 -50
- instaui-0.1.8.dist-info/METADATA +0 -160
- {instaui-0.1.8.dist-info → instaui-0.1.10.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
import typing
|
2
|
+
from instaui.common.jsonable import Jsonable
|
3
|
+
from instaui.vars.mixin_types.observable import ObservableMixin
|
4
|
+
from .event_mixin import EventMixin
|
5
|
+
|
6
|
+
|
7
|
+
class VueEvent(Jsonable, EventMixin):
|
8
|
+
"""
|
9
|
+
Create an event object that can be bound to a UI component's event listener.
|
10
|
+
|
11
|
+
This function generates a callable event handler with optional contextual bindings.
|
12
|
+
The event logic is defined via a code string, which can reference bound variables.
|
13
|
+
|
14
|
+
Args:
|
15
|
+
code (str): A string containing the executable logic for the event handler.
|
16
|
+
Typically contains a function body or expression that utilizes bound variables.
|
17
|
+
bindings (typing.Optional[typing.Dict[str, typing.Any]], optional): A dictionary mapping variable names to values that should be available in the
|
18
|
+
event handler's context. If None, no additional bindings are created.. Defaults to None.
|
19
|
+
|
20
|
+
Example:
|
21
|
+
.. code-block:: python
|
22
|
+
a = ui.state(1)
|
23
|
+
|
24
|
+
event = ui.vue_event(bindings={"a": a}, code=r'''()=> { a.value +=1}''')
|
25
|
+
|
26
|
+
html.span(a)
|
27
|
+
html.button("plus").on("click", event)
|
28
|
+
"""
|
29
|
+
|
30
|
+
def __init__(
|
31
|
+
self,
|
32
|
+
*,
|
33
|
+
code: str,
|
34
|
+
bindings: typing.Optional[typing.Dict[str, typing.Any]] = None,
|
35
|
+
):
|
36
|
+
self.code = code
|
37
|
+
self._bindings = bindings
|
38
|
+
|
39
|
+
if bindings:
|
40
|
+
bindData = [
|
41
|
+
int(not isinstance(v, ObservableMixin)) for v in bindings.values()
|
42
|
+
]
|
43
|
+
|
44
|
+
if sum(bindData) > 0:
|
45
|
+
self.bindData = bindData
|
46
|
+
|
47
|
+
self.bind = {
|
48
|
+
k: typing.cast(ObservableMixin, v)._to_observable_config()
|
49
|
+
if isinstance(v, ObservableMixin)
|
50
|
+
else v
|
51
|
+
for k, v in bindings.items()
|
52
|
+
}
|
53
|
+
|
54
|
+
def copy_with_extends(self, extends: typing.Dict):
|
55
|
+
raise NotImplementedError("VueEvent does not support extends")
|
56
|
+
|
57
|
+
def event_type(self):
|
58
|
+
return "vue"
|
59
|
+
|
60
|
+
def _to_json_dict(self):
|
61
|
+
data = super()._to_json_dict()
|
62
|
+
data["type"] = self.event_type()
|
63
|
+
return data
|
64
|
+
|
65
|
+
|
66
|
+
vue_event = VueEvent
|
instaui/event/web_event.py
CHANGED
@@ -20,8 +20,8 @@ class WebEvent(Jsonable, EventMixin, typing.Generic[P, R]):
|
|
20
20
|
def __init__(
|
21
21
|
self,
|
22
22
|
fn: typing.Callable[P, R],
|
23
|
-
inputs: typing.
|
24
|
-
outputs: typing.
|
23
|
+
inputs: typing.Sequence[CanInputMixin],
|
24
|
+
outputs: typing.Sequence[CanOutputMixin],
|
25
25
|
):
|
26
26
|
self._inputs = inputs
|
27
27
|
self._outputs = outputs
|
@@ -36,7 +36,7 @@ class WebEvent(Jsonable, EventMixin, typing.Generic[P, R]):
|
|
36
36
|
def copy_with_extends(self, extends: typing.Sequence[CanInputMixin]):
|
37
37
|
return WebEvent(
|
38
38
|
fn=self._fn,
|
39
|
-
inputs=self._inputs + list(extends),
|
39
|
+
inputs=list(self._inputs) + list(extends),
|
40
40
|
outputs=self._outputs,
|
41
41
|
)
|
42
42
|
|
@@ -76,32 +76,43 @@ class WebEvent(Jsonable, EventMixin, typing.Generic[P, R]):
|
|
76
76
|
return data
|
77
77
|
|
78
78
|
|
79
|
-
|
80
|
-
|
79
|
+
def event(
|
80
|
+
*,
|
81
|
+
inputs: typing.Optional[typing.Sequence] = None,
|
82
|
+
outputs: typing.Optional[typing.Sequence] = None,
|
83
|
+
):
|
84
|
+
"""
|
85
|
+
Creates an event handler decorator for binding reactive logic to component events.
|
81
86
|
|
87
|
+
Args:
|
88
|
+
inputs (typing.Optional[typing.Sequence], optional): Reactive sources (state objects, computed properties)
|
89
|
+
that should be accessible during event handling.
|
90
|
+
These values will be passed to the decorated function
|
91
|
+
when the event fires.
|
92
|
+
outputs (typing.Optional[typing.Sequence], optional): Targets (state variables, UI elements) that should
|
93
|
+
update when this handler executes. Used for coordinating
|
94
|
+
interface updates after the event is processed.
|
82
95
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
typing.Union[_T_output, typing.Sequence[_T_output]]
|
89
|
-
] = None,
|
90
|
-
) -> typing.Callable[[typing.Callable[P, R]], WebEvent[P, R]]: ...
|
96
|
+
# Example:
|
97
|
+
.. code-block:: python
|
98
|
+
from instaui import ui, html
|
99
|
+
|
100
|
+
a = ui.state(0)
|
91
101
|
|
102
|
+
@ui.event(inputs=[a], outputs=[a])
|
103
|
+
def plus_one(a):
|
104
|
+
return a + 1
|
92
105
|
|
93
|
-
|
94
|
-
|
95
|
-
) -> typing.Union[
|
96
|
-
WebEvent[P, R], typing.Callable[[typing.Callable[P, R]], WebEvent[P, R]]
|
97
|
-
]:
|
98
|
-
inputs = [inputs] if isinstance(inputs, CanInputMixin) else inputs
|
99
|
-
outputs = [outputs] if isinstance(outputs, CanOutputMixin) else outputs
|
100
|
-
if fn is None:
|
106
|
+
html.button("click me").on_click(plus_one)
|
107
|
+
html.paragraph(a)
|
101
108
|
|
102
|
-
|
103
|
-
return WebEvent(fn, inputs=inputs or [], outputs=outputs or [])
|
109
|
+
"""
|
104
110
|
|
105
|
-
|
111
|
+
def wrapper(func: typing.Callable[P, R]):
|
112
|
+
return WebEvent(
|
113
|
+
func,
|
114
|
+
inputs or [],
|
115
|
+
outputs=outputs or [],
|
116
|
+
)
|
106
117
|
|
107
|
-
return
|
118
|
+
return wrapper
|
instaui/experimental/__init__.py
CHANGED
instaui/handlers/_utils.py
CHANGED
@@ -23,17 +23,20 @@ class HandlerInfo:
|
|
23
23
|
fn: Callable
|
24
24
|
fn_location_info: str
|
25
25
|
outputs_binding_count: int = 0
|
26
|
-
|
26
|
+
handler_param_converters: List[pydantic_system.TypeAdapterProtocol] = field(
|
27
27
|
default_factory=list
|
28
28
|
)
|
29
|
+
is_last_param_args: bool = False
|
29
30
|
|
30
31
|
def get_handler_args(self, input_values: List):
|
32
|
+
real_param_converters = _try_expand_params_converters(
|
33
|
+
self.handler_param_converters, input_values, self.is_last_param_args
|
34
|
+
)
|
35
|
+
|
31
36
|
try:
|
32
37
|
return [
|
33
38
|
param_converter.to_python_value(value)
|
34
|
-
for param_converter, value in zip(
|
35
|
-
self.hanlder_param_converters, input_values
|
36
|
-
)
|
39
|
+
for param_converter, value in zip(real_param_converters, input_values)
|
37
40
|
]
|
38
41
|
except pydantic_core._pydantic_core.ValidationError as e:
|
39
42
|
raise ValueError(f"invalid input[{self.fn_location_info}]: {e}") from None
|
@@ -49,6 +52,7 @@ class HandlerInfo:
|
|
49
52
|
):
|
50
53
|
custom_type_adapter_map = custom_type_adapter_map or {}
|
51
54
|
params_infos = func_system.get_fn_params_infos(handler)
|
55
|
+
is_last_param_args = func_system.is_last_param_args(handler)
|
52
56
|
param_converters = [
|
53
57
|
custom_type_adapter_map.get(
|
54
58
|
idx, pydantic_system.create_type_adapter(param_type)
|
@@ -62,5 +66,23 @@ class HandlerInfo:
|
|
62
66
|
handler,
|
63
67
|
f'File "{file}", line {lineno}',
|
64
68
|
outputs_binding_count,
|
65
|
-
|
69
|
+
handler_param_converters=param_converters,
|
70
|
+
is_last_param_args=is_last_param_args,
|
66
71
|
)
|
72
|
+
|
73
|
+
|
74
|
+
def _try_expand_params_converters(
|
75
|
+
old_param_converters: List[pydantic_system.TypeAdapterProtocol],
|
76
|
+
input_values: List,
|
77
|
+
is_last_param_args: bool,
|
78
|
+
):
|
79
|
+
if not is_last_param_args:
|
80
|
+
return old_param_converters
|
81
|
+
|
82
|
+
diff = len(input_values) - len(old_param_converters)
|
83
|
+
if diff == 0:
|
84
|
+
return old_param_converters
|
85
|
+
|
86
|
+
arg_param_converters = [old_param_converters[-1]] * diff
|
87
|
+
|
88
|
+
return [*old_param_converters[:], *arg_param_converters]
|