flet 0.85.0.dev4__tar.gz → 0.85.2__tar.gz

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 (316) hide show
  1. {flet-0.85.0.dev4 → flet-0.85.2}/PKG-INFO +11 -11
  2. {flet-0.85.0.dev4 → flet-0.85.2}/pyproject.toml +11 -11
  3. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/router.py +239 -45
  4. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/tooltip.py +27 -11
  5. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/theme.py +3 -0
  6. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/types.py +1 -1
  7. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/version.py +1 -1
  8. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet.egg-info/PKG-INFO +11 -11
  9. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet.egg-info/SOURCES.txt +2 -0
  10. flet-0.85.2/src/flet.egg-info/requires.txt +29 -0
  11. flet-0.85.2/tests/test_router_modal.py +180 -0
  12. flet-0.85.2/tests/test_router_recursive.py +251 -0
  13. flet-0.85.0.dev4/src/flet.egg-info/requires.txt +0 -29
  14. {flet-0.85.0.dev4 → flet-0.85.2}/README.md +0 -0
  15. {flet-0.85.0.dev4 → flet-0.85.2}/setup.cfg +0 -0
  16. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/__init__.py +0 -0
  17. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/app.py +0 -0
  18. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/auth/__init__.py +0 -0
  19. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/auth/authorization.py +0 -0
  20. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/auth/authorization_service.py +0 -0
  21. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/auth/group.py +0 -0
  22. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/auth/oauth_provider.py +0 -0
  23. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/auth/oauth_token.py +0 -0
  24. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/auth/providers/__init__.py +0 -0
  25. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/auth/providers/auth0_oauth_provider.py +0 -0
  26. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/auth/providers/azure_oauth_provider.py +0 -0
  27. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/auth/providers/github_oauth_provider.py +0 -0
  28. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/auth/providers/google_oauth_provider.py +0 -0
  29. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/auth/user.py +0 -0
  30. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/canvas/__init__.py +0 -0
  31. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/cli.py +0 -0
  32. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/__init__.py +0 -0
  33. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/component.py +0 -0
  34. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/component_decorator.py +0 -0
  35. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/component_owned.py +0 -0
  36. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/hooks/__init__.py +0 -0
  37. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/hooks/hook.py +0 -0
  38. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/hooks/use_callback.py +0 -0
  39. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/hooks/use_context.py +0 -0
  40. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/hooks/use_dialog.py +0 -0
  41. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/hooks/use_effect.py +0 -0
  42. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/hooks/use_memo.py +0 -0
  43. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/hooks/use_ref.py +0 -0
  44. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/hooks/use_state.py +0 -0
  45. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/memo.py +0 -0
  46. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/observable.py +0 -0
  47. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/public_utils.py +0 -0
  48. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/components/utils.py +0 -0
  49. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/__init__.py +0 -0
  50. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/adaptive_control.py +0 -0
  51. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/alignment.py +0 -0
  52. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/animation.py +0 -0
  53. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/base_control.py +0 -0
  54. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/base_page.py +0 -0
  55. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/blur.py +0 -0
  56. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/border.py +0 -0
  57. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/border_radius.py +0 -0
  58. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/box.py +0 -0
  59. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/buttons.py +0 -0
  60. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/colors.py +0 -0
  61. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/context.py +0 -0
  62. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/control.py +0 -0
  63. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/control_event.py +0 -0
  64. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/control_state.py +0 -0
  65. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/__init__.py +0 -0
  66. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/animated_switcher.py +0 -0
  67. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/autofill_group.py +0 -0
  68. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/__init__.py +0 -0
  69. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/arc.py +0 -0
  70. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/canvas.py +0 -0
  71. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/circle.py +0 -0
  72. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/color.py +0 -0
  73. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/fill.py +0 -0
  74. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/image.py +0 -0
  75. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/line.py +0 -0
  76. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/oval.py +0 -0
  77. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/path.py +0 -0
  78. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/points.py +0 -0
  79. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/rect.py +0 -0
  80. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/shadow.py +0 -0
  81. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/shape.py +0 -0
  82. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/canvas/text.py +0 -0
  83. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/column.py +0 -0
  84. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/dismissible.py +0 -0
  85. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/drag_target.py +0 -0
  86. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/draggable.py +0 -0
  87. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/flet_app.py +0 -0
  88. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/gesture_detector.py +0 -0
  89. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/grid_view.py +0 -0
  90. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/hero.py +0 -0
  91. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/icon.py +0 -0
  92. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/image.py +0 -0
  93. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/interactive_viewer.py +0 -0
  94. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/keyboard_listener.py +0 -0
  95. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/list_view.py +0 -0
  96. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/markdown.py +0 -0
  97. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/merge_semantics.py +0 -0
  98. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/page_view.py +0 -0
  99. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/pagelet.py +0 -0
  100. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/placeholder.py +0 -0
  101. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/reorderable_drag_handle.py +0 -0
  102. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/responsive_row.py +0 -0
  103. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/rotated_box.py +0 -0
  104. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/row.py +0 -0
  105. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/safe_area.py +0 -0
  106. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/screenshot.py +0 -0
  107. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/semantics.py +0 -0
  108. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/shader_mask.py +0 -0
  109. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/shimmer.py +0 -0
  110. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/stack.py +0 -0
  111. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/text.py +0 -0
  112. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/text_span.py +0 -0
  113. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/transparent_pointer.py +0 -0
  114. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/view.py +0 -0
  115. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/window.py +0 -0
  116. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/core/window_drag_area.py +0 -0
  117. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/__init__.py +0 -0
  118. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_action_sheet.py +0 -0
  119. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_action_sheet_action.py +0 -0
  120. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_activity_indicator.py +0 -0
  121. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_alert_dialog.py +0 -0
  122. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_app_bar.py +0 -0
  123. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_bottom_sheet.py +0 -0
  124. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_button.py +0 -0
  125. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_checkbox.py +0 -0
  126. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_colors.py +0 -0
  127. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_context_menu.py +0 -0
  128. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_context_menu_action.py +0 -0
  129. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_date_picker.py +0 -0
  130. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_dialog_action.py +0 -0
  131. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_filled_button.py +0 -0
  132. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_icons.json +0 -0
  133. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_icons.py +0 -0
  134. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_icons.pyi +0 -0
  135. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_list_tile.py +0 -0
  136. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_navigation_bar.py +0 -0
  137. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_picker.py +0 -0
  138. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_radio.py +0 -0
  139. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_segmented_button.py +0 -0
  140. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_slider.py +0 -0
  141. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_sliding_segmented_button.py +0 -0
  142. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_switch.py +0 -0
  143. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_textfield.py +0 -0
  144. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_timer_picker.py +0 -0
  145. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/cupertino/cupertino_tinted_button.py +0 -0
  146. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/device_info.py +0 -0
  147. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/dialog_control.py +0 -0
  148. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/duration.py +0 -0
  149. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/embed_json_encoder.py +0 -0
  150. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/events.py +0 -0
  151. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/exceptions.py +0 -0
  152. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/geometry.py +0 -0
  153. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/gradients.py +0 -0
  154. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/icon_data.py +0 -0
  155. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/id_counter.py +0 -0
  156. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/keys.py +0 -0
  157. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/layout_control.py +0 -0
  158. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/margin.py +0 -0
  159. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/__init__.py +0 -0
  160. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/alert_dialog.py +0 -0
  161. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/app_bar.py +0 -0
  162. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/auto_complete.py +0 -0
  163. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/badge.py +0 -0
  164. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/banner.py +0 -0
  165. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/bottom_app_bar.py +0 -0
  166. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/bottom_sheet.py +0 -0
  167. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/button.py +0 -0
  168. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/card.py +0 -0
  169. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/checkbox.py +0 -0
  170. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/chip.py +0 -0
  171. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/circle_avatar.py +0 -0
  172. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/container.py +0 -0
  173. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/context_menu.py +0 -0
  174. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/datatable.py +0 -0
  175. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/date_picker.py +0 -0
  176. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/date_range_picker.py +0 -0
  177. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/divider.py +0 -0
  178. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/dropdown.py +0 -0
  179. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/dropdownm2.py +0 -0
  180. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/elevated_button.py +0 -0
  181. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/expansion_panel.py +0 -0
  182. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/expansion_tile.py +0 -0
  183. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/filled_button.py +0 -0
  184. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/filled_tonal_button.py +0 -0
  185. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/floating_action_button.py +0 -0
  186. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/form_field_control.py +0 -0
  187. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/icon_button.py +0 -0
  188. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/icons.json +0 -0
  189. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/icons.py +0 -0
  190. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/icons.pyi +0 -0
  191. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/list_tile.py +0 -0
  192. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/menu_bar.py +0 -0
  193. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/menu_item_button.py +0 -0
  194. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/navigation_bar.py +0 -0
  195. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/navigation_drawer.py +0 -0
  196. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/navigation_rail.py +0 -0
  197. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/outlined_button.py +0 -0
  198. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/popup_menu_button.py +0 -0
  199. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/progress_bar.py +0 -0
  200. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/progress_ring.py +0 -0
  201. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/radio.py +0 -0
  202. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/radio_group.py +0 -0
  203. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/range_slider.py +0 -0
  204. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/reorderable_list_view.py +0 -0
  205. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/search_bar.py +0 -0
  206. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/segmented_button.py +0 -0
  207. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/selection_area.py +0 -0
  208. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/slider.py +0 -0
  209. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/snack_bar.py +0 -0
  210. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/submenu_button.py +0 -0
  211. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/switch.py +0 -0
  212. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/tabs.py +0 -0
  213. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/text_button.py +0 -0
  214. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/textfield.py +0 -0
  215. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/time_picker.py +0 -0
  216. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/material/vertical_divider.py +0 -0
  217. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/multi_view.py +0 -0
  218. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/object_patch.py +0 -0
  219. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/padding.py +0 -0
  220. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/page.py +0 -0
  221. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/painting.py +0 -0
  222. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/query_string.py +0 -0
  223. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/ref.py +0 -0
  224. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/scrollable_control.py +0 -0
  225. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/__init__.py +0 -0
  226. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/accelerometer.py +0 -0
  227. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/barometer.py +0 -0
  228. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/battery.py +0 -0
  229. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/browser_context_menu.py +0 -0
  230. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/clipboard.py +0 -0
  231. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/connectivity.py +0 -0
  232. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/file_picker.py +0 -0
  233. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/gyroscope.py +0 -0
  234. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/haptic_feedback.py +0 -0
  235. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/magnetometer.py +0 -0
  236. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/screen_brightness.py +0 -0
  237. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/semantics_service.py +0 -0
  238. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/sensor_error_event.py +0 -0
  239. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/service.py +0 -0
  240. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/shake_detector.py +0 -0
  241. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/share.py +0 -0
  242. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/shared_preferences.py +0 -0
  243. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/storage_paths.py +0 -0
  244. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/url_launcher.py +0 -0
  245. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/user_accelerometer.py +0 -0
  246. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/services/wakelock.py +0 -0
  247. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/template_route.py +0 -0
  248. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/text_style.py +0 -0
  249. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/transform.py +0 -0
  250. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/controls/value_types.py +0 -0
  251. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/fastapi/__init__.py +0 -0
  252. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/messaging/connection.py +0 -0
  253. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/messaging/flet_socket_server.py +0 -0
  254. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/messaging/protocol.py +0 -0
  255. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/messaging/pyodide_connection.py +0 -0
  256. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/messaging/session.py +0 -0
  257. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/messaging/session_store.py +0 -0
  258. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/pubsub/__init__.py +0 -0
  259. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/pubsub/pubsub_client.py +0 -0
  260. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/pubsub/pubsub_hub.py +0 -0
  261. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/py.typed +0 -0
  262. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/security/__init__.py +0 -0
  263. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/testing/__init__.py +0 -0
  264. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/testing/finder.py +0 -0
  265. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/testing/flet_test_app.py +0 -0
  266. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/testing/tester.py +0 -0
  267. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/__init__.py +0 -0
  268. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/browser.py +0 -0
  269. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/classproperty.py +0 -0
  270. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/deprecated.py +0 -0
  271. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/deprecated_enum.py +0 -0
  272. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/files.py +0 -0
  273. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/from_dict.py +0 -0
  274. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/griffe_deprecations.py +0 -0
  275. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/hashing.py +0 -0
  276. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/json_utils.py +0 -0
  277. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/linux_deps.py +0 -0
  278. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/locks.py +0 -0
  279. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/network.py +0 -0
  280. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/object_model.py +0 -0
  281. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/once.py +0 -0
  282. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/pip.py +0 -0
  283. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/platform_utils.py +0 -0
  284. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/slugify.py +0 -0
  285. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/strings.py +0 -0
  286. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/typing_utils.py +0 -0
  287. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/validation.py +0 -0
  288. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet/utils/vector.py +0 -0
  289. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet.egg-info/dependency_links.txt +0 -0
  290. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet.egg-info/entry_points.txt +0 -0
  291. {flet-0.85.0.dev4 → flet-0.85.2}/src/flet.egg-info/top_level.txt +0 -0
  292. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_auth_lazy_imports.py +0 -0
  293. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_base_control.py +0 -0
  294. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_colors.py +0 -0
  295. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_component_diff.py +0 -0
  296. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_component_effects.py +0 -0
  297. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_component_renderer.py +0 -0
  298. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_dataclasses.py +0 -0
  299. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_datetime.py +0 -0
  300. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_deprecated.py +0 -0
  301. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_events.py +0 -0
  302. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_from_dict.py +0 -0
  303. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_griffe_deprecations.py +0 -0
  304. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_icons.py +0 -0
  305. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_object_diff_frozen.py +0 -0
  306. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_object_diff_in_place.py +0 -0
  307. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_object_diff_memory_churn.py +0 -0
  308. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_object_diff_performance.py +0 -0
  309. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_observable.py +0 -0
  310. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_patch_dataclass.py +0 -0
  311. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_session_disconnect_buffering.py +0 -0
  312. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_skip_double_update.py +0 -0
  313. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_use_dialog.py +0 -0
  314. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_validation.py +0 -0
  315. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_validation_benchmark.py +0 -0
  316. {flet-0.85.0.dev4 → flet-0.85.2}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flet
