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.
Files changed (464) hide show
  1. prefix/etc/jupyter/jupyter_notebook_config.d/solara.json +7 -0
  2. prefix/etc/jupyter/jupyter_server_config.d/solara.json +7 -0
  3. solara/__init__.py +124 -0
  4. solara/__main__.py +765 -0
  5. solara/_stores.py +297 -0
  6. solara/alias.py +6 -0
  7. solara/autorouting.py +555 -0
  8. solara/cache.py +305 -0
  9. solara/checks.html +71 -0
  10. solara/checks.py +227 -0
  11. solara/comm.py +28 -0
  12. solara/components/__init__.py +77 -0
  13. solara/components/alert.py +155 -0
  14. solara/components/applayout.py +397 -0
  15. solara/components/button.py +85 -0
  16. solara/components/card.py +87 -0
  17. solara/components/checkbox.py +50 -0
  18. solara/components/code_highlight_css.py +11 -0
  19. solara/components/code_highlight_css.vue +63 -0
  20. solara/components/columns.py +159 -0
  21. solara/components/component_vue.py +134 -0
  22. solara/components/cross_filter.py +335 -0
  23. solara/components/dataframe.py +546 -0
  24. solara/components/datatable.py +214 -0
  25. solara/components/datatable.vue +175 -0
  26. solara/components/details.py +56 -0
  27. solara/components/download.vue +35 -0
  28. solara/components/echarts.py +86 -0
  29. solara/components/echarts.vue +139 -0
  30. solara/components/figure_altair.py +39 -0
  31. solara/components/file_browser.py +181 -0
  32. solara/components/file_download.py +199 -0
  33. solara/components/file_drop.py +159 -0
  34. solara/components/file_drop.vue +83 -0
  35. solara/components/file_list_widget.vue +78 -0
  36. solara/components/head.py +27 -0
  37. solara/components/head_tag.py +49 -0
  38. solara/components/head_tag.vue +60 -0
  39. solara/components/image.py +173 -0
  40. solara/components/input.py +456 -0
  41. solara/components/input_text_area.py +86 -0
  42. solara/components/link.py +55 -0
  43. solara/components/markdown.py +441 -0
  44. solara/components/markdown_editor.py +33 -0
  45. solara/components/markdown_editor.vue +359 -0
  46. solara/components/matplotlib.py +74 -0
  47. solara/components/meta.py +47 -0
  48. solara/components/misc.py +333 -0
  49. solara/components/pivot_table.py +258 -0
  50. solara/components/pivot_table.vue +158 -0
  51. solara/components/progress.py +47 -0
  52. solara/components/select.py +182 -0
  53. solara/components/select.vue +27 -0
  54. solara/components/slider.py +442 -0
  55. solara/components/slider_date.vue +56 -0
  56. solara/components/spinner-solara.vue +105 -0
  57. solara/components/spinner.py +45 -0
  58. solara/components/sql_code.py +41 -0
  59. solara/components/sql_code.vue +125 -0
  60. solara/components/style.py +105 -0
  61. solara/components/switch.py +71 -0
  62. solara/components/tab_navigation.py +37 -0
  63. solara/components/title.py +90 -0
  64. solara/components/title.vue +38 -0
  65. solara/components/togglebuttons.py +200 -0
  66. solara/components/tooltip.py +61 -0
  67. solara/core.py +42 -0
  68. solara/datatypes.py +143 -0
  69. solara/express.py +241 -0
  70. solara/hooks/__init__.py +4 -0
  71. solara/hooks/dataframe.py +99 -0
  72. solara/hooks/misc.py +263 -0
  73. solara/hooks/use_reactive.py +151 -0
  74. solara/hooks/use_thread.py +129 -0
  75. solara/kitchensink.py +8 -0
  76. solara/lab/__init__.py +34 -0
  77. solara/lab/components/__init__.py +7 -0
  78. solara/lab/components/chat.py +215 -0
  79. solara/lab/components/confirmation_dialog.py +163 -0
  80. solara/lab/components/cross_filter.py +7 -0
  81. solara/lab/components/input_date.py +339 -0
  82. solara/lab/components/input_time.py +133 -0
  83. solara/lab/components/menu.py +181 -0
  84. solara/lab/components/menu.vue +38 -0
  85. solara/lab/components/tabs.py +274 -0
  86. solara/lab/components/theming.py +98 -0
  87. solara/lab/components/theming.vue +72 -0
  88. solara/lab/hooks/__init__.py +0 -0
  89. solara/lab/hooks/dataframe.py +2 -0
  90. solara/lab/toestand.py +3 -0
  91. solara/lab/utils/__init__.py +2 -0
  92. solara/lab/utils/cookies.py +5 -0
  93. solara/lab/utils/dataframe.py +165 -0
  94. solara/lab/utils/headers.py +5 -0
  95. solara/layout.py +44 -0
  96. solara/lifecycle.py +46 -0
  97. solara/minisettings.py +141 -0
  98. solara/py.typed +0 -0
  99. solara/reactive.py +99 -0
  100. solara/routing.py +268 -0
  101. solara/scope/__init__.py +88 -0
  102. solara/scope/types.py +55 -0
  103. solara/server/__init__.py +0 -0
  104. solara/server/app.py +527 -0
  105. solara/server/assets/custom.css +1 -0
  106. solara/server/assets/custom.js +1 -0
  107. solara/server/assets/favicon.png +0 -0
  108. solara/server/assets/favicon.svg +5 -0
  109. solara/server/assets/style.css +1681 -0
  110. solara/server/assets/theme-dark.css +437 -0
  111. solara/server/assets/theme-light.css +420 -0
  112. solara/server/assets/theme.js +3 -0
  113. solara/server/cdn_helper.py +91 -0
  114. solara/server/esm.py +71 -0
  115. solara/server/fastapi.py +5 -0
  116. solara/server/flask.py +297 -0
  117. solara/server/jupyter/__init__.py +2 -0
  118. solara/server/jupyter/cdn_handler.py +28 -0
  119. solara/server/jupyter/server_extension.py +40 -0
  120. solara/server/jupyter/solara.py +91 -0
  121. solara/server/jupytertools.py +46 -0
  122. solara/server/kernel.py +388 -0
  123. solara/server/kernel_context.py +467 -0
  124. solara/server/patch.py +564 -0
  125. solara/server/pyinstaller/__init__.py +9 -0
  126. solara/server/pyinstaller/hook-ipyreact.py +5 -0
  127. solara/server/pyinstaller/hook-ipyvuetify.py +5 -0
  128. solara/server/pyinstaller/hook-solara.py +9 -0
  129. solara/server/qt.py +113 -0
  130. solara/server/reload.py +251 -0
  131. solara/server/server.py +484 -0
  132. solara/server/settings.py +249 -0
  133. solara/server/shell.py +269 -0
  134. solara/server/starlette.py +770 -0
  135. solara/server/static/ansi.js +270 -0
  136. solara/server/static/highlight-dark.css +82 -0
  137. solara/server/static/highlight.css +43 -0
  138. solara/server/static/main-vuetify.js +272 -0
  139. solara/server/static/main.js +163 -0
  140. solara/server/static/solara_bootstrap.py +129 -0
  141. solara/server/static/sun.svg +23 -0
  142. solara/server/static/webworker.js +42 -0
  143. solara/server/telemetry.py +212 -0
  144. solara/server/templates/index.html.j2 +1 -0
  145. solara/server/templates/loader-plain.css +11 -0
  146. solara/server/templates/loader-plain.html +20 -0
  147. solara/server/templates/loader-solara.css +111 -0
  148. solara/server/templates/loader-solara.html +40 -0
  149. solara/server/templates/plain.html +82 -0
  150. solara/server/templates/solara.html.j2 +486 -0
  151. solara/server/threaded.py +84 -0
  152. solara/server/utils.py +44 -0
  153. solara/server/websocket.py +45 -0
  154. solara/settings.py +86 -0
  155. solara/tasks.py +893 -0
  156. solara/template/button.py +16 -0
  157. solara/template/markdown.py +42 -0
  158. solara/template/portal/.flake8 +6 -0
  159. solara/template/portal/.pre-commit-config.yaml +28 -0
  160. solara/template/portal/LICENSE +21 -0
  161. solara/template/portal/Procfile +7 -0
  162. solara/template/portal/mypy.ini +3 -0
  163. solara/template/portal/pyproject.toml +26 -0
  164. solara/template/portal/solara_portal/__init__.py +4 -0
  165. solara/template/portal/solara_portal/components/__init__.py +2 -0
  166. solara/template/portal/solara_portal/components/article.py +28 -0
  167. solara/template/portal/solara_portal/components/data.py +28 -0
  168. solara/template/portal/solara_portal/components/header.py +6 -0
  169. solara/template/portal/solara_portal/components/layout.py +6 -0
  170. solara/template/portal/solara_portal/content/articles/equis-in-vidi.md +85 -0
  171. solara/template/portal/solara_portal/content/articles/substiterat-vati.md +70 -0
  172. solara/template/portal/solara_portal/data.py +60 -0
  173. solara/template/portal/solara_portal/pages/__init__.py +67 -0
  174. solara/template/portal/solara_portal/pages/article/__init__.py +26 -0
  175. solara/template/portal/solara_portal/pages/tabular.py +29 -0
  176. solara/template/portal/solara_portal/pages/viz/__init__.py +70 -0
  177. solara/template/portal/solara_portal/pages/viz/overview.py +14 -0
  178. solara/test/__init__.py +0 -0
  179. solara/test/pytest_plugin.py +783 -0
  180. solara/toestand.py +998 -0
  181. solara/util.py +348 -0
  182. solara/validate_hooks.py +258 -0
  183. solara/website/__init__.py +0 -0
  184. solara/website/assets/custom.css +444 -0
  185. solara/website/assets/images/logo-small.png +0 -0
  186. solara/website/assets/images/logo.svg +17 -0
  187. solara/website/assets/images/logo_white.svg +50 -0
  188. solara/website/assets/theme.js +8 -0
  189. solara/website/components/__init__.py +5 -0
  190. solara/website/components/algolia.py +6 -0
  191. solara/website/components/algolia.vue +24 -0
  192. solara/website/components/algolia_api.vue +202 -0
  193. solara/website/components/breadcrumbs.py +28 -0
  194. solara/website/components/contact.py +144 -0
  195. solara/website/components/docs.py +143 -0
  196. solara/website/components/header.py +75 -0
  197. solara/website/components/mailchimp.py +12 -0
  198. solara/website/components/mailchimp.vue +47 -0
  199. solara/website/components/markdown.py +99 -0
  200. solara/website/components/markdown_nav.vue +34 -0
  201. solara/website/components/notebook.py +171 -0
  202. solara/website/components/sidebar.py +105 -0
  203. solara/website/pages/__init__.py +370 -0
  204. solara/website/pages/about/__init__.py +9 -0
  205. solara/website/pages/about/about.md +3 -0
  206. solara/website/pages/apps/__init__.py +16 -0
  207. solara/website/pages/apps/authorization/__init__.py +119 -0
  208. solara/website/pages/apps/authorization/admin.py +12 -0
  209. solara/website/pages/apps/authorization/users.py +12 -0
  210. solara/website/pages/apps/jupyter-dashboard-1.py +116 -0
  211. solara/website/pages/apps/layout-demo.py +40 -0
  212. solara/website/pages/apps/multipage/__init__.py +38 -0
  213. solara/website/pages/apps/multipage/page1.py +26 -0
  214. solara/website/pages/apps/multipage/page2.py +34 -0
  215. solara/website/pages/apps/scatter.py +136 -0
  216. solara/website/pages/apps/scrolling.py +63 -0
  217. solara/website/pages/apps/tutorial-streamlit.py +18 -0
  218. solara/website/pages/careers/__init__.py +27 -0
  219. solara/website/pages/changelog/__init__.py +10 -0
  220. solara/website/pages/changelog/changelog.md +372 -0
  221. solara/website/pages/contact/__init__.py +34 -0
  222. solara/website/pages/doc_use_download.py +85 -0
  223. solara/website/pages/documentation/__init__.py +90 -0
  224. solara/website/pages/documentation/advanced/__init__.py +9 -0
  225. solara/website/pages/documentation/advanced/content/00-overview.md +1 -0
  226. solara/website/pages/documentation/advanced/content/10-howto/00-overview.md +6 -0
  227. solara/website/pages/documentation/advanced/content/10-howto/10-multipage.md +196 -0
  228. solara/website/pages/documentation/advanced/content/10-howto/20-layout.md +125 -0
  229. solara/website/pages/documentation/advanced/content/10-howto/30-testing.md +417 -0
  230. solara/website/pages/documentation/advanced/content/10-howto/31-debugging.md +69 -0
  231. solara/website/pages/documentation/advanced/content/10-howto/40-embed.md +50 -0
  232. solara/website/pages/documentation/advanced/content/10-howto/50-ipywidget_libraries.md +124 -0
  233. solara/website/pages/documentation/advanced/content/15-reference/00-overview.md +3 -0
  234. solara/website/pages/documentation/advanced/content/15-reference/40-static_files.md +31 -0
  235. solara/website/pages/documentation/advanced/content/15-reference/41-asset-files.md +72 -0
  236. solara/website/pages/documentation/advanced/content/15-reference/60-static-site-generation.md +59 -0
  237. solara/website/pages/documentation/advanced/content/15-reference/70-search.md +34 -0
  238. solara/website/pages/documentation/advanced/content/15-reference/80-reloading.md +34 -0
  239. solara/website/pages/documentation/advanced/content/15-reference/90-notebook-support.md +7 -0
  240. solara/website/pages/documentation/advanced/content/15-reference/95-caching.md +148 -0
  241. solara/website/pages/documentation/advanced/content/20-understanding/00-introduction.md +10 -0
  242. solara/website/pages/documentation/advanced/content/20-understanding/05-ipywidgets.md +35 -0
  243. solara/website/pages/documentation/advanced/content/20-understanding/06-ipyvuetify.md +42 -0
  244. solara/website/pages/documentation/advanced/content/20-understanding/10-reacton.md +28 -0
  245. solara/website/pages/documentation/advanced/content/20-understanding/12-reacton-basics.md +108 -0
  246. solara/website/pages/documentation/advanced/content/20-understanding/15-anatomy.md +23 -0
  247. solara/website/pages/documentation/advanced/content/20-understanding/17-rules-of-hooks.md +192 -0
  248. solara/website/pages/documentation/advanced/content/20-understanding/18-containers.md +166 -0
  249. solara/website/pages/documentation/advanced/content/20-understanding/20-solara.md +18 -0
  250. solara/website/pages/documentation/advanced/content/20-understanding/40-routing.md +256 -0
  251. solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +108 -0
  252. solara/website/pages/documentation/advanced/content/20-understanding/60-voila.md +12 -0
  253. solara/website/pages/documentation/advanced/content/30-enterprise/00-overview.md +7 -0
  254. solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +187 -0
  255. solara/website/pages/documentation/advanced/content/40-development/00-overview.md +0 -0
  256. solara/website/pages/documentation/advanced/content/40-development/01-contribute.md +45 -0
  257. solara/website/pages/documentation/advanced/content/40-development/10-setup.md +76 -0
  258. solara/website/pages/documentation/api/__init__.py +19 -0
  259. solara/website/pages/documentation/api/cross_filter/__init__.py +9 -0
  260. solara/website/pages/documentation/api/cross_filter/cross_filter_dataframe.py +22 -0
  261. solara/website/pages/documentation/api/cross_filter/cross_filter_report.py +20 -0
  262. solara/website/pages/documentation/api/cross_filter/cross_filter_select.py +20 -0
  263. solara/website/pages/documentation/api/cross_filter/cross_filter_slider.py +20 -0
  264. solara/website/pages/documentation/api/hooks/__init__.py +9 -0
  265. solara/website/pages/documentation/api/hooks/use_cross_filter.py +23 -0
  266. solara/website/pages/documentation/api/hooks/use_dark_effective.py +12 -0
  267. solara/website/pages/documentation/api/hooks/use_effect.md +43 -0
  268. solara/website/pages/documentation/api/hooks/use_effect.py +9 -0
  269. solara/website/pages/documentation/api/hooks/use_exception.py +31 -0
  270. solara/website/pages/documentation/api/hooks/use_memo.md +16 -0
  271. solara/website/pages/documentation/api/hooks/use_memo.py +9 -0
  272. solara/website/pages/documentation/api/hooks/use_previous.py +30 -0
  273. solara/website/pages/documentation/api/hooks/use_reactive.py +16 -0
  274. solara/website/pages/documentation/api/hooks/use_state.py +10 -0
  275. solara/website/pages/documentation/api/hooks/use_state_or_update.py +66 -0
  276. solara/website/pages/documentation/api/hooks/use_thread.md +64 -0
  277. solara/website/pages/documentation/api/hooks/use_thread.py +42 -0
  278. solara/website/pages/documentation/api/hooks/use_trait_observe.py +12 -0
  279. solara/website/pages/documentation/api/routing/__init__.py +9 -0
  280. solara/website/pages/documentation/api/routing/generate_routes.py +10 -0
  281. solara/website/pages/documentation/api/routing/generate_routes_directory.py +10 -0
  282. solara/website/pages/documentation/api/routing/resolve_path.py +35 -0
  283. solara/website/pages/documentation/api/routing/route.py +29 -0
  284. solara/website/pages/documentation/api/routing/use_route.py +76 -0
  285. solara/website/pages/documentation/api/routing/use_router.py +16 -0
  286. solara/website/pages/documentation/api/utilities/__init__.py +9 -0
  287. solara/website/pages/documentation/api/utilities/component_vue.py +10 -0
  288. solara/website/pages/documentation/api/utilities/computed.py +16 -0
  289. solara/website/pages/documentation/api/utilities/display.py +16 -0
  290. solara/website/pages/documentation/api/utilities/get_kernel_id.py +16 -0
  291. solara/website/pages/documentation/api/utilities/get_session_id.py +16 -0
  292. solara/website/pages/documentation/api/utilities/memoize.py +35 -0
  293. solara/website/pages/documentation/api/utilities/on_kernel_start.py +44 -0
  294. solara/website/pages/documentation/api/utilities/reactive.py +16 -0
  295. solara/website/pages/documentation/api/utilities/widget.py +104 -0
  296. solara/website/pages/documentation/components/__init__.py +12 -0
  297. solara/website/pages/documentation/components/advanced/__init__.py +9 -0
  298. solara/website/pages/documentation/components/advanced/link.py +25 -0
  299. solara/website/pages/documentation/components/advanced/meta.py +17 -0
  300. solara/website/pages/documentation/components/advanced/style.py +43 -0
  301. solara/website/pages/documentation/components/common.py +9 -0
  302. solara/website/pages/documentation/components/data/__init__.py +9 -0
  303. solara/website/pages/documentation/components/data/dataframe.py +44 -0
  304. solara/website/pages/documentation/components/data/pivot_table.py +81 -0
  305. solara/website/pages/documentation/components/enterprise/__init__.py +9 -0
  306. solara/website/pages/documentation/components/enterprise/avatar.py +24 -0
  307. solara/website/pages/documentation/components/enterprise/avatar_menu.py +25 -0
  308. solara/website/pages/documentation/components/input/__init__.py +9 -0
  309. solara/website/pages/documentation/components/input/button.py +23 -0
  310. solara/website/pages/documentation/components/input/checkbox.py +10 -0
  311. solara/website/pages/documentation/components/input/file_browser.py +30 -0
  312. solara/website/pages/documentation/components/input/file_drop.py +76 -0
  313. solara/website/pages/documentation/components/input/input.py +43 -0
  314. solara/website/pages/documentation/components/input/select.py +22 -0
  315. solara/website/pages/documentation/components/input/slider.py +29 -0
  316. solara/website/pages/documentation/components/input/switch.py +10 -0
  317. solara/website/pages/documentation/components/input/togglebuttons.py +21 -0
  318. solara/website/pages/documentation/components/lab/__init__.py +9 -0
  319. solara/website/pages/documentation/components/lab/chat.py +109 -0
  320. solara/website/pages/documentation/components/lab/confirmation_dialog.py +55 -0
  321. solara/website/pages/documentation/components/lab/cookies_headers.py +48 -0
  322. solara/website/pages/documentation/components/lab/input_date.py +20 -0
  323. solara/website/pages/documentation/components/lab/input_time.py +15 -0
  324. solara/website/pages/documentation/components/lab/menu.py +22 -0
  325. solara/website/pages/documentation/components/lab/tab.py +25 -0
  326. solara/website/pages/documentation/components/lab/tabs.py +45 -0
  327. solara/website/pages/documentation/components/lab/task.py +11 -0
  328. solara/website/pages/documentation/components/lab/theming.py +74 -0
  329. solara/website/pages/documentation/components/lab/use_task.py +11 -0
  330. solara/website/pages/documentation/components/layout/__init__.py +9 -0
  331. solara/website/pages/documentation/components/layout/app_bar.py +16 -0
  332. solara/website/pages/documentation/components/layout/app_bar_title.py +16 -0
  333. solara/website/pages/documentation/components/layout/app_layout.py +24 -0
  334. solara/website/pages/documentation/components/layout/card.py +15 -0
  335. solara/website/pages/documentation/components/layout/card_actions.py +16 -0
  336. solara/website/pages/documentation/components/layout/column.py +30 -0
  337. solara/website/pages/documentation/components/layout/columns.py +27 -0
  338. solara/website/pages/documentation/components/layout/columns_responsive.py +66 -0
  339. solara/website/pages/documentation/components/layout/details.py +13 -0
  340. solara/website/pages/documentation/components/layout/griddraggable.py +62 -0
  341. solara/website/pages/documentation/components/layout/gridfixed.py +19 -0
  342. solara/website/pages/documentation/components/layout/hbox.py +18 -0
  343. solara/website/pages/documentation/components/layout/row.py +30 -0
  344. solara/website/pages/documentation/components/layout/sidebar.py +24 -0
  345. solara/website/pages/documentation/components/layout/vbox.py +19 -0
  346. solara/website/pages/documentation/components/output/__init__.py +9 -0
  347. solara/website/pages/documentation/components/output/file_download.py +11 -0
  348. solara/website/pages/documentation/components/output/html.py +19 -0
  349. solara/website/pages/documentation/components/output/image.py +11 -0
  350. solara/website/pages/documentation/components/output/markdown.py +57 -0
  351. solara/website/pages/documentation/components/output/markdown_editor.py +51 -0
  352. solara/website/pages/documentation/components/output/sql_code.py +83 -0
  353. solara/website/pages/documentation/components/output/tooltip.py +11 -0
  354. solara/website/pages/documentation/components/page/__init__.py +9 -0
  355. solara/website/pages/documentation/components/page/head.py +15 -0
  356. solara/website/pages/documentation/components/page/title.py +25 -0
  357. solara/website/pages/documentation/components/status/__init__.py +9 -0
  358. solara/website/pages/documentation/components/status/error.py +39 -0
  359. solara/website/pages/documentation/components/status/info.py +39 -0
  360. solara/website/pages/documentation/components/status/progress.py +10 -0
  361. solara/website/pages/documentation/components/status/spinner.py +11 -0
  362. solara/website/pages/documentation/components/status/success.py +40 -0
  363. solara/website/pages/documentation/components/status/warning.py +47 -0
  364. solara/website/pages/documentation/components/viz/__init__.py +9 -0
  365. solara/website/pages/documentation/components/viz/altair.py +42 -0
  366. solara/website/pages/documentation/components/viz/echarts.py +77 -0
  367. solara/website/pages/documentation/components/viz/matplotlib.py +30 -0
  368. solara/website/pages/documentation/components/viz/plotly.py +63 -0
  369. solara/website/pages/documentation/components/viz/plotly_express.py +41 -0
  370. solara/website/pages/documentation/examples/__init__.py +54 -0
  371. solara/website/pages/documentation/examples/ai/__init__.py +11 -0
  372. solara/website/pages/documentation/examples/ai/chatbot.py +113 -0
  373. solara/website/pages/documentation/examples/ai/tokenizer.py +107 -0
  374. solara/website/pages/documentation/examples/basics/__init__.py +10 -0
  375. solara/website/pages/documentation/examples/basics/sine.py +28 -0
  376. solara/website/pages/documentation/examples/fullscreen/__init__.py +10 -0
  377. solara/website/pages/documentation/examples/fullscreen/authorization.py +3 -0
  378. solara/website/pages/documentation/examples/fullscreen/layout_demo.py +3 -0
  379. solara/website/pages/documentation/examples/fullscreen/multipage.py +3 -0
  380. solara/website/pages/documentation/examples/fullscreen/scatter.py +3 -0
  381. solara/website/pages/documentation/examples/fullscreen/scrolling.py +3 -0
  382. solara/website/pages/documentation/examples/fullscreen/tutorial_streamlit.py +3 -0
  383. solara/website/pages/documentation/examples/general/__init__.py +10 -0
  384. solara/website/pages/documentation/examples/general/custom_storage.py +70 -0
  385. solara/website/pages/documentation/examples/general/deploy_model.py +115 -0
  386. solara/website/pages/documentation/examples/general/live_update.py +32 -0
  387. solara/website/pages/documentation/examples/general/login_oauth.py +81 -0
  388. solara/website/pages/documentation/examples/general/mycard.vue +58 -0
  389. solara/website/pages/documentation/examples/general/pokemon_search.py +51 -0
  390. solara/website/pages/documentation/examples/general/vue_component.py +50 -0
  391. solara/website/pages/documentation/examples/ipycanvas.py +49 -0
  392. solara/website/pages/documentation/examples/libraries/__init__.py +10 -0
  393. solara/website/pages/documentation/examples/libraries/altair.py +65 -0
  394. solara/website/pages/documentation/examples/libraries/bqplot.py +39 -0
  395. solara/website/pages/documentation/examples/libraries/ipyleaflet.py +33 -0
  396. solara/website/pages/documentation/examples/libraries/ipyleaflet_advanced.py +66 -0
  397. solara/website/pages/documentation/examples/utilities/__init__.py +10 -0
  398. solara/website/pages/documentation/examples/utilities/calculator.py +157 -0
  399. solara/website/pages/documentation/examples/utilities/countdown_timer.py +62 -0
  400. solara/website/pages/documentation/examples/utilities/todo.py +196 -0
  401. solara/website/pages/documentation/examples/visualization/__init__.py +6 -0
  402. solara/website/pages/documentation/examples/visualization/annotator.py +67 -0
  403. solara/website/pages/documentation/examples/visualization/linked_views.py +81 -0
  404. solara/website/pages/documentation/examples/visualization/plotly.py +44 -0
  405. solara/website/pages/documentation/faq/__init__.py +12 -0
  406. solara/website/pages/documentation/faq/content/99-faq.md +112 -0
  407. solara/website/pages/documentation/getting_started/__init__.py +9 -0
  408. solara/website/pages/documentation/getting_started/content/00-quickstart.md +107 -0
  409. solara/website/pages/documentation/getting_started/content/01-introduction.md +125 -0
  410. solara/website/pages/documentation/getting_started/content/02-installing.md +134 -0
  411. solara/website/pages/documentation/getting_started/content/04-tutorials/00-overview.md +14 -0
  412. solara/website/pages/documentation/getting_started/content/04-tutorials/10_data_science.py +13 -0
  413. solara/website/pages/documentation/getting_started/content/04-tutorials/20-web-app.md +89 -0
  414. solara/website/pages/documentation/getting_started/content/04-tutorials/30-ipywidgets.md +124 -0
  415. solara/website/pages/documentation/getting_started/content/04-tutorials/40-streamlit.md +146 -0
  416. solara/website/pages/documentation/getting_started/content/04-tutorials/50-dash.md +144 -0
  417. solara/website/pages/documentation/getting_started/content/04-tutorials/60-jupyter-dashboard-part1.py +65 -0
  418. solara/website/pages/documentation/getting_started/content/04-tutorials/SF_crime_sample.csv.gz +0 -0
  419. solara/website/pages/documentation/getting_started/content/04-tutorials/_data_science.ipynb +445 -0
  420. solara/website/pages/documentation/getting_started/content/04-tutorials/_jupyter_dashboard_1.ipynb +1021 -0
  421. solara/website/pages/documentation/getting_started/content/05-fundamentals/00-overview.md +11 -0
  422. solara/website/pages/documentation/getting_started/content/05-fundamentals/10-components.md +228 -0
  423. solara/website/pages/documentation/getting_started/content/05-fundamentals/50-state-management.md +278 -0
  424. solara/website/pages/documentation/getting_started/content/07-deploying/00-overview.md +7 -0
  425. solara/website/pages/documentation/getting_started/content/07-deploying/10-self-hosted.md +305 -0
  426. solara/website/pages/documentation/getting_started/content/07-deploying/20-cloud-hosted.md +80 -0
  427. solara/website/pages/documentation/getting_started/content/80-what-is-lab.md +7 -0
  428. solara/website/pages/documentation/getting_started/content/90-troubleshoot.md +26 -0
  429. solara/website/pages/docutils.py +38 -0
  430. solara/website/pages/home.vue +1199 -0
  431. solara/website/pages/our_team/__init__.py +83 -0
  432. solara/website/pages/pricing/__init__.py +31 -0
  433. solara/website/pages/roadmap/__init__.py +11 -0
  434. solara/website/pages/roadmap/roadmap.md +47 -0
  435. solara/website/pages/scale_ipywidgets.py +45 -0
  436. solara/website/pages/showcase/__init__.py +105 -0
  437. solara/website/pages/showcase/domino_code_assist.py +60 -0
  438. solara/website/pages/showcase/planeto_tessa.py +19 -0
  439. solara/website/pages/showcase/solara_dev.py +54 -0
  440. solara/website/pages/showcase/solarathon_2023_team_2.py +22 -0
  441. solara/website/pages/showcase/solarathon_2023_team_4.py +22 -0
  442. solara/website/pages/showcase/solarathon_2023_team_5.py +23 -0
  443. solara/website/pages/showcase/solarathon_2023_team_6.py +34 -0
  444. solara/website/pages/showcase/wanderlust.py +27 -0
  445. solara/website/public/beach.jpeg +0 -0
  446. solara/website/public/logo.svg +6 -0
  447. solara/website/public/social/discord.svg +1 -0
  448. solara/website/public/social/github.svg +1 -0
  449. solara/website/public/social/twitter.svg +3 -0
  450. solara/website/public/success.html +25 -0
  451. solara/website/templates/index.html.j2 +117 -0
  452. solara/website/utils.py +51 -0
  453. solara/widgets/__init__.py +1 -0
  454. solara/widgets/vue/gridlayout.vue +107 -0
  455. solara/widgets/vue/html.vue +4 -0
  456. solara/widgets/vue/navigator.vue +134 -0
  457. solara/widgets/vue/vegalite.vue +130 -0
  458. solara/widgets/widgets.py +74 -0
  459. solara_ui-1.45.0.data/data/etc/jupyter/jupyter_notebook_config.d/solara.json +7 -0
  460. solara_ui-1.45.0.data/data/etc/jupyter/jupyter_server_config.d/solara.json +7 -0
  461. solara_ui-1.45.0.dist-info/METADATA +162 -0
  462. solara_ui-1.45.0.dist-info/RECORD +464 -0
  463. solara_ui-1.45.0.dist-info/WHEEL +4 -0
  464. solara_ui-1.45.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,546 @@
