solara 1.29.0__py2.py3-none-any.whl → 1.30.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. solara/__init__.py +5 -5
  2. solara/__main__.py +6 -2
  3. solara/autorouting.py +79 -38
  4. solara/cache.py +2 -2
  5. solara/checks.html +1 -1
  6. solara/components/__init__.py +1 -1
  7. solara/components/applayout.py +5 -5
  8. solara/components/button.py +4 -4
  9. solara/components/card.py +1 -2
  10. solara/components/component_vue.py +1 -1
  11. solara/components/cross_filter.py +6 -7
  12. solara/components/datatable.py +2 -3
  13. solara/components/figure_altair.py +1 -1
  14. solara/components/file_download.py +2 -2
  15. solara/components/file_drop.py +76 -33
  16. solara/components/file_drop.vue +24 -10
  17. solara/components/head.py +1 -2
  18. solara/components/head_tag.py +2 -3
  19. solara/components/link.py +3 -4
  20. solara/components/meta.py +1 -1
  21. solara/components/misc.py +5 -9
  22. solara/datatypes.py +2 -2
  23. solara/hooks/use_reactive.py +2 -2
  24. solara/lab/components/confirmation_dialog.py +1 -1
  25. solara/lab/components/tabs.py +6 -6
  26. solara/reactive.py +1 -1
  27. solara/routing.py +9 -8
  28. solara/server/app.py +44 -1
  29. solara/server/assets/style.css +6 -0
  30. solara/server/esm.py +28 -4
  31. solara/server/kernel_context.py +75 -7
  32. solara/server/patch.py +3 -0
  33. solara/server/reload.py +2 -2
  34. solara/server/server.py +3 -3
  35. solara/server/settings.py +1 -0
  36. solara/server/starlette.py +66 -33
  37. solara/server/static/solara_bootstrap.py +1 -1
  38. solara/server/templates/solara.html.j2 +62 -42
  39. solara/tasks.py +1 -6
  40. solara/util.py +23 -1
  41. solara/website/assets/custom.css +56 -0
  42. solara/website/components/__init__.py +1 -0
  43. solara/website/components/algolia_api.vue +157 -0
  44. solara/website/components/docs.py +118 -0
  45. solara/website/components/header.py +20 -10
  46. solara/website/components/hero.py +1 -1
  47. solara/website/pages/__init__.py +223 -20
  48. solara/website/pages/apps/jupyter-dashboard-1.py +1 -1
  49. solara/website/pages/apps/multipage/__init__.py +1 -1
  50. solara/website/pages/apps/multipage/page2.py +1 -1
  51. solara/website/pages/apps/scatter.py +21 -7
  52. solara/website/pages/changelog/__init__.py +8 -0
  53. solara/website/pages/{docs/content/95-changelog.md → changelog/changelog.md} +28 -2
  54. solara/website/pages/contact/__init__.py +8 -0
  55. solara/website/pages/documentation/__init__.py +184 -0
  56. solara/website/pages/documentation/advanced/__init__.py +36 -0
  57. solara/website/pages/documentation/advanced/content/00-overview.md +1 -0
  58. solara/website/pages/{docs/content/10-howto/20-multipage.md → documentation/advanced/content/10-howto/10-multipage.md} +4 -5
  59. solara/website/pages/{docs/content/10-howto/30-layout.md → documentation/advanced/content/10-howto/20-layout.md} +21 -21
  60. solara/website/pages/{docs/content/10-howto/80-embed.md → documentation/advanced/content/10-howto/40-embed.md} +1 -1
  61. solara/website/pages/{docs → documentation/advanced}/content/20-understanding/06-ipyvuetify.md +1 -1
  62. solara/website/pages/{docs → documentation/advanced}/content/20-understanding/12-reacton-basics.md +1 -1
  63. solara/website/pages/{docs → documentation/advanced}/content/20-understanding/15-anatomy.md +2 -2
  64. solara/website/pages/{docs → documentation/advanced}/content/20-understanding/18-containers.md +3 -3
  65. solara/website/pages/{docs → documentation/advanced}/content/20-understanding/40-routing.md +9 -9
  66. solara/website/pages/{docs → documentation/advanced}/content/20-understanding/50-solara-server.md +1 -1
  67. solara/website/pages/{docs/content/50-enterprise → documentation/advanced/content/30-enterprise}/10-oauth.md +3 -3
  68. solara/website/pages/{docs/content/10-howto → documentation/advanced/content/40-development}/01-contribute.md +5 -5
  69. solara/website/pages/{docs/content/90-development → documentation/advanced/content/40-development}/10-setup.md +2 -2
  70. solara/website/pages/documentation/advanced/content/__init__.py +0 -0
  71. solara/website/pages/documentation/api/__init__.py +19 -0
  72. solara/website/pages/documentation/api/cross_filter/__init__.py +9 -0
  73. solara/website/pages/documentation/api/hooks/__init__.py +9 -0
  74. solara/website/pages/{api → documentation/api/hooks}/use_effect.md +3 -3
  75. solara/website/pages/{api → documentation/api/hooks}/use_effect.py +2 -1
  76. solara/website/pages/{api → documentation/api/hooks}/use_memo.md +2 -2
  77. solara/website/pages/{api → documentation/api/hooks}/use_memo.py +2 -1
  78. solara/website/pages/{api → documentation/api/hooks}/use_reactive.py +1 -2
  79. solara/website/pages/{api → documentation/api/hooks}/use_state.py +1 -2
  80. solara/website/pages/documentation/api/routing/__init__.py +9 -0
  81. solara/website/pages/{api → documentation/api/routing}/generate_routes.py +1 -2
  82. solara/website/pages/{api → documentation/api/routing}/generate_routes_directory.py +1 -2
  83. solara/website/pages/{api → documentation/api/routing}/use_route.py +2 -2
  84. solara/website/pages/{api → documentation/api/routing}/use_router.py +1 -2
  85. solara/website/pages/documentation/api/utilities/__init__.py +9 -0
  86. solara/website/pages/{api → documentation/api/utilities}/component_vue.py +1 -2
  87. solara/website/pages/{api → documentation/api/utilities}/computed.py +2 -2
  88. solara/website/pages/{api → documentation/api/utilities}/display.py +1 -2
  89. solara/website/pages/{api → documentation/api/utilities}/get_kernel_id.py +2 -2
  90. solara/website/pages/{api → documentation/api/utilities}/get_session_id.py +2 -2
  91. solara/website/pages/{api → documentation/api/utilities}/on_kernel_start.py +9 -3
  92. solara/website/pages/{api → documentation/api/utilities}/reactive.py +1 -2
  93. solara/website/pages/{api → documentation/api/utilities}/widget.py +2 -2
  94. solara/website/pages/documentation/components/__init__.py +12 -0
  95. solara/website/pages/documentation/components/advanced/__init__.py +9 -0
  96. solara/website/pages/documentation/components/data/__init__.py +9 -0
  97. solara/website/pages/documentation/components/enterprise/__init__.py +9 -0
  98. solara/website/pages/{api → documentation/components/enterprise}/avatar.py +1 -2
  99. solara/website/pages/{api → documentation/components/enterprise}/avatar_menu.py +1 -2
  100. solara/website/pages/documentation/components/input/__init__.py +9 -0
  101. solara/website/pages/{api → documentation/components/input}/checkbox.py +1 -2
  102. solara/website/pages/documentation/components/input/file_drop.py +75 -0
  103. solara/website/pages/{api → documentation/components/input}/input.py +1 -2
  104. solara/website/pages/{api → documentation/components/input}/select.py +1 -2
  105. solara/website/pages/{api → documentation/components/input}/slider.py +1 -2
  106. solara/website/pages/{api → documentation/components/input}/switch.py +1 -2
  107. solara/website/pages/{api → documentation/components/input}/togglebuttons.py +1 -2
  108. solara/website/pages/documentation/components/lab/__init__.py +9 -0
  109. solara/website/pages/{api → documentation/components/lab}/chat.py +2 -3
  110. solara/website/pages/{api → documentation/components/lab}/cookies_headers.py +1 -1
  111. solara/website/pages/{api → documentation/components/lab}/input_date.py +1 -2
  112. solara/website/pages/{api → documentation/components/lab}/menu.py +1 -2
  113. solara/website/pages/{api → documentation/components/lab}/task.py +1 -2
  114. solara/website/pages/{api → documentation/components/lab}/theming.py +1 -2
  115. solara/website/pages/{api → documentation/components/lab}/use_task.py +1 -2
  116. solara/website/pages/documentation/components/layout/__init__.py +9 -0
  117. solara/website/pages/{api → documentation/components/layout}/app_bar.py +1 -2
  118. solara/website/pages/{api → documentation/components/layout}/app_bar_title.py +1 -2
  119. solara/website/pages/{api → documentation/components/layout}/card.py +1 -2
  120. solara/website/pages/{api → documentation/components/layout}/card_actions.py +1 -2
  121. solara/website/pages/{api → documentation/components/layout}/griddraggable.py +1 -1
  122. solara/website/pages/{api → documentation/components/layout}/gridfixed.py +1 -1
  123. solara/website/pages/{api → documentation/components/layout}/hbox.py +1 -1
  124. solara/website/pages/{api → documentation/components/layout}/vbox.py +1 -1
  125. solara/website/pages/documentation/components/output/__init__.py +9 -0
  126. solara/website/pages/{api → documentation/components/output}/file_download.py +1 -2
  127. solara/website/pages/{api → documentation/components/output}/image.py +1 -2
  128. solara/website/pages/{api → documentation/components/output}/tooltip.py +1 -2
  129. solara/website/pages/documentation/components/page/__init__.py +9 -0
  130. solara/website/pages/documentation/components/status/__init__.py +9 -0
  131. solara/website/pages/{api → documentation/components/status}/error.py +3 -3
  132. solara/website/pages/{api → documentation/components/status}/info.py +3 -3
  133. solara/website/pages/{api → documentation/components/status}/progress.py +1 -2
  134. solara/website/pages/{api → documentation/components/status}/spinner.py +1 -2
  135. solara/website/pages/{api → documentation/components/status}/success.py +3 -3
  136. solara/website/pages/{api → documentation/components/status}/warning.py +3 -3
  137. solara/website/pages/documentation/components/viz/__init__.py +9 -0
  138. solara/website/pages/{api → documentation/components/viz}/plotly.py +1 -0
  139. solara/website/pages/{examples → documentation/examples}/__init__.py +3 -43
  140. solara/website/pages/{examples → documentation/examples}/general/deploy_model.py +3 -3
  141. solara/website/pages/{examples → documentation/examples}/general/login_oauth.py +1 -1
  142. solara/website/pages/{examples → documentation/examples}/general/vue_component.py +1 -2
  143. solara/website/pages/{examples → documentation/examples}/libraries/altair.py +2 -3
  144. solara/website/pages/{examples → documentation/examples}/libraries/ipyleaflet_advanced.py +1 -1
  145. solara/website/pages/{examples → documentation/examples}/utilities/countdown_timer.py +1 -1
  146. solara/website/pages/{examples → documentation/examples}/visualization/plotly.py +1 -2
  147. solara/website/pages/documentation/faq/__init__.py +11 -0
  148. solara/website/pages/{docs → documentation/getting_started}/__init__.py +7 -1
  149. solara/website/pages/{docs/content/03-quickstart.md → documentation/getting_started/content/00-quickstart.md} +2 -2
  150. solara/website/pages/{docs/content/00-introduction.md → documentation/getting_started/content/01-introduction.md} +16 -16
  151. solara/website/pages/{docs → documentation/getting_started}/content/02-installing.md +1 -1
  152. solara/website/pages/documentation/getting_started/content/04-tutorials/00-overview.md +9 -0
  153. solara/website/pages/{docs/content/04-tutorial → documentation/getting_started/content/04-tutorials}/20-web-app.md +4 -4
  154. solara/website/pages/{docs/content/04-tutorial → documentation/getting_started/content/04-tutorials}/30-ipywidgets.md +9 -9
  155. solara/website/pages/{docs/content/04-tutorial → documentation/getting_started/content/04-tutorials}/40-streamlit.md +13 -13
  156. solara/website/pages/{docs/content/04-tutorial → documentation/getting_started/content/04-tutorials}/50-dash.md +3 -3
  157. solara/website/pages/{docs/content/04-tutorial → documentation/getting_started/content/04-tutorials}/_data_science.ipynb +5 -5
  158. solara/website/pages/documentation/getting_started/content/05-fundamentals/00-overview.md +7 -0
  159. solara/website/pages/{docs/content/07-fundamentals → documentation/getting_started/content/05-fundamentals}/10-components.md +2 -2
  160. solara/website/pages/{docs/content/07-fundamentals → documentation/getting_started/content/05-fundamentals}/50-state-management.md +3 -3
  161. solara/website/pages/documentation/getting_started/content/06-reference/00-overview.md +3 -0
  162. solara/website/pages/{docs/content/15-reference → documentation/getting_started/content/06-reference}/41-asset-files.md +1 -1
  163. solara/website/pages/{docs/content/15-reference → documentation/getting_started/content/06-reference}/60-static-site-generation.md +1 -1
  164. solara/website/pages/{docs/content/15-reference → documentation/getting_started/content/06-reference}/70-search.md +1 -1
  165. solara/website/pages/{docs/content/15-reference → documentation/getting_started/content/06-reference}/80-reloading.md +3 -3
  166. solara/website/pages/{docs/content/15-reference → documentation/getting_started/content/06-reference}/95-caching.md +1 -1
  167. solara/website/pages/documentation/getting_started/content/07-deploying/00-overview.md +3 -0
  168. solara/website/pages/{docs/content/30-deploying → documentation/getting_started/content/07-deploying}/10-self-hosted.md +3 -3
  169. solara/website/pages/{docs/content/30-deploying → documentation/getting_started/content/07-deploying}/20-cloud-hosted.md +1 -1
  170. solara/website/pages/documentation/getting_started/content/__init__.py +0 -0
  171. solara/website/pages/showcase/__init__.py +1 -1
  172. solara/website/pages/showcase/domino_code_assist.py +1 -1
  173. solara/website/pages/showcase/solara_dev.py +1 -1
  174. solara/website/public/social/discord.svg +1 -0
  175. solara/website/public/social/github.svg +1 -0
  176. solara/website/public/social/twitter.svg +3 -0
  177. {solara-1.29.0.dist-info → solara-1.30.0.dist-info}/METADATA +8 -7
  178. solara-1.30.0.dist-info/RECORD +438 -0
  179. {solara-1.29.0.dist-info → solara-1.30.0.dist-info}/WHEEL +1 -1
  180. solara/website/pages/api/__init__.py +0 -292
  181. solara/website/pages/api/default_layout.py +0 -16
  182. solara/website/pages/api/file_drop.py +0 -36
  183. solara/website/pages/docs/content/04-tutorial/00-overview.md +0 -9
  184. solara/website/pages/docs/content/07-fundamentals/00-overview.md +0 -7
  185. solara/website/pages/docs/content/15-reference/00-overview.md +0 -6
  186. solara/website/pages/docs/content/30-deploying/00-overview.md +0 -3
  187. solara-1.29.0.data/data/prefix/etc/jupyter/jupyter_notebook_config.d/solara.json +0 -7
  188. solara-1.29.0.data/data/prefix/etc/jupyter/jupyter_server_config.d/solara.json +0 -7
  189. solara-1.29.0.dist-info/RECORD +0 -413
  190. /solara/website/pages/{docs/content/99-contact.md → contact/contact.md} +0 -0
  191. /solara/website/pages/{docs → documentation/advanced}/content/10-howto/00-overview.md +0 -0
  192. /solara/website/pages/{docs/content/10-howto/50-testing.md → documentation/advanced/content/10-howto/30-testing.md} +0 -0
  193. /solara/website/pages/{docs/content/10-howto/51-debugging.md → documentation/advanced/content/10-howto/31-debugging.md} +0 -0
  194. /solara/website/pages/{docs/content/10-howto/ipywidget_libraries.md → documentation/advanced/content/10-howto/50-ipywidget_libraries.md} +0 -0
  195. /solara/website/pages/{docs → documentation/advanced}/content/20-understanding/00-introduction.md +0 -0
  196. /solara/website/pages/{docs → documentation/advanced}/content/20-understanding/05-ipywidgets.md +0 -0
  197. /solara/website/pages/{docs → documentation/advanced}/content/20-understanding/10-reacton.md +0 -0
  198. /solara/website/pages/{docs → documentation/advanced}/content/20-understanding/17-rules-of-hooks.md +0 -0
  199. /solara/website/pages/{docs → documentation/advanced}/content/20-understanding/20-solara.md +0 -0
  200. /solara/website/pages/{docs → documentation/advanced}/content/20-understanding/60-voila.md +0 -0
  201. /solara/website/pages/{docs/content/50-enterprise → documentation/advanced/content/30-enterprise}/00-overview.md +0 -0
  202. /solara/website/pages/{docs/content/__init__.py → documentation/advanced/content/40-development/00-overview.md} +0 -0
  203. /solara/website/pages/{api → documentation/api/cross_filter}/cross_filter_dataframe.py +0 -0
  204. /solara/website/pages/{api → documentation/api/cross_filter}/cross_filter_report.py +0 -0
  205. /solara/website/pages/{api → documentation/api/cross_filter}/cross_filter_select.py +0 -0
  206. /solara/website/pages/{api → documentation/api/cross_filter}/cross_filter_slider.py +0 -0
  207. /solara/website/pages/{api → documentation/api/hooks}/use_cross_filter.py +0 -0
  208. /solara/website/pages/{api → documentation/api/hooks}/use_dark_effective.py +0 -0
  209. /solara/website/pages/{api → documentation/api/hooks}/use_exception.py +0 -0
  210. /solara/website/pages/{api → documentation/api/hooks}/use_previous.py +0 -0
  211. /solara/website/pages/{api → documentation/api/hooks}/use_state_or_update.py +0 -0
  212. /solara/website/pages/{api → documentation/api/hooks}/use_thread.md +0 -0
  213. /solara/website/pages/{api → documentation/api/hooks}/use_thread.py +0 -0
  214. /solara/website/pages/{api → documentation/api/hooks}/use_trait_observe.py +0 -0
  215. /solara/website/pages/{api → documentation/api/routing}/resolve_path.py +0 -0
  216. /solara/website/pages/{api → documentation/api/routing}/route.py +0 -0
  217. /solara/website/pages/{api → documentation/api/utilities}/memoize.py +0 -0
  218. /solara/website/pages/{api → documentation/components/advanced}/link.py +0 -0
  219. /solara/website/pages/{api → documentation/components/advanced}/meta.py +0 -0
  220. /solara/website/pages/{api → documentation/components/advanced}/style.py +0 -0
  221. /solara/website/pages/{api → documentation/components}/common.py +0 -0
  222. /solara/website/pages/{api → documentation/components/data}/dataframe.py +0 -0
  223. /solara/website/pages/{api → documentation/components/data}/pivot_table.py +0 -0
  224. /solara/website/pages/{api → documentation/components/input}/button.py +0 -0
  225. /solara/website/pages/{api → documentation/components/input}/file_browser.py +0 -0
  226. /solara/website/pages/{api → documentation/components/lab}/confirmation_dialog.py +0 -0
  227. /solara/website/pages/{api → documentation/components/lab}/tab.py +0 -0
  228. /solara/website/pages/{api → documentation/components/lab}/tabs.py +0 -0
  229. /solara/website/pages/{api → documentation/components/layout}/app_layout.py +0 -0
  230. /solara/website/pages/{api → documentation/components/layout}/column.py +0 -0
  231. /solara/website/pages/{api → documentation/components/layout}/columns.py +0 -0
  232. /solara/website/pages/{api → documentation/components/layout}/columns_responsive.py +0 -0
  233. /solara/website/pages/{api → documentation/components/layout}/row.py +0 -0
  234. /solara/website/pages/{api → documentation/components/layout}/sidebar.py +0 -0
  235. /solara/website/pages/{api → documentation/components/output}/html.py +0 -0
  236. /solara/website/pages/{api → documentation/components/output}/markdown.py +0 -0
  237. /solara/website/pages/{api → documentation/components/output}/markdown_editor.py +0 -0
  238. /solara/website/pages/{api → documentation/components/output}/sql_code.py +0 -0
  239. /solara/website/pages/{api → documentation/components/page}/head.py +0 -0
  240. /solara/website/pages/{api → documentation/components/page}/title.py +0 -0
  241. /solara/website/pages/{api → documentation/components/viz}/altair.py +0 -0
  242. /solara/website/pages/{api → documentation/components/viz}/echarts.py +0 -0
  243. /solara/website/pages/{api → documentation/components/viz}/matplotlib.py +0 -0
  244. /solara/website/pages/{api → documentation/components/viz}/plotly_express.py +0 -0
  245. /solara/website/pages/{examples → documentation/examples}/ai/__init__.py +0 -0
  246. /solara/website/pages/{examples → documentation/examples}/ai/chatbot.py +0 -0
  247. /solara/website/pages/{examples → documentation/examples}/ai/tokenizer.py +0 -0
  248. /solara/website/pages/{examples → documentation/examples}/basics/__init__.py +0 -0
  249. /solara/website/pages/{examples → documentation/examples}/basics/sine.py +0 -0
  250. /solara/website/pages/{examples → documentation/examples}/fullscreen/__init__.py +0 -0
  251. /solara/website/pages/{examples → documentation/examples}/fullscreen/authorization.py +0 -0
  252. /solara/website/pages/{examples → documentation/examples}/fullscreen/layout_demo.py +0 -0
  253. /solara/website/pages/{examples → documentation/examples}/fullscreen/multipage.py +0 -0
  254. /solara/website/pages/{examples → documentation/examples}/fullscreen/scatter.py +0 -0
  255. /solara/website/pages/{examples → documentation/examples}/fullscreen/scrolling.py +0 -0
  256. /solara/website/pages/{examples → documentation/examples}/fullscreen/tutorial_streamlit.py +0 -0
  257. /solara/website/pages/{examples → documentation/examples}/general/__init__.py +0 -0
  258. /solara/website/pages/{examples → documentation/examples}/general/custom_storage.py +0 -0
  259. /solara/website/pages/{examples → documentation/examples}/general/live_update.py +0 -0
  260. /solara/website/pages/{examples → documentation/examples}/general/mycard.vue +0 -0
  261. /solara/website/pages/{examples → documentation/examples}/general/pokemon_search.py +0 -0
  262. /solara/website/pages/{examples → documentation/examples}/ipycanvas.py +0 -0
  263. /solara/website/pages/{examples → documentation/examples}/libraries/__init__.py +0 -0
  264. /solara/website/pages/{examples → documentation/examples}/libraries/bqplot.py +0 -0
  265. /solara/website/pages/{examples → documentation/examples}/libraries/ipyleaflet.py +0 -0
  266. /solara/website/pages/{examples → documentation/examples}/utilities/__init__.py +0 -0
  267. /solara/website/pages/{examples → documentation/examples}/utilities/calculator.py +0 -0
  268. /solara/website/pages/{examples → documentation/examples}/utilities/todo.py +0 -0
  269. /solara/website/pages/{examples → documentation/examples}/visualization/__init__.py +0 -0
  270. /solara/website/pages/{examples → documentation/examples}/visualization/annotator.py +0 -0
  271. /solara/website/pages/{examples → documentation/examples}/visualization/linked_views.py +0 -0
  272. /solara/website/pages/{docs → documentation/faq}/content/99-faq.md +0 -0
  273. /solara/website/pages/{docs/content/04-tutorial → documentation/getting_started/content/04-tutorials}/10_data_science.py +0 -0
  274. /solara/website/pages/{docs/content/04-tutorial → documentation/getting_started/content/04-tutorials}/60-jupyter-dashboard-part1.py +0 -0
  275. /solara/website/pages/{docs/content/04-tutorial → documentation/getting_started/content/04-tutorials}/SF_crime_sample.csv.gz +0 -0
  276. /solara/website/pages/{docs/content/04-tutorial → documentation/getting_started/content/04-tutorials}/_jupyter_dashboard_1.ipynb +0 -0
  277. /solara/website/pages/{docs/content/15-reference → documentation/getting_started/content/06-reference}/40-static_files.md +0 -0
  278. /solara/website/pages/{docs/content/15-reference → documentation/getting_started/content/06-reference}/90-notebook-support.md +0 -0
  279. /solara/website/pages/{docs/content/lab → documentation/getting_started/content/08-lab}/00-what-is-lab.md +0 -0
  280. /solara/website/pages/{docs → documentation/getting_started}/content/90-troubleshoot.md +0 -0
  281. {solara-1.29.0.data → solara-1.30.0.data}/data/etc/jupyter/jupyter_notebook_config.d/solara.json +0 -0
  282. {solara-1.29.0.data → solara-1.30.0.data}/data/etc/jupyter/jupyter_server_config.d/solara.json +0 -0
  283. {solara-1.29.0.dist-info → solara-1.30.0.dist-info}/entry_points.txt +0 -0
  284. {solara-1.29.0.dist-info → solara-1.30.0.dist-info}/licenses/LICENSE +0 -0
