flet 0.70.0.dev6370__py3-none-any.whl → 0.70.0.dev6425__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.

Potentially problematic release.


This version of flet might be problematic. Click here for more details.

@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from collections.abc import Callable
2
4
  from dataclasses import dataclass
3
5
  from typing import Any, TypeVar
@@ -6,6 +8,9 @@ from flet.components.hooks.hook import Hook
6
8
  from flet.components.observable import Observable, ObservableSubscription
7
9
  from flet.components.utils import current_component
8
10
 
11
+ StateT = TypeVar("StateT")
12
+ Updater = Callable[[StateT], StateT]
13
+
9
14
 
10
15
  @dataclass
11
16
  class StateHook(Hook):
@@ -14,20 +19,21 @@ class StateHook(Hook):
14
19
  version: int = 0
15
20
 
16
21
 
17
- StateT = TypeVar("StateT")
18
-
19
-
20
22
  def use_state(
21
23
  initial: StateT | Callable[[], StateT],
22
- ) -> tuple[StateT, Callable[[StateT], None]]:
24
+ ) -> tuple[StateT, Callable[[StateT | Updater], None]]:
23
25
  """
24
- Add state to function components.
26
+ Adds state to a function component, similar to React's useState().
27
+
28
+ The returned setter accepts either:
29
+ - a new value, or
30
+ - a function receiving the previous state and returning the next one.
25
31
 
26
32
  Args:
27
- initial: Initial state value or a function that returns the initial state value.
33
+ initial: Initial state value or a function returning it.
28
34
 
29
35
  Returns:
30
- A tuple of the current state value and a function to update it.
36
+ (value, set_value) tuple.
31
37
  """
32
38
  component = current_component()
33
39
  hook = component.use_hook(
@@ -37,17 +43,34 @@ def use_state(
37
43
  )
38
44
  )
39
45
 
40
- def update_subscription(hook: StateHook):
41
- if hook.subscription:
42
- component._detach_observable_subscription(hook.subscription)
43
- hook.subscription = None
44
- if isinstance(hook.value, Observable):
45
- hook.subscription = component._attach_observable_subscription(hook.value)
46
+ def update_subscription(h: StateHook):
47
+ # Detach previous subscription if any
48
+ if h.subscription:
49
+ component._detach_observable_subscription(h.subscription)
50
+ h.subscription = None
51
+
52
+ # Attach new subscription if value is Observable
53
+ if isinstance(h.value, Observable):
54
+ h.subscription = component._attach_observable_subscription(h.value)
46
55
 
47
56
  update_subscription(hook)
48
57
 
49
- def set_state(new_value: Any):
50
- # shallow equality; swap to "is" or custom comparator if needed
58
+ def set_state(new_value_or_fn: StateT | Updater):
59
+ """
60
+ Update the state value.
61
+
62
+ Can be called with either:
63
+ - a direct new value, or
64
+ - a function that takes the current value and returns the next one.
65
+ """
66
+ # Compute next value
67
+ new_value = (
68
+ new_value_or_fn(hook.value)
69
+ if callable(new_value_or_fn)
70
+ else new_value_or_fn
71
+ )
72
+
73
+ # Only trigger update if value changed (shallow equality)
51
74
  if new_value != hook.value:
52
75
  hook.value = new_value
53
76
  update_subscription(hook)
@@ -31,6 +31,33 @@ class Stack(LayoutControl, AdaptiveControl):
31
31
  Stack is also useful if you want to implement implicit animations
