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,339 @@
1
+ import datetime as dt
2
+ from typing import Callable, Dict, List, Optional, Tuple, Union, cast
3
+
4
+ import ipyvue
5
+ import reacton
6
+
7
+ import solara
8
+ import solara.lab
9
+ from solara.components.input import _use_input_type
10
+
11
+
12
+ def use_close_menu(el: reacton.core.Element, is_open: solara.Reactive[bool]):
13
+ is_open_ref = solara.use_ref(is_open)
14
+ is_open_ref.current = is_open
15
+
16
+ def monitor_events():
17
+ def close_menu(*ignore_args):
18
+ is_open_ref.current.set(False)
19
+
20
+ widget = cast(ipyvue.VueWidget, solara.get_widget(el))
21
+ widget.on_event("keyup.enter", close_menu)
22
+ widget.on_event("keydown.tab", close_menu)
23
+
24
+ def cleanup():
25
+ widget.on_event("keyup.enter", close_menu, remove=True)
26
+ widget.on_event("keydown.tab", close_menu, remove=True)
27
+
28
+ return cleanup
29
+
30
+ solara.use_effect(monitor_events, [])
31
+
32
+
33
+ @solara.component
34
+ def InputDate(
35
+ value: Union[solara.Reactive[Optional[dt.date]], Optional[dt.date]],
36
+ on_value: Optional[Callable[[Optional[dt.date]], None]] = None,
37
+ label: str = "Pick a date",
38
+ children: List[solara.Element] = [],
39
+ open_value: Union[solara.Reactive[bool], bool] = False,
40
+ on_open_value: Optional[Callable[[bool], None]] = None,
41
+ optional: bool = False,
42
+ date_format: str = "%Y/%m/%d",
43
+ first_day_of_the_week: int = 1,
44
+ style: Optional[Union[str, Dict[str, str]]] = None,
45
+ classes: Optional[List[str]] = None,
46
+ date_picker_type: str = "date",
47
+ min_date: Optional[str] = None,
48
+ max_date: Optional[str] = None,
49
+ ):
50
+ """
51
+ Show a textfield, which when clicked, opens a datepicker. The input date should be of type `datetime.date`.
52
+
53
+ ## Basic Example
54
+
55
+ ```solara
56
+ import solara
57
+ import solara.lab
58
+ import datetime as dt
59
+
60
+
61
+ @solara.component
62
+ def Page():
63
+ date = solara.use_reactive(dt.date.today())
64
+
65
+ solara.lab.InputDate(date)
66
+ solara.Text(str(date.value))
67
+ ```
68
+
69
+ ## Arguments
70
+
71
+ * value: Reactive variable of type `datetime.date`, or `None`. This date is selected the first time the component is rendered.
72
+ * on_value: a callback function for when value changes. The callback function receives the new value as an argument.
73
+ * label: Text used to label the text field that triggers the datepicker.
74
+ * children: List of Elements to be rendered under the calendar. If empty, a close button is rendered.
75
+ * open_value: Controls and communicates the state of the datepicker. If True, the datepicker is open. If False, the datepicker is closed.
76
+ Intended to be used in conjunction with a custom set of controls to close the datepicker.
77
+ * on_open_value: a callback function for when open_value changes. Also receives the new value as an argument.
78
+ * optional: Determines whether to show an error when value is `None`. If `True`, no error is shown.
79
+ * date_format: Sets the format of the date displayed in the text field. Defaults to `"%Y/%m/%d"`. For more information, see
80
+ <a href="https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes" target="_blank">the Python documentation</a>.
81
+ * first_day_of_the_week: Sets the first day of the week, as an `int` starting count from Sunday (`=0`). Defaults to `1`, which is Monday.
82
+ * style: CSS style to apply to the text field. Either a string or a dictionary of CSS properties (i.e. `{"property": "value"}`).
83
+ * classes: List of CSS classes to apply to the text field.
84
+ * date_picker_type: Sets the type of the datepicker. Use `"date"` for date selection or `"month"` for month selection. Defaults to `"date"`.
85
+ * min_date: Earliest allowed date/month (ISO 8601 format). If not specified, there is no limit.
86
+ * max_date: Latest allowed date/month (ISO 8601 format). If not specified, there is no limit.
87
+ """
88
+ value_reactive = solara.use_reactive(value, on_value) # type: ignore
89
+ del value, on_value
90
+ datepicker_is_open = solara.use_reactive(open_value, on_open_value) # type: ignore
91
+ del open_value, on_open_value
92
+
93
+ if date_picker_type == "date":
94
+ internal_date_format = "%Y-%m-%d"
95
+ elif date_picker_type == "month":
96
+ internal_date_format = "%Y-%m"
97
+ else:
98
+ raise ValueError("date_picker_type must be either 'date' or 'month'.")
99
+
100
+ def set_date_typed_cast(value: Optional[str]):
101
+ if value:
102
+ try:
103
+ date_value = dt.datetime.strptime(value, date_format).date()
104
+ return date_value
105
+ except ValueError:
106
+ raise ValueError(f"Date {value} does not match format {date_format.replace('%', '')}")
107
+ elif optional:
108
+ return None
109
+ else:
110
+ raise ValueError("Date cannot be empty")
111
+
112
+ def date_to_str(date: Optional[dt.date]) -> str:
113
+ if date is not None:
114
+ return date.strftime(date_format)
115
+ return ""
116
+
117
+ def set_date_cast(new_value: Optional[str]):
118
+ if new_value:
119
+ date_value = dt.datetime.strptime(new_value, internal_date_format).date()
120
+ datepicker_is_open.set(False)
121
+ value_reactive.value = date_value
122
+
123
+ def standard_strfy(date: Optional[dt.date]):
124
+ if date is None:
125
+ return None
126
+ else:
127
+ return date.strftime(internal_date_format)
128
+
129
+ date_standard_str = standard_strfy(value_reactive.value)
130
+
131
+ style_flat = solara.util._flatten_style(style)
132
+
133
+ internal_value, error_message, set_value_cast = _use_input_type(value_reactive, set_date_typed_cast, date_to_str)
134
+
135
+ if error_message:
136
+ label += f" ({error_message})"
137
+ input = solara.v.TextField(
138
+ label=label,
139
+ v_model=internal_value,
140
+ on_v_model=set_value_cast,
141
+ append_icon="mdi-calendar",
142
+ error=bool(error_message),
143
+ style_="min-width: 290px;" + style_flat,
144
+ class_=", ".join(classes) if classes else "",
145
+ )
146
+
147
+ use_close_menu(input, datepicker_is_open)
148
+
149
+ with solara.lab.Menu(
150
+ activator=input,
151
+ close_on_content_click=False,
152
+ open_value=datepicker_is_open,
153
+ use_activator_width=False,
154
+ ):
155
+ with solara.v.DatePicker(
156
+ v_model=date_standard_str,
157
+ on_v_model=set_date_cast,
158
+ first_day_of_week=first_day_of_the_week,
159
+ style_="width: 100%;",
160
+ max=max_date,
161
+ min=min_date,
162
+ type=date_picker_type,
163
+ ):
164
+ if len(children) > 0:
165
+ solara.display(*children)
166
+
167
+
168
+ @solara.component
169
+ def InputDateRange(
170
+ value: Union[solara.Reactive[Tuple[Optional[dt.date], Optional[dt.date]]], Tuple[Optional[dt.date], Optional[dt.date]]],
171
+ on_value: Optional[Callable[[Optional[Tuple[Optional[dt.date], Optional[dt.date]]]], None]] = None,
172
+ label: str = "Select dates",
173
+ children: List[solara.Element] = [],
174
+ open_value: Union[solara.Reactive[bool], bool] = False,
175
+ on_open_value: Optional[Callable[[bool], None]] = None,
176
+ optional: bool = False,
177
+ date_format: str = "%Y/%m/%d",
178
+ first_day_of_the_week: int = 1,
179
+ style: Optional[Union[str, Dict[str, str]]] = None,
180
+ classes: Optional[List[str]] = None,
181
+ date_picker_type: str = "date",
182
+ min_date: Optional[str] = None,
183
+ max_date: Optional[str] = None,
184
+ sort: Optional[bool] = False,
185
+ ):
186
+ """
187
+ Show a textfield, which when clicked, opens a datepicker that allows users to select a range of dates by choosing a starting and ending date.
188
+ The input dates should be stored in a reactive tuple of type `datetime.date`. The list should contain either precisely two elements.
189
+ For an empty pre-selection of dates, pass a reactive empty list.
190
+
191
+ ## Basic Example
192
+
193
+ ```solara
194
+ import solara
195
+ import solara.lab
196
+ import datetime as dt
197
+
198
+
199
+ @solara.component
200
+ def Page():
201
+ dates = solara.use_reactive(tuple([dt.date.today(), dt.date.today() + dt.timedelta(days=1)]))
202
+
203
+ solara.lab.InputDateRange(dates)
204
+ solara.Text(str(dates.value))
205
+ ```
206
+
207
+ ## Arguments
208
+
209
+ * value: Tuple with elements of type `datetime.date`. For an empty pre-selection of dates, pass an empty tuple.
210
+ * on_value: a callback function for when value changes. The callback function receives the new value as an argument.
211
+ * label: Text used to label the text field that triggers the datepicker.
212
+ * children: List of Elements to be rendered under the calendar. If empty, a close button is rendered.
213
+ * open_value: Controls and communicates the state of the datepicker. If True, the datepicker is open. If False, the datepicker is closed.
214
+ Intended to be used in conjunction with a custom set of controls to close the datepicker.
215
+ * on_open_value: a callback function for when open_value changes. Also receives the new value as an argument.
216
+ * date_format: Sets the format of the date displayed in the text field. Defaults to `"%Y/%m/%d"`. For more information,
217
+ see <a href="https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes" target="_blank">the Python documentation</a>.
218
+ * optional: Determines whether go show an error when value is `None`. If `True`, no error is shown.
219
+ * first_day_of_the_week: Sets the first day of the week, as an `int` starting count from Sunday (`=0`). Defaults to `1`, which is Monday.
220
+ * style: CSS style to apply to the text field. Either a string or a dictionary of CSS properties (i.e. `{"property": "value"}`).
221
+ * classes: List of CSS classes to apply to the text field.
222
+ * date_picker_type: Sets the type of the datepicker. Use `"date"` for date selection or `"month"` for month selection. Defaults to `"date"`.
223
+ * min_date: Earliest allowed date/month (ISO 8601 format). If not specified, there is no limit.
224
+ * max_date: Latest allowed date/month (ISO 8601 format). If not specified, there is no limit.
225
+ * sort: If True, selected dates will be sorted in ascending order, regardless of the order they were picked. If False, preserves the order the
226
+ dates were selected.
227
+
228
+ ## A More Advanced Example
229
+
230
+ ```solara
231
+ import solara
232
+ import solara.lab
233
+ import datetime as dt
234
+
235
+
236
+ @solara.component
237
+ def Page():
238
+ date = solara.use_reactive(tuple([dt.date.today(), None]))
239
+ range_is_open = solara.use_reactive(False)
240
+ stay_length = solara.use_reactive(1)
241
+
242
+ def set_end_date(value):
243
+ if value and value[0]:
244
+ value = value[0]
245
+ second_date = value + dt.timedelta(days=stay_length.value)
246
+ date.set([value, second_date])
247
+
248
+ def book():
249
+ # Do some stuff here
250
+ range_is_open.set(False)
251
+
252
+ solara.use_memo(lambda: set_end_date(date.value), [stay_length.value])
253
+
254
+ with solara.Column(style="width: 400px;"):
255
+ solara.IntSlider("Length of stay", stay_length, min=1, max=10)
256
+ with solara.lab.InputDateRange(
257
+ date,
258
+ on_value=set_end_date,
259
+ open_value=range_is_open,
260
+ ):
261
+ with solara.Row(justify="end", style="width: 100%;"):
262
+ solara.Button(
263
+ label="Book",
264
+ color="primary",
265
+ on_click=book,
266
+ )
267
+
268
+ ```
269
+ """
270
+ value_reactive = solara.use_reactive(value, on_value) # type: ignore
271
+ del value, on_value
272
+
273
+ if date_picker_type == "date":
274
+ internal_date_format = "%Y-%m-%d"
275
+ elif date_picker_type == "month":
276
+ internal_date_format = "%Y-%m"
277
+ else:
278
+ raise ValueError("date_picker_type must be either 'date' or 'month'.")
279
+
280
+ date_standard_strings = [date.strftime(internal_date_format) for date in value_reactive.value if date is not None]
281
+ datepicker_is_open = solara.use_reactive(open_value, on_open_value) # type: ignore
282
+ del open_value, on_open_value
283
+ style_flat = solara.util._flatten_style(style)
284
+
285
+ def dates_to_string(dates: Tuple[Optional[dt.date], Optional[dt.date]]):
286
+ string_dates = [date.strftime(date_format) if date is not None else "" for date in dates]
287
+ if (len(dates) < 2 or dates[1] is None) and not optional:
288
+ return string_dates[0], f"Please select two {date_picker_type}s"
289
+ return " - ".join(string_dates), None
290
+
291
+ def set_dates_cast(values):
292
+ date_value = cast(
293
+ Tuple[Optional[dt.date], Optional[dt.date]],
294
+ tuple([(dt.datetime.strptime(item, internal_date_format).date() if item is not None else None) for item in values]),
295
+ )
296
+ if len(date_value) > 1 and date_value[1] is not None:
297
+ datepicker_is_open.set(False)
298
+
299
+ if sort:
300
+ date_value = cast(Tuple[dt.date, dt.date], tuple(sorted(date_value)))
301
+
302
+ value_reactive.value = date_value
303
+
304
+ string_dates, error_message = dates_to_string(value_reactive.value)
305
+
306
+ if error_message:
307
+ label += f" ({error_message})"
308
+ input = solara.v.TextField(
309
+ label=label,
310
+ v_model=string_dates,
311
+ append_icon="mdi-calendar",
312
+ error=bool(error_message),
313
+ style_="min-width: 290px;" + style_flat,
314
+ readonly=True,
315
+ class_=", ".join(classes) if classes else "",
316
+ )
317
+
318
+ # We include closing on tab in case users want to skip the field with tab
319
+ use_close_menu(input, datepicker_is_open)
320
+
321
+ with solara.lab.Menu(
322
+ activator=input,
323
+ close_on_content_click=False,
324
+ open_value=datepicker_is_open,
325
+ use_activator_width=False,
326
+ ):
327
+ with solara.v.DatePicker(
328
+ v_model=date_standard_strings,
329
+ on_v_model=set_dates_cast,
330
+ range=True,
331
+ first_day_of_week=first_day_of_the_week,
332
+ style_="width: 100%;",
333
+ max=max_date,
334
+ min=min_date,
335
+ type=date_picker_type,
336
+ ):
337
+ if len(children) > 0:
338
+ for el in children:
339
+ solara.display(el)
@@ -0,0 +1,133 @@
1
+ import datetime as dt
2
+ from typing import Callable, Dict, List, Optional, Union
3
+
4
+ import solara
5
+ import solara.lab
6
+ from solara.lab.components.input_date import use_close_menu
7
+ from solara.components.input import _use_input_type
8
+
9
+
10
+ @solara.component
11
+ def InputTime(
12
+ value: Union[solara.Reactive[Optional[dt.time]], Optional[dt.time]],
13
+ on_value: Optional[Callable[[Optional[dt.time]], None]] = None,
14
+ label: str = "Pick a time",
15
+ children: List[solara.Element] = [],
16
+ open_value: Union[solara.Reactive[bool], bool] = False,
17
+ on_open_value: Optional[Callable[[bool], None]] = None,
18
+ optional: bool = False,
19
+ twelve_hour_clock: bool = False,
20
+ use_seconds: bool = False,
21
+ allowed_minutes: Optional[List[int]] = None,
22
+ style: Optional[Union[str, Dict[str, str]]] = None,
23
+ classes: Optional[List[str]] = None,
24
+ ):
25
+ """
26
+ Show a textfield, which when clicked, opens a timepicker. The input time should be of type `datetime.time`.
27
+
28
+ ## Basic Example
29
+
30
+ ```solara {pycafe-link}
31
+ import solara
32
+ import solara.lab
33
+ import datetime as dt
34
+
35
+
36
+ @solara.component
37
+ def Page():
38
+ time = solara.use_reactive(dt.time(12, 0))
39
+
40
+ solara.lab.InputTime(time, allowed_minutes=[0, 15, 30, 45])
41
+ solara.Text(str(time.value))
42
+ ```
43
+
44
+ ## Arguments
45
+
46
+ * value: Reactive variable of type `datetime.time`, or `None`. This time is selected the first time the component is rendered.
47
+ * on_value: a callback function for when value changes. The callback function receives the new value as an argument.
48
+ * label: Text used to label the text field that triggers the timepicker.
49
+ * children: List of Elements to be rendered under the timepicker. If empty, a close button is rendered.
50
+ * open_value: Controls and communicates the state of the timepicker. If True, the timepicker is open. If False, the timepicker is closed.
51
+ Intended to be used in conjunction with a custom set of controls to close the timepicker.
52
+ * on_open_value: a callback function for when open_value changes. Also receives the new value as an argument.
53
+ * optional: Determines whether to show an error when value is `None`. If `True`, no error is shown.
54
+ * twelve_hour_clock: If `True`, the timepicker will display in 12-hour format. If `False`, the timepicker will display in 24-hour format.
55
+ * use_seconds: If `True`, the timepicker will allow input of seconds.
56
+ * allowed_minutes: List of allowed minutes for the timepicker. Restricts the input to specific minute intervals.
57
+ * style: CSS style to apply to the text field. Either a string or a dictionary of CSS properties (i.e. `{"property": "value"}`).
58
+ * classes: List of CSS classes to apply to the text field.
59
+ """
60
+ time_format_internal = f"%H:%M{':%S' if use_seconds else ''}"
61
+ time_format_display = f"%H:%M{':%S' if use_seconds else ''}"
62
+ if twelve_hour_clock:
63
+ time_format_display = f"%I:%M{':%S' if use_seconds else ''} %p"
64
+ value_reactive = solara.use_reactive(value, on_value) # type: ignore
65
+ del value, on_value
66
+ timepicker_is_open = solara.use_reactive(open_value, on_open_value) # type: ignore
67
+ del open_value, on_open_value
68
+
69
+ def set_time_typed_cast(value: Optional[str]):
70
+ if value:
71
+ try:
72
+ time_value = dt.datetime.strptime(value, time_format_display).time()
73
+ return time_value
74
+ except ValueError:
75
+ raise ValueError(f"Time {value} does not match format {time_format_display.replace('%', '')}")
76
+ elif optional:
77
+ return None
78
+ else:
79
+ raise ValueError("Time cannot be empty")
80
+
81
+ def time_to_str(time: Optional[dt.time]) -> str:
82
+ if time is not None:
83
+ return time.strftime(time_format_display)
84
+ return ""
85
+
86
+ def set_time_cast(new_value: Optional[str]):
87
+ if new_value:
88
+ time_value = dt.datetime.strptime(new_value, time_format_internal).time()
89
+ value_reactive.value = time_value
90
+
91
+ def standard_strfy(time: Optional[dt.time]):
92
+ if time is None:
93
+ return None
94
+ else:
95
+ return time.strftime(time_format_internal)
96
+
97
+ time_standard_str = standard_strfy(value_reactive.value)
98
+
99
+ style_flat = solara.util._flatten_style(style)
100
+
101
+ internal_value, error_message, set_value_cast = _use_input_type(value_reactive, set_time_typed_cast, time_to_str)
102
+
103
+ if error_message:
104
+ label += f" ({error_message})"
105
+ input = solara.v.TextField(
106
+ label=label,
107
+ v_model=internal_value,
108
+ on_v_model=set_value_cast,
109
+ append_icon="mdi-clock",
110
+ error=bool(error_message),
111
+ style_="min-width: 290px;" + style_flat,
112
+ class_=", ".join(classes) if classes else "",
113
+ )
114
+
115
+ use_close_menu(input, timepicker_is_open)
116
+
117
+ with solara.lab.Menu(
118
+ activator=input,
119
+ close_on_content_click=False,
120
+ open_value=timepicker_is_open,
121
+ use_activator_width=False,
122
+ ):
123
+ with solara.v.TimePicker(
124
+ ampm_in_title=twelve_hour_clock,
125
+ v_model=time_standard_str,
126
+ on_v_model=set_time_cast,
127
+ format="24hr" if not twelve_hour_clock else "ampm",
128
+ allowed_minutes=allowed_minutes,
129
+ use_seconds=use_seconds,
130
+ style_="width: 100%;",
131
+ ):
132
+ if len(children) > 0:
133
+ solara.display(*children)
@@ -0,0 +1,181 @@
1
+ from typing import Callable, Dict, List, Optional, Union
2
+
3
+ import solara
4
+ from solara.components.component_vue import component_vue
5
+
6
+
7
+ @component_vue("menu.vue")
8
+ def MenuWidget(
9
+ activator: List[solara.Element],
10
+ show_menu: bool,
11
+ on_show_menu: Optional[Callable] = None,
12
+ close_on_content_click: bool = True,
13
+ children: List[solara.Element] = [],
14
+ style: Optional[str] = None,
15
+ context: bool = False,
16
+ use_absolute: bool = True,
17
+ use_activator_width: bool = True,
18
+ ):
19
+ pass
20
+
21
+
22
+ @solara.component
23
+ def ClickMenu(
24
+ activator: Union[solara.Element, List[solara.Element]],
25
+ open_value: Union[solara.Reactive[bool], bool] = False,
26
+ on_open_value: Optional[Callable] = None,
27
+ children: List[solara.Element] = [],
28
+ style: Optional[Union[str, Dict[str, str]]] = None,
29
+ ):
30
+ """
31
+ Show a pop-up menu by clicking on the `activator` element. The menu appears at the cursor position.
32
+
33
+ ```solara
34
+ import solara
35
+
36
+
37
+ @solara.component
38
+ def Page():
39
+ image_url = "/static/public/beach.jpeg"
40
+ image = solara.Image(image=image_url)
41
+
42
+ with solara.lab.ClickMenu(activator=image):
43
+ with solara.Column(gap="0px"):
44
+ [solara.Button(f"Click me {i}!", text=True) for i in range(5)]
45
+
46
+ ```
47
+
48
+
49
+ ## Arguments
50
+
51
+ * activator: Clicking on this element will open the menu. Accepts either a `solara.Element`, or a list of elements.
52
+ * open_value: Controls and communicates the state of the menu. If True, the menu is open. If False, the menu is closed.
53
+ * on_open_value: Function to call when the menu is opened or closed.
54
+ * menu_contents: List of Elements to be contained in the menu.
55
+ * style: CSS style to apply. Applied directly onto the `v-menu` component.
56
+ """
57
+ open_reactive = solara.use_reactive(open_value, on_open_value)
58
+ del open_value
59
+
60
+ style_flat = solara.util._flatten_style(style)
61
+
62
+ if not isinstance(activator, list):
63
+ activator = [activator]
64
+
65
+ return MenuWidget(
66
+ activator=activator,
67
+ children=children,
68
+ show_menu=open_reactive.value,
69
+ on_show_menu=open_reactive.set,
70
+ style=style_flat,
71
+ )
72
+
73
+
74
+ @solara.component
75
+ def ContextMenu(
76
+ activator: Union[solara.Element, List[solara.Element]],
77
+ open_value: Union[solara.Reactive[bool], bool] = False,
78
+ on_open_value: Optional[Callable] = None,
79
+ children: List[solara.Element] = [],
80
+ style: Optional[Union[str, Dict[str, str]]] = None,
81
+ ):
82
+ """
83
+ Show a context menu by triggering the contextmenu event on the `activator` element. The menu appears at the cursor position.
84
+
85
+ A contextmenu event is typically triggered by clicking the right mouse button, or by pressing the context menu key.
86
+
87
+ ```solara
88
+ import solara
89
+
90
+
91
+ @solara.component
92
+ def Page():
93
+ image_url = "/static/public/beach.jpeg"
94
+ image = solara.Image(image=image_url)
95
+
96
+ with solara.lab.ContextMenu(activator=image):
97
+ with solara.Column(gap="0px"):
98
+ [solara.Button(f"Click me {i}!", text=True) for i in range(5)]
99
+
100
+ ```
101
+
102
+ ## Arguments
103
+
104
+ * activator: Clicking on this element will open the menu. Accepts either a `solara.Element`, or a list of elements.
105
+ * open_value: Controls and communicates the state of the menu. If True, the menu is open. If False, the menu is closed.
106
+ * on_open_value: Function to call when the menu is opened or closed.
107
+ * children: List of Elements to be contained in the menu
108
+ * style: CSS style to apply. Applied directly onto the `v-menu` component.
109
+ """
110
+ open_reactive = solara.use_reactive(open_value, on_open_value)
111
+ del open_value
112
+ style_flat = solara.util._flatten_style(style)
113
+
114
+ if not isinstance(activator, list):
115
+ activator = [activator]
116
+
117
+ return MenuWidget(
118
+ activator=activator,
119
+ children=children,
120
+ show_menu=open_reactive.value,
121
+ on_show_menu=open_reactive.set,
122
+ style=style_flat,
123
+ context=True,
124
+ )
125
+
126
+
127
+ @solara.component
128
+ def Menu(
129
+ activator: Union[solara.Element, List[solara.Element]],
130
+ open_value: Union[solara.Reactive[bool], bool] = False,
131
+ on_open_value: Optional[Callable] = None,
132
+ close_on_content_click: bool = True,
133
+ children: List[solara.Element] = [],
134
+ style: Optional[Union[str, Dict[str, str]]] = None,
135
+ use_activator_width: bool = True,
136
+ ):
137
+ """
138
+ Show a pop-up menu by clicking on the `activator` element. The menu appears below the `activator` element.
139
+
140
+ ```solara
141
+ import solara
142
+
143
+
144
+ @solara.component
145
+ def Page():
146
+ btn = solara.Button("Show suboptions")
147
+
148
+ with solara.lab.Menu(activator=btn):
149
+ with solara.Column(gap="0px"):
150
+ [solara.Button(f"Click me {str(i)}!", text=True) for i in range(5)]
151
+
152
+ ```
153
+
154
+ ## Arguments
155
+
156
+ * activator: Clicking on this element will open the menu. Accepts either a `solara.Element`, or a list of elements.
157
+ * open_value: Controls and communicates the state of the menu. If True, the menu is open. If False, the menu is closed.
158
+ * on_open_value: Function to call when the menu is opened or closed.
159
+ * children: List of Elements to be contained in the menu
160
+ * style: CSS style to apply. Applied directly onto the `v-menu` component.
161
+ * use_activator_width: If True, the menu will have a minimum width equal to the activator element.
162
+ If False, the menu width will be determined by the content.
163
+ """
164
+ open_reactive = solara.use_reactive(open_value, on_open_value)
165
+ del open_value
166
+
167
+ style_flat = solara.util._flatten_style(style)
168
+
169
+ if not isinstance(activator, list):
170
+ activator = [activator]
171
+
172
+ return MenuWidget(
173
+ activator=activator,
174
+ children=children,
175
+ show_menu=open_reactive.value,
176
+ on_show_menu=open_reactive.set,
177
+ close_on_content_click=close_on_content_click,
178
+ style=style_flat,
179
+ use_absolute=False,
180
+ use_activator_width=use_activator_width,
181
+ )
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <v-menu
3
+ v-model="show_menu"
4
+ :absolute="use_absolute"
5
+ offset-y
6
+ :close-on-content-click="close_on_content_click"
7
+ :min-width="use_activator_width ? null : 'auto'"
8
+ >
9
+ <template v-if="context" v-slot:activator="{ on }">
10
+ <div v-for="(element, index) in activator"
11
+ :key="index"
12
+ @contextmenu.prevent="show($event, on)">
13
+ <jupyter-widget :widget="element"></jupyter-widget>
14
+ </div>
15
+ </template>
16
+ <template v-else v-slot:activator="{ on }">
17
+ <jupyter-widget :widget="element" v-for="(element, index) in activator" :key="index" @click.native="on.click"></jupyter-widget>
18
+ </template>
19
+ <v-list v-for="(element, index) in children" :key="index" style="padding: 0;">
20
+ <jupyter-widget :widget="element" :style="style" ></jupyter-widget>
21
+ </v-list>
22
+ </v-menu>
23
+ </template>
24
+
25
+ <script>
26
+ module.exports = {
27
+ methods: {
28
+ show(e, on) {
29
+ // hide menu, and trigger the event on the next tick, otherwise vue does not see
30
+ // `show_menu` changing and will no do any animation
31
+ this.show_menu = false;
32
+ this.$nextTick(() => {
33
+ on.click(e)
34
+ })
35
+ }
36
+ }
37
+ }
38
+ </script>