3
- Version: 0.85.0.dev4
3
+ Version: 0.85.2
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
@@ -9,23 +9,23 @@ Project-URL: Repository, https://github.com/flet-dev/flet
9
9
  Project-URL: Documentation, https://flet.dev/docs/
10
10
  Requires-Python: >=3.10
11
11
  Description-Content-Type: text/markdown
12
- Requires-Dist: flet-cli==0.85.0.dev4; extra == "cli"
13
- Requires-Dist: flet-web==0.85.0.dev4; extra == "web"
14
- Requires-Dist: oauthlib>=3.2.2; platform_system != "Pyodide"
15
- Requires-Dist: httpx>=0.28.1; platform_system != "Pyodide"
12
+ Requires-Dist: flet-cli==0.85.2; extra == "cli"
13
+ Requires-Dist: flet-web==0.85.2; extra == "web"
14
+ Requires-Dist: oauthlib>=3.2.2; platform_system != "Emscripten"
15
+ Requires-Dist: httpx>=0.28.1; platform_system != "Emscripten"
16
16
  Requires-Dist: repath>=0.9.0
17
17
  Requires-Dist: msgpack>=1.1.0
18
18
  Requires-Dist: typing-extensions; python_version < "3.11"
19
19
  Provides-Extra: all
20
- Requires-Dist: flet-cli==0.85.0.dev4; extra == "all"
21
- Requires-Dist: flet-web==0.85.0.dev4; extra == "all"
22
- Requires-Dist: flet-desktop==0.85.0.dev4; extra == "all"
20
+ Requires-Dist: flet-cli==0.85.2; extra == "all"
21
+ Requires-Dist: flet-web==0.85.2; extra == "all"
22
+ Requires-Dist: flet-desktop==0.85.2; extra == "all"
23
23
  Provides-Extra: cli
