solara-ui 1.45.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- prefix/etc/jupyter/jupyter_notebook_config.d/solara.json +7 -0
- prefix/etc/jupyter/jupyter_server_config.d/solara.json +7 -0
- solara/__init__.py +124 -0
- solara/__main__.py +765 -0
- solara/_stores.py +297 -0
- solara/alias.py +6 -0
- solara/autorouting.py +555 -0
- solara/cache.py +305 -0
- solara/checks.html +71 -0
- solara/checks.py +227 -0
- solara/comm.py +28 -0
- solara/components/__init__.py +77 -0
- solara/components/alert.py +155 -0
- solara/components/applayout.py +397 -0
- solara/components/button.py +85 -0
- solara/components/card.py +87 -0
- solara/components/checkbox.py +50 -0
- solara/components/code_highlight_css.py +11 -0
- solara/components/code_highlight_css.vue +63 -0
- solara/components/columns.py +159 -0
- solara/components/component_vue.py +134 -0
- solara/components/cross_filter.py +335 -0
- solara/components/dataframe.py +546 -0
- solara/components/datatable.py +214 -0
- solara/components/datatable.vue +175 -0
- solara/components/details.py +56 -0
- solara/components/download.vue +35 -0
- solara/components/echarts.py +86 -0
- solara/components/echarts.vue +139 -0
- solara/components/figure_altair.py +39 -0
- solara/components/file_browser.py +181 -0
- solara/components/file_download.py +199 -0
- solara/components/file_drop.py +159 -0
- solara/components/file_drop.vue +83 -0
- solara/components/file_list_widget.vue +78 -0
- solara/components/head.py +27 -0
- solara/components/head_tag.py +49 -0
- solara/components/head_tag.vue +60 -0
- solara/components/image.py +173 -0
- solara/components/input.py +456 -0
- solara/components/input_text_area.py +86 -0
- solara/components/link.py +55 -0
- solara/components/markdown.py +441 -0
- solara/components/markdown_editor.py +33 -0
- solara/components/markdown_editor.vue +359 -0
- solara/components/matplotlib.py +74 -0
- solara/components/meta.py +47 -0
- solara/components/misc.py +333 -0
- solara/components/pivot_table.py +258 -0
- solara/components/pivot_table.vue +158 -0
- solara/components/progress.py +47 -0
- solara/components/select.py +182 -0
- solara/components/select.vue +27 -0
- solara/components/slider.py +442 -0
- solara/components/slider_date.vue +56 -0
- solara/components/spinner-solara.vue +105 -0
- solara/components/spinner.py +45 -0
- solara/components/sql_code.py +41 -0
- solara/components/sql_code.vue +125 -0
- solara/components/style.py +105 -0
- solara/components/switch.py +71 -0
- solara/components/tab_navigation.py +37 -0
- solara/components/title.py +90 -0
- solara/components/title.vue +38 -0
- solara/components/togglebuttons.py +200 -0
- solara/components/tooltip.py +61 -0
- solara/core.py +42 -0
- solara/datatypes.py +143 -0
- solara/express.py +241 -0
- solara/hooks/__init__.py +4 -0
- solara/hooks/dataframe.py +99 -0
- solara/hooks/misc.py +263 -0
- solara/hooks/use_reactive.py +151 -0
- solara/hooks/use_thread.py +129 -0
- solara/kitchensink.py +8 -0
- solara/lab/__init__.py +34 -0
- solara/lab/components/__init__.py +7 -0
- solara/lab/components/chat.py +215 -0
- solara/lab/components/confirmation_dialog.py +163 -0
- solara/lab/components/cross_filter.py +7 -0
- solara/lab/components/input_date.py +339 -0
- solara/lab/components/input_time.py +133 -0
- solara/lab/components/menu.py +181 -0
- solara/lab/components/menu.vue +38 -0
- solara/lab/components/tabs.py +274 -0
- solara/lab/components/theming.py +98 -0
- solara/lab/components/theming.vue +72 -0
- solara/lab/hooks/__init__.py +0 -0
- solara/lab/hooks/dataframe.py +2 -0
- solara/lab/toestand.py +3 -0
- solara/lab/utils/__init__.py +2 -0
- solara/lab/utils/cookies.py +5 -0
- solara/lab/utils/dataframe.py +165 -0
- solara/lab/utils/headers.py +5 -0
- solara/layout.py +44 -0
- solara/lifecycle.py +46 -0
- solara/minisettings.py +141 -0
- solara/py.typed +0 -0
- solara/reactive.py +99 -0
- solara/routing.py +268 -0
- solara/scope/__init__.py +88 -0
- solara/scope/types.py +55 -0
- solara/server/__init__.py +0 -0
- solara/server/app.py +527 -0
- solara/server/assets/custom.css +1 -0
- solara/server/assets/custom.js +1 -0
- solara/server/assets/favicon.png +0 -0
- solara/server/assets/favicon.svg +5 -0
- solara/server/assets/style.css +1681 -0
- solara/server/assets/theme-dark.css +437 -0
- solara/server/assets/theme-light.css +420 -0
- solara/server/assets/theme.js +3 -0
- solara/server/cdn_helper.py +91 -0
- solara/server/esm.py +71 -0
- solara/server/fastapi.py +5 -0
- solara/server/flask.py +297 -0
- solara/server/jupyter/__init__.py +2 -0
- solara/server/jupyter/cdn_handler.py +28 -0
- solara/server/jupyter/server_extension.py +40 -0
- solara/server/jupyter/solara.py +91 -0
- solara/server/jupytertools.py +46 -0
- solara/server/kernel.py +388 -0
- solara/server/kernel_context.py +467 -0
- solara/server/patch.py +564 -0
- solara/server/pyinstaller/__init__.py +9 -0
- solara/server/pyinstaller/hook-ipyreact.py +5 -0
- solara/server/pyinstaller/hook-ipyvuetify.py +5 -0
- solara/server/pyinstaller/hook-solara.py +9 -0
- solara/server/qt.py +113 -0
- solara/server/reload.py +251 -0
- solara/server/server.py +484 -0
- solara/server/settings.py +249 -0
- solara/server/shell.py +269 -0
- solara/server/starlette.py +770 -0
- solara/server/static/ansi.js +270 -0
- solara/server/static/highlight-dark.css +82 -0
- solara/server/static/highlight.css +43 -0
- solara/server/static/main-vuetify.js +272 -0
- solara/server/static/main.js +163 -0
- solara/server/static/solara_bootstrap.py +129 -0
- solara/server/static/sun.svg +23 -0
- solara/server/static/webworker.js +42 -0
- solara/server/telemetry.py +212 -0
- solara/server/templates/index.html.j2 +1 -0
- solara/server/templates/loader-plain.css +11 -0
- solara/server/templates/loader-plain.html +20 -0
- solara/server/templates/loader-solara.css +111 -0
- solara/server/templates/loader-solara.html +40 -0
- solara/server/templates/plain.html +82 -0
- solara/server/templates/solara.html.j2 +486 -0
- solara/server/threaded.py +84 -0
- solara/server/utils.py +44 -0
- solara/server/websocket.py +45 -0
- solara/settings.py +86 -0
- solara/tasks.py +893 -0
- solara/template/button.py +16 -0
- solara/template/markdown.py +42 -0
- solara/template/portal/.flake8 +6 -0
- solara/template/portal/.pre-commit-config.yaml +28 -0
- solara/template/portal/LICENSE +21 -0
- solara/template/portal/Procfile +7 -0
- solara/template/portal/mypy.ini +3 -0
- solara/template/portal/pyproject.toml +26 -0
- solara/template/portal/solara_portal/__init__.py +4 -0
- solara/template/portal/solara_portal/components/__init__.py +2 -0
- solara/template/portal/solara_portal/components/article.py +28 -0
- solara/template/portal/solara_portal/components/data.py +28 -0
- solara/template/portal/solara_portal/components/header.py +6 -0
- solara/template/portal/solara_portal/components/layout.py +6 -0
- solara/template/portal/solara_portal/content/articles/equis-in-vidi.md +85 -0
- solara/template/portal/solara_portal/content/articles/substiterat-vati.md +70 -0
- solara/template/portal/solara_portal/data.py +60 -0
- solara/template/portal/solara_portal/pages/__init__.py +67 -0
- solara/template/portal/solara_portal/pages/article/__init__.py +26 -0
- solara/template/portal/solara_portal/pages/tabular.py +29 -0
- solara/template/portal/solara_portal/pages/viz/__init__.py +70 -0
- solara/template/portal/solara_portal/pages/viz/overview.py +14 -0
- solara/test/__init__.py +0 -0
- solara/test/pytest_plugin.py +783 -0
- solara/toestand.py +998 -0
- solara/util.py +348 -0
- solara/validate_hooks.py +258 -0
- solara/website/__init__.py +0 -0
- solara/website/assets/custom.css +444 -0
- solara/website/assets/images/logo-small.png +0 -0
- solara/website/assets/images/logo.svg +17 -0
- solara/website/assets/images/logo_white.svg +50 -0
- solara/website/assets/theme.js +8 -0
- solara/website/components/__init__.py +5 -0
- solara/website/components/algolia.py +6 -0
- solara/website/components/algolia.vue +24 -0
- solara/website/components/algolia_api.vue +202 -0
- solara/website/components/breadcrumbs.py +28 -0
- solara/website/components/contact.py +144 -0
- solara/website/components/docs.py +143 -0
- solara/website/components/header.py +75 -0
- solara/website/components/mailchimp.py +12 -0
- solara/website/components/mailchimp.vue +47 -0
- solara/website/components/markdown.py +99 -0
- solara/website/components/markdown_nav.vue +34 -0
- solara/website/components/notebook.py +171 -0
- solara/website/components/sidebar.py +105 -0
- solara/website/pages/__init__.py +370 -0
- solara/website/pages/about/__init__.py +9 -0
- solara/website/pages/about/about.md +3 -0
- solara/website/pages/apps/__init__.py +16 -0
- solara/website/pages/apps/authorization/__init__.py +119 -0
- solara/website/pages/apps/authorization/admin.py +12 -0
- solara/website/pages/apps/authorization/users.py +12 -0
- solara/website/pages/apps/jupyter-dashboard-1.py +116 -0
- solara/website/pages/apps/layout-demo.py +40 -0
- solara/website/pages/apps/multipage/__init__.py +38 -0
- solara/website/pages/apps/multipage/page1.py +26 -0
- solara/website/pages/apps/multipage/page2.py +34 -0
- solara/website/pages/apps/scatter.py +136 -0
- solara/website/pages/apps/scrolling.py +63 -0
- solara/website/pages/apps/tutorial-streamlit.py +18 -0
- solara/website/pages/careers/__init__.py +27 -0
- solara/website/pages/changelog/__init__.py +10 -0
- solara/website/pages/changelog/changelog.md +372 -0
- solara/website/pages/contact/__init__.py +34 -0
- solara/website/pages/doc_use_download.py +85 -0
- solara/website/pages/documentation/__init__.py +90 -0
- solara/website/pages/documentation/advanced/__init__.py +9 -0
- solara/website/pages/documentation/advanced/content/00-overview.md +1 -0
- solara/website/pages/documentation/advanced/content/10-howto/00-overview.md +6 -0
- solara/website/pages/documentation/advanced/content/10-howto/10-multipage.md +196 -0
- solara/website/pages/documentation/advanced/content/10-howto/20-layout.md +125 -0
- solara/website/pages/documentation/advanced/content/10-howto/30-testing.md +417 -0
- solara/website/pages/documentation/advanced/content/10-howto/31-debugging.md +69 -0
- solara/website/pages/documentation/advanced/content/10-howto/40-embed.md +50 -0
- solara/website/pages/documentation/advanced/content/10-howto/50-ipywidget_libraries.md +124 -0
- solara/website/pages/documentation/advanced/content/15-reference/00-overview.md +3 -0
- solara/website/pages/documentation/advanced/content/15-reference/40-static_files.md +31 -0
- solara/website/pages/documentation/advanced/content/15-reference/41-asset-files.md +72 -0
- solara/website/pages/documentation/advanced/content/15-reference/60-static-site-generation.md +59 -0
- solara/website/pages/documentation/advanced/content/15-reference/70-search.md +34 -0
- solara/website/pages/documentation/advanced/content/15-reference/80-reloading.md +34 -0
- solara/website/pages/documentation/advanced/content/15-reference/90-notebook-support.md +7 -0
- solara/website/pages/documentation/advanced/content/15-reference/95-caching.md +148 -0
- solara/website/pages/documentation/advanced/content/20-understanding/00-introduction.md +10 -0
- solara/website/pages/documentation/advanced/content/20-understanding/05-ipywidgets.md +35 -0
- solara/website/pages/documentation/advanced/content/20-understanding/06-ipyvuetify.md +42 -0
- solara/website/pages/documentation/advanced/content/20-understanding/10-reacton.md +28 -0
- solara/website/pages/documentation/advanced/content/20-understanding/12-reacton-basics.md +108 -0
- solara/website/pages/documentation/advanced/content/20-understanding/15-anatomy.md +23 -0
- solara/website/pages/documentation/advanced/content/20-understanding/17-rules-of-hooks.md +192 -0
- solara/website/pages/documentation/advanced/content/20-understanding/18-containers.md +166 -0
- solara/website/pages/documentation/advanced/content/20-understanding/20-solara.md +18 -0
- solara/website/pages/documentation/advanced/content/20-understanding/40-routing.md +256 -0
- solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +108 -0
- solara/website/pages/documentation/advanced/content/20-understanding/60-voila.md +12 -0
- solara/website/pages/documentation/advanced/content/30-enterprise/00-overview.md +7 -0
- solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +187 -0
- solara/website/pages/documentation/advanced/content/40-development/00-overview.md +0 -0
- solara/website/pages/documentation/advanced/content/40-development/01-contribute.md +45 -0
- solara/website/pages/documentation/advanced/content/40-development/10-setup.md +76 -0
- solara/website/pages/documentation/api/__init__.py +19 -0
- solara/website/pages/documentation/api/cross_filter/__init__.py +9 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_dataframe.py +22 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_report.py +20 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_select.py +20 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_slider.py +20 -0
- solara/website/pages/documentation/api/hooks/__init__.py +9 -0
- solara/website/pages/documentation/api/hooks/use_cross_filter.py +23 -0
- solara/website/pages/documentation/api/hooks/use_dark_effective.py +12 -0
- solara/website/pages/documentation/api/hooks/use_effect.md +43 -0
- solara/website/pages/documentation/api/hooks/use_effect.py +9 -0
- solara/website/pages/documentation/api/hooks/use_exception.py +31 -0
- solara/website/pages/documentation/api/hooks/use_memo.md +16 -0
- solara/website/pages/documentation/api/hooks/use_memo.py +9 -0
- solara/website/pages/documentation/api/hooks/use_previous.py +30 -0
- solara/website/pages/documentation/api/hooks/use_reactive.py +16 -0
- solara/website/pages/documentation/api/hooks/use_state.py +10 -0
- solara/website/pages/documentation/api/hooks/use_state_or_update.py +66 -0
- solara/website/pages/documentation/api/hooks/use_thread.md +64 -0
- solara/website/pages/documentation/api/hooks/use_thread.py +42 -0
- solara/website/pages/documentation/api/hooks/use_trait_observe.py +12 -0
- solara/website/pages/documentation/api/routing/__init__.py +9 -0
- solara/website/pages/documentation/api/routing/generate_routes.py +10 -0
- solara/website/pages/documentation/api/routing/generate_routes_directory.py +10 -0
- solara/website/pages/documentation/api/routing/resolve_path.py +35 -0
- solara/website/pages/documentation/api/routing/route.py +29 -0
- solara/website/pages/documentation/api/routing/use_route.py +76 -0
- solara/website/pages/documentation/api/routing/use_router.py +16 -0
- solara/website/pages/documentation/api/utilities/__init__.py +9 -0
- solara/website/pages/documentation/api/utilities/component_vue.py +10 -0
- solara/website/pages/documentation/api/utilities/computed.py +16 -0
- solara/website/pages/documentation/api/utilities/display.py +16 -0
- solara/website/pages/documentation/api/utilities/get_kernel_id.py +16 -0
- solara/website/pages/documentation/api/utilities/get_session_id.py +16 -0
- solara/website/pages/documentation/api/utilities/memoize.py +35 -0
- solara/website/pages/documentation/api/utilities/on_kernel_start.py +44 -0
- solara/website/pages/documentation/api/utilities/reactive.py +16 -0
- solara/website/pages/documentation/api/utilities/widget.py +104 -0
- solara/website/pages/documentation/components/__init__.py +12 -0
- solara/website/pages/documentation/components/advanced/__init__.py +9 -0
- solara/website/pages/documentation/components/advanced/link.py +25 -0
- solara/website/pages/documentation/components/advanced/meta.py +17 -0
- solara/website/pages/documentation/components/advanced/style.py +43 -0
- solara/website/pages/documentation/components/common.py +9 -0
- solara/website/pages/documentation/components/data/__init__.py +9 -0
- solara/website/pages/documentation/components/data/dataframe.py +44 -0
- solara/website/pages/documentation/components/data/pivot_table.py +81 -0
- solara/website/pages/documentation/components/enterprise/__init__.py +9 -0
- solara/website/pages/documentation/components/enterprise/avatar.py +24 -0
- solara/website/pages/documentation/components/enterprise/avatar_menu.py +25 -0
- solara/website/pages/documentation/components/input/__init__.py +9 -0
- solara/website/pages/documentation/components/input/button.py +23 -0
- solara/website/pages/documentation/components/input/checkbox.py +10 -0
- solara/website/pages/documentation/components/input/file_browser.py +30 -0
- solara/website/pages/documentation/components/input/file_drop.py +76 -0
- solara/website/pages/documentation/components/input/input.py +43 -0
- solara/website/pages/documentation/components/input/select.py +22 -0
- solara/website/pages/documentation/components/input/slider.py +29 -0
- solara/website/pages/documentation/components/input/switch.py +10 -0
- solara/website/pages/documentation/components/input/togglebuttons.py +21 -0
- solara/website/pages/documentation/components/lab/__init__.py +9 -0
- solara/website/pages/documentation/components/lab/chat.py +109 -0
- solara/website/pages/documentation/components/lab/confirmation_dialog.py +55 -0
- solara/website/pages/documentation/components/lab/cookies_headers.py +48 -0
- solara/website/pages/documentation/components/lab/input_date.py +20 -0
- solara/website/pages/documentation/components/lab/input_time.py +15 -0
- solara/website/pages/documentation/components/lab/menu.py +22 -0
- solara/website/pages/documentation/components/lab/tab.py +25 -0
- solara/website/pages/documentation/components/lab/tabs.py +45 -0
- solara/website/pages/documentation/components/lab/task.py +11 -0
- solara/website/pages/documentation/components/lab/theming.py +74 -0
- solara/website/pages/documentation/components/lab/use_task.py +11 -0
- solara/website/pages/documentation/components/layout/__init__.py +9 -0
- solara/website/pages/documentation/components/layout/app_bar.py +16 -0
- solara/website/pages/documentation/components/layout/app_bar_title.py +16 -0
- solara/website/pages/documentation/components/layout/app_layout.py +24 -0
- solara/website/pages/documentation/components/layout/card.py +15 -0
- solara/website/pages/documentation/components/layout/card_actions.py +16 -0
- solara/website/pages/documentation/components/layout/column.py +30 -0
- solara/website/pages/documentation/components/layout/columns.py +27 -0
- solara/website/pages/documentation/components/layout/columns_responsive.py +66 -0
- solara/website/pages/documentation/components/layout/details.py +13 -0
- solara/website/pages/documentation/components/layout/griddraggable.py +62 -0
- solara/website/pages/documentation/components/layout/gridfixed.py +19 -0
- solara/website/pages/documentation/components/layout/hbox.py +18 -0
- solara/website/pages/documentation/components/layout/row.py +30 -0
- solara/website/pages/documentation/components/layout/sidebar.py +24 -0
- solara/website/pages/documentation/components/layout/vbox.py +19 -0
- solara/website/pages/documentation/components/output/__init__.py +9 -0
- solara/website/pages/documentation/components/output/file_download.py +11 -0
- solara/website/pages/documentation/components/output/html.py +19 -0
- solara/website/pages/documentation/components/output/image.py +11 -0
- solara/website/pages/documentation/components/output/markdown.py +57 -0
- solara/website/pages/documentation/components/output/markdown_editor.py +51 -0
- solara/website/pages/documentation/components/output/sql_code.py +83 -0
- solara/website/pages/documentation/components/output/tooltip.py +11 -0
- solara/website/pages/documentation/components/page/__init__.py +9 -0
- solara/website/pages/documentation/components/page/head.py +15 -0
- solara/website/pages/documentation/components/page/title.py +25 -0
- solara/website/pages/documentation/components/status/__init__.py +9 -0
- solara/website/pages/documentation/components/status/error.py +39 -0
- solara/website/pages/documentation/components/status/info.py +39 -0
- solara/website/pages/documentation/components/status/progress.py +10 -0
- solara/website/pages/documentation/components/status/spinner.py +11 -0
- solara/website/pages/documentation/components/status/success.py +40 -0
- solara/website/pages/documentation/components/status/warning.py +47 -0
- solara/website/pages/documentation/components/viz/__init__.py +9 -0
- solara/website/pages/documentation/components/viz/altair.py +42 -0
- solara/website/pages/documentation/components/viz/echarts.py +77 -0
- solara/website/pages/documentation/components/viz/matplotlib.py +30 -0
- solara/website/pages/documentation/components/viz/plotly.py +63 -0
- solara/website/pages/documentation/components/viz/plotly_express.py +41 -0
- solara/website/pages/documentation/examples/__init__.py +54 -0
- solara/website/pages/documentation/examples/ai/__init__.py +11 -0
- solara/website/pages/documentation/examples/ai/chatbot.py +113 -0
- solara/website/pages/documentation/examples/ai/tokenizer.py +107 -0
- solara/website/pages/documentation/examples/basics/__init__.py +10 -0
- solara/website/pages/documentation/examples/basics/sine.py +28 -0
- solara/website/pages/documentation/examples/fullscreen/__init__.py +10 -0
- solara/website/pages/documentation/examples/fullscreen/authorization.py +3 -0
- solara/website/pages/documentation/examples/fullscreen/layout_demo.py +3 -0
- solara/website/pages/documentation/examples/fullscreen/multipage.py +3 -0
- solara/website/pages/documentation/examples/fullscreen/scatter.py +3 -0
- solara/website/pages/documentation/examples/fullscreen/scrolling.py +3 -0
- solara/website/pages/documentation/examples/fullscreen/tutorial_streamlit.py +3 -0
- solara/website/pages/documentation/examples/general/__init__.py +10 -0
- solara/website/pages/documentation/examples/general/custom_storage.py +70 -0
- solara/website/pages/documentation/examples/general/deploy_model.py +115 -0
- solara/website/pages/documentation/examples/general/live_update.py +32 -0
- solara/website/pages/documentation/examples/general/login_oauth.py +81 -0
- solara/website/pages/documentation/examples/general/mycard.vue +58 -0
- solara/website/pages/documentation/examples/general/pokemon_search.py +51 -0
- solara/website/pages/documentation/examples/general/vue_component.py +50 -0
- solara/website/pages/documentation/examples/ipycanvas.py +49 -0
- solara/website/pages/documentation/examples/libraries/__init__.py +10 -0
- solara/website/pages/documentation/examples/libraries/altair.py +65 -0
- solara/website/pages/documentation/examples/libraries/bqplot.py +39 -0
- solara/website/pages/documentation/examples/libraries/ipyleaflet.py +33 -0
- solara/website/pages/documentation/examples/libraries/ipyleaflet_advanced.py +66 -0
- solara/website/pages/documentation/examples/utilities/__init__.py +10 -0
- solara/website/pages/documentation/examples/utilities/calculator.py +157 -0
- solara/website/pages/documentation/examples/utilities/countdown_timer.py +62 -0
- solara/website/pages/documentation/examples/utilities/todo.py +196 -0
- solara/website/pages/documentation/examples/visualization/__init__.py +6 -0
- solara/website/pages/documentation/examples/visualization/annotator.py +67 -0
- solara/website/pages/documentation/examples/visualization/linked_views.py +81 -0
- solara/website/pages/documentation/examples/visualization/plotly.py +44 -0
- solara/website/pages/documentation/faq/__init__.py +12 -0
- solara/website/pages/documentation/faq/content/99-faq.md +112 -0
- solara/website/pages/documentation/getting_started/__init__.py +9 -0
- solara/website/pages/documentation/getting_started/content/00-quickstart.md +107 -0
- solara/website/pages/documentation/getting_started/content/01-introduction.md +125 -0
- solara/website/pages/documentation/getting_started/content/02-installing.md +134 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/00-overview.md +14 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/10_data_science.py +13 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/20-web-app.md +89 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/30-ipywidgets.md +124 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/40-streamlit.md +146 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/50-dash.md +144 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/60-jupyter-dashboard-part1.py +65 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/SF_crime_sample.csv.gz +0 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/_data_science.ipynb +445 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/_jupyter_dashboard_1.ipynb +1021 -0
- solara/website/pages/documentation/getting_started/content/05-fundamentals/00-overview.md +11 -0
- solara/website/pages/documentation/getting_started/content/05-fundamentals/10-components.md +228 -0
- solara/website/pages/documentation/getting_started/content/05-fundamentals/50-state-management.md +278 -0
- solara/website/pages/documentation/getting_started/content/07-deploying/00-overview.md +7 -0
- solara/website/pages/documentation/getting_started/content/07-deploying/10-self-hosted.md +305 -0
- solara/website/pages/documentation/getting_started/content/07-deploying/20-cloud-hosted.md +80 -0
- solara/website/pages/documentation/getting_started/content/80-what-is-lab.md +7 -0
- solara/website/pages/documentation/getting_started/content/90-troubleshoot.md +26 -0
- solara/website/pages/docutils.py +38 -0
- solara/website/pages/home.vue +1199 -0
- solara/website/pages/our_team/__init__.py +83 -0
- solara/website/pages/pricing/__init__.py +31 -0
- solara/website/pages/roadmap/__init__.py +11 -0
- solara/website/pages/roadmap/roadmap.md +47 -0
- solara/website/pages/scale_ipywidgets.py +45 -0
- solara/website/pages/showcase/__init__.py +105 -0
- solara/website/pages/showcase/domino_code_assist.py +60 -0
- solara/website/pages/showcase/planeto_tessa.py +19 -0
- solara/website/pages/showcase/solara_dev.py +54 -0
- solara/website/pages/showcase/solarathon_2023_team_2.py +22 -0
- solara/website/pages/showcase/solarathon_2023_team_4.py +22 -0
- solara/website/pages/showcase/solarathon_2023_team_5.py +23 -0
- solara/website/pages/showcase/solarathon_2023_team_6.py +34 -0
- solara/website/pages/showcase/wanderlust.py +27 -0
- solara/website/public/beach.jpeg +0 -0
- solara/website/public/logo.svg +6 -0
- solara/website/public/social/discord.svg +1 -0
- solara/website/public/social/github.svg +1 -0
- solara/website/public/social/twitter.svg +3 -0
- solara/website/public/success.html +25 -0
- solara/website/templates/index.html.j2 +117 -0
- solara/website/utils.py +51 -0
- solara/widgets/__init__.py +1 -0
- solara/widgets/vue/gridlayout.vue +107 -0
- solara/widgets/vue/html.vue +4 -0
- solara/widgets/vue/navigator.vue +134 -0
- solara/widgets/vue/vegalite.vue +130 -0
- solara/widgets/widgets.py +74 -0
- solara_ui-1.45.0.data/data/etc/jupyter/jupyter_notebook_config.d/solara.json +7 -0
- solara_ui-1.45.0.data/data/etc/jupyter/jupyter_server_config.d/solara.json +7 -0
- solara_ui-1.45.0.dist-info/METADATA +162 -0
- solara_ui-1.45.0.dist-info/RECORD +464 -0
- solara_ui-1.45.0.dist-info/WHEEL +4 -0
- solara_ui-1.45.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: The rules of hooks in Solara
|
|
3
|
+
description: Learn the rules that govern the usage of hooks in your Solara application.
|
|
4
|
+
----
|
|
5
|
+
# Rules of hooks
|
|
6
|
+
|
|
7
|
+
Hooks are Python function whose name start with `use_`. The most used hook is [use_state](https://solara.dev/documentation/api/hooks/use_state) which is used to manage the state of a component.
|
|
8
|
+
|
|
9
|
+
Hooks can only be called at the top level of a function component or a custom hook. They cannot be called inside loops, conditions, or nested functions.
|
|
10
|
+
The reason for this is that hooks rely on the order in which they are called to maintain state between renders. If a hook is called conditionally, it may not be called on every render, which can mix up the states.
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
import solara
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@solara.component
|
|
17
|
+
def Page():
|
|
18
|
+
x, set_x = solara.use_state(1) # state 'slot' 1
|
|
19
|
+
if x < 10:
|
|
20
|
+
y, set_y = solara.use_state(2) # state 'slot' 2
|
|
21
|
+
else:
|
|
22
|
+
y, set_y = solara.use_state("foo") # *also* state 'slot' 2
|
|
23
|
+
solara.Text("Done")
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
In the above example, the `use_state(2)` and `use_state("foo")` is called conditionally, which means that the state 'slot' 2 (meaning, `y` and `set_y`) sometimes refer to the integer `2` and sometimes to the string `"foo"`. This gives unexpected behavior and will lead to bugs.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
The rules of hooks are checked by Solara, if you break the rules, you will get a warning, and in the future (Solara v2.0) you will get an error (an exception is raised).
|
|
30
|
+
|
|
31
|
+
## Example
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
import solara
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@solara.component
|
|
38
|
+
def Page():
|
|
39
|
+
for i in range(10):
|
|
40
|
+
solara.use_state(1)
|
|
41
|
+
solara.Text("Done")
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Will give the warning:
|
|
45
|
+
```
|
|
46
|
+
/some/prefix/site-packages/solara/solara/validate_hooks.py:122: UserWarning: /my/app.py:56: Page: `use_state` found within a loop created on line 55
|
|
47
|
+
To suppress this check, replace the line with:
|
|
48
|
+
solara.use_state(1) # noqa: SH103
|
|
49
|
+
|
|
50
|
+
Make sure you understand the consequences of this, by reading about the rules of hooks at:
|
|
51
|
+
https://solara.dev/documentation/advanced/understanding/rules-of-hooks
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
As the warning suggests, you can suppress the warning by adding `# noqa: SH103` to the line that breaks the rules.
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import solara
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@solara.component
|
|
61
|
+
def Page():
|
|
62
|
+
for i in range(10):
|
|
63
|
+
solara.use_state(1) # noqa: SH103
|
|
64
|
+
|
|
65
|
+
solara.Text("Done")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The warning can also be suppressed for the whole component by adding `# noqa: SH103` to the function definition.
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
import solara
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@solara.component
|
|
75
|
+
def Page(): # noqa: SH103
|
|
76
|
+
for i in range(10):
|
|
77
|
+
solara.use_state(1)
|
|
78
|
+
|
|
79
|
+
solara.Text("Done")
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
However, we strongly advise against this, and you should only use it if you know what you are doing (knowing the the loop will always run a fixed amount of times).
|
|
84
|
+
|
|
85
|
+
If you want to have an error raised instead of a warning, you can set the environment variable `SOLARA_CHECK_HOOKS=raise`, this is
|
|
86
|
+
planned to be the default in Solara v2.0.
|
|
87
|
+
|
|
88
|
+
In that case, you should get an error like this:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
solara.validate_hooks.HookValidationError: /my/app.py:56: Page: `use_state` found within a loop created on line 55
|
|
93
|
+
To suppress this check, replace the line with:
|
|
94
|
+
solara.use_state(1) # noqa: SH103
|
|
95
|
+
|
|
96
|
+
Make sure you understand the consequences of this, by reading about the rules of hooks at:
|
|
97
|
+
https://solara.dev/documentation/advanced/understanding/rules-of-hooks
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
For convenience, you can also disable the check by setting the environment variable `SOLARA_CHECK_HOOKS=off`, but we strongly advise against this.
|
|
102
|
+
|
|
103
|
+
## Types of error
|
|
104
|
+
|
|
105
|
+
### Early return (SH101)
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
import solara
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@solara.component
|
|
112
|
+
def Page():
|
|
113
|
+
solara.Text("Done")
|
|
114
|
+
if x < 10:
|
|
115
|
+
return # will cause the below use_state to not always be called
|
|
116
|
+
solara.use_state(1)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Conditional use (SH102)
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
import solara
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@solara.component
|
|
126
|
+
def Page():
|
|
127
|
+
if x < 10:
|
|
128
|
+
solara.use_state(1) # will cause the use_state to not always be called
|
|
129
|
+
solara.Text("Done")
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
### Loop use (SH103)
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
import solara
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@solara.component
|
|
140
|
+
def Page():
|
|
141
|
+
for i in range(x):
|
|
142
|
+
solara.use_state(1) # will cause the use_state to not always be a constant number of times
|
|
143
|
+
solara.Text("Done")
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Nested function use (SH104)
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
import solara
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@solara.component
|
|
153
|
+
def Page():
|
|
154
|
+
def inner():
|
|
155
|
+
solara.use_state(1) # will use_state always be called? Difficult to analyze, so don't do it
|
|
156
|
+
inner()
|
|
157
|
+
solara.Text("Done")
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
### Variable assignment (SH105)
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
import solara
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@solara.component
|
|
168
|
+
def Page():
|
|
169
|
+
x = solara.use_state
|
|
170
|
+
x(1) # will use_state always be called? Difficult to analyze, so don't do it
|
|
171
|
+
solara.Text("Done")
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
### Exception use (SH106)
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
import solara
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@solara.component
|
|
182
|
+
def Page():
|
|
183
|
+
try:
|
|
184
|
+
this_might_fail()
|
|
185
|
+
solara.use_state(1) # will use_state always be called? Difficult to analyze, so don't do it
|
|
186
|
+
except:
|
|
187
|
+
pass
|
|
188
|
+
solara.Text("Done")
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
For this reason, it's also advised to always call hooks first, before doing anything else in a function component that might raise
|
|
192
|
+
an exception.
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Using Solara with containers to build complex UIs
|
|
3
|
+
description: Solara allows for using python with statements to populate your UIs in a structured manner. This makes it easy to compose different components to build cohesive
|
|
4
|
+
wholes.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Laying out components with containers
|
|
8
|
+
|
|
9
|
+
## Introduction
|
|
10
|
+
Some components, such as our favorite `ClickButton` only add logic on top of an existing component:
|
|
11
|
+
|
|
12
|
+
```solara
|
|
13
|
+
import solara
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@solara.component
|
|
17
|
+
def ClickButton():
|
|
18
|
+
clicks, set_clicks = solara.use_state(0)
|
|
19
|
+
|
|
20
|
+
def my_click_hander():
|
|
21
|
+
set_clicks(clicks + 1)
|
|
22
|
+
|
|
23
|
+
# We return a single component
|
|
24
|
+
return solara.Button(label=f"Clicked: {clicks}", on_click=my_click_hander)
|
|
25
|
+
|
|
26
|
+
Page = ClickButton
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## Containers with children
|
|
31
|
+
However, more sophisticated components will add multiple components together into a container component, let's take a look at an example.
|
|
32
|
+
|
|
33
|
+
```solara
|
|
34
|
+
import solara
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@solara.component
|
|
38
|
+
def FancyClickButton():
|
|
39
|
+
clicks, set_clicks = solara.use_state(0)
|
|
40
|
+
|
|
41
|
+
def increase_count():
|
|
42
|
+
set_clicks(clicks + 1)
|
|
43
|
+
|
|
44
|
+
def reset_count():
|
|
45
|
+
set_clicks(0)
|
|
46
|
+
|
|
47
|
+
button_increase = solara.Button(label=f"Clicked: {clicks}", on_click=increase_count)
|
|
48
|
+
button_reset = solara.Button(label="Reset", on_click=reset_count)
|
|
49
|
+
|
|
50
|
+
return solara.Row(children=[button_increase,
|
|
51
|
+
button_reset,
|
|
52
|
+
])
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
Page = FancyClickButton
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
Here we use an [HBox](/documentation/components/layout/hbox) to lay out two child components horizontally.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## Cleaner way to add children to containers
|
|
64
|
+
|
|
65
|
+
Because using container components is so common, we created a more convenient way to pass children to components and made your code look neater and more structured as well (avoiding nested lists).
|
|
66
|
+
|
|
67
|
+
```solara
|
|
68
|
+
import solara
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@solara.component
|
|
72
|
+
def FancyClickButton():
|
|
73
|
+
clicks, set_clicks = solara.use_state(0)
|
|
74
|
+
|
|
75
|
+
def increase_count():
|
|
76
|
+
set_clicks(clicks + 1)
|
|
77
|
+
|
|
78
|
+
def reset_count():
|
|
79
|
+
set_clicks(0)
|
|
80
|
+
|
|
81
|
+
with solara.Row() as main:
|
|
82
|
+
solara.Button(label=f"Clicked: {clicks}", on_click=increase_count)
|
|
83
|
+
solara.Button(label="Reset", on_click=reset_count)
|
|
84
|
+
return main
|
|
85
|
+
|
|
86
|
+
Page = FancyClickButton
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Here we are using the top-level Row as a context manager (with the name `main`). All child elements created within this context are automatically added as a child.
|
|
91
|
+
|
|
92
|
+
### About Context managers
|
|
93
|
+
|
|
94
|
+
Context managers are a Python language feature, there are two ways to use them:
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
|
|
98
|
+
with some_anonymous_context_manager():
|
|
99
|
+
print("some code")
|
|
100
|
+
|
|
101
|
+
with some_named_context_manager() as this_is_my_name:
|
|
102
|
+
print("some other code")
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Where the last example assigns the context manager to a variable. In Solara we only need to do that to the top context manager, since we need to return that in our [render function](/documentation/advanced/understanding/anatomy).
|
|
106
|
+
|
|
107
|
+
All Reacton or Solara components return elements that can be used as context managers. Context managers allow for code to be executed before and after your code block inside of the context manager. This allows us to capture all elements created inside of the context manager. If you want to know more about context managers, consult the Python documentation since this is not Solara specific.
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
### Nested layout
|
|
111
|
+
|
|
112
|
+
Adding children using context managers work at any level, you can nest Rows and Columns [or any other containers](/api#components).
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
```solara
|
|
116
|
+
import solara
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@solara.component
|
|
120
|
+
def FancyClickButton():
|
|
121
|
+
clicks, set_clicks = solara.use_state(0)
|
|
122
|
+
|
|
123
|
+
def increase_count():
|
|
124
|
+
set_clicks(clicks + 1)
|
|
125
|
+
|
|
126
|
+
def reset_count():
|
|
127
|
+
set_clicks(0)
|
|
128
|
+
|
|
129
|
+
with solara.Column() as main:
|
|
130
|
+
with solara.Row():
|
|
131
|
+
solara.Button(label=f"Clicked: {clicks}", on_click=increase_count)
|
|
132
|
+
solara.Button(label="Reset", on_click=reset_count)
|
|
133
|
+
solara.Text("I am a child of a VBox")
|
|
134
|
+
return main
|
|
135
|
+
|
|
136
|
+
Page = FancyClickButton
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
## Automatic containers
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
Instead of returning the main container, Solara also allows you to not have a return value (or return `None`).
|
|
145
|
+
If that is the case, Solara will look at what elements you created. If you created one, that element will be taken
|
|
146
|
+
as a return value instead. If you make more than one element, those elements will be automatically wrapped by
|
|
147
|
+
a [Column](/documentation/components/layout/column). The only benefit of returning an element, is that we can infer the correct return type,
|
|
148
|
+
which can be useful for testing purposes. Users should probably never return an element, but use the automatic
|
|
149
|
+
container feature.
|
|
150
|
+
|
|
151
|
+
```solara
|
|
152
|
+
import solara
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@solara.component
|
|
156
|
+
def ClickButton():
|
|
157
|
+
clicks, set_clicks = solara.use_state(0)
|
|
158
|
+
|
|
159
|
+
def my_click_hander():
|
|
160
|
+
set_clicks(clicks + 1)
|
|
161
|
+
|
|
162
|
+
solara.Button(label=f"Clicked: {clicks}", on_click=my_click_hander)
|
|
163
|
+
solara.Button(label=f"Reset", on_click=lambda: set_clicks(0))
|
|
164
|
+
|
|
165
|
+
Page = ClickButton
|
|
166
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Understanding different parts of Solara
|
|
3
|
+
description: Solara is made of two main components, the bulk of the Solara package with UI elements that can be used together with Jupyter, and Solara server, which
|
|
4
|
+
allows for these UI elements to be used in standalone apps and dashboards
|
|
5
|
+
---
|
|
6
|
+
# Solara
|
|
7
|
+
|
|
8
|
+
Solara combines [ipywidgets](./ipywidgets), [reacton](./reacton) and puts it into a opinionated framework to make web apps with a focus on data (data apps for short).
|
|
9
|
+
|
|
10
|
+
Solara consists of two main parts
|
|
11
|
+
|
|
12
|
+
## Solara-ui
|
|
13
|
+
|
|
14
|
+
A set of opinionated react components and hooks that allow you to build web apps and data apps faster.
|
|
15
|
+
|
|
16
|
+
## Solara-server
|
|
17
|
+
|
|
18
|
+
A web framework for deploying web apps or data apps in production. Opinionated about pages and routing.
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Understanding routing in multi-page solara apps
|
|
3
|
+
description: Dive into Solara's routing, which provides a powerful way to compose multiple pages or dashboards into an integrated app.
|
|
4
|
+
---
|
|
5
|
+
# Routing
|
|
6
|
+
|
|
7
|
+
Routing takes care of linking a web address (more specifically the [pathname](https://developer.mozilla.org/en-US/docs/Web/API/Location), e.g. "/docs/basics/solara") to a state of the UI,
|
|
8
|
+
usually in the form of what appears as pages to a user.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
Routing includes navigation (hitting the back and forward button of your browser) without causing a page reload.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## Automatic routing
|
|
15
|
+
|
|
16
|
+
Setting up routing can be repetitive, and therefore Solara comes also with a more opinionated method for setting up routing automatically.
|
|
17
|
+
|
|
18
|
+
### Based on a directory
|
|
19
|
+
|
|
20
|
+
Using [`generate_routes_directory(path: Path) -> List[solara.Route]:`](/documentation/api/routing/generate_routes_directory) we can request Solara to give us a list of
|
|
21
|
+
routes by scanning a directory for Python scripts, Notebooks and Markdown files.
|
|
22
|
+
|
|
23
|
+
This function is being used by Solara if you run solara server with a directory as argument name, as used in [our Multi Page guide](/documentation/advanced/howto/multipage). More details can be found there.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Based on a Python package
|
|
27
|
+
|
|
28
|
+
Similar to the previous section [`generate_routes(module: ModuleType) -> List[solara.Route]:`](/documentation/api/routing/generate_routes) will return a list of routes by scanning a Python package or module for `Page` components, or `app` elements. Again, more information can be found at [our Multi Page guide](/documentation/advanced/howto/multipage).
|
|
29
|
+
|
|
30
|
+
## Manually defining routes
|
|
31
|
+
|
|
32
|
+
In Solara, we set up routing by defining a list of `solara.Route` objects, where each route can have another list of routes, its children, forming
|
|
33
|
+
a tree of routes. We assign this list to the `routes` variable in your main app script or module.
|
|
34
|
+
|
|
35
|
+
### Defining route components
|
|
36
|
+
|
|
37
|
+
If no `Page` component is found in your main script or module, Solara will assume you have either set the `component` or the `module` argument of the `solara.Route` object.
|
|
38
|
+
|
|
39
|
+
For example
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
import solara
|
|
43
|
+
from solara.website.pages.examples.utilities import calculator
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@solara.component
|
|
47
|
+
def Home():
|
|
48
|
+
solara.Markdown("Home")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@solara.component
|
|
52
|
+
def About():
|
|
53
|
+
solara.Markdown("About")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
routes = [
|
|
57
|
+
solara.Route(path="/", component=Home, label="Home"),
|
|
58
|
+
# the calculator module should have a Page component
|
|
59
|
+
solara.Route(path="calculator", module=calculator, label="Calculator"),
|
|
60
|
+
solara.Route(path="about", component=About, label="About"),
|
|
61
|
+
]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Defining route components
|
|
65
|
+
|
|
66
|
+
If you do define a `Page` component, you are fully responsible for how routing is done, but we recommend using [use_route](/documentation/api/routing/use_route).
|
|
67
|
+
|
|
68
|
+
An example route definition could be something like this:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
import solara
|
|
72
|
+
|
|
73
|
+
routes = [
|
|
74
|
+
# route level == 0
|
|
75
|
+
solara.Route(path="/"), # matches empty path ''
|
|
76
|
+
solara.Route(
|
|
77
|
+
# route level == 1
|
|
78
|
+
path="docs", # matches '/docs'
|
|
79
|
+
children=[
|
|
80
|
+
# route level == 2
|
|
81
|
+
solara.Route(path="basics", children=[ # matches '/docs/basics'
|
|
82
|
+
# route level == 3
|
|
83
|
+
solara.Route(path="react"), # matches '/docs/basics/react'
|
|
84
|
+
solara.Route(path="ipywidgets"), # matches '/docs/basics/ipywidgets'
|
|
85
|
+
solara.Route(path="solara"), # matches '/docs/basics/solara'
|
|
86
|
+
]),
|
|
87
|
+
solara.Route(path="advanced") # matches '/docs/advanced'
|
|
88
|
+
],
|
|
89
|
+
),
|
|
90
|
+
solara.Route(
|
|
91
|
+
path="blog",
|
|
92
|
+
# route level == 1
|
|
93
|
+
children=[
|
|
94
|
+
solara.Route(path="/"), # matches '/blog'
|
|
95
|
+
solara.Route(path="foo"), # matches '/blog/foo'
|
|
96
|
+
solara.Route(path="bar"), # matches '/blog/bar'
|
|
97
|
+
],
|
|
98
|
+
),
|
|
99
|
+
solara.Route(path="contact") # matches '/contact'
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
# Lets assume our pathname is `/docs/basics/react`,
|
|
103
|
+
@solara.component
|
|
104
|
+
def Page():
|
|
105
|
+
level = solara.use_route_level() # returns 0
|
|
106
|
+
route_current, routes_current_level = solara.use_route()
|
|
107
|
+
# route_current is routes[1], i.e. solara.Route(path="docs", children=[...])
|
|
108
|
+
# routes_current_level is [routes[0], routes[1], routes[2], routes[3]], i.e.:
|
|
109
|
+
# [solara.Route(path="/"), solara.Route(path="docs", children=[...]),
|
|
110
|
+
# solara.Route(path="blog", children=[...]), solara.Route(path="contact")]
|
|
111
|
+
if route_current is None: # no matching route
|
|
112
|
+
return solara.Error("oops, page not found")
|
|
113
|
+
else:
|
|
114
|
+
# we could render some top level navigation here based on route_current_level and route_current
|
|
115
|
+
return MyFirstLevelChildComponent()
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Routes are matched by splitting the pathname around the slash ("/") and matching each part to the routes. The level of the depth into the tree is what we call the `route_level`, which starts at 0, the top level.
|
|
119
|
+
Each call to `use_route` will return the current route (if there is a match to the current path) and the list of siblings including itself.
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
Now the `MyFirstLevelChildComponent` component is responsible for rendering the second level navigation:
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
@solara.component
|
|
126
|
+
def MyFirstLevelChildComponent():
|
|
127
|
+
level = solara.use_route_level() # returns 1
|
|
128
|
+
route_current, routes_current_level = solara.use_route()
|
|
129
|
+
# route_current is routes[1].children[0], i.e. solara.Route(path="basics", children=[...])
|
|
130
|
+
# routes_current_level is [routes[1].children[0], routes[1].children[1]], i.e.:
|
|
131
|
+
# [solara.Route(path="basics", children=[...]), solara.Route(path="advanced")]
|
|
132
|
+
if route_current is None: # no matching route
|
|
133
|
+
return solara.Error("oops, page not found")
|
|
134
|
+
else:
|
|
135
|
+
# we could render some mid level navigation here based on route_current_level and route_current
|
|
136
|
+
return MySecondLevelChildComponent()
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
And the `MySecondLevelChildComponent` component is responsible for rendering the third level navigation:
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
@solara.component
|
|
144
|
+
def MySecondLevelChildComponent():
|
|
145
|
+
level = solara.use_route_level() # returns 2
|
|
146
|
+
route_current, routes_current_level = solara.use_route()
|
|
147
|
+
# route_current is routes[1].children[0].children[0], i.e. solara.Route(path="react")
|
|
148
|
+
# routes_current_level is [routes[1].children[0].children[0], routes[1].children[0].children[1], routes[1].children[0].children[2]], i.e.
|
|
149
|
+
# [solara.Route(path="react"), solara.Route(path="ipywidgets"), solara.Route(path="solara")]
|
|
150
|
+
if route_current is None: # no matching route
|
|
151
|
+
return solara.Error("oops, page not found")
|
|
152
|
+
else:
|
|
153
|
+
# we could render some mid level navigation here based on route_current_level and route_current
|
|
154
|
+
if route_current.path == "react":
|
|
155
|
+
return DocsBasicReact() # render the actual content
|
|
156
|
+
elif route_current.path == "ipywidgets":
|
|
157
|
+
return DocsBasicIpyWidgets()
|
|
158
|
+
elif route_current.path == "solara":
|
|
159
|
+
return DocsBasicSolara()
|
|
160
|
+
else:
|
|
161
|
+
return solara.Error("oops, not possible!")
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
From this code, we can see we are free how we transform the routes into the state of the UI (i.e. which components are rendered).
|
|
166
|
+
|
|
167
|
+
## Adding data
|
|
168
|
+
|
|
169
|
+
Often, your render logic needs some extra data on what to display. For instance, you may want to dynamically render tabs based on the routes,
|
|
170
|
+
which requires you to have a label, and know which component to add.
|
|
171
|
+
For this purposed we added `label: str` and the `component' attributes, so you can defines routes likes:
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
routes = [
|
|
175
|
+
solara.Route("/", component=Home, label="What is Solara ☀️?"),
|
|
176
|
+
solara.Route("docs", component=docs.App, label="Docs", children=docs.routes),
|
|
177
|
+
solara.Route(
|
|
178
|
+
"demo",
|
|
179
|
+
component=demo.Demo,
|
|
180
|
+
children=demo.routes,
|
|
181
|
+
label="Demo",
|
|
182
|
+
),
|
|
183
|
+
...
|
|
184
|
+
]
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
In the case where you did not specify a `Page` component, label is used for the [Title](/documentation/components/page/title) component.
|
|
188
|
+
|
|
189
|
+
If you need to store more data in the route, you are free to put whatever you want in the `data` attribute, see also [Route](/documentation/api/routing/route).
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
## Linking
|
|
194
|
+
|
|
195
|
+
Note that all routes are relative, since a component does not know if it is embedded into a larger application, which may also do routing.
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
Therefore you should never use the `route.path` for navigation since the route object has no knowledge of the full url
|
|
199
|
+
(e.g. `/docs/basics/ipywidgets`) but only knows its small piece of the pathname (e.g. `ipywidgets`)
|
|
200
|
+
|
|
201
|
+
Using [`resolve_path`](/documentation/api/routing/resolve_path) we can request the full url for navigation.
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
def resolve_path(path_or_route: Union[str, solara.Route], level=0) -> str:
|
|
205
|
+
...
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
We can pass this full URL to the [`solara.Link`](/documentation/components/advanced/link) component, e.g. like:
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
@solara.component
|
|
212
|
+
def LinkToIpywidgets():
|
|
213
|
+
route_ipywidgets = routes.children[1].children[0].children[1]
|
|
214
|
+
# route_ipywidgets.path == "ipywidgets"
|
|
215
|
+
path = solara.resolve_path(route_ipywidgets)
|
|
216
|
+
# path == '/docs/basics/ipywidgets
|
|
217
|
+
with solara.Link(path) as main:
|
|
218
|
+
solara.Button("read about ipywidgets")
|
|
219
|
+
return main
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Linking to Sections of a Page
|
|
223
|
+
|
|
224
|
+
The `solara.Link` component also supports linking to HTML elements identified by id. Although most Solara components don't directly support the id attribute, you can assign ids to all ipyvuetify components, using the `attributes` argument:
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
solara.v.Btn(attributes={"id": "my-id"}, ...)
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
You can then link to a particular element by appending `#` followed by its id to your link, i.e. `solara.Link(route_or_path="/page#my-id")`. If you want the page to smoothly scroll to the linked element, you should give an element that contains it (for instance the `html`-element) the following CSS rule:
|
|
231
|
+
|
|
232
|
+
```css
|
|
233
|
+
html {
|
|
234
|
+
scroll-behaviour: smooth;
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Fully manual routing
|
|
239
|
+
|
|
240
|
+
If you want to do routing fully manually, you can use the [`solara.use_router`](/documentation/api/routing/use_router) hook, and use the `.path` attribute.
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
import solara
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@solara.component
|
|
247
|
+
def Page():
|
|
248
|
+
router = solara.use_router()
|
|
249
|
+
path = router.path
|
|
250
|
+
parts = path.split("/")
|
|
251
|
+
solara.Markdown(f"Path = {path!r}, and split up into {parts!r}")
|
|
252
|
+
# now you can do anything with path or parts.
|
|
253
|
+
# e.g.
|
|
254
|
+
# if parts[0] == "docs":
|
|
255
|
+
# solara.Markdown("You are in the docs section")
|
|
256
|
+
```
|