-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathui_elements.py
242 lines (196 loc) · 9.41 KB
/
ui_elements.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
from talon import Module, actions
from typing import List, Any, Union, Callable
from .src.elements import ui_elements, ui_elements_svg, use_effect_without_tree
from .src.entity_manager import entity_manager
from .src.state_manager import state_manager
from .src.nodes.tree import render_ui
from .src.utils import get_version
from .examples.examples_ui import toggle_elements_examples
mod = Module()
UNSET = object()
@mod.action_class
class Actions:
def ui_elements(elements: Union[str, List[str]]) -> Union[tuple[callable], callable]:
"""
Provides elements and utilities to build your UI.
```
# Example 1
div, text, screen = actions.user.ui_elements(["div", "text", "screen"])
# Example 2 - All elements
elements = ["screen", "active_window", "div", "text", "button", "input_text", "state", "ref", "effect", "icon"]
screen, active_window, div, text, button, input_text, state, ref, effect, icon = actions.user.ui_elements(elements)
```
"""
return ui_elements(elements)
def ui_elements_show(
renderer: callable,
props: dict[str, Any] = None,
on_mount: callable = None,
on_unmount: callable = None,
show_hints: bool = None,
initial_state: dict[str, Any] = None,
):
"""
Render and show the UI
```
div, text, screen = actions.user.ui_elements(["div", "text", "screen"])
def ui():
return screen()[
div()[
text("Hello world"),
]
]
actions.user.ui_elements_show(ui)
# with initial state
actions.user.ui_elements_show(ui, initial_state={"color": "red"})
# `on_mount` (after UI is visible) and `on_unmount` (before UI is hidden)
actions.user.ui_elements_show(ui, on_mount=lambda: print("mounted"), on_unmount=lambda: print("unmounted"))
```
"""
render_ui(renderer, props, on_mount, on_unmount, show_hints, initial_state)
def ui_elements_hide(renderer: Union[str, Callable]):
"""Destroy and hide a specific ui based on its renderer function or an id on the root node (screen)"""
entity_manager.hide_tree(renderer)
def ui_elements_hide_all():
"""Destroy and hide all UIs"""
entity_manager.hide_all_trees()
def ui_elements_toggle(
renderer: Union[str, Callable],
props: dict[str, Any] = None,
on_mount: callable = None,
on_unmount: callable = None,
show_hints: bool = None,
initial_state: dict[str, Any] = None,
):
"""Toggle visibility of a specific ui based on its renderer function or an id on the root node"""
if entity_manager.does_tree_exist(renderer):
actions.user.ui_elements_hide(renderer)
else:
actions.user.ui_elements_show(renderer, props, on_mount, on_unmount, show_hints, initial_state)
def ui_elements_set_state(name: Union[str, dict], value: Union[Any, callable] = UNSET):
"""
Set global state which will cause a rerender to any respective UIs using the state.
```
actions.user.ui_elements_set_state("active_tab", 1)
```
Set multiple states at once:
```
actions.user.ui_elements_set_state({
"title": "Notes",
"subtitle": "Write a note"
"actions": {
"text": "Action 1",
"action": lambda: print("Action 1 clicked")
}
})
```
"""
if isinstance(name, dict):
for key, val in name.items():
state_manager.set_state_value(key, val)
else:
if value is UNSET:
raise TypeError("actions.user.ui_elements_set_state requires a string key and a value.")
state_manager.set_state_value(name, value)
def ui_elements_get_state(name: str):
"""
Get global state value by its name.
```
"""
state_manager.get_state_value(name)
def ui_elements_set_text(id: str, text_or_callable: Union[str, callable]):
"""
Set text based on its `id`. Renders on a decoration layer, and faster than using `ui_elements_set_state`.
```
text("Hello", id="my_id")[...]
actions.user.ui_elements_set_text("my_id", "Hello world")
actions.user.ui_elements_set_text("my_id", lambda current_text: current_text + "!")
```
"""
state_manager.set_text_mutation(id, text_or_callable)
def ui_elements_set_property(id: str, property_name: Union[str, dict], value: Any):
"""
Set a property of an element based on its `id`. Will cause a rerender.
For example: `color`, `background_color`, `font_size`, `flex_direction`, `justify_content`, `align_items`, `width`, etc...
```
div(id="my_id")[...]
actions.user.ui_elements_set_property("my_id", "background_color", "red")
actions.user.ui_elements_set_property("my_id", "justify_content", "flex_start")
actions.user.ui_elements_set_property("my_id", {
"background_color": "red",
"justify_content": "flex_start"
})
```
"""
if isinstance(property_name, dict):
for key, val in property_name.items():
state_manager.set_property_override(id, key, val)
else:
state_manager.set_ref_property_override(id, property_name, value)
def ui_elements_get_input_value(id: str):
"""Get the value of a `input_text` element based on its id"""
return state_manager.get_input_value(id)
def ui_elements_highlight(id: str, color: str = None):
"""Highlight element based on its id. Renders on a decoration layer."""
state_manager.highlight(id, color)
def ui_elements_unhighlight(id: str):
"""Unhighlight element based on its id. Renders on a decoration layer."""
state_manager.unhighlight(id)
def ui_elements_highlight_briefly(id: str, color: str = None):
"""Highlight element briefly based on its id. Renders on a decoration layer."""
state_manager.highlight_briefly(id, color)
def ui_elements_get_node(id: str):
"""Get node for informational purposes e.g. to access `.box_model`, `.tree`, `.parent_node`, `.children_nodes`, or other properties"""
return entity_manager.get_node(id)
def ui_elements_get_trees():
"""Get all trees. A tree is responsible for each individual UI that is rendered and has all information and methods related to that UI."""
return entity_manager.get_all_trees()
def ui_elements_version():
"""Get the current version of `talon-ui-elements`"""
return get_version()
def ui_elements_examples():
"""Test example UIs"""
toggle_elements_examples()
def ui_elements_debug():
"""Prints debug output to talon log"""
entity_manager.debug()
def ui_elements_svg(elements: List[str]) -> Union[tuple[callable], callable]:
"""
Provides elements to create standard SVG elements, based on view_box 0 0 24 24.
```
# Example 1
svg, path = actions.user.ui_elements_svg(["svg", "path"])
# Example 2 - All elements
elements = ["svg", "path", "rect", "circle", "line", "polyline", "polygon"]
svg, path, rect, circle, line, polyline, polygon = actions.user.ui_elements_svg(elements)
svg()[
path(d="M150 0 L75 200 L225 200 Z", fill="red"),
rect(x=10, y=10, width=100, height=100, fill="blue"),
]
```
"""
return ui_elements_svg(elements)
def ui_elements_register_effect(callback: callable, arg2: Any, arg3: Any = None):
"""
Same as `effect`, but can be registered independently, and will be attached to current or upcoming renderer.
`ui_elements_register_effect(on_mount, [])`
`ui_elements_register_effect(on_mount, on_unmount, [])`
`ui_elements_register_effect(on_change, [state_key])`
Dependencies are `str` state keys, or empty `[]` for mount/unmount effects.
```
"""
use_effect_without_tree(callback, arg2, arg3)
def ui_elements_register_on_lifecycle(callback: callable):
"""
DEPRECATED: Register a callback to be called on mount or unmount.
Deprecated note: Use `ui_elements_register_effect` instead.
"""
print("actions.user.ui_elements_register_on_lifecycle is deprecated. Use `actions.user.ui_elements_register_effect` or `effect` from `actions.user.ui_elements` instead.")
state_manager.deprecated_event_register_on_lifecycle(callback)
def ui_elements_unregister_on_lifecycle(callback: callable):
"""
DEPRECATED: Unregister a lifecycle callback.
Deprecated note: Use `effect` instead inside your renderer, or use `on_mount` and `on_unmount` kwargs in `ui_elements_show`.
"""
print("actions.user.ui_elements_unregister_on_lifecycle is deprecated. Use `actions.user.ui_elements_register_effect` or `effect` from `actions.user.ui_elements` instead.")
state_manager.deprecated_event_unregister_on_lifecycle(callback)