32
32
  (https://flet.dev/docs/guides/python/animations/) that require knowing absolute
33
33
  position of a target value.
34
+
35
+ ```python
36
+ ft.Stack(
37
+ width=300,
38
+ height=300,
39
+ controls=[
40
+ ft.Image(
41
+ src="https://picsum.photos/300/300",
42
+ width=300,
43
+ height=300,
44
+ fit=ft.BoxFit.CONTAIN,
45
+ ),
46
+ ft.Row(
47
+ alignment=ft.MainAxisAlignment.CENTER,
48
+ controls=[
49
+ ft.Text(
50
+ value="Image title",
51
+ color=ft.Colors.SURFACE_TINT,
52
+ size=40,
53
+ weight=ft.FontWeight.BOLD,
54
+ opacity=0.5,
55
+ )
56
+ ],
57
+ ),
58
+ ],
59
+ )
60
+ ```
34
61
  """
35
62
 
36
63
  controls: list[Control] = field(default_factory=list)
@@ -51,56 +51,96 @@ class TextSelection:
51
51
  A range of text that represents a selection.
52
52
  """
53
53
 
54
- start: Optional[int] = None
55
- """
56
- The index of the first character in the range.
57
- """
58
-
59
- end: Optional[int] = None
60
- """
61
- The next index after the characters in this range.
62
- """
63
-
64
- selection: Optional[str] = None
65
- """
66
- The text string that is selected.
67
- """
68
-
69
- base_offset: Optional[int] = None
54
+ base_offset: int
70
55
  """
71
56
  The offset at which the selection originates.
72
57
  """
73
58
 
74
- extent_offset: Optional[int] = None
59
+ extent_offset: int
75
60
  """
76
61
  The offset at which the selection terminates.
77
62
  """
78
63
 
79
- affinity: Optional["TextAffinity"] = None
64
+ affinity: "TextAffinity" = TextAffinity.DOWNSTREAM
80
65
  """
81
66
  If the text range is collapsed and has more than one visual location (e.g., occurs
82
67
  at a line break), which of the two locations to use when painting the caret.
83
68
  """
84
69
 
85
- directional: Optional[bool] = None
70
+ directional: bool = False
86
71
  """
87
72
  Whether this selection has disambiguated its base and extent.
88
73
  """
89
74
 
90
- collapsed: Optional[bool] = None
91
- """
92
- Whether this range is empty (but still potentially placed inside the text).
93
- """
94
-
95
- valid: Optional[bool] = None
96
- """
97
- Whether this range represents a valid position in the text.
98
- """
99
-
100
- normalized: Optional[bool] = None
101
- """
102
- Whether the start of this range precedes the end.
103
- """
75
+ @property
76
+ def start(self) -> int:
77
+ """
78
+ The index of the first character in the range.
79
+
80
+ Note:
81
+ This property is read-only.
82
+ """
83
+ if self.base_offset < self.extent_offset:
84
+ return self.base_offset
85
+ else:
86
+ return self.extent_offset
87
+
88
+ @property
89
+ def end(self) -> int:
90
+ """
91
+ The next index after the characters in this range.
92
+
93
+ Note:
94
+ This property is read-only.
95
+ """
96
+ if self.base_offset < self.extent_offset:
97
+ return self.extent_offset
98
+ else:
99
+ return self.base_offset
100
+
101
+ @property
102
+ def is_valid(self) -> bool:
103
+ """
104
+ Whether this range represents a valid position in the text.
105
+
106
+ Note:
107
+ This property is read-only.
108
+ """
109
+ return self.start >= 0 and self.end >= 0
110
+
111
+ @property
112
+ def is_collapsed(self) -> bool:
113
+ """
114
+ Whether this range is empty (but still potentially placed inside the text).
115
+
116
+ Note:
117
+ This property is read-only.
118
+ """
119
+ return self.start == self.end
120
+
121
+ @property
122
+ def is_normalized(self) -> bool:
123
+ """
124
+ Whether the start of this range precedes the end.
125
+
126
+ Note:
127
+ This property is read-only.
128
+ """
129
+ return self.start <= self.end
130
+
131
+ def get_selected_text(self, source_text: str) -> str:
132
+ """
133
+ Returns the selected text from the given full text.
134
+
135
+ Args:
136
+ source_text: The full text to get the selection from.
137
+
138
+ Raises:
139
+ AssertionError: If the selection is not valid,
140
+ i.e. [`is_valid`][(c).] is `False`.
141
+ """
142
+ assert self.is_valid
143
+ return source_text[self.start : self.end]
104
144
 
105
145
 
106
146
  class TextSelectionChangeCause(Enum):
@@ -166,9 +206,16 @@ class TextSelectionChangeCause(Enum):
166
206
 
167
207
  @dataclass
168
208
  class TextSelectionChangeEvent(Event[EventControlType]):
169
- text: str
170
- cause: TextSelectionChangeCause
209
+ """An event emitted when the text selection changes."""
210
+
211
+ selected_text: str
212
+ """The selected text."""
213
+
171
214
  selection: TextSelection
215
+ """The new text selection."""
216
+
217
+ cause: Optional[TextSelectionChangeCause] = None
218
+ """The cause of the selection change."""
172
219
 
173
220
 
174
221
  @control("Text")
@@ -1,9 +1,9 @@
1
1
  from dataclasses import dataclass, field
2
2
  from typing import Optional
3
3
 
4
+ from flet import LayoutControl
4
5
  from flet.controls.base_control import control
5
- from flet.controls.control import Control
6
- from flet.controls.control_event import Event, EventHandler
6
+ from flet.controls.control_event import ControlEventHandler, Event, EventHandler
7
7
  from flet.controls.types import Number
8
8
 
9
9
  __all__ = ["AutoComplete", "AutoCompleteSelectEvent", "AutoCompleteSuggestion"]
@@ -11,22 +11,45 @@ __all__ = ["AutoComplete", "AutoCompleteSelectEvent", "AutoCompleteSuggestion"]
11
11
 
12
12
  @dataclass
13
13
  class AutoCompleteSuggestion:
14
+ """
15
+ Represents a suggestion item for the [`AutoComplete`][flet.] control.
16
+ """
17
+
14
18
  key: str
19
+ """A unique identifier or value used for filtering and selection."""
20
+
15
21
  value: str
22
+ """The display text shown to the user."""
16
23
 
17
24
 
18
25
  @dataclass
19
26
  class AutoCompleteSelectEvent(Event["AutoComplete"]):
27
+ """Event representing the selection of a suggestion in the AutoComplete control."""
28
+
29
+ index: int
30
+ """
31
+ The index of the selected suggestion from the corresponding
32
+ [`AutoComplete.suggestions`][flet.] list.
33
+ """
34
+
20
35
  selection: AutoCompleteSuggestion
36
+ """The selected suggestion."""
21
37
 
22
38
 
23
39
  @control("AutoComplete")
24
- class AutoComplete(Control):
40
+ class AutoComplete(LayoutControl):
25
41
  """
26
42
  Helps the user make a selection by entering some text and choosing from among a
27
43
  list of displayed options.
28
44
  """
29
45
 
46
+ value: str = ""
47
+ """
48
+ Current text displayed in the input field.
49
+
50
+ This value reflects user input even if it does not match any provided suggestion.
51
+ """
52
+
30
53
  suggestions: list[AutoCompleteSuggestion] = field(default_factory=list)
31
54
  """
32
55
  A list of [`AutoCompleteSuggestion`][flet.]
@@ -53,7 +76,19 @@ class AutoComplete(Control):
53
76
  Called when a suggestion is selected.
54
77
  """
55
78
 
79
+ on_change: Optional[ControlEventHandler["AutoComplete"]] = None
80
+ """
81
+ Called when the input text changes.
82
+ """
83
+
56
84
  @property
57
- def selected_index(self):
58
- # TODO: check availability of _selected_index + a default if not yet available
59
- return self._selected_index
85
+ def selected_index(self) -> Optional[int]:
86
+ """
87
+ The index of the (last) selected suggestion.
88
+
89
+ It is `None` until a suggestion has been selected from the UI.
90
+
91
+ Note:
92
+ This property is read-only.
93
+ """
94
+ return getattr(self, "_selected_index", None)
@@ -324,4 +324,14 @@ class FormFieldControl(LayoutControl):
324
324
  """
325
325
 
326
326
  async def focus(self):
327
+ """
328
+ Request focus for this control.
329
+
330
+ Example:
331
+ ```python
332
+ async def main(page: ft.Page):
333
+ page.add(ctf := ft.TextField())
334
+ await ctf.focus()
335
+ ```
336
+ """
327
337
  await self._invoke_method("focus")
@@ -80,7 +80,7 @@ class MenuItemButton(LayoutControl):
80
80
 
81
81
  on_click: Optional[ControlEventHandler["MenuItemButton"]] = None
82
82
  """
83
- Called when the button is clicked.
83
+ Called when the button is clicked.If not defined the button will be disabled.
84
84
  """
85
85
 
86
86
  on_hover: Optional[ControlEventHandler["MenuItemButton"]] = None
@@ -30,7 +30,8 @@ class SearchBar(LayoutControl):
30
30
  controls: list[Control] = field(default_factory=list)
31
31
  """
32
32
  The list of controls to be displayed below the search bar when in search view.
33
- These controls are usually [`ListTile`][flet.]s and will be displayed
33
+
34
+ Typically [`ListTile`][flet.]s and will be displayed
34
35
  in a [`ListView`][flet.].
35
36
  """
36
37
 
@@ -42,7 +43,8 @@ class SearchBar(LayoutControl):
42
43
  bar_leading: Optional[Control] = None
43
44
  """
44
45
  A control to display before the text input field when the search view is close.
45
- This is typically an `Icon` or an `IconButton`.
46
+
47
+ Typically an [`Icon`][flet.] or an [`IconButton`][flet.].
46
48
  """
47
49
 
48
50
  bar_trailing: Optional[list[Control]] = None
@@ -89,7 +91,7 @@ class SearchBar(LayoutControl):
89
91
  """
90
92
  The color and weight of the search bar's outline.
91
93
 
92
- This value is combined with [`SearchBar.bar_shape`][flet.] to
94
+ This value is combined with [`bar_shape`][(c).] to
93
95
  create a shape decorated with an outline.
94
96
  """
95
97
 
@@ -97,8 +99,7 @@ class SearchBar(LayoutControl):
97
99
  """
98
100
  The shape of the search bar.
99
101
 
100
- This shape is combined with
101
- [`SearchBar.bar_border_side`][flet.] to create a shape
102
+ This shape is combined with [`bar_border_side`][(c).] to create a shape
102
103
  decorated with an outline.
103
104
  """
104
105
 
@@ -134,7 +135,8 @@ class SearchBar(LayoutControl):
134
135
  view_leading: Optional[Control] = None
135
136
  """
136
137
  A `Control` to display before the text input field when the search view is open.
137
- Typically an `Icon` or an `IconButton`.
138
+
139
+ Typically an [`Icon`][flet.] or an [`IconButton`][flet.].
138
140
 
139
141
  Defaults to a back button which closes/pops the search view.
140
142
  """
@@ -154,8 +156,7 @@ class SearchBar(LayoutControl):
154
156
 
155
157
  view_bgcolor: Optional[ColorValue] = None
156
158
  """
157
- Defines the background color of the
158
- search view.
159
+ Defines the background color of the search view.
159
160
  """
160
161
 
161
162
  view_hint_text: Optional[str] = None
@@ -175,14 +176,12 @@ class SearchBar(LayoutControl):
175
176
 
176
177
  view_header_text_style: Optional[TextStyle] = None
177
178
  """
178
- Defines the [`TextStyle`][flet.] of the
179
- text being edited on the search view.
179
+ Defines the text style of the text being edited on the search view.
180
180
  """
181
181
 
182
182
  view_hint_text_style: Optional[TextStyle] = None
183
183
  """
184
- Defines the [`TextStyle`][flet.] of
185
- `view_hint_text`.
184
+ Defines the text style of [`view_hint_text`][(c).].
186
185
  """
187
186
 
188
187
  view_size_constraints: Optional[BoxConstraints] = None
@@ -232,7 +231,7 @@ class SearchBar(LayoutControl):
232
231
  full_screen: bool = False
233
232
  """
234
233
  Defines whether the search view grows to fill the entire screen when the search
235
- bar is tapped. Defaults to `False`.
234
+ bar is tapped.
236
235
  """
237
236
 
238
237
  keyboard_type: KeyboardType = KeyboardType.TEXT
@@ -243,8 +242,6 @@ class SearchBar(LayoutControl):
243
242
  autofocus: bool = False
244
243
  """
245
244
  Whether the text field should focus itself if nothing else is already focused.
246
-
247
- Defaults to `False`.
248
245
  """
249
246
 
250
247
  on_tap: Optional[ControlEventHandler["SearchBar"]] = None
@@ -254,7 +251,7 @@ class SearchBar(LayoutControl):
254
251
 
255
252
  on_tap_outside_bar: Optional[ControlEventHandler["SearchBar"]] = None
256
253
  """
257
- TBD
254
+ Fired when the user taps outside the search bar while the search view is open.
258
255
  """
259
256
 
260
257
  on_submit: Optional[ControlEventHandler["SearchBar"]] = None
@@ -269,12 +266,12 @@ class SearchBar(LayoutControl):
269
266
 
270
267
  on_focus: Optional[ControlEventHandler["SearchBar"]] = None
271
268
  """
272
- TBD
269
+ Fired when the search bar gains focus.
273
270
  """
274
271
 
275
272
  on_blur: Optional[ControlEventHandler["SearchBar"]] = None
276
273
  """
277
- TBD
274
+ Fired when the search bar loses focus.
278
275
  """
279
276
 
280
277
  def __contains__(self, item):
@@ -285,15 +282,21 @@ class SearchBar(LayoutControl):
285
282
 
286
283
  # Public methods
287
284
  async def focus(self):
285
+ """Requests focus for this control."""
288
286
  await self._invoke_method("focus")
289
287
 
290
- async def blur(self):
291
- await self._invoke_method("blur")
292
-
293
288
  async def open_view(self):
289
+ """Opens the search view."""
294
290
  await self._invoke_method("open_view")
295
291
 
296
292
  async def close_view(self, text: Optional[str] = None):
293
+ """
294
+ Closes an opened search view.
295
+
296
+ Args:
297
+ text: The text to set in the search bar when closing the view. If not
298
+ provided, the current [`value`][(c).] of the search bar will be used.
299
+ """
297
300
  await self._invoke_method(
298
301
  "close_view", {"text": text if text is not None else self.value}
299
302
  )
@@ -19,6 +19,25 @@ class SubmenuButton(LayoutControl):
19
19
  A menu button that displays a cascading menu.
20
20
 
21
21
  Typically used in a [`MenuBar`][flet.] control.
22
+
23
+ ```python
24
+ ft.SubmenuButton(
25
+ content=ft.Text("Choose text style"),
26
+ key="smbutton",
27
+ expand=True,
28
+ menu_style=ft.MenuStyle(
29
+ alignment=ft.Alignment.BOTTOM_LEFT, side=ft.BorderSide(1)
30
+ ),
31
+ controls=[
32
+ ft.MenuItemButton(
33
+ content=ft.Text("Underlined"),
34
+ on_click=lambda e: print(f"{e.control.content.value}.on_click")
35
+ ),
36
+ ft.MenuItemButton(...),
37
+ ...
38
+ ]
39
+ )
40
+ ```
22
41
  """
23
42
 
24
43
  content: Optional[StrOrControl] = None
@@ -26,6 +26,11 @@ class Switch(LayoutControl, AdaptiveControl):
26
26
  two mutually exclusive options.
27
27
 
28
28
  For example, "On/Off", "Show/Hide".
29
+
30
+ ```python
31
+ ft.Switch(label="Unchecked switch", value=False)
32
+ ft.Switch(label="Disabled switch", disabled=True)
33
+ ```
29
34
  """
30
35
 
31
36
  label: Optional[StrOrControl] = None
@@ -22,6 +22,14 @@ class TextButton(LayoutControl, AdaptiveControl):
22
22
  Text buttons are used for the lowest priority actions, especially when presenting
23
23
  multiple options. Text buttons can be placed on a variety of backgrounds. Until the
24
24
  button is interacted with, its container isn’t visible.
25
+
26
+ ```python
27
+ ft.TextButton(
28
+ content="Text Button",
29
+ icon=ft.Icons.STAR_BORDER,
30
+ icon_color=ft.Colors.BLUE_300,
31
+ )
32
+ ```
25
33
  """
26
34
 
27
35
  content: Optional[StrOrControl] = None
@@ -4,8 +4,9 @@ from typing import Optional, Union
4
4
 
5
5
  from flet.controls.adaptive_control import AdaptiveControl
6
6
  from flet.controls.base_control import BaseControl, control
7
- from flet.controls.control_event import ControlEventHandler
7
+ from flet.controls.control_event import ControlEventHandler, EventHandler
8
8
  from flet.controls.core.autofill_group import AutofillHint
9
+ from flet.controls.core.text import TextSelection, TextSelectionChangeEvent
9
10
  from flet.controls.material.form_field_control import FormFieldControl
10
11
  from flet.controls.padding import PaddingValue
11
12
  from flet.controls.text_style import StrutStyle
@@ -144,6 +145,19 @@ class TextField(FormFieldControl, AdaptiveControl):
144
145
  Current value of the TextField.
145
146
  """
146
147
 
148
+ selection: Optional[TextSelection] = None
149
+ """
150
+ Represents the current text selection or caret position in the field.
151
+
152
+ When the user selects text, this property is updated to reflect the selected range.
153
+ If no text is selected, it contains an empty range indicating the caret position.
154
+
155
+ Setting this property visually updates the field's selection to match the given
156
+ value, and hence leads to the [`on_selection_change`][(c).] event being triggered.
157
+ To ensure the selection is visible and the event is fired, the text field must
158
+ be focused. Call [`focus()`][(c).focus] on the field before setting this property.
159
+ """
160
+
147
161
  keyboard_type: KeyboardType = KeyboardType.TEXT
148
162
  """
149
163
  The type of keyboard to use for editing the text.
@@ -151,7 +165,7 @@ class TextField(FormFieldControl, AdaptiveControl):
151
165
 
152
166
  multiline: bool = False
153
167
  """
154
- `True` if TextField can contain multiple lines of text.
168
+ Whether this field can contain multiple lines of text.
155
169
  """
156
170
 
157
171
  min_lines: Optional[int] = None
@@ -400,7 +414,8 @@ class TextField(FormFieldControl, AdaptiveControl):
400
414
  """
401
415
  Helps the autofill service identify the type of this text input.
402
416
 
403
- More information [here](https://api.flutter.dev/flutter/material/TextField/autofillHints.html).
417
+ More information
418
+ [here](https://api.flutter.dev/flutter/material/TextField/autofillHints.html).
404
419
  """
405
420
 
406
421
  on_change: Optional[ControlEventHandler["TextField"]] = None
@@ -408,6 +423,16 @@ class TextField(FormFieldControl, AdaptiveControl):
408
423
  Called when the typed input for the TextField has changed.
409
424
  """
410
425
 
426
+ on_selection_change: Optional[
427
+ EventHandler[TextSelectionChangeEvent["TextField"]]
428
+ ] = None
429
+ """
430
+ Called when the text selection or caret position changes.
431
+
432
+ This can be triggered either by user interaction (selecting text or moving
433
+ the caret) or programmatically (through the [`selection`][(c).] property).
434
+ """
435
+
411
436
  on_click: Optional[ControlEventHandler["TextField"]] = None
412
437
  """
413
438
  TBD
@@ -38,6 +38,14 @@ class TimePicker(DialogControl):
38
38
 
39
39
  Depending on the `time_picker_entry_mode`, it will show either a Dial or
40
40
  an Input (hour and minute text fields) for picking a time.
41
+
42
+ ```python
43
+ ft.TimePicker(
44
+ value=time(1, 2),
45
+ time_picker_entry_mode=ft.TimePickerEntryMode.INPUT_ONLY,
46
+ open=True,
47
+ )
48
+ ```
41
49
  """
42
50
 
43
51
  value: Optional[time] = field(default_factory=lambda: datetime.now().time())
@@ -29,8 +29,7 @@ class FilePickerFileType(Enum):
29
29
 
30
30
  MEDIA = "media"
31
31
  """
32
- A combination of [`VIDEO`][(c).] and
33
- [`IMAGE`][(c).].
32
+ A combination of [`VIDEO`][(c).] and [`IMAGE`][(c).].
34
33
  """
35
34
 
36
35
  IMAGE = "image"
@@ -158,8 +157,11 @@ class FilePicker(Service):
158
157
  dialog_title: The title of the dialog window. Defaults to [`FilePicker.
159
158
  initial_directory: The initial directory where the dialog should open.
160
159
 
160
+ Returns:
161
+ The selected directory path or `None` if the dialog was cancelled.
162
+
161
163
  Raises:
162
- NotImplementedError: If called in web app.
164
+ FletUnsupportedPlatformException: If called in web mode.
163
165
  """
164
166
  if self.page.web:
165
167
  raise FletUnsupportedPlatformException(
@@ -213,7 +215,7 @@ class FilePicker(Service):
213
215
  if (self.page.web or self.page.platform.is_mobile()) and not src_bytes:
214
216
  raise ValueError(
215
217
  '"src_bytes" is required when saving a file in web mode,'
216
- "on Android and iOS."
218
+ "or on mobile (Android & iOS)."
217
219
  )
218
220
  if self.page.web and not file_name:
219
221
  raise ValueError('"file_name" is required when saving a file in web mode.')
@@ -248,8 +250,10 @@ class FilePicker(Service):
248
250
  file_type: The file types allowed to be selected.
249
251
  allow_multiple: Allow the selection of multiple files at once.
250
252
  allowed_extensions: The allowed file extensions. Has effect only if
251
- `file_type` is
252
- [`FilePickerFileType.CUSTOM`][flet.].
253
+ `file_type` is [`FilePickerFileType.CUSTOM`][flet.].
254
+
255
+ Returns:
256
+ A list of selected files.
253
257
  """
254
258
  files = await self._invoke_method(
255
259
  "pick_files",
@@ -1,14 +1,112 @@
1
+ from dataclasses import dataclass
1
2
  from enum import Enum
2
3
 
3
4
  from flet.controls.base_control import control
4
5
  from flet.controls.services.service import Service
6
+ from flet.utils import from_dict
5
7
 
6
- __all__ = ["Assertiveness", "SemanticsService"]
8
+ __all__ = ["AccessibilityFeatures", "Assertiveness", "SemanticsService"]
7
9
 
8
10
 
9
11
  class Assertiveness(Enum):
12
+ """
13
+ Determines the assertiveness level of the accessibility announcement.
14
+ """
15
+
10
16
  POLITE = "polite"
17
+ """
18
+ The assistive technology will speak changes whenever the user is idle.
19
+ """
20
+
11
21
  ASSERTIVE = "assertive"
22
+ """
23
+ The assistive technology will interrupt any announcement that it is
24
+ currently making to notify the user about the change.
25
+
26
+ It should only be used for time-sensitive/critical notifications.
27
+ """
28
+
29
+
30
+ @dataclass
31
+ class AccessibilityFeatures:
32
+ """
33
+ Accessibility features that may be enabled by the platform.
34
+
35
+ Note:
36
+ It is not possible to enable these settings from Flet, instead they are
37
+ used by the platform to indicate that additional accessibility features are
38
+ enabled.
39
+ """
40
+
41
+ accessible_navigation: bool
42
+ """
43
+ Whether there is a running accessibility service which is changing the
44
+ interaction model of the device.
45
+
46
+ For example, TalkBack on Android and VoiceOver on iOS enable this flag.
47
+ """
48
+
49
+ bold_text: bool
50
+ """
51
+ The platform is requesting that text be rendered at a bold font weight.
52
+
53
+ Note:
54
+ Only supported on iOS and Android API 31+.
55
+ """
56
+
57
+ disable_animations: bool
58
+ """
59
+ The platform is requesting that animations be disabled or simplified.
60
+ """
61
+
62
+ high_contrast: bool
63
+ """
64
+ The platform is requesting that UI be rendered with darker colors.
65
+
66
+ Note:
67
+ Only supported on iOS.
68
+ """
69
+
70
+ invert_colors: bool
71
+ """
72
+ The platform is inverting the colors of the application.
73
+ """
74
+
75
+ reduce_motion: bool
76
+ """
77
+ The platform is requesting that certain animations be simplified and
78
+ parallax effects removed.
79
+
80
+ Note:
81
+ Only supported on iOS.
82
+ """
83
+
84
+ on_off_switch_labels: bool
85
+ """
86
+ The platform is requesting to show on/off labels inside switches.
87
+
88
+ Note:
89
+ Only supported on iOS.
90
+ """
91
+
92
+ supports_announcements: bool
93
+ """
94
+ Whether the platform supports accessibility announcement API, i.e.
95
+ [`SemanticsService.announce_message()`][flet.SemanticsService.announce_message].
96
+
97
+ Will be `False` on platforms where announcements are deprecated or
98
+ unsupported by the underlying platform and `True` on platforms where such
99
+ announcements are generally supported without discouragement (ex: iOS, web).
100
+
101
+ Note:
102
+ Some platforms do not support or discourage the use of
103
+ announcement. Using `SemanticsService.announce_message()` on those platforms
104
+ may be ignored. Consider using other way to convey message to the
105
+ user. For example, Android discourages the uses of direct message
106
+ announcement, and rather encourages using other semantic
107
+ properties such as [`Semantics.live_region`][flet.] to convey
108
+ message to the user.
109
+ """
12
110
 
13
111
 
14
112
  @control("SemanticsService")
@@ -19,9 +117,10 @@ class SemanticsService(Service):
19
117
 
20
118
  async def announce_tooltip(self, message: str):
21
119
  """
22
- Sends a semantic announcement of a tooltip. Currently honored on Android only.
120
+ Sends a semantic announcement of a tooltip.
23
121
 
24
- The provided `message` will be read by TalkBack.
122
+ Note:
123
+ Only supported on Android.
25
124
  """
26
125
  await self._invoke_method("announce_tooltip", arguments={"message": message})
27
126
 
@@ -32,15 +131,17 @@ class SemanticsService(Service):
32
131
  assertiveness: Assertiveness = Assertiveness.POLITE,
33
132
  ):
34
133
  """
35
- Sends a semantic announcement with the given `message`. This should preferably
36
- be used for announcements that are not seamlessly announced by the system as a
37
- result of a UI state change.
134
+ Sends a semantic announcement with the given message.
38
135
 
39
- `rtl` is a boolean and indicates the text direction of the `message`.
136
+ Args:
137
+ message: The message to be announced.
138
+ rtl: Indicates if the message text direction is right-to-left.
139
+ assertiveness: The assertiveness level of the announcement.
140
+ Only supported on web.
40
141
 
41
- The `assertiveness` level of the announcement is only supported by the web
42
- engine and has no effect on other platforms. Value is an `Assertiveness` enum
43
- and can either be `Assertiveness.ASSERTIVE` or `Assertiveness.POLITE` (default).
142
+ Notes:
143
+ This method should be used for announcements that are not automatically
144
+ handled by the system as a result of a UI state change.
44
145
  """
45
146
  await self._invoke_method(
46
147
  "announce_message",
@@ -50,3 +151,14 @@ class SemanticsService(Service):
50
151
  "assertiveness": assertiveness,
51
152
  },
52
153
  )
154
+
155
+ async def get_accessibility_features(self) -> AccessibilityFeatures:
156
+ """
157
+ Returns the current platform accessibility feature flags.
158
+
159
+ Returns:
160
+ A snapshot of the platform's accessibility
161
+ preferences at the time of invocation.
162
+ """
163
+ features = await self._invoke_method("get_accessibility_features")
164
+ return from_dict(AccessibilityFeatures, features)
flet/version.py CHANGED
@@ -10,7 +10,7 @@ from flet.utils import is_mobile, is_windows, which
10
10
  DEFAULT_VERSION = "0.1.0"
11
11
 
12
12
  # will be replaced by CI
13
- version = "0.70.0.dev6370"
13
+ version = "0.70.0.dev6425"
14
14
 
15
15
 
16
16
  def update_version():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flet
3
- Version: 0.70.0.dev6370
3
+ Version: 0.70.0.dev6425
4
4
  Summary: Flet for Python - easily build interactive multi-platform apps in Python
5
5
  Author-email: "Appveyor Systems Inc." <hello@flet.dev>
6
6
  License-Expression: Apache-2.0
@@ -1,7 +1,7 @@
1
1
  flet/__init__.py,sha256=39Ci10DOyWcl-9adUYDbIX7eR0PHsRELpESPQZnCw9M,26200
2
2
  flet/app.py,sha256=HSws0Zm4ZO0-Hp2P9h7xirCVnRkKCVXhuekyAXT_9Fo,11883
3
3
  flet/cli.py,sha256=IUM25fY_sqMtl0hlQGhlMQaBb1oNyO0VZeeBgRodhuA,204
4
- flet/version.py,sha256=G79_e0GaEWAHubI5qUf3Oswkoj0--Y3hrdFTF03GxoM,2512
4
+ flet/version.py,sha256=bsmWJ4dhyVkSfL4LEUHdvb1fHjod74HlV0ehKrH0zss,2512
5
5
  flet/auth/__init__.py,sha256=eDqmi0Ki8Resd198S7XxgYa2R14wnNqIXnYhBLPl8fQ,289
6
6
  flet/auth/authorization.py,sha256=hP_36RiRPtSwmK_Yp6MMzAjQdDxbBiEcZ2yFNqyNiRs,357
7
7
  flet/auth/authorization_service.py,sha256=6N2LvisSt7KI_VgfyCH0OaJ6jTcmXCkAldN1yYlakzQ,6410
@@ -29,7 +29,7 @@ flet/components/hooks/use_callback.py,sha256=TUTIfwBeZ5Xsbt7wI8OVbzfMKBGyPq27z3J
29
29
  flet/components/hooks/use_context.py,sha256=38_MYBIOzHE-X45psuyHV6cTjbcrQVXVRzcCz_bMwv8,2516
30
30
  flet/components/hooks/use_effect.py,sha256=dZik3viWSfkOi5uTzc-kWV00P2_DIWcV2OzA8OexAN4,3225
31
31
  flet/components/hooks/use_memo.py,sha256=4IbT89yQXicMgzqp9a6hJ6egit_6GX8sVkn4DczVeyQ,1693
32
- flet/components/hooks/use_state.py,sha256=ZAhtIRnm2CKDK2-cIWmkWWEV-Gz2eOx7f9ZhsE1b06M,1680
32
+ flet/components/hooks/use_state.py,sha256=NXCkMQ-KIsu5pzr9CmaPZuUlQYUEE54CIKSQFr7KkyE,2351
33
33
  flet/controls/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
34
  flet/controls/adaptive_control.py,sha256=Pw0E7z0IlNSe05cQTi5BLElLF3OnlVLzwfvtOQpsRr8,1594
35
35
  flet/controls/alignment.py,sha256=re4jnpuqNPPWs55bf8RB_c9llqcuGhZcCjdNutx2N5M,3257
@@ -98,8 +98,8 @@ flet/controls/core/safe_area.py,sha256=Yf2ZWmZpGZ_xpNw16xozbc99KTXXmyXGYo-gPlC9b
98
98
  flet/controls/core/screenshot.py,sha256=6X3f6rYaX7PHkvWM7gpFlyhA2xzt-M15ax-Nfd45n1g,1110
99
99
  flet/controls/core/semantics.py,sha256=tiRTyFMYYNIcj8kuiopZMPGxeo_n4L7eCchHcywColI,7413
100
100
  flet/controls/core/shader_mask.py,sha256=z4sr8RP2PnP-ooh0c5KNiUDLsHmj1S-R7ATm53j5CJo,1034
101
- flet/controls/core/stack.py,sha256=JqCIXFcDxd4C7dhJik0qwOu7IoHRmkj7BpvF6LhM03k,1954
102
- flet/controls/core/text.py,sha256=jKl-j9Zzoj0nuxIbj-wRj4re6VLSvygvsqTwAIiMKqg,8903
101
+ flet/controls/core/stack.py,sha256=Px_1SllMdOwDuMv8_xp28jwccy9wleSlaM3F5H5MXgA,2749
102
+ flet/controls/core/text.py,sha256=u63G2TPDMzKcEnQwwsgfdtwU4_Bj_HjqFi7MdTdvG8o,10201
103
103
  flet/controls/core/text_span.py,sha256=-f60CaJ6H31_f6JcYLEogiwe14Lw_HdvCAccRRsANP8,2939
104
104
  flet/controls/core/transparent_pointer.py,sha256=BGDFuDWyDUIYOmwaEgMMks6OWS_lVjZObAw2M-3r2bQ,963
105
105
  flet/controls/core/view.py,sha256=J0C7VNl-qSyNlVMyCaesFFmuBFFskz9kS3-QsxqI2hc,5015
@@ -150,7 +150,7 @@ flet/controls/cupertino/cupertino_tinted_button.py,sha256=SmLukUZWYU_c2roz81a1hY
150
150
  flet/controls/material/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
151
151
  flet/controls/material/alert_dialog.py,sha256=_6D1a0iBDNImmExHjXzpxyGOnEA0DLk2Cj_Akl_uXio,7822
152
152
  flet/controls/material/app_bar.py,sha256=hEaZLSSKcJc5WQ7BcIPhB0m5_C9CnBVOkiYiMYQsJRY,6605
153
- flet/controls/material/auto_complete.py,sha256=MVesy4fUvLvY0pw_BDQXpRB5o9ac1Ci7icTdG4nC5oM,1856
153
+ flet/controls/material/auto_complete.py,sha256=hLH4cuhxno1wkh_JcX9RERe1_oaZIIkHjAVk9aR-1X8,2797
154
154
  flet/controls/material/badge.py,sha256=gWkDrqoZMIrjEreWeTaANlnzJn394Gj4vQZikuVAEIk,3365
155
155
  flet/controls/material/banner.py,sha256=gFj9oNpPMNiAMnFNWkZiUdgGcE6T72VVVw73BeIRMvU,4512
156
156
  flet/controls/material/bottom_app_bar.py,sha256=_nnAUEP7_z3seEaDQ29qO5qEn8xbBEUxL-I68i9lk5c,2456
@@ -173,12 +173,12 @@ flet/controls/material/expansion_tile.py,sha256=sEAXoc7-FkjFUEIgM5pK3LVKIpjsTxI2
173
173
  flet/controls/material/filled_button.py,sha256=ZtCy47Yrv2B1RyDk1pszVKiUj-YtMcLI7koTf5Bz0Mo,452
174
174
  flet/controls/material/filled_tonal_button.py,sha256=t9zXaMvakzmHUWtPfJK1ORAd8P3O5XCPi098PYAiOCU,574
175
175
  flet/controls/material/floating_action_button.py,sha256=1i9__kC4Y0uuha2lnWInYszUXLQW05_PmgiAwPUOpAk,6023
176
- flet/controls/material/form_field_control.py,sha256=8T3wrdfJ3j9Npz_A90TjJSFOzuVuhzR50v1qCpiRLOM,8433
176
+ flet/controls/material/form_field_control.py,sha256=kTVeg-gfytcQdoF3bwaGu_N2kZXSR_180beNPPwTi-w,8678
177
177
  flet/controls/material/icon_button.py,sha256=ZmOmOtk7fv1B2gWOvf0yTvwxxRdI7UDl5YsNLsEzLNA,7788
178
178
  flet/controls/material/icons.py,sha256=dsBk2nwUW3SQjwpzPv8G53ILP_zCg7tJocylHQLC-RU,287261
179
179
  flet/controls/material/list_tile.py,sha256=RIBO8ibubZjnGyWV4iTw7FOhMVNJM6jImoUYumAvjfw,8061
180
180
  flet/controls/material/menu_bar.py,sha256=78RmnKy9npkdcp8QYqp4kHqXnVHaZWkRNqEURJISGZg,2250
181
- flet/controls/material/menu_item_button.py,sha256=ICiTw3FMCTL7maI04KggHOcuxEOEHLPxAU08D_XVVxY,2523
181
+ flet/controls/material/menu_item_button.py,sha256=nlxXnBgJfB7oJ1F-7PuQy-67nmYTxglZ14u4uGf63kc,2566
182
182
  flet/controls/material/navigation_bar.py,sha256=HzSiMT6P6bgkxz-d1iWxRNACMuOqnPKi2qbLBmp7BCg,4998
183
183
  flet/controls/material/navigation_drawer.py,sha256=_Wraal9cxMqyXUbDC26wMEUWlWu0pVT7V28DR-MCoQE,3794
184
184
  flet/controls/material/navigation_rail.py,sha256=bnzSJ8LKV-Y7GUPslX7cTpkgnnzjsHp0DftFUp-5l2c,7856
@@ -190,25 +190,25 @@ flet/controls/material/radio.py,sha256=IK3hS-qT3BHA-0xDXWRDSoFQQHnMw4t-x6EayPBeb
190
190
  flet/controls/material/radio_group.py,sha256=-B1djdfuOPYF1_hfjTj4CQ6ytJHhfFs2iY64ebVg63U,972
191
191
  flet/controls/material/range_slider.py,sha256=drZjlzG3kQGI0Ybl18uAQhY7YIoB056TTxw5CqxOcwM,4413
192
192
  flet/controls/material/reorderable_list_view.py,sha256=iH87xlj7pIK1Kf-nQk5_PJ1sWmA0NXLCSQArDDrB-8Q,4692
193
- flet/controls/material/search_bar.py,sha256=hoeZxdTG4vqCqgWlRBaJi-iGenDOpIpedHrUJqp9X04,8448
193
+ flet/controls/material/search_bar.py,sha256=vqq7HeQmdOwCwn6TVes4OKjNwN4FzdqoRiWpT95Q4KE,8770
194
194
  flet/controls/material/segmented_button.py,sha256=f01DPN_QbUvzGS8tEilASVI6VFQwURDZ-uy2en_0U74,5510
195
195
  flet/controls/material/selection_area.py,sha256=KYjMBMuuSKmi6sKBl0UZgZurBOeJMbgNazi-jsR1KU4,1032
196
196
  flet/controls/material/slider.py,sha256=zV0Jres_HPwP590kNe663GeML9gIx4U24W_R7BpCV6o,6952
197
197
  flet/controls/material/snack_bar.py,sha256=8X3P_TgHBAWafMzaC6NskPey2_k-JeheL29PrgxAVYc,7374
198
- flet/controls/material/submenu_button.py,sha256=4iQvOPTNRjNwXx3in8FWqBFKW6Mt22awwAhL8HiWd_I,2683
199
- flet/controls/material/switch.py,sha256=EaeAF1qDQfzmHz_uLzQTurc5vKUXXYuCSmoKdXjmQCg,6892
198
+ flet/controls/material/submenu_button.py,sha256=xDGBjZLT22Pi0UrRnUQFx9RAl7oJEWChuP5929rEkeE,3193
199
+ flet/controls/material/switch.py,sha256=JLAPcOq0XzIkw1_HmsmBukROV9zBAkm-MZt8iqIKKXg,7030
200
200
  flet/controls/material/tabs.py,sha256=WIGsEs6lpw3LwqWsgIAJ4a0PpWKgLVOKkZRKfarnNY4,18565
201
- flet/controls/material/text_button.py,sha256=Mkvz4LIl0yH1-e0ekOjPD6z8CZ5ZUIyE00zcb7sLKns,2578
202
- flet/controls/material/textfield.py,sha256=_JrdBKfVwwSeROm3Yh-0u2TsuovYcW7P8nQevIP7g2I,11816
203
- flet/controls/material/time_picker.py,sha256=_gUTaQi4N-mo1Oj_yJEsti8ToM0WhwhofbCjP5v2gzA,3070
201
+ flet/controls/material/text_button.py,sha256=xAHx613EN07MT9fuWhvp7oUQ6zZ7Gw7rtsO5YaHrd1A,2747
202
+ flet/controls/material/textfield.py,sha256=veYqSHOz_YDBjQsd-cK8ALxrgtWyy50p_Yyj51biPSA,12909
203
+ flet/controls/material/time_picker.py,sha256=Jj1snTHdZdbG40d0AYrt2mwrXxxFEU-TfDcT6pH6Y5Q,3229
204
204
  flet/controls/material/tooltip.py,sha256=PTqJiiE95z4WCTlvCx7i3vA-gGwphUT7w_2oXMiiVtY,5636
205
205
  flet/controls/material/vertical_divider.py,sha256=kOqmL4XoL6tfRHoXA3oJurvIaixwn54Qf6ATC0-CT48,2752
206
206
  flet/controls/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
207
207
  flet/controls/services/browser_context_menu.py,sha256=orB2vzQmZ3TvgEdZV1NUUkcQkEs49uFr9unyum2J0ug,592
208
208
  flet/controls/services/clipboard.py,sha256=XWp8OqFBUwd1ULeQ35nufGI_yR0WqNauWv8Zf1CHR0k,846
209
- flet/controls/services/file_picker.py,sha256=Gsh1A4XBD3nIS9MDsLDirDwTMwO9nBZGHeC-F2furXI,7662
209
+ flet/controls/services/file_picker.py,sha256=Pd72x7ZT4xBpGSXjmQ88M6F9J621qWHWdVrygxKGpzg,7819
210
210
  flet/controls/services/haptic_feedback.py,sha256=JZMveq3loC3CWt3LPp87iWl6IeAzyUOnRejKzX9nLmo,1164
211
- flet/controls/services/semantics_service.py,sha256=eF_EcVqOMsgUyyZYhKTNLP-PcFTX0a8NQsQkAU-jxyk,1662
211
+ flet/controls/services/semantics_service.py,sha256=0DkKWE0cuv4v-RIusHy9I4QQSZmz8vmADA7lHaotTVk,4829
212
212
  flet/controls/services/service.py,sha256=1k3PGJxkJOub5Eb9SIjrRo2-Ik_xrmERQD0TfxjHYC0,378
213
213
  flet/controls/services/shake_detector.py,sha256=A9o5Z89lBUL7j6OhhMWv3Qna2O_ke1h3R1AFwKgmMwk,895
214
214
  flet/controls/services/shared_preferences.py,sha256=ec_dMBMozfAalyw1exdXd9ayDY7g08oC-oE8JkqU-PE,994
@@ -246,8 +246,8 @@ flet/utils/platform_utils.py,sha256=U4cqV3EPi5QNYjbhfZmtk41-KMtI_P7KvVdnZzMOgJA,
246
246
  flet/utils/slugify.py,sha256=e-lsoDc2_dk5jQnySaHCU83AA4O6mguEgCEdk2smW2Y,466
247
247
  flet/utils/strings.py,sha256=R63_i7PdSAStCDPJ-O_WHBt3H02JQ14GSbnjLIpPTUc,178
248
248
  flet/utils/vector.py,sha256=pYZzjldBWCZbSeSkZ8VmujwcZC7VBWk1NLBPA-2th3U,3207
249
- flet-0.70.0.dev6370.dist-info/METADATA,sha256=u9p6dNcRA2r0bUV9wWwDITiJtju60zql11_kt2JL7R4,6109
250
- flet-0.70.0.dev6370.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
251
- flet-0.70.0.dev6370.dist-info/entry_points.txt,sha256=mbBhHNUnLHiDqR36WeJrfLJU0Y0y087-M4wagQmaQ_Y,39
252
- flet-0.70.0.dev6370.dist-info/top_level.txt,sha256=HbLrSnWJX2jZOEZAI14cGzW8Q5BbOGTtE-7knD5FDh0,5
253
- flet-0.70.0.dev6370.dist-info/RECORD,,
249
+ flet-0.70.0.dev6425.dist-info/METADATA,sha256=W3ne-aoxSBH-shKc3Z447t3MCIJOESQmCotE3qWBRdM,6109
250
+ flet-0.70.0.dev6425.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
251
+ flet-0.70.0.dev6425.dist-info/entry_points.txt,sha256=mbBhHNUnLHiDqR36WeJrfLJU0Y0y087-M4wagQmaQ_Y,39
252
+ flet-0.70.0.dev6425.dist-info/top_level.txt,sha256=HbLrSnWJX2jZOEZAI14cGzW8Q5BbOGTtE-7knD5FDh0,5
253
+ flet-0.70.0.dev6425.dist-info/RECORD,,