solara/server/settings.py CHANGED
@@ -86,6 +86,7 @@ class Assets(BaseSettings):
86
86
  class Kernel(BaseSettings):
87
87
  cull_timeout: str = "24h"
88
88
  max_count: Optional[int] = None
89
+ threaded: bool = solara.util.has_threads
89
90
 
90
91
  class Config:
91
92
  env_prefix = "solara_kernel_"
@@ -6,7 +6,7 @@ import os
6
6
  import sys
7
7
  import threading
8
8
  import typing
9
- from typing import Any, Dict, List, Optional, Union, cast
9
+ from typing import Any, Dict, List, Optional, Set, Union, cast
10
10
  from uuid import uuid4
11
11
 
12
12
  import anyio
@@ -40,7 +40,7 @@ from starlette.middleware import Middleware
40
40
  from starlette.middleware.authentication import AuthenticationMiddleware
41
41
  from starlette.middleware.gzip import GZipMiddleware
42
42
  from starlette.requests import HTTPConnection, Request
43
- from starlette.responses import HTMLResponse, JSONResponse, Response
43
+ from starlette.responses import HTMLResponse, JSONResponse, RedirectResponse, Response
44
44
  from starlette.routing import Mount, Route, WebSocketRoute
45
45
  from starlette.staticfiles import StaticFiles
