solara-ui 1.31.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (439) 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 +734 -0
  5. solara/alias.py +6 -0
  6. solara/autorouting.py +546 -0
  7. solara/cache.py +303 -0
  8. solara/checks.html +71 -0
  9. solara/checks.py +224 -0
  10. solara/comm.py +28 -0
  11. solara/components/__init__.py +59 -0
  12. solara/components/alert.py +155 -0
  13. solara/components/applayout.py +393 -0
  14. solara/components/button.py +85 -0
  15. solara/components/card.py +87 -0
  16. solara/components/checkbox.py +50 -0
  17. solara/components/code_highlight_css.py +11 -0
  18. solara/components/code_highlight_css.vue +63 -0
  19. solara/components/columns.py +159 -0
  20. solara/components/component_vue.py +110 -0
  21. solara/components/cross_filter.py +335 -0
  22. solara/components/dataframe.py +546 -0
  23. solara/components/datatable.py +221 -0
  24. solara/components/datatable.vue +175 -0
  25. solara/components/details.py +21 -0
  26. solara/components/download.vue +35 -0
  27. solara/components/echarts.py +75 -0
  28. solara/components/echarts.vue +128 -0
  29. solara/components/figure_altair.py +39 -0
  30. solara/components/file_browser.py +182 -0
  31. solara/components/file_download.py +199 -0
  32. solara/components/file_drop.py +139 -0
  33. solara/components/file_drop.vue +83 -0
  34. solara/components/file_list_widget.vue +78 -0
  35. solara/components/head.py +27 -0
  36. solara/components/head_tag.py +49 -0
  37. solara/components/head_tag.vue +60 -0
  38. solara/components/image.py +173 -0
  39. solara/components/input.py +436 -0
  40. solara/components/link.py +55 -0
  41. solara/components/markdown.py +378 -0
  42. solara/components/markdown_editor.py +25 -0
  43. solara/components/markdown_editor.vue +362 -0
  44. solara/components/matplotlib.py +74 -0
  45. solara/components/meta.py +47 -0
  46. solara/components/misc.py +333 -0
  47. solara/components/pivot_table.py +258 -0
  48. solara/components/pivot_table.vue +158 -0
  49. solara/components/progress.py +47 -0
  50. solara/components/select.py +182 -0
  51. solara/components/select.vue +27 -0
  52. solara/components/slider.py +442 -0
  53. solara/components/slider_date.vue +56 -0
  54. solara/components/spinner-solara.vue +105 -0
  55. solara/components/spinner.py +30 -0
  56. solara/components/sql_code.py +33 -0
  57. solara/components/sql_code.vue +128 -0
  58. solara/components/style.py +105 -0
  59. solara/components/switch.py +68 -0
  60. solara/components/tab_navigation.py +37 -0
  61. solara/components/title.py +90 -0
  62. solara/components/title.vue +38 -0
  63. solara/components/togglebuttons.py +200 -0
  64. solara/components/tooltip.py +61 -0
  65. solara/datatypes.py +143 -0
  66. solara/express.py +241 -0
  67. solara/hooks/__init__.py +4 -0
  68. solara/hooks/dataframe.py +99 -0
  69. solara/hooks/misc.py +263 -0
  70. solara/hooks/use_reactive.py +129 -0
  71. solara/hooks/use_thread.py +129 -0
  72. solara/kitchensink.py +8 -0
  73. solara/lab/__init__.py +34 -0
  74. solara/lab/components/__init__.py +6 -0
  75. solara/lab/components/chat.py +203 -0
  76. solara/lab/components/confirmation_dialog.py +163 -0
  77. solara/lab/components/cross_filter.py +7 -0
  78. solara/lab/components/input_date.py +298 -0
  79. solara/lab/components/menu.py +181 -0
  80. solara/lab/components/menu.vue +38 -0
  81. solara/lab/components/tabs.py +274 -0
  82. solara/lab/components/theming.py +98 -0
  83. solara/lab/components/theming.vue +72 -0
  84. solara/lab/hooks/__init__.py +0 -0
  85. solara/lab/hooks/dataframe.py +12 -0
  86. solara/lab/toestand.py +3 -0
  87. solara/lab/utils/__init__.py +2 -0
  88. solara/lab/utils/cookies.py +5 -0
  89. solara/lab/utils/dataframe.py +115 -0
  90. solara/lab/utils/headers.py +5 -0
  91. solara/layout.py +44 -0
  92. solara/lifecycle.py +46 -0
  93. solara/minisettings.py +133 -0
  94. solara/py.typed +0 -0
  95. solara/reactive.py +93 -0
  96. solara/routing.py +268 -0
  97. solara/scope/__init__.py +88 -0
  98. solara/scope/types.py +55 -0
  99. solara/server/__init__.py +0 -0
  100. solara/server/app.py +491 -0
  101. solara/server/assets/custom.css +1 -0
  102. solara/server/assets/custom.js +1 -0
  103. solara/server/assets/favicon.png +0 -0
  104. solara/server/assets/favicon.svg +5 -0
  105. solara/server/assets/style.css +1665 -0
  106. solara/server/assets/theme-dark.css +437 -0
  107. solara/server/assets/theme-light.css +420 -0
  108. solara/server/assets/theme.js +3 -0
  109. solara/server/cdn_helper.py +77 -0
  110. solara/server/esm.py +69 -0
  111. solara/server/fastapi.py +5 -0
  112. solara/server/flask.py +286 -0
  113. solara/server/jupyter/__init__.py +2 -0
  114. solara/server/jupyter/cdn_handler.py +28 -0
  115. solara/server/jupyter/server_extension.py +29 -0
  116. solara/server/jupytertools.py +46 -0
  117. solara/server/kernel.py +338 -0
  118. solara/server/kernel_context.py +357 -0
  119. solara/server/patch.py +552 -0
  120. solara/server/reload.py +242 -0
  121. solara/server/server.py +456 -0
  122. solara/server/settings.py +215 -0
  123. solara/server/shell.py +251 -0
  124. solara/server/starlette.py +601 -0
  125. solara/server/static/ansi.js +270 -0
  126. solara/server/static/highlight-dark.css +82 -0
  127. solara/server/static/highlight.css +43 -0
  128. solara/server/static/main-vuetify.js +260 -0
  129. solara/server/static/main.js +163 -0
  130. solara/server/static/solara_bootstrap.py +129 -0
  131. solara/server/static/sun.svg +23 -0
  132. solara/server/static/webworker.js +42 -0
  133. solara/server/telemetry.py +212 -0
  134. solara/server/templates/index.html.j2 +1 -0
  135. solara/server/templates/loader-plain.css +11 -0
  136. solara/server/templates/loader-plain.html +20 -0
  137. solara/server/templates/loader-solara.css +111 -0
  138. solara/server/templates/loader-solara.html +40 -0
  139. solara/server/templates/plain.html +82 -0
  140. solara/server/templates/solara.html.j2 +446 -0
  141. solara/server/threaded.py +75 -0
  142. solara/server/utils.py +30 -0
  143. solara/server/websocket.py +45 -0
  144. solara/settings.py +56 -0
  145. solara/tasks.py +837 -0
  146. solara/template/button.py +16 -0
  147. solara/template/markdown.py +42 -0
  148. solara/template/portal/.flake8 +6 -0
  149. solara/template/portal/.pre-commit-config.yaml +28 -0
  150. solara/template/portal/LICENSE +21 -0
  151. solara/template/portal/Procfile +7 -0
  152. solara/template/portal/mypy.ini +3 -0
  153. solara/template/portal/pyproject.toml +26 -0
  154. solara/template/portal/solara_portal/__init__.py +4 -0
  155. solara/template/portal/solara_portal/components/__init__.py +2 -0
  156. solara/template/portal/solara_portal/components/article.py +28 -0
  157. solara/template/portal/solara_portal/components/data.py +28 -0
  158. solara/template/portal/solara_portal/components/header.py +6 -0
  159. solara/template/portal/solara_portal/components/layout.py +6 -0
  160. solara/template/portal/solara_portal/content/articles/equis-in-vidi.md +85 -0
  161. solara/template/portal/solara_portal/content/articles/substiterat-vati.md +70 -0
  162. solara/template/portal/solara_portal/data.py +60 -0
  163. solara/template/portal/solara_portal/pages/__init__.py +67 -0
  164. solara/template/portal/solara_portal/pages/article/__init__.py +26 -0
  165. solara/template/portal/solara_portal/pages/tabular.py +29 -0
  166. solara/template/portal/solara_portal/pages/viz/__init__.py +70 -0
  167. solara/template/portal/solara_portal/pages/viz/overview.py +14 -0
  168. solara/test/__init__.py +0 -0
  169. solara/test/pytest_plugin.py +697 -0
  170. solara/toestand.py +772 -0
  171. solara/util.py +308 -0
  172. solara/website/__init__.py +0 -0
  173. solara/website/assets/custom.css +468 -0
  174. solara/website/assets/images/logo-small.png +0 -0
  175. solara/website/assets/images/logo.svg +17 -0
  176. solara/website/assets/images/logo_white.svg +50 -0
  177. solara/website/assets/theme.js +8 -0
  178. solara/website/components/__init__.py +5 -0
  179. solara/website/components/algolia.vue +24 -0
  180. solara/website/components/algolia_api.vue +187 -0
  181. solara/website/components/docs.py +118 -0
  182. solara/website/components/header.py +72 -0
  183. solara/website/components/hero.py +15 -0
  184. solara/website/components/mailchimp.py +12 -0
  185. solara/website/components/mailchimp.vue +47 -0
  186. solara/website/components/markdown.py +30 -0
  187. solara/website/components/notebook.py +171 -0
  188. solara/website/pages/__init__.py +575 -0
  189. solara/website/pages/apps/__init__.py +16 -0
  190. solara/website/pages/apps/authorization/__init__.py +119 -0
  191. solara/website/pages/apps/authorization/admin.py +12 -0
  192. solara/website/pages/apps/authorization/users.py +12 -0
  193. solara/website/pages/apps/jupyter-dashboard-1.py +116 -0
  194. solara/website/pages/apps/layout-demo.py +40 -0
  195. solara/website/pages/apps/multipage/__init__.py +38 -0
  196. solara/website/pages/apps/multipage/page1.py +26 -0
  197. solara/website/pages/apps/multipage/page2.py +34 -0
  198. solara/website/pages/apps/scatter.py +136 -0
  199. solara/website/pages/apps/scrolling.py +63 -0
  200. solara/website/pages/apps/tutorial-streamlit.py +18 -0
  201. solara/website/pages/changelog/__init__.py +8 -0
  202. solara/website/pages/changelog/changelog.md +204 -0
  203. solara/website/pages/contact/__init__.py +8 -0
  204. solara/website/pages/contact/contact.md +17 -0
  205. solara/website/pages/doc_use_download.py +85 -0
  206. solara/website/pages/documentation/__init__.py +184 -0
  207. solara/website/pages/documentation/advanced/__init__.py +9 -0
  208. solara/website/pages/documentation/advanced/content/00-overview.md +1 -0
  209. solara/website/pages/documentation/advanced/content/10-howto/00-overview.md +6 -0
  210. solara/website/pages/documentation/advanced/content/10-howto/10-multipage.md +196 -0
  211. solara/website/pages/documentation/advanced/content/10-howto/20-layout.md +125 -0
  212. solara/website/pages/documentation/advanced/content/10-howto/30-testing.md +162 -0
  213. solara/website/pages/documentation/advanced/content/10-howto/31-debugging.md +69 -0
  214. solara/website/pages/documentation/advanced/content/10-howto/40-embed.md +49 -0
  215. solara/website/pages/documentation/advanced/content/10-howto/50-ipywidget_libraries.md +124 -0
  216. solara/website/pages/documentation/advanced/content/15-reference/00-overview.md +3 -0
  217. solara/website/pages/documentation/advanced/content/15-reference/40-static_files.md +31 -0
  218. solara/website/pages/documentation/advanced/content/15-reference/41-asset-files.md +36 -0
  219. solara/website/pages/documentation/advanced/content/15-reference/60-static-site-generation.md +59 -0
  220. solara/website/pages/documentation/advanced/content/15-reference/70-search.md +34 -0
  221. solara/website/pages/documentation/advanced/content/15-reference/80-reloading.md +34 -0
  222. solara/website/pages/documentation/advanced/content/15-reference/90-notebook-support.md +7 -0
  223. solara/website/pages/documentation/advanced/content/15-reference/95-caching.md +148 -0
  224. solara/website/pages/documentation/advanced/content/20-understanding/00-introduction.md +10 -0
  225. solara/website/pages/documentation/advanced/content/20-understanding/05-ipywidgets.md +35 -0
  226. solara/website/pages/documentation/advanced/content/20-understanding/06-ipyvuetify.md +42 -0
  227. solara/website/pages/documentation/advanced/content/20-understanding/10-reacton.md +28 -0
  228. solara/website/pages/documentation/advanced/content/20-understanding/12-reacton-basics.md +108 -0
  229. solara/website/pages/documentation/advanced/content/20-understanding/15-anatomy.md +23 -0
  230. solara/website/pages/documentation/advanced/content/20-understanding/17-rules-of-hooks.md +7 -0
  231. solara/website/pages/documentation/advanced/content/20-understanding/18-containers.md +166 -0
  232. solara/website/pages/documentation/advanced/content/20-understanding/20-solara.md +18 -0
  233. solara/website/pages/documentation/advanced/content/20-understanding/40-routing.md +240 -0
  234. solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +97 -0
  235. solara/website/pages/documentation/advanced/content/20-understanding/60-voila.md +12 -0
  236. solara/website/pages/documentation/advanced/content/30-enterprise/00-overview.md +1 -0
  237. solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +171 -0
  238. solara/website/pages/documentation/advanced/content/40-development/00-overview.md +0 -0
  239. solara/website/pages/documentation/advanced/content/40-development/01-contribute.md +45 -0
  240. solara/website/pages/documentation/advanced/content/40-development/10-setup.md +76 -0
  241. solara/website/pages/documentation/api/__init__.py +19 -0
  242. solara/website/pages/documentation/api/cross_filter/__init__.py +9 -0
  243. solara/website/pages/documentation/api/cross_filter/cross_filter_dataframe.py +23 -0
  244. solara/website/pages/documentation/api/cross_filter/cross_filter_report.py +22 -0
  245. solara/website/pages/documentation/api/cross_filter/cross_filter_select.py +22 -0
  246. solara/website/pages/documentation/api/cross_filter/cross_filter_slider.py +22 -0
  247. solara/website/pages/documentation/api/hooks/__init__.py +9 -0
  248. solara/website/pages/documentation/api/hooks/use_cross_filter.py +25 -0
  249. solara/website/pages/documentation/api/hooks/use_dark_effective.py +12 -0
  250. solara/website/pages/documentation/api/hooks/use_effect.md +43 -0
  251. solara/website/pages/documentation/api/hooks/use_effect.py +9 -0
  252. solara/website/pages/documentation/api/hooks/use_exception.py +33 -0
  253. solara/website/pages/documentation/api/hooks/use_memo.md +16 -0
  254. solara/website/pages/documentation/api/hooks/use_memo.py +9 -0
  255. solara/website/pages/documentation/api/hooks/use_previous.py +33 -0
  256. solara/website/pages/documentation/api/hooks/use_reactive.py +16 -0
  257. solara/website/pages/documentation/api/hooks/use_state.py +10 -0
  258. solara/website/pages/documentation/api/hooks/use_state_or_update.py +69 -0
  259. solara/website/pages/documentation/api/hooks/use_thread.md +58 -0
  260. solara/website/pages/documentation/api/hooks/use_thread.py +44 -0
  261. solara/website/pages/documentation/api/hooks/use_trait_observe.py +12 -0
  262. solara/website/pages/documentation/api/routing/__init__.py +9 -0
  263. solara/website/pages/documentation/api/routing/generate_routes.py +10 -0
  264. solara/website/pages/documentation/api/routing/generate_routes_directory.py +10 -0
  265. solara/website/pages/documentation/api/routing/resolve_path.py +35 -0
  266. solara/website/pages/documentation/api/routing/route.py +31 -0
  267. solara/website/pages/documentation/api/routing/use_route.py +80 -0
  268. solara/website/pages/documentation/api/routing/use_router.py +16 -0
  269. solara/website/pages/documentation/api/utilities/__init__.py +9 -0
  270. solara/website/pages/documentation/api/utilities/component_vue.py +10 -0
  271. solara/website/pages/documentation/api/utilities/computed.py +16 -0
  272. solara/website/pages/documentation/api/utilities/display.py +16 -0
  273. solara/website/pages/documentation/api/utilities/get_kernel_id.py +16 -0
  274. solara/website/pages/documentation/api/utilities/get_session_id.py +16 -0
  275. solara/website/pages/documentation/api/utilities/memoize.py +35 -0
  276. solara/website/pages/documentation/api/utilities/on_kernel_start.py +27 -0
  277. solara/website/pages/documentation/api/utilities/reactive.py +16 -0
  278. solara/website/pages/documentation/api/utilities/widget.py +104 -0
  279. solara/website/pages/documentation/components/__init__.py +12 -0
  280. solara/website/pages/documentation/components/advanced/__init__.py +9 -0
  281. solara/website/pages/documentation/components/advanced/link.py +27 -0
  282. solara/website/pages/documentation/components/advanced/meta.py +20 -0
  283. solara/website/pages/documentation/components/advanced/style.py +45 -0
  284. solara/website/pages/documentation/components/common.py +9 -0
  285. solara/website/pages/documentation/components/data/__init__.py +9 -0
  286. solara/website/pages/documentation/components/data/dataframe.py +44 -0
  287. solara/website/pages/documentation/components/data/pivot_table.py +81 -0
  288. solara/website/pages/documentation/components/enterprise/__init__.py +9 -0
  289. solara/website/pages/documentation/components/enterprise/avatar.py +24 -0
  290. solara/website/pages/documentation/components/enterprise/avatar_menu.py +25 -0
  291. solara/website/pages/documentation/components/input/__init__.py +9 -0
  292. solara/website/pages/documentation/components/input/button.py +23 -0
  293. solara/website/pages/documentation/components/input/checkbox.py +10 -0
  294. solara/website/pages/documentation/components/input/file_browser.py +32 -0
  295. solara/website/pages/documentation/components/input/file_drop.py +76 -0
  296. solara/website/pages/documentation/components/input/input.py +19 -0
  297. solara/website/pages/documentation/components/input/select.py +22 -0
  298. solara/website/pages/documentation/components/input/slider.py +29 -0
  299. solara/website/pages/documentation/components/input/switch.py +10 -0
  300. solara/website/pages/documentation/components/input/togglebuttons.py +21 -0
  301. solara/website/pages/documentation/components/lab/__init__.py +9 -0
  302. solara/website/pages/documentation/components/lab/chat.py +109 -0
  303. solara/website/pages/documentation/components/lab/confirmation_dialog.py +55 -0
  304. solara/website/pages/documentation/components/lab/cookies_headers.py +48 -0
  305. solara/website/pages/documentation/components/lab/input_date.py +20 -0
  306. solara/website/pages/documentation/components/lab/menu.py +22 -0
  307. solara/website/pages/documentation/components/lab/tab.py +25 -0
  308. solara/website/pages/documentation/components/lab/tabs.py +45 -0
  309. solara/website/pages/documentation/components/lab/task.py +11 -0
  310. solara/website/pages/documentation/components/lab/theming.py +72 -0
  311. solara/website/pages/documentation/components/lab/use_task.py +11 -0
  312. solara/website/pages/documentation/components/layout/__init__.py +9 -0
  313. solara/website/pages/documentation/components/layout/app_bar.py +16 -0
  314. solara/website/pages/documentation/components/layout/app_bar_title.py +16 -0
  315. solara/website/pages/documentation/components/layout/app_layout.py +24 -0
  316. solara/website/pages/documentation/components/layout/card.py +15 -0
  317. solara/website/pages/documentation/components/layout/card_actions.py +16 -0
  318. solara/website/pages/documentation/components/layout/column.py +30 -0
  319. solara/website/pages/documentation/components/layout/columns.py +27 -0
  320. solara/website/pages/documentation/components/layout/columns_responsive.py +68 -0
  321. solara/website/pages/documentation/components/layout/griddraggable.py +62 -0
  322. solara/website/pages/documentation/components/layout/gridfixed.py +21 -0
  323. solara/website/pages/documentation/components/layout/hbox.py +18 -0
  324. solara/website/pages/documentation/components/layout/row.py +30 -0
  325. solara/website/pages/documentation/components/layout/sidebar.py +24 -0
  326. solara/website/pages/documentation/components/layout/vbox.py +19 -0
  327. solara/website/pages/documentation/components/output/__init__.py +9 -0
  328. solara/website/pages/documentation/components/output/file_download.py +11 -0
  329. solara/website/pages/documentation/components/output/html.py +21 -0
  330. solara/website/pages/documentation/components/output/image.py +11 -0
  331. solara/website/pages/documentation/components/output/markdown.py +57 -0
  332. solara/website/pages/documentation/components/output/markdown_editor.py +51 -0
  333. solara/website/pages/documentation/components/output/sql_code.py +85 -0
  334. solara/website/pages/documentation/components/output/tooltip.py +11 -0
  335. solara/website/pages/documentation/components/page/__init__.py +9 -0
  336. solara/website/pages/documentation/components/page/head.py +18 -0
  337. solara/website/pages/documentation/components/page/title.py +27 -0
  338. solara/website/pages/documentation/components/status/__init__.py +9 -0
  339. solara/website/pages/documentation/components/status/error.py +40 -0
  340. solara/website/pages/documentation/components/status/info.py +40 -0
  341. solara/website/pages/documentation/components/status/progress.py +10 -0
  342. solara/website/pages/documentation/components/status/spinner.py +11 -0
  343. solara/website/pages/documentation/components/status/success.py +40 -0
  344. solara/website/pages/documentation/components/status/warning.py +47 -0
  345. solara/website/pages/documentation/components/viz/__init__.py +9 -0
  346. solara/website/pages/documentation/components/viz/altair.py +42 -0
  347. solara/website/pages/documentation/components/viz/echarts.py +75 -0
  348. solara/website/pages/documentation/components/viz/matplotlib.py +30 -0
  349. solara/website/pages/documentation/components/viz/plotly.py +63 -0
  350. solara/website/pages/documentation/components/viz/plotly_express.py +41 -0
  351. solara/website/pages/documentation/examples/__init__.py +52 -0
  352. solara/website/pages/documentation/examples/ai/__init__.py +11 -0
  353. solara/website/pages/documentation/examples/ai/chatbot.py +95 -0
  354. solara/website/pages/documentation/examples/ai/tokenizer.py +107 -0
  355. solara/website/pages/documentation/examples/basics/__init__.py +10 -0
  356. solara/website/pages/documentation/examples/basics/sine.py +28 -0
  357. solara/website/pages/documentation/examples/fullscreen/__init__.py +10 -0
  358. solara/website/pages/documentation/examples/fullscreen/authorization.py +3 -0
  359. solara/website/pages/documentation/examples/fullscreen/layout_demo.py +3 -0
  360. solara/website/pages/documentation/examples/fullscreen/multipage.py +3 -0
  361. solara/website/pages/documentation/examples/fullscreen/scatter.py +3 -0
  362. solara/website/pages/documentation/examples/fullscreen/scrolling.py +3 -0
  363. solara/website/pages/documentation/examples/fullscreen/tutorial_streamlit.py +3 -0
  364. solara/website/pages/documentation/examples/general/__init__.py +10 -0
  365. solara/website/pages/documentation/examples/general/custom_storage.py +70 -0
  366. solara/website/pages/documentation/examples/general/deploy_model.py +115 -0
  367. solara/website/pages/documentation/examples/general/live_update.py +38 -0
  368. solara/website/pages/documentation/examples/general/login_oauth.py +81 -0
  369. solara/website/pages/documentation/examples/general/mycard.vue +58 -0
  370. solara/website/pages/documentation/examples/general/pokemon_search.py +51 -0
  371. solara/website/pages/documentation/examples/general/vue_component.py +50 -0
  372. solara/website/pages/documentation/examples/ipycanvas.py +49 -0
  373. solara/website/pages/documentation/examples/libraries/__init__.py +10 -0
  374. solara/website/pages/documentation/examples/libraries/altair.py +64 -0
  375. solara/website/pages/documentation/examples/libraries/bqplot.py +39 -0
  376. solara/website/pages/documentation/examples/libraries/ipyleaflet.py +33 -0
  377. solara/website/pages/documentation/examples/libraries/ipyleaflet_advanced.py +66 -0
  378. solara/website/pages/documentation/examples/utilities/__init__.py +10 -0
  379. solara/website/pages/documentation/examples/utilities/calculator.py +157 -0
  380. solara/website/pages/documentation/examples/utilities/countdown_timer.py +64 -0
  381. solara/website/pages/documentation/examples/utilities/todo.py +196 -0
  382. solara/website/pages/documentation/examples/visualization/__init__.py +6 -0
  383. solara/website/pages/documentation/examples/visualization/annotator.py +69 -0
  384. solara/website/pages/documentation/examples/visualization/linked_views.py +84 -0
  385. solara/website/pages/documentation/examples/visualization/plotly.py +44 -0
  386. solara/website/pages/documentation/faq/__init__.py +12 -0
  387. solara/website/pages/documentation/faq/content/99-faq.md +76 -0
  388. solara/website/pages/documentation/getting_started/__init__.py +9 -0
  389. solara/website/pages/documentation/getting_started/content/00-quickstart.md +89 -0
  390. solara/website/pages/documentation/getting_started/content/01-introduction.md +125 -0
  391. solara/website/pages/documentation/getting_started/content/02-installing.md +134 -0
  392. solara/website/pages/documentation/getting_started/content/04-tutorials/00-overview.md +14 -0
  393. solara/website/pages/documentation/getting_started/content/04-tutorials/10_data_science.py +13 -0
  394. solara/website/pages/documentation/getting_started/content/04-tutorials/20-web-app.md +89 -0
  395. solara/website/pages/documentation/getting_started/content/04-tutorials/30-ipywidgets.md +124 -0
  396. solara/website/pages/documentation/getting_started/content/04-tutorials/40-streamlit.md +146 -0
  397. solara/website/pages/documentation/getting_started/content/04-tutorials/50-dash.md +144 -0
  398. solara/website/pages/documentation/getting_started/content/04-tutorials/60-jupyter-dashboard-part1.py +64 -0
  399. solara/website/pages/documentation/getting_started/content/04-tutorials/SF_crime_sample.csv.gz +0 -0
  400. solara/website/pages/documentation/getting_started/content/04-tutorials/_data_science.ipynb +445 -0
  401. solara/website/pages/documentation/getting_started/content/04-tutorials/_jupyter_dashboard_1.ipynb +1000 -0
  402. solara/website/pages/documentation/getting_started/content/05-fundamentals/00-overview.md +11 -0
  403. solara/website/pages/documentation/getting_started/content/05-fundamentals/10-components.md +223 -0
  404. solara/website/pages/documentation/getting_started/content/05-fundamentals/50-state-management.md +88 -0
  405. solara/website/pages/documentation/getting_started/content/07-deploying/00-overview.md +7 -0
  406. solara/website/pages/documentation/getting_started/content/07-deploying/10-self-hosted.md +273 -0
  407. solara/website/pages/documentation/getting_started/content/07-deploying/20-cloud-hosted.md +80 -0
  408. solara/website/pages/documentation/getting_started/content/80-what-is-lab.md +7 -0
  409. solara/website/pages/documentation/getting_started/content/90-troubleshoot.md +26 -0
  410. solara/website/pages/docutils.py +38 -0
  411. solara/website/pages/showcase/__init__.py +105 -0
  412. solara/website/pages/showcase/domino_code_assist.py +60 -0
  413. solara/website/pages/showcase/planeto_tessa.py +19 -0
  414. solara/website/pages/showcase/solara_dev.py +54 -0
  415. solara/website/pages/showcase/solarathon_2023_team_2.py +22 -0
  416. solara/website/pages/showcase/solarathon_2023_team_4.py +22 -0
  417. solara/website/pages/showcase/solarathon_2023_team_5.py +23 -0
  418. solara/website/pages/showcase/solarathon_2023_team_6.py +34 -0
  419. solara/website/pages/showcase/wanderlust.py +27 -0
  420. solara/website/public/beach.jpeg +0 -0
  421. solara/website/public/logo.svg +6 -0
  422. solara/website/public/social/discord.svg +1 -0
  423. solara/website/public/social/github.svg +1 -0
  424. solara/website/public/social/twitter.svg +3 -0
  425. solara/website/public/success.html +25 -0
  426. solara/website/templates/index.html.j2 +117 -0
  427. solara/website/utils.py +51 -0
  428. solara/widgets/__init__.py +1 -0
  429. solara/widgets/vue/gridlayout.vue +110 -0
  430. solara/widgets/vue/html.vue +4 -0
  431. solara/widgets/vue/navigator.vue +104 -0
  432. solara/widgets/vue/vegalite.vue +115 -0
  433. solara/widgets/widgets.py +66 -0
  434. solara_ui-1.31.0.data/data/etc/jupyter/jupyter_notebook_config.d/solara.json +7 -0
  435. solara_ui-1.31.0.data/data/etc/jupyter/jupyter_server_config.d/solara.json +7 -0
  436. solara_ui-1.31.0.dist-info/METADATA +158 -0
  437. solara_ui-1.31.0.dist-info/RECORD +439 -0
  438. solara_ui-1.31.0.dist-info/WHEEL +5 -0
  439. solara_ui-1.31.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,221 @@
