pythonnative 0.14.0__py3-none-any.whl → 0.16.0__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.
- pythonnative/__init__.py +120 -6
- pythonnative/animated.py +40 -2
- pythonnative/components.py +774 -474
- pythonnative/hooks.py +74 -20
- pythonnative/native_views/__init__.py +62 -14
- pythonnative/native_views/android.py +96 -3
- pythonnative/native_views/base.py +3 -92
- pythonnative/native_views/ios.py +121 -2
- pythonnative/reconciler.py +123 -14
- pythonnative/sdk/__init__.py +131 -0
- pythonnative/sdk/_components.py +429 -0
- pythonnative/style.py +413 -61
- {pythonnative-0.14.0.dist-info → pythonnative-0.16.0.dist-info}/METADATA +5 -4
- {pythonnative-0.14.0.dist-info → pythonnative-0.16.0.dist-info}/RECORD +18 -16
- {pythonnative-0.14.0.dist-info → pythonnative-0.16.0.dist-info}/WHEEL +0 -0
- {pythonnative-0.14.0.dist-info → pythonnative-0.16.0.dist-info}/entry_points.txt +0 -0
- {pythonnative-0.14.0.dist-info → pythonnative-0.16.0.dist-info}/licenses/LICENSE +0 -0
- {pythonnative-0.14.0.dist-info → pythonnative-0.16.0.dist-info}/top_level.txt +0 -0
pythonnative/components.py
CHANGED
|
@@ -1,79 +1,310 @@
|
|
|
1
|
-
"""Built-in element factories
|
|
1
|
+
"""Built-in element factories and the typed prop schemas they share.
|
|
2
2
|
|
|
3
|
-
Each
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Each ``@dataclass(frozen=True)`` class in this module — ``TextProps``,
|
|
4
|
+
``ButtonProps``, etc. — is the canonical schema for one built-in
|
|
5
|
+
component. Each factory function (``Text``, ``Button``, …) is a thin
|
|
6
|
+
ergonomic wrapper that builds an [`Element`][pythonnative.Element]
|
|
7
|
+
through the shared :func:`_make_element` helper, so style resolution,
|
|
8
|
+
``ref`` attachment, ``None``-default dropping, and forced overrides
|
|
9
|
+
(e.g. ``Column``'s fixed ``flex_direction``) live in exactly one place.
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Layout properties supported by every component:
|
|
12
|
-
|
|
13
|
-
- `width`, `height`, `flex`, `flex_grow`, `flex_shrink`, `margin`,
|
|
14
|
-
`min_width`, `max_width`, `min_height`, `max_height`, `align_self`.
|
|
15
|
-
|
|
16
|
-
Flex container properties (`View` / `Column` / `Row`):
|
|
17
|
-
|
|
18
|
-
- `flex_direction`, `justify_content`, `align_items`, `overflow`,
|
|
19
|
-
`spacing`, `padding`.
|
|
20
|
-
|
|
21
|
-
[`View`][pythonnative.View] is the universal flex container (like React
|
|
22
|
-
Native's `View`). It defaults to `flex_direction: "column"`.
|
|
23
|
-
[`Column`][pythonnative.Column] and [`Row`][pythonnative.Row] are
|
|
24
|
-
convenience wrappers that fix the direction.
|
|
11
|
+
The same Props dataclasses are used by the `pythonnative.sdk` surface
|
|
12
|
+
for third-party components, so the built-in API and the extension API
|
|
13
|
+
speak the same shape.
|
|
25
14
|
|
|
26
15
|
Example:
|
|
27
16
|
```python
|
|
28
17
|
import pythonnative as pn
|
|
29
18
|
|
|
30
19
|
pn.Column(
|
|
31
|
-
pn.Text("Hello", style=
|
|
20
|
+
pn.Text("Hello", style=pn.style(font_size=18)),
|
|
32
21
|
pn.Button("Tap", on_click=lambda: print("tapped")),
|
|
33
|
-
style=
|
|
22
|
+
style=pn.style(spacing=12, padding=16),
|
|
34
23
|
)
|
|
35
24
|
```
|
|
36
25
|
"""
|
|
37
26
|
|
|
38
|
-
from
|
|
27
|
+
from dataclasses import dataclass, field
|
|
28
|
+
from typing import Any, Callable, Dict, List, Literal, Optional
|
|
39
29
|
|
|
40
30
|
from .element import Element
|
|
41
|
-
from .
|
|
31
|
+
from .sdk import Props
|
|
32
|
+
from .style import (
|
|
33
|
+
AutoCapitalize,
|
|
34
|
+
Color,
|
|
35
|
+
KeyboardType,
|
|
36
|
+
ReturnKeyType,
|
|
37
|
+
ScaleType,
|
|
38
|
+
StyleProp,
|
|
39
|
+
resolve_style,
|
|
40
|
+
)
|
|
42
41
|
|
|
43
42
|
# ======================================================================
|
|
44
|
-
#
|
|
43
|
+
# Canonical element builder
|
|
45
44
|
# ======================================================================
|
|
46
45
|
|
|
47
46
|
|
|
48
|
-
def
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
def _make_element(
|
|
48
|
+
name: str,
|
|
49
|
+
*children: Element,
|
|
50
|
+
style: StyleProp = None,
|
|
51
|
+
ref: Optional[Dict[str, Any]] = None,
|
|
52
|
+
key: Optional[str] = None,
|
|
53
|
+
_defaults: Optional[Dict[str, Any]] = None,
|
|
54
|
+
_forced: Optional[Dict[str, Any]] = None,
|
|
55
|
+
**props: Any,
|
|
56
|
+
) -> Element:
|
|
57
|
+
"""Build an [`Element`][pythonnative.Element] of type ``name``.
|
|
58
|
+
|
|
59
|
+
This is the single helper every built-in factory routes through, so
|
|
60
|
+
the cross-cutting concerns that used to be duplicated per component
|
|
61
|
+
live in one place:
|
|
62
|
+
|
|
63
|
+
1. ``style`` is flattened via
|
|
64
|
+
[`resolve_style`][pythonnative.style.resolve_style] (list-of-dicts
|
|
65
|
+
and ``None`` both handled).
|
|
66
|
+
2. ``_defaults`` are filled in for keys not already present (used for
|
|
67
|
+
things like ``View``'s default ``flex_direction: "column"`` that
|
|
68
|
+
a user style may legitimately override).
|
|
69
|
+
3. ``**props`` are merged on top, with ``None`` values *dropped* so
|
|
70
|
+
optional kwargs don't pollute the prop dict.
|
|
71
|
+
4. ``ref`` is attached under the reserved ``"ref"`` key.
|
|
72
|
+
5. ``_forced`` overrides everything (used by ``Column`` / ``Row`` to
|
|
73
|
+
lock their flex direction regardless of user style).
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
name: Element type name (e.g. ``"Text"``).
|
|
77
|
+
*children: Child elements.
|
|
78
|
+
style: Style dict, list of dicts, or ``None``.
|
|
79
|
+
ref: Optional ``use_ref()`` dict; the reconciler populates
|
|
80
|
+
``ref["current"]`` with the underlying native view.
|
|
81
|
+
key: Stable identity for keyed reconciliation.
|
|
82
|
+
_defaults: Internal: fill-only-if-missing prop defaults.
|
|
83
|
+
_forced: Internal: prop overrides applied last.
|
|
84
|
+
**props: Per-component props. ``None`` values are dropped.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
A fresh [`Element`][pythonnative.Element].
|
|
88
|
+
"""
|
|
89
|
+
out: Dict[str, Any] = dict(resolve_style(style))
|
|
90
|
+
if _defaults:
|
|
91
|
+
for k, v in _defaults.items():
|
|
92
|
+
out.setdefault(k, v)
|
|
93
|
+
for k, v in props.items():
|
|
94
|
+
if v is not None:
|
|
95
|
+
out[k] = v
|
|
96
|
+
if ref is not None:
|
|
97
|
+
out["ref"] = ref
|
|
98
|
+
if _forced:
|
|
99
|
+
out.update(_forced)
|
|
100
|
+
return Element(name, out, list(children), key=key)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# ======================================================================
|
|
104
|
+
# Props dataclasses
|
|
105
|
+
# ======================================================================
|
|
106
|
+
#
|
|
107
|
+
# These are the canonical schemas for every built-in component. They
|
|
108
|
+
# subclass the SDK's ``Props`` base, so the same shape works for both
|
|
109
|
+
# the built-in factory functions and the third-party
|
|
110
|
+
# [`element_factory`][pythonnative.element_factory] API.
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@dataclass(frozen=True)
|
|
114
|
+
class TextProps(Props):
|
|
115
|
+
"""Props for [`Text`][pythonnative.Text]."""
|
|
116
|
+
|
|
117
|
+
text: str = ""
|
|
118
|
+
accessibility_label: Optional[str] = None
|
|
119
|
+
accessibility_hint: Optional[str] = None
|
|
120
|
+
accessibility_role: Optional[str] = None
|
|
121
|
+
accessible: Optional[bool] = None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@dataclass(frozen=True)
|
|
125
|
+
class ButtonProps(Props):
|
|
126
|
+
"""Props for [`Button`][pythonnative.Button]."""
|
|
127
|
+
|
|
128
|
+
title: str = ""
|
|
129
|
+
on_click: Optional[Callable[[], None]] = None
|
|
130
|
+
enabled: bool = True
|
|
131
|
+
accessibility_label: Optional[str] = None
|
|
132
|
+
accessibility_hint: Optional[str] = None
|
|
133
|
+
accessibility_role: Optional[str] = None
|
|
134
|
+
accessible: Optional[bool] = None
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@dataclass(frozen=True)
|
|
138
|
+
class TextInputProps(Props):
|
|
139
|
+
"""Props for [`TextInput`][pythonnative.TextInput]."""
|
|
140
|
+
|
|
141
|
+
value: str = ""
|
|
142
|
+
placeholder: Optional[str] = None
|
|
143
|
+
on_change: Optional[Callable[[str], None]] = None
|
|
144
|
+
on_submit: Optional[Callable[[str], None]] = None
|
|
145
|
+
secure: bool = False
|
|
146
|
+
multiline: bool = False
|
|
147
|
+
keyboard_type: Optional[KeyboardType] = None
|
|
148
|
+
auto_capitalize: Optional[AutoCapitalize] = None
|
|
149
|
+
auto_correct: Optional[bool] = None
|
|
150
|
+
auto_focus: bool = False
|
|
151
|
+
return_key_type: Optional[ReturnKeyType] = None
|
|
152
|
+
max_length: Optional[int] = None
|
|
153
|
+
placeholder_color: Optional[Color] = None
|
|
154
|
+
accessibility_label: Optional[str] = None
|
|
155
|
+
accessibility_hint: Optional[str] = None
|
|
156
|
+
accessible: Optional[bool] = None
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@dataclass(frozen=True)
|
|
160
|
+
class ImageProps(Props):
|
|
161
|
+
"""Props for [`Image`][pythonnative.Image]."""
|
|
162
|
+
|
|
163
|
+
source: Optional[str] = None
|
|
164
|
+
scale_type: Optional[ScaleType] = None
|
|
165
|
+
tint_color: Optional[Color] = None
|
|
166
|
+
accessibility_label: Optional[str] = None
|
|
167
|
+
accessibility_role: Optional[str] = None
|
|
168
|
+
accessible: Optional[bool] = None
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@dataclass(frozen=True)
|
|
172
|
+
class SwitchProps(Props):
|
|
173
|
+
"""Props for [`Switch`][pythonnative.Switch]."""
|
|
174
|
+
|
|
175
|
+
value: bool = False
|
|
176
|
+
on_change: Optional[Callable[[bool], None]] = None
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@dataclass(frozen=True)
|
|
180
|
+
class ProgressBarProps(Props):
|
|
181
|
+
"""Props for [`ProgressBar`][pythonnative.ProgressBar]."""
|
|
182
|
+
|
|
183
|
+
value: float = 0.0
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@dataclass(frozen=True)
|
|
187
|
+
class ActivityIndicatorProps(Props):
|
|
188
|
+
"""Props for [`ActivityIndicator`][pythonnative.ActivityIndicator]."""
|
|
189
|
+
|
|
190
|
+
animating: bool = True
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@dataclass(frozen=True)
|
|
194
|
+
class WebViewProps(Props):
|
|
195
|
+
"""Props for [`WebView`][pythonnative.WebView]."""
|
|
196
|
+
|
|
197
|
+
url: Optional[str] = None
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
@dataclass(frozen=True)
|
|
201
|
+
class SpacerProps(Props):
|
|
202
|
+
"""Props for [`Spacer`][pythonnative.Spacer]."""
|
|
55
203
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
204
|
+
size: Optional[float] = None
|
|
205
|
+
flex: Optional[float] = None
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@dataclass(frozen=True)
|
|
209
|
+
class SliderProps(Props):
|
|
210
|
+
"""Props for [`Slider`][pythonnative.Slider]."""
|
|
211
|
+
|
|
212
|
+
value: float = 0.0
|
|
213
|
+
min_value: float = 0.0
|
|
214
|
+
max_value: float = 1.0
|
|
215
|
+
on_change: Optional[Callable[[float], None]] = None
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
@dataclass(frozen=True)
|
|
219
|
+
class ViewProps(Props):
|
|
220
|
+
"""Props for [`View`][pythonnative.View], [`Column`][pythonnative.Column], and [`Row`][pythonnative.Row]."""
|
|
221
|
+
|
|
222
|
+
accessibility_label: Optional[str] = None
|
|
223
|
+
accessibility_hint: Optional[str] = None
|
|
224
|
+
accessibility_role: Optional[str] = None
|
|
225
|
+
accessible: Optional[bool] = None
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
@dataclass(frozen=True)
|
|
229
|
+
class ScrollViewProps(Props):
|
|
230
|
+
"""Props for [`ScrollView`][pythonnative.ScrollView]."""
|
|
231
|
+
|
|
232
|
+
refresh_control: Optional[Dict[str, Any]] = None
|
|
233
|
+
scroll_axis: Optional[Literal["vertical", "horizontal"]] = None
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
@dataclass(frozen=True)
|
|
237
|
+
class SafeAreaViewProps(Props):
|
|
238
|
+
"""Props for [`SafeAreaView`][pythonnative.SafeAreaView]."""
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
@dataclass(frozen=True)
|
|
242
|
+
class ModalProps(Props):
|
|
243
|
+
"""Props for [`Modal`][pythonnative.Modal]."""
|
|
244
|
+
|
|
245
|
+
visible: bool = False
|
|
246
|
+
on_dismiss: Optional[Callable[[], None]] = None
|
|
247
|
+
title: Optional[str] = None
|
|
248
|
+
animation_type: Literal["slide", "fade", "none"] = "slide"
|
|
249
|
+
transparent: bool = False
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@dataclass(frozen=True)
|
|
253
|
+
class PressableProps(Props):
|
|
254
|
+
"""Props for [`Pressable`][pythonnative.Pressable]."""
|
|
255
|
+
|
|
256
|
+
on_press: Optional[Callable[[], None]] = None
|
|
257
|
+
on_long_press: Optional[Callable[[], None]] = None
|
|
258
|
+
pressed_opacity: float = 0.6
|
|
259
|
+
accessibility_label: Optional[str] = None
|
|
260
|
+
accessibility_hint: Optional[str] = None
|
|
261
|
+
accessibility_role: Optional[str] = None
|
|
262
|
+
accessible: Optional[bool] = None
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
@dataclass(frozen=True)
|
|
266
|
+
class StatusBarProps(Props):
|
|
267
|
+
"""Props for [`StatusBar`][pythonnative.StatusBar]."""
|
|
268
|
+
|
|
269
|
+
bar_style: Optional[Literal["light", "dark", "default"]] = None
|
|
270
|
+
background_color: Optional[Color] = None
|
|
271
|
+
hidden: Optional[bool] = None
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
@dataclass(frozen=True)
|
|
275
|
+
class KeyboardAvoidingViewProps(Props):
|
|
276
|
+
"""Props for [`KeyboardAvoidingView`][pythonnative.KeyboardAvoidingView]."""
|
|
277
|
+
|
|
278
|
+
behavior: Literal["padding", "position"] = "padding"
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
@dataclass(frozen=True)
|
|
282
|
+
class PickerProps(Props):
|
|
283
|
+
"""Props for [`Picker`][pythonnative.Picker].
|
|
284
|
+
|
|
285
|
+
``items`` is an ordered list of ``{"value": Any, "label": str}``
|
|
286
|
+
entries. ``value`` is matched against ``items[i]["value"]`` to
|
|
287
|
+
determine the currently selected row.
|
|
60
288
|
"""
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
289
|
+
|
|
290
|
+
value: Any = None
|
|
291
|
+
items: List[Dict[str, Any]] = field(default_factory=list)
|
|
292
|
+
on_change: Optional[Callable[[Any], None]] = None
|
|
293
|
+
placeholder: str = "Select…"
|
|
294
|
+
accessibility_label: Optional[str] = None
|
|
295
|
+
accessibility_hint: Optional[str] = None
|
|
296
|
+
accessible: Optional[bool] = None
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
# ======================================================================
|
|
300
|
+
# Leaf factories
|
|
301
|
+
# ======================================================================
|
|
71
302
|
|
|
72
303
|
|
|
73
304
|
def Text(
|
|
74
305
|
text: str = "",
|
|
75
306
|
*,
|
|
76
|
-
style:
|
|
307
|
+
style: StyleProp = None,
|
|
77
308
|
accessibility_label: Optional[str] = None,
|
|
78
309
|
accessibility_hint: Optional[str] = None,
|
|
79
310
|
accessibility_role: Optional[str] = None,
|
|
@@ -83,34 +314,38 @@ def Text(
|
|
|
83
314
|
) -> Element:
|
|
84
315
|
"""Display a string of text.
|
|
85
316
|
|
|
86
|
-
Style properties:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
(
|
|
90
|
-
|
|
91
|
-
|
|
317
|
+
Style properties: ``font_size``, ``color``, ``bold``,
|
|
318
|
+
``font_weight``, ``font_family``, ``italic``, ``text_align``,
|
|
319
|
+
``background_color``, ``max_lines``, ``letter_spacing``,
|
|
320
|
+
``line_height``, ``text_decoration`` (``"underline"`` /
|
|
321
|
+
``"line_through"``), ``border_radius``, ``border_width``,
|
|
322
|
+
``border_color``, ``shadow_*``, ``opacity``, ``transform``, plus
|
|
323
|
+
the common layout props.
|
|
92
324
|
|
|
93
325
|
Args:
|
|
94
326
|
text: Text content to display.
|
|
95
|
-
style: Style dict (or list of dicts)
|
|
96
|
-
layout.
|
|
327
|
+
style: Style dict (or list of dicts).
|
|
97
328
|
accessibility_label: Spoken description for screen readers.
|
|
98
329
|
accessibility_hint: Spoken extra detail (iOS only).
|
|
99
330
|
accessibility_role: Semantic role for assistive tech.
|
|
100
331
|
accessible: Override whether the element is exposed to AT.
|
|
101
|
-
ref: Optional ``use_ref()`` dict
|
|
102
|
-
|
|
103
|
-
key: Stable identity for keyed reconciliation in lists.
|
|
332
|
+
ref: Optional ``use_ref()`` dict.
|
|
333
|
+
key: Stable identity for keyed reconciliation.
|
|
104
334
|
|
|
105
335
|
Returns:
|
|
106
|
-
An [`Element`][pythonnative.Element] of type
|
|
336
|
+
An [`Element`][pythonnative.Element] of type ``"Text"``.
|
|
107
337
|
"""
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
338
|
+
return _make_element(
|
|
339
|
+
"Text",
|
|
340
|
+
style=style,
|
|
341
|
+
ref=ref,
|
|
342
|
+
key=key,
|
|
343
|
+
text=text,
|
|
344
|
+
accessibility_label=accessibility_label,
|
|
345
|
+
accessibility_hint=accessibility_hint,
|
|
346
|
+
accessibility_role=accessibility_role,
|
|
347
|
+
accessible=accessible,
|
|
348
|
+
)
|
|
114
349
|
|
|
115
350
|
|
|
116
351
|
def Button(
|
|
@@ -118,100 +353,99 @@ def Button(
|
|
|
118
353
|
*,
|
|
119
354
|
on_click: Optional[Callable[[], None]] = None,
|
|
120
355
|
enabled: bool = True,
|
|
121
|
-
style:
|
|
356
|
+
style: StyleProp = None,
|
|
122
357
|
accessibility_label: Optional[str] = None,
|
|
123
358
|
accessibility_hint: Optional[str] = None,
|
|
359
|
+
accessibility_role: Optional[str] = None,
|
|
124
360
|
accessible: Optional[bool] = None,
|
|
125
361
|
ref: Optional[Dict[str, Any]] = None,
|
|
126
362
|
key: Optional[str] = None,
|
|
127
363
|
) -> Element:
|
|
128
364
|
"""Display a tappable button.
|
|
129
365
|
|
|
130
|
-
Style properties:
|
|
131
|
-
|
|
132
|
-
|
|
366
|
+
Style properties: ``color``, ``background_color``, ``font_size``,
|
|
367
|
+
``border_radius``, ``border_width``, ``border_color``, ``shadow_*``,
|
|
368
|
+
``opacity``, ``transform``, plus the common layout props.
|
|
369
|
+
|
|
370
|
+
Buttons get ``accessibility_role="button"`` by default.
|
|
133
371
|
|
|
134
372
|
Args:
|
|
135
373
|
title: Button label.
|
|
136
374
|
on_click: Callback invoked when the user taps the button.
|
|
137
|
-
enabled: When
|
|
375
|
+
enabled: When ``False``, the button is disabled and cannot be
|
|
138
376
|
tapped.
|
|
139
377
|
style: Style dict (or list of dicts).
|
|
140
378
|
accessibility_label: Spoken description for screen readers.
|
|
141
379
|
accessibility_hint: Spoken extra detail (iOS only).
|
|
380
|
+
accessibility_role: Override the default ``"button"`` role.
|
|
142
381
|
accessible: Override whether the element is exposed to AT.
|
|
143
|
-
ref: Optional ``use_ref()`` dict
|
|
144
|
-
``ref["current"]`` with the underlying native view.
|
|
382
|
+
ref: Optional ``use_ref()`` dict.
|
|
145
383
|
key: Stable identity for keyed reconciliation.
|
|
146
384
|
|
|
147
385
|
Returns:
|
|
148
|
-
An [`Element`][pythonnative.Element] of type
|
|
386
|
+
An [`Element`][pythonnative.Element] of type ``"Button"``.
|
|
149
387
|
"""
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if ref is not None:
|
|
165
|
-
props["ref"] = ref
|
|
166
|
-
return Element("Button", props, [], key=key)
|
|
388
|
+
return _make_element(
|
|
389
|
+
"Button",
|
|
390
|
+
style=style,
|
|
391
|
+
ref=ref,
|
|
392
|
+
key=key,
|
|
393
|
+
title=title,
|
|
394
|
+
on_click=on_click,
|
|
395
|
+
enabled=enabled,
|
|
396
|
+
accessibility_label=accessibility_label,
|
|
397
|
+
accessibility_hint=accessibility_hint,
|
|
398
|
+
accessibility_role=accessibility_role,
|
|
399
|
+
accessible=accessible,
|
|
400
|
+
_defaults={"accessibility_role": "button"},
|
|
401
|
+
)
|
|
167
402
|
|
|
168
403
|
|
|
169
404
|
def TextInput(
|
|
170
405
|
*,
|
|
171
406
|
value: str = "",
|
|
172
|
-
placeholder: str =
|
|
407
|
+
placeholder: Optional[str] = None,
|
|
173
408
|
on_change: Optional[Callable[[str], None]] = None,
|
|
174
409
|
on_submit: Optional[Callable[[str], None]] = None,
|
|
175
410
|
secure: bool = False,
|
|
176
411
|
multiline: bool = False,
|
|
177
|
-
keyboard_type: Optional[
|
|
178
|
-
auto_capitalize: Optional[
|
|
412
|
+
keyboard_type: Optional[KeyboardType] = None,
|
|
413
|
+
auto_capitalize: Optional[AutoCapitalize] = None,
|
|
179
414
|
auto_correct: Optional[bool] = None,
|
|
180
415
|
auto_focus: bool = False,
|
|
181
|
-
return_key_type: Optional[
|
|
416
|
+
return_key_type: Optional[ReturnKeyType] = None,
|
|
182
417
|
max_length: Optional[int] = None,
|
|
183
|
-
placeholder_color: Optional[
|
|
184
|
-
style:
|
|
418
|
+
placeholder_color: Optional[Color] = None,
|
|
419
|
+
style: StyleProp = None,
|
|
185
420
|
accessibility_label: Optional[str] = None,
|
|
186
421
|
accessibility_hint: Optional[str] = None,
|
|
187
422
|
accessible: Optional[bool] = None,
|
|
188
423
|
ref: Optional[Dict[str, Any]] = None,
|
|
189
424
|
key: Optional[str] = None,
|
|
190
425
|
) -> Element:
|
|
191
|
-
"""Display a text
|
|
426
|
+
"""Display a text-entry field (single-line by default, or ``multiline``).
|
|
192
427
|
|
|
193
|
-
Style properties:
|
|
194
|
-
|
|
428
|
+
Style properties: ``font_size``, ``color``, ``background_color``,
|
|
429
|
+
``border_*``, plus the common layout props.
|
|
195
430
|
|
|
196
431
|
Args:
|
|
197
432
|
value: Current text content (controlled-input pattern).
|
|
198
|
-
placeholder: Hint shown when
|
|
433
|
+
placeholder: Hint shown when ``value`` is empty.
|
|
199
434
|
on_change: Callback invoked with the new string each keystroke.
|
|
200
435
|
on_submit: Callback invoked when the user submits (Return /
|
|
201
436
|
Done / etc.). Receives the final text.
|
|
202
|
-
secure: When
|
|
203
|
-
multiline: When
|
|
437
|
+
secure: When ``True``, characters are masked (use for passwords).
|
|
438
|
+
multiline: When ``True``, allows multiple lines of input.
|
|
204
439
|
keyboard_type: One of ``"default"``, ``"email_address"``,
|
|
205
|
-
``"number_pad"``, ``"decimal_pad"``, ``"phone_pad"``,
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
``"words"``, ``"characters"``.
|
|
440
|
+
``"number_pad"``, ``"decimal_pad"``, ``"phone_pad"``, ``"url"``.
|
|
441
|
+
auto_capitalize: One of ``"none"``, ``"sentences"``, ``"words"``,
|
|
442
|
+
``"characters"``.
|
|
209
443
|
auto_correct: Enable/disable autocorrection.
|
|
210
444
|
auto_focus: Request focus on mount.
|
|
211
445
|
return_key_type: One of ``"default"``, ``"done"``, ``"go"``,
|
|
212
446
|
``"next"``, ``"send"``, ``"search"``.
|
|
213
447
|
max_length: Maximum number of characters allowed.
|
|
214
|
-
placeholder_color: Color
|
|
448
|
+
placeholder_color: Color used for the placeholder string.
|
|
215
449
|
style: Style dict (or list of dicts).
|
|
216
450
|
accessibility_label: Spoken description for screen readers.
|
|
217
451
|
accessibility_hint: Spoken extra detail (iOS only).
|
|
@@ -220,94 +454,90 @@ def TextInput(
|
|
|
220
454
|
key: Stable identity for keyed reconciliation.
|
|
221
455
|
|
|
222
456
|
Returns:
|
|
223
|
-
An [`Element`][pythonnative.Element] of type
|
|
457
|
+
An [`Element`][pythonnative.Element] of type ``"TextInput"``.
|
|
224
458
|
"""
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
props["max_length"] = max_length
|
|
248
|
-
if placeholder_color is not None:
|
|
249
|
-
props["placeholder_color"] = placeholder_color
|
|
250
|
-
props.update(resolve_style(style))
|
|
251
|
-
props.update(_accessibility_props(accessibility_label, accessibility_hint, None, accessible))
|
|
252
|
-
if ref is not None:
|
|
253
|
-
props["ref"] = ref
|
|
254
|
-
return Element("TextInput", props, [], key=key)
|
|
459
|
+
return _make_element(
|
|
460
|
+
"TextInput",
|
|
461
|
+
style=style,
|
|
462
|
+
ref=ref,
|
|
463
|
+
key=key,
|
|
464
|
+
value=value,
|
|
465
|
+
placeholder=placeholder,
|
|
466
|
+
on_change=on_change,
|
|
467
|
+
on_submit=on_submit,
|
|
468
|
+
secure=secure or None,
|
|
469
|
+
multiline=multiline or None,
|
|
470
|
+
keyboard_type=keyboard_type,
|
|
471
|
+
auto_capitalize=auto_capitalize,
|
|
472
|
+
auto_correct=auto_correct,
|
|
473
|
+
auto_focus=auto_focus or None,
|
|
474
|
+
return_key_type=return_key_type,
|
|
475
|
+
max_length=max_length,
|
|
476
|
+
placeholder_color=placeholder_color,
|
|
477
|
+
accessibility_label=accessibility_label,
|
|
478
|
+
accessibility_hint=accessibility_hint,
|
|
479
|
+
accessible=accessible,
|
|
480
|
+
)
|
|
255
481
|
|
|
256
482
|
|
|
257
483
|
def Image(
|
|
258
484
|
source: str = "",
|
|
259
485
|
*,
|
|
260
|
-
scale_type: Optional[
|
|
261
|
-
tint_color: Optional[
|
|
262
|
-
style:
|
|
486
|
+
scale_type: Optional[ScaleType] = None,
|
|
487
|
+
tint_color: Optional[Color] = None,
|
|
488
|
+
style: StyleProp = None,
|
|
263
489
|
accessibility_label: Optional[str] = None,
|
|
490
|
+
accessibility_role: Optional[str] = None,
|
|
264
491
|
accessible: Optional[bool] = None,
|
|
265
492
|
ref: Optional[Dict[str, Any]] = None,
|
|
266
493
|
key: Optional[str] = None,
|
|
267
494
|
) -> Element:
|
|
268
495
|
"""Display an image from a resource path or URL.
|
|
269
496
|
|
|
270
|
-
Style properties:
|
|
271
|
-
|
|
497
|
+
Style properties: ``background_color``, ``border_*``, ``opacity``,
|
|
498
|
+
``transform``, plus the common layout props.
|
|
272
499
|
|
|
273
500
|
Network images (``http://`` / ``https://``) are loaded
|
|
274
|
-
asynchronously off the main thread on both iOS (via
|
|
275
|
-
and Android (via a worker thread
|
|
501
|
+
asynchronously off the main thread on both iOS (via
|
|
502
|
+
``NSURLSession``) and Android (via a worker thread plus
|
|
503
|
+
``BitmapFactory``).
|
|
276
504
|
|
|
277
505
|
Args:
|
|
278
506
|
source: Image resource name or URL.
|
|
279
|
-
scale_type: Fit mode:
|
|
280
|
-
|
|
507
|
+
scale_type: Fit mode: ``"cover"``, ``"contain"``, ``"stretch"``,
|
|
508
|
+
``"center"``.
|
|
281
509
|
tint_color: Color overlay applied to template images
|
|
282
510
|
(monochrome icons).
|
|
283
511
|
style: Style dict (or list of dicts).
|
|
284
512
|
accessibility_label: Spoken description for screen readers.
|
|
513
|
+
accessibility_role: Override the default ``"image"`` role.
|
|
285
514
|
accessible: Override whether the element is exposed to AT.
|
|
286
515
|
ref: Optional ``use_ref()`` dict.
|
|
287
516
|
key: Stable identity for keyed reconciliation.
|
|
288
517
|
|
|
289
518
|
Returns:
|
|
290
|
-
An [`Element`][pythonnative.Element] of type
|
|
519
|
+
An [`Element`][pythonnative.Element] of type ``"Image"``.
|
|
291
520
|
"""
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
521
|
+
return _make_element(
|
|
522
|
+
"Image",
|
|
523
|
+
style=style,
|
|
524
|
+
ref=ref,
|
|
525
|
+
key=key,
|
|
526
|
+
source=source or None,
|
|
527
|
+
scale_type=scale_type,
|
|
528
|
+
tint_color=tint_color,
|
|
529
|
+
accessibility_label=accessibility_label,
|
|
530
|
+
accessibility_role=accessibility_role,
|
|
531
|
+
accessible=accessible,
|
|
532
|
+
_defaults={"accessibility_role": "image"},
|
|
533
|
+
)
|
|
304
534
|
|
|
305
535
|
|
|
306
536
|
def Switch(
|
|
307
537
|
*,
|
|
308
538
|
value: bool = False,
|
|
309
539
|
on_change: Optional[Callable[[bool], None]] = None,
|
|
310
|
-
style:
|
|
540
|
+
style: StyleProp = None,
|
|
311
541
|
key: Optional[str] = None,
|
|
312
542
|
) -> Element:
|
|
313
543
|
"""Display a toggle switch.
|
|
@@ -319,66 +549,74 @@ def Switch(
|
|
|
319
549
|
key: Stable identity for keyed reconciliation.
|
|
320
550
|
|
|
321
551
|
Returns:
|
|
322
|
-
An [`Element`][pythonnative.Element] of type
|
|
552
|
+
An [`Element`][pythonnative.Element] of type ``"Switch"``.
|
|
323
553
|
"""
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
554
|
+
return _make_element(
|
|
555
|
+
"Switch",
|
|
556
|
+
style=style,
|
|
557
|
+
key=key,
|
|
558
|
+
value=value,
|
|
559
|
+
on_change=on_change,
|
|
560
|
+
)
|
|
329
561
|
|
|
330
562
|
|
|
331
563
|
def ProgressBar(
|
|
332
564
|
*,
|
|
333
565
|
value: float = 0.0,
|
|
334
|
-
style:
|
|
566
|
+
style: StyleProp = None,
|
|
335
567
|
key: Optional[str] = None,
|
|
336
568
|
) -> Element:
|
|
337
|
-
"""Show determinate progress as a value between 0.0 and 1.0
|
|
569
|
+
"""Show determinate progress as a value between ``0.0`` and ``1.0``.
|
|
338
570
|
|
|
339
571
|
For indeterminate progress, use
|
|
340
572
|
[`ActivityIndicator`][pythonnative.ActivityIndicator] instead.
|
|
341
573
|
|
|
342
574
|
Args:
|
|
343
|
-
value: Fraction complete (clamped to
|
|
575
|
+
value: Fraction complete (clamped to ``[0.0, 1.0]`` by the
|
|
344
576
|
platform handler).
|
|
345
577
|
style: Style dict (or list of dicts).
|
|
346
578
|
key: Stable identity for keyed reconciliation.
|
|
347
579
|
|
|
348
580
|
Returns:
|
|
349
|
-
An [`Element`][pythonnative.Element] of type
|
|
581
|
+
An [`Element`][pythonnative.Element] of type ``"ProgressBar"``.
|
|
350
582
|
"""
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
583
|
+
return _make_element(
|
|
584
|
+
"ProgressBar",
|
|
585
|
+
style=style,
|
|
586
|
+
key=key,
|
|
587
|
+
value=value,
|
|
588
|
+
)
|
|
354
589
|
|
|
355
590
|
|
|
356
591
|
def ActivityIndicator(
|
|
357
592
|
*,
|
|
358
593
|
animating: bool = True,
|
|
359
|
-
style:
|
|
594
|
+
style: StyleProp = None,
|
|
360
595
|
key: Optional[str] = None,
|
|
361
596
|
) -> Element:
|
|
362
597
|
"""Show an indeterminate loading spinner.
|
|
363
598
|
|
|
364
599
|
Args:
|
|
365
|
-
animating: When
|
|
600
|
+
animating: When ``False``, the spinner is hidden.
|
|
366
601
|
style: Style dict (or list of dicts).
|
|
367
602
|
key: Stable identity for keyed reconciliation.
|
|
368
603
|
|
|
369
604
|
Returns:
|
|
370
605
|
An [`Element`][pythonnative.Element] of type
|
|
371
|
-
|
|
606
|
+
``"ActivityIndicator"``.
|
|
372
607
|
"""
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
608
|
+
return _make_element(
|
|
609
|
+
"ActivityIndicator",
|
|
610
|
+
style=style,
|
|
611
|
+
key=key,
|
|
612
|
+
animating=animating,
|
|
613
|
+
)
|
|
376
614
|
|
|
377
615
|
|
|
378
616
|
def WebView(
|
|
379
617
|
*,
|
|
380
618
|
url: str = "",
|
|
381
|
-
style:
|
|
619
|
+
style: StyleProp = None,
|
|
382
620
|
key: Optional[str] = None,
|
|
383
621
|
) -> Element:
|
|
384
622
|
"""Embed web content from a URL.
|
|
@@ -389,13 +627,14 @@ def WebView(
|
|
|
389
627
|
key: Stable identity for keyed reconciliation.
|
|
390
628
|
|
|
391
629
|
Returns:
|
|
392
|
-
An [`Element`][pythonnative.Element] of type
|
|
630
|
+
An [`Element`][pythonnative.Element] of type ``"WebView"``.
|
|
393
631
|
"""
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
632
|
+
return _make_element(
|
|
633
|
+
"WebView",
|
|
634
|
+
style=style,
|
|
635
|
+
key=key,
|
|
636
|
+
url=url or None,
|
|
637
|
+
)
|
|
399
638
|
|
|
400
639
|
|
|
401
640
|
def Spacer(
|
|
@@ -406,32 +645,31 @@ def Spacer(
|
|
|
406
645
|
) -> Element:
|
|
407
646
|
"""Insert empty space inside a flex container.
|
|
408
647
|
|
|
409
|
-
Pass
|
|
648
|
+
Pass ``size`` for a fixed gap, or ``flex`` to expand and absorb
|
|
410
649
|
remaining space.
|
|
411
650
|
|
|
412
651
|
Args:
|
|
413
|
-
size: Fixed gap in dp/pt along the parent's main axis.
|
|
652
|
+
size: Fixed gap in dp/pt along the parent's main axis. Mirrored
|
|
653
|
+
on both axes — whichever axis the parent's
|
|
654
|
+
``flex_direction`` chooses as main becomes the actual gap.
|
|
414
655
|
flex: Flex-grow weight; useful for pushing siblings to the
|
|
415
656
|
opposite end of a [`Row`][pythonnative.Row] or
|
|
416
657
|
[`Column`][pythonnative.Column].
|
|
417
658
|
key: Stable identity for keyed reconciliation.
|
|
418
659
|
|
|
419
660
|
Returns:
|
|
420
|
-
An [`Element`][pythonnative.Element] of type
|
|
661
|
+
An [`Element`][pythonnative.Element] of type ``"Spacer"``.
|
|
421
662
|
"""
|
|
422
|
-
|
|
423
|
-
if size is not None
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
if flex is not None:
|
|
433
|
-
props["flex"] = flex
|
|
434
|
-
return Element("Spacer", props, [], key=key)
|
|
663
|
+
width = size if size is not None else None
|
|
664
|
+
height = size if size is not None else None
|
|
665
|
+
return _make_element(
|
|
666
|
+
"Spacer",
|
|
667
|
+
key=key,
|
|
668
|
+
size=size,
|
|
669
|
+
width=width,
|
|
670
|
+
height=height,
|
|
671
|
+
flex=flex,
|
|
672
|
+
)
|
|
435
673
|
|
|
436
674
|
|
|
437
675
|
def Slider(
|
|
@@ -440,10 +678,10 @@ def Slider(
|
|
|
440
678
|
min_value: float = 0.0,
|
|
441
679
|
max_value: float = 1.0,
|
|
442
680
|
on_change: Optional[Callable[[float], None]] = None,
|
|
443
|
-
style:
|
|
681
|
+
style: StyleProp = None,
|
|
444
682
|
key: Optional[str] = None,
|
|
445
683
|
) -> Element:
|
|
446
|
-
"""Continuous-value slider between
|
|
684
|
+
"""Continuous-value slider between ``min_value`` and ``max_value``.
|
|
447
685
|
|
|
448
686
|
Args:
|
|
449
687
|
value: Current slider value.
|
|
@@ -455,27 +693,27 @@ def Slider(
|
|
|
455
693
|
key: Stable identity for keyed reconciliation.
|
|
456
694
|
|
|
457
695
|
Returns:
|
|
458
|
-
An [`Element`][pythonnative.Element] of type
|
|
696
|
+
An [`Element`][pythonnative.Element] of type ``"Slider"``.
|
|
459
697
|
"""
|
|
460
|
-
|
|
461
|
-
"
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
698
|
+
return _make_element(
|
|
699
|
+
"Slider",
|
|
700
|
+
style=style,
|
|
701
|
+
key=key,
|
|
702
|
+
value=value,
|
|
703
|
+
min_value=min_value,
|
|
704
|
+
max_value=max_value,
|
|
705
|
+
on_change=on_change,
|
|
706
|
+
)
|
|
469
707
|
|
|
470
708
|
|
|
471
709
|
# ======================================================================
|
|
472
|
-
# Container
|
|
710
|
+
# Container factories
|
|
473
711
|
# ======================================================================
|
|
474
712
|
|
|
475
713
|
|
|
476
714
|
def View(
|
|
477
715
|
*children: Element,
|
|
478
|
-
style:
|
|
716
|
+
style: StyleProp = None,
|
|
479
717
|
accessibility_label: Optional[str] = None,
|
|
480
718
|
accessibility_hint: Optional[str] = None,
|
|
481
719
|
accessibility_role: Optional[str] = None,
|
|
@@ -483,28 +721,24 @@ def View(
|
|
|
483
721
|
ref: Optional[Dict[str, Any]] = None,
|
|
484
722
|
key: Optional[str] = None,
|
|
485
723
|
) -> Element:
|
|
486
|
-
"""Universal flex container (like React Native's
|
|
724
|
+
"""Universal flex container (like React Native's ``View``).
|
|
487
725
|
|
|
488
|
-
Defaults to
|
|
726
|
+
Defaults to ``flex_direction: "column"`` (override via ``style``).
|
|
489
727
|
|
|
490
|
-
|
|
491
|
-
pn.View(child_a, child_b, style={"flex_direction": "row"})
|
|
492
|
-
```
|
|
728
|
+
Flex container properties (passed via ``style``):
|
|
493
729
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
`shadow_opacity`, `shadow_radius`, `elevation`, `opacity`,
|
|
507
|
-
`transform`.
|
|
730
|
+
- ``flex_direction``: ``"column"`` (default), ``"row"``,
|
|
731
|
+
``"column_reverse"``, ``"row_reverse"``.
|
|
732
|
+
- ``justify_content``: main-axis distribution. Accepts
|
|
733
|
+
``"flex_start"`` (default), ``"center"``, ``"flex_end"``,
|
|
734
|
+
``"space_between"``, ``"space_around"``, ``"space_evenly"``.
|
|
735
|
+
- ``align_items``: cross-axis alignment. Accepts ``"stretch"``
|
|
736
|
+
(default), ``"flex_start"``, ``"center"``, ``"flex_end"``.
|
|
737
|
+
- ``overflow``: ``"visible"`` (default) or ``"hidden"``.
|
|
738
|
+
- ``spacing``, ``padding``, ``background_color``, ``border_radius``,
|
|
739
|
+
``border_width``, ``border_color``, ``shadow_color``,
|
|
740
|
+
``shadow_offset``, ``shadow_opacity``, ``shadow_radius``,
|
|
741
|
+
``elevation``, ``opacity``, ``transform``.
|
|
508
742
|
|
|
509
743
|
Args:
|
|
510
744
|
*children: Child elements rendered inside the container.
|
|
@@ -513,44 +747,37 @@ def View(
|
|
|
513
747
|
accessibility_hint: Spoken extra detail (iOS only).
|
|
514
748
|
accessibility_role: Semantic role for assistive tech.
|
|
515
749
|
accessible: Override whether the element is exposed to AT.
|
|
516
|
-
ref: Optional ``use_ref()`` dict
|
|
517
|
-
``ref["current"]`` with the underlying native view.
|
|
750
|
+
ref: Optional ``use_ref()`` dict.
|
|
518
751
|
key: Stable identity for keyed reconciliation.
|
|
519
752
|
|
|
520
753
|
Returns:
|
|
521
|
-
An [`Element`][pythonnative.Element] of type
|
|
754
|
+
An [`Element`][pythonnative.Element] of type ``"View"``.
|
|
522
755
|
"""
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
756
|
+
return _make_element(
|
|
757
|
+
"View",
|
|
758
|
+
*children,
|
|
759
|
+
style=style,
|
|
760
|
+
ref=ref,
|
|
761
|
+
key=key,
|
|
762
|
+
accessibility_label=accessibility_label,
|
|
763
|
+
accessibility_hint=accessibility_hint,
|
|
764
|
+
accessibility_role=accessibility_role,
|
|
765
|
+
accessible=accessible,
|
|
766
|
+
_defaults={"flex_direction": "column"},
|
|
767
|
+
)
|
|
529
768
|
|
|
530
769
|
|
|
531
770
|
def Column(
|
|
532
771
|
*children: Element,
|
|
533
|
-
style:
|
|
772
|
+
style: StyleProp = None,
|
|
534
773
|
ref: Optional[Dict[str, Any]] = None,
|
|
535
774
|
key: Optional[str] = None,
|
|
536
775
|
) -> Element:
|
|
537
776
|
"""Arrange children vertically.
|
|
538
777
|
|
|
539
778
|
Convenience wrapper around [`View`][pythonnative.View] with
|
|
540
|
-
|
|
541
|
-
need to switch between row and column at runtime.
|
|
542
|
-
|
|
543
|
-
Style properties: `spacing`, `padding`, `align_items`,
|
|
544
|
-
`justify_content`, `background_color`, `overflow`, plus the common
|
|
545
|
-
layout props.
|
|
546
|
-
|
|
547
|
-
`align_items` controls cross-axis (horizontal) alignment:
|
|
548
|
-
`"stretch"` (default), `"flex_start"` / `"leading"`, `"center"`, or
|
|
549
|
-
`"flex_end"` / `"trailing"`.
|
|
550
|
-
|
|
551
|
-
`justify_content` controls main-axis (vertical) distribution:
|
|
552
|
-
`"flex_start"` (default), `"center"`, `"flex_end"`,
|
|
553
|
-
`"space_between"`, `"space_around"`, `"space_evenly"`.
|
|
779
|
+
``flex_direction`` locked to ``"column"``. Use ``View`` directly if
|
|
780
|
+
you need to switch between row and column at runtime.
|
|
554
781
|
|
|
555
782
|
Args:
|
|
556
783
|
*children: Child elements stacked top to bottom.
|
|
@@ -559,39 +786,29 @@ def Column(
|
|
|
559
786
|
key: Stable identity for keyed reconciliation.
|
|
560
787
|
|
|
561
788
|
Returns:
|
|
562
|
-
An [`Element`][pythonnative.Element] of type
|
|
789
|
+
An [`Element`][pythonnative.Element] of type ``"Column"``.
|
|
563
790
|
"""
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
791
|
+
return _make_element(
|
|
792
|
+
"Column",
|
|
793
|
+
*children,
|
|
794
|
+
style=style,
|
|
795
|
+
ref=ref,
|
|
796
|
+
key=key,
|
|
797
|
+
_forced={"flex_direction": "column"},
|
|
798
|
+
)
|
|
570
799
|
|
|
571
800
|
|
|
572
801
|
def Row(
|
|
573
802
|
*children: Element,
|
|
574
|
-
style:
|
|
803
|
+
style: StyleProp = None,
|
|
575
804
|
ref: Optional[Dict[str, Any]] = None,
|
|
576
805
|
key: Optional[str] = None,
|
|
577
806
|
) -> Element:
|
|
578
807
|
"""Arrange children horizontally.
|
|
579
808
|
|
|
580
809
|
Convenience wrapper around [`View`][pythonnative.View] with
|
|
581
|
-
|
|
582
|
-
to switch between row and column at runtime.
|
|
583
|
-
|
|
584
|
-
Style properties: `spacing`, `padding`, `align_items`,
|
|
585
|
-
`justify_content`, `background_color`, `overflow`, plus the common
|
|
586
|
-
layout props.
|
|
587
|
-
|
|
588
|
-
`align_items` controls cross-axis (vertical) alignment:
|
|
589
|
-
`"stretch"` (default), `"flex_start"` / `"top"`, `"center"`, or
|
|
590
|
-
`"flex_end"` / `"bottom"`.
|
|
591
|
-
|
|
592
|
-
`justify_content` controls main-axis (horizontal) distribution:
|
|
593
|
-
`"flex_start"` (default), `"center"`, `"flex_end"`,
|
|
594
|
-
`"space_between"`, `"space_around"`, `"space_evenly"`.
|
|
810
|
+
``flex_direction`` locked to ``"row"``. Use ``View`` directly if you
|
|
811
|
+
need to switch between row and column at runtime.
|
|
595
812
|
|
|
596
813
|
Args:
|
|
597
814
|
*children: Child elements arranged left to right.
|
|
@@ -600,54 +817,62 @@ def Row(
|
|
|
600
817
|
key: Stable identity for keyed reconciliation.
|
|
601
818
|
|
|
602
819
|
Returns:
|
|
603
|
-
An [`Element`][pythonnative.Element] of type
|
|
820
|
+
An [`Element`][pythonnative.Element] of type ``"Row"``.
|
|
604
821
|
"""
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
822
|
+
return _make_element(
|
|
823
|
+
"Row",
|
|
824
|
+
*children,
|
|
825
|
+
style=style,
|
|
826
|
+
ref=ref,
|
|
827
|
+
key=key,
|
|
828
|
+
_forced={"flex_direction": "row"},
|
|
829
|
+
)
|
|
611
830
|
|
|
612
831
|
|
|
613
832
|
def ScrollView(
|
|
614
|
-
|
|
615
|
-
*,
|
|
833
|
+
*children: Element,
|
|
616
834
|
refresh_control: Optional[Dict[str, Any]] = None,
|
|
617
|
-
|
|
835
|
+
scroll_axis: Optional[Literal["vertical", "horizontal"]] = None,
|
|
836
|
+
style: StyleProp = None,
|
|
618
837
|
ref: Optional[Dict[str, Any]] = None,
|
|
619
838
|
key: Optional[str] = None,
|
|
620
839
|
) -> Element:
|
|
621
|
-
"""Wrap
|
|
840
|
+
"""Wrap children in a scrollable container.
|
|
841
|
+
|
|
842
|
+
``ScrollView`` typically takes a single child (a ``Column`` or
|
|
843
|
+
``Row`` aggregating the scrollable content). It accepts ``*children``
|
|
844
|
+
for ergonomic call sites; the underlying native scroll view stacks
|
|
845
|
+
them on its content axis.
|
|
622
846
|
|
|
623
847
|
Args:
|
|
624
|
-
|
|
625
|
-
[`Column`][pythonnative.Column] or
|
|
626
|
-
[`Row`][pythonnative.Row] first.
|
|
848
|
+
*children: Child elements to scroll.
|
|
627
849
|
refresh_control: Optional pull-to-refresh spec, typically
|
|
628
850
|
constructed via
|
|
629
851
|
[`RefreshControl`][pythonnative.RefreshControl]. The dict
|
|
630
|
-
must have ``refreshing`` (bool) and ``on_refresh``
|
|
852
|
+
must have ``refreshing`` (bool) and ``on_refresh``
|
|
853
|
+
(callable).
|
|
854
|
+
scroll_axis: ``"vertical"`` (default) or ``"horizontal"``.
|
|
631
855
|
style: Style dict (or list of dicts).
|
|
632
856
|
ref: Optional ``use_ref()`` dict.
|
|
633
857
|
key: Stable identity for keyed reconciliation.
|
|
634
858
|
|
|
635
859
|
Returns:
|
|
636
|
-
An [`Element`][pythonnative.Element] of type
|
|
860
|
+
An [`Element`][pythonnative.Element] of type ``"ScrollView"``.
|
|
637
861
|
"""
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
862
|
+
return _make_element(
|
|
863
|
+
"ScrollView",
|
|
864
|
+
*children,
|
|
865
|
+
style=style,
|
|
866
|
+
ref=ref,
|
|
867
|
+
key=key,
|
|
868
|
+
refresh_control=refresh_control,
|
|
869
|
+
scroll_axis=scroll_axis,
|
|
870
|
+
)
|
|
646
871
|
|
|
647
872
|
|
|
648
873
|
def SafeAreaView(
|
|
649
874
|
*children: Element,
|
|
650
|
-
style:
|
|
875
|
+
style: StyleProp = None,
|
|
651
876
|
key: Optional[str] = None,
|
|
652
877
|
) -> Element:
|
|
653
878
|
"""Container that respects safe-area insets (notch, status bar, home indicator).
|
|
@@ -658,11 +883,14 @@ def SafeAreaView(
|
|
|
658
883
|
key: Stable identity for keyed reconciliation.
|
|
659
884
|
|
|
660
885
|
Returns:
|
|
661
|
-
An [`Element`][pythonnative.Element] of type
|
|
886
|
+
An [`Element`][pythonnative.Element] of type ``"SafeAreaView"``.
|
|
662
887
|
"""
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
888
|
+
return _make_element(
|
|
889
|
+
"SafeAreaView",
|
|
890
|
+
*children,
|
|
891
|
+
style=style,
|
|
892
|
+
key=key,
|
|
893
|
+
)
|
|
666
894
|
|
|
667
895
|
|
|
668
896
|
def Modal(
|
|
@@ -670,28 +898,28 @@ def Modal(
|
|
|
670
898
|
visible: bool = False,
|
|
671
899
|
on_dismiss: Optional[Callable[[], None]] = None,
|
|
672
900
|
title: Optional[str] = None,
|
|
673
|
-
animation_type:
|
|
901
|
+
animation_type: Literal["slide", "fade", "none"] = "slide",
|
|
674
902
|
transparent: bool = False,
|
|
675
|
-
style:
|
|
903
|
+
style: StyleProp = None,
|
|
676
904
|
key: Optional[str] = None,
|
|
677
905
|
) -> Element:
|
|
678
906
|
"""Overlay modal dialog backed by a real native presentation.
|
|
679
907
|
|
|
680
|
-
The modal is shown when
|
|
681
|
-
Drive
|
|
908
|
+
The modal is shown when ``visible=True`` and hidden when ``False``.
|
|
909
|
+
Drive ``visible`` from a hook so the parent component can dismiss
|
|
682
910
|
the modal in response to user actions. On iOS this presents a
|
|
683
|
-
|
|
911
|
+
``UIViewController``; on Android it shows an ``android.app.Dialog``.
|
|
684
912
|
|
|
685
913
|
Children are mounted as the modal's content view, not into the
|
|
686
|
-
on-tree placeholder, so they appear above all other native
|
|
687
|
-
|
|
914
|
+
on-tree placeholder, so they appear above all other native content
|
|
915
|
+
and don't influence the underlying layout.
|
|
688
916
|
|
|
689
917
|
Args:
|
|
690
918
|
*children: Modal content.
|
|
691
919
|
visible: Controls whether the modal is presented.
|
|
692
920
|
on_dismiss: Callback invoked when the user dismisses the modal
|
|
693
|
-
via system gesture
|
|
694
|
-
title: Optional title
|
|
921
|
+
via system gesture.
|
|
922
|
+
title: Optional title-bar text.
|
|
695
923
|
animation_type: ``"slide"`` (default), ``"fade"``, or ``"none"``.
|
|
696
924
|
transparent: When ``True``, the underlying view is dimmed
|
|
697
925
|
instead of fully covered.
|
|
@@ -699,91 +927,152 @@ def Modal(
|
|
|
699
927
|
key: Stable identity for keyed reconciliation.
|
|
700
928
|
|
|
701
929
|
Returns:
|
|
702
|
-
An [`Element`][pythonnative.Element] of type
|
|
930
|
+
An [`Element`][pythonnative.Element] of type ``"Modal"``.
|
|
703
931
|
"""
|
|
704
|
-
|
|
705
|
-
"
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
932
|
+
return _make_element(
|
|
933
|
+
"Modal",
|
|
934
|
+
*children,
|
|
935
|
+
style=style,
|
|
936
|
+
key=key,
|
|
937
|
+
visible=visible,
|
|
938
|
+
animation_type=animation_type,
|
|
939
|
+
transparent=transparent,
|
|
940
|
+
on_dismiss=on_dismiss,
|
|
941
|
+
title=title,
|
|
942
|
+
)
|
|
715
943
|
|
|
716
944
|
|
|
717
945
|
def Pressable(
|
|
718
|
-
|
|
719
|
-
*,
|
|
946
|
+
*children: Element,
|
|
720
947
|
on_press: Optional[Callable[[], None]] = None,
|
|
721
948
|
on_long_press: Optional[Callable[[], None]] = None,
|
|
722
949
|
pressed_opacity: float = 0.6,
|
|
723
|
-
style:
|
|
950
|
+
style: StyleProp = None,
|
|
724
951
|
accessibility_label: Optional[str] = None,
|
|
725
952
|
accessibility_hint: Optional[str] = None,
|
|
953
|
+
accessibility_role: Optional[str] = None,
|
|
726
954
|
accessible: Optional[bool] = None,
|
|
727
955
|
key: Optional[str] = None,
|
|
728
956
|
) -> Element:
|
|
729
|
-
"""Wrap
|
|
957
|
+
"""Wrap children with tap and long-press handlers.
|
|
730
958
|
|
|
731
959
|
Useful for making non-button elements (text, images, custom views)
|
|
732
960
|
respond to user taps. The wrapper view fades to ``pressed_opacity``
|
|
733
|
-
on touch-down and back to full opacity on touch-up
|
|
734
|
-
|
|
961
|
+
on touch-down and back to full opacity on touch-up.
|
|
962
|
+
|
|
963
|
+
Pressable gets ``accessibility_role="button"`` by default.
|
|
735
964
|
|
|
736
965
|
Args:
|
|
737
|
-
|
|
966
|
+
*children: Elements to make pressable.
|
|
738
967
|
on_press: Callback invoked on a normal tap.
|
|
739
968
|
on_long_press: Callback invoked on a sustained press.
|
|
740
|
-
pressed_opacity: Opacity (0
|
|
741
|
-
|
|
742
|
-
feedback.
|
|
969
|
+
pressed_opacity: Opacity (0–1) applied while the user's finger
|
|
970
|
+
is down. Set to ``1.0`` for no visual feedback.
|
|
743
971
|
style: Style dict applied to the wrapper.
|
|
744
972
|
accessibility_label: Spoken description for screen readers.
|
|
745
973
|
accessibility_hint: Spoken extra detail (iOS only).
|
|
974
|
+
accessibility_role: Override the default ``"button"`` role.
|
|
746
975
|
accessible: Override whether the element is exposed to AT.
|
|
747
976
|
key: Stable identity for keyed reconciliation.
|
|
748
977
|
|
|
749
978
|
Returns:
|
|
750
|
-
An [`Element`][pythonnative.Element] of type
|
|
979
|
+
An [`Element`][pythonnative.Element] of type ``"Pressable"``.
|
|
751
980
|
"""
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
981
|
+
return _make_element(
|
|
982
|
+
"Pressable",
|
|
983
|
+
*children,
|
|
984
|
+
style=style,
|
|
985
|
+
key=key,
|
|
986
|
+
on_press=on_press,
|
|
987
|
+
on_long_press=on_long_press,
|
|
988
|
+
pressed_opacity=pressed_opacity,
|
|
989
|
+
accessibility_label=accessibility_label,
|
|
990
|
+
accessibility_hint=accessibility_hint,
|
|
991
|
+
accessibility_role=accessibility_role,
|
|
992
|
+
accessible=accessible,
|
|
993
|
+
_defaults={"accessibility_role": "button"},
|
|
994
|
+
)
|
|
995
|
+
|
|
996
|
+
|
|
997
|
+
# ======================================================================
|
|
998
|
+
# Fragment
|
|
999
|
+
# ======================================================================
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
def Fragment(*children: Optional[Element], key: Optional[str] = None) -> Element:
|
|
1003
|
+
"""Group children without adding a wrapping native view.
|
|
1004
|
+
|
|
1005
|
+
Like React's ``<></>``: returns multiple elements from a component
|
|
1006
|
+
without introducing an extra container. The reconciler flattens
|
|
1007
|
+
Fragment elements at the children-list level, so each child appears
|
|
1008
|
+
as a direct sibling of the Fragment's parent in the native tree.
|
|
1009
|
+
|
|
1010
|
+
Useful inside [`Provider`][pythonnative.Provider] /
|
|
1011
|
+
[`memo`][pythonnative.memo] / conditional logic when grouping
|
|
1012
|
+
siblings inside another component's child list:
|
|
1013
|
+
|
|
1014
|
+
```python
|
|
1015
|
+
pn.Column(
|
|
1016
|
+
pn.Text("Top"),
|
|
1017
|
+
pn.Fragment(
|
|
1018
|
+
pn.Text("Middle A"),
|
|
1019
|
+
pn.Text("Middle B"),
|
|
1020
|
+
),
|
|
1021
|
+
pn.Text("Bottom"),
|
|
1022
|
+
)
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
Args:
|
|
1026
|
+
*children: Child elements to expose at the parent level. ``None``
|
|
1027
|
+
children are dropped, which makes conditional rendering with
|
|
1028
|
+
``cond and pn.Text(...)`` ergonomic.
|
|
1029
|
+
key: Optional key for the Fragment itself (rarely useful since
|
|
1030
|
+
Fragment doesn't appear in the native tree).
|
|
1031
|
+
|
|
1032
|
+
Returns:
|
|
1033
|
+
An [`Element`][pythonnative.Element] of type ``"__Fragment__"``.
|
|
1034
|
+
|
|
1035
|
+
Note:
|
|
1036
|
+
Today, returning a Fragment from a ``@pn.component`` function
|
|
1037
|
+
only mounts its first child as the component's root. To return
|
|
1038
|
+
multiple top-level elements from a function component, use a
|
|
1039
|
+
container such as [`Column`][pythonnative.Column] or
|
|
1040
|
+
[`Row`][pythonnative.Row] instead.
|
|
1041
|
+
"""
|
|
1042
|
+
filtered = [c for c in children if c is not None]
|
|
1043
|
+
return Element("__Fragment__", {}, filtered, key=key)
|
|
1044
|
+
|
|
1045
|
+
|
|
1046
|
+
# ======================================================================
|
|
1047
|
+
# Error boundary
|
|
1048
|
+
# ======================================================================
|
|
765
1049
|
|
|
766
1050
|
|
|
767
1051
|
def ErrorBoundary(
|
|
768
|
-
|
|
769
|
-
*,
|
|
1052
|
+
*children: Element,
|
|
770
1053
|
fallback: Optional[Any] = None,
|
|
771
1054
|
key: Optional[str] = None,
|
|
772
1055
|
) -> Element:
|
|
773
|
-
"""Catch render errors in
|
|
1056
|
+
"""Catch render errors in the wrapped subtree and display ``fallback`` instead.
|
|
1057
|
+
|
|
1058
|
+
``fallback`` may be an [`Element`][pythonnative.Element] or a
|
|
1059
|
+
callable that receives the exception and returns an ``Element``.
|
|
1060
|
+
Useful for isolating risky subtrees so a single failure doesn't
|
|
1061
|
+
crash the page.
|
|
774
1062
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
1063
|
+
When multiple children are passed they're grouped under a
|
|
1064
|
+
[`Fragment`][pythonnative.Fragment] so the boundary still wraps a
|
|
1065
|
+
single logical subtree.
|
|
778
1066
|
|
|
779
1067
|
Args:
|
|
780
|
-
|
|
781
|
-
fallback: Element
|
|
782
|
-
or a callable
|
|
1068
|
+
*children: Subtree to wrap.
|
|
1069
|
+
fallback: Element rendered when the subtree raises during
|
|
1070
|
+
render, or a callable ``fallback(err) -> Element``.
|
|
783
1071
|
key: Stable identity for keyed reconciliation.
|
|
784
1072
|
|
|
785
1073
|
Returns:
|
|
786
|
-
An [`Element`][pythonnative.Element] of type
|
|
1074
|
+
An [`Element`][pythonnative.Element] of type
|
|
1075
|
+
``"__ErrorBoundary__"``.
|
|
787
1076
|
|
|
788
1077
|
Example:
|
|
789
1078
|
```python
|
|
@@ -798,8 +1087,16 @@ def ErrorBoundary(
|
|
|
798
1087
|
props: Dict[str, Any] = {}
|
|
799
1088
|
if fallback is not None:
|
|
800
1089
|
props["__fallback__"] = fallback
|
|
801
|
-
|
|
802
|
-
|
|
1090
|
+
if len(children) <= 1:
|
|
1091
|
+
kids = list(children)
|
|
1092
|
+
else:
|
|
1093
|
+
kids = [Fragment(*children)]
|
|
1094
|
+
return Element("__ErrorBoundary__", props, kids, key=key)
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
# ======================================================================
|
|
1098
|
+
# Lists
|
|
1099
|
+
# ======================================================================
|
|
803
1100
|
|
|
804
1101
|
|
|
805
1102
|
def FlatList(
|
|
@@ -811,20 +1108,21 @@ def FlatList(
|
|
|
811
1108
|
separator_height: float = 0,
|
|
812
1109
|
refresh_control: Optional[Dict[str, Any]] = None,
|
|
813
1110
|
on_item_press: Optional[Callable[[int], None]] = None,
|
|
814
|
-
style:
|
|
1111
|
+
style: StyleProp = None,
|
|
815
1112
|
key: Optional[str] = None,
|
|
816
1113
|
) -> Element:
|
|
817
|
-
"""Virtualized scrollable list that renders items from
|
|
1114
|
+
"""Virtualized scrollable list that renders items from ``data`` lazily.
|
|
818
1115
|
|
|
819
|
-
Backed by
|
|
820
|
-
|
|
821
|
-
|
|
1116
|
+
Backed by ``UITableView`` on iOS and ``RecyclerView`` on Android via
|
|
1117
|
+
the ``VirtualList`` element. Each visible row is mounted on demand
|
|
1118
|
+
by a nested
|
|
1119
|
+
[`Reconciler`][pythonnative.reconciler.Reconciler] when
|
|
822
1120
|
``item_height`` is specified.
|
|
823
1121
|
|
|
824
1122
|
When ``item_height`` is omitted the implementation falls back to an
|
|
825
1123
|
eager (non-virtualized) ``ScrollView`` of every row — keep the data
|
|
826
|
-
set small in that mode (the fallback is convenient for short
|
|
827
|
-
|
|
1124
|
+
set small in that mode (the fallback is convenient for short lists
|
|
1125
|
+
where virtualization overhead would dominate).
|
|
828
1126
|
|
|
829
1127
|
Args:
|
|
830
1128
|
data: Iterable of arbitrary item values.
|
|
@@ -844,11 +1142,12 @@ def FlatList(
|
|
|
844
1142
|
on_item_press: Callback invoked with the row index when the
|
|
845
1143
|
user taps a row (virtualized backend only).
|
|
846
1144
|
style: Style dict (or list of dicts).
|
|
847
|
-
key: Stable identity for keyed reconciliation of the list
|
|
1145
|
+
key: Stable identity for keyed reconciliation of the list
|
|
1146
|
+
itself.
|
|
848
1147
|
|
|
849
1148
|
Returns:
|
|
850
|
-
An [`Element`][pythonnative.Element] of type
|
|
851
|
-
(virtualized) or
|
|
1149
|
+
An [`Element`][pythonnative.Element] of type ``"VirtualList"``
|
|
1150
|
+
(virtualized) or ``"ScrollView"`` (eager fallback).
|
|
852
1151
|
|
|
853
1152
|
Example:
|
|
854
1153
|
```python
|
|
@@ -875,11 +1174,7 @@ def FlatList(
|
|
|
875
1174
|
el = Element(el.type, el.props, el.children, key=key_extractor(item, i))
|
|
876
1175
|
items_eager.append(el)
|
|
877
1176
|
inner = Column(*items_eager, style={"spacing": separator_height} if separator_height else None)
|
|
878
|
-
|
|
879
|
-
if refresh_control is not None:
|
|
880
|
-
sv_props["refresh_control"] = refresh_control
|
|
881
|
-
sv_props.update(resolve_style(style))
|
|
882
|
-
return Element("ScrollView", sv_props, [inner], key=key)
|
|
1177
|
+
return ScrollView(inner, refresh_control=refresh_control, style=style, key=key)
|
|
883
1178
|
|
|
884
1179
|
# Virtualized path: render_item is invoked lazily by the native
|
|
885
1180
|
# cell mount callback when each row scrolls into view.
|
|
@@ -920,17 +1215,16 @@ def FlatList(
|
|
|
920
1215
|
|
|
921
1216
|
backend.add_child(content_view, native_root, "View")
|
|
922
1217
|
|
|
923
|
-
|
|
924
|
-
"
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
return Element("VirtualList", list_props, [], key=key)
|
|
1218
|
+
return _make_element(
|
|
1219
|
+
"VirtualList",
|
|
1220
|
+
style=style,
|
|
1221
|
+
key=key,
|
|
1222
|
+
count=len(items_list),
|
|
1223
|
+
row_height=row_h,
|
|
1224
|
+
mount_row=_mount_row,
|
|
1225
|
+
on_row_press=on_item_press,
|
|
1226
|
+
refresh_control=refresh_control,
|
|
1227
|
+
)
|
|
934
1228
|
|
|
935
1229
|
|
|
936
1230
|
def SectionList(
|
|
@@ -941,7 +1235,7 @@ def SectionList(
|
|
|
941
1235
|
item_height: Optional[float] = None,
|
|
942
1236
|
section_header_height: float = 32.0,
|
|
943
1237
|
separator_height: float = 0,
|
|
944
|
-
style:
|
|
1238
|
+
style: StyleProp = None,
|
|
945
1239
|
key: Optional[str] = None,
|
|
946
1240
|
) -> Element:
|
|
947
1241
|
"""Virtualized list that supports section headers.
|
|
@@ -953,8 +1247,10 @@ def SectionList(
|
|
|
953
1247
|
|
|
954
1248
|
Args:
|
|
955
1249
|
sections: Each section is ``{"title": ..., "data": [...]}``.
|
|
956
|
-
render_item: ``render_item(item, item_index, section_index) ->
|
|
957
|
-
|
|
1250
|
+
render_item: ``render_item(item, item_index, section_index) ->
|
|
1251
|
+
Element``.
|
|
1252
|
+
render_section_header: ``render_section_header(section,
|
|
1253
|
+
section_index) -> Element``.
|
|
958
1254
|
item_height: Fixed row height for items, in layout units.
|
|
959
1255
|
section_header_height: Fixed header height in layout units.
|
|
960
1256
|
separator_height: Gap appended below each item, in layout units.
|
|
@@ -962,9 +1258,9 @@ def SectionList(
|
|
|
962
1258
|
key: Stable identity for keyed reconciliation.
|
|
963
1259
|
|
|
964
1260
|
Returns:
|
|
965
|
-
An [`Element`][pythonnative.Element] of type
|
|
966
|
-
(virtualized). When ``item_height`` is omitted the layout
|
|
967
|
-
|
|
1261
|
+
An [`Element`][pythonnative.Element] of type ``"VirtualList"``
|
|
1262
|
+
(virtualized). When ``item_height`` is omitted the layout falls
|
|
1263
|
+
back to an eager column.
|
|
968
1264
|
"""
|
|
969
1265
|
sections_list = list(sections or [])
|
|
970
1266
|
|
|
@@ -989,9 +1285,7 @@ def SectionList(
|
|
|
989
1285
|
else:
|
|
990
1286
|
children.append(Text(str(entry["item"])))
|
|
991
1287
|
inner = Column(*children, style={"spacing": separator_height} if separator_height else None)
|
|
992
|
-
|
|
993
|
-
sv_props.update(resolve_style(style))
|
|
994
|
-
return Element("ScrollView", sv_props, [inner], key=key)
|
|
1288
|
+
return ScrollView(inner, style=style, key=key)
|
|
995
1289
|
|
|
996
1290
|
# Virtualized: mixed row heights aren't supported in v1, so we
|
|
997
1291
|
# use the larger of section_header_height and item_height + sep.
|
|
@@ -1024,24 +1318,25 @@ def SectionList(
|
|
|
1024
1318
|
except Exception:
|
|
1025
1319
|
pass
|
|
1026
1320
|
|
|
1027
|
-
|
|
1028
|
-
"
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1321
|
+
return _make_element(
|
|
1322
|
+
"VirtualList",
|
|
1323
|
+
style=style,
|
|
1324
|
+
key=key,
|
|
1325
|
+
count=len(flat),
|
|
1326
|
+
row_height=row_h,
|
|
1327
|
+
mount_row=_mount_row,
|
|
1328
|
+
)
|
|
1034
1329
|
|
|
1035
1330
|
|
|
1036
1331
|
# ======================================================================
|
|
1037
|
-
#
|
|
1332
|
+
# StatusBar / KeyboardAvoidingView / RefreshControl / Picker
|
|
1038
1333
|
# ======================================================================
|
|
1039
1334
|
|
|
1040
1335
|
|
|
1041
1336
|
def StatusBar(
|
|
1042
1337
|
*,
|
|
1043
|
-
|
|
1044
|
-
background_color: Optional[
|
|
1338
|
+
bar_style: Optional[Literal["light", "dark", "default"]] = None,
|
|
1339
|
+
background_color: Optional[Color] = None,
|
|
1045
1340
|
hidden: Optional[bool] = None,
|
|
1046
1341
|
key: Optional[str] = None,
|
|
1047
1342
|
) -> Element:
|
|
@@ -1051,8 +1346,13 @@ def StatusBar(
|
|
|
1051
1346
|
content but applies its props to the host platform's status bar.
|
|
1052
1347
|
Mount one near the top of your tree.
|
|
1053
1348
|
|
|
1349
|
+
The ``bar_style`` parameter is named separately from the universal
|
|
1350
|
+
``style`` kwarg (which is unused here) to avoid the conflict that
|
|
1351
|
+
``style="light"`` would create with the visual-style dict used
|
|
1352
|
+
elsewhere.
|
|
1353
|
+
|
|
1054
1354
|
Args:
|
|
1055
|
-
|
|
1355
|
+
bar_style: ``"light"`` (light icons over dark backgrounds),
|
|
1056
1356
|
``"dark"`` (dark icons over light backgrounds), or
|
|
1057
1357
|
``"default"`` (system default).
|
|
1058
1358
|
background_color: Color of the status-bar background (Android
|
|
@@ -1061,11 +1361,11 @@ def StatusBar(
|
|
|
1061
1361
|
key: Stable identity for keyed reconciliation.
|
|
1062
1362
|
|
|
1063
1363
|
Returns:
|
|
1064
|
-
An [`Element`][pythonnative.Element] of type
|
|
1364
|
+
An [`Element`][pythonnative.Element] of type ``"StatusBar"``.
|
|
1065
1365
|
"""
|
|
1066
1366
|
props: Dict[str, Any] = {}
|
|
1067
|
-
if
|
|
1068
|
-
props["
|
|
1367
|
+
if bar_style is not None:
|
|
1368
|
+
props["bar_style"] = bar_style
|
|
1069
1369
|
if background_color is not None:
|
|
1070
1370
|
props["background_color"] = background_color
|
|
1071
1371
|
if hidden is not None:
|
|
@@ -1075,16 +1375,16 @@ def StatusBar(
|
|
|
1075
1375
|
|
|
1076
1376
|
def KeyboardAvoidingView(
|
|
1077
1377
|
*children: Element,
|
|
1078
|
-
behavior:
|
|
1079
|
-
style:
|
|
1378
|
+
behavior: Literal["padding", "position"] = "padding",
|
|
1379
|
+
style: StyleProp = None,
|
|
1080
1380
|
key: Optional[str] = None,
|
|
1081
1381
|
) -> Element:
|
|
1082
1382
|
"""Wrap content that should shift up when the keyboard is shown.
|
|
1083
1383
|
|
|
1084
1384
|
Subscribes to the platform-reported keyboard height (via
|
|
1085
1385
|
[`use_keyboard_height`][pythonnative.use_keyboard_height]
|
|
1086
|
-
internally) and applies it as bottom padding so the focused
|
|
1087
|
-
|
|
1386
|
+
internally) and applies it as bottom padding so the focused text
|
|
1387
|
+
input stays visible.
|
|
1088
1388
|
|
|
1089
1389
|
Args:
|
|
1090
1390
|
*children: Children rendered inside the avoiding container.
|
|
@@ -1095,32 +1395,36 @@ def KeyboardAvoidingView(
|
|
|
1095
1395
|
|
|
1096
1396
|
Returns:
|
|
1097
1397
|
An [`Element`][pythonnative.Element] of type
|
|
1098
|
-
|
|
1398
|
+
``"KeyboardAvoidingView"``.
|
|
1099
1399
|
"""
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1400
|
+
return _make_element(
|
|
1401
|
+
"KeyboardAvoidingView",
|
|
1402
|
+
*children,
|
|
1403
|
+
style=style,
|
|
1404
|
+
key=key,
|
|
1405
|
+
behavior=behavior,
|
|
1406
|
+
)
|
|
1103
1407
|
|
|
1104
1408
|
|
|
1105
1409
|
def RefreshControl(
|
|
1106
1410
|
*,
|
|
1107
1411
|
refreshing: bool = False,
|
|
1108
1412
|
on_refresh: Optional[Callable[[], None]] = None,
|
|
1109
|
-
tint_color: Optional[
|
|
1413
|
+
tint_color: Optional[Color] = None,
|
|
1110
1414
|
) -> Dict[str, Any]:
|
|
1111
1415
|
"""Pull-to-refresh spec for [`ScrollView`][pythonnative.ScrollView] / [`FlatList`][pythonnative.FlatList].
|
|
1112
1416
|
|
|
1113
1417
|
Returns a plain dict that should be passed as the
|
|
1114
|
-
``refresh_control=`` prop. Modeled as a dict (not an
|
|
1115
|
-
the host scroll container can
|
|
1116
|
-
child node.
|
|
1418
|
+
``refresh_control=`` prop. Modeled as a dict (not an
|
|
1419
|
+
[`Element`][pythonnative.Element]) so the host scroll container can
|
|
1420
|
+
hold one without it appearing as a child node.
|
|
1117
1421
|
|
|
1118
1422
|
Args:
|
|
1119
1423
|
refreshing: Drive the spinner's visibility from a use_state
|
|
1120
1424
|
value.
|
|
1121
|
-
on_refresh: Callback invoked when the user pulls down past
|
|
1122
|
-
|
|
1123
|
-
|
|
1425
|
+
on_refresh: Callback invoked when the user pulls down past the
|
|
1426
|
+
threshold. Set ``refreshing`` to ``True`` for the duration
|
|
1427
|
+
of the work, then back to ``False`` on completion.
|
|
1124
1428
|
tint_color: Color of the spinner.
|
|
1125
1429
|
|
|
1126
1430
|
Returns:
|
|
@@ -1162,54 +1466,50 @@ def Picker(
|
|
|
1162
1466
|
items: Optional[List[Dict[str, Any]]] = None,
|
|
1163
1467
|
on_change: Optional[Callable[[Any], None]] = None,
|
|
1164
1468
|
placeholder: str = "Select…",
|
|
1165
|
-
style:
|
|
1469
|
+
style: StyleProp = None,
|
|
1470
|
+
accessibility_label: Optional[str] = None,
|
|
1471
|
+
accessibility_hint: Optional[str] = None,
|
|
1472
|
+
accessible: Optional[bool] = None,
|
|
1473
|
+
ref: Optional[Dict[str, Any]] = None,
|
|
1166
1474
|
key: Optional[str] = None,
|
|
1167
1475
|
) -> Element:
|
|
1168
|
-
"""A
|
|
1476
|
+
"""A real native dropdown / select widget.
|
|
1477
|
+
|
|
1478
|
+
Renders a tappable trigger labelled with the selected item; the
|
|
1479
|
+
iOS handler attaches a ``UIMenu`` (system dropdown) and the Android
|
|
1480
|
+
handler uses a native ``Spinner``. Selecting an item fires
|
|
1481
|
+
``on_change(value)``.
|
|
1169
1482
|
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
[`Alert`][pythonnative.Alert]-style action sheet listing the
|
|
1173
|
-
options. Selecting an option fires ``on_change(value)``.
|
|
1483
|
+
``items`` is an ordered list of ``{"value": Any, "label": str}``
|
|
1484
|
+
entries (``label`` defaults to ``str(value)`` when omitted).
|
|
1174
1485
|
|
|
1175
1486
|
Args:
|
|
1176
1487
|
value: Currently selected value (matched against
|
|
1177
1488
|
``items[i]["value"]``).
|
|
1178
|
-
items:
|
|
1179
|
-
on_change: Callback invoked with the
|
|
1180
|
-
placeholder: Label shown when
|
|
1181
|
-
style: Style dict applied to the trigger
|
|
1489
|
+
items: Selectable options.
|
|
1490
|
+
on_change: Callback invoked with the new value.
|
|
1491
|
+
placeholder: Label shown when no item matches ``value``.
|
|
1492
|
+
style: Style dict applied to the trigger.
|
|
1493
|
+
accessibility_label: Spoken description for screen readers.
|
|
1494
|
+
accessibility_hint: Spoken extra detail (iOS only).
|
|
1495
|
+
accessible: Override whether the element is exposed to AT.
|
|
1496
|
+
ref: Optional ``use_ref()`` dict.
|
|
1182
1497
|
key: Stable identity for keyed reconciliation.
|
|
1183
1498
|
|
|
1184
1499
|
Returns:
|
|
1185
|
-
An [`Element`][pythonnative.Element] of type
|
|
1500
|
+
An [`Element`][pythonnative.Element] of type ``"Picker"``.
|
|
1186
1501
|
"""
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
def _press() -> None:
|
|
1202
|
-
if on_change is not None:
|
|
1203
|
-
try:
|
|
1204
|
-
on_change(item.get("value"))
|
|
1205
|
-
except Exception:
|
|
1206
|
-
pass
|
|
1207
|
-
|
|
1208
|
-
return {"label": str(item.get("label", item.get("value"))), "on_press": _press}
|
|
1209
|
-
|
|
1210
|
-
buttons = [_make_btn(it) for it in items_list]
|
|
1211
|
-
buttons.append({"label": "Cancel", "style": "cancel"})
|
|
1212
|
-
Alert.show(title=placeholder, buttons=buttons, style="action_sheet")
|
|
1213
|
-
|
|
1214
|
-
label_text = Text(selected_label)
|
|
1215
|
-
return Pressable(label_text, on_press=_open, style=style, key=key)
|
|
1502
|
+
return _make_element(
|
|
1503
|
+
"Picker",
|
|
1504
|
+
style=style,
|
|
1505
|
+
ref=ref,
|
|
1506
|
+
key=key,
|
|
1507
|
+
value=value,
|
|
1508
|
+
items=list(items) if items is not None else [],
|
|
1509
|
+
on_change=on_change,
|
|
1510
|
+
placeholder=placeholder,
|
|
1511
|
+
accessibility_label=accessibility_label,
|
|
1512
|
+
accessibility_hint=accessibility_hint,
|
|
1513
|
+
accessible=accessible,
|
|
1514
|
+
_defaults={"accessibility_role": "button"},
|
|
1515
|
+
)
|