46
46
  from starlette.types import Receive, Scope, Send
@@ -96,10 +96,14 @@ class WebsocketDebugInfo:
96
96
  class WebsocketWrapper(websocket.WebsocketWrapper):
97
97
  ws: starlette.websockets.WebSocket
98
98
 
99
- def __init__(self, ws: starlette.websockets.WebSocket, portal: anyio.from_thread.BlockingPortal) -> None:
99
+ def __init__(self, ws: starlette.websockets.WebSocket, portal: Optional[anyio.from_thread.BlockingPortal]) -> None:
100
100
  self.ws = ws
101
101
  self.portal = portal
102
102
  self.to_send: List[Union[str, bytes]] = []
103
+ # following https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task
104
+ # we store a strong reference
105
+ self.tasks: Set[asyncio.Task] = set()
106
+ self.event_loop = asyncio.get_event_loop()
103
107
  if settings.main.experimental_performance:
104
108
  self.task = asyncio.ensure_future(self.process_messages_task())
105
109
 
@@ -114,28 +118,44 @@ class WebsocketWrapper(websocket.WebsocketWrapper):
114
118
  await self.ws.send_text(first)
115
119
 
116
120
  def close(self):
117
- self.portal.call(self.ws.close) # type: ignore
121
+ if self.portal is None:
122
+ asyncio.ensure_future(self.ws.close())
123
+ else:
124
+ self.portal.call(self.ws.close) # type: ignore
118
125
 
