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,77 @@
|
|
|
1
|
+
# isort: skip_file
|
|
2
|
+
from .button import Button # noqa: F401
|
|
3
|
+
from .style import Style # noqa: F401 F403
|
|
4
|
+
from .misc import * # noqa: F401 F403
|
|
5
|
+
from .alert import Warning, Info, Error, Success # noqa: F401 F403
|
|
6
|
+
from .checkbox import Checkbox # noqa: F401 F403
|
|
7
|
+
from .cross_filter import ( # noqa: F401
|
|
8
|
+
CrossFilterDataFrame,
|
|
9
|
+
CrossFilterReport,
|
|
10
|
+
CrossFilterSelect,
|
|
11
|
+
CrossFilterSlider,
|
|
12
|
+
)
|
|
13
|
+
from .datatable import DataTable, DataFrame # noqa: F401 F403
|
|
14
|
+
from .details import Details # noqa: F401 F403
|
|
15
|
+
from .file_browser import FileBrowser # noqa: F401 F403
|
|
16
|
+
from .image import Image # noqa: F401 F403
|
|
17
|
+
from .markdown import Markdown, MarkdownIt # noqa: F401 F403
|
|
18
|
+
from .slider import ( # noqa: F401 F403
|
|
19
|
+
DateSlider, # noqa: F401 F403
|
|
20
|
+
FloatSlider, # noqa: F401 F403
|
|
21
|
+
IntSlider, # noqa: F401 F403
|
|
22
|
+
ValueSlider, # noqa: F401 F403
|
|
23
|
+
SliderDate, # noqa: F401 F403
|
|
24
|
+
SliderFloat, # noqa: F401 F403
|
|
25
|
+
SliderInt, # noqa: F401 F403
|
|
26
|
+
SliderValue, # noqa: F401 F403
|
|
27
|
+
SliderRangeInt, # noqa: F401 F403
|
|
28
|
+
SliderRangeFloat, # noqa: F401 F403
|
|
29
|
+
) # noqa: F401 F403
|
|
30
|
+
from .sql_code import SqlCode # noqa: F401 F403
|
|
31
|
+
from .togglebuttons import ( # noqa: F401 F403
|
|
32
|
+
ToggleButtonsMultiple,
|
|
33
|
+
ToggleButtonsSingle,
|
|
34
|
+
)
|
|
35
|
+
from .input import InputText, InputFloat, InputInt # noqa: F401 F403
|
|
36
|
+
from .input_text_area import InputTextArea # noqa: F401 F403
|
|
37
|
+
from .pivot_table import PivotTableView, PivotTable, PivotTableCard # noqa: F401 F403
|
|
38
|
+
from .head import Head # noqa: F401 F403
|
|
39
|
+
from .title import Title # noqa: F401 F403
|
|
40
|
+
from .link import Link # noqa: F401 F403
|
|
41
|
+
from .applayout import AppLayout, Sidebar, AppBar, AppBarTitle # noqa: F401 F403
|
|
42
|
+
from .tab_navigation import TabNavigation # noqa: F401 F403
|
|
43
|
+
from .markdown_editor import MarkdownEditor # noqa: F401 F403
|
|
44
|
+
from .select import Select, SelectMultiple # noqa: F401 F403
|
|
45
|
+
from .matplotlib import FigureMatplotlib # noqa: F401 F403
|
|
46
|
+
from .echarts import FigureEcharts # noqa: F401 F403
|
|
47
|
+
from .figure_altair import FigureAltair, AltairChart # noqa: F401 F403
|
|
48
|
+
from .meta import Meta # noqa: F401 F403
|
|
49
|
+
from .columns import Columns, ColumnsResponsive # noqa: F401 F403
|
|
50
|
+
from .file_drop import FileDrop, FileDropMultiple # noqa: F401 F403
|
|
51
|
+
from .file_download import FileDownload # noqa: F401 F403
|
|
52
|
+
from .tooltip import Tooltip # noqa: F401 F403
|
|
53
|
+
from .card import Card, CardActions # noqa: F401 F403
|
|
54
|
+
from .spinner import SpinnerSolara # noqa: F401 F403
|
|
55
|
+
from .switch import Switch # noqa: F401 F403
|
|
56
|
+
from .progress import ProgressLinear # noqa: F401 F403
|
|
57
|
+
from .component_vue import _component_vue, component_vue # noqa: F401 F403
|
|
58
|
+
import reacton.core
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
from reacton import Fragment as Fragment # type: ignore
|
|
62
|
+
except ImportError:
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
import logging
|
|
66
|
+
from ..settings import main
|
|
67
|
+
|
|
68
|
+
_container = None
|
|
69
|
+
|
|
70
|
+
if main.default_container in globals():
|
|
71
|
+
_container = globals()[main.default_container]
|
|
72
|
+
else:
|
|
73
|
+
logger = logging.getLogger("solara.components")
|
|
74
|
+
logger.warning(f"Default container {main.default_container} not found in solara.components. Defaulting to Column.")
|
|
75
|
+
|
|
76
|
+
# TODO: When Solara 2.0 releases Column should be replaced with Fragment
|
|
77
|
+
reacton.core._default_container = _container or Column # noqa: F405
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
from typing import List, Optional, Union
|
|
2
|
+
|
|
3
|
+
import reacton.ipyvuetify as v
|
|
4
|
+
|
|
5
|
+
import solara
|
|
6
|
+
from solara.util import _combine_classes
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@solara.component
|
|
10
|
+
def Success(
|
|
11
|
+
label: Optional[str] = None,
|
|
12
|
+
icon: Union[bool, str, None] = True,
|
|
13
|
+
dense=False,
|
|
14
|
+
outlined=True,
|
|
15
|
+
text=True,
|
|
16
|
+
children=[],
|
|
17
|
+
classes: List[str] = [],
|
|
18
|
+
**kwargs,
|
|
19
|
+
):
|
|
20
|
+
"""Display a success message (green color).
|
|
21
|
+
|
|
22
|
+
## Arguments
|
|
23
|
+
|
|
24
|
+
* `label`: the message to display
|
|
25
|
+
* `icon`: if True, display a check icon, if False, don't display an icon, if a string,
|
|
26
|
+
display the icon with that name ([Overview of available icons](https://pictogrammers.github.io/@mdi/font/4.9.95/)).
|
|
27
|
+
* `dense`: if True, display the message in a dense format, using less vertical height.
|
|
28
|
+
* `outlined`: if True (default), display the message in an outlined border, instead of a filled box.
|
|
29
|
+
* `text`: if True (default), display the message in a text format, which applies a semi-transparent background.
|
|
30
|
+
* `classes`: additional CSS classes to apply.
|
|
31
|
+
"""
|
|
32
|
+
# vuetify doesn't accept True, but is ok with None for a default icon
|
|
33
|
+
if icon is True:
|
|
34
|
+
icon = None
|
|
35
|
+
return v.Alert(
|
|
36
|
+
type="success",
|
|
37
|
+
text=text,
|
|
38
|
+
outlined=outlined,
|
|
39
|
+
dense=dense,
|
|
40
|
+
icon=icon,
|
|
41
|
+
children=[*([label] if label is not None else []), *children],
|
|
42
|
+
class_=_combine_classes(classes),
|
|
43
|
+
**kwargs,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@solara.component
|
|
48
|
+
def Info(
|
|
49
|
+
label: Optional[str] = None,
|
|
50
|
+
icon: Union[bool, str, None] = True,
|
|
51
|
+
dense=False,
|
|
52
|
+
outlined=True,
|
|
53
|
+
text=True,
|
|
54
|
+
children=[],
|
|
55
|
+
classes: List[str] = [],
|
|
56
|
+
**kwargs,
|
|
57
|
+
):
|
|
58
|
+
"""Display a info message (blue color).
|
|
59
|
+
|
|
60
|
+
## Arguments
|
|
61
|
+
|
|
62
|
+
* `label`: the message to display
|
|
63
|
+
* `icon`: if True, display a info icon, if False, don't display an icon, if a string,
|
|
64
|
+
display the icon with that name ([Overview of available icons](https://pictogrammers.github.io/@mdi/font/4.9.95/)).
|
|
65
|
+
* `dense`: if True, display the message in a dense format, using less vertical height.
|
|
66
|
+
* `outlined`: if True (default), display the message in an outlined border, instead of a filled box.
|
|
67
|
+
* `text`: if True (default), display the message in a text format, which applies a semi-transparent background.
|
|
68
|
+
* `classes`: additional CSS classes to apply.
|
|
69
|
+
"""
|
|
70
|
+
if icon is True:
|
|
71
|
+
icon = None
|
|
72
|
+
return v.Alert(
|
|
73
|
+
type="info",
|
|
74
|
+
text=text,
|
|
75
|
+
outlined=outlined,
|
|
76
|
+
dense=dense,
|
|
77
|
+
icon=icon,
|
|
78
|
+
children=[*([label] if label is not None else []), *children],
|
|
79
|
+
class_=_combine_classes(classes),
|
|
80
|
+
**kwargs,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@solara.component
|
|
85
|
+
def Warning(
|
|
86
|
+
label: Optional[str] = None,
|
|
87
|
+
icon: Union[bool, str, None] = True,
|
|
88
|
+
dense=False,
|
|
89
|
+
outlined=True,
|
|
90
|
+
text=True,
|
|
91
|
+
children=[],
|
|
92
|
+
classes: List[str] = [],
|
|
93
|
+
**kwargs,
|
|
94
|
+
):
|
|
95
|
+
"""Display a warning message (orange color).
|
|
96
|
+
|
|
97
|
+
## Arguments
|
|
98
|
+
|
|
99
|
+
* `label`: the message to display
|
|
100
|
+
* `icon`: if True, display a exclamation icon, if False, don't display an icon, if a string,
|
|
101
|
+
display the icon with that name ([Overview of available icons](https://pictogrammers.github.io/@mdi/font/4.9.95/)).
|
|
102
|
+
* `dense`: if True, display the message in a dense format, using less vertical height.
|
|
103
|
+
* `outlined`: if True (default), display the message in an outlined border, instead of a filled box.
|
|
104
|
+
* `text`: if True (default), display the message in a text format, which applies a semi-transparent background.
|
|
105
|
+
* `classes`: additional CSS classes to apply.
|
|
106
|
+
"""
|
|
107
|
+
if icon is True:
|
|
108
|
+
icon = None
|
|
109
|
+
return v.Alert(
|
|
110
|
+
type="warning",
|
|
111
|
+
text=text,
|
|
112
|
+
outlined=outlined,
|
|
113
|
+
dense=dense,
|
|
114
|
+
icon=icon,
|
|
115
|
+
children=[*([label] if label is not None else []), *children],
|
|
116
|
+
class_=_combine_classes(classes),
|
|
117
|
+
**kwargs,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@solara.component
|
|
122
|
+
def Error(
|
|
123
|
+
label: Optional[str] = None,
|
|
124
|
+
icon: Union[bool, str, None] = True,
|
|
125
|
+
dense=False,
|
|
126
|
+
outlined=True,
|
|
127
|
+
text=True,
|
|
128
|
+
children=[],
|
|
129
|
+
classes: List[str] = [],
|
|
130
|
+
**kwargs,
|
|
131
|
+
):
|
|
132
|
+
"""Display an error message (red color).
|
|
133
|
+
|
|
134
|
+
## Arguments
|
|
135
|
+
|
|
136
|
+
* `label`: the message to display
|
|
137
|
+
* `icon`: if True, display a exclamation in a red triangle icon, if False, don't display an icon, if a string,
|
|
138
|
+
display the icon with that name ([Overview of available icons](https://pictogrammers.github.io/@mdi/font/4.9.95/)).
|
|
139
|
+
* `dense`: if True, display the message in a dense format, using less vertical height.
|
|
140
|
+
* `outlined`: if True (default), display the message in an outlined border, instead of a filled box.
|
|
141
|
+
* `text`: if True (default), display the message in a text format, which applies a semi-transparent background.
|
|
142
|
+
* `classes`: additional CSS classes to apply.
|
|
143
|
+
"""
|
|
144
|
+
if icon is True:
|
|
145
|
+
icon = None
|
|
146
|
+
return v.Alert(
|
|
147
|
+
type="error",
|
|
148
|
+
text=text,
|
|
149
|
+
outlined=outlined,
|
|
150
|
+
dense=dense,
|
|
151
|
+
icon=icon,
|
|
152
|
+
children=[*([label] if label is not None else []), *children],
|
|
153
|
+
class_=_combine_classes(classes),
|
|
154
|
+
**kwargs,
|
|
155
|
+
)
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
from typing import Callable, Dict, List, Optional, Tuple, Union, cast
|
|
2
|
+
|
|
3
|
+
import reacton
|
|
4
|
+
import reacton.core
|
|
5
|
+
import reacton.ipyvuetify as v
|
|
6
|
+
import reacton.utils
|
|
7
|
+
from reacton.core import Element
|
|
8
|
+
|
|
9
|
+
import solara
|
|
10
|
+
import solara.lab
|
|
11
|
+
|
|
12
|
+
from . import title as t
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@solara.component
|
|
16
|
+
def AppIcon(open=False, on_click=None, **kwargs):
|
|
17
|
+
def click(*ignore):
|
|
18
|
+
on_click()
|
|
19
|
+
|
|
20
|
+
icon = v.AppBarNavIcon(**kwargs)
|
|
21
|
+
v.use_event(icon, "click", click)
|
|
22
|
+
return icon
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
should_use_embed = solara.create_context(False)
|
|
26
|
+
PortalElements = Dict[str, List[Tuple[int, Element]]]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _set_sidebar_default(updater: Callable[[PortalElements], PortalElements]):
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ElementPortal:
|
|
34
|
+
def __init__(self):
|
|
35
|
+
self.context = solara.create_context(_set_sidebar_default)
|
|
36
|
+
|
|
37
|
+
# TODO: can we generalize the use of 'portals' ? (i.e. transporting elements from one place to another)
|
|
38
|
+
def use_portal(self) -> List[Element]:
|
|
39
|
+
portal_elements, set_portal_elements = solara.use_state(cast(PortalElements, {}))
|
|
40
|
+
self.context.provide(set_portal_elements) # type: ignore
|
|
41
|
+
|
|
42
|
+
portal_elements_flat: List[Tuple[int, Element]] = []
|
|
43
|
+
for uuid, value in portal_elements.items():
|
|
44
|
+
portal_elements_flat.extend(value)
|
|
45
|
+
portal_elements_flat.sort(key=lambda x: x[0])
|
|
46
|
+
return [e[1] for e in portal_elements_flat]
|
|
47
|
+
|
|
48
|
+
def use_portal_add(self, children: List[Element], offset: int):
|
|
49
|
+
key = solara.use_unique_key(prefix="portal-")
|
|
50
|
+
set_portal_elements = solara.use_context(self.context)
|
|
51
|
+
values: List[Tuple[int, Element]] = []
|
|
52
|
+
for i, child in enumerate(children):
|
|
53
|
+
values.append((offset + i, child))
|
|
54
|
+
|
|
55
|
+
# updates we do when children/offset changes
|
|
56
|
+
def add():
|
|
57
|
+
# we use the update function method, to avoid stale data
|
|
58
|
+
def update_dict(portal_elements):
|
|
59
|
+
portal_elements_updated = portal_elements.copy()
|
|
60
|
+
portal_elements_updated[key] = values
|
|
61
|
+
return portal_elements_updated
|
|
62
|
+
|
|
63
|
+
set_portal_elements(update_dict)
|
|
64
|
+
|
|
65
|
+
solara.use_effect(add, [values])
|
|
66
|
+
|
|
67
|
+
# cleanup we only need to do after component removal
|
|
68
|
+
def add_cleanup():
|
|
69
|
+
def cleanup():
|
|
70
|
+
def without(portal_elements):
|
|
71
|
+
portal_elements_restored = portal_elements.copy()
|
|
72
|
+
portal_elements_restored.pop(key, None)
|
|
73
|
+
return portal_elements_restored
|
|
74
|
+
|
|
75
|
+
set_portal_elements(without)
|
|
76
|
+
|
|
77
|
+
return cleanup
|
|
78
|
+
|
|
79
|
+
solara.use_effect(add_cleanup, [])
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
sidebar_portal = ElementPortal()
|
|
83
|
+
appbar_portal = ElementPortal()
|
|
84
|
+
apptitle_portal = ElementPortal()
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@solara.component
|
|
88
|
+
def AppBar(children=[]):
|
|
89
|
+
"""Puts its children in the app bar of the AppLayout (or any layout that supports it).
|
|
90
|
+
|
|
91
|
+
This component does not need to be a direct child of the AppLayout, it can be at any level in your component tree.
|
|
92
|
+
|
|
93
|
+
If a [Tabs](/documentation/components/lab/tabs) component is used as direct child of the app bar, it will be shown under the app bar.
|
|
94
|
+
|
|
95
|
+
## Example showing an app bar
|
|
96
|
+
```solara
|
|
97
|
+
import solara
|
|
98
|
+
|
|
99
|
+
@solara.component
|
|
100
|
+
def Page():
|
|
101
|
+
logged_in, set_logged_in = solara.use_state(False)
|
|
102
|
+
def toggle_login():
|
|
103
|
+
set_logged_in(not logged_in)
|
|
104
|
+
|
|
105
|
+
with solara.AppBar():
|
|
106
|
+
icon_name = "mdi-logout" if logged_in else "mdi-login"
|
|
107
|
+
solara.Button(icon_name=icon_name , on_click=toggle_login, icon=True)
|
|
108
|
+
with solara.Column():
|
|
109
|
+
if logged_in:
|
|
110
|
+
solara.Info("You are logged in")
|
|
111
|
+
else:
|
|
112
|
+
solara.Error("You are logged out")
|
|
113
|
+
```
|
|
114
|
+
"""
|
|
115
|
+
# TODO: generalize this, this is also used in title
|
|
116
|
+
level = 0
|
|
117
|
+
rc = reacton.core.get_render_context()
|
|
118
|
+
context = rc.context
|
|
119
|
+
while context and context.parent:
|
|
120
|
+
level += 1
|
|
121
|
+
context = context.parent
|
|
122
|
+
offset = 2**level
|
|
123
|
+
appbar_portal.use_portal_add(children, offset)
|
|
124
|
+
|
|
125
|
+
return solara.Div(style="display; none")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@solara.component
|
|
129
|
+
def AppBarTitle(children=[]):
|
|
130
|
+
"""Puts its children in the title section of the AppBar (or any layout that supports it).
|
|
131
|
+
|
|
132
|
+
This component does not need to be a direct child of the AppBar, it can be at any level in your component tree.
|
|
133
|
+
|
|
134
|
+
## Example
|
|
135
|
+
|
|
136
|
+
```solara
|
|
137
|
+
import solara
|
|
138
|
+
|
|
139
|
+
@solara.component
|
|
140
|
+
def Page():
|
|
141
|
+
with solara.AppBarTitle():
|
|
142
|
+
solara.Text("Hi there")
|
|
143
|
+
solara.Button("Click me", outlined=True, classes=["mx-2"])
|
|
144
|
+
```
|
|
145
|
+
"""
|
|
146
|
+
level = 0
|
|
147
|
+
rc = reacton.core.get_render_context()
|
|
148
|
+
context = rc.context
|
|
149
|
+
while context and context.parent:
|
|
150
|
+
level += 1
|
|
151
|
+
context = context.parent
|
|
152
|
+
offset = 2**level
|
|
153
|
+
apptitle_portal.use_portal_add(children, offset)
|
|
154
|
+
|
|
155
|
+
return solara.Div(style="display; none")
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@solara.component
|
|
159
|
+
def Sidebar(children=[]):
|
|
160
|
+
"""Puts its children in the sidebar of the AppLayout (or any layout that supports it).
|
|
161
|
+
This component does not need to be a direct child of the AppLayout, it can be at any level in your component tree.
|
|
162
|
+
|
|
163
|
+
On the solara.dev website and in the Jupyter notebook, the sidebar is shown in a dialog instead (embedded mode)
|
|
164
|
+
|
|
165
|
+
## Example showing a sidebar (embedded mode)
|
|
166
|
+
```solara
|
|
167
|
+
import solara
|
|
168
|
+
|
|
169
|
+
@solara.component
|
|
170
|
+
def Page():
|
|
171
|
+
with solara.Column() as main:
|
|
172
|
+
with solara.Sidebar():
|
|
173
|
+
solara.Markdown("## I am in the sidebar")
|
|
174
|
+
solara.SliderInt(label="Ideal for placing controls")
|
|
175
|
+
solara.Info("I'm in the main content area, put your main content here")
|
|
176
|
+
return main
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
"""
|
|
181
|
+
# TODO: generalize this, this is also used in title
|
|
182
|
+
level = 0
|
|
183
|
+
rc = reacton.core.get_render_context()
|
|
184
|
+
context = rc.context
|
|
185
|
+
while context and context.parent:
|
|
186
|
+
level += 1
|
|
187
|
+
context = context.parent
|
|
188
|
+
offset = 2**level
|
|
189
|
+
sidebar_portal.use_portal_add(children, offset)
|
|
190
|
+
|
|
191
|
+
return solara.Div(style="display; none")
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
@solara.component
|
|
195
|
+
def AppLayout(
|
|
196
|
+
children=[],
|
|
197
|
+
sidebar_open=True,
|
|
198
|
+
title=None,
|
|
199
|
+
navigation=True,
|
|
200
|
+
toolbar_dark=True,
|
|
201
|
+
color: Optional[str] = "primary",
|
|
202
|
+
classes: List[str] = [],
|
|
203
|
+
style: Optional[Union[str, Dict[str, str]]] = None,
|
|
204
|
+
):
|
|
205
|
+
"""The default layout for Solara apps. It consists of an toolbar bar, a sidebar and a main content area.
|
|
206
|
+
|
|
207
|
+
* The title of the app is set using the [Title](/documentation/components/page/title) component.
|
|
208
|
+
* The sidebar content is set using the [Sidebar](/documentation/components/layout/sidebar) component.
|
|
209
|
+
* The content is set by the `Page` component provided by the user.
|
|
210
|
+
|
|
211
|
+
This component is usually not used directly, but rather through via the [Layout system](/documentation/advanced/howto/layout).
|
|
212
|
+
|
|
213
|
+
The sidebar is only added when the AppLayout has more than one child.
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
with AppLayout(title="My App"):
|
|
217
|
+
with v.Card():
|
|
218
|
+
... # sidebar content
|
|
219
|
+
with v.Card():
|
|
220
|
+
... # main content
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
# Arguments
|
|
224
|
+
|
|
225
|
+
* `children`: The children of the AppLayout. The first child is used as the sidebar content, the rest as the main content.
|
|
226
|
+
* `sidebar_open`: Whether the sidebar is open or not.
|
|
227
|
+
* `title`: The title of the app shown in the app bar, can also be set using the [Title](/documentation/components/page/title) component.
|
|
228
|
+
* `toolbar_dark`: Whether the toolbar should be dark or not.
|
|
229
|
+
* `navigation`: Whether the navigation tabs based on routing should be shown.
|
|
230
|
+
* `color`: The color of the toolbar.
|
|
231
|
+
* `classes`: List of CSS classes to apply to the direct parent of the childred.
|
|
232
|
+
* `style`: CSS style to apply to the direct parent of the children. If style is None we use a default style of "height: 100%; overflow: auto;"
|
|
233
|
+
and add 12px of padding when the sidebar of titlebar is visible. This will make sure your app gets scrollbars when need.
|
|
234
|
+
"""
|
|
235
|
+
route, routes = solara.use_route()
|
|
236
|
+
paths = [solara.resolve_path(r, level=0) for r in routes]
|
|
237
|
+
location = solara.use_context(solara.routing._location_context)
|
|
238
|
+
embedded_mode = solara.use_context(should_use_embed)
|
|
239
|
+
fullscreen, set_fullscreen = solara.use_state(False)
|
|
240
|
+
# we cannot nest AppLayouts, so we can use the context to set the embedded mode
|
|
241
|
+
should_use_embed.provide(True)
|
|
242
|
+
index = routes.index(route) if route else None
|
|
243
|
+
|
|
244
|
+
sidebar_open, set_sidebar_open = solara.use_state_or_update(sidebar_open)
|
|
245
|
+
# remove the appbar from the children
|
|
246
|
+
children_without_portal_sources = [c for c in children if c.component != AppBar]
|
|
247
|
+
use_drawer = len(children_without_portal_sources) > 1
|
|
248
|
+
children_content = children
|
|
249
|
+
children_sidebar = []
|
|
250
|
+
if use_drawer:
|
|
251
|
+
child_sidebar = children_without_portal_sources.pop(0)
|
|
252
|
+
children_sidebar = [child_sidebar]
|
|
253
|
+
children_content = [c for c in children if c is not child_sidebar]
|
|
254
|
+
children_sidebar = children_sidebar + sidebar_portal.use_portal()
|
|
255
|
+
children_appbar = appbar_portal.use_portal()
|
|
256
|
+
if children_sidebar:
|
|
257
|
+
use_drawer = True
|
|
258
|
+
title = t.use_title_get() or title
|
|
259
|
+
children_appbartitle = apptitle_portal.use_portal()
|
|
260
|
+
v_slots = []
|
|
261
|
+
|
|
262
|
+
tabs_element = None
|
|
263
|
+
for child_appbar in children_appbar.copy():
|
|
264
|
+
if child_appbar.component == solara.lab.Tabs:
|
|
265
|
+
if tabs_element is not None:
|
|
266
|
+
raise ValueError("Only one Tabs component is allowed in the AppBar")
|
|
267
|
+
tabs_element = child_appbar
|
|
268
|
+
children_appbar.remove(tabs_element)
|
|
269
|
+
|
|
270
|
+
show_app_bar = (title and (len(routes) > 1 and navigation)) or bool(children_appbar) or bool(use_drawer) or bool(children_appbartitle) or bool(tabs_element)
|
|
271
|
+
|
|
272
|
+
if style is None:
|
|
273
|
+
style = {"height": "100%", "max-height": "100%", "overflow": "auto"}
|
|
274
|
+
# if style is None, we choose a default style based on whether we are seeing the appbar, etc
|
|
275
|
+
if show_app_bar or children_sidebar or len(children) != 1:
|
|
276
|
+
style["padding"] = "12px"
|
|
277
|
+
|
|
278
|
+
def set_path(index):
|
|
279
|
+
path = paths[index]
|
|
280
|
+
location.pathname = path
|
|
281
|
+
|
|
282
|
+
if (tabs_element is None) and routes and navigation and (len(routes) > 1):
|
|
283
|
+
with solara.lab.Tabs(value=index, on_value=set_path, align="center") as tabs_element:
|
|
284
|
+
for route in routes:
|
|
285
|
+
name = route.path if route.path != "/" else "Home"
|
|
286
|
+
solara.lab.Tab(name)
|
|
287
|
+
# with v.Tabs(v_model=index, on_v_model=set_path, centered=True) as tabs:
|
|
288
|
+
# for route in routes:
|
|
289
|
+
# name = route.path if route.path != "/" else "Home"
|
|
290
|
+
# v.Tab(children=[name])
|
|
291
|
+
if tabs_element is not None and navigation:
|
|
292
|
+
v_slots = [{"name": "extension", "children": tabs_element}]
|
|
293
|
+
if embedded_mode and not fullscreen:
|
|
294
|
+
# this version doesn't need to run fullscreen
|
|
295
|
+
# also ideal in jupyter notebooks
|
|
296
|
+
with v.Html(tag="div") as main:
|
|
297
|
+
if show_app_bar or use_drawer:
|
|
298
|
+
with v.AppBar(color=color, dark=toolbar_dark, v_slots=v_slots):
|
|
299
|
+
if use_drawer:
|
|
300
|
+
icon = AppIcon(sidebar_open, on_click=lambda: set_sidebar_open(not sidebar_open), v_on="x.on")
|
|
301
|
+
with v.Menu(
|
|
302
|
+
offset_y=True,
|
|
303
|
+
nudge_left="50px",
|
|
304
|
+
left=True,
|
|
305
|
+
v_slots=[{"name": "activator", "variable": "x", "children": [icon]}],
|
|
306
|
+
close_on_content_click=False,
|
|
307
|
+
):
|
|
308
|
+
pass
|
|
309
|
+
v.Sheet(children=children_sidebar, style_="padding: 12px; min-width: 400px")
|
|
310
|
+
if title or children_appbartitle:
|
|
311
|
+
v.ToolbarTitle(children=children_appbartitle or [title])
|
|
312
|
+
v.Spacer()
|
|
313
|
+
for i, child in enumerate(children_appbar):
|
|
314
|
+
# if the user already provided a key, don't override it
|
|
315
|
+
if child._key is None:
|
|
316
|
+
solara.display(child.key(f"app-layout-appbar-user-child-{i}"))
|
|
317
|
+
else:
|
|
318
|
+
solara.display(child)
|
|
319
|
+
solara.Button(icon_name="mdi-fullscreen", on_click=lambda: set_fullscreen(True), icon=True, dark=False)
|
|
320
|
+
with v.Row(no_gutters=False, class_="solara-content-main"):
|
|
321
|
+
v.Col(cols=12, children=children_content)
|
|
322
|
+
else:
|
|
323
|
+
# this limits the height of the app to the height of the screen
|
|
324
|
+
# and further down we use overflow: auto to add scrollbars to the main content
|
|
325
|
+
# the navigation drawer adds it own scrollbars
|
|
326
|
+
# NOTE: while developing this we added overflow: hidden, but this does not seem
|
|
327
|
+
# to be necessary anymore
|
|
328
|
+
with v.Html(tag="div", style_="height: 100vh") as main:
|
|
329
|
+
with solara.HBox():
|
|
330
|
+
if use_drawer:
|
|
331
|
+
with v.NavigationDrawer(
|
|
332
|
+
width="min-content",
|
|
333
|
+
v_model=sidebar_open,
|
|
334
|
+
on_v_model=set_sidebar_open,
|
|
335
|
+
style_="min-width: 400px; max-width: 600px",
|
|
336
|
+
clipped=True,
|
|
337
|
+
app=True,
|
|
338
|
+
# disable_resize_watcher=True,
|
|
339
|
+
disable_route_watcher=True,
|
|
340
|
+
mobile_break_point="960",
|
|
341
|
+
class_="solara-content-main",
|
|
342
|
+
):
|
|
343
|
+
if not show_app_bar:
|
|
344
|
+
AppIcon(sidebar_open, on_click=lambda: set_sidebar_open(not sidebar_open))
|
|
345
|
+
v.Html(tag="div", children=children_sidebar, style_="padding: 12px; height: 100%").meta(ref="sidebar-content")
|
|
346
|
+
if show_app_bar:
|
|
347
|
+
# if hide_on_scroll is True, and we have a little bit of scrolling, vuetify seems to act strangely
|
|
348
|
+
# when scrolling (on @mariobuikhuizen/vuetify v2.2.26-rc.0
|
|
349
|
+
with v.AppBar(color=color, dark=toolbar_dark, app=True, clipped_left=True, hide_on_scroll=False, v_slots=v_slots).key("app-layout-appbar"):
|
|
350
|
+
if use_drawer:
|
|
351
|
+
AppIcon(sidebar_open, on_click=lambda: set_sidebar_open(not sidebar_open))
|
|
352
|
+
if title or children_appbartitle:
|
|
353
|
+
v.ToolbarTitle(children=children_appbartitle or [title])
|
|
354
|
+
v.Spacer()
|
|
355
|
+
for i, child in enumerate(children_appbar):
|
|
356
|
+
# if the user already provided a key, don't override it
|
|
357
|
+
if child._key is None:
|
|
358
|
+
solara.display(child.key(f"app-layout-appbar-user-child-{i}"))
|
|
359
|
+
else:
|
|
360
|
+
solara.display(child)
|
|
361
|
+
if fullscreen:
|
|
362
|
+
solara.Button(icon_name="mdi-fullscreen-exit", on_click=lambda: set_fullscreen(False), icon=True, dark=False)
|
|
363
|
+
# in vue2 is was v-content, in vue3 it is v-main
|
|
364
|
+
MainComponent = v.Main if solara.util.ipyvuetify_major_version == 3 else v.Content # type: ignore
|
|
365
|
+
with MainComponent(class_="solara-content-main", style_="height: 100%;").key("app-layout-content"):
|
|
366
|
+
# make sure the scrollbar does no go under the appbar by adding overflow: auto
|
|
367
|
+
# to a child of content, because content has padding-top: 64px (set by vuetify)
|
|
368
|
+
# the padding: 12px is needed for backward compatibility with the previously used
|
|
369
|
+
# v.Col which has this by default. If we do not use this, a solara.Column will
|
|
370
|
+
# use a margin: -12px which will make a horizontal scrollbar appear
|
|
371
|
+
solara.Div(style=style, classes=classes, children=children_content)
|
|
372
|
+
if fullscreen:
|
|
373
|
+
with v.Dialog(v_model=True, children=[], fullscreen=True, hide_overlay=True, persistent=True, no_click_animation=True) as dialog:
|
|
374
|
+
v.Sheet(class_="overflow-y-auto overflow-x-auto", children=[main])
|
|
375
|
+
pass
|
|
376
|
+
return dialog
|
|
377
|
+
return main
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
@solara.component
|
|
381
|
+
def _AppLayoutEmbed(children=[], sidebar_open=True, title=None):
|
|
382
|
+
"""Forces the embed more for a AppLayout. This is used by default in Jupyter."""
|
|
383
|
+
should_use_embed.provide(True)
|
|
384
|
+
|
|
385
|
+
if solara.checks.should_perform_jupyter_check():
|
|
386
|
+
children = [solara.Column(children=children + [solara.checks.JupyterCheck()])]
|
|
387
|
+
|
|
388
|
+
def once():
|
|
389
|
+
import solara.server.telemetry
|
|
390
|
+
|
|
391
|
+
solara.server.telemetry.jupyter_start()
|
|
392
|
+
|
|
393
|
+
solara.use_effect(once, [])
|
|
394
|
+
return AppLayout(children=children, sidebar_open=sidebar_open, title=title)
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
reacton.core.jupyter_decorator_components.append(_AppLayoutEmbed)
|