flet 0.85.1__tar.gz → 0.85.3.dev0__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.
- {flet-0.85.1 → flet-0.85.3.dev0}/PKG-INFO +9 -9
- {flet-0.85.1 → flet-0.85.3.dev0}/pyproject.toml +9 -9
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/router.py +279 -76
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/icon.py +1 -1
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/keys.py +1 -1
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/radio_group.py +2 -2
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/page.py +2 -2
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/types.py +1 -1
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/messaging/session_store.py +3 -3
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/testing/flet_test_app.py +10 -10
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/object_model.py +4 -4
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/version.py +1 -1
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet.egg-info/PKG-INFO +9 -9
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet.egg-info/SOURCES.txt +3 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet.egg-info/requires.txt +8 -8
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_component_diff.py +8 -8
- flet-0.85.3.dev0/tests/test_router_modal.py +180 -0
- flet-0.85.3.dev0/tests/test_router_pop.py +94 -0
- flet-0.85.3.dev0/tests/test_router_recursive.py +251 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/README.md +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/setup.cfg +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/app.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/auth/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/auth/authorization.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/auth/authorization_service.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/auth/group.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/auth/oauth_provider.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/auth/oauth_token.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/auth/providers/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/auth/providers/auth0_oauth_provider.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/auth/providers/azure_oauth_provider.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/auth/providers/github_oauth_provider.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/auth/providers/google_oauth_provider.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/auth/user.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/canvas/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/cli.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/component.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/component_decorator.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/component_owned.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/hooks/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/hooks/hook.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/hooks/use_callback.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/hooks/use_context.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/hooks/use_dialog.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/hooks/use_effect.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/hooks/use_memo.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/hooks/use_ref.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/hooks/use_state.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/memo.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/observable.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/public_utils.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/components/utils.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/adaptive_control.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/alignment.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/animation.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/base_control.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/base_page.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/blur.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/border.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/border_radius.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/box.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/buttons.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/colors.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/context.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/control.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/control_event.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/control_state.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/animated_switcher.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/autofill_group.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/arc.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/canvas.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/circle.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/color.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/fill.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/image.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/line.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/oval.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/path.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/points.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/rect.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/shadow.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/shape.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/canvas/text.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/column.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/dismissible.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/drag_target.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/draggable.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/flet_app.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/gesture_detector.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/grid_view.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/hero.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/image.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/interactive_viewer.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/keyboard_listener.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/list_view.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/markdown.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/merge_semantics.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/page_view.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/pagelet.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/placeholder.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/reorderable_drag_handle.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/responsive_row.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/rotated_box.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/row.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/safe_area.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/screenshot.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/semantics.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/shader_mask.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/shimmer.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/stack.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/text.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/text_span.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/transparent_pointer.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/view.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/window.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/core/window_drag_area.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_action_sheet.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_action_sheet_action.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_activity_indicator.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_alert_dialog.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_app_bar.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_bottom_sheet.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_checkbox.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_colors.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_context_menu.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_context_menu_action.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_date_picker.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_dialog_action.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_filled_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_icons.json +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_icons.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_icons.pyi +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_list_tile.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_navigation_bar.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_picker.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_radio.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_segmented_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_slider.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_sliding_segmented_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_switch.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_textfield.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_timer_picker.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/cupertino/cupertino_tinted_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/device_info.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/dialog_control.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/duration.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/embed_json_encoder.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/events.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/exceptions.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/geometry.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/gradients.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/icon_data.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/id_counter.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/layout_control.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/margin.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/alert_dialog.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/app_bar.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/auto_complete.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/badge.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/banner.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/bottom_app_bar.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/bottom_sheet.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/card.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/checkbox.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/chip.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/circle_avatar.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/container.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/context_menu.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/datatable.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/date_picker.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/date_range_picker.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/divider.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/dropdown.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/dropdownm2.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/elevated_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/expansion_panel.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/expansion_tile.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/filled_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/filled_tonal_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/floating_action_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/form_field_control.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/icon_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/icons.json +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/icons.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/icons.pyi +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/list_tile.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/menu_bar.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/menu_item_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/navigation_bar.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/navigation_drawer.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/navigation_rail.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/outlined_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/popup_menu_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/progress_bar.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/progress_ring.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/radio.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/range_slider.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/reorderable_list_view.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/search_bar.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/segmented_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/selection_area.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/slider.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/snack_bar.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/submenu_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/switch.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/tabs.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/text_button.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/textfield.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/time_picker.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/tooltip.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/material/vertical_divider.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/multi_view.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/object_patch.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/padding.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/painting.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/query_string.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/ref.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/scrollable_control.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/accelerometer.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/barometer.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/battery.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/browser_context_menu.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/clipboard.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/connectivity.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/file_picker.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/gyroscope.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/haptic_feedback.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/magnetometer.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/screen_brightness.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/semantics_service.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/sensor_error_event.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/service.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/shake_detector.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/share.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/shared_preferences.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/storage_paths.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/url_launcher.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/user_accelerometer.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/services/wakelock.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/template_route.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/text_style.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/theme.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/transform.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/controls/value_types.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/fastapi/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/messaging/connection.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/messaging/flet_socket_server.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/messaging/protocol.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/messaging/pyodide_connection.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/messaging/session.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/pubsub/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/pubsub/pubsub_client.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/pubsub/pubsub_hub.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/py.typed +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/security/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/testing/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/testing/finder.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/testing/tester.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/__init__.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/browser.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/classproperty.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/deprecated.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/deprecated_enum.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/files.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/from_dict.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/griffe_deprecations.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/hashing.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/json_utils.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/linux_deps.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/locks.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/network.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/once.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/pip.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/platform_utils.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/slugify.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/strings.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/typing_utils.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/validation.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet/utils/vector.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet.egg-info/dependency_links.txt +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet.egg-info/entry_points.txt +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/src/flet.egg-info/top_level.txt +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_auth_lazy_imports.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_base_control.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_colors.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_component_effects.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_component_renderer.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_dataclasses.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_datetime.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_deprecated.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_events.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_from_dict.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_griffe_deprecations.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_icons.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_object_diff_frozen.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_object_diff_in_place.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_object_diff_memory_churn.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_object_diff_performance.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_observable.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_patch_dataclass.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_session_disconnect_buffering.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_skip_double_update.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_use_dialog.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_validation.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_validation_benchmark.py +0 -0
- {flet-0.85.1 → flet-0.85.3.dev0}/tests/test_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flet
|
|
3
|
-
Version: 0.85.
|
|
3
|
+
Version: 0.85.3.dev0
|
|
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.
|
|
13
|
-
Requires-Dist: flet-web==0.85.
|
|
12
|
+
Requires-Dist: flet-cli==0.85.3.dev0; extra == "cli"
|
|
13
|
+
Requires-Dist: flet-web==0.85.3.dev0; extra == "web"
|
|
14
14
|
Requires-Dist: oauthlib>=3.2.2; platform_system != "Emscripten"
|
|
15
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.
|
|
21
|
-
Requires-Dist: flet-web==0.85.
|
|
22
|
-
Requires-Dist: flet-desktop==0.85.
|
|
20
|
+
Requires-Dist: flet-cli==0.85.3.dev0; extra == "all"
|
|
21
|
+
Requires-Dist: flet-web==0.85.3.dev0; extra == "all"
|
|
22
|
+
Requires-Dist: flet-desktop==0.85.3.dev0; extra == "all"
|
|
23
23
|
Provides-Extra: cli
|
|
24
|
-
Requires-Dist: flet-cli==0.85.
|
|
24
|
+
Requires-Dist: flet-cli==0.85.3.dev0; extra == "cli"
|
|
25
25
|
Provides-Extra: desktop
|
|
26
|
-
Requires-Dist: flet-desktop==0.85.
|
|
26
|
+
Requires-Dist: flet-desktop==0.85.3.dev0; extra == "desktop"
|
|
27
27
|
Provides-Extra: web
|
|
28
|
-
Requires-Dist: flet-web==0.85.
|
|
28
|
+
Requires-Dist: flet-web==0.85.3.dev0; 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,14 +1,14 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "flet"
|
|
3
|
-
version = "0.85.
|
|
3
|
+
version = "0.85.3.dev0"
|
|
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.
|
|
11
|
-
"flet-web==0.85.
|
|
10
|
+
"flet-cli==0.85.3.dev0; extra == 'cli'",
|
|
11
|
+
"flet-web==0.85.3.dev0; extra == 'web'",
|
|
12
12
|
"oauthlib >=3.2.2; platform_system != 'Emscripten'",
|
|
13
13
|
"httpx >=0.28.1; platform_system != 'Emscripten'",
|
|
14
14
|
"repath >=0.9.0",
|
|
@@ -23,15 +23,15 @@ Documentation = "https://flet.dev/docs/"
|
|
|
23
23
|
|
|
24
24
|
[project.optional-dependencies]
|
|
25
25
|
all = [
|
|
26
|
-
"flet-cli==0.85.
|
|
27
|
-
"flet-web==0.85.
|
|
28
|
-
"flet-desktop==0.85.
|
|
26
|
+
"flet-cli==0.85.3.dev0",
|
|
27
|
+
"flet-web==0.85.3.dev0",
|
|
28
|
+
"flet-desktop==0.85.3.dev0",
|
|
29
29
|
]
|
|
30
|
-
cli = ["flet-cli==0.85.
|
|
30
|
+
cli = ["flet-cli==0.85.3.dev0"]
|
|
31
31
|
desktop = [
|
|
32
|
-
"flet-desktop==0.85.
|
|
32
|
+
"flet-desktop==0.85.3.dev0",
|
|
33
33
|
]
|
|
34
|
-
web = ["flet-web==0.85.
|
|
34
|
+
web = ["flet-web==0.85.3.dev0"]
|
|
35
35
|
|
|
36
36
|
[project.scripts]
|
|
37
37
|
flet = "flet.cli:main"
|
|
@@ -47,30 +47,55 @@ class Route:
|
|
|
47
47
|
"""
|
|
48
48
|
Defines a single route in the route tree.
|
|
49
49
|
|
|
50
|
-
Routes can be nested via
|
|
51
|
-
A route with
|
|
50
|
+
Routes can be nested via `children` to create layout hierarchies.
|
|
51
|
+
A route with `component` and `children` acts as a layout route — its
|
|
52
52
|
component should call :func:`~flet.use_route_outlet` to render the
|
|
53
53
|
matched child.
|
|
54
54
|
|
|
55
55
|
Args:
|
|
56
|
-
path: Relative path segment. Supports dynamic segments (
|
|
57
|
-
optional segments (
|
|
58
|
-
regex constraints (
|
|
56
|
+
path: Relative path segment. Supports dynamic segments (`:name`),
|
|
57
|
+
optional segments (`:name?`), splats (`:name*`), and custom
|
|
58
|
+
regex constraints (`:name(\\\\d+)`). `None` for pathless
|
|
59
59
|
layout routes.
|
|
60
|
-
index: When
|
|
60
|
+
index: When `True`, this route matches when the parent path
|
|
61
61
|
matches exactly (no further segments). Index routes must not
|
|
62
|
-
have
|
|
63
|
-
component: A
|
|
62
|
+
have `path` or `children`.
|
|
63
|
+
component: A `@component` function to render when this route
|
|
64
64
|
matches.
|
|
65
65
|
children: Nested child routes.
|
|
66
66
|
loader: Optional data loader function. Called with the matched
|
|
67
67
|
params dict when the route matches. Result is available via
|
|
68
68
|
:func:`~flet.use_route_loader_data`.
|
|
69
|
-
outlet: When
|
|
69
|
+
outlet: When `True` and `manage_views=True`, this route acts
|
|
70
70
|
as a layout that wraps its matched child via
|
|
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
|
|
@@ -87,9 +114,9 @@ class LocationInfo:
|
|
|
87
114
|
Describes the current location parsed from the page route.
|
|
88
115
|
|
|
89
116
|
Args:
|
|
90
|
-
pathname: URL path portion (e.g.
|
|
91
|
-
search: Query string portion without leading
|
|
92
|
-
hash: Fragment portion without leading
|
|
117
|
+
pathname: URL path portion (e.g. `/products/42`).
|
|
118
|
+
search: Query string portion without leading `?`.
|
|
119
|
+
hash: Fragment portion without leading `#`.
|
|
93
120
|
"""
|
|
94
121
|
|
|
95
122
|
pathname: str
|
|
@@ -142,7 +169,7 @@ def _match_routes(
|
|
|
142
169
|
Match pathname against route tree.
|
|
143
170
|
|
|
144
171
|
Returns a chain of matched routes from outermost to innermost,
|
|
145
|
-
or
|
|
172
|
+
or `None` if no route matches.
|
|
146
173
|
"""
|
|
147
174
|
for route in routes:
|
|
148
175
|
result = _try_match(route, pathname, parent_path)
|
|
@@ -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] = {}
|
|
@@ -298,7 +362,7 @@ def use_route_location() -> str:
|
|
|
298
362
|
Returns an empty string if called outside a Router tree.
|
|
299
363
|
|
|
300
364
|
Returns:
|
|
301
|
-
The current URL pathname (e.g.
|
|
365
|
+
The current URL pathname (e.g. `"/products/42"`).
|
|
302
366
|
"""
|
|
303
367
|
loc = use_context(_location_context)
|
|
304
368
|
if not _is_inside_router(loc):
|
|
@@ -311,17 +375,17 @@ def use_view_path() -> str:
|
|
|
311
375
|
Returns the resolved URL for the current view level.
|
|
312
376
|
|
|
313
377
|
This differs from :func:`use_route_location` which returns the full
|
|
314
|
-
current URL.
|
|
315
|
-
view level (the leaf route of the view in
|
|
378
|
+
current URL. `use_view_path` returns the URL up to the current
|
|
379
|
+
view level (the leaf route of the view in `manage_views=True` mode).
|
|
316
380
|
|
|
317
|
-
Useful as the
|
|
381
|
+
Useful as the `route` value for :class:`~flet.View` to produce a
|
|
318
382
|
unique Navigator key per view in the stack.
|
|
319
383
|
|
|
320
384
|
Must be called inside a component rendered by a :class:`~flet.Router`.
|
|
321
385
|
Returns an empty string if called outside a Router tree.
|
|
322
386
|
|
|
323
387
|
Returns:
|
|
324
|
-
The resolved URL for this view level (e.g.
|
|
388
|
+
The resolved URL for this view level (e.g. `"/products/42"`).
|
|
325
389
|
"""
|
|
326
390
|
value = use_context(_view_path_context)
|
|
327
391
|
if not _is_inside_router(value):
|
|
@@ -335,10 +399,10 @@ def use_route_outlet() -> Control:
|
|
|
335
399
|
|
|
336
400
|
Used inside layout route components to render the active child route.
|
|
337
401
|
Must be called inside a component rendered by a :class:`~flet.Router`.
|
|
338
|
-
Returns
|
|
402
|
+
Returns `None` if called outside a Router tree.
|
|
339
403
|
|
|
340
404
|
Returns:
|
|
341
|
-
The rendered child component, or
|
|
405
|
+
The rendered child component, or `None` if no child matches.
|
|
342
406
|
"""
|
|
343
407
|
value = use_context(_outlet_context)
|
|
344
408
|
if not _is_inside_router(value):
|
|
@@ -350,10 +414,10 @@ def use_route_loader_data():
|
|
|
350
414
|
"""
|
|
351
415
|
Returns the data from the current route's loader function.
|
|
352
416
|
|
|
353
|
-
Must be called inside a component whose route has a
|
|
417
|
+
Must be called inside a component whose route has a `loader` defined.
|
|
354
418
|
|
|
355
419
|
Returns:
|
|
356
|
-
The return value of the route's loader function, or
|
|
420
|
+
The return value of the route's loader function, or `None`.
|
|
357
421
|
"""
|
|
358
422
|
value = use_context(_loader_data_context)
|
|
359
423
|
if not _is_inside_router(value):
|
|
@@ -369,12 +433,12 @@ def is_route_active(path: str, exact: bool = False) -> bool:
|
|
|
369
433
|
|
|
370
434
|
Args:
|
|
371
435
|
path: Path to check against the current location.
|
|
372
|
-
exact: If
|
|
373
|
-
a prefix match is used (e.g.
|
|
374
|
-
|
|
436
|
+
exact: If `True`, requires an exact match. If `False` (default),
|
|
437
|
+
a prefix match is used (e.g. `"/products"` matches
|
|
438
|
+
`"/products/42"`).
|
|
375
439
|
|
|
376
440
|
Returns:
|
|
377
|
-
|
|
441
|
+
`True` if the path matches the current location.
|
|
378
442
|
"""
|
|
379
443
|
loc = use_context(_location_context)
|
|
380
444
|
if not _is_inside_router(loc):
|
|
@@ -443,7 +507,7 @@ def _split_chain_into_view_levels(
|
|
|
443
507
|
"""
|
|
444
508
|
Split matched chain into layout wrappers and view entries.
|
|
445
509
|
|
|
446
|
-
Only **pathless** routes (no
|
|
510
|
+
Only **pathless** routes (no `path`, not `index`) with a component
|
|
447
511
|
are treated as layouts that wrap every View. All other routes with
|
|
448
512
|
a component become their own View in the stack.
|
|
449
513
|
|
|
@@ -451,7 +515,7 @@ def _split_chain_into_view_levels(
|
|
|
451
515
|
A tuple of (layouts, view_entries) where:
|
|
452
516
|
- layouts: pathless routes with components that wrap every View
|
|
453
517
|
- view_entries: path-bearing routes, each becoming its own View.
|
|
454
|
-
Each entry is
|
|
518
|
+
Each entry is `(match, accumulated_path)`.
|
|
455
519
|
"""
|
|
456
520
|
layouts: list[_RouteMatch] = []
|
|
457
521
|
view_entries: list[tuple[_RouteMatch, str]] = []
|
|
@@ -543,7 +607,7 @@ def Router(
|
|
|
543
607
|
Navigation is done via :meth:`~flet.Page.push_route` or
|
|
544
608
|
:meth:`~flet.Page.navigate`.
|
|
545
609
|
|
|
546
|
-
When
|
|
610
|
+
When `manage_views` is `True`, the Router returns a list of
|
|
547
611
|
:class:`~flet.View` objects (one per path level) instead of a single
|
|
548
612
|
component tree. This enables swipe-back gestures, system back button,
|
|
549
613
|
and :class:`~flet.AppBar` implicit back button on mobile.
|
|
@@ -552,10 +616,10 @@ def Router(
|
|
|
552
616
|
Args:
|
|
553
617
|
routes: List of top-level :class:`~flet.Route` definitions.
|
|
554
618
|
not_found: Optional component to render when no route matches (404).
|
|
555
|
-
manage_views: When
|
|
619
|
+
manage_views: When `True`, produce a list of
|
|
556
620
|
:class:`~flet.View` objects (one per path level) instead of a
|
|
557
621
|
single component tree. Route components should return
|
|
558
|
-
:class:`~flet.View` instances with
|
|
622
|
+
:class:`~flet.View` instances with `route` and `appbar`
|
|
559
623
|
set. Use with :meth:`~flet.Page.render_views`.
|
|
560
624
|
|
|
561
625
|
Example:
|
|
@@ -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,45 @@ def Router(
|
|
|
590
670
|
prev_pop_handler_ref.current = page.on_view_pop
|
|
591
671
|
|
|
592
672
|
def on_view_pop(e):
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
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: navigate to the previous *view entry*'s
|
|
690
|
+
# resolved URL rather than `chain[-2]` or
|
|
691
|
+
# `views[-2].route`. Classifying into view entries skips
|
|
692
|
+
# `outlet=True` layouts and componentless grouping routes
|
|
693
|
+
# — otherwise `chain[-2]` can point at a layout whose URL
|
|
694
|
+
# equals the current view's URL, making the pop navigate
|
|
695
|
+
# to where we already are (a no-op that strands the URL).
|
|
696
|
+
# Staying route-tree-structural also survives shared view
|
|
697
|
+
# keys like a tab-root layout emitting `route="/"` for
|
|
698
|
+
# multiple sibling sections.
|
|
699
|
+
chain_now = current_chain_ref.current
|
|
700
|
+
if chain_now:
|
|
701
|
+
_, view_entries = _split_chain_into_view_levels(chain_now)
|
|
702
|
+
if len(view_entries) > 1:
|
|
703
|
+
parent_match = view_entries[-2][0]
|
|
704
|
+
target = (
|
|
705
|
+
parent_match.resolved_path or parent_match.full_path or "/"
|
|
706
|
+
)
|
|
707
|
+
page.navigate(target)
|
|
708
|
+
return
|
|
709
|
+
|
|
710
|
+
# Stack of length 1 — nothing to pop to. (Flutter's
|
|
711
|
+
# `Navigator.canPop` is False here anyway.)
|
|
600
712
|
|
|
601
713
|
page.on_view_pop = on_view_pop
|
|
602
714
|
|
|
@@ -621,10 +733,66 @@ def Router(
|
|
|
621
733
|
if manage_views:
|
|
622
734
|
from flet.controls.core.view import View
|
|
623
735
|
|
|
736
|
+
# Reset state so a stale modal pop_to doesn't leak into
|
|
737
|
+
# a 404'd location.
|
|
738
|
+
current_chain_ref.current = None
|
|
739
|
+
current_modal_pop_to_ref.current = None
|
|
624
740
|
return [View(route=pathname, controls=[not_found()])]
|
|
625
741
|
return not_found()
|
|
626
742
|
return None
|
|
627
743
|
|
|
744
|
+
# Detect modal routes in the chain. `modal_idx` is the index of
|
|
745
|
+
# the first route in the chain with `modal=True`; `-1` means
|
|
746
|
+
# the chain is fully non-modal.
|
|
747
|
+
modal_idx = -1
|
|
748
|
+
for i, m in enumerate(chain):
|
|
749
|
+
if m.route.modal:
|
|
750
|
+
modal_idx = i
|
|
751
|
+
break
|
|
752
|
+
|
|
753
|
+
# For a *global* modal (`modal_idx == 0` — the chain starts at a
|
|
754
|
+
# modal with no non-modal parents) we want the visible stack to be
|
|
755
|
+
# the chain of the previously visited non-modal location +
|
|
756
|
+
# the modal's own chain. This way the underlying stack stays mounted
|
|
757
|
+
# underneath the modal — closing the modal reveals it without a
|
|
758
|
+
# rebuild.
|
|
759
|
+
if manage_views and modal_idx == 0:
|
|
760
|
+
base_location = prev_non_modal_location_ref.current or "/"
|
|
761
|
+
base_pathname = _normalize_path(urlparse(base_location).path or "/")
|
|
762
|
+
base_chain = _match_routes(routes, base_pathname) or []
|
|
763
|
+
# If the base path also resolves to a modal (shouldn't happen
|
|
764
|
+
# in practice — non-modal navigations are the only ones that
|
|
765
|
+
# update prev_non_modal_location_ref), fall back to no base.
|
|
766
|
+
if any(b.route.modal for b in base_chain):
|
|
767
|
+
base_chain = []
|
|
768
|
+
# Combine: base lives below, modal sits on top.
|
|
769
|
+
chain = base_chain + chain
|
|
770
|
+
# Re-locate the modal index in the combined chain.
|
|
771
|
+
modal_idx = len(base_chain)
|
|
772
|
+
|
|
773
|
+
# Track refs that downstream consumers (default pop handler, etc.)
|
|
774
|
+
# read. `current_chain_ref` always reflects the chain we're
|
|
775
|
+
# actually emitting. `current_modal_pop_to_ref` is set only when
|
|
776
|
+
# the chain ends in a modal — non-modal navigations clear it.
|
|
777
|
+
current_chain_ref.current = chain
|
|
778
|
+
if modal_idx == -1:
|
|
779
|
+
# Non-modal navigation — remember it as the next base.
|
|
780
|
+
prev_non_modal_location_ref.current = location
|
|
781
|
+
current_modal_pop_to_ref.current = None
|
|
782
|
+
else:
|
|
783
|
+
# Modal route — the URL to pop to is the resolved URL of the
|
|
784
|
+
# last non-modal entry in the chain.
|
|
785
|
+
if modal_idx > 0:
|
|
786
|
+
parent = chain[modal_idx - 1]
|
|
787
|
+
current_modal_pop_to_ref.current = (
|
|
788
|
+
parent.resolved_path or parent.full_path or "/"
|
|
789
|
+
)
|
|
790
|
+
else:
|
|
791
|
+
# No non-modal parent in the chain (rare — would require a
|
|
792
|
+
# deep-link to a top-level modal with no remembered base
|
|
793
|
+
# AND an empty default match). Fall back to "/".
|
|
794
|
+
current_modal_pop_to_ref.current = "/"
|
|
795
|
+
|
|
628
796
|
# Merge all params from the chain
|
|
629
797
|
all_params: dict[str, str] = {}
|
|
630
798
|
for m in chain:
|
|
@@ -640,7 +808,8 @@ def Router(
|
|
|
640
808
|
loc = LocationInfo(pathname=pathname, search=search, hash=hash_val)
|
|
641
809
|
|
|
642
810
|
if not manage_views:
|
|
643
|
-
# Single-view mode (existing behavior)
|
|
811
|
+
# Single-view mode (existing behavior). `modal` is ignored
|
|
812
|
+
# here — it only affects stack composition in multi-view mode.
|
|
644
813
|
return _location_context(
|
|
645
814
|
loc,
|
|
646
815
|
lambda: _params_context(
|
|
@@ -653,47 +822,81 @@ def Router(
|
|
|
653
822
|
# route, etc.). The Router sets route and can_pop on each View
|
|
654
823
|
# after the component body executes (via the patch walk).
|
|
655
824
|
# Used with page.render_views(App).
|
|
656
|
-
|
|
825
|
+
#
|
|
826
|
+
# If the chain contains a modal route, split into two independent
|
|
827
|
+
# sub-chains at the modal boundary. Each sub-chain is classified
|
|
828
|
+
# into layouts vs. view entries SEPARATELY so that an outlet route
|
|
829
|
+
# that would be a leaf view in its own sub-chain doesn't get
|
|
830
|
+
# re-classified as a layout just because there's more chain after
|
|
831
|
+
# the boundary. `modal_idx` already points to the modal route in
|
|
832
|
+
# the (possibly combined) chain.
|
|
833
|
+
# `modal_idx <= 0` covers both the no-modal case (`-1`) and a
|
|
834
|
+
# degenerate modal chain with no base (`0`) — neither is split.
|
|
835
|
+
sub_chains = [chain] if modal_idx <= 0 else [chain[:modal_idx], chain[modal_idx:]]
|
|
836
|
+
|
|
837
|
+
# Each sub-chain's views see their own URL via the location
|
|
838
|
+
# context. The base sub-chain (when there's a modal split) sees the
|
|
839
|
+
# remembered non-modal location it was matched against — so
|
|
840
|
+
# `is_route_active("/gallery")` inside a base view stays True
|
|
841
|
+
# while a global `/settings` modal is open over Gallery.
|
|
842
|
+
base_sub_loc = LocationInfo(pathname=pathname, search=search, hash=hash_val)
|
|
843
|
+
if modal_idx > 0:
|
|
844
|
+
base_loc_str = prev_non_modal_location_ref.current or "/"
|
|
845
|
+
base_parsed = urlparse(base_loc_str)
|
|
846
|
+
base_sub_loc = LocationInfo(
|
|
847
|
+
pathname=_normalize_path(base_parsed.path or "/"),
|
|
848
|
+
search=base_parsed.query or "",
|
|
849
|
+
hash=base_parsed.fragment or "",
|
|
850
|
+
)
|
|
657
851
|
|
|
658
852
|
results = []
|
|
659
|
-
for
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
_match=
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
853
|
+
for sub_chain_idx, sub_chain in enumerate(sub_chains):
|
|
854
|
+
layouts, view_entries = _split_chain_into_view_levels(sub_chain)
|
|
855
|
+
# The base sub-chain (everything before the modal) is rendered
|
|
856
|
+
# "as if" the user is at the previous non-modal URL; the modal
|
|
857
|
+
# sub-chain is rendered at the modal URL.
|
|
858
|
+
sub_loc = base_sub_loc if (modal_idx > 0 and sub_chain_idx == 0) else loc
|
|
859
|
+
for match, _ in view_entries:
|
|
860
|
+
# Params accumulated up to this view level — within the
|
|
861
|
+
# combined chain so a local modal view still sees its
|
|
862
|
+
# parents' captures.
|
|
863
|
+
level_params: dict[str, str] = {}
|
|
864
|
+
for m in chain:
|
|
865
|
+
level_params.update(m.params)
|
|
866
|
+
if m is match:
|
|
867
|
+
break
|
|
868
|
+
|
|
869
|
+
# Per-view resolved URL — unique per view level for
|
|
870
|
+
# Navigator keying.
|
|
871
|
+
level_view_path = match.resolved_path or match.full_path or "/"
|
|
872
|
+
_match = match
|
|
873
|
+
# Only apply layouts that appear before this view entry IN
|
|
874
|
+
# THE SAME SUB-CHAIN. A modal view never inherits the
|
|
875
|
+
# base's layouts (and vice versa).
|
|
876
|
+
match_idx = sub_chain.index(match)
|
|
877
|
+
_layouts = [lm for lm in layouts if sub_chain.index(lm) < match_idx]
|
|
878
|
+
|
|
879
|
+
def build_view_content(
|
|
880
|
+
_match=_match,
|
|
881
|
+
_layouts=_layouts,
|
|
882
|
+
_level_params=level_params,
|
|
883
|
+
_level_loc=sub_loc,
|
|
884
|
+
_level_view_path=level_view_path,
|
|
885
|
+
_sub_chain=sub_chain,
|
|
886
|
+
):
|
|
887
|
+
return _view_path_context(
|
|
888
|
+
_level_view_path,
|
|
889
|
+
lambda: _location_context(
|
|
890
|
+
_level_loc,
|
|
891
|
+
lambda: _params_context(
|
|
892
|
+
_level_params,
|
|
893
|
+
lambda: _build_view_level(
|
|
894
|
+
_layouts, _match, loader_results, _sub_chain
|
|
895
|
+
),
|
|
692
896
|
),
|
|
693
897
|
),
|
|
694
|
-
)
|
|
695
|
-
)
|
|
898
|
+
)
|
|
696
899
|
|
|
697
|
-
|
|
900
|
+
results.append(build_view_content())
|
|
698
901
|
|
|
699
902
|
return results
|
|
@@ -28,7 +28,7 @@ class Icon(LayoutControl):
|
|
|
28
28
|
The icon to display, selected from a predefined icon set.
|
|
29
29
|
|
|
30
30
|
You can explore available icons using the
|
|
31
|
-
[Flet Icons Browser](https://
|
|
31
|
+
[Flet Icons Browser](https://flet.app/gallery/run/apps/icons_browser/).
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
34
|
color: Optional[ColorValue] = None
|
|
@@ -10,7 +10,7 @@ __all__ = [
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def _lazy_value(cls=None, **kwargs):
|
|
13
|
-
"""Deferred proxy for
|
|
13
|
+
"""Deferred proxy for `value` to avoid circular import with base_control."""
|
|
14
14
|
from flet.controls.base_control import value as _v
|
|
15
15
|
|
|
16
16
|
if cls is not None:
|
|
@@ -21,8 +21,8 @@ class RadioGroup(Control):
|
|
|
21
21
|
"""
|
|
22
22
|
The content of the RadioGroup.
|
|
23
23
|
|
|
24
|
-
Typically a list of
|
|
25
|
-
`Row`.
|
|
24
|
+
Typically a list of :class:`~flet.Radio` controls nested in a container control,
|
|
25
|
+
e.g. `Column`, `Row`.
|
|
26
26
|
|
|
27
27
|
Raises:
|
|
28
28
|
ValueError: If :attr:`content` is not visible.
|
|
@@ -947,8 +947,8 @@ class Page(BasePage):
|
|
|
947
947
|
"""
|
|
948
948
|
Navigate to a new route (sync convenience wrapper).
|
|
949
949
|
|
|
950
|
-
Equivalent to
|
|
951
|
-
Use this in synchronous callbacks (e.g.
|
|
950
|
+
Equivalent to `asyncio.create_task(page.push_route(route, **kwargs))`.
|
|
951
|
+
Use this in synchronous callbacks (e.g. `on_click`) where awaiting
|
|
952
952
|
is not possible.
|
|
953
953
|
|
|
954
954
|
Args:
|
|
@@ -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/
|
|
1310
|
+
More information [here](https://flet.dev/docs/cookbook/colors).
|
|
1311
1311
|
"""
|
|
1312
1312
|
|
|
1313
1313
|
# Icons
|