119
126
  def send_text(self, data: str) -> None:
120
- if settings.main.experimental_performance:
121
- self.to_send.append(data)
127
+ if self.portal is None:
128
+ task = self.event_loop.create_task(self.ws.send_text(data))
129
+ self.tasks.add(task)
130
+ task.add_done_callback(self.tasks.discard)
122
131
  else:
123
- self.portal.call(self.ws.send_bytes, data) # type: ignore
132
+ if settings.main.experimental_performance:
133
+ self.to_send.append(data)
134
+ else:
135
+ self.portal.call(self.ws.send_bytes, data) # type: ignore
124
136
 
125
137
  def send_bytes(self, data: bytes) -> None:
126
- if settings.main.experimental_performance:
127
- self.to_send.append(data)
138
+ if self.portal is None:
139
+ task = self.event_loop.create_task(self.ws.send_bytes(data))
140
+ self.tasks.add(task)
141
+ task.add_done_callback(self.tasks.discard)
128
142
  else:
129
- self.portal.call(self.ws.send_bytes, data) # type: ignore
143
+ if settings.main.experimental_performance:
144
+ self.to_send.append(data)
145
+ else:
146
+ self.portal.call(self.ws.send_bytes, data) # type: ignore
130
147
 
131
148
  async def receive(self):
