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,159 @@
1
+ import threading
2
+ import typing
3
+ from typing import Any, Callable, List, Optional, Union, cast
4
+
5
+ import traitlets
6
+ from ipyvue import Template
7
+ from ipyvuetify.extra import FileInput
8
+ from ipywidgets import widget_serialization
9
+ from typing_extensions import TypedDict
10
+
11
+ import solara
12
+ import solara.hooks as hooks
13
+
14
+
15
+ class FileInfo(TypedDict):
16
+ name: str
17
+ size: int
18
+ file_obj: typing.BinaryIO
19
+ data: Optional[bytes]
20
+
21
+
22
+ class FileDropZone(FileInput):
23
+ # override to narrow traitlet of FileInput
24
+ template = traitlets.Instance(Template).tag(sync=True, **widget_serialization)
25
+ template_file = (__file__, "file_drop.vue")
26
+ items = traitlets.List(default_value=cast(List[Any], [])).tag(sync=True)
27
+ label = traitlets.Unicode().tag(sync=True)
28
+ multiple = traitlets.Bool(True).tag(sync=True)
29
+
30
+
31
+ @solara.component
32
+ def _FileDrop(
33
+ label="Drop file(s) here",
34
+ on_total_progress: Optional[Callable[[float], None]] = None,
35
+ on_file: Optional[Callable[[Union[FileInfo, List[FileInfo]]], None]] = None,
36
+ lazy: bool = True,
37
+ multiple: bool = False,
38
+ ):
39
+ """Generic implementation used by FileDrop and FileDropMultiple.
40
+
41
+ If multiple=True, multiple files can be uploaded.
42
+ """
43
+
44
+ file_info, set_file_info = solara.use_state(None)
45
+ wired_files, set_wired_files = solara.use_state(cast(Optional[typing.List[FileInfo]], None))
46
+
47
+ file_drop = FileDropZone.element(label=label, on_total_progress=on_total_progress, on_file_info=set_file_info, multiple=multiple) # type: ignore
48
+
49
+ def wire_files():
50
+ if not file_info:
51
+ return
52
+
53
+ real = cast(FileDropZone, solara.get_widget(file_drop))
54
+
55
+ # workaround for @observe being cleared
56
+ real.version += 1
57
+ real.reset_stats()
58
+
59
+ set_wired_files(cast(typing.List[FileInfo], real.get_files()))
60
+
61
+ solara.use_effect(wire_files, [file_info])
62
+
63
+ def handle_file(cancel: threading.Event):
64
+ if not wired_files:
65
+ return
66
+ if on_file:
67
+ for i in range(len(wired_files)):
68
+ if not lazy:
69
+ wired_files[i]["data"] = wired_files[i]["file_obj"].read()
70
+ else:
71
+ wired_files[i]["data"] = None
72
+ if multiple:
73
+ on_file(wired_files)
74
+ else:
75
+ on_file(wired_files[0])
76
+
77
+ result: solara.Result = hooks.use_thread(handle_file, [wired_files])
78
+ if result.error:
79
+ raise result.error
80
+
81
+ return file_drop
82
+
83
+
84
+ @solara.component
85
+ def FileDrop(
86
+ label="Drop file here",
87
+ on_total_progress: Optional[Callable[[float], None]] = None,
88
+ on_file: Optional[Callable[[FileInfo], None]] = None,
89
+ lazy: bool = True,
90
+ ):
91
+ """Region a user can drop a file into for file uploading.
92
+
93
+ If lazy=True, no file content will be loaded into memory,
94
+ nor will any data be transferred by default.
95
+ If lazy=False, file content will be loaded into memory and passed to the `on_file` callback via the `FileInfo.data` attribute.
96
+
97
+
98
+ A file object is of the following argument type:
99
+ ```python
100
+ class FileInfo(typing.TypedDict):
101
+ name: str # file name
102
+ size: int # file size in bytes
103
+ file_obj: typing.BinaryIO
104
+ data: Optional[bytes]: bytes # only present if lazy=False
105
+ ```
106
+
107
+
108
+ ## Arguments
109
+ * `on_total_progress`: Will be called with the progress in % of the file upload.
110
+ * `on_file`: Will be called with a `FileInfo` object, which contains the file `.name`, `.length` and a `.file_obj` object.
111
+ * `lazy`: Whether to load the file contents into memory or not. If `False`,
112
+ the file contents will be loaded into memory via the `.data` attribute of file object(s).
113
+
114
+ ## Load into Pandas
115
+ To load the data into a Pandas DF, set `lazy=False` and use `file['file_obj']` (be careful of memory)<br>
116
+ You can run this directly in your Jupyter notebook
117
+
118
+ ```python
119
+ import io
120
+ import pandas as pd
121
+ import solara
122
+
123
+ @solara.component
124
+ def Page():
125
+ def load_file_df(file):
126
+ df = pd.read_csv(file["file_obj"])
127
+ print("Loaded dataframe:")
128
+ print(df)
129
+
130
+ solara.FileDrop(label="Drop file to see dataframe!", on_file=load_file_df)
131
+
132
+ ```
133
+
134
+ """
135
+
136
+ return _FileDrop(label=label, on_total_progress=on_total_progress, on_file=on_file, lazy=lazy, multiple=False)
137
+
138
+
139
+ @solara.component
140
+ def FileDropMultiple(
141
+ label="Drop files here",
142
+ on_total_progress: Optional[Callable[[float], None]] = None,
143
+ on_file: Optional[Callable[[List[FileInfo]], None]] = None,
144
+ lazy: bool = True,
145
+ ):
146
+ """Region a user can drop multiple files into for file uploading.
147
+
148
+ Almost identical to `FileDrop` except that multiple files can be dropped and `on_file` is called
149
+ with a list of `FileInfo` objects.
150
+
151
+ ## Arguments
152
+ * `on_total_progress`: Will be called with the progress in % of the file(s) upload.
153
+ * `on_file`: Will be called with a `List[FileInfo]`.
154
+ Each `FileInfo` contains the file `.name`, `.length`, `.file_obj` object, and `.data` attributes.
155
+ * `lazy`: Whether to load the file contents into memory or not.
156
+
157
+ """
158
+
159
+ return _FileDrop(label=label, on_total_progress=on_total_progress, on_file=on_file, lazy=lazy, multiple=True)
@@ -0,0 +1,83 @@
1
+ <template>
2
+ <div ref="dropzone" class="solara-file-drop" effectAllowed="move">
3
+ <template v-if="file_info && file_info.length > 0">
4
+ <template v-if="multiple">
5
+ <div v-for="file in file_info">
6
+ {{ file.name }}
7
+ </div>
8
+ </template>
9
+ <template v-else>
10
+ {{ file_info[0].name }}
11
+ </template>
12
+ </template>
13
+ <template v-else>
14
+ {{ label }}
15
+ </template>
16
+ </div>
17
+ </template>
18
+
19
+ <script>
20
+ module.exports = {
21
+ mounted() {
22
+ this.chunk_size = 2 * 1024 * 1024;
23
+ this.$refs.dropzone.addEventListener('dragover', event => {
24
+ event.preventDefault();
25
+ });
26
+
27
+ this.$refs.dropzone.addEventListener('drop', async event => {
28
+ event.preventDefault();
29
+ const items = await Promise.all([...event.dataTransfer.items]);
30
+ const files = items.map(i => i.webkitGetAsEntry())
31
+ const fileHolders = files.filter(f => f.isFile)
32
+ const nativeFilesPromises = fileHolders.map(fileHolder => new Promise((rs, rj) => fileHolder.file(rs, rj)))
33
+ const nativeFiles = await Promise.all(nativeFilesPromises)
34
+
35
+ this.native_file_info = nativeFiles
36
+ this.file_info = this.native_file_info.map(
37
+ ({name, size}) => ({
38
+ name,
39
+ isFile: true,
40
+ size,
41
+ }));
42
+ });
43
+ },
44
+ methods: {
45
+ jupyter_clear() {
46
+ this.native_file_info = [];
47
+ this.file_info = [];
48
+ },
49
+ jupyter_read(chunk) {
50
+ const {id, file_index, offset, length} = chunk;
51
+ let to_do = length;
52
+ let sub_offset = offset;
53
+
54
+ (async () => {
55
+ while (to_do > 0) {
56
+ console.log(this.chunk_size, to_do);
57
+ const sub_length = Math.min(to_do, this.chunk_size);
58
+
59
+ const file = this.native_file_info[file_index];
60
+ const blob = file.slice(sub_offset, sub_offset + sub_length);
61
+ const buff = await blob.arrayBuffer();
62
+
63
+ const msg = {id, file_index, offset: sub_offset, length: sub_length}
64
+ this.upload(msg, [buff]);
65
+
66
+ to_do -= sub_length
67
+ sub_offset += sub_length
68
+ }
69
+ })();
70
+ }
71
+ }
72
+ }
73
+ </script>
74
+
75
+ <style id="solara-file-drop">
76
+ .solara-file-drop {
77
+ height: 100px;
78
+ border: 1px dashed gray;
79
+ margin: 8px 0;
80
+ padding: 8px;
81
+ overflow: auto;
82
+ }
83
+ </style>
@@ -0,0 +1,78 @@
1
+ <template>
2
+ <v-sheet class="solara-file-list" ref="scrollpane"
3
+ @click="clicked = null"
4
+ >
5
+ <v-list
6
+ @click="clicked = null"
7
+ >
8
+ <v-list-item
9
+ v-for="{name, is_file, size} in files"
10
+ :key="name + '|' + is_file"
11
+ @click.stop="clicked = { name, is_file }"
12
+ @dblclick="double_clicked = { name, is_file }"
13
+ :class="(clicked && clicked.name == name) ? 'solara-file-list-selected': ''"
14
+ >
15
+ <v-list-item-icon>
16
+ <v-icon>{{ name === '..' ? 'mdi-keyboard-backspace' : is_file ? 'mdi-file-document' : 'mdi-folder' }}</v-icon>
17
+ </v-list-item-icon>
18
+
19
+ <v-list-item-content>
20
+ <v-list-item-title :class="'solara-file-list-' + (is_file ? 'file' : 'dir')">
21
+ {{ name }}<span v-if="size"> - {{ size }}</span>
22
+ </v-list-item-title>
23
+ </v-list-item-content>
24
+ </v-list-item>
25
+ </v-list>
26
+ </v-sheet>
27
+ </template>
28
+
29
+ <script>
30
+ module.exports = {
31
+ mounted() {
32
+ const element = this.$refs.scrollpane.$el
33
+ element.scrollTop = this.scroll_pos
34
+
35
+ this._scrollListener = _.debounce((e) => {
36
+ this.scroll_pos = Math.round(element.scrollTop)
37
+ }, 50)
38
+ element.addEventListener('scroll', this._scrollListener)
39
+ },
40
+ watch: {
41
+ scroll_pos(v) {
42
+ this.$nextTick(() => this.$refs.scrollpane.$el.scrollTop = v);
43
+ }
44
+ }
45
+ }
46
+ </script>
47
+
48
+ <style id="solara-file-list">
49
+ .solara-file-list {
50
+ height: 400px;
51
+ overflow: auto;
52
+ }
53
+
54
+ .solara-file-list-dir {
55
+ font-weight: bold;
56
+ }
57
+
58
+ .solara-file-list-selected {
59
+ background-color: #3333;
60
+
61
+ }
62
+
63
+ .solara-file-list .v-list-item__icon,
64
+ .solara-file-list .v-list-item__list {
65
+ margin-top: 0;
66
+ margin-bottom: 0;
67
+ }
68
+
69
+ .v-application--is-ltr .solara-file-list .v-list-item__icon {
70
+ margin-right: 8px;
71
+ }
72
+
73
+ .solara-file-list .v-list-item {
74
+ height: 28px;
75
+ min-height: 0;
76
+ padding-left: 0;
77
+ }
78
+ </style>
@@ -0,0 +1,27 @@
1
+ from typing import List
2
+
3
+ import reacton
4
+ import solara
5
+
6
+
7
+ @reacton.component
8
+ def Head(children: List[reacton.core.Element] = []):
9
+ """A component that manager the "head" tag of the page to avoid duplicate tags, such as titles.
10
+
11
+ Currently only supports the [title](/documentation/components/page/title) tag as child, e.g.:
12
+
13
+ ```python
14
+ import solara
15
+
16
+ @solara.component
17
+ def Page():
18
+ with solara.VBox() as main:
19
+ MyAwesomeComponent()
20
+ with solara.Head():
21
+ solara.Title("My page title")
22
+ return main
23
+
24
+ ```
25
+
26
+ """
27
+ return solara.Div(children=children, style="display; none")
@@ -0,0 +1,49 @@
1
+ from typing import Optional
2
+
3
+ import ipyvuetify as vy
4
+ import reacton.core
5
+ import solara
6
+ import traitlets
7
+
8
+
9
+ class HeadTagWidget(vy.VuetifyTemplate):
10
+ template_file = (__file__, "head_tag.vue")
11
+ tagname = traitlets.Unicode().tag(sync=True)
12
+ key = traitlets.Unicode(None, allow_none=True).tag(sync=True)
13
+ attributes = traitlets.Dict().tag(sync=True)
14
+ level = traitlets.Int().tag(sync=True)
15
+
16
+
17
+ @solara.component
18
+ def HeadTag(tagname: str, key=None, attributes: Optional[dict] = None):
19
+ """Add a child element to head element, or replace a meta tag with the same tagname and key.
20
+
21
+ This component should be used inside a [Head](/documentation/components/page/head) component, e.g.:
22
+
23
+ ```python
24
+ import solara
25
+
26
+ @solara.component
27
+ def Page():
28
+ with solara.VBox() as main:
29
+ MyAwesomeComponent()
30
+ with solara.Head():
31
+ solara.HeadTag(tagname="meta", attributes={"name": "description", "content": "My page description"})
32
+ return main
33
+ ```
34
+
35
+ If multiple HeadTag components are used with the same key, the 'deepest' child will take precedence.
36
+
37
+ ## Arguments
38
+
39
+ * tagname: the tagname of the element (e.g. 'meta', 'link', 'script')
40
+ * attributes: a dictionary of attributes to set on the element.
41
+ """
42
+ level = 0
43
+ rc = reacton.core.get_render_context()
44
+ context = rc.context
45
+ while context and context.parent:
46
+ level += 1
47
+ context = context.parent
48
+ attributes = attributes or {}
49
+ return HeadTagWidget.element(tagname=tagname, key=key, attributes=attributes, level=level)
@@ -0,0 +1,60 @@
1
+ <template><span></span></template>
2
+
3
+ <script>
4
+ module.exports = {
5
+ mounted() {
6
+ if (window._solaraHeadTags === undefined) {
7
+ window._solaraHeadTags = {};
8
+ }
9
+ if (window._solaraHeadTags[this.key] === undefined) {
10
+ window._solaraHeadTags[this.key] = [];
11
+ }
12
+ window._solaraHeadTags[this.key].push(this);
13
+ this.updateElement();
14
+ },
15
+ destroyed() {
16
+ const tags = window._solaraHeadTags[this.key];
17
+ tags.splice(tags.indexOf(this), 1);
18
+ // ask another headtag to update the element
19
+ if (tags.length) {
20
+ tags[0].updateElement();
21
+ }
22
+ },
23
+ watch: {
24
+ tagname() {
25
+ this.updateElement();
26
+ },
27
+ attributes() {
28
+ this.updateElement();
29
+ },
30
+ level() {
31
+ this.updateElement();
32
+ },
33
+ },
34
+ methods: {
35
+ updateElement() {
36
+ const tags = window._solaraHeadTags[this.key];
37
+ let deepestTag = tags[0];
38
+ for (let i = 1; i < tags.length; i++) {
39
+ if (tags[i].level > deepestTag.level) {
40
+ deepestTag = tags[i];
41
+ }
42
+ }
43
+ let el = document.head.querySelector(`[data-solara-head-key="${deepestTag.tagname}-${deepestTag.key}"]`);
44
+ if (el === null) {
45
+ el = document.createElement(deepestTag.tagname);
46
+ document.head.appendChild(el);
47
+ } else {
48
+ el.innerHTML = '';
49
+ while (el.attributes.length > 0) {
50
+ el.removeAttribute(el.attributes[0].name);
51
+ }
52
+ }
53
+ Object.keys(deepestTag.attributes).forEach((key) => {
54
+ el.setAttribute(key, deepestTag.attributes[key]);
55
+ });
56
+ el.setAttribute('data-solara-head-key', `${deepestTag.tagname}-${deepestTag.key}`);
57
+ }
58
+ },
59
+ };
60
+ </script>
@@ -0,0 +1,173 @@
1
+ import typing
2
+ from io import BytesIO
3
+ from pathlib import Path
4
+ from typing import List, Optional, Union
5
+
6
+ import solara
7
+ from solara.alias import rw
8
+
9
+ if typing.TYPE_CHECKING:
10
+ import numpy as np
11
+ import PIL.Image
12
+
13
+
14
+ @solara.component
15
+ def Image(
16
+ image: Union[str, Path, "np.ndarray", bytes, "PIL.Image.Image"],
17
+ width: Optional[str] = None,
18
+ format="png",
19
+ classes: List[str] = [],
20
+ ):
21
+ """Displays an image from a URL, Path, numpy data, bytes or PIL image.
22
+
23
+ If passed as bytes, the image is assumed to be in the format specified by the `format` argument.
24
+
25
+ ## Examples
26
+
27
+ ### Displaying an image from a Path
28
+
29
+ ```solara
30
+ import solara
31
+ import solara.website
32
+ from pathlib import Path
33
+
34
+
35
+ image_path = Path(solara.website.__file__).parent / "public/beach.jpeg"
36
+
37
+ @solara.component
38
+ def Page():
39
+ solara.Image(image_path)
40
+ ```
41
+
42
+ ### Displaying an image from a URL
43
+
44
+ ```solara
45
+ import solara
46
+
47
+
48
+ image_url = "/static/public/beach.jpeg"
49
+
50
+ @solara.component
51
+ def Page():
52
+ solara.Image(image_url)
53
+ display(image_url)
54
+
55
+ ```
56
+
57
+ ### Displaying an image from a numpy array
58
+
59
+ ```solara
60
+
61
+ import solara
62
+ import solara.website
63
+ from pathlib import Path
64
+ import numpy as np
65
+ import PIL.Image
66
+
67
+
68
+ image_path = Path(solara.website.__file__).parent / "public/beach.jpeg"
69
+ image_ndarray = np.asarray(PIL.Image.open(image_path))
70
+
71
+ @solara.component
72
+ def Page():
73
+ solara.Image(image_ndarray)
74
+ display(image_ndarray)
75
+ ```
76
+
77
+ ### Displaying an image from bytes
78
+
79
+ ```solara
80
+
81
+ import solara
82
+ import solara.website
83
+ from pathlib import Path
84
+ import PIL.Image
85
+
86
+
87
+ image_path = Path(solara.website.__file__).parent / "public/beach.jpeg"
88
+ image_bytes = image_path.read_bytes()
89
+
90
+ @solara.component
91
+ def Page():
92
+ solara.Image(image_bytes, format="jpeg")
93
+ display(image_bytes[:100])
94
+ ```
95
+
96
+ ### Displaying an image from a PIL Image
97
+
98
+ ```solara
99
+
100
+ import solara
101
+ import solara.website
102
+ from pathlib import Path
103
+ import PIL.Image
104
+
105
+
106
+ image_path = Path(solara.website.__file__).parent / "public/beach.jpeg"
107
+ image = PIL.Image.open(image_path)
108
+
109
+ @solara.component
110
+ def Page():
111
+ solara.Image(image)
112
+ ```
113
+
114
+
115
+ ## Arguments
116
+ * `image`: URL, Path, numpy data, bytes or PIL Image.
117
+ * `width`: Width of the image, by default (None) the image is displayed at its original size.
118
+ Other options are: "100%" (to full its parent size), "100px" (to display it at 100 pixels wide),
119
+ or any other CSS width value.
120
+ * `format`: Format of the image, only used when image is of type bytes, or a PIL Image is passed.
121
+ * `classes`: List of CSS classes to add to the image.
122
+ """
123
+ layout = {}
124
+ if width:
125
+ layout["width"] = width
126
+ classes = ["solara-image"] + classes
127
+ if isinstance(image, (str, Path)):
128
+ path = Path(image)
129
+ if path.exists():
130
+ import ipywidgets
131
+
132
+ format = ipywidgets.Image._guess_format("image", str(path))
133
+ value = ipywidgets.Image._load_file_value(str(path))
134
+ return rw.Image(
135
+ value=value,
136
+ format=format,
137
+ _dom_classes=classes, # type: ignore
138
+ layout=layout,
139
+ )
140
+ elif isinstance(image, str):
141
+ url_data = image.encode("utf8")
142
+ return rw.Image(
143
+ value=url_data,
144
+ format="url",
145
+ _dom_classes=classes, # type: ignore
146
+ layout=layout,
147
+ )
148
+ elif isinstance(image, bytes):
149
+ return rw.Image(
150
+ value=image,
151
+ format=format,
152
+ _dom_classes=classes, # type: ignore
153
+ layout=layout,
154
+ )
155
+ elif solara.util.isinstanceof(image, "PIL.Image:Image"):
156
+ f = BytesIO()
157
+ image.save(f, format=format) # type: ignore
158
+ value = f.getvalue()
159
+ return rw.Image(
160
+ value=value,
161
+ format="png",
162
+ _dom_classes=classes, # type: ignore
163
+ layout=layout,
164
+ )
165
+ elif solara.util.isinstanceof(image, "numpy:ndarray"):
166
+ value = solara.util.numpy_to_image(image, format="png") # type: ignore
167
+ return rw.Image(
168
+ value=value,
169
+ format="png",
170
+ _dom_classes=classes, # type: ignore
171
+ layout=layout,
172
+ )
173
+ raise TypeError(f"Only support URL, path or numpy array, not {image}")