1
+ import dataclasses
2
+ import math
3
+ import os
4
+ from dataclasses import replace
5
+ from typing import Any, Callable, List, Optional, cast
6
+
7
+ import ipyvuetify as v
8
+ import ipywidgets
9
+ import solara
10
+ import solara.hooks.dataframe
11
+ import solara.lab
12
+ import traitlets
13
+ from solara.lab.hooks.dataframe import use_df_column_names
14
+ from solara.lab.utils.dataframe import df_type
15
+
16
+ from .. import CellAction, ColumnAction
17
+
18
+
19
+ def _ensure_dict(d):
20
+ if dataclasses.is_dataclass(d):
21
+ return dataclasses.asdict(d)
22
+ return d
23
+
24
+
25
+ def _drop_keys_from_list_of_mappings(drop):
26
+ def closure(list_of_dicts, widget):
27
+ return [{k: v for k, v in _ensure_dict(d).items() if k not in drop} for d in list_of_dicts]
28
+
29
+ return closure
30
+
31
+
32
+ class DataTableWidget(v.VuetifyTemplate):
33
+ template_file = os.path.realpath(os.path.join(os.path.dirname(__file__), "datatable.vue"))
34
+
35
+ total_length = traitlets.CInt().tag(sync=True)
36
+ checked = traitlets.List(cast(List[Any], [])).tag(sync=True) # indices of which rows are selected
37
+ column_actions = traitlets.List(trait=traitlets.Instance(ColumnAction), default_value=[]).tag(
38
+ sync=True, to_json=_drop_keys_from_list_of_mappings(["on_click"])
39
+ )
40
+ _column_actions_callbacks = traitlets.List(trait=traitlets.Callable(), default_value=[])
41
+ cell_actions = traitlets.List(trait=traitlets.Instance(CellAction), default_value=[]).tag(sync=True, to_json=_drop_keys_from_list_of_mappings(["on_click"]))
42
+ _cell_actions_callbacks = traitlets.List(trait=traitlets.Callable(), default_value=[])
43
+ items = traitlets.Any().tag(sync=True) # the data, a list of dict
44
+ headers = traitlets.Any().tag(sync=True)
45
+ headers_selections = traitlets.Any().tag(sync=True)
46
+ options = traitlets.Any().tag(sync=True)
47
+ items_per_page = traitlets.CInt(11).tag(sync=True)
48
+ selections = traitlets.Any([]).tag(sync=True)
49
+ selection_colors = traitlets.Any([]).tag(sync=True)
50
+ selection_enabled = traitlets.Bool(True).tag(sync=True)
51
+ highlighted = traitlets.Int(None, allow_none=True).tag(sync=True)
52
+ scrollable = traitlets.Bool(False).tag(sync=True)
53
+
54
+ # for use with scrollable, when used in the default UI
55
+ height = traitlets.Unicode(None, allow_none=True).tag(sync=True)
56
+
57
+ hidden_components = traitlets.List(cast(List[Any], [])).tag(sync=False)
58
+ column_header_hover = traitlets.Unicode(allow_none=True).tag(sync=True)
59
+ column_header_widget = traitlets.Any(allow_none=True).tag(sync=True, **ipywidgets.widget_serialization)
60
+
61
+ def vue_on_column_action(self, data):
62
+ header_value, action_index = data
63
+ on_click = self._column_actions_callbacks[action_index]
64
+ if on_click:
65
+ on_click(header_value)
66
+
67
+ def vue_on_cell_action(self, data):
68
+ row, header_value, action_index = data
69
+ on_click = self._cell_actions_callbacks[action_index]
70
+ if on_click:
71
+ on_click(header_value, row)
72
+
73
+
74
+ def format_default(df, column, row_index, value):
75
+ if isinstance(value, float) and math.isnan(value):
76
+ return "NaN"
77
+ return str(value)
78
+
79
+
80
+ @solara.component
81
+ def DataTable(
82
+ df,
83
+ page=0,
84
+ items_per_page=20,
85
+ format=None,
86
+ column_actions: List[ColumnAction] = [],
87
+ cell_actions: List[CellAction] = [],
88
+ scrollable=False,
89
+ on_column_header_hover: Optional[Callable[[Optional[str]], None]] = None,
90
+ column_header_info: Optional[solara.Element] = None,
91
+ ):
92
+ total_length = len(df)
93
+ options = {"descending": False, "page": page + 1, "itemsPerPage": items_per_page, "sortBy": [], "totalItems": total_length}
94
+ options, set_options = solara.use_state(options, key="options")
95
+ format = format or format_default
96
+ # frontend does 1 base, we use 0 based
97
+ page = options["page"] - 1
98
+ items_per_page = options["itemsPerPage"]
99
+ i1 = page * items_per_page
100
+ i2 = min(total_length, (page + 1) * items_per_page)
101
+
102
+ columns = use_df_column_names(df)
103
+
104
+ items = []
105
+ column_data = {}
106
+ dfs = df[i1:i2]
107
+
108
+ if df_type(df) == "pandas":
109
+ column_data = dfs[columns].to_dict("records")
110
+ elif df_type(df) == "polars":
111
+ column_data = dfs[columns].to_dicts()
112
+ else:
113
+ column_data = dfs[columns].to_records()
114
+ for i in range(i2 - i1):
115
+ item = {"__row__": i + i1} # special key for the row number
116
+ for column in columns:
117
+ item[column] = format(dfs, column, i + i1, column_data[i][column])
118
+ items.append(item)
119
+
120
+ headers = [{"text": name, "value": name, "sortable": False} for name in columns]
121
+ column_actions_callbacks = [k.on_click for k in column_actions]
122
+ cell_actions_callbacks = [k.on_click for k in cell_actions]
123
+ column_actions = [replace(k, on_click=None) for k in column_actions]
124
+ cell_actions = [replace(k, on_click=None) for k in cell_actions]
125
+
126
+ return DataTableWidget.element(
127
+ total_length=total_length,
128
+ items=items,
129
+ headers=headers,
130
+ headers_selections=[],
131
+ options=options,
132
+ items_per_page=items_per_page,
133
+ selections=[],
134
+ selection_colors=[],
135
+ selection_enabled=False,
136
+ highlighted=None,
137
+ scrollable=scrollable,
138
+ on_options=set_options,
139
+ column_actions=column_actions,
140
+ cell_actions=cell_actions,
141
+ _column_actions_callbacks=column_actions_callbacks,
142
+ _cell_actions_callbacks=cell_actions_callbacks,
143
+ on_column_header_hover=on_column_header_hover,
144
+ column_header_widget=column_header_info,
145
+ )
146
+
147
+
148
+ @solara.component
149
+ def DataFrame(
150
+ df,
151
+ items_per_page=20,
152
+ column_actions: List[ColumnAction] = [],
153
+ cell_actions: List[CellAction] = [],
154
+ scrollable=False,
155
+ on_column_header_hover: Optional[Callable[[Optional[str]], None]] = None,
156
+ column_header_info: Optional[solara.Element] = None,
157
+ ):
158
+ """Displays a Pandas dataframe in a table.
159
+
160
+ Pass in a dataframe as first argument, and optionally how many items per page to display.
161
+
162
+ ```solara
163
+ import solara
164
+ import pandas as pd
165
+ import plotly
166
+
167
+ df = plotly.data.iris()
168
+
169
+ @solara.component
170
+ def Page():
171
+ solara.DataFrame(df, items_per_page=5)
172
+
173
+ ```
174
+
175
+ # Custom column header info
176
+
177
+ Use the `column_header_info` argument to display a custom component on the column header when
178
+ the user hover above it. In this case we display the value counts for the column.
179
+
180
+ ```solara
181
+ import solara
182
+ import pandas as pd
183
+ import plotly
184
+
185
+ df = plotly.data.iris()
186
+
187
+ @solara.component
188
+ def Page():
189
+ column_hover, set_column_hover = solara.use_state(None)
190
+
191
+ with solara.Column(margin=4) as column_header_info:
192
+ if column_hover:
193
+ solara.Text("Value counts for " + column_hover)
194
+ display(df[column_hover].value_counts())
195
+ # if no column is hovered above, we provide an empty container
196
+ # so we always see the triple dot icon on the column header
197
+
198
+ solara.DataFrame(df, column_header_info=column_header_info, on_column_header_hover=set_column_hover)
199
+ ```
200
+
201
+
202
+ ## Arguments
203
+
204
+ * `df` - `DataFrame` - a Pandas dataframe.
205
+ * `items_per_page` - `int` - number of items per page.
206
+ * `column_actions` - Triggered via clicking on the triple dot icon on the headers (visible when hovering).
207
+ * `cell_actions` - Triggered via clicking on the triple dot icon in the cell (visible when hovering).
208
+ * `on_column_header_hover` - Optional callback when the user hovers over the triple dot icon on a header.
209
+ * `column_header_info` - Element to display in the column menu popup (visible when hovering), provide an
210
+ empty container element (like [Column](/documentation/components/layout/column)) to force showing the trigle dot icon (see example).
211
+
212
+ """
213
+ return DataTable(
214
+ df,
215
+ items_per_page=items_per_page,
216
+ column_actions=column_actions,
217
+ cell_actions=cell_actions,
218
+ scrollable=scrollable,
219
+ on_column_header_hover=on_column_header_hover,
220
+ column_header_info=column_header_info,
221
+ )
@@ -0,0 +1,175 @@
1
+ <template>
2
+ <v-slide-x-transition appear>
3
+ <div class="solara-data-table__viewport">
4
+ <v-data-table dense hide-default-header :headers="[...headers]" :items="items"
5
+ :footer-props="{ 'items-per-page-options': [10, 20, 50, 100] }" :options.sync="options"
6
+ :items_per_page.sync="items_per_page" :server-items-length="total_length" :class="[
7
+ 'elevation-1',
8
+ 'solara-data-table',
9
+ scrollable && 'solara-data-table--scrollable',
10
+ ]" :style="scrollable && height != null && `height: ${height}`">
11
+ <template v-slot:header="props">
12
+ <thead>
13
+ <tr>
14
+ <th style="padding: 0 10px; width: 40px">#</th>
15
+ <th style="padding: 0 1px; width: 30px" v-if="selection_enabled">
16
+ <v-btn icon color="primary" text small @click="apply_filter">
17
+ <v-icon>filter_list</v-icon>
18
+ </v-btn>
19
+ </th>
20
+ <th style="padding: 0 1px" v-for="(header, index) in headers_selections" :key="header.text">
21
+ <v-icon style="padding: 0 1px" :key="index" :color="selection_colors[index]">brightness_1</v-icon>
22
+ </th>
23
+ <v-slide-x-transition :key="header.text" v-for="header in headers">
24
+ <th class="text-no-wrap">
25
+ {{ header.text }}
26
+ <v-menu open-on-hover bottom offset-y @input="isOpen => onHeaderHover({ isOpen, header })"
27
+ v-if="(column_actions && column_actions.length) || column_header_widget">
28
+ <template v-slot:activator="{ on, attrs }">
29
+ <v-icon v-bind="attrs" v-on="on" small class="solara-data-table-menu">mdi-dots-vertical</v-icon>
30
+ </template>
31
+ <v-sheet v-if="header.value === column_header_hover" class="solara-data-table-column-header-sheet">
32
+ <jupyter-widget v-if="column_header_widget" :widget="column_header_widget"></jupyter-widget>
33
+ </v-sheet>
34
+ <v-list v-if="column_actions && column_actions.length">
35
+ <v-subheader>Actions:</v-subheader>
36
+ <v-list-item link @click="on_column_action([header.value, index])"
37
+ v-for="(action, index) in column_actions" :key="index">
38
+ <v-list-item-icon><v-icon>{{ action.icon }}</v-icon></v-list-item-icon>
39
+ <v-list-item-title>{{ action.name }}</v-list-item-title>
40
+ </v-list-item>
41
+ </v-list>
42
+ </v-menu>
43
+ </th>
44
+ </v-slide-x-transition>
45
+ </tr>
46
+ </thead>
47
+ </template>
48
+ <template v-slot:item="props">
49
+ <!-- @click="on_row_clicked(props.item.__row__)" -->
50
+ <tr :class="{ highlightedRow: props.item.__row__ === highlighted }">
51
+ <td style="padding: 0 10px" class="text-xs-left">
52
+ <i>{{ props.item.__row__ }}</i>
53
+ </td>
54
+ <td style="padding: 0 1px" class="text-xs-left" v-if="selection_enabled">
55
+ <v-checkbox hide-details style="margin-top: 0; padding-top: 0"
56
+ :input-value="checked.indexOf(props.item.__row__) != -1" :key="props.item.__row__"
57
+ @change="(value) => select({ checked: value, row: props.item.__row__ })" />
58
+ </td>
59
+ <td style="padding: 0 1px" :key="header.text" v-for="(header, index) in headers_selections">
60
+ <v-fade-transition leave-absolute>
61
+ <v-icon v-if="props.item[header.value]" v-model="props.item[header.value]"
62
+ :color="selection_colors[index]">brightness_1</v-icon>
63
+ </v-fade-transition>
64
+ </td>
65
+ <td v-for="header in headers" class="text-truncate text-no-wrap" :key="header.text"
66
+ :title="props.item[header.value]">
67
+ <v-slide-x-transition appear>
68
+ <!-- <span @click="on_item_click([props.item.__row__, header.value])">{{ props.item[header.value] }}</span> -->
69
+ <span>
70
+ {{ props.item[header.value] }}
71
+ <v-menu open-on-hover bottom offset-y v-if="cell_actions.length">
72
+ <template v-slot:activator="{ on, attrs }">
73
+ <v-icon v-bind="attrs" v-on="on" small class="solara-data-table-menu">mdi-dots-vertical</v-icon>
74
+ </template>
75
+ <v-list v-for="(action, index) in cell_actions" :key="index">
76
+ <v-list-item link @click="on_cell_action([props.item.__row__, header.value, index])">
77
+ <v-list-item-icon><v-icon>{{ action.icon }}</v-icon></v-list-item-icon>
78
+ <v-list-item-title>{{ action.name }}</v-list-item-title>
79
+ </v-list-item>
80
+ </v-list>
81
+ </v-menu>
82
+ </span>
83
+
84
+ </v-slide-x-transition>
85
+ </td>
86
+ </tr>
87
+ </template>
88
+ </v-data-table>
89
+ </div>
90
+ </v-slide-x-transition>
91
+ </template>
92
+
93
+ <script>
94
+ module.exports = {
95
+ methods: {
96
+ onHeaderHover({ header, isOpen }) {
97
+ if (isOpen) {
98
+ // if isOpen is true, we clicked, and we set it header.value
99
+ this.column_header_hover = header.value
100
+ } else {
101
+ // if false, we only 'unset' if the current header equals the current open menu
102
+ // because sometimes the menu from another column is closed after opening the new one
103
+ if (this.column_header_hover == header.value) {
104
+ this.column_header_hover = null
105
+ }
106
+ }
107
+ }
108
+ }
109
+ }
110
+ </script>
111
+ <style id="solara_table">
112
+ .highlightedRow {
113
+ background-color: #e3f2fd;
114
+ }
115
+
116
+ .solara-data-table table {
117
+ table-layout: fixed;
118
+ }
119
+
120
+ .solara-data-table--scrollable .v-data-table__wrapper {
121
+ overflow-y: auto;
122
+ height: calc(100% - 59px);
123
+ }
124
+
125
+ .solara-data-table--scrollable thead>tr {
126
+ position: sticky;
127
+ top: 0;
128
+ }
129
+
130
+ .solara-data-table--scrollable .v-data-table__wrapper,
131
+ .solara-data-table--scrollable .v-data-table__wrapper>table,
132
+ .solara-data-table--scrollable .v-data-table__wrapper>table thead,
133
+ .solara-data-table--scrollable .v-data-table__wrapper>table thead * {
134
+ background-color: inherit;
135
+ }
136
+
137
+ /* prevent checkboxes overlaying the table header */
138
+ .solara-data-table--scrollable .v-data-table__wrapper>table thead {
139
+ position: relative;
140
+ z-index: 1;
141
+ }
142
+
143
+ /* avoid margins to collapse, to avoid a white background */
144
+ .solara-data-table-column-header-sheet {
145
+ overflow: auto;
146
+ }
147
+
148
+ .solara-data-table.v-data-table th,
149
+ .solara-data-table.v-data-table td {
150
+ padding-left: 4px;
151
+ padding-right: 0;
152
+ }
153
+
154
+ .v-data-table .solara-data-table-menu {
155
+ opacity: 0;
156
+ transition: opacity 0.5s;
157
+ }
158
+
159
+ .v-data-table th:hover .solara-data-table-menu,
160
+ .v-data-table td:hover .solara-data-table-menu {
161
+ opacity: 1;
162
+ }
163
+
164
+ .solara-data-table__viewport {
165
+ overflow-x: auto;
166
+ width: 100%;
167
+ max-height: 100%;
168
+ }
169
+
170
+ .solara-data-table.v-data-table,
171
+ .solara-data-table.v-data-table table {
172
+ max-width: unset;
173
+ width: unset;
174
+ }
175
+ </style>
@@ -0,0 +1,21 @@
1
+ import solara
2
+ from solara.alias import rv
3
+
4
+
5
+ @solara.component
6
+ def Details(summary="Summary", children=[], expand=False):
7
+ expand, set_expand = solara.use_state_or_update(expand)
8
+
9
+ def on_v_model(v_model):
10
+ if v_model is None: # collapsed:
11
+ set_expand(False)
12
+ elif v_model == 0:
13
+ set_expand(True)
14
+ else:
15
+ raise RuntimeError(f"v_model has odd value: {v_model}")
16
+
17
+ with rv.ExpansionPanels(v_model=0 if expand else None, on_v_model=on_v_model) as main:
18
+ with rv.ExpansionPanel():
19
+ rv.ExpansionPanelHeader(children=[summary])
20
+ rv.ExpansionPanelContent(children=children)
21
+ return main
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <div @click="request_download = true" class="solara-file-download-container">
3
+ <jupyter-widget v-for="child in children" :key="child" :widget="child"></jupyter-widget>
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ module.exports = {
9
+ watch: {
10
+ bytes(value) {
11
+ if (this.request_download) {
12
+ const a = document.createElement('a');
13
+ a.download = this.filename;
14
+ const blob = new Blob([this.bytes], { type: this.mime_type });
15
+ const blobUrl = window.URL.createObjectURL(blob);
16
+ a.href = blobUrl;
17
+ document.body.appendChild(a);
18
+ a.click();
19
+ document.body.removeChild(a);
20
+ setTimeout(() => {
21
+ // Make sure we clean up
22
+ window.URL.revokeObjectURL(blobUrl);
23
+ }, 1000);
24
+ this.request_download = false;
25
+ }
26
+ }
27
+ }
28
+ }
29
+ </script>
30
+
31
+ <style id="solara-file-download">
32
+ .solara-file-download-container {
33
+ cursor: pointer;
34
+ }
35
+ </style>
@@ -0,0 +1,75 @@
1
+ from typing import Any, Callable
2
+
3
+ import ipyvuetify
4
+ import traitlets
5
+
6
+ import solara
7
+
8
+
9
+ class EchartsWidget(ipyvuetify.VuetifyTemplate):
10
+ template_file = (__file__, "echarts.vue")
11
+
12
+ attributes = traitlets.Dict(default_value=None, allow_none=True).tag(sync=True)
13
+
14
+ maps = traitlets.Any({}).tag(sync=True)
15
+ option = traitlets.Any({}).tag(sync=True)
16
+ on_click = traitlets.Callable(None, allow_none=True)
17
+ on_mouseover = traitlets.Callable(None, allow_none=True)
18
+ # for performance, so we don't get events from the frontend we don't care about
19
+ on_mouseover_enabled = traitlets.Bool(False).tag(sync=True)
20
+ on_mouseout = traitlets.Callable(None, allow_none=True)
21
+ # same, for performance
22
+ on_mouseout_enabled = traitlets.Bool(False).tag(sync=True)
23
+
24
+ def vue_on_click(self, data):
25
+ if self.on_click is not None:
26
+ self.on_click(data)
27
+
28
+ def vue_on_mouseover(self, data):
29
+ if self.on_mouseover is not None:
30
+ self.on_mouseover(data)
31
+
32
+ def vue_on_mouseout(self, data):
33
+ if self.on_mouseout is not None:
34
+ self.on_mouseout(data)
35
+
36
+
37
+ @solara.component
38
+ def FigureEcharts(
39
+ option: dict = {},
40
+ on_click: Callable[[Any], Any] = None,
41
+ on_mouseover: Callable[[Any], Any] = None,
42
+ on_mouseout: Callable[[Any], Any] = None,
43
+ maps: dict = {},
44
+ attributes={"style": "height: 400px"},
45
+ ):
46
+ """Create a Echarts figure.
47
+
48
+ See [The Echarts website for examples](https://echarts.apache.org/)
49
+
50
+ Note that we do not support a Python API to create the figure data.
51
+
52
+ A library such as Pyecharts can help you with that, otherwise you can provide
53
+ the data simply as data similarly as on the Echarts example webpage.
54
+
55
+ # Arguments
56
+
57
+ * option: dict, the option for the figure, see the echart documentation.
58
+ * on_click: Callable, a function that will be called when the user clicks on the figure.
59
+ * on_mouseover: Callable, a function that will be called when the user moves the mouse over a certain component.
60
+ * on_mouseout: Callable, a function that will be called when the user moves the mouse out of a certain component.
61
+ * maps: dict, a dictionary of maps to be used in the figure.
62
+ * attributes: dict, a dictionary of attributes to be passed to the container (like style, class).
63
+
64
+
65
+ """
66
+ return EchartsWidget.element(
67
+ option=option,
68
+ on_click=on_click,
69
+ on_mouseover=on_mouseover,
70
+ on_mouseover_enabled=on_mouseover is not None,
71
+ maps=maps,
72
+ on_mouseout=on_mouseout,
73
+ on_mouseout_enabled=on_mouseout is not None,
74
+ attributes=attributes,
75
+ )
@@ -0,0 +1,128 @@
1
+ <template>
2
+ <div>
3
+ <div ref="echarts" class="solara-echarts" v-bind="attributes"></div>
4
+ </div>
5
+ </template>
6
+ <script>
7
+ module.exports = {
8
+ mounted() {
9
+ const version = "5.4.0";
10
+ (async () => {
11
+ const echarts = (
12
+ await this.import([`${this.getCdn()}/echarts@${version}/dist/echarts.js`])
13
+ )[0];
14
+ this.echarts = echarts;
15
+ this.create();
16
+ })();
17
+ },
18
+ watch: {
19
+ option() {
20
+ // notMerge, otherwise we're left with axes etc
21
+ // see https://echarts.apache.org/en/api.html#echartsInstance.setOption
22
+ this.chart.setOption(this.option, true);
23
+ },
24
+ },
25
+ methods: {
26
+ create() {
27
+ this.chart = this.echarts.init(this.$refs.echarts);
28
+ console.log(this.maps);
29
+ Object.keys(this.maps).forEach((mapName) => {
30
+ console.log(mapName);
31
+ this.echarts.registerMap(mapName, this.maps[mapName]);
32
+ });
33
+
34
+ this.chart.setOption(this.option, true);
35
+ const eventProps = [
36
+ "componentType",
37
+ "seriesType",
38
+ "seriesIndex",
39
+ "seriesName",
40
+ "name",
41
+ "dataIndex",
42
+ "data",
43
+ "dataType",
44
+ "value",
45
+ "color",
46
+ ];
47
+ this.chart.on("click", (fullEvent) => {
48
+ const eventData = {};
49
+ eventProps.forEach((prop) => {
50
+ eventData[prop] = fullEvent[prop];
51
+ });
52
+ this.on_click(eventData);
53
+ });
54
+ this.chart.on("mouseover", (fullEvent) => {
55
+ const eventData = {};
56
+ eventProps.forEach((prop) => {
57
+ eventData[prop] = fullEvent[prop];
58
+ });
59
+ if (this.on_mouseover_enabled) this.on_mouseover(eventData);
60
+ });
61
+ this.chart.on("mouseout", (fullEvent) => {
62
+ const eventData = {};
63
+ eventProps.forEach((prop) => {
64
+ eventData[prop] = fullEvent[prop];
65
+ });
66
+ if (this.on_mouseout_enabled) this.on_mouseout(eventData);
67
+ });
68
+ },
69
+ import(deps) {
70
+ return this.loadRequire().then(() => {
71
+ if (window.jupyterVue) {
72
+ // in jupyterlab, we take Vue from ipyvue/jupyterVue
73
+ define("vue", [], () => window.jupyterVue.Vue);
74
+ } else {
75
+ define("vue", ["jupyter-vue"], (jupyterVue) => jupyterVue.Vue);
76
+ }
77
+ return new Promise((resolve, reject) => {
78
+ requirejs(deps, (...modules) => resolve(modules));
79
+ });
80
+ });
81
+ },
82
+ loadRequire() {
83
+ /* Needed in lab */
84
+ if (window.requirejs) {
85
+ console.log("require found");
86
+ return Promise.resolve();
87
+ }
88
+ return new Promise((resolve, reject) => {
89
+ const script = document.createElement("script");
90
+ script.src = `${this.getCdn()}/requirejs@2.3.6/require.js`;
91
+ script.onload = resolve;
92
+ script.onerror = reject;
93
+ document.head.appendChild(script);
94
+ });
95
+ },
96
+ getBaseUrl() {
97
+ if (window.solara && window.solara.rootPath !== undefined) {
98
+ return solara.rootPath + "/";
99
+ }
100
+ // if base url is set, we use ./ for relative paths compared to the base url
101
+ if (document.getElementsByTagName("base").length) {
102
+ return "./";
103
+ }
104
+ const labConfigData = document.getElementById("jupyter-config-data");
105
+ if (labConfigData) {
106
+ /* lab and Voila */
107
+ return JSON.parse(labConfigData.textContent).baseUrl;
108
+ }
109
+ let base = document.body.dataset.baseUrl || document.baseURI;
110
+ if (!base.endsWith("/")) {
111
+ base += "/";
112
+ }
113
+ return base;
114
+ },
115
+ getCdn() {
116
+ return (
117
+ (typeof solara_cdn !== "undefined" && solara_cdn) ||
118
+ `${this.getBaseUrl()}_solara/cdn`
119
+ );
120
+ },
121
+ },
122
+ };
123
+ </script>
124
+
125
+ <style id="solara-markdown-editor">
126
+ .solara-echarts {
127
+ }
128
+ </style>
@@ -0,0 +1,39 @@
1
+ from typing import Any, Callable
2
+
3
+ import solara
4
+ import solara.widgets
5
+
6
+
7
+ @solara.component
8
+ def FigureAltair(
9
+ chart,
10
+ on_click: Callable[[Any], None] = None,
11
+ on_hover: Callable[[Any], None] = None,
12
+ ):
13
+ """Renders an Altair chart using VegaLite.
14
+
15
+ See also [our altair example](/documentation/examples/libraries/altair).
16
+
17
+ ## Arguments
18
+
19
+ - chart: Altair chart
20
+ - on_click: Callback function for click events.
21
+ - on_hover: Callback function for hover events.
22
+
23
+ """
24
+ import altair as alt
25
+
26
+ with alt.renderers.enable("mimetype"):
27
+ bundle = chart._repr_mimebundle_()[0]
28
+ key4 = "application/vnd.vegalite.v4+json"
29
+ key5 = "application/vnd.vegalite.v5+json"
30
+ if key4 not in bundle and key5 not in bundle:
31
+ raise KeyError(f"{key4} and {key5} not in mimebundle:\n\n{bundle}")
32
+ spec = bundle.get(key5, bundle.get(key4))
33
+ return solara.widgets.VegaLite.element(
34
+ spec=spec, on_click=on_click, listen_to_click=on_click is not None, on_hover=on_hover, listen_to_hover=on_hover is not None
35
+ )
36
+
37
+
38
+ # alias for backward compatibility
39
+ AltairChart = FigureAltair