pythonnative 0.33.0__py3-none-any.whl → 0.35.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.
Files changed (77) hide show
  1. pythonnative/__init__.py +29 -16
  2. pythonnative/animated.py +7 -13
  3. pythonnative/cli/pn.py +1 -2
  4. pythonnative/component.py +255 -0
  5. pythonnative/components/__init__.py +106 -0
  6. pythonnative/components/_base.py +132 -0
  7. pythonnative/components/controls.py +515 -0
  8. pythonnative/components/layout.py +459 -0
  9. pythonnative/components/lists.py +809 -0
  10. pythonnative/components/media.py +204 -0
  11. pythonnative/components/overlays.py +107 -0
  12. pythonnative/components/pressable.py +252 -0
  13. pythonnative/components/structural.py +167 -0
  14. pythonnative/components/text.py +291 -0
  15. pythonnative/diagnostics.py +1 -1
  16. pythonnative/element.py +108 -29
  17. pythonnative/gestures.py +1 -1
  18. pythonnative/hooks.py +366 -671
  19. pythonnative/hosts/__init__.py +85 -0
  20. pythonnative/hosts/android.py +269 -0
  21. pythonnative/hosts/base.py +665 -0
  22. pythonnative/hosts/desktop.py +107 -0
  23. pythonnative/hosts/ios.py +404 -0
  24. pythonnative/hot_reload.py +16 -24
  25. pythonnative/layout.py +372 -66
  26. pythonnative/native_modules/__init__.py +23 -0
  27. pythonnative/native_modules/net_info.py +5 -1
  28. pythonnative/native_views/__init__.py +1 -1
  29. pythonnative/native_views/android.py +50 -6
  30. pythonnative/native_views/base.py +64 -1
  31. pythonnative/native_views/desktop.py +11 -3
  32. pythonnative/native_views/ios.py +72 -12
  33. pythonnative/navigation/__init__.py +102 -0
  34. pythonnative/navigation/container.py +154 -0
  35. pythonnative/navigation/handle.py +573 -0
  36. pythonnative/navigation/hooks.py +94 -0
  37. pythonnative/navigation/host.py +58 -0
  38. pythonnative/navigation/linking.py +200 -0
  39. pythonnative/navigation/navigators.py +637 -0
  40. pythonnative/navigation/screen.py +149 -0
  41. pythonnative/navigation/state.py +248 -0
  42. pythonnative/platform_metrics.py +1 -1
  43. pythonnative/preview.py +21 -19
  44. pythonnative/project/android.py +7 -1
  45. pythonnative/project/doctor.py +1 -1
  46. pythonnative/project/ios.py +1 -0
  47. pythonnative/project/runtime_assets.py +1 -1
  48. pythonnative/reconciler/__init__.py +29 -0
  49. pythonnative/reconciler/boundaries.py +365 -0
  50. pythonnative/reconciler/children.py +88 -0
  51. pythonnative/reconciler/core.py +1153 -0
  52. pythonnative/reconciler/layout_pass.py +359 -0
  53. pythonnative/reconciler/vnode.py +266 -0
  54. pythonnative/scheduler.py +159 -0
  55. pythonnative/sdk/_components.py +2 -4
  56. pythonnative/style.py +95 -13
  57. pythonnative/suspense.py +8 -12
  58. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +85 -1
  59. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/ScreenFragment.kt +6 -7
  60. pythonnative/templates/android_template/app/src/main/res/navigation/nav_graph.xml +1 -1
  61. pythonnative/templates/android_template/app/src/main/res/values/strings.xml +3 -1
  62. pythonnative/templates/ios_template/ios_template/AppDelegate.swift +33 -0
  63. pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +1 -1
  64. pythonnative/templates/ios_template/ios_template/ViewController.swift +12 -10
  65. pythonnative/testing/__init__.py +53 -0
  66. pythonnative/testing/backend.py +276 -0
  67. pythonnative/testing/harness.py +391 -0
  68. {pythonnative-0.33.0.dist-info → pythonnative-0.35.0.dist-info}/METADATA +2 -1
  69. {pythonnative-0.33.0.dist-info → pythonnative-0.35.0.dist-info}/RECORD +73 -42
  70. pythonnative/components.py +0 -2856
  71. pythonnative/navigation.py +0 -1031
  72. pythonnative/reconciler.py +0 -2298
  73. pythonnative/screen.py +0 -2068
  74. {pythonnative-0.33.0.dist-info → pythonnative-0.35.0.dist-info}/WHEEL +0 -0
  75. {pythonnative-0.33.0.dist-info → pythonnative-0.35.0.dist-info}/entry_points.txt +0 -0
  76. {pythonnative-0.33.0.dist-info → pythonnative-0.35.0.dist-info}/licenses/LICENSE +0 -0
  77. {pythonnative-0.33.0.dist-info → pythonnative-0.35.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,515 @@
1
+ """Form controls and side-effect elements.
2
+
3
+ ``Switch``, ``Slider``, ``ProgressBar``, ``ActivityIndicator``,
4
+ ``Checkbox``, ``SegmentedControl``, ``DatePicker``, ``Picker``, the
5
+ ``RefreshControl`` spec helper, and ``StatusBar``.
6
+ """
7
+
8
+ from typing import Any, Callable, Dict, List, Literal, Optional
9
+
10
+ from ..element import Element
11
+ from ..hooks import Ref
12
+ from ..style import AccessibilityState, Color, StyleProp
13
+ from ._base import _make_element
14
+
15
+
16
+ def Switch(
17
+ *,
18
+ value: bool = False,
19
+ on_change: Optional[Callable[[bool], Any]] = None,
20
+ accessibility_label: Optional[str] = None,
21
+ style: StyleProp = None,
22
+ key: Optional[str] = None,
23
+ ) -> Element:
24
+ """Display a toggle switch.
25
+
26
+ Args:
27
+ value: Current on/off state.
28
+ on_change: Callback invoked with the new boolean state.
29
+ accessibility_label: Label exposed to assistive technology (and
30
+ UI test drivers) for the switch.
31
+ style: Style dict (or list of dicts).
32
+ key: Stable identity for keyed reconciliation.
33
+
34
+ Returns:
35
+ An [`Element`][pythonnative.Element] of type ``"Switch"``.
36
+ """
37
+ return _make_element(
38
+ "Switch",
39
+ style=style,
40
+ key=key,
41
+ value=value,
42
+ on_change=on_change,
43
+ accessibility_label=accessibility_label,
44
+ )
45
+
46
+
47
+ def Slider(
48
+ *,
49
+ value: float = 0.0,
50
+ min_value: float = 0.0,
51
+ max_value: float = 1.0,
52
+ on_change: Optional[Callable[[float], Any]] = None,
53
+ accessibility_label: Optional[str] = None,
54
+ style: StyleProp = None,
55
+ key: Optional[str] = None,
56
+ ) -> Element:
57
+ """Continuous-value slider between ``min_value`` and ``max_value``.
58
+
59
+ Args:
60
+ value: Current slider value.
61
+ min_value: Lower bound.
62
+ max_value: Upper bound.
63
+ on_change: Callback invoked with the new value as the user
64
+ drags.
65
+ accessibility_label: Label exposed to assistive technology (and
66
+ UI test drivers) for the slider.
67
+ style: Style dict (or list of dicts).
68
+ key: Stable identity for keyed reconciliation.
69
+
70
+ Returns:
71
+ An [`Element`][pythonnative.Element] of type ``"Slider"``.
72
+ """
73
+ return _make_element(
74
+ "Slider",
75
+ style=style,
76
+ key=key,
77
+ value=value,
78
+ min_value=min_value,
79
+ max_value=max_value,
80
+ on_change=on_change,
81
+ accessibility_label=accessibility_label,
82
+ )
83
+
84
+
85
+ def ProgressBar(
86
+ *,
87
+ value: float = 0.0,
88
+ color: Optional[Color] = None,
89
+ track_color: Optional[Color] = None,
90
+ indeterminate: bool = False,
91
+ style: StyleProp = None,
92
+ key: Optional[str] = None,
93
+ ) -> Element:
94
+ """Show determinate progress as a value between ``0.0`` and ``1.0``.
95
+
96
+ For a spinner instead of a bar, use
97
+ [`ActivityIndicator`][pythonnative.ActivityIndicator]; for an
98
+ indeterminate *bar* pass ``indeterminate=True``.
99
+
100
+ Args:
101
+ value: Fraction complete (clamped to ``[0.0, 1.0]`` by the
102
+ platform handler).
103
+ color: Color of the filled portion of the bar.
104
+ track_color: Color of the unfilled track behind the fill.
105
+ indeterminate: When ``True``, the bar animates continuously and
106
+ ``value`` is ignored.
107
+ style: Style dict (or list of dicts).
108
+ key: Stable identity for keyed reconciliation.
109
+
110
+ Returns:
111
+ An [`Element`][pythonnative.Element] of type ``"ProgressBar"``.
112
+ """
113
+ return _make_element(
114
+ "ProgressBar",
115
+ style=style,
116
+ key=key,
117
+ value=value,
118
+ color=color,
119
+ track_color=track_color,
120
+ indeterminate=indeterminate or None,
121
+ )
122
+
123
+
124
+ def ActivityIndicator(
125
+ *,
126
+ animating: bool = True,
127
+ color: Optional[Color] = None,
128
+ size: Literal["small", "large"] = "small",
129
+ style: StyleProp = None,
130
+ key: Optional[str] = None,
131
+ ) -> Element:
132
+ """Show an indeterminate loading spinner.
133
+
134
+ Args:
135
+ animating: When ``False``, the spinner is hidden.
136
+ color: Spinner color.
137
+ size: ``"small"`` (default) or ``"large"``.
138
+ style: Style dict (or list of dicts).
139
+ key: Stable identity for keyed reconciliation.
140
+
141
+ Returns:
142
+ An [`Element`][pythonnative.Element] of type
143
+ ``"ActivityIndicator"``.
144
+ """
145
+ return _make_element(
146
+ "ActivityIndicator",
147
+ style=style,
148
+ key=key,
149
+ animating=animating,
150
+ color=color,
151
+ size=size,
152
+ )
153
+
154
+
155
+ def Checkbox(
156
+ *,
157
+ value: bool = False,
158
+ on_change: Optional[Callable[[bool], Any]] = None,
159
+ label: Optional[str] = None,
160
+ disabled: bool = False,
161
+ color: Optional[Color] = None,
162
+ style: StyleProp = None,
163
+ accessibility_label: Optional[str] = None,
164
+ accessibility_hint: Optional[str] = None,
165
+ accessible: Optional[bool] = None,
166
+ accessibility_state: Optional[AccessibilityState] = None,
167
+ accessibility_live_region: Optional[Literal["none", "polite", "assertive"]] = None,
168
+ test_id: Optional[str] = None,
169
+ key: Optional[str] = None,
170
+ ) -> Element:
171
+ """A boolean checkbox with an optional inline label.
172
+
173
+ Backed by ``android.widget.CheckBox`` on Android and a checkmark
174
+ ``UIButton`` on iOS. Tapping the control (or its label) toggles the
175
+ value and fires ``on_change(new_value)``.
176
+
177
+ Args:
178
+ value: Current checked state.
179
+ on_change: Callback invoked with the new boolean state.
180
+ label: Optional text shown beside the box (also tappable).
181
+ disabled: When ``True``, the control is greyed out and inert.
182
+ color: Tint applied to the checked box.
183
+ style: Style dict (or list of dicts).
184
+ accessibility_label: Spoken description for screen readers.
185
+ accessibility_hint: Spoken extra detail (iOS only).
186
+ accessible: Override whether the element is exposed to AT.
187
+ accessibility_state: Current widget state for assistive tech,
188
+ e.g. ``{"disabled": True, "selected": False}``. Recognized
189
+ keys: ``disabled``, ``selected``, ``checked``, ``busy``,
190
+ ``expanded``.
191
+ accessibility_live_region: How AT announces dynamic changes to
192
+ this view: ``"none"``, ``"polite"``, or ``"assertive"``
193
+ (Android only).
194
+ test_id: Stable identifier for UI tests; exposed as
195
+ ``resource-id`` on Android and ``accessibilityIdentifier``
196
+ on iOS.
197
+ key: Stable identity for keyed reconciliation.
198
+
199
+ Returns:
200
+ An [`Element`][pythonnative.Element] of type ``"Checkbox"``.
201
+ """
202
+ return _make_element(
203
+ "Checkbox",
204
+ style=style,
205
+ key=key,
206
+ value=value,
207
+ on_change=on_change,
208
+ label=label,
209
+ disabled=disabled or None,
210
+ color=color,
211
+ accessibility_label=accessibility_label,
212
+ accessibility_hint=accessibility_hint,
213
+ accessible=accessible,
214
+ accessibility_state=accessibility_state,
215
+ accessibility_live_region=accessibility_live_region,
216
+ test_id=test_id,
217
+ _defaults={"accessibility_role": "checkbox"},
218
+ )
219
+
220
+
221
+ def SegmentedControl(
222
+ *,
223
+ segments: Optional[List[str]] = None,
224
+ selected_index: int = 0,
225
+ on_change: Optional[Callable[[int], Any]] = None,
226
+ enabled: bool = True,
227
+ tint_color: Optional[Color] = None,
228
+ style: StyleProp = None,
229
+ accessibility_label: Optional[str] = None,
230
+ accessible: Optional[bool] = None,
231
+ accessibility_state: Optional[AccessibilityState] = None,
232
+ accessibility_live_region: Optional[Literal["none", "polite", "assertive"]] = None,
233
+ test_id: Optional[str] = None,
234
+ key: Optional[str] = None,
235
+ ) -> Element:
236
+ """A horizontal multi-choice control (one selected segment at a time).
237
+
238
+ Backed by ``UISegmentedControl`` on iOS and a styled toggle row on
239
+ Android. Selecting a segment fires ``on_change(index)``.
240
+
241
+ Args:
242
+ segments: Ordered list of segment labels.
243
+ selected_index: Index of the currently selected segment.
244
+ on_change: Callback invoked with the newly selected index.
245
+ enabled: When ``False``, the control is disabled.
246
+ tint_color: Accent color for the selected segment.
247
+ style: Style dict (or list of dicts).
248
+ accessibility_label: Spoken description for screen readers.
249
+ accessible: Override whether the element is exposed to AT.
250
+ accessibility_state: Current widget state for assistive tech,
251
+ e.g. ``{"disabled": True, "selected": False}``. Recognized
252
+ keys: ``disabled``, ``selected``, ``checked``, ``busy``,
253
+ ``expanded``.
254
+ accessibility_live_region: How AT announces dynamic changes to
255
+ this view: ``"none"``, ``"polite"``, or ``"assertive"``
256
+ (Android only).
257
+ test_id: Stable identifier for UI tests; exposed as
258
+ ``resource-id`` on Android and ``accessibilityIdentifier``
259
+ on iOS.
260
+ key: Stable identity for keyed reconciliation.
261
+
262
+ Returns:
263
+ An [`Element`][pythonnative.Element] of type
264
+ ``"SegmentedControl"``.
265
+ """
266
+ return _make_element(
267
+ "SegmentedControl",
268
+ style=style,
269
+ key=key,
270
+ segments=list(segments) if segments is not None else [],
271
+ selected_index=selected_index,
272
+ on_change=on_change,
273
+ enabled=False if enabled is False else None,
274
+ tint_color=tint_color,
275
+ accessibility_label=accessibility_label,
276
+ accessible=accessible,
277
+ accessibility_state=accessibility_state,
278
+ accessibility_live_region=accessibility_live_region,
279
+ test_id=test_id,
280
+ )
281
+
282
+
283
+ def DatePicker(
284
+ *,
285
+ value: Optional[str] = None,
286
+ mode: Literal["date", "time", "datetime"] = "date",
287
+ on_change: Optional[Callable[[str], Any]] = None,
288
+ minimum: Optional[str] = None,
289
+ maximum: Optional[str] = None,
290
+ enabled: bool = True,
291
+ style: StyleProp = None,
292
+ accessibility_label: Optional[str] = None,
293
+ accessible: Optional[bool] = None,
294
+ accessibility_state: Optional[AccessibilityState] = None,
295
+ accessibility_live_region: Optional[Literal["none", "polite", "assertive"]] = None,
296
+ test_id: Optional[str] = None,
297
+ key: Optional[str] = None,
298
+ ) -> Element:
299
+ """A native date / time picker.
300
+
301
+ Backed by ``UIDatePicker`` on iOS and a trigger button that opens
302
+ the platform ``DatePickerDialog`` / ``TimePickerDialog`` on
303
+ Android. ``value`` and the value reported to ``on_change`` are
304
+ ISO-8601 strings (``"2026-05-31"`` for ``mode="date"``, ``"14:30"``
305
+ for ``mode="time"``, ``"2026-05-31T14:30"`` for
306
+ ``mode="datetime"``), so values stay JSON-serializable and
307
+ platform-agnostic.
308
+
309
+ Args:
310
+ value: Currently selected value as an ISO-8601 string.
311
+ mode: ``"date"`` (default), ``"time"``, or ``"datetime"``.
312
+ on_change: Callback invoked with the new ISO-8601 string.
313
+ minimum: Earliest selectable value (ISO-8601), if any.
314
+ maximum: Latest selectable value (ISO-8601), if any.
315
+ enabled: When ``False``, the picker is disabled.
316
+ style: Style dict (or list of dicts).
317
+ accessibility_label: Spoken description for screen readers.
318
+ accessible: Override whether the element is exposed to AT.
319
+ accessibility_state: Current widget state for assistive tech,
320
+ e.g. ``{"disabled": True, "selected": False}``. Recognized
321
+ keys: ``disabled``, ``selected``, ``checked``, ``busy``,
322
+ ``expanded``.
323
+ accessibility_live_region: How AT announces dynamic changes to
324
+ this view: ``"none"``, ``"polite"``, or ``"assertive"``
325
+ (Android only).
326
+ test_id: Stable identifier for UI tests; exposed as
327
+ ``resource-id`` on Android and ``accessibilityIdentifier``
328
+ on iOS.
329
+ key: Stable identity for keyed reconciliation.
330
+
331
+ Returns:
332
+ An [`Element`][pythonnative.Element] of type ``"DatePicker"``.
333
+ """
334
+ return _make_element(
335
+ "DatePicker",
336
+ style=style,
337
+ key=key,
338
+ value=value,
339
+ mode=mode,
340
+ on_change=on_change,
341
+ minimum=minimum,
342
+ maximum=maximum,
343
+ enabled=False if enabled is False else None,
344
+ accessibility_label=accessibility_label,
345
+ accessible=accessible,
346
+ accessibility_state=accessibility_state,
347
+ accessibility_live_region=accessibility_live_region,
348
+ test_id=test_id,
349
+ _defaults={"accessibility_role": "button"},
350
+ )
351
+
352
+
353
+ def Picker(
354
+ *,
355
+ value: Any = None,
356
+ items: Optional[List[Dict[str, Any]]] = None,
357
+ on_change: Optional[Callable[[Any], Any]] = None,
358
+ placeholder: str = "Select…",
359
+ style: StyleProp = None,
360
+ accessibility_label: Optional[str] = None,
361
+ accessibility_hint: Optional[str] = None,
362
+ accessible: Optional[bool] = None,
363
+ accessibility_state: Optional[AccessibilityState] = None,
364
+ accessibility_live_region: Optional[Literal["none", "polite", "assertive"]] = None,
365
+ test_id: Optional[str] = None,
366
+ ref: Optional[Ref] = None,
367
+ key: Optional[str] = None,
368
+ ) -> Element:
369
+ """A real native dropdown / select widget.
370
+
371
+ Renders a tappable trigger labelled with the selected item; the
372
+ iOS handler attaches a ``UIMenu`` (system dropdown) and the Android
373
+ handler uses a native ``Spinner``. Selecting an item fires
374
+ ``on_change(value)``.
375
+
376
+ ``items`` is an ordered list of ``{"value": Any, "label": str}``
377
+ entries (``label`` defaults to ``str(value)`` when omitted).
378
+
379
+ Args:
380
+ value: Currently selected value (matched against
381
+ ``items[i]["value"]``).
382
+ items: Selectable options.
383
+ on_change: Callback invoked with the new value.
384
+ placeholder: Label shown when no item matches ``value``.
385
+ style: Style dict applied to the trigger.
386
+ accessibility_label: Spoken description for screen readers.
387
+ accessibility_hint: Spoken extra detail (iOS only).
388
+ accessible: Override whether the element is exposed to AT.
389
+ accessibility_state: Current widget state for assistive tech,
390
+ e.g. ``{"disabled": True, "selected": False}``. Recognized
391
+ keys: ``disabled``, ``selected``, ``checked``, ``busy``,
392
+ ``expanded``.
393
+ accessibility_live_region: How AT announces dynamic changes to
394
+ this view: ``"none"``, ``"polite"``, or ``"assertive"``
395
+ (Android only).
396
+ test_id: Stable identifier for UI tests; exposed as
397
+ ``resource-id`` on Android and ``accessibilityIdentifier``
398
+ on iOS.
399
+ ref: Optional [`Ref`][pythonnative.Ref] from ``use_ref()``.
400
+ key: Stable identity for keyed reconciliation.
401
+
402
+ Returns:
403
+ An [`Element`][pythonnative.Element] of type ``"Picker"``.
404
+ """
405
+ return _make_element(
406
+ "Picker",
407
+ style=style,
408
+ ref=ref,
409
+ key=key,
410
+ value=value,
411
+ items=list(items) if items is not None else [],
412
+ on_change=on_change,
413
+ placeholder=placeholder,
414
+ accessibility_label=accessibility_label,
415
+ accessibility_hint=accessibility_hint,
416
+ accessible=accessible,
417
+ accessibility_state=accessibility_state,
418
+ accessibility_live_region=accessibility_live_region,
419
+ test_id=test_id,
420
+ _defaults={"accessibility_role": "button"},
421
+ )
422
+
423
+
424
+ def RefreshControl(
425
+ *,
426
+ refreshing: bool = False,
427
+ on_refresh: Optional[Callable[[], Any]] = None,
428
+ tint_color: Optional[Color] = None,
429
+ ) -> Dict[str, Any]:
430
+ """Pull-to-refresh spec for [`ScrollView`][pythonnative.ScrollView] / [`FlatList`][pythonnative.FlatList].
431
+
432
+ Returns a plain dict that should be passed as the
433
+ ``refresh_control=`` prop. Modeled as a dict (not an
434
+ [`Element`][pythonnative.Element]) so the host scroll container can
435
+ hold one without it appearing as a child node.
436
+
437
+ Args:
438
+ refreshing: Drive the spinner's visibility from a use_state
439
+ value.
440
+ on_refresh: Callback invoked when the user pulls down past the
441
+ threshold. Set ``refreshing`` to ``True`` for the duration
442
+ of the work, then back to ``False`` on completion.
443
+ tint_color: Color of the spinner.
444
+
445
+ Returns:
446
+ Dict suitable for the ``refresh_control`` prop on a scroll
447
+ container.
448
+
449
+ Example:
450
+ ```python
451
+ import pythonnative as pn
452
+
453
+ @pn.component
454
+ def MyList():
455
+ refreshing, set_refreshing = pn.use_state(False)
456
+
457
+ def reload():
458
+ set_refreshing(True)
459
+ # ... fetch data ...
460
+ set_refreshing(False)
461
+
462
+ return pn.ScrollView(
463
+ pn.Text("Pull me!"),
464
+ refresh_control=pn.RefreshControl(
465
+ refreshing=refreshing, on_refresh=reload
466
+ ),
467
+ )
468
+ ```
469
+ """
470
+ spec: Dict[str, Any] = {"refreshing": bool(refreshing)}
471
+ if on_refresh is not None:
472
+ spec["on_refresh"] = on_refresh
473
+ if tint_color is not None:
474
+ spec["tint_color"] = tint_color
475
+ return spec
476
+
477
+
478
+ def StatusBar(
479
+ *,
480
+ bar_style: Optional[Literal["light", "dark", "default"]] = None,
481
+ background_color: Optional[Color] = None,
482
+ hidden: Optional[bool] = None,
483
+ key: Optional[str] = None,
484
+ ) -> Element:
485
+ """Configure the device's status bar appearance.
486
+
487
+ StatusBar is a side-effect element: it doesn't render any visible
488
+ content but applies its props to the host platform's status bar.
489
+ Mount one near the top of your tree.
490
+
491
+ The ``bar_style`` parameter is named separately from the universal
492
+ ``style`` kwarg (which is unused here) to avoid the conflict that
493
+ ``style="light"`` would create with the visual-style dict used
494
+ elsewhere.
495
+
496
+ Args:
497
+ bar_style: ``"light"`` (light icons over dark backgrounds),
498
+ ``"dark"`` (dark icons over light backgrounds), or
499
+ ``"default"`` (system default).
500
+ background_color: Color of the status-bar background (Android
501
+ only; iOS draws the bar transparent over your content).
502
+ hidden: When ``True``, the status bar is hidden.
503
+ key: Stable identity for keyed reconciliation.
504
+
505
+ Returns:
506
+ An [`Element`][pythonnative.Element] of type ``"StatusBar"``.
507
+ """
508
+ props: Dict[str, Any] = {}
509
+ if bar_style is not None:
510
+ props["bar_style"] = bar_style
511
+ if background_color is not None:
512
+ props["background_color"] = background_color
513
+ if hidden is not None:
514
+ props["hidden"] = hidden
515
+ return Element("StatusBar", props, [], key=key)