1
+ from typing import List, cast
2
+
3
+ import numpy as np
4
+ import reacton.bqplot as bqplot
5
+ import reacton.ipyvuetify as v
6
+ import reacton.ipywidgets as w
7
+
8
+ import solara
9
+ from solara.components import ui_checkbox, ui_dropdown
10
+ from solara.hooks import use_cross_filter
11
+ from solara.lab.hooks.dataframe import use_df_column_names
12
+ from solara.lab.utils.dataframe import df_unique
13
+
14
+ cardheight = "100%"
15
+
16
+
17
+ @solara.component
18
+ def ExpressionEditor(df, value: str, label="Custom expression", on_value=None, placeholder="Enter an expression", prepend_icon="function"):
19
+ """Editor for expression for Vaex, on_value will only be triggered for valid expressions"""
20
+
21
+ def get_error(value):
22
+ if value is None:
23
+ return None
24
+ try:
25
+ df.validate_expression(value)
26
+ return None
27
+ except Exception as e:
28
+ return str(e)
29
+
30
+ value, set_value = solara.use_state(value)
31
+ error: List = []
32
+ error, set_error = solara.use_state(cast(List, []))
33
+ set_error([get_error(value)])
34
+
35
+ def on_value_local(value):
36
+ error = get_error(value)
37
+ set_value(value)
38
+ set_error([error])
39
+
40
+ if not error and on_value:
41
+ on_value(df[value])
42
+
43
+ return v.TextField(
44
+ label=label,
45
+ v_model=value,
46
+ on_v_model=on_value_local,
47
+ placeholder=placeholder,
48
+ prepend_icon="mdi-filter",
49
+ error_messages=error,
50
+ success_messages="Looking good" if value is not None else None,
51
+ )
52
+
53
+
54
+ @solara.component
55
+ def FilterCard(df):
56
+ filter, set_filter = use_cross_filter(id(df), "filter-custom")
57
+
58
+ with v.Card(elevation=2, height=cardheight) as main:
59
+ with v.CardTitle(children=["Filter"]):
60
+ pass
61
+ with v.CardText():
62
+ ExpressionEditor(df, "", on_value=set_filter)
63
+ return main
64
+
65
+
66
+ @solara.component
67
+ def Table(df, n=5):
68
+ output_c = w.Output()
69
+
70
+ def output():
71
+ import ipywidgets as widgets
72
+
73
+ output_real: widgets.Output = solara.get_widget(output_c)
74
+ # don't rely on display, does not work in solara yet
75
+ with output_real.hold_sync():
76
+ output_real.outputs = tuple()
77
+ output_real.append_display_data(df)
78
+
79
+ solara.use_effect(output)
80
+ return output_c
81
+
82
+
83
+ @solara.component
84
+ def TableCard(df):
85
+ filter, set_filter = use_cross_filter(id(df), "table")
86
+ dff = df
87
+ filtered = False
88
+ if filter is not None:
89
+ filtered = True
90
+ dff = df[filter]
91
+ if filtered:
92
+ title = "Filtered"
93
+ else:
94
+ title = "Showing all"
95
+ title = "Showing first 10 rows"
96
+ progress = len(dff) / len(df) * 100
97
+ with v.Card(elevation=2, height=cardheight) as main:
98
+ with v.CardTitle(children=[title]):
99
+ if filtered:
100
+ v.ProgressLinear(value=progress)
101
+ with v.CardText():
102
+ Table(dff)
103
+ return main
104
+
105
+
106
+ @solara.component
107
+ def HistogramCard(df, column=None, max_unique=100):
108
+ filter, set_filter = use_cross_filter(id(df), "filter-histogram")
109
+ dff = df # filter(df)
110
+
111
+ items = use_df_column_names(df)
112
+
113
+ with v.Card(elevation=2, height=cardheight) as main:
114
+ with v.CardTitle(children=["Histogram"]):
115
+ pass
116
+ with v.CardText():
117
+ with v.Btn(v_on="x.on", icon=True, absolute=True, style_="right: 10px; top: 10px") as btn:
118
+ v.Icon(children=["mdi-settings"])
119
+ with v.Dialog(v_slots=[{"name": "activator", "variable": "x", "children": btn}], width="500"):
120
+ with v.Sheet():
121
+ with v.Card(elevation=2):
122
+ with v.CardTitle(children=["Histogram input"]):
123
+ pass
124
+ with v.CardText():
125
+ column = items[0] if column not in items else column
126
+ column = ui_dropdown(value=column, label="x", options=items)
127
+ if column:
128
+ log = False
129
+ import vaex
130
+
131
+ dfg = dff.groupby(column, agg={"count": vaex.agg.count(selection=filter)}, sort=True)
132
+ if len(dfg) > max_unique:
133
+ with v.Alert(
134
+ type="warning",
135
+ text=True,
136
+ prominent=True,
137
+ icon="mdi-alert",
138
+ children=[f"Too many unique values: {len(dfg)}, only showing first {max_unique}"],
139
+ ):
140
+ pass
141
+ dfg = dfg[:max_unique]
142
+ if 1:
143
+ x = dfg[column].to_numpy()
144
+ y = dfg["count"].to_numpy()
145
+ if df[column].dtype == bool:
146
+ scale_x = bqplot.OrdinalScale()
147
+ x = np.where(x.astype("int8"), "true", "false")
148
+ elif dfg[column].dtype == str:
149
+ scale_x = bqplot.OrdinalScale(domain=x.tolist())
150
+ else:
151
+ scale_x = bqplot.OrdinalScale()
152
+ if log:
153
+ scale_y = bqplot.LogScale()
154
+ else:
155
+ scale_y = bqplot.LinearScale()
156
+
157
+ def on_selected(selected):
158
+ if selected is not None:
159
+ if df[column].dtype == bool:
160
+ value = [True, False][selected[0]]
161
+ else:
162
+ value = x[selected[0]]
163
+ expression = df[column] == value
164
+ set_filter(expression)
165
+ else:
166
+ set_filter(None)
167
+
168
+ lines = bqplot.Bars(
169
+ colors=["rgba(58, 130, 246, 0.5)"],
170
+ x=x.tolist(),
171
+ y=y.tolist(),
172
+ scales={"x": scale_x, "y": scale_y},
173
+ type="grouped",
174
+ selected_style={"fill": "rgba(58, 130, 246, 0.8)"},
175
+ on_selected=on_selected,
176
+ interactions={"click": "select"},
177
+ )
178
+ x_axis = bqplot.Axis(
179
+ scale=scale_x,
180
+ label=column,
181
+ grid_lines="none",
182
+ color="rgba(0,0,0,0)",
183
+ tick_style={
184
+ "fill": "rgba(0,0,0,0.8)",
185
+ },
186
+ )
187
+ y_axis = bqplot.Axis(
188
+ scale=scale_y,
189
+ orientation="vertical",
190
+ label="count",
191
+ color="rgba(0,0,0,0)",
192
+ tick_style={
193
+ "fill": "rgba(0,0,0,0.8)",
194
+ },
195
+ )
196
+ axes = [x_axis, y_axis]
197
+ bqplot.Figure(axes=axes, marks=[lines])
198
+ return main
199
+
200
+
201
+ @solara.component
202
+ def ScatterCard(df, x=None, y=None, color=None):
203
+ filter, set_filter = use_cross_filter(id(df), "filter-scatter")
204
+ dff = df
205
+ if filter:
206
+ dff = df[filter]
207
+ columns = use_df_column_names(df)
208
+ max_points = 1000
209
+ floats = [k for k in columns if df[k].dtype == float]
210
+ # flots = df.get_column_names()
211
+
212
+ with v.Card(elevation=2, height=cardheight) as main:
213
+ with v.CardTitle(children=["Scatter"]):
214
+ pass
215
+ with v.CardText():
216
+ with v.Btn(v_on="x.on", icon=True, absolute=True, style_="right: 10px; top: 10px") as btn:
217
+ v.Icon(children=["mdi-settings"])
218
+ with v.Dialog(v_slots=[{"name": "activator", "variable": "x", "children": btn}], width="500"):
219
+ with v.Sheet():
220
+ with v.Card(elevation=2):
221
+ with v.CardTitle(children=["Histogram input"]):
222
+ pass
223
+ with v.CardText():
224
+ xcol = x
225
+ if xcol is None:
226
+ xcol = xcol if len(floats) == 0 else floats[0]
227
+ xcol = ui_dropdown(value=xcol, label="x", options=floats)
228
+ ycol = y
229
+ if ycol is None:
230
+ ycol = ycol if len(floats) < 2 else floats[1]
231
+ ycol = ui_dropdown(value=ycol, label="y", options=floats)
232
+ ccol = color
233
+ if ccol is None:
234
+ ccol = ccol if len(floats) < 3 else floats[0]
235
+ ccol = ui_dropdown(value=ccol, label="Color", options=floats)
236
+ if xcol and ycol:
237
+ if len(dff) > max_points:
238
+ v.Alert(
239
+ type="warning", text=True, prominent=True, icon="mdi-alert", children=[f"Too many unique values, will only show first {max_points}"]
240
+ )
241
+ dff = dff[:max_points]
242
+
243
+ x = dff[xcol].to_numpy()
244
+ y = dff[ycol].to_numpy()
245
+ if ccol is not None:
246
+ colord = dff[ccol].to_numpy().tolist()
247
+ else:
248
+ colord = None
249
+
250
+ if df[xcol].dtype == bool:
251
+ scale_x = bqplot.OrdinalScale()
252
+ x = np.where(x.astype("int8"), "true", "false")
253
+ elif df[xcol].dtype == str:
254
+ scale_x = bqplot.OrdinalScale()
255
+ else:
256
+ scale_x = bqplot.LinearScale()
257
+
258
+ if df[ycol].dtype == bool:
259
+ scale_y = bqplot.OrdinalScale()
260
+ y = np.where(y.astype("int8"), "true", "false")
261
+ elif df[ycol].dtype == str:
262
+ scale_y = bqplot.OrdinalScale()
263
+ else:
264
+ scale_y = bqplot.LinearScale()
265
+
266
+ def on_selected(selected):
267
+ if selected is not None and len(selected) > 0:
268
+ if df[xcol].dtype == bool:
269
+ value_x = [True, False][selected[0]]
270
+ else:
271
+ value_x = x[selected[0]]
272
+ if df[ycol].dtype == bool:
273
+ value_y = [True, False][selected[0]]
274
+ else:
275
+ value_y = y[selected[0]]
276
+ expression = (df[xcol] == value_x) & (df[ycol] == value_y)
277
+ set_filter(expression)
278
+ else:
279
+ set_filter(None)
280
+
281
+ scale_color = bqplot.ColorScale()
282
+ scatter = bqplot.Scatter(
283
+ x=x,
284
+ y=y,
285
+ scales={"x": scale_x, "y": scale_y, "color": scale_color},
286
+ color=colord,
287
+ selected_style={"fill": "#f55"},
288
+ on_selected=on_selected,
289
+ interactions={"click": "select"},
290
+ )
291
+ x_axis = bqplot.Axis(scale=scale_x, label=xcol)
292
+ y_axis = bqplot.Axis(scale=scale_y, orientation="vertical", label=ycol)
293
+ axes = [x_axis, y_axis]
294
+ marks = [scatter]
295
+ bqplot.Figure(axes=axes, marks=marks)
296
+ return main
297
+
298
+
299
+ color_maps = [
300
+ "Spectral",
301
+ "RdYlGn",
302
+ "RdBu",
303
+ "PiYG",
304
+ "PRGn",
305
+ "RdYlBu",
306
+ "BrBG",
307
+ "RdGy",
308
+ "PuOr",
309
+ "Set2",
310
+ "Accent",
311
+ "Set1",
312
+ "Set3",
313
+ "Dark2",
314
+ "Paired",
315
+ "Pastel2",
316
+ "Pastel1",
317
+ "OrRd",
318
+ "PuBu",
319
+ "BuPu",
320
+ "Oranges",
321
+ "BuGn",
322
+ "YlOrBr",
323
+ "YlGn",
324
+ "Reds",
325
+ "RdPu",
326
+ "Greens",
327
+ "YlGnBu",
328
+ "Purples",
329
+ "GnBu",
330
+ "Greys",
331
+ "YlOrRd",
332
+ "PuRd",
333
+ "Blues",
334
+ "PuBuGn",
335
+ "viridis",
336
+ "plasma",
337
+ "inferno",
338
+ "magma",
339
+ ]
340
+
341
+ cardheight = "100%"
342
+
343
+
344
+ @solara.component
345
+ def HeatmapCard(df, x=None, y=None, debounce=True):
346
+ limit_keys = "xmin xmax ymin ymax".split()
347
+ limits, set_limits = solara.use_state(dict.fromkeys(limit_keys))
348
+ contrast, set_contrast = solara.use_state([0.5, 99.5])
349
+ # print("limits", limits)
350
+ limits = limits.copy()
351
+ filter, set_filter = use_cross_filter(id(df), "filter-heatmap")
352
+ dff = df
353
+ selection = filter
354
+ # print("unfiltered", dff is df)
355
+
356
+ items = use_df_column_names(df)
357
+ floats = [k for k in items if df[k].dtype == float]
358
+
359
+ with v.Card(elevation=2, height=cardheight) as main:
360
+ with v.CardTitle(children=["Heatmap"]):
361
+ pass
362
+ with v.CardText():
363
+ with v.Btn(v_on="x.on", icon=True, absolute=True, style_="right: 10px; top: 10px") as btn:
364
+ v.Icon(children=["mdi-settings"])
365
+ with v.Dialog(v_slots=[{"name": "activator", "variable": "x", "children": btn}], width="700"):
366
+ with v.Sheet():
367
+ with v.Card(elevation=2):
368
+ with v.CardTitle(children=["Histogram input"]):
369
+ pass
370
+ with v.CardText():
371
+ xcol = x
372
+ if xcol is None:
373
+ xcol = xcol if len(floats) == 0 else floats[0]
374
+ xcol = ui_dropdown(value=xcol, label="x", options=floats)
375
+ ycol = y
376
+ if ycol is None:
377
+ ycol = ycol if len(floats) == 0 else floats[1]
378
+ ycol = ui_dropdown(value=ycol, label="y", options=floats)
379
+ scheme = ui_dropdown("Color map", value=color_maps[0], options=color_maps)
380
+ v.RangeSlider(v_model=contrast, on_v_model=set_contrast, label="Contrast", min=0, max=100)
381
+ crossfilter_visible = ui_checkbox(value=False, label="Cross filter visible")
382
+
383
+ if xcol and ycol:
384
+ import vaex.jupyter
385
+
386
+ def updater(name):
387
+ def make():
388
+ # def shared(): # all render functions get a shared function per 'name'
389
+ def setter(value):
390
+ def state_updater(state):
391
+ return {**state, name: value}
392
+
393
+ set_limits(state_updater)
394
+
395
+ if debounce:
396
+ return vaex.jupyter.debounced(0.3)(setter)
397
+ else:
398
+ return setter
399
+ # return shared
400
+
401
+ return solara.use_memo(make, [name])
402
+
403
+ update_xmin = updater("xmin")
404
+ update_xmax = updater("xmax")
405
+ update_ymin = updater("ymin")
406
+ update_ymax = updater("ymax")
407
+
408
+ # def update(name):
409
+ # def update_single(value):
410
+ # update_single_debouced(name, value)
411
+ # return update_single
412
+
413
+ def minx(x):
414
+ values = [k.item() for k in dff[x].minmax()]
415
+ update_xmin(values[0])
416
+ update_xmax(values[1])
417
+
418
+ solara.use_memo(lambda: minx(xcol), [xcol])
419
+
420
+ # @solara.use_memo
421
+ def miny(y):
422
+ values = [k.item() for k in dff[y].minmax()]
423
+ update_ymin(values[0])
424
+ update_ymax(values[1])
425
+
426
+ solara.use_memo(lambda: miny(ycol), [ycol])
427
+
428
+ if all(limits[k] is not None for k in limit_keys):
429
+ # print("limits used", limits)
430
+ xrange = limits["xmin"], limits["xmax"]
431
+ yrange = limits["ymin"], limits["ymax"]
432
+
433
+ def cross_filter():
434
+ if crossfilter_visible:
435
+ visible_filter = (df[xcol] >= xrange[0]) & (df[xcol] <= xrange[1]) & (df[ycol] >= yrange[0]) & (df[ycol] <= yrange[1])
436
+ set_filter(visible_filter)
437
+ else:
438
+ set_filter(None)
439
+
440
+ solara.use_memo(cross_filter, [crossfilter_visible, xrange, yrange])
441
+
442
+ # @solara.use_memo
443
+
444
+ def grid(xcol, ycol, limits):
445
+ vaex_limits = [xrange, yrange]
446
+ # print(xcol, ycol, vaex_limits)
447
+ # print("grid", len(dff))
448
+ return dff.count(binby=(xcol, ycol), limits=vaex_limits, shape=(512, 256), selection=selection)
449
+
450
+ values = grid(xcol, ycol, limits).astype("float32").T
451
+
452
+ vmin = np.percentile(values.ravel(), contrast[0]).item()
453
+ vmax = np.percentile(values.ravel(), contrast[1]).item()
454
+ if vmin == vmax:
455
+ vmax = values.min().item()
456
+ vmax = values.max().item()
457
+ # print(values.min(), values.max(), vmin, vmax, contrast)
458
+
459
+ scale_x = bqplot.LinearScale(allow_padding=False, on_min=update_xmin, on_max=update_xmax) # min=0, max=1)
460
+ scale_y = bqplot.LinearScale(allow_padding=False, on_min=update_ymin, on_max=update_ymax) # min=0, max=1)
461
+ scales = {"x": scale_x, "y": scale_y, "image": bqplot.ColorScale(min=vmin, max=vmax, scheme=scheme)}
462
+ from bqplot_image_gl import ImageGL
463
+
464
+ image = ImageGL.element(image=values, scales=scales, x=xrange, y=yrange)
465
+ panzoom = bqplot.PanZoom(scales={"x": [scales["x"]], "y": [scales["y"]]})
466
+
467
+ x_axis = bqplot.Axis(scale=scale_x, label=xcol)
468
+ y_axis = bqplot.Axis(scale=scale_y, orientation="vertical", label=ycol)
469
+ axes = [x_axis, y_axis]
470
+ marks = [image]
471
+ bqplot.Figure(axes=axes, marks=marks, interaction=panzoom)
472
+ return main
473
+
474
+
475
+ @solara.component
476
+ def SummaryCard(df):
477
+ filter, set_filter = use_cross_filter(id(df), "summary")
478
+ dff = df
479
+ filtered = False
480
+ if filter is not None:
481
+ filtered = True
482
+ dff = df[filter]
483
+ if filtered:
484
+ title = "Filtered"
485
+ else:
486
+ title = "Showing all"
487
+ progress = len(dff) / len(df) * 100
488
+ with v.Card(elevation=2, height=cardheight) as main:
489
+ with v.CardTitle(children=[title]):
490
+ if filtered:
491
+ v.ProgressLinear(value=progress)
492
+ with v.CardText():
493
+ icon = "mdi-filter"
494
+ v.Icon(children=[icon], style_="opacity: 0.1" if not filtered else "")
495
+ if filtered:
496
+ summary = f"{len(dff):,} / {len(df):,}"
497
+ else:
498
+ summary = f"{len(dff):,}"
499
+ v.Html(tag="h3", children=[summary], style_="display: inline")
500
+ return main
501
+
502
+
503
+ @solara.component
504
+ def DropdownCard(df, column=None):
505
+ max_unique = 100
506
+ filter, set_filter = use_cross_filter(id(df), "filter-dropdown")
507
+ columns = use_df_column_names(df)
508
+ column, set_column = solara.use_state(columns[0] if column is None else column)
509
+ uniques = df_unique(df, column, limit=max_unique + 1)
510
+ value, set_value = solara.use_state(None)
511
+ # to avoid confusing vuetify about selecting 'None' and nothing
512
+ magic_value_missing = "__missing_value__"
513
+
514
+ def set_value_and_filter(value):
515
+ set_value(value)
516
+ # print(value)
517
+ if value is None:
518
+ set_filter(None)
519
+ else:
520
+ value = value["value"]
521
+ if value == magic_value_missing:
522
+ set_filter(str(df[column].ismissing()))
523
+ else:
524
+ filter = df[column] == value
525
+ # print(filter)
526
+ set_filter(filter)
527
+
528
+ with v.Card(elevation=2, height=cardheight) as main:
529
+ with v.CardTitle(children=["Filter out single value"]):
530
+ pass
531
+ with v.CardText():
532
+ with v.Btn(v_on="x.on", icon=True, absolute=True, style_="right: 10px; top: 10px") as btn:
533
+ v.Icon(children=["mdi-settings"])
534
+ with v.Dialog(v_slots=[{"name": "activator", "variable": "x", "children": btn}], width="500"):
535
+ with v.Sheet():
536
+ with v.Container(pa_4=True, ma_0=True):
537
+ with v.Row():
538
+ with v.Col():
539
+ v.Select(v_model=column, items=columns, on_v_model=set_column, label="Choose column")
540
+ # we use objects to we can distinguish between selecting nothing or None
541
+ items = [{"value": magic_value_missing if k is None else k, "text": str(k)} for k in uniques]
542
+ v.Select(v_model=value, items=items, on_v_model=set_value_and_filter, label=f"Choose {column} value", clearable=True, return_object=True)
543
+ if len(uniques) > max_unique:
544
+ v.Alert(type="warning", text=True, prominent=True, icon="mdi-alert", children=[f"Too many unique values, will only show first {max_unique}"])
545
+
546
+ return main