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,125 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<v-subheader class="pl-0 query-input-label">{{ label }}</v-subheader>
|
|
4
|
+
<div ref="cm" class="solara-sql-code" :style="`height: ${height};`"></div>
|
|
5
|
+
<div>Use <kbd>Ctrl</kbd>+<kbd>Space</kbd> for auto-complete</div>
|
|
6
|
+
</div>
|
|
7
|
+
</template>
|
|
8
|
+
<script>
|
|
9
|
+
module.exports = {
|
|
10
|
+
async mounted() {
|
|
11
|
+
const cmVersion = '5.65.3';
|
|
12
|
+
|
|
13
|
+
if (!document.getElementById('codemirror-hint.css')) {
|
|
14
|
+
const link = document.createElement('link');
|
|
15
|
+
link.href = `${this.getCdn()}/codemirror@${cmVersion}/addon/hint/show-hint.css`;
|
|
16
|
+
link.type = "text/css";
|
|
17
|
+
link.rel = "stylesheet";
|
|
18
|
+
link.id="codemirror-hint.css";
|
|
19
|
+
document.head.appendChild(link);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
await this.loadRequire();
|
|
23
|
+
|
|
24
|
+
requirejs.config({paths:{
|
|
25
|
+
codemirror: `${this.getCdn()}/codemirror@${cmVersion}`
|
|
26
|
+
}});
|
|
27
|
+
|
|
28
|
+
requirejs(["codemirror/lib/codemirror", "codemirror/mode/sql/sql", "codemirror/addon/hint/show-hint", "codemirror/addon/hint/sql-hint"],
|
|
29
|
+
(cm) => {
|
|
30
|
+
this.myCodeMirror = cm(this.$refs.cm, {
|
|
31
|
+
value: this.query || '',
|
|
32
|
+
mode: "text/x-sql",
|
|
33
|
+
extraKeys: {"Ctrl-Space": "autocomplete"},
|
|
34
|
+
hint: cm.hint.sql,
|
|
35
|
+
hintOptions: {
|
|
36
|
+
tables: this.tables
|
|
37
|
+
},
|
|
38
|
+
lineNumbers: true,
|
|
39
|
+
gutter: true,
|
|
40
|
+
});
|
|
41
|
+
this.myCodeMirror.on('change', (cm, changeObj) => this.query=cm.getValue())
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
watch: {
|
|
45
|
+
query(value) {
|
|
46
|
+
if (this.myCodeMirror.getValue() !== value) {
|
|
47
|
+
this.myCodeMirror.setValue(value)
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
tables(value) {
|
|
51
|
+
if (this.myCodeMirror) {
|
|
52
|
+
this.myCodeMirror.options.hintOptions.tables = value;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
methods: {
|
|
57
|
+
import(deps) {
|
|
58
|
+
return this.loadRequire().then(
|
|
59
|
+
() => {
|
|
60
|
+
if(window.jupyterVue) {
|
|
61
|
+
// in jupyterlab, we take Vue from ipyvue/jupyterVue
|
|
62
|
+
define("vue", [], () => window.jupyterVue.Vue);
|
|
63
|
+
} else {
|
|
64
|
+
define("vue", ['jupyter-vue'], jupyterVue => jupyterVue.Vue);
|
|
65
|
+
}
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
requirejs(deps, (...modules) => resolve(modules));
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
},
|
|
72
|
+
loadRequire() {
|
|
73
|
+
/* Needed in lab */
|
|
74
|
+
if (window.requirejs) {
|
|
75
|
+
console.log('require found');
|
|
76
|
+
return Promise.resolve()
|
|
77
|
+
}
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
const script = document.createElement('script');
|
|
80
|
+
script.src = `${this.getCdn()}/requirejs@2.3.6/require.js`;
|
|
81
|
+
script.onload = resolve;
|
|
82
|
+
script.onerror = reject;
|
|
83
|
+
document.head.appendChild(script);
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
getJupyterBaseUrl() {
|
|
87
|
+
// if base url is set, we use ./ for relative paths compared to the base url
|
|
88
|
+
if (document.getElementsByTagName("base").length) {
|
|
89
|
+
return document.baseURI;
|
|
90
|
+
}
|
|
91
|
+
const labConfigData = document.getElementById('jupyter-config-data');
|
|
92
|
+
if(labConfigData) {
|
|
93
|
+
/* lab and Voila */
|
|
94
|
+
return JSON.parse(labConfigData.textContent).baseUrl;
|
|
95
|
+
}
|
|
96
|
+
let base = document.body.dataset.baseUrl || document.baseURI;
|
|
97
|
+
if(!base.endsWith('/')) {
|
|
98
|
+
base += '/';
|
|
99
|
+
}
|
|
100
|
+
return base
|
|
101
|
+
},
|
|
102
|
+
getCdn() {
|
|
103
|
+
return this.cdn || (window.solara ? window.solara.cdn : `${this.getJupyterBaseUrl()}_solara/cdn`);
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
</script>
|
|
108
|
+
<style id="solara-sql-code">
|
|
109
|
+
.solara-sql-code {
|
|
110
|
+
border: 1px solid gray;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
ul.CodeMirror-hints.default {
|
|
114
|
+
z-index: 10000;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.solara-sql-code .CodeMirror.cm-s-default {
|
|
118
|
+
height: 100%
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.v-subheader.query-input-label {
|
|
122
|
+
font-size: 12px;
|
|
123
|
+
height: unset;
|
|
124
|
+
}
|
|
125
|
+
</style>
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import hashlib
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Optional, Union, cast
|
|
6
|
+
|
|
7
|
+
import ipyvuetify as v
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
import watchfiles
|
|
11
|
+
except ModuleNotFoundError:
|
|
12
|
+
watchfiles = None # type: ignore
|
|
13
|
+
|
|
14
|
+
import solara
|
|
15
|
+
import solara.server.settings
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger("solara.Style")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@solara.component
|
|
21
|
+
def Style(value: Union[str, Path] = ""):
|
|
22
|
+
"""Add a custom piece of CSS.
|
|
23
|
+
|
|
24
|
+
Note that this is considered an advanced feature, and should be used with caution.
|
|
25
|
+
|
|
26
|
+
## Example
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from pathlib import Path
|
|
30
|
+
import solara
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@solara.component
|
|
34
|
+
def Page():
|
|
35
|
+
solara.Style(Path("style.css"))
|
|
36
|
+
solara.Button("Click me", classes=["company-style-button"])
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Arguments
|
|
40
|
+
|
|
41
|
+
- `value`: The CSS string of CSS file to insert into the page. In development mode (the default)
|
|
42
|
+
when a Path argument is passed, the file will be watched for changes, and the CSS will be reloaded when
|
|
43
|
+
the file changes. In production mode, the CSS will be inserted once, and not reloaded.
|
|
44
|
+
"""
|
|
45
|
+
css_content_reloaded, set_css_content_reloaded = solara.use_state(cast(Optional[str], None))
|
|
46
|
+
|
|
47
|
+
def hot_reload():
|
|
48
|
+
in_production = solara.server.settings.main.mode == "production"
|
|
49
|
+
if not in_production and isinstance(value, Path):
|
|
50
|
+
|
|
51
|
+
async def watch():
|
|
52
|
+
try:
|
|
53
|
+
async for _ in watchfiles.awatch(value):
|
|
54
|
+
print(value, "changed, reloading css") # noqa
|
|
55
|
+
set_css_content_reloaded(cast(Path, value).read_text(encoding="utf-8"))
|
|
56
|
+
except RuntimeError:
|
|
57
|
+
pass # swallow the RuntimeError: Already borrowed errors from watchfiles
|
|
58
|
+
except Exception:
|
|
59
|
+
logger.exception("Error watching file")
|
|
60
|
+
|
|
61
|
+
if watchfiles:
|
|
62
|
+
future = asyncio.create_task(watch())
|
|
63
|
+
return future.cancel
|
|
64
|
+
else:
|
|
65
|
+
logger.warning("watchfiles not installed, cannot watch file")
|
|
66
|
+
|
|
67
|
+
solara.use_effect(hot_reload, [value])
|
|
68
|
+
|
|
69
|
+
uuid = solara.use_unique_key()
|
|
70
|
+
if css_content_reloaded is not None:
|
|
71
|
+
css_content = css_content_reloaded
|
|
72
|
+
else:
|
|
73
|
+
css_content = value.read_text(encoding="utf-8") if isinstance(value, Path) else value
|
|
74
|
+
# del value
|
|
75
|
+
hash = hashlib.sha256(css_content.encode("utf-8")).hexdigest()
|
|
76
|
+
# the key is unique for this component + value
|
|
77
|
+
# so that we create a new component if the value changes
|
|
78
|
+
# but we do not remove the css of a component with the same value
|
|
79
|
+
key = uuid + "-" + hash
|
|
80
|
+
# ipyvue does not remove the css itself, so we need to do it manually
|
|
81
|
+
script = (
|
|
82
|
+
"""
|
|
83
|
+
<script>
|
|
84
|
+
module.exports = {
|
|
85
|
+
destroyed() {
|
|
86
|
+
document.getElementById("ipyvue-%s").remove();
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
</script>
|
|
90
|
+
"""
|
|
91
|
+
% key
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
template = f"""
|
|
95
|
+
<template>
|
|
96
|
+
<span style="display: none">
|
|
97
|
+
</span>
|
|
98
|
+
</template>
|
|
99
|
+
{script}
|
|
100
|
+
<style id="{key}">
|
|
101
|
+
{css_content}
|
|
102
|
+
</style>
|
|
103
|
+
"""
|
|
104
|
+
# using .key avoids reusing the template, which causes a flicker (due to ipyvue)
|
|
105
|
+
return v.VuetifyTemplate.element(template=template).key(key)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from typing import Callable, Dict, List, Optional, Union
|
|
2
|
+
|
|
3
|
+
import reacton.ipyvuetify as v
|
|
4
|
+
|
|
5
|
+
import solara
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@solara.value_component(bool)
|
|
9
|
+
def Switch(
|
|
10
|
+
*,
|
|
11
|
+
label: str = None,
|
|
12
|
+
value: Union[bool, solara.Reactive[bool]] = True,
|
|
13
|
+
on_value: Callable[[bool], None] = None,
|
|
14
|
+
disabled: bool = False,
|
|
15
|
+
color: str = None,
|
|
16
|
+
children: list = [],
|
|
17
|
+
classes: List[str] = [],
|
|
18
|
+
style: Optional[Union[str, Dict[str, str]]] = None,
|
|
19
|
+
):
|
|
20
|
+
"""A switch component provides users the ability to choose between two distinct values. But aesthetically different from a checkbox.
|
|
21
|
+
|
|
22
|
+
Basic examples
|
|
23
|
+
|
|
24
|
+
```solara
|
|
25
|
+
import solara
|
|
26
|
+
|
|
27
|
+
show_message = solara.reactive(True)
|
|
28
|
+
disable = solara.reactive(False)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@solara.component
|
|
32
|
+
def Page():
|
|
33
|
+
with solara.Column():
|
|
34
|
+
with solara.Row():
|
|
35
|
+
solara.Switch(label="Hide Message", value=show_message, disabled=disable.value)
|
|
36
|
+
solara.Switch(label="Disable Message Switch", value=disable)
|
|
37
|
+
|
|
38
|
+
if show_message.value:
|
|
39
|
+
solara.Markdown("## Use Switch to show/hide message")
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
## Arguments
|
|
45
|
+
|
|
46
|
+
* `label`: The label to display next to the switch.
|
|
47
|
+
* `value`: The current value of the switch (True or False).
|
|
48
|
+
* `on_value`: A callback that is called when the switch is toggled.
|
|
49
|
+
* `disabled`: If True, the switch is disabled and cannot be used.
|
|
50
|
+
* `color`: The color of the switch. Can be the name of a [theme](https://solara.dev/documentation/components/lab/theming) color variable (i.e. "success"), a color from the [Material color palette](https://v2.vuetifyjs.com/en/styles/colors/#material-colors) (i.e. "red darken-3"), or a CSS color (i.e. "#ff991f").
|
|
51
|
+
* `children`: A list of child elements to display on the switch.
|
|
52
|
+
* `classes`: Additional CSS classes to apply.
|
|
53
|
+
* `style`: CSS style to apply.
|
|
54
|
+
|
|
55
|
+
"""
|
|
56
|
+
reactive_value = solara.use_reactive(value, on_value)
|
|
57
|
+
del value, on_value
|
|
58
|
+
|
|
59
|
+
if label:
|
|
60
|
+
children = [label] + children
|
|
61
|
+
|
|
62
|
+
return v.Switch(
|
|
63
|
+
label=label,
|
|
64
|
+
v_model=reactive_value.value,
|
|
65
|
+
on_v_model=reactive_value.set,
|
|
66
|
+
disabled=disabled,
|
|
67
|
+
color=color,
|
|
68
|
+
class_=solara.util._combine_classes(classes),
|
|
69
|
+
style_=solara.util._flatten_style(style),
|
|
70
|
+
children=children,
|
|
71
|
+
)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import solara
|
|
2
|
+
from solara.alias import rv, rvue
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@solara.component
|
|
6
|
+
def LinkTab(path, label):
|
|
7
|
+
# both adding href to tab or adding Link makes vuetify buggy
|
|
8
|
+
with rv.Tab() as tab:
|
|
9
|
+
# with solara.Link(path):
|
|
10
|
+
solara.Text(label)
|
|
11
|
+
router = solara.use_router()
|
|
12
|
+
|
|
13
|
+
def go(*ignore):
|
|
14
|
+
router.push(path)
|
|
15
|
+
|
|
16
|
+
rvue.use_event(tab, "click.prevent.stop", go)
|
|
17
|
+
return tab
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@solara.component
|
|
21
|
+
def TabNavigation(children=[], vertical=False, **kwargs):
|
|
22
|
+
children = children or []
|
|
23
|
+
route_current, all_routes = solara.use_route()
|
|
24
|
+
|
|
25
|
+
tab_index = all_routes.index(route_current) if route_current is not None else 0
|
|
26
|
+
|
|
27
|
+
with rv.Tabs(v_model=tab_index, vertical=vertical, **kwargs) as main:
|
|
28
|
+
for i, route in enumerate(all_routes):
|
|
29
|
+
path = solara.resolve_path(route)
|
|
30
|
+
LinkTab(path, route.label or "No title")
|
|
31
|
+
if route_current is None:
|
|
32
|
+
return solara.Error("Page does not exist")
|
|
33
|
+
|
|
34
|
+
with rv.TabsItems(v_model=tab_index, children=children):
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
return main
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
from typing import Callable, Dict, Optional, Tuple, cast
|
|
2
|
+
|
|
3
|
+
import ipyvuetify as vy
|
|
4
|
+
import reacton.core
|
|
5
|
+
import traitlets
|
|
6
|
+
|
|
7
|
+
import solara
|
|
8
|
+
import solara.lab
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TitleWidget(vy.VuetifyTemplate):
|
|
12
|
+
template_file = (__file__, "title.vue")
|
|
13
|
+
title = traitlets.Unicode().tag(sync=True)
|
|
14
|
+
level = traitlets.Int().tag(sync=True)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
Titles = Dict[str, Tuple[int, str]]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _set_titles_default(updater: Callable[[Titles], Titles]):
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
titles_context = solara.create_context(_set_titles_default)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def use_title_get() -> Optional[str]:
|
|
28
|
+
titles, set_titles = solara.use_state(cast(Titles, {}))
|
|
29
|
+
titles_context.provide(set_titles) # type: ignore
|
|
30
|
+
if titles:
|
|
31
|
+
title = max([(order, title) for (key, (order, title)) in titles.items()], key=lambda x: x[0])[1]
|
|
32
|
+
else:
|
|
33
|
+
title = None
|
|
34
|
+
return title
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def use_title_set(title: str, offset: int):
|
|
38
|
+
key = solara.use_unique_key(prefix="title-")
|
|
39
|
+
set_titles = solara.use_context(titles_context)
|
|
40
|
+
|
|
41
|
+
def update():
|
|
42
|
+
set_titles(lambda titles: {**titles, key: (offset, title)})
|
|
43
|
+
|
|
44
|
+
solara.use_effect(update, [title])
|
|
45
|
+
|
|
46
|
+
def restore():
|
|
47
|
+
def cleanup():
|
|
48
|
+
def without(titles):
|
|
49
|
+
titles_restored = titles.copy()
|
|
50
|
+
titles_restored.pop(key, None)
|
|
51
|
+
return titles_restored
|
|
52
|
+
|
|
53
|
+
set_titles(without)
|
|
54
|
+
|
|
55
|
+
return cleanup
|
|
56
|
+
|
|
57
|
+
solara.use_effect(restore, [])
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@solara.component
|
|
61
|
+
def Title(title: str):
|
|
62
|
+
"""Set the title of a page.
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
import solara
|
|
66
|
+
|
|
67
|
+
@solara.component
|
|
68
|
+
def Page():
|
|
69
|
+
with solara.VBox() as main:
|
|
70
|
+
MyAwesomeComponent()
|
|
71
|
+
solara.Title("My page title")
|
|
72
|
+
return main
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
If multiple Title components are used, the 'deepest' child will take precedence.
|
|
76
|
+
|
|
77
|
+
## Arguments
|
|
78
|
+
|
|
79
|
+
* title: the title of the page
|
|
80
|
+
"""
|
|
81
|
+
level = 0
|
|
82
|
+
rc = reacton.core.get_render_context()
|
|
83
|
+
context = rc.context
|
|
84
|
+
while context and context.parent:
|
|
85
|
+
level += 1
|
|
86
|
+
context = context.parent
|
|
87
|
+
offset = 2**level
|
|
88
|
+
use_title_set(title, offset)
|
|
89
|
+
|
|
90
|
+
return TitleWidget.element(title=title, level=level)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<template><span style="display: none">{{ title }}</span></template>
|
|
2
|
+
|
|
3
|
+
<script>
|
|
4
|
+
module.exports = {
|
|
5
|
+
mounted() {
|
|
6
|
+
if (window._solaraTitles === undefined) {
|
|
7
|
+
window._solaraTitles = [];
|
|
8
|
+
}
|
|
9
|
+
window._solaraTitles.push(this);
|
|
10
|
+
this.updateTitle();
|
|
11
|
+
},
|
|
12
|
+
destroyed() {
|
|
13
|
+
window._solaraTitles.splice(window._solaraTitles.indexOf(this), 1);
|
|
14
|
+
if (window._solaraTitles.length) {
|
|
15
|
+
window._solaraTitles[0].updateTitle();
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
watch: {
|
|
19
|
+
title() {
|
|
20
|
+
this.updateTitle();
|
|
21
|
+
},
|
|
22
|
+
level() {
|
|
23
|
+
this.updateTitle();
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
methods: {
|
|
27
|
+
updateTitle() {
|
|
28
|
+
let deepestTitle = window._solaraTitles[0];
|
|
29
|
+
for (let i = 1; i < window._solaraTitles.length; i++) {
|
|
30
|
+
if (window._solaraTitles[i].level > deepestTitle.level) {
|
|
31
|
+
deepestTitle = window._solaraTitles[i];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
document.title = deepestTitle.title;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
</script>
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
from typing import Callable, Dict, List, Optional, TypeVar, Union, cast, overload
|
|
2
|
+
|
|
3
|
+
import ipyvuetify as v
|
|
4
|
+
import reacton
|
|
5
|
+
from typing_extensions import Literal
|
|
6
|
+
|
|
7
|
+
import solara
|
|
8
|
+
from solara.alias import rv
|
|
9
|
+
from solara.util import _combine_classes
|
|
10
|
+
|
|
11
|
+
T = TypeVar("T")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _get_button_value(button: reacton.core.Element):
|
|
15
|
+
if "value" in button.kwargs:
|
|
16
|
+
value = button.kwargs["value"]
|
|
17
|
+
else:
|
|
18
|
+
value = button.kwargs.get("label")
|
|
19
|
+
if value is None and button.args:
|
|
20
|
+
value = button.args[0]
|
|
21
|
+
return value
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@overload
|
|
25
|
+
@solara.value_component(None)
|
|
26
|
+
def ToggleButtonsSingle(
|
|
27
|
+
value: Union[T, solara.Reactive[T]],
|
|
28
|
+
values: List[T] = ...,
|
|
29
|
+
children: List[reacton.core.Element] = ...,
|
|
30
|
+
on_value: Optional[Callable[[T], None]] = ...,
|
|
31
|
+
dense: bool = ...,
|
|
32
|
+
mandatory: Literal[True] = ...,
|
|
33
|
+
classes: List[str] = ...,
|
|
34
|
+
style: Union[str, Dict[str, str], None] = ...,
|
|
35
|
+
) -> reacton.core.ValueElement[v.BtnToggle, T]: ...
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@overload
|
|
39
|
+
@solara.value_component(None)
|
|
40
|
+
def ToggleButtonsSingle(
|
|
41
|
+
value: Union[Optional[T], solara.Reactive[Optional[T]]] = None,
|
|
42
|
+
values: List[T] = ...,
|
|
43
|
+
children: List[reacton.core.Element] = ...,
|
|
44
|
+
on_value: Optional[Callable[[Optional[T]], None]] = ...,
|
|
45
|
+
dense: bool = ...,
|
|
46
|
+
mandatory: Literal[False] = ...,
|
|
47
|
+
classes: List[str] = ...,
|
|
48
|
+
style: Union[str, Dict[str, str], None] = ...,
|
|
49
|
+
) -> reacton.core.ValueElement[v.BtnToggle, T]: ...
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@solara.value_component(None)
|
|
53
|
+
def ToggleButtonsSingle(
|
|
54
|
+
value: Union[None, T, Optional[T], solara.Reactive[T], solara.Reactive[Optional[T]]] = None,
|
|
55
|
+
values: List[T] = [],
|
|
56
|
+
children: List[reacton.core.Element] = [],
|
|
57
|
+
on_value: Optional[Callable[[T], None]] = None,
|
|
58
|
+
dense: bool = False,
|
|
59
|
+
mandatory: bool = True,
|
|
60
|
+
classes: List[str] = [],
|
|
61
|
+
style: Union[str, Dict[str, str], None] = None,
|
|
62
|
+
) -> reacton.core.ValueElement[v.BtnToggle, T]:
|
|
63
|
+
"""ToggleButtons for selecting a single value.
|
|
64
|
+
|
|
65
|
+
```solara
|
|
66
|
+
import solara
|
|
67
|
+
|
|
68
|
+
foods = ["Kiwi", "Banana", "Apple"]
|
|
69
|
+
food = solara.reactive("Banana")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@solara.component
|
|
73
|
+
def Page():
|
|
74
|
+
with solara.Card("My favorite food"):
|
|
75
|
+
solara.ToggleButtonsSingle(value=food, values=foods)
|
|
76
|
+
solara.Markdown(f"**Selected**: {food.value}")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Using Buttons
|
|
80
|
+
|
|
81
|
+
Instead of passing the values as a list, we can also use the buttons as children.
|
|
82
|
+
This allows us to customize the buttons, for example to add an icon.
|
|
83
|
+
|
|
84
|
+
```solara
|
|
85
|
+
import solara
|
|
86
|
+
|
|
87
|
+
direction = solara.reactive("left")
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@solara.component
|
|
91
|
+
def Page():
|
|
92
|
+
with solara.Card("Pick a direction"):
|
|
93
|
+
# instead of using the values argument, we can use the buttons as children
|
|
94
|
+
# the label of the button will be used as value, if no value is given.
|
|
95
|
+
with solara.ToggleButtonsSingle(value=direction):
|
|
96
|
+
# note that the label and the value are different
|
|
97
|
+
solara.Button("Up", icon_name="mdi-arrow-up-bold", value="up", text=True)
|
|
98
|
+
solara.Button("Down", icon_name="mdi-arrow-down-bold", value="down", text=True)
|
|
99
|
+
solara.Button("Left", icon_name="mdi-arrow-left-bold", value="left", text=True)
|
|
100
|
+
solara.Button("Right", icon_name="mdi-arrow-right-bold", value="right", text=True)
|
|
101
|
+
solara.Markdown(f"**Selected**: {direction.value}")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Arguments
|
|
105
|
+
|
|
106
|
+
* `value`: The currently selected value.
|
|
107
|
+
* `values`: List of values to select from.
|
|
108
|
+
* `children`: List of buttons to use as values.
|
|
109
|
+
* `on_value`: Callback to call when the value changes.
|
|
110
|
+
* `dense`: Whether to use a dense (smaller) style.
|
|
111
|
+
* `mandatory`: Whether a choice is mandatory.
|
|
112
|
+
* `style`: CSS style to apply to the top level element.
|
|
113
|
+
* `classes`: List of CSS classes to be applied to the top level element.
|
|
114
|
+
"""
|
|
115
|
+
class_ = _combine_classes(classes)
|
|
116
|
+
style_flat = solara.util._flatten_style(style)
|
|
117
|
+
# TODO: make type safe
|
|
118
|
+
# typing is ignored below due to an issue with the typing; The combination of value being T and on_value being of type Callback[[Optional[T]], None] is
|
|
119
|
+
# not allowed to be passed to use_reactive. We also do not allow this by using our overloads, but this information seems lost at this point by
|
|
120
|
+
# the typechecker
|
|
121
|
+
reactive_value = solara.use_reactive(value, on_value) # type: ignore
|
|
122
|
+
children = [solara.Button(label=str(value)) for value in values] + children
|
|
123
|
+
values = values + [_get_button_value(button) for button in children] # type: ignore
|
|
124
|
+
# When mandatory = True, index should not be None, but we are letting the front-end take care of setting index to 0 because of a bug
|
|
125
|
+
# (see https://github.com/widgetti/solara/issues/282)
|
|
126
|
+
# TODO: set index to 0 on python side (after #282 is resolved)
|
|
127
|
+
index, set_index = solara.use_state_or_update(values.index(reactive_value.value) if reactive_value.value in values else None, key="index")
|
|
128
|
+
|
|
129
|
+
def on_index(index):
|
|
130
|
+
set_index(index)
|
|
131
|
+
if mandatory:
|
|
132
|
+
value = values[index]
|
|
133
|
+
else:
|
|
134
|
+
value = values[index] if index is not None else None
|
|
135
|
+
reactive_value.set(value)
|
|
136
|
+
|
|
137
|
+
return cast(
|
|
138
|
+
reacton.core.ValueElement[v.BtnToggle, T],
|
|
139
|
+
rv.BtnToggle(children=children, multiple=False, mandatory=mandatory, v_model=index, on_v_model=on_index, dense=dense, class_=class_, style_=style_flat),
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@solara.value_component(None)
|
|
144
|
+
def ToggleButtonsMultiple(
|
|
145
|
+
value: Union[List[T], solara.Reactive[List[T]]] = [],
|
|
146
|
+
values: List[T] = [],
|
|
147
|
+
children: List[reacton.core.Element] = [],
|
|
148
|
+
on_value: Union[Callable[[List[T]], None], None] = None,
|
|
149
|
+
dense: bool = False,
|
|
150
|
+
mandatory: bool = False,
|
|
151
|
+
classes: List[str] = [],
|
|
152
|
+
style: Union[str, Dict[str, str], None] = None,
|
|
153
|
+
) -> reacton.core.ValueElement[v.BtnToggle, List[T]]:
|
|
154
|
+
"""ToggleButtons for selecting multiple values.
|
|
155
|
+
|
|
156
|
+
### Basic example:
|
|
157
|
+
```solara
|
|
158
|
+
import solara
|
|
159
|
+
|
|
160
|
+
all_languages = "Python C++ Java JavaScript TypeScript BASIC".split()
|
|
161
|
+
languages = solara.reactive([all_languages[0]])
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@solara.component
|
|
165
|
+
def Page():
|
|
166
|
+
with solara.Card("My favorite programming languages"):
|
|
167
|
+
solara.ToggleButtonsMultiple(languages, all_languages)
|
|
168
|
+
solara.Markdown(f"**Selected**: {languages.value}")
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Arguments
|
|
172
|
+
|
|
173
|
+
* `value`: The currently selected values.
|
|
174
|
+
* `values`: List of values to select from.
|
|
175
|
+
* `children`: List of buttons to use as values.
|
|
176
|
+
* `on_value`: Callback to call when the value changes.
|
|
177
|
+
* `dense`: Whether to use a dense (smaller) style.
|
|
178
|
+
* `mandatory`: Whether selecting at least one element is mandatory.
|
|
179
|
+
* `style`: CSS style to apply to the top level element.
|
|
180
|
+
* `classes`: List of CSS classes to be applied to the top level element.
|
|
181
|
+
"""
|
|
182
|
+
class_ = _combine_classes(classes)
|
|
183
|
+
style_flat = solara.util._flatten_style(style)
|
|
184
|
+
# See comment regarding typing issue in ToggleButtonsSingle
|
|
185
|
+
reactive_value = solara.use_reactive(value, on_value) # type: ignore
|
|
186
|
+
children = [solara.Button(label=str(value)) for value in values] + children
|
|
187
|
+
allvalues = values + [_get_button_value(button) for button in children]
|
|
188
|
+
indices, set_indices = solara.use_state_or_update([allvalues.index(k) for k in reactive_value.value], key="index")
|
|
189
|
+
|
|
190
|
+
def on_indices(indices):
|
|
191
|
+
set_indices(indices)
|
|
192
|
+
value = [allvalues[k] for k in indices]
|
|
193
|
+
reactive_value.set(value)
|
|
194
|
+
|
|
195
|
+
return cast(
|
|
196
|
+
reacton.core.ValueElement[v.BtnToggle, List[T]],
|
|
197
|
+
rv.BtnToggle(
|
|
198
|
+
children=children, multiple=True, mandatory=mandatory, v_model=indices, on_v_model=on_indices, dense=dense, class_=class_, style_=style_flat
|
|
199
|
+
),
|
|
200
|
+
)
|