solara-ui 1.31.0__py2.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 +734 -0
- solara/alias.py +6 -0
- solara/autorouting.py +546 -0
- solara/cache.py +303 -0
- solara/checks.html +71 -0
- solara/checks.py +224 -0
- solara/comm.py +28 -0
- solara/components/__init__.py +59 -0
- solara/components/alert.py +155 -0
- solara/components/applayout.py +393 -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 +110 -0
- solara/components/cross_filter.py +335 -0
- solara/components/dataframe.py +546 -0
- solara/components/datatable.py +221 -0
- solara/components/datatable.vue +175 -0
- solara/components/details.py +21 -0
- solara/components/download.vue +35 -0
- solara/components/echarts.py +75 -0
- solara/components/echarts.vue +128 -0
- solara/components/figure_altair.py +39 -0
- solara/components/file_browser.py +182 -0
- solara/components/file_download.py +199 -0
- solara/components/file_drop.py +139 -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 +436 -0
- solara/components/link.py +55 -0
- solara/components/markdown.py +378 -0
- solara/components/markdown_editor.py +25 -0
- solara/components/markdown_editor.vue +362 -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 +30 -0
- solara/components/sql_code.py +33 -0
- solara/components/sql_code.vue +128 -0
- solara/components/style.py +105 -0
- solara/components/switch.py +68 -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/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 +129 -0
- solara/hooks/use_thread.py +129 -0
- solara/kitchensink.py +8 -0
- solara/lab/__init__.py +34 -0
- solara/lab/components/__init__.py +6 -0
- solara/lab/components/chat.py +203 -0
- solara/lab/components/confirmation_dialog.py +163 -0
- solara/lab/components/cross_filter.py +7 -0
- solara/lab/components/input_date.py +298 -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 +12 -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 +115 -0
- solara/lab/utils/headers.py +5 -0
- solara/layout.py +44 -0
- solara/lifecycle.py +46 -0
- solara/minisettings.py +133 -0
- solara/py.typed +0 -0
- solara/reactive.py +93 -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 +491 -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 +1665 -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 +77 -0
- solara/server/esm.py +69 -0
- solara/server/fastapi.py +5 -0
- solara/server/flask.py +286 -0
- solara/server/jupyter/__init__.py +2 -0
- solara/server/jupyter/cdn_handler.py +28 -0
- solara/server/jupyter/server_extension.py +29 -0
- solara/server/jupytertools.py +46 -0
- solara/server/kernel.py +338 -0
- solara/server/kernel_context.py +357 -0
- solara/server/patch.py +552 -0
- solara/server/reload.py +242 -0
- solara/server/server.py +456 -0
- solara/server/settings.py +215 -0
- solara/server/shell.py +251 -0
- solara/server/starlette.py +601 -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 +260 -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 +446 -0
- solara/server/threaded.py +75 -0
- solara/server/utils.py +30 -0
- solara/server/websocket.py +45 -0
- solara/settings.py +56 -0
- solara/tasks.py +837 -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 +697 -0
- solara/toestand.py +772 -0
- solara/util.py +308 -0
- solara/website/__init__.py +0 -0
- solara/website/assets/custom.css +468 -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.vue +24 -0
- solara/website/components/algolia_api.vue +187 -0
- solara/website/components/docs.py +118 -0
- solara/website/components/header.py +72 -0
- solara/website/components/hero.py +15 -0
- solara/website/components/mailchimp.py +12 -0
- solara/website/components/mailchimp.vue +47 -0
- solara/website/components/markdown.py +30 -0
- solara/website/components/notebook.py +171 -0
- solara/website/pages/__init__.py +575 -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/changelog/__init__.py +8 -0
- solara/website/pages/changelog/changelog.md +204 -0
- solara/website/pages/contact/__init__.py +8 -0
- solara/website/pages/contact/contact.md +17 -0
- solara/website/pages/doc_use_download.py +85 -0
- solara/website/pages/documentation/__init__.py +184 -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 +162 -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 +49 -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 +36 -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 +7 -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 +240 -0
- solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +97 -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 +1 -0
- solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +171 -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 +23 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_report.py +22 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_select.py +22 -0
- solara/website/pages/documentation/api/cross_filter/cross_filter_slider.py +22 -0
- solara/website/pages/documentation/api/hooks/__init__.py +9 -0
- solara/website/pages/documentation/api/hooks/use_cross_filter.py +25 -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 +33 -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 +33 -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 +69 -0
- solara/website/pages/documentation/api/hooks/use_thread.md +58 -0
- solara/website/pages/documentation/api/hooks/use_thread.py +44 -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 +31 -0
- solara/website/pages/documentation/api/routing/use_route.py +80 -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 +27 -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 +27 -0
- solara/website/pages/documentation/components/advanced/meta.py +20 -0
- solara/website/pages/documentation/components/advanced/style.py +45 -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 +32 -0
- solara/website/pages/documentation/components/input/file_drop.py +76 -0
- solara/website/pages/documentation/components/input/input.py +19 -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/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 +72 -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 +68 -0
- solara/website/pages/documentation/components/layout/griddraggable.py +62 -0
- solara/website/pages/documentation/components/layout/gridfixed.py +21 -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 +21 -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 +85 -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 +18 -0
- solara/website/pages/documentation/components/page/title.py +27 -0
- solara/website/pages/documentation/components/status/__init__.py +9 -0
- solara/website/pages/documentation/components/status/error.py +40 -0
- solara/website/pages/documentation/components/status/info.py +40 -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 +75 -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 +52 -0
- solara/website/pages/documentation/examples/ai/__init__.py +11 -0
- solara/website/pages/documentation/examples/ai/chatbot.py +95 -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 +38 -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 +64 -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 +64 -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 +69 -0
- solara/website/pages/documentation/examples/visualization/linked_views.py +84 -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 +76 -0
- solara/website/pages/documentation/getting_started/__init__.py +9 -0
- solara/website/pages/documentation/getting_started/content/00-quickstart.md +89 -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 +64 -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 +1000 -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 +223 -0
- solara/website/pages/documentation/getting_started/content/05-fundamentals/50-state-management.md +88 -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 +273 -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/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 +110 -0
- solara/widgets/vue/html.vue +4 -0
- solara/widgets/vue/navigator.vue +104 -0
- solara/widgets/vue/vegalite.vue +115 -0
- solara/widgets/widgets.py +66 -0
- solara_ui-1.31.0.data/data/etc/jupyter/jupyter_notebook_config.d/solara.json +7 -0
- solara_ui-1.31.0.data/data/etc/jupyter/jupyter_server_config.d/solara.json +7 -0
- solara_ui-1.31.0.dist-info/METADATA +158 -0
- solara_ui-1.31.0.dist-info/RECORD +439 -0
- solara_ui-1.31.0.dist-info/WHEEL +5 -0
- solara_ui-1.31.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""# Authorization
|
|
2
|
+
|
|
3
|
+
Authorization is a common requirement for web applications. This example shows how to implement a simple login form and
|
|
4
|
+
how to use `use_route` to implement authorization.
|
|
5
|
+
|
|
6
|
+
The `Layout` component checks if the current route requires authorization and if the user is logged in. If not, it
|
|
7
|
+
redirects to the login form.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import dataclasses
|
|
11
|
+
from typing import Optional, cast
|
|
12
|
+
|
|
13
|
+
import solara
|
|
14
|
+
import solara.lab
|
|
15
|
+
|
|
16
|
+
github_url = solara.util.github_url(__file__)
|
|
17
|
+
|
|
18
|
+
route_order = ["/", "users", "admin"]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def check_auth(route, children):
|
|
22
|
+
# This can be replaced by a custom function that checks if the user is
|
|
23
|
+
# logged in and has the required permissions.
|
|
24
|
+
|
|
25
|
+
# routes that are public or only for admin
|
|
26
|
+
# the rest only requires login
|
|
27
|
+
public_paths = ["/"]
|
|
28
|
+
admin_paths = ["admin"]
|
|
29
|
+
|
|
30
|
+
if route.path in public_paths:
|
|
31
|
+
children_auth = children
|
|
32
|
+
else:
|
|
33
|
+
if user.value is None:
|
|
34
|
+
children_auth = [LoginForm()]
|
|
35
|
+
else:
|
|
36
|
+
if route.path in admin_paths and not user.value.admin:
|
|
37
|
+
children_auth = [solara.Error("You are not an admin")]
|
|
38
|
+
else:
|
|
39
|
+
children_auth = children
|
|
40
|
+
return children_auth
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclasses.dataclass
|
|
44
|
+
class User:
|
|
45
|
+
username: str
|
|
46
|
+
admin: bool = False
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
user = solara.reactive(cast(Optional[User], None))
|
|
50
|
+
login_failed = solara.reactive(False)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def login(username: str, password: str):
|
|
54
|
+
# this function can be replace by a custom username/password check
|
|
55
|
+
if username == "test" and password == "test":
|
|
56
|
+
user.value = User(username, admin=False)
|
|
57
|
+
login_failed.value = False
|
|
58
|
+
elif username == "admin" and password == "admin":
|
|
59
|
+
user.value = User(username, admin=True)
|
|
60
|
+
login_failed.value = False
|
|
61
|
+
else:
|
|
62
|
+
login_failed.value = True
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@solara.component
|
|
66
|
+
def Page():
|
|
67
|
+
solara.Markdown("This page is visible for everyone")
|
|
68
|
+
|
|
69
|
+
solara.Markdown(__doc__)
|
|
70
|
+
solara.Button(label="View source", icon_name="mdi-github-circle", attributes={"href": github_url, "target": "_blank"}, text=True, outlined=True)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@solara.component
|
|
74
|
+
def LoginForm():
|
|
75
|
+
username = solara.use_reactive("")
|
|
76
|
+
password = solara.use_reactive("")
|
|
77
|
+
with solara.Card("Login"):
|
|
78
|
+
solara.Markdown(
|
|
79
|
+
"""
|
|
80
|
+
This is an example login form.
|
|
81
|
+
|
|
82
|
+
* use admin/admin to login as admin.
|
|
83
|
+
* use test/test to login as a normal user.
|
|
84
|
+
"""
|
|
85
|
+
)
|
|
86
|
+
solara.InputText(label="Username", value=username)
|
|
87
|
+
solara.InputText(label="Password", password=True, value=password)
|
|
88
|
+
solara.Button(label="Login", on_click=lambda: login(username.value, password.value))
|
|
89
|
+
if login_failed.value:
|
|
90
|
+
solara.Error("Wrong username or password")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@solara.component
|
|
94
|
+
def Layout(children=[]):
|
|
95
|
+
route, routes = solara.use_route(peek=True)
|
|
96
|
+
if route is None:
|
|
97
|
+
return solara.Error("Route not found")
|
|
98
|
+
|
|
99
|
+
children = check_auth(route, children)
|
|
100
|
+
|
|
101
|
+
with solara.AppLayout(children=children, navigation=True):
|
|
102
|
+
with solara.AppBar():
|
|
103
|
+
with solara.lab.Tabs(align="center"):
|
|
104
|
+
for route in routes:
|
|
105
|
+
name = route.path if route.path != "/" else "Home"
|
|
106
|
+
is_admin = user.value and user.value.admin
|
|
107
|
+
# we could skip the admin tab if the user is not an admin
|
|
108
|
+
# if route.path == "admin" and not is_admin:
|
|
109
|
+
# continue
|
|
110
|
+
# in this case we disable the tab
|
|
111
|
+
disabled = route.path == "admin" and not is_admin
|
|
112
|
+
solara.lab.Tab(name, path_or_route=route, disabled=disabled)
|
|
113
|
+
if user.value:
|
|
114
|
+
solara.Text(f"Logged in as {user.value.username} as {'admin' if user.value.admin else 'user'}")
|
|
115
|
+
with solara.Tooltip("Logout"):
|
|
116
|
+
solara.Button(icon_name="mdi-logout", icon=True, on_click=lambda: user.set(None))
|
|
117
|
+
else:
|
|
118
|
+
with solara.AppBar():
|
|
119
|
+
solara.Text("Not logged in")
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import solara
|
|
2
|
+
|
|
3
|
+
from . import user
|
|
4
|
+
|
|
5
|
+
github_url = solara.util.github_url(__file__)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@solara.component
|
|
9
|
+
def Page():
|
|
10
|
+
assert user.value is not None
|
|
11
|
+
solara.Markdown(f"Hi {user.value.username}, you are an admin")
|
|
12
|
+
solara.Button(label="View source", icon_name="mdi-github-circle", attributes={"href": github_url, "target": "_blank"}, text=True, outlined=True)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import solara
|
|
2
|
+
|
|
3
|
+
from . import user
|
|
4
|
+
|
|
5
|
+
github_url = solara.util.github_url(__file__)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@solara.component
|
|
9
|
+
def Page():
|
|
10
|
+
assert user.value is not None
|
|
11
|
+
solara.Markdown(f"Hi {user.value.username}!")
|
|
12
|
+
solara.Button(label="View source", icon_name="mdi-github-circle", attributes={"href": github_url, "target": "_blank"}, text=True, outlined=True)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import folium
|
|
4
|
+
import folium.plugins
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
import solara
|
|
9
|
+
|
|
10
|
+
districts = solara.reactive(
|
|
11
|
+
["Bayview", "Northern"],
|
|
12
|
+
)
|
|
13
|
+
categories = solara.reactive(["Vandalism", "Assault", "Robbery"])
|
|
14
|
+
limit = solara.reactive(100)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
ROOT = Path(solara.__file__).parent / "website" / "pages" / "documentation" / "getting_started" / "content" / "04-tutorials"
|
|
18
|
+
path = ROOT / Path("SF_crime_sample.csv.gz")
|
|
19
|
+
url = "https://raw.githubusercontent.com/widgetti/solara/master/solara/website/pages/docs/content/04-tutorial/SF_crime_sample.csv"
|
|
20
|
+
|
|
21
|
+
if path.exists():
|
|
22
|
+
df_crime = pd.read_csv(path)
|
|
23
|
+
else:
|
|
24
|
+
df_crime = pd.read_csv(url)
|
|
25
|
+
|
|
26
|
+
df_crime
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
df_crime["Category"] = df_crime["Category"].str.title()
|
|
30
|
+
df_crime["PdDistrict"] = df_crime["PdDistrict"].str.title()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def crime_filter(df, district_values, category_values):
|
|
34
|
+
df_dist = df.loc[df["PdDistrict"].isin(district_values)]
|
|
35
|
+
df_category = df_dist.loc[df_dist["Category"].isin(category_values)]
|
|
36
|
+
return df_category
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def crime_charts(df):
|
|
40
|
+
cat_unique = df["Category"].value_counts()
|
|
41
|
+
cat_unique = cat_unique.reset_index()
|
|
42
|
+
|
|
43
|
+
dist_unique = df["PdDistrict"].value_counts()
|
|
44
|
+
dist_unique = dist_unique.reset_index()
|
|
45
|
+
|
|
46
|
+
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 10))
|
|
47
|
+
|
|
48
|
+
ax1.bar(cat_unique["Category"], cat_unique["count"])
|
|
49
|
+
ax1.set_title("Amount of Criminal Case Based on Category")
|
|
50
|
+
ax2.bar(dist_unique["PdDistrict"], dist_unique["count"])
|
|
51
|
+
ax2.set_title("Amount of Criminal Case in Selected District")
|
|
52
|
+
|
|
53
|
+
# this does not work on solara yet: https://github.com/widgetti/solara/issues/399
|
|
54
|
+
# display(fig)
|
|
55
|
+
# plt.close(fig)
|
|
56
|
+
solara.FigureMatplotlib(fig)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def crime_map(df):
|
|
60
|
+
latitude = 37.77
|
|
61
|
+
longitude = -122.42
|
|
62
|
+
|
|
63
|
+
sanfran_map = folium.Map(height=400, location=[latitude, longitude], zoom_start=12)
|
|
64
|
+
|
|
65
|
+
incidents = folium.plugins.MarkerCluster().add_to(sanfran_map)
|
|
66
|
+
|
|
67
|
+
# loop through the dataframe and add each data point to the mark cluster
|
|
68
|
+
for (
|
|
69
|
+
lat,
|
|
70
|
+
lng,
|
|
71
|
+
label,
|
|
72
|
+
) in zip(df.Y, df.X, df.Category):
|
|
73
|
+
folium.Marker(
|
|
74
|
+
location=[lat, lng],
|
|
75
|
+
icon=None,
|
|
76
|
+
popup=label,
|
|
77
|
+
).add_to(incidents)
|
|
78
|
+
|
|
79
|
+
# show map
|
|
80
|
+
solara.display(sanfran_map)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@solara.component
|
|
84
|
+
def View():
|
|
85
|
+
dff = crime_filter(df_crime, districts.value, categories.value)
|
|
86
|
+
row_count = len(dff)
|
|
87
|
+
if row_count > limit.value:
|
|
88
|
+
solara.Warning(f"Only showing the first {limit.value} of {row_count:,} crimes on map")
|
|
89
|
+
with solara.Column(style={"max-height": "400px"}):
|
|
90
|
+
crime_map(dff.iloc[: limit.value])
|
|
91
|
+
if row_count > 0:
|
|
92
|
+
crime_charts(dff)
|
|
93
|
+
else:
|
|
94
|
+
solara.Warning("You filtered out all the data, no charts shown")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@solara.component
|
|
98
|
+
def Controls():
|
|
99
|
+
solara.SelectMultiple("District", all_values=[str(k) for k in df_crime["PdDistrict"].unique().tolist()], values=districts) # type: ignore
|
|
100
|
+
solara.SelectMultiple("Category", all_values=[str(k) for k in df_crime["Category"].unique().tolist()], values=categories) # type: ignore
|
|
101
|
+
solara.Text("Maximum number of rows to show on map")
|
|
102
|
+
solara.SliderInt("", value=limit, min=1, max=1000)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@solara.component
|
|
106
|
+
def Page():
|
|
107
|
+
with solara.Sidebar():
|
|
108
|
+
Controls()
|
|
109
|
+
View()
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# only needed on the solara website itself
|
|
113
|
+
@solara.component
|
|
114
|
+
def Layout(children):
|
|
115
|
+
route, routes = solara.use_route()
|
|
116
|
+
return solara.AppLayout(children=children)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import solara
|
|
2
|
+
import solara.lab
|
|
3
|
+
|
|
4
|
+
github_url = solara.util.github_url(__file__)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@solara.component
|
|
8
|
+
def Page():
|
|
9
|
+
with solara.Column():
|
|
10
|
+
solara.Title("I'm in the browser tab and the toolbar bar")
|
|
11
|
+
with solara.Sidebar():
|
|
12
|
+
with solara.Card("I am in the sidebar"):
|
|
13
|
+
with solara.Column():
|
|
14
|
+
solara.SliderInt(label="Ideal for placing controls")
|
|
15
|
+
solara.Button(
|
|
16
|
+
label="View source", icon_name="mdi-github-circle", attributes={"href": github_url, "target": "_blank"}, text=True, outlined=True
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
solara.Info("I'm in the main content area, put your main content here")
|
|
20
|
+
with solara.Card("Use solara.Columns to create relatively sized columns"):
|
|
21
|
+
with solara.Columns([1, 2]):
|
|
22
|
+
solara.Success("I'm in the first column")
|
|
23
|
+
solara.Warning("I'm in the second column, I am twice as wide")
|
|
24
|
+
|
|
25
|
+
with solara.Card("Use solara.Column to create a full width column"):
|
|
26
|
+
with solara.Column():
|
|
27
|
+
solara.Success("I'm first in this full with column")
|
|
28
|
+
solara.Warning("I'm second in this full with column")
|
|
29
|
+
solara.Error("I'm third in this full with column")
|
|
30
|
+
|
|
31
|
+
with solara.Card("Use solara.ColumnsResponsive to response to screen size"):
|
|
32
|
+
with solara.ColumnsResponsive(6, large=4):
|
|
33
|
+
for i in range(6):
|
|
34
|
+
solara.Info("two per column on small screens, three per column on large screens")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@solara.component
|
|
38
|
+
def Layout(children):
|
|
39
|
+
route, routes = solara.use_route()
|
|
40
|
+
return solara.AppLayout(children=children)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import solara
|
|
2
|
+
|
|
3
|
+
github_url = solara.util.github_url(__file__)
|
|
4
|
+
# some app state that outlives a single page
|
|
5
|
+
app_state = solara.reactive(0)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@solara.component
|
|
9
|
+
def SharedComponent():
|
|
10
|
+
with solara.Card("Shown on each page", style={"max-width": "500px"}, margin=0, classes=["my-2"]):
|
|
11
|
+
solara.Markdown(
|
|
12
|
+
f"""
|
|
13
|
+
This component will be used on each page.
|
|
14
|
+
|
|
15
|
+
It uses the `app_state` [reactive variable](https://solara.dev/documentation/api/utilities/reactive)
|
|
16
|
+
so that the state outlives each page
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
app_state: {app_state.value}
|
|
20
|
+
"""
|
|
21
|
+
)
|
|
22
|
+
solara.Button(label="Increment app_state", icon_name="mdi-plus", on_click=lambda: app_state.set(app_state.value + 1), outlined=True)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@solara.component
|
|
26
|
+
def Page():
|
|
27
|
+
with solara.Sidebar():
|
|
28
|
+
solara.Markdown("This is the sidebar at the home page!")
|
|
29
|
+
with solara.Card("Home"):
|
|
30
|
+
solara.Markdown("This is the home page")
|
|
31
|
+
solara.Button(label="View source", icon_name="mdi-github-circle", attributes={"href": github_url, "target": "_blank"}, text=True, outlined=True)
|
|
32
|
+
|
|
33
|
+
SharedComponent()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@solara.component
|
|
37
|
+
def Layout(children):
|
|
38
|
+
return solara.AppLayout(children=children)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import solara
|
|
2
|
+
|
|
3
|
+
from . import SharedComponent
|
|
4
|
+
|
|
5
|
+
github_url = solara.util.github_url(__file__)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@solara.component
|
|
9
|
+
def Sub():
|
|
10
|
+
with solara.Card("Sub component", margin=0, classes=["my-2"]):
|
|
11
|
+
solara.Markdown("This sub component is the best")
|
|
12
|
+
with solara.Sidebar():
|
|
13
|
+
with solara.Card("Sidebar of sub component", margin=0, elevation=0):
|
|
14
|
+
solara.Markdown("*Markdown* **is** 👍")
|
|
15
|
+
SharedComponent()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@solara.component
|
|
19
|
+
def Page():
|
|
20
|
+
with solara.Sidebar():
|
|
21
|
+
with solara.Card("Sidebar of page 1", margin=0, elevation=0):
|
|
22
|
+
solara.Markdown("Hi there 👋!")
|
|
23
|
+
solara.Button(label="View source", icon_name="mdi-github-circle", attributes={"href": github_url, "target": "_blank"}, text=True, outlined=True)
|
|
24
|
+
with solara.Card("Page 1"):
|
|
25
|
+
Sub()
|
|
26
|
+
solara.Markdown("Page 1 is the best")
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import solara
|
|
2
|
+
|
|
3
|
+
from . import SharedComponent
|
|
4
|
+
|
|
5
|
+
github_url = solara.util.github_url(__file__)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@solara.component
|
|
9
|
+
def Page():
|
|
10
|
+
component_state = solara.use_reactive(0)
|
|
11
|
+
solara.Title("Page 2 set with title")
|
|
12
|
+
with solara.Card("Page 2"):
|
|
13
|
+
solara.Markdown("Page 2 is even better, even though it has no sidebar.")
|
|
14
|
+
solara.Button(label="View source", icon_name="mdi-github-circle", attributes={"href": github_url, "target": "_blank"}, text=True, outlined=True)
|
|
15
|
+
SharedComponent()
|
|
16
|
+
|
|
17
|
+
with solara.Card("Shown only on page2", style={"max-width": "500px"}, margin=0, classes=["my-2"]):
|
|
18
|
+
solara.Markdown(
|
|
19
|
+
f"""
|
|
20
|
+
The lifetime of `component_state` if bound to this page. If you navigate away from it,
|
|
21
|
+
the state will be reset.
|
|
22
|
+
|
|
23
|
+
It creates the `component_state` [using the use_reactive hook](https://solara.dev/api/use_reactive)
|
|
24
|
+
so that the state is bound to the component.
|
|
25
|
+
|
|
26
|
+
See also [about state management](https://solara.dev/documentation/getting_started/fundamentals/state-management) for more information.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
component_state: {component_state.value}
|
|
30
|
+
"""
|
|
31
|
+
)
|
|
32
|
+
solara.Button(
|
|
33
|
+
label="Increment component_state", icon_name="mdi-plus", on_click=lambda: component_state.set(component_state.value + 1), outlined=True
|
|
34
|
+
)
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import pathlib
|
|
2
|
+
import sys
|
|
3
|
+
from typing import Optional, cast
|
|
4
|
+
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
import solara
|
|
8
|
+
import solara.express as solara_px # similar to plotly express, but comes with cross filters
|
|
9
|
+
import solara.lab
|
|
10
|
+
from solara.components.columns import Columns
|
|
11
|
+
from solara.components.file_drop import FileDrop
|
|
12
|
+
|
|
13
|
+
github_url = solara.util.github_url(__file__)
|
|
14
|
+
if sys.platform != "emscripten":
|
|
15
|
+
pycafe_url = solara.util.pycafe_url(path=pathlib.Path(__file__), requirements=["solara", "pandas", "plotly"])
|
|
16
|
+
else:
|
|
17
|
+
pycafe_url = None
|
|
18
|
+
df_sample = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class State:
|
|
22
|
+
size_max = solara.reactive(40.0)
|
|
23
|
+
size = solara.reactive(cast(Optional[str], None))
|
|
24
|
+
color = solara.reactive(cast(Optional[str], None))
|
|
25
|
+
x = solara.reactive(cast(Optional[str], None))
|
|
26
|
+
y = solara.reactive(cast(Optional[str], None))
|
|
27
|
+
logx = solara.reactive(False)
|
|
28
|
+
logy = solara.reactive(False)
|
|
29
|
+
df = solara.reactive(cast(Optional[pd.DataFrame], None))
|
|
30
|
+
|
|
31
|
+
@staticmethod
|
|
32
|
+
def load_sample():
|
|
33
|
+
State.x.value = "gdpPercap"
|
|
34
|
+
State.y.value = "lifeExp"
|
|
35
|
+
State.size.value = "pop"
|
|
36
|
+
State.color.value = "continent"
|
|
37
|
+
State.logx.value = True
|
|
38
|
+
State.df.value = df_sample
|
|
39
|
+
|
|
40
|
+
@staticmethod
|
|
41
|
+
def load_from_file(file):
|
|
42
|
+
df = pd.read_csv(file["file_obj"])
|
|
43
|
+
State.x.value = str(df.columns[0])
|
|
44
|
+
State.y.value = str(df.columns[1])
|
|
45
|
+
State.size.value = str(df.columns[2])
|
|
46
|
+
State.color.value = str(df.columns[3])
|
|
47
|
+
State.df.value = df
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def reset():
|
|
51
|
+
State.df.value = None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@solara.component
|
|
55
|
+
def Page():
|
|
56
|
+
df = State.df.value
|
|
57
|
+
dark_effective = solara.lab.use_dark_effective()
|
|
58
|
+
|
|
59
|
+
# the .scatter will set this cross filter
|
|
60
|
+
filter, _set_filter = solara.use_cross_filter(id(df))
|
|
61
|
+
|
|
62
|
+
# only apply the filter if the filter or dataframe changes
|
|
63
|
+
def filter_df():
|
|
64
|
+
if filter is not None and df is not None:
|
|
65
|
+
return df.loc[filter]
|
|
66
|
+
|
|
67
|
+
dff = solara.use_memo(filter_df, dependencies=[df, filter])
|
|
68
|
+
|
|
69
|
+
with solara.AppBar():
|
|
70
|
+
solara.lab.ThemeToggle()
|
|
71
|
+
with solara.Sidebar():
|
|
72
|
+
with solara.Card("Controls", margin=0, elevation=0):
|
|
73
|
+
with solara.Column():
|
|
74
|
+
with solara.Row():
|
|
75
|
+
solara.Button("Sample dataset", color="primary", text=True, outlined=True, on_click=State.load_sample, disabled=df is not None)
|
|
76
|
+
solara.Button("Clear dataset", color="primary", text=True, outlined=True, on_click=State.reset)
|
|
77
|
+
if sys.platform != "emscripten":
|
|
78
|
+
FileDrop(on_file=State.load_from_file, on_total_progress=lambda *args: None, label="Drag file here")
|
|
79
|
+
else:
|
|
80
|
+
solara.Info("File upload not supported in this environment")
|
|
81
|
+
|
|
82
|
+
if df is not None:
|
|
83
|
+
solara.SliderFloat(label="Size", value=State.size_max, min=1, max=100)
|
|
84
|
+
solara.Checkbox(label="Log x", value=State.logx)
|
|
85
|
+
solara.Checkbox(label="Log y", value=State.logy)
|
|
86
|
+
columns = list(map(str, df.columns))
|
|
87
|
+
solara.Select("Column x", values=columns, value=State.x)
|
|
88
|
+
solara.Select("Column y", values=columns, value=State.y)
|
|
89
|
+
solara.Select("Size", values=columns, value=State.size)
|
|
90
|
+
solara.Select("Color", values=columns, value=State.color)
|
|
91
|
+
if filter is None:
|
|
92
|
+
solara.Info("If you select points in the scatter plot, you can download the points here.")
|
|
93
|
+
else:
|
|
94
|
+
|
|
95
|
+
def get_data():
|
|
96
|
+
return dff.to_csv(index=False)
|
|
97
|
+
|
|
98
|
+
solara.FileDownload(get_data, label=f"Download {len(dff):,} selected points", filename="selected.csv")
|
|
99
|
+
|
|
100
|
+
if df is not None:
|
|
101
|
+
with Columns(widths=[2, 4]):
|
|
102
|
+
if State.x.value and State.y.value:
|
|
103
|
+
solara_px.scatter(
|
|
104
|
+
df,
|
|
105
|
+
State.x.value,
|
|
106
|
+
State.y.value,
|
|
107
|
+
size=State.size.value,
|
|
108
|
+
color=State.color.value,
|
|
109
|
+
size_max=State.size_max.value,
|
|
110
|
+
log_x=State.logx.value,
|
|
111
|
+
log_y=State.logy.value,
|
|
112
|
+
template="plotly_dark" if dark_effective else "plotly_white",
|
|
113
|
+
)
|
|
114
|
+
else:
|
|
115
|
+
solara.Warning("Select x and y columns")
|
|
116
|
+
|
|
117
|
+
else:
|
|
118
|
+
solara.Info("No data loaded, click on the sample dataset button to load a sample dataset, or upload a file.")
|
|
119
|
+
|
|
120
|
+
with solara.Column(style={"max-width": "400px"}):
|
|
121
|
+
solara.Button(label="View source", icon_name="mdi-github-circle", attributes={"href": github_url, "target": "_blank"}, text=True, outlined=True)
|
|
122
|
+
if sys.platform != "emscripten":
|
|
123
|
+
solara.Button(
|
|
124
|
+
label="Edit this example live on py.cafe",
|
|
125
|
+
icon_name="mdi-coffee-to-go-outline",
|
|
126
|
+
attributes={"href": pycafe_url, "target": "_blank"},
|
|
127
|
+
text=True,
|
|
128
|
+
outlined=True,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@solara.component
|
|
133
|
+
def Layout(children):
|
|
134
|
+
route, routes = solara.use_route()
|
|
135
|
+
dark_effective = solara.lab.use_dark_effective()
|
|
136
|
+
return solara.AppLayout(children=children, toolbar_dark=dark_effective, color=None) # if dark_effective else "primary")
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import solara
|
|
2
|
+
|
|
3
|
+
github_url = solara.util.github_url(__file__)
|
|
4
|
+
|
|
5
|
+
# list of nice soft colors
|
|
6
|
+
colors = [
|
|
7
|
+
"#e6194b",
|
|
8
|
+
"#3cb44b",
|
|
9
|
+
"#ffe119",
|
|
10
|
+
"#4363d8",
|
|
11
|
+
"#f58231",
|
|
12
|
+
"#911eb4",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@solara.component
|
|
17
|
+
def Page1():
|
|
18
|
+
with solara.Sidebar():
|
|
19
|
+
solara.Button(label="View source", icon_name="mdi-github-circle", attributes={"href": github_url, "target": "_blank"}, text=True, outlined=True)
|
|
20
|
+
solara.Markdown("The sidebar will get scrollbars automatically, independently of the main content.")
|
|
21
|
+
for i in range(10):
|
|
22
|
+
with solara.Card(f"Card {i}"):
|
|
23
|
+
solara.Info(f"Text {i}", color=colors[i % len(colors)])
|
|
24
|
+
|
|
25
|
+
solara.Markdown("The main content will get scrollbars automatically, independently of the sidebar.")
|
|
26
|
+
for i in range(10):
|
|
27
|
+
with solara.Card(f"Card {i}"):
|
|
28
|
+
solara.Info(f"Text {i}", color=colors[i % len(colors)])
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@solara.component
|
|
32
|
+
def Page2():
|
|
33
|
+
# it is important we do not interrupt the height 100% chain
|
|
34
|
+
limit_content_height = solara.use_reactive(True)
|
|
35
|
+
# warning: if we add "margin": "10px" to the style, we will trigger
|
|
36
|
+
# scrollbars in the parent div, if you really need to add margins,
|
|
37
|
+
# you should correct for that in the height using "calc(100% - 20px)"
|
|
38
|
+
with solara.Column(style={"height": "100%"}):
|
|
39
|
+
with solara.Sidebar():
|
|
40
|
+
solara.Button(label="View source", icon_name="mdi-github-circle", attributes={"href": github_url, "target": "_blank"}, text=True, outlined=True)
|
|
41
|
+
solara.Markdown("Main content columns will scroll together, or independently if we limit height to 100%")
|
|
42
|
+
solara.Checkbox(label="Limit content height", value=limit_content_height)
|
|
43
|
+
|
|
44
|
+
# if we do not limit height to 100%, solara's AppLayout will add a scroll bar
|
|
45
|
+
# to the main content, which will be independent of the sidebar's scroll bar
|
|
46
|
+
# but both columns will scroll together
|
|
47
|
+
with solara.Columns([2, 4], style={"height": "100%"} if limit_content_height.value else {}):
|
|
48
|
+
with solara.Card("I have my own scroll bar"):
|
|
49
|
+
solara.Markdown("")
|
|
50
|
+
for i in range(10):
|
|
51
|
+
with solara.Card(f"Card {i}"):
|
|
52
|
+
solara.Info(f"Text {i}", color=colors[i % len(colors)])
|
|
53
|
+
with solara.Card("I also have my own scroll bar"):
|
|
54
|
+
solara.Markdown("")
|
|
55
|
+
for i in range(20):
|
|
56
|
+
with solara.Card(f"Card {i}"):
|
|
57
|
+
solara.Info(f"Text {i}", color=colors[i % len(colors)])
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
routes = [
|
|
61
|
+
solara.Route(path="/", component=Page1, label="Scrolling"),
|
|
62
|
+
solara.Route(path="custom", component=Page2, label="Custom scrolling"),
|
|
63
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import solara
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@solara.component
|
|
5
|
+
def Page():
|
|
6
|
+
x, set_x = solara.use_state(2)
|
|
7
|
+
x_squared = x**2
|
|
8
|
+
|
|
9
|
+
with solara.Sidebar():
|
|
10
|
+
solara.Markdown("## My First Solara app ☀️")
|
|
11
|
+
solara.SliderInt(label="x", value=x, on_value=set_x)
|
|
12
|
+
solara.Markdown(f"{x} squared = {x_squared}")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@solara.component
|
|
16
|
+
def Layout(children):
|
|
17
|
+
route, routes = solara.use_route()
|
|
18
|
+
return solara.AppLayout(children=children)
|