24
- Requires-Dist: flet-cli==0.85.0.dev4; extra == "cli"
24
+ Requires-Dist: flet-cli==0.85.2; extra == "cli"
25
25
  Provides-Extra: desktop
26
- Requires-Dist: flet-desktop==0.85.0.dev4; extra == "desktop"
26
+ Requires-Dist: flet-desktop==0.85.2; extra == "desktop"
27
27
  Provides-Extra: web
28
- Requires-Dist: flet-web==0.85.0.dev4; extra == "web"
28
+ Requires-Dist: flet-web==0.85.2; extra == "web"
29
29
 
30
30
  <p align="center">
31
31
  <a href="https://flet.dev"><img src="https://raw.githubusercontent.com/flet-dev/flet/refs/heads/main/media/logo/flet-logo.svg" height="150" alt="Flet logo"></a>
@@ -1,16 +1,16 @@
1
1
  [project]
2
2
  name = "flet"
3
- version = "0.85.0.dev4"
3
+ version = "0.85.2"
4
4
  description = "Flet for Python - easily build interactive multi-platform apps in Python"
5
5
  authors = [{name = "Appveyor Systems Inc.", email = "hello@flet.dev"}]
6
6
  license = "Apache-2.0"
7
7
  readme = "README.md"
8
8
  requires-python = ">=3.10"