132
- if hasattr(self.portal, "start_task_soon"):
133
- # version 3+
134
- fut = self.portal.start_task_soon(self.ws.receive) # type: ignore
149
+ if self.portal is None:
150
+ message = await asyncio.ensure_future(self.ws.receive())
135
151
  else:
136
- fut = self.portal.spawn_task(self.ws.receive) # type: ignore
152
+ if hasattr(self.portal, "start_task_soon"):
153
+ # version 3+
154
+ fut = self.portal.start_task_soon(self.ws.receive) # type: ignore
155
+ else:
156
+ fut = self.portal.spawn_task(self.ws.receive) # type: ignore
137
157
 
138
- message = await asyncio.wrap_future(fut)
158
+ message = await asyncio.wrap_future(fut)
139
159
  if "text" in message:
140
160
  return message["text"]
141
161
  elif "bytes" in message:
@@ -237,35 +257,45 @@ async def _kernel_connection(ws: starlette.websockets.WebSocket):
237
257
  WebsocketDebugInfo.connecting -= 1
238
258
  WebsocketDebugInfo.open += 1
239
259
 
240
- def websocket_thread_runner(ws: starlette.websockets.WebSocket, portal: anyio.from_thread.BlockingPortal):
241
- async def run():
260
+ async def run(ws_wrapper: WebsocketWrapper):
261
+ if kernel_context.async_context_id is not None:
262
+ kernel_context.async_context_id.set(uuid4().hex)
263
+ assert session_id is not None
264
+ assert kernel_id is not None
265
+ telemetry.connection_open(session_id)
266
+ headers_dict: Dict[str, List[str]] = {}
267
+ for k, v in ws.headers.items():
268
+ if k not in headers_dict.keys():
269
+ headers_dict[k] = [v]
270
+ else:
271
+ headers_dict[k].append(v)
272
+ await server.app_loop(ws_wrapper, ws.cookies, headers_dict, session_id, kernel_id, page_id, user)
273
+
274
+ def websocket_thread_runner(ws_wrapper: WebsocketWrapper, portal: anyio.from_thread.BlockingPortal):
275
+ async def run_wrapper():
242
276
  try:
243
- assert session_id is not None
244
- assert kernel_id is not None
245
- telemetry.connection_open(session_id)
246
- headers_dict: Dict[str, List[str]] = {}
247
- for k, v in ws.headers.items():
248
- if k not in headers_dict.keys():
249
- headers_dict[k] = [v]
250
- else:
251
- headers_dict[k].append(v)
252
- await server.app_loop(ws_wrapper, ws.cookies, headers_dict, session_id, kernel_id, page_id, user)
277
+ await run(ws_wrapper)
253
278
  except: # noqa
254
- await portal.stop(cancel_remaining=True)
279
+ if portal is not None:
280
+ await portal.stop(cancel_remaining=True)
255
281
  raise
256
282
  finally:
257
283
  telemetry.connection_close(session_id)
258
284
 
259
285
  # sometimes throws: RuntimeError: Already running asyncio in this thread
260
- anyio.run(run) # type: ignore
286
+ anyio.run(run_wrapper) # type: ignore
261
287
 
262
288
  # this portal allows us to sync call the websocket calls from this current event loop we are in
263
289
  # each websocket however, is handled from a separate thread
264
290
  try:
265
- async with anyio.from_thread.BlockingPortal() as portal:
266
- ws_wrapper = WebsocketWrapper(ws, portal)
267
- thread_return = anyio.to_thread.run_sync(websocket_thread_runner, ws, portal, limiter=limiter) # type: ignore
268
- await thread_return
291
+ if settings.kernel.threaded:
292
+ async with anyio.from_thread.BlockingPortal() as portal:
293
+ ws_wrapper = WebsocketWrapper(ws, portal)
294
+ thread_return = anyio.to_thread.run_sync(websocket_thread_runner, ws_wrapper, portal, limiter=limiter) # type: ignore
295
+ await thread_return
296
+ else:
297
+ ws_wrapper = WebsocketWrapper(ws, None)
298
+ await run(ws_wrapper)
269
299
  finally:
270
300
  if settings.main.experimental_performance:
271
301
  try:
@@ -315,6 +345,9 @@ async def root(request: Request, fullpath: str = ""):
315
345
  request_path = request.url.path
316
346
  if request_path.startswith(root_path):
317
347
  request_path = request_path[len(root_path) :]
348
+ if request_path in server._redirects.keys():
349
+ return RedirectResponse(server._redirects[request_path])
350
+
318
351
  content = server.read_root(request_path, root_path)
319
352
  if content is None:
320
353
  if settings.oauth.private and not request.user.is_authenticated:
@@ -119,7 +119,7 @@ async def main():
119
119
  ]
120
120
  for dep in requirements:
121
121
  await micropip.install(dep, keep_going=True)
122
- await micropip.install("/wheels/solara-1.29.0-py2.py3-none-any.whl", keep_going=True)
122
+ await micropip.install("/wheels/solara-1.30.0-py2.py3-none-any.whl", keep_going=True)
123
123
  import solara
124
124
 
125
125
  el = solara.Warning("lala")
@@ -11,13 +11,11 @@
11
11
 
12
12
  {% block header %}
13
13
 
14
-
15
14
  {{ pre_rendered_css | safe }}
16
-
17
15
  {% if vue3 == True %}
18
- <link href="{{cdn}}/@widgetti/solara-vuetify3-app@5.0.1/dist/main{{ipywidget_major_version}}.css" rel="stylesheet"></link>
16
+ <link href="{{cdn}}/@widgetti/solara-vuetify3-app@5.0.1/dist/main{{ipywidget_major_version}}.css" rel="stylesheet" class="solara-template-css"></link>
19
17
  {% else %}
20
- <link href="{{cdn}}/@widgetti/solara-vuetify-app@10.0.1/dist/main{{ipywidget_major_version}}.css" rel="stylesheet"></link>
18
+ <link href="{{cdn}}/@widgetti/solara-vuetify-app@10.0.1/dist/main{{ipywidget_major_version}}.css" rel="stylesheet" class="solara-template-css"></link>
21
19
  {% endif %}
22
20
 
23
21
 
@@ -27,8 +25,7 @@
27
25
  {{ resources.include_css("/static/highlight.css") }}
28
26
  {{ resources.include_css("/static/highlight-dark.css") }}
29
27
  {{ resources.include_css("/static/assets/style.css") }}
30
- <style id="jupyter-theme-css">
31
- {{ resources.include_css("/static/assets/theme-"~theme.variant~".css") }}
28
+ <style id="jupyter-theme-css" class="solara-template-css">
32
29
  </style>
33
30
  {{ resources.include_css("/static/assets/custom.css") }}
34
31
 
@@ -38,9 +35,24 @@
38
35
  "kernelId": "1234"
39
36
  }
40
37
  </script>
41
- <style>
38
+ <style class="solara-template-css">
42
39
  {% include "loader-"~theme.loader~".css" %}
43
40
  </style>
41
+ <!-- Include Vuetify background colours so static html from SSG renders the right general colour theme
42
+ before first render. We remove these after Vue takes over rendering to avoid collisions -->
43
+ <style id="pre-render-theme">
44
+ .theme--light .v-sheet {
45
+ background-color: #fff;
46
+ border-color: #fff;
47
+ color: rgba(0,0,0,.87)
48
+ }
49
+
50
+ .theme--dark .v-sheet {
51
+ background-color: #1e1e1e;
52
+ border-color: #1e1e1e;
53
+ color: #fff
54
+ }
55
+ </style>
44
56
  {% endblock header %}
45
57
  </head>
46
58
  {% raw -%}
@@ -175,6 +187,38 @@
175
187
  {# next div is used in ssg code to see if vue took over rendering #}
176
188
  <div id="pre-rendered-html-present" style="display: none"></div>
177
189
  </div>
190
+ <script>
191
+ var theme = {{ theme | tojson | safe }}
192
+ function getThemeVariant() {
193
+ if (localStorage.getItem(':solara:theme.variant')) {
194
+ return JSON.parse(localStorage.getItem(':solara:theme.variant'))
195
+ }
196
+ return theme.variant;
197
+ }
198
+ if (localStorage.getItem(':solara:theme.variant')) {
199
+ theme.variant = JSON.parse(localStorage.getItem(':solara:theme.variant'))
200
+ }
201
+ function prefersDarkScheme() {
202
+ return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
203
+ }
204
+ function inDarkMode() {
205
+ if (getThemeVariant() == 'auto') {
206
+ return prefersDarkScheme();
207
+ }
208
+ else {
209
+ return getThemeVariant() == 'dark';
210
+ }
211
+ }
212
+ // Init theme
213
+ let appContainer = document.getElementById('app');
214
+ if (inDarkMode()) {
215
+ appContainer.classList.remove('theme--light');
216
+ appContainer.classList.add('theme--dark');
217
+ } else {
218
+ appContainer.classList.remove('theme--dark');
219
+ appContainer.classList.add('theme--light');
220
+ }
221
+ </script>
178
222
  {% block after_pre_rendered_html %}{% endblock %}
179
223
  {% if vue3 == True %}
180
224
  <link href="{{cdn}}/@widgetti/solara-vuetify3-app@5.0.1/dist/fonts.css" rel="stylesheet"></link>
@@ -194,6 +238,12 @@
194
238
  <script>
195
239
  solara.rootPath = {{ root_path | tojson | safe}};
196
240
  console.log("rootPath", solara.rootPath);
241
+
242
+ async function changeThemeCSS(theme) {
243
+ let css = await fetch(`${solara.rootPath}/static/assets/theme-${theme}.css`).then(r => r.text());
244
+ document.getElementById('jupyter-theme-css').innerHTML = css;
245
+ }
246
+ changeThemeCSS(inDarkMode() ? 'dark' : 'light');
197
247
  </script>
198
248
 
199
249
  {{ resources.include_js("/static/assets/custom.js") }}
@@ -208,27 +258,6 @@
208
258
  solara.production = {{ production | tojson | safe }};
209
259
  const themeVariants = ['light', 'dark', 'auto']
210
260
  solara.preRendered = {{ pre_rendered_html | safe | length | tojson }} > 0
211
- var theme = {{ theme | tojson | safe }}
212
- function getThemeVariant() {
213
- if (localStorage.getItem(':solara:theme.variant')) {
214
- return JSON.parse(localStorage.getItem(':solara:theme.variant'))
215
- }
216
- return theme.variant;
217
- }
218
- if (localStorage.getItem(':solara:theme.variant')) {
219
- theme.variant = JSON.parse(localStorage.getItem(':solara:theme.variant'))
220
- }
221
- function prefersDarkScheme() {
222
- return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
223
- }
224
- function inDarkMode() {
225
- if (getThemeVariant() == 'auto') {
226
- return prefersDarkScheme();
227
- }
228
- else {
229
- return getThemeVariant() == 'dark';
230
- }
231
- }
232
261
  </script>
233
262
 
234
263
  <script>
@@ -256,11 +285,7 @@
256
285
  window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
257
286
  this.$vuetify.theme.dark = inDarkMode();
258
287
  });