9
9
  dependencies = [
10
- "flet-cli==0.85.0.dev4; extra == 'cli'",
11
- "flet-web==0.85.0.dev4; extra == 'web'",
12
- "oauthlib >=3.2.2; platform_system != 'Pyodide'",
13
- "httpx >=0.28.1; platform_system != 'Pyodide'",
10
+ "flet-cli==0.85.2; extra == 'cli'",
11
+ "flet-web==0.85.2; extra == 'web'",
12
+ "oauthlib >=3.2.2; platform_system != 'Emscripten'",
13
+ "httpx >=0.28.1; platform_system != 'Emscripten'",
14
14
  "repath >=0.9.0",
15
15
  "msgpack >=1.1.0",
16
16
  "typing-extensions; python_version < '3.11'"
@@ -23,15 +23,15 @@ Documentation = "https://flet.dev/docs/"
23
23
 
24
24
  [project.optional-dependencies]
25
25
  all = [
26
- "flet-cli==0.85.0.dev4",
27
- "flet-web==0.85.0.dev4",
28
- "flet-desktop==0.85.0.dev4",
26
+ "flet-cli==0.85.2",
27
+ "flet-web==0.85.2",
28
+ "flet-desktop==0.85.2",
29
29
  ]
30
- cli = ["flet-cli==0.85.0.dev4"]
30
+ cli = ["flet-cli==0.85.2"]
31
31
  desktop = [
32
- "flet-desktop==0.85.0.dev4",
32
+ "flet-desktop==0.85.2",
33
33
  ]
34
- web = ["flet-web==0.85.0.dev4"]
34
+ web = ["flet-web==0.85.2"]
35
35
 
36
36
  [project.scripts]
37
37
  flet = "flet.cli:main"
@@ -71,6 +71,31 @@ class Route:
71
71
  :func:`~flet.use_route_outlet` within a single
72
72
  :class:`~flet.View`, instead of each child becoming a separate
73
73
  :class:`~flet.View`.
74
+ modal: When ``True`` and ``manage_views=True``, the route's View
75
+ is rendered as a modal overlay on top of the existing stack
76
+ instead of replacing it. The route's component should set
77
+ ``fullscreen_dialog=True`` on its returned :class:`~flet.View`
78
+ so Flutter renders the slide-up presentation and a close (X)
79
+ icon. Placement controls the base stack:
80
+
81
+ * Declared at the **top level**: a *global* modal. The base
82
+ stack is rebuilt from the last non-modal location the
83
+ Router saw (defaults to ``"/"`` on first render).
84
+ * Declared as a **child** of a non-modal route: a *local*
85
+ modal. The base stack is the chain above the modal in the
86
+ route tree, so deep-link works from the URL alone.
87
+
88
+ On pop, the Router navigates to the resolved URL of the
89
+ non-modal parent — never to ``views[-2].route`` — so a
90
+ modal close is always a real navigation back to the
91
+ base location.
92
+ recursive: When ``True``, the route can match itself as its own
93
+ descendant — one matched ``_RouteMatch`` per consumed segment.
94
+ Useful for tree-shaped URLs with unbounded depth
95
+ (e.g. ``/folder/a/b/c``) where each segment should become its
96
+ own stack entry. Non-recursive children are tried before
97
+ self-recursion at every depth so a more specific sibling
98
+ (e.g. ``example/:gp*``) wins over the recursive ``:slug``.
74
99
  """
75
100
 
76
101
  path: str | None = None
@@ -79,6 +104,8 @@ class Route:
79
104
  children: list[Route] | None = field(default=None)
80
105
  loader: Callable[..., Any] | None = None
81
106
  outlet: bool = False
107
+ modal: bool = False
108
+ recursive: bool = False
82
109
 
83
110
 
84
111
  @dataclass
@@ -192,6 +219,43 @@ def _try_match(
192
219
  if not full_path:
193
220
  full_path = "/"
194
221
 
222
+ if route.recursive:
223
+ # Recursive routes consume one matched segment per recursion and
224
+ # try non-recursive children before self-recursing — so a more
225
+ # specific sibling (e.g. ``example/:gp*``) wins over the
226
+ # recursive ``:slug`` at every depth without duplicate
227
+ # declarations.
228
+ prefix_pattern = repath.pattern(full_path, end=False)
229
+ prefix_m = re.match(prefix_pattern, pathname)
230
+ if not prefix_m:
231
+ return None
232
+ consumed = prefix_m.group(0)
233
+ head = _RouteMatch(
234
+ route=route,
235
+ params=prefix_m.groupdict(),
236
+ full_path=full_path,
237
+ resolved_path=consumed,
238
+ )
239
+ # Fully consumed → this is the leaf. Accept either an exact
240
+ # match or a trailing "/" remainder (so /folder/a and
241
+ # /folder/a/ both terminate cleanly).
242
+ remainder = pathname[len(consumed) :]
243
+ if not remainder or remainder == "/":
244
+ return [head]
245
+ # 1) Try non-recursive children first (more specific match).
246
+ for child in route.children or []:
247
+ if child is route:
248
+ continue
249
+ child_result = _try_match(child, pathname, consumed)
250
+ if child_result is not None:
251
+ return [head] + child_result
252
+ # 2) Fall back to self-recursion with the consumed prefix as
253
+ # the parent path.
254
+ recurse = _try_match(route, pathname, consumed)
255
+ if recurse is None:
256
+ return None
257
+ return [head] + recurse
258
+
195
259
  if route.children:
196
260
  # Parent route — try prefix match to extract params, then match children
197
261
  parent_params: dict[str, str] = {}
@@ -576,6 +640,22 @@ def Router(
576
640
  location, set_location = use_state(page.route or "/")
577
641
  prev_route_handler_ref = use_ref(None)
578
642
  prev_pop_handler_ref = use_ref(None)
643
+ # Last non-modal location the Router saw. Used as the base for
644
+ # global modal routes (declared at the top level) — when the user
645
+ # navigates from /apps/X to /settings (modal=True), the modal is
646
+ # rendered ON TOP OF the chain matched against /apps/X, so closing
647
+ # it reveals the original stack instead of rebuilding it.
648
+ prev_non_modal_location_ref = use_ref(None)
649
+ # Snapshot of the chain emitted for the current location. Used by
650
+ # the default pop handler to compute the parent URL structurally
651
+ # (``chain[-2].resolved_path``), which survives shared ``view.route``
652
+ # keys (e.g. an app that uses the same route key for two sibling
653
+ # tab roots to suppress switch animations).
654
+ current_chain_ref = use_ref(None)
655
+ # URL to navigate to when popping the topmost view, IF the current
656
+ # chain ends in a modal route. ``None`` otherwise. Set whenever a
657
+ # modal route matches.
658
+ current_modal_pop_to_ref = use_ref(None)
579
659
 
580
660
  # Subscribe to route changes on mount
581
661
  def setup_listeners():
@@ -590,13 +670,36 @@ def Router(
590
670
  prev_pop_handler_ref.current = page.on_view_pop
591
671
 
592
672
  def on_view_pop(e):
593
- from flet.components.public_utils import unwrap_component
594
-
595
- views_list = unwrap_component(page.views)
596
- if isinstance(views_list, list) and len(views_list) > 1:
597
- prev_view = unwrap_component(views_list[-2])
598
- if prev_view is not None:
599
- page.navigate(prev_view.route)
673
+ # If the app installed its own `page.on_view_pop` before
674
+ # the Router mounted, delegate to it. Apps can still
675
+ # override entirely (e.g. for a stack visualisation or
676
+ # confirmation flow).
677
+ prev = prev_pop_handler_ref.current
678
+ if prev is not None:
679
+ prev(e)
680
+ return
681
+
682
+ # Modal pop: navigate to the base URL stamped at emit
683
+ # time. Same logic for global and local modals — the
684
+ # base URL was resolved when the modal was matched.
685
+ if current_modal_pop_to_ref.current is not None:
686
+ page.navigate(current_modal_pop_to_ref.current)
687
+ return
688
+
689
+ # Non-modal pop: use the matched chain's parent route
690
+ # (route-tree-structural) rather than
691
+ # ``views[-2].route``. This survives shared view keys
692
+ # like a tab-root layout that emits ``route="/"`` for
693
+ # multiple sibling sections.
694
+ chain_now = current_chain_ref.current
695
+ if chain_now and len(chain_now) > 1:
696
+ parent_match = chain_now[-2]
697
+ target = parent_match.resolved_path or parent_match.full_path or "/"
698
+ page.navigate(target)
699
+ return
700
+
701
+ # Stack of length 1 — nothing to pop to. (Flutter's
702
+ # ``Navigator.canPop`` is False here anyway.)
600
703
 
601
704
  page.on_view_pop = on_view_pop
602
705
 
@@ -621,10 +724,66 @@ def Router(
621
724
  if manage_views:
622
725
  from flet.controls.core.view import View
623
726
 
727
+ # Reset state so a stale modal pop_to doesn't leak into
728
+ # a 404'd location.
729
+ current_chain_ref.current = None
730
+ current_modal_pop_to_ref.current = None
624
731
  return [View(route=pathname, controls=[not_found()])]
625
732
  return not_found()
626
733
  return None
627
734
 
735
+ # Detect modal routes in the chain. ``modal_idx`` is the index of
736
+ # the first route in the chain with ``modal=True``; ``-1`` means
737
+ # the chain is fully non-modal.
738
+ modal_idx = -1
739
+ for i, m in enumerate(chain):
740
+ if m.route.modal:
741
+ modal_idx = i
742
+ break
743
+
744
+ # For a *global* modal (``modal_idx == 0`` — the chain starts at a
745
+ # modal with no non-modal parents) we want the visible stack to be
746
+ # the chain of the previously visited non-modal location +
747
+ # the modal's own chain. This way the underlying stack stays mounted
748
+ # underneath the modal — closing the modal reveals it without a
749
+ # rebuild.
750
+ if manage_views and modal_idx == 0:
751
+ base_location = prev_non_modal_location_ref.current or "/"
752
+ base_pathname = _normalize_path(urlparse(base_location).path or "/")
753
+ base_chain = _match_routes(routes, base_pathname) or []
754
+ # If the base path also resolves to a modal (shouldn't happen
755
+ # in practice — non-modal navigations are the only ones that
756
+ # update prev_non_modal_location_ref), fall back to no base.
757
+ if any(b.route.modal for b in base_chain):
758
+ base_chain = []
759
+ # Combine: base lives below, modal sits on top.
760
+ chain = base_chain + chain
761
+ # Re-locate the modal index in the combined chain.
762
+ modal_idx = len(base_chain)
763
+
764
+ # Track refs that downstream consumers (default pop handler, etc.)
765
+ # read. ``current_chain_ref`` always reflects the chain we're
766
+ # actually emitting. ``current_modal_pop_to_ref`` is set only when
767
+ # the chain ends in a modal — non-modal navigations clear it.
768
+ current_chain_ref.current = chain
769
+ if modal_idx == -1:
770
+ # Non-modal navigation — remember it as the next base.
771
+ prev_non_modal_location_ref.current = location
772
+ current_modal_pop_to_ref.current = None
773
+ else:
774
+ # Modal route — the URL to pop to is the resolved URL of the
775
+ # last non-modal entry in the chain.
776
+ if modal_idx > 0:
777
+ parent = chain[modal_idx - 1]
778
+ current_modal_pop_to_ref.current = (
779
+ parent.resolved_path or parent.full_path or "/"
780
+ )
781
+ else:
782
+ # No non-modal parent in the chain (rare — would require a
783
+ # deep-link to a top-level modal with no remembered base
784
+ # AND an empty default match). Fall back to "/".
785
+ current_modal_pop_to_ref.current = "/"
786
+
628
787
  # Merge all params from the chain
629
788
  all_params: dict[str, str] = {}
630
789
  for m in chain:
@@ -640,7 +799,8 @@ def Router(
640
799
  loc = LocationInfo(pathname=pathname, search=search, hash=hash_val)
641
800
 
642
801
  if not manage_views:
643
- # Single-view mode (existing behavior)
802
+ # Single-view mode (existing behavior). ``modal`` is ignored
803
+ # here — it only affects stack composition in multi-view mode.
644
804
  return _location_context(
645
805
  loc,
646
806
  lambda: _params_context(
@@ -653,47 +813,81 @@ def Router(
653
813
  # route, etc.). The Router sets route and can_pop on each View
654
814
  # after the component body executes (via the patch walk).
655
815
  # Used with page.render_views(App).
656
- layouts, view_entries = _split_chain_into_view_levels(chain)
816
+ #
817
+ # If the chain contains a modal route, split into two independent
818
+ # sub-chains at the modal boundary. Each sub-chain is classified
819
+ # into layouts vs. view entries SEPARATELY so that an outlet route
820
+ # that would be a leaf view in its own sub-chain doesn't get
821
+ # re-classified as a layout just because there's more chain after
822
+ # the boundary. ``modal_idx`` already points to the modal route in
823
+ # the (possibly combined) chain.
824
+ # ``modal_idx <= 0`` covers both the no-modal case (``-1``) and a
825
+ # degenerate modal chain with no base (``0``) — neither is split.
826
+ sub_chains = [chain] if modal_idx <= 0 else [chain[:modal_idx], chain[modal_idx:]]
827
+
828
+ # Each sub-chain's views see their own URL via the location
829
+ # context. The base sub-chain (when there's a modal split) sees the
830
+ # remembered non-modal location it was matched against — so
831
+ # ``is_route_active("/gallery")`` inside a base view stays True
832
+ # while a global ``/settings`` modal is open over Gallery.
833
+ base_sub_loc = LocationInfo(pathname=pathname, search=search, hash=hash_val)
834
+ if modal_idx > 0:
835
+ base_loc_str = prev_non_modal_location_ref.current or "/"
836
+ base_parsed = urlparse(base_loc_str)
837
+ base_sub_loc = LocationInfo(
838
+ pathname=_normalize_path(base_parsed.path or "/"),
839
+ search=base_parsed.query or "",
840
+ hash=base_parsed.fragment or "",
841
+ )
657
842
 
658
843
  results = []
659
- for match, _ in view_entries:
660
- # Params accumulated up to this view level
661
- level_params: dict[str, str] = {}
662
- for m in chain:
663
- level_params.update(m.params)
664
- if m is match:
665
- break
666
-
667
- # LocationInfo.pathname is the actual URL (not the route template),
668
- # so is_route_active() and use_route_location() work consistently.
669
- level_loc = LocationInfo(pathname=pathname, search=search, hash=hash_val)
670
- # Per-view resolved URL — unique per view level for Navigator keying.
671
- level_view_path = match.resolved_path or match.full_path or "/"
672
- _match = match
673
- # Only apply layouts that appear before this view entry in the chain
674
- match_idx = chain.index(match)
675
- _layouts = [lm for lm in layouts if chain.index(lm) < match_idx]
676
-
677
- def build_view_content(
678
- _match=_match,
679
- _layouts=_layouts,
680
- _level_params=level_params,
681
- _level_loc=level_loc,
682
- _level_view_path=level_view_path,
683
- ):
684
- return _view_path_context(
685
- _level_view_path,
686
- lambda: _location_context(
687
- _level_loc,
688
- lambda: _params_context(
689
- _level_params,
690
- lambda: _build_view_level(
691
- _layouts, _match, loader_results, chain
844
+ for sub_chain_idx, sub_chain in enumerate(sub_chains):
845
+ layouts, view_entries = _split_chain_into_view_levels(sub_chain)
846
+ # The base sub-chain (everything before the modal) is rendered
847
+ # "as if" the user is at the previous non-modal URL; the modal
848
+ # sub-chain is rendered at the modal URL.
849
+ sub_loc = base_sub_loc if (modal_idx > 0 and sub_chain_idx == 0) else loc
850
+ for match, _ in view_entries:
851
+ # Params accumulated up to this view level — within the
852
+ # combined chain so a local modal view still sees its
853
+ # parents' captures.
854
+ level_params: dict[str, str] = {}
855
+ for m in chain:
856
+ level_params.update(m.params)
857
+ if m is match:
858
+ break
859
+
860
+ # Per-view resolved URL unique per view level for
861
+ # Navigator keying.
862
+ level_view_path = match.resolved_path or match.full_path or "/"
863
+ _match = match
864
+ # Only apply layouts that appear before this view entry IN
865
+ # THE SAME SUB-CHAIN. A modal view never inherits the
866
+ # base's layouts (and vice versa).
867
+ match_idx = sub_chain.index(match)
868
+ _layouts = [lm for lm in layouts if sub_chain.index(lm) < match_idx]
869
+
870
+ def build_view_content(
871
+ _match=_match,
872
+ _layouts=_layouts,
873
+ _level_params=level_params,
874
+ _level_loc=sub_loc,
875
+ _level_view_path=level_view_path,
876
+ _sub_chain=sub_chain,
877
+ ):
878
+ return _view_path_context(
879
+ _level_view_path,
880
+ lambda: _location_context(
881
+ _level_loc,
882
+ lambda: _params_context(
883
+ _level_params,
884
+ lambda: _build_view_level(
885
+ _layouts, _match, loader_results, _sub_chain
886
+ ),
692
887
  ),
693
888
  ),
694
- ),
695
- )
889
+ )
696
890
 
697
- results.append(build_view_content())
891
+ results.append(build_view_content())
698
892
 
699
893
  return results
@@ -1,10 +1,6 @@
1
- from dataclasses import field
2
1
  from typing import Optional, Union
3
2
 
4
3
  from flet.controls.base_control import value
5
- from flet.controls.border_radius import (
6
- BorderRadius,
7
- )
8
4
  from flet.controls.box import BoxConstraints, BoxDecoration
9
5
  from flet.controls.duration import DurationValue
10
6
  from flet.controls.margin import MarginValue
@@ -44,20 +40,40 @@ class TooltipTriggerMode:
44
40
  @value
45
41
  class Tooltip:
46
42
  """
47
- Provide text labels which help explain the function of a button or other user \
48
- interface action.
43
+ Provide text labels which help explain the function of a button
44
+ or other user interface action.
49
45
  """
50
46
 
51
47
  message: str
52
48
  """
53
- The text to display in the tooltip.
49
+ The text to display in this tooltip.
54
50
  """
55
51
 
56
- decoration: Optional[BoxDecoration] = field(
57
- default_factory=lambda: BoxDecoration(border_radius=BorderRadius.all(4.0))
58
- )
52
+ decoration: Optional[BoxDecoration] = None
59
53
  """
60
- The tooltip's background decoration.
54
+ The background decoration of this tooltip.
55
+
56
+ If `None`, :attr:`flet.TooltipTheme.decoration` is used.
57
+ If that is also `None`, a default decoration will be picked based
58
+ on the current theme mode:
59
+
60
+ In light theme mode:
61
+
62
+ ```python
63
+ ft.BoxDecoration(
64
+ border_radius=ft.BorderRadius.all(4.0),
65
+ bgcolor=ft.Colors.with_opacity(0.9, ft.Colors.GREY_700),
66
+ )
67
+ ```
68
+
69
+ In dark theme mode:
70
+
71
+ ```python
72
+ ft.BoxDecoration(
73
+ border_radius=ft.BorderRadius.all(4.0),
74
+ bgcolor=ft.Colors.with_opacity(0.9, ft.Colors.WHITE),
75
+ )
76
+ ```
61
77
  """
62
78
 
63
79
  enable_feedback: Optional[bool] = None
@@ -3406,6 +3406,9 @@ class Theme:
3406
3406
  disabled_color: Optional[ColorValue] = None
3407
3407
  canvas_color: Optional[ColorValue] = None
3408
3408
  scaffold_bgcolor: Optional[ColorValue] = None
3409
+ """
3410
+ Customizes the page background color.
3411
+ """
3409
3412
  card_bgcolor: Optional[ColorValue] = None
3410
3413
  hint_color: Optional[ColorValue] = None
3411
3414
  secondary_header_color: Optional[ColorValue] = None
@@ -1307,7 +1307,7 @@ Represents a color and can be:
1307
1307
  - a material color from the :class:`~flet.Colors` enum,
1308
1308
  - or a Cupertino color from the :class:`~flet.CupertinoColors` enum.
1309
1309
 
1310
- More information [here](https://flet.dev/docs/cookbook/cookbook/cookbook/colors).
1310
+ More information [here](https://flet.dev/docs/cookbook/colors).
1311
1311
  """
1312
1312
 
1313
1313
  # Icons
@@ -17,7 +17,7 @@ __all__ = [
17
17
  ]
18
18
 
19
19
  # set by CI
20
- flet_version = "0.85.0.dev4"
20
+ flet_version = "0.85.2"
21
21
  """
22
22
  The Flet version in use.
23
23
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flet
3
- Version: 0.85.0.dev4
3
+ Version: 0.85.2
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
@@ -9,23 +9,23 @@ Project-URL: Repository, https://github.com/flet-dev/flet
9
9
  Project-URL: Documentation, https://flet.dev/docs/
10
10
  Requires-Python: >=3.10
11
11
  Description-Content-Type: text/markdown
12
- Requires-Dist: flet-cli==0.85.0.dev4; extra == "cli"
13
- Requires-Dist: flet-web==0.85.0.dev4; extra == "web"
14
- Requires-Dist: oauthlib>=3.2.2; platform_system != "Pyodide"
15
- Requires-Dist: httpx>=0.28.1; platform_system != "Pyodide"
12
+ Requires-Dist: flet-cli==0.85.2; extra == "cli"
13
+ Requires-Dist: flet-web==0.85.2; extra == "web"
14
+ Requires-Dist: oauthlib>=3.2.2; platform_system != "Emscripten"
15
+ Requires-Dist: httpx>=0.28.1; platform_system != "Emscripten"
16
16
  Requires-Dist: repath>=0.9.0
17
17
  Requires-Dist: msgpack>=1.1.0
18
18
  Requires-Dist: typing-extensions; python_version < "3.11"
19
19
  Provides-Extra: all
20
- Requires-Dist: flet-cli==0.85.0.dev4; extra == "all"
21
- Requires-Dist: flet-web==0.85.0.dev4; extra == "all"
22
- Requires-Dist: flet-desktop==0.85.0.dev4; extra == "all"
20
+ Requires-Dist: flet-cli==0.85.2; extra == "all"
21
+ Requires-Dist: flet-web==0.85.2; extra == "all"
22
+ Requires-Dist: flet-desktop==0.85.2; extra == "all"
23
23
  Provides-Extra: cli
24
- Requires-Dist: flet-cli==0.85.0.dev4; extra == "cli"
24
+ Requires-Dist: flet-cli==0.85.2; extra == "cli"
25
25
  Provides-Extra: desktop
26
- Requires-Dist: flet-desktop==0.85.0.dev4; extra == "desktop"
26
+ Requires-Dist: flet-desktop==0.85.2; extra == "desktop"
27
27
  Provides-Extra: web
28
- Requires-Dist: flet-web==0.85.0.dev4; extra == "web"
28
+ Requires-Dist: flet-web==0.85.2; extra == "web"
29
29
 
30
30
  <p align="center">
31
31
  <a href="https://flet.dev"><img src="https://raw.githubusercontent.com/flet-dev/flet/refs/heads/main/media/logo/flet-logo.svg" height="150" alt="Flet logo"></a>
@@ -303,6 +303,8 @@ tests/test_object_diff_memory_churn.py
303
303
  tests/test_object_diff_performance.py
304
304
  tests/test_observable.py
305
305
  tests/test_patch_dataclass.py
306
+ tests/test_router_modal.py
307
+ tests/test_router_recursive.py
306
308
  tests/test_session_disconnect_buffering.py
307
309
  tests/test_skip_double_update.py
308
310
  tests/test_use_dialog.py
@@ -0,0 +1,29 @@
1
+ repath>=0.9.0
2
+ msgpack>=1.1.0
3
+
4
+ [:extra == "cli"]
5
+ flet-cli==0.85.2
6
+
7
+ [:extra == "web"]
8
+ flet-web==0.85.2
9
+
10
+ [:platform_system != "Emscripten"]
11
+ oauthlib>=3.2.2
12
+ httpx>=0.28.1
13
+
14
+ [:python_version < "3.11"]
15
+ typing-extensions
16
+
17
+ [all]
18
+ flet-cli==0.85.2
19
+ flet-web==0.85.2
20
+ flet-desktop==0.85.2
21
+
22
+ [cli]
23
+ flet-cli==0.85.2
24
+
25
+ [desktop]
26
+ flet-desktop==0.85.2
27
+
28
+ [web]
29
+ flet-web==0.85.2