259
- if (this.$vuetify.theme.dark) {
260
- this.changeThemeCSS('dark');
261
- } else {
262
- this.changeThemeCSS('light');
263
- }
288
+ document.getElementById('pre-render-theme').remove();
264
289
  },
265
290
  methods: {
266
291
  stateReset() {
@@ -275,10 +300,6 @@
275
300
  reload() {
276
301
  location.reload();
277
302
  },
278
- async changeThemeCSS(theme) {
279
- let css = await fetch(`/static/assets/theme-${theme}.css`).then(r => r.text());
280
- document.getElementById('jupyter-theme-css').innerHTML = css;
281
- }
282
303
  },
283
304
  watch: {
284
305
  kernelBusy: function (value) {
@@ -325,15 +346,14 @@
325
346
  }
326
347
  },
327
348
  '$vuetify.theme.dark': function (value) {
328
- let app = document.getElementById('app');
329
349
  if ( value ) {
330
350
  this.changeThemeCSS('dark');
331
- app.classList.remove('theme--light');
332
- app.classList.add('theme--dark');
351
+ appContainer.classList.remove('theme--light');
352
+ appContainer.classList.add('theme--dark');
333
353
  } else {
334
354
  this.changeThemeCSS('light');
335
- app.classList.remove('theme--dark');
336
- app.classList.add('theme--light');
355
+ appContainer.classList.remove('theme--dark');
356
+ appContainer.classList.add('theme--light');
337
357
  }
338
358
  }
339
359
  },
solara/tasks.py CHANGED
@@ -32,12 +32,7 @@ P = typing_extensions.ParamSpec("P")
32
32
 
33
33
  logger = logging.getLogger("solara.task")
34
34
 
35
- try:
36
- threading.Thread(target=lambda: None).start()
37
- has_threads = True
38
- except RuntimeError:
39
- has_threads = False
40
- has_threads
35
+ has_threads = solara.util.has_threads
41
36
 
42
37
 
43
38
  class TaskState(Enum):
solara/util.py CHANGED
@@ -1,12 +1,15 @@
1
1
  import base64
2
2
  import contextlib
3
+ import gzip
3
4
  import hashlib
5
+ import json
4
6
  import os
5
7
  import sys
6
8
  import threading
7
9
  from collections import abc
8
10
  from pathlib import Path
9
- from typing import TYPE_CHECKING, Dict, List, Tuple, Union
11
+ from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Union
12
+ from urllib.parse import urlencode
10
13
 
11
14
  if TYPE_CHECKING:
12
15
  import numpy as np
@@ -21,6 +24,12 @@ SOLARA_ALLOW_OTHER_TRACER = os.environ.get("SOLARA_ALLOW_OTHER_TRACER", False) i
21
24
  ipyvuetify_major_version = int(ipyvuetify.__version__.split(".")[0])
22
25
  ipywidgets_major = int(ipywidgets.__version__.split(".")[0])
23
26
 
27
+ try:
28
+ threading.Thread(target=lambda: None).start()
29
+ has_threads = True
30
+ except RuntimeError:
31
+ has_threads = False
32
+
24
33
 
25
34
  def github_url(file):
26
35
  rel_path = os.path.relpath(file, Path(solara.__file__).parent.parent)
@@ -28,6 +37,19 @@ def github_url(file):
28
37
  return github_url
29
38
 
30
39
 
40
+ def pycafe_url(*, path: Path, requirements: Optional[List[str]] = None):
41
+ json_object = {"code": path.read_text("utf8")}
42
+ if requirements:
43
+ json_object["requirements"] = "\n".join(requirements)
44
+ json_text = json.dumps(json_object)
45
+ # gzip -> base64
46
+ compressed_json_text = gzip.compress(json_text.encode("utf8"))
47
+ base64_text = base64.b64encode(compressed_json_text).decode("utf8")
48
+ query = urlencode({"c": base64_text})
49
+ base_url = "https://app.py.cafe"
50
+ return f"{base_url}/snippet/solara?{query}"
51
+
52
+
31
53
  def github_edit_url(file):
32
54
  # e.g. https://github.com/widgetti/solara/edit/master/solara/__init__.py
33
55
  rel_path = os.path.relpath(file, Path(solara.__file__).parent.parent)
@@ -27,6 +27,11 @@
27
27
  --dark-color-text: hsla(0,0%,100%,.7);
28
28
  --dark-color-grey: #ababab;
29
29
  --dark-color-grey-light: #202020;
30
+
31
+ --docs-color-grey: #40362E;
32
+ --docs-social-discord: #5865F2;
33
+ --docs-social-github: #333;
34
+ --docs-social-twitter: #000000;
30
35
  }
31
36
 
32
37
  html,
@@ -178,6 +183,56 @@ blockquote p:last-child {
178
183
  background-color: var(--dark-color-primary-lightest);
179
184
  }
180
185
 
186
+ /* API PAGE REFACTOR STYLE */
187
+
188
+ .v-sheet.api-search-container{
189
+ flex-grow: 1;
190
+ }
191
+ .v-sheet.api-search-container .v-input{
192
+ flex-grow: 0;
193
+ }
194
+ .v-sheet.docs-card-container{
195
+ width: 100%;
196
+ padding: 0 10%;
197
+ justify-content: start;
198
+ align-content: center;
199
+ flex-wrap: wrap !important;
200
+ flex-grow: 1;
201
+ row-gap: 20px;
202
+ }
203
+ .v-sheet.docs-card-container > a{
204
+ height: fit-content;
205
+ }
206
+ .v-sheet.docs-card-container > a > .docs-card{
207
+ display: flex;
208
+ width: 20rem;
209
+ height: 12rem;
210
+ border-radius: 16px !important;
211
+ color: var(--color-grey-light);
212
+ }
213
+ .v-sheet.docs-card-container > a .docs-card-icon{
214
+ padding-right: 1.5rem;
215
+ transition: ease padding 0.25s;
216
+ }
217
+ .v-sheet.docs-card-container > a:hover .docs-card-icon{
218
+ color: var(--color-primary);
219
+ padding-right: 0.5rem;
220
+ transition: ease padding 0.25s;
221
+ }
222
+ .component-card{
223
+ display: flex;
224
+ flex-direction: column;
225
+ width: 19rem;
226
+ }
227
+ .social-logo-container{
228
+ display: flex;
229
+ justify-content: center;
230
+ align-items: center;
231
+ width: 4rem;
232
+ height: 4rem;
233
+ border-radius: 8px;
234
+ }
235
+
181
236
  /* vuetify component overrides */
182
237
 
183
238
  .v-btn.solara-docs-button {
@@ -354,6 +409,7 @@ blockquote p:last-child {
354
409
  }
355
410
 
356
411
  .solara-autorouter-content {
412
+ padding-top: 2rem;
357
413
  max-width: 100%;
358
414
  }
359
415
 
@@ -1,3 +1,4 @@
1
+ from .docs import CategoryLayout, Gallery, NoPage, SubCategoryLayout, WithCode # noqa
1
2
  from .header import Header
2
3
  from .hero import Hero
3
4
 
@@ -0,0 +1,157 @@
1
+ <template>
2
+ <v-menu
3
+ v-model="show_results"
4
+ offset-y>
5
+ <template v-slot:activator="{ on }">
6
+ <v-text-field
7
+ v-model="query"
8
+ prepend-inner-icon="mdi-magnify"
9
+ hide-details
10
+ :placeholder="mac ? '⌘K to search' : 'Ctrl+K to search'"
11
+ outlined
12
+ rounded
13
+ clearable
14
+ ref="search"
15
+ style="max-width: 50%; flex-grow: 1;"
16
+ @click="show($event, on);"
17
+ @keyup.enter="item = 0"
18
+ ></v-text-field>
19
+ </template>
20
+ <v-list v-if="results != null && results.length == 0">
21
+ <v-list-item>
22
+ <v-list-item-content>
23
+ {{this.query == "" ? "Start Typing to Search" : "No search results found."}}
24
+ </v-list-item-content>
25
+ </v-list-item>
26
+ </v-list>
27
+ <v-list v-else>
28
+ <v-list-item-group v-model="item">
29
+ <v-list-item v-for="(element, index) in this.results.hits" :key="element['url']">
30
+ <v-list-item-content>
31
+ <v-list-item-title>{{ element.hierarchy[element.type] }}</v-list-item-title>
32
+ </v-list-item-content>
33
+ </v-list-item>
34
+ </v-list-item-group>
35
+ <v-list-item>
36
+ <v-list-item-content>
37
+ <v-list-item-title>And {{ this.results.nbHits - 10}} More...</v-list-item-title>
38
+ </v-list-item-content>
39
+ </v-list-item>
40
+ </v-list>
41
+ </v-menu>
42
+ </template>
43
+ <script>
44
+ const search = ref(null);
45
+ module.exports = {
46
+ async mounted() {
47
+ window.search = this;
48
+ await this.loadRequire();
49
+ this.algoliasearch = (await this.import([`https://cdn.jsdelivr.net/npm/algoliasearch@4.20.0/dist/algoliasearch-lite.umd.js`]))[0];
50
+ this.initSearch();
51
+ window.search = this;
52
+ },
53
+ watch: {
54
+ query ( value ) {
55
+ this.show_results = true;
56
+ this.search();
57
+ },
58
+ item ( value ) {
59
+ if ( this.results.hits != null && this.results.hits.length > 0 ) {
60
+ let url = this.results.hits[value].url;
61
+ if (url.startsWith("https://solara.dev")) {
62
+ url = url.slice(18);
63
+ }
64
+ solara.router.push( url );
65
+ }
66
+ },
67
+ },
68
+ methods: {
69
+ show( e, on ) {
70
+ this.show_results = false;
71
+ this.$nextTick( () => {
72
+ on.click( e )
73
+ } );
74
+ },
75
+ initSearch() {
76
+ this.client = this.algoliasearch( '9KW9L7O5EQ', '647ca12ba642437cc40c2adee4a78d08' );
77
+ this.index = this.client.initIndex( 'solara' );
78
+ this.mac = window.navigator.userAgent.indexOf("Mac") != -1;
79
+ document.addEventListener( 'keydown', ( e ) => {
80
+
81
+ if (this.mac) {
82
+ if ( this.$refs.search && e.metaKey && e.key === 'k' ) {
83
+ this.$refs.search.focus();
84
+ }
85
+ }else{
86
+ if ( this.$refs.search && e.ctrlKey && e.key === 'k' ) {
87
+ this.$refs.search.focus();
88
+ }
89
+ }
90
+ });
91
+ },
92
+ async search() {
93
+ results = await this.index.search( this.query, { hitsPerPage: 10 } );
94
+ if (results) {
95
+ this.results = results;
96
+ }else{
97
+ this.$set(this.results, []);
98
+ }
99
+ },
100
+ import(dependencies) {
101
+ return this.loadRequire().then(
102
+ () => {
103
+ if (window.jupyterVue) {
104
+ // in jupyterlab, we take Vue from ipyvue/jupyterVue
105
+ define("vue", [], () => window.jupyterVue.Vue);
106
+ } else {
107
+ define("vue", ['jupyter-vue'], jupyterVue => jupyterVue.Vue);
108
+ }
109
+ return new Promise((resolve, reject) => {
110
+ requirejs(dependencies, (...modules) => resolve(modules));
111
+ })
112
+ }
113
+ );
114
+ },
115
+ loadRequire() {
116
+ return new Promise((resolve, reject) => {
117
+ const script = document.createElement('script');
118
+ script.src = `${this.getCdn()}/requirejs@2.3.6/require.js`;
119
+ script.onload = resolve;
120
+ script.onerror = reject;
121
+ document.head.appendChild(script);
122
+ });
123
+ },
124
+ getBaseUrl() {
125
+ if (window.solara && window.solara.rootPath !== undefined) {
126
+ return solara.rootPath + "/";
127
+ }
128
+ // if base url is set, we use ./ for relative paths compared to the base url
129
+ if (document.getElementsByTagName("base").length) {
130
+ return document.baseURI;
131
+ }
132
+ const labConfigData = document.getElementById('jupyter-config-data');
133
+ if (labConfigData) {
134
+ /* lab and Voila */
135
+ return JSON.parse(labConfigData.textContent).baseUrl;
136
+ }
137
+ let base = document.body.dataset.baseUrl || document.baseURI;
138
+ if (!base.endsWith('/')) {
139
+ base += '/';
140
+ }
141
+ return base
142
+ },
143
+ getCdn() {
144
+ return (typeof solara_cdn !== "undefined" && solara_cdn) || `${this.getBaseUrl()}_solara/cdn`;
145
+ },
146
+ },
147
+ data(){
148
+ return {
149
+ query: '',
150
+ results: [],
151
+ item: null,
152
+ show_results: false,
153
+ mac: false,
154
+ }
155
+ },
156
+ }
157
+ </script>