solara-ui 1.39.0__py2.py3-none-any.whl → 1.41.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 (85) hide show
  1. solara/__init__.py +1 -1
  2. solara/__main__.py +23 -10
  3. solara/components/__init__.py +1 -0
  4. solara/components/component_vue.py +3 -2
  5. solara/components/input_text_area.py +86 -0
  6. solara/components/markdown.py +1 -1
  7. solara/hooks/use_thread.py +4 -4
  8. solara/lab/components/chat.py +8 -2
  9. solara/server/assets/style.css +4 -1
  10. solara/server/flask.py +1 -1
  11. solara/server/jupyter/server_extension.py +11 -1
  12. solara/server/jupyter/solara.py +91 -0
  13. solara/server/patch.py +1 -0
  14. solara/server/pyinstaller/__init__.py +9 -0
  15. solara/server/pyinstaller/hook-ipyreact.py +5 -0
  16. solara/server/pyinstaller/hook-ipyvuetify.py +5 -0
  17. solara/server/pyinstaller/hook-solara.py +9 -0
  18. solara/server/qt.py +113 -0
  19. solara/server/server.py +6 -1
  20. solara/server/settings.py +1 -0
  21. solara/server/starlette.py +18 -6
  22. solara/server/static/highlight-dark.css +1 -1
  23. solara/server/static/main-vuetify.js +11 -1
  24. solara/server/static/solara_bootstrap.py +1 -1
  25. solara/server/templates/loader-solara.html +1 -1
  26. solara/server/templates/solara.html.j2 +36 -7
  27. solara/website/assets/custom.css +20 -57
  28. solara/website/components/__init__.py +2 -2
  29. solara/website/components/algolia_api.vue +23 -6
  30. solara/website/components/breadcrumbs.py +28 -0
  31. solara/website/components/contact.py +144 -0
  32. solara/website/components/docs.py +11 -9
  33. solara/website/components/header.py +31 -20
  34. solara/website/components/markdown.py +12 -1
  35. solara/website/components/markdown_nav.vue +34 -0
  36. solara/website/components/sidebar.py +9 -1
  37. solara/website/pages/__init__.py +93 -254
  38. solara/website/pages/about/__init__.py +9 -0
  39. solara/website/pages/about/about.md +3 -0
  40. solara/website/pages/careers/__init__.py +27 -0
  41. solara/website/pages/changelog/__init__.py +2 -2
  42. solara/website/pages/changelog/changelog.md +12 -0
  43. solara/website/pages/contact/__init__.py +30 -6
  44. solara/website/pages/documentation/__init__.py +25 -33
  45. solara/website/pages/documentation/advanced/content/10-howto/40-embed.md +2 -1
  46. solara/website/pages/documentation/advanced/content/15-reference/41-asset-files.md +1 -1
  47. solara/website/pages/documentation/advanced/content/20-understanding/40-routing.md +17 -1
  48. solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +2 -1
  49. solara/website/pages/documentation/advanced/content/30-enterprise/00-overview.md +1 -1
  50. solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +5 -2
  51. solara/website/pages/documentation/api/hooks/use_thread.md +6 -0
  52. solara/website/pages/documentation/components/data/pivot_table.py +2 -2
  53. solara/website/pages/documentation/components/input/input.py +2 -0
  54. solara/website/pages/documentation/components/output/sql_code.py +3 -3
  55. solara/website/pages/documentation/examples/__init__.py +14 -22
  56. solara/website/pages/documentation/examples/ai/chatbot.py +1 -1
  57. solara/website/pages/documentation/examples/general/vue_component.py +1 -1
  58. solara/website/pages/documentation/examples/libraries/altair.py +1 -0
  59. solara/website/pages/documentation/examples/libraries/bqplot.py +1 -1
  60. solara/website/pages/documentation/examples/libraries/ipyleaflet.py +1 -1
  61. solara/website/pages/documentation/examples/libraries/ipyleaflet_advanced.py +1 -1
  62. solara/website/pages/documentation/examples/utilities/countdown_timer.py +18 -20
  63. solara/website/pages/documentation/examples/visualization/annotator.py +1 -3
  64. solara/website/pages/documentation/examples/visualization/linked_views.py +4 -4
  65. solara/website/pages/documentation/getting_started/content/00-quickstart.md +18 -0
  66. solara/website/pages/documentation/getting_started/content/04-tutorials/_jupyter_dashboard_1.ipynb +2 -2
  67. solara/website/pages/documentation/getting_started/content/05-fundamentals/10-components.md +19 -14
  68. solara/website/pages/documentation/getting_started/content/05-fundamentals/50-state-management.md +205 -15
  69. solara/website/pages/documentation/getting_started/content/07-deploying/10-self-hosted.md +3 -1
  70. solara/website/pages/home.vue +1199 -0
  71. solara/website/pages/our_team/__init__.py +83 -0
  72. solara/website/pages/pricing/__init__.py +31 -0
  73. solara/website/pages/roadmap/__init__.py +11 -0
  74. solara/website/pages/roadmap/roadmap.md +41 -0
  75. solara/website/pages/scale_ipywidgets.py +45 -0
  76. solara/widgets/vue/navigator.vue +46 -16
  77. solara/widgets/vue/vegalite.vue +18 -0
  78. {solara_ui-1.39.0.dist-info → solara_ui-1.41.0.dist-info}/METADATA +2 -2
  79. {solara_ui-1.39.0.dist-info → solara_ui-1.41.0.dist-info}/RECORD +83 -66
  80. solara/website/components/hero.py +0 -15
  81. solara/website/pages/contact/contact.md +0 -17
  82. {solara_ui-1.39.0.data → solara_ui-1.41.0.data}/data/etc/jupyter/jupyter_notebook_config.d/solara.json +0 -0
  83. {solara_ui-1.39.0.data → solara_ui-1.41.0.data}/data/etc/jupyter/jupyter_server_config.d/solara.json +0 -0
  84. {solara_ui-1.39.0.dist-info → solara_ui-1.41.0.dist-info}/WHEEL +0 -0
  85. {solara_ui-1.39.0.dist-info → solara_ui-1.41.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,17 @@
1
1
  # Solara Changelog
2
2
 
3
+ ## Version 1.40.0
4
+ * Feature: In Jupyter Notebook and Lab, Solara (server) now renders the [ipypopout](https://github.com/widgetti/ipypopout) window instead of Voila [#805](render ipypopout content in jupyter notebook and lab)
5
+ * Feature: Support styling input field of [ChatInput component](https://solara.dev/documentation/components/lab/chat). [#800](https://github.com/widgetti/solara/pull/800).
6
+ * Feature: [InputTextArea component](https://solara.dev/documentation/components/input/input) for multi line text input. [#801](https://github.com/widgetti/solara/pull/801). Contributed by [Alonso Silva](https://github.com/alonsosilvaallende)
7
+ * Bug Fix: Markdown links triggered a JavaScript error. [#765](https://github.com/widgetti/solara/pull/765)
8
+
9
+ ## Version 1.39.0
10
+
11
+ * Feature: Add option to start Solara server on a random unused port (using `--port=0`). [#762](https://github.com/widgetti/solara/pull/762)
12
+ * Bug Fix: Extension checking for e.g. ipyleaflet now work correctly on Amazon SageMaker Studio Lab. [#757](https://github.com/widgetti/solara/pull/757)
13
+ * Bug Fix: Various solara components should now work correctly in notebooks viewed on vscode, colab and voila. [#763](https://github.com/widgetti/solara/pull/763)
14
+
3
15
  ## Version 1.38.0
4
16
 
5
17
  * Feature: We detect and warn when there are possible reverse proxy or uvicorn misconfigurations. [#745](https://github.com/widgetti/solara/pull/745)
@@ -1,10 +1,34 @@
1
- from pathlib import Path
2
-
3
1
  import solara
4
2
  from solara.website.components.sidebar import Sidebar
3
+ from solara.website.components.contact import Contact
5
4
 
6
- title = "Contact"
7
- HERE = Path(__file__)
8
-
9
- Page = solara.Markdown(Path(HERE.parent / "contact.md").read_text())
10
5
  Sidebar = Sidebar
6
+
7
+
8
+ @solara.component
9
+ def Page():
10
+ solara.Markdown("""
11
+ # Contact
12
+
13
+ ## Business
14
+
15
+ Solara is developed mostly by Maarten Breddels and Mario Buikhuizen, Founders
16
+ of [Widgetti](https://widgetti.io/).
17
+
18
+ For business inquiries, please reach out using the form below, or send an email to [contact@solara.dev](mailto:contact@solara.dev) regarding Solara, or [info@widgetti.io](mailto:info@widgetti.io) regarding more general Jupyter related matters.
19
+ """)
20
+ Contact(
21
+ title="Contact Us", subtitle="Please fill out the form below and we will get back to you as soon as possible.", email_subject="Contact Form Submission"
22
+ )
23
+ solara.Markdown(
24
+ """
25
+ ## Community
26
+
27
+ If you want to share your thoughts, share your experiences, or just want to talk
28
+ to other people using and developing on Solara, consider using [GitHub discussions](https://github.com/widgetti/solara/discussions) for asynchronous discussions
29
+ or consider joining discord for more synchronous discussions.
30
+
31
+
32
+ [![Discord Shield](https://discordapp.com/api/guilds/1106593685241614489/widget.png?style=banner2)](https://discord.gg/dm4GKNDjXN)
33
+ """
34
+ )
@@ -17,34 +17,28 @@ def Algolia():
17
17
 
18
18
 
19
19
  @solara.component
20
- def Page(children=[]):
20
+ def Page():
21
21
  # show a gallery of all the api pages
22
22
  router = solara.use_router()
23
23
  route_current = router.path_routes[-2]
24
-
25
- with solara.Column(style={"width": "100%"}, gap="75px"):
26
- if route_current.path == "documentation":
27
- with solara.Column(classes=["api-search-container"], gap="50px", style={"justify-content": "center"}, align="center"):
28
- solara.Markdown("# Search the Solara Documentation", style={"text-align": "center"})
29
- with solara.Row(style={"width": "100%", "min-width": "20rem", "justify-content": "center", "background-color": "transparent"}):
30
- Algolia()
31
- with solara.Row(gap="20px", classes=["docs-card-container"]):
32
- for route in route_current.children:
33
- if route.path in ["/", "advanced", "faq"]:
34
- continue
35
- with solara.Link("/documentation/" + route.path):
36
- with solara.Row(
37
- classes=["docs-card"],
38
- style={
39
- "background-color": f"var({'--docs-color-grey' if route.path != 'getting_started' else '--color-primary'})",
40
- },
41
- ):
42
- with solara.Column(style={"height": "100%", "flex-grow": "1", "background-color": "transparent"}):
43
- solara.HTML(tag="h2", unsafe_innerHTML=route.label, style={"color": "white", "padding": "1.5rem"})
44
- with solara.Column(style={"justify-content": "center", "height": "100%", "background-color": "transparent"}):
24
+ if route_current.path == "documentation":
25
+ with solara.Column(style={"width": "100%", "max-width": "1024px"}, gap="40px"):
26
+ with solara.Column(style={"width": "100%", "align-items": "center"}, gap="40px"):
27
+ with solara.Column(gap="20px", classes=["docs-card-container"], style={"max-width": "80%", "padding-top": "64px"}, align="stretch"):
28
+ for route in route_current.children:
29
+ if route.path in ["/", "advanced", "faq"]:
30
+ continue
31
+ with solara.Link("/documentation/" + route.path):
32
+ with solara.Row(
33
+ classes=["docs-card"],
34
+ style={
35
+ "background-color": f"var({'--docs-color-grey' if route.path != 'getting_started' else '--color-primary'})",
36
+ "align-items": "center",
37
+ },
38
+ ):
39
+ solara.HTML(tag="h2", unsafe_innerHTML=route.label, style={"color": "white", "display": "block", "flex-grow": "1"})
45
40
  solara.v.Icon(children=["mdi-arrow-right"], color="var(--color-grey-light)", x_large=True, class_="docs-card-icon")
46
- with solara.Row(gap="75px", style={"flex-wrap": "wrap", "row-gap": "75px", "padding-bottom": "75px"}):
47
- with solara.Column(style={"padding-left": "10%"}):
41
+ with solara.Column(gap="10px", style={"flex-wrap": "wrap", "max-width": "80%"}):
48
42
  solara.HTML(tag="h2", unsafe_innerHTML="How to use our documentation:", style={"padding": "1.5rem"})
49
43
  solara.Markdown(
50
44
  """
@@ -58,28 +52,23 @@ def Page(children=[]):
58
52
  If a component you would like to use is not available in Solara, you can use the underlying library directly.
59
53
  """
60
54
  )
61
- with solara.Column(style={"justify-content": "center", "height": "100%"}):
62
55
  solara.HTML(tag="h2", unsafe_innerHTML="Also Check Out", style={"padding": "1.5rem"})
63
- with solara.Row(gap="20px", style={"flex-wrap": "wrap", "row-gap": "20px", "align-items": "center"}):
56
+ with solara.Row(gap="20px", style={"flex-wrap": "wrap", "row-gap": "20px", "align-items": "center", "padding-left": "24px"}):
64
57
  with solara.v.Html(tag="a", attributes={"href": "https://discord.solara.dev", "target": "_blank"}):
65
58
  with solara.Div(classes=["social-logo-container"], style={"background-color": "var(--docs-social-discord)"}):
66
59
  solara.v.Html(tag="img", attributes={"src": "/static/public/social/discord.svg"}, style_="height: 1.5rem; width: auto;")
67
60
  solara.Text("We use discord to provide support and answer questions there actively.")
68
- with solara.Row(gap="20px", style={"flex-wrap": "wrap", "row-gap": "20px", "align-items": "center"}):
61
+ with solara.Row(gap="20px", style={"flex-wrap": "wrap", "row-gap": "20px", "align-items": "center", "padding-left": "24px"}):
69
62
  with solara.v.Html(tag="a", attributes={"href": "https://github.com/widgetti/solara", "target": "_blank"}):
70
63
  with solara.Div(classes=["social-logo-container"], style={"background-color": "var(--docs-social-github)"}):
71
64
  solara.v.Html(tag="img", attributes={"src": "/static/public/social/github.svg"}, style_="height: 1.5rem; width: auto;")
72
65
  solara.Text("Search for solutions on Github issues, or report bugs.")
73
- with solara.Row(gap="20px", style={"flex-wrap": "wrap", "row-gap": "20px", "align-items": "center"}):
66
+ with solara.Row(gap="20px", style={"flex-wrap": "wrap", "row-gap": "20px", "align-items": "center", "padding-left": "24px"}):
74
67
  with solara.v.Html(tag="a", attributes={"href": "https://twitter.com/solara_dev", "target": "_blank"}):
75
68
  with solara.Div(classes=["social-logo-container"], style={"background-color": "var(--docs-social-twitter)"}):
76
69
  solara.v.Html(tag="img", attributes={"src": "/static/public/social/twitter.svg"}, style_="height: 1.5rem; width: auto;")
77
70
  solara.Text("Get announcements about Solara features, showcases, and events!.")
78
71
 
79
- else:
80
- with solara.Column(align="center", children=children, style={"padding": "0"}):
81
- pass
82
-
83
72
 
84
73
  @solara.component
85
74
  def Layout(children=[]):
@@ -90,7 +79,10 @@ def Layout(children=[]):
90
79
  if route_current.path == "/":
91
80
  return Page()
92
81
  else:
93
- return Page(children=children)
82
+ with solara.Column(
83
+ align="center", children=children, style={"padding": "0 0 40px 0", "max-width": "90%"}
84
+ ): # 40px bottom margin for "runs on Solara" text
85
+ pass
94
86
 
95
87
 
96
88
  @solara.component
@@ -41,7 +41,8 @@ If you do not see your app, you can open the browser developer tools in your bro
41
41
 
42
42
  ### Security considerations
43
43
 
44
- Solara uses a cookie to implement sessions. To support cookies settings in an iframe, we set the session cookie using `Secure`, and `SameSite=Strict`. See [https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies](MDN) for more details. This means that we can only support loading via iframes via https or localhost.
44
+ Solara uses a cookie to implement sessions. To support setting cookies in an iframe, we set the session cookie using `Secure`, and `SameSite=Strict`. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) for more details. This means that we can only support iframes via https or localhost. Note that proxy servers can tell
45
+ solara-server that the connection is secure by forwarding the `X-Forwarded-Proto` header, see [our self hosted deployment documentation for more information](https://solara.dev/documentation/getting_started/deploying/self-hosted).
45
46
 
46
47
 
47
48
  ## Embed into an existing page
@@ -6,7 +6,7 @@ description: Solara looks for overrides of certain style and asset files in the
6
6
 
7
7
  Asset files are special files with are loaded by Solara-server and thus have a special meaning, and come with defaults. Current supported assets files are:
8
8
 
9
- * `favicon.png` - Image shown by the browser (usually in the tab).
9
+ * `favicon.png` and/or `favicon.svg` - Image shown by the browser (usually in the tab). If SVG is not provided, default `favicon.svg` of the solara server may override your custom favicon.png depending on the browser. Providing both PNG and SVG versions is recommended.
10
10
  * `style.css` - Default `CSS` used by Solara.
11
11
  * `custom.css` - Custom `CSS` you can override for your project (empty `CSS` file by default).
12
12
  * `custom.js` - Custom Javascript you can use for your project (empty Javascript file by default).
@@ -196,7 +196,7 @@ Note that all routes are relative, since a component does not know if it is embe
196
196
 
197
197
 
198
198
  Therefore you should never use the `route.path` for navigation since the route object has no knowledge of the full url
199
- (e.g. `/docs/basics/ipywigets`) but only knows its small piece of the pathname (e.g. `ipywidgets`)
199
+ (e.g. `/docs/basics/ipywidgets`) but only knows its small piece of the pathname (e.g. `ipywidgets`)
200
200
 
201
201
  Using [`resolve_path`](/documentation/api/routing/resolve_path) we can request the full url for navigation.
202
202
 
@@ -219,6 +219,22 @@ def LinkToIpywidgets():
219
219
  return main
220
220
  ```
221
221
 
222
+ ### Linking to Sections of a Page
223
+
224
+ The `solara.Link` component also supports linking to HTML elements identified by id. Although most Solara components don't directly support the id attribute, you can assign ids to all ipyvuetify components, using the `attributes` argument:
225
+
226
+ ```python
227
+ solara.v.Btn(attributes={"id": "my-id"}, ...)
228
+ ```
229
+
230
+ You can then link to a particular element by appending `#` followed by its id to your link, i.e. `solara.Link(route_or_path="/page#my-id")`. If you want the page to smoothly scroll to the linked element, you should give an element that contains it (for instance the `html`-element) the following CSS rule:
231
+
232
+ ```css
233
+ html {
234
+ scroll-behaviour: smooth;
235
+ }
236
+ ```
237
+
222
238
  ## Fully manual routing
223
239
 
224
240
  If you want to do routing fully manually, you can use the [`solara.use_router`](/documentation/api/routing/use_router) hook, and use the `.path` attribute.
@@ -38,7 +38,8 @@ Each virtual kernel runs in its own thread, this ensures that one particular use
38
38
 
39
39
 
40
40
  ## Handling Multiple Workers
41
- In setups with multiple workers, it's possible for a page to reconnect to a different worker than its original. This would result in a loss of the virtual kernel (since it lives on a different worker), prompting the Solara app to initiate a fresh start. To prevent this scenario, a sticky session configuration is recommended, ensuring consistent client-worker connections. Utilizing a load balancer, such as [nginx](https://www.nginx.com/), can achieve this.
41
+
42
+ In setups with multiple workers, it's possible for a page to (re)connect to a different worker than its original. This can happen after a lost network connection is restored, or when [ipypopout](https://github.com/widgetti/ipypopout) is used, since ipypopout creates a new connection, which can end up at a different worker. This can result in a loss of the virtual kernel, since it lives on the worker that was first connected to. The Solara app will then initiate a fresh start, or simply fail when ipypopout is used. To prevent this scenario, a sticky session configuration is recommended, ensuring consistent client-worker connections. A load balancer, such as [nginx](https://www.nginx.com/), can be used to achieve this. Note that using multiple workers (e.g. by using gunicorn) cannot work since a connection will be made to a different worker each time.
42
43
 
43
44
  If you have questions about setting this up, or require assistance, please [contact us](https://solara.dev/docs/contact).
44
45
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  Solara enterprise is a not Open Source, but the source code is visible, is free for non-commercial use and installable from pypi.
4
4
 
5
- For commercial use, you require a license. Please [contact](/contact) us for more information.
5
+ For commercial use, you require a license. Please see [pricing](/pricing) for more information.
6
6
 
7
7
  Solara-enterprise will stay free for non-commercial use and features that are in solara will **not be moved to solara-enterprise**.
@@ -44,12 +44,15 @@ from solara_enterprise import auth
44
44
  @solara.component
45
45
  def Page():
46
46
  if not auth.user.value:
47
- solara.Button("Login", icon_name="mdi-login", href=auth.get_login_url())
47
+ # `get_login_url` should automatically redirect the user back to the current page.
48
+ # The URL argument is only used here as an example.
49
+ solara.Button("Login", icon_name="mdi-login", href=auth.get_login_url("documentation/advanced/enterprise/oauth"))
48
50
  else:
49
51
  userinfo = auth.user.value['userinfo']
50
52
  if 'name' in userinfo:
51
53
  solara.Markdown(f"### Welcome {userinfo['name']}")
52
- solara.Button("Logout", icon_name="mdi-logout", href=auth.get_logout_url())
54
+ # See above comment
55
+ solara.Button("Logout", icon_name="mdi-logout", href=auth.get_logout_url("documentation/advanced/enterprise/oauth"))
53
56
  ```
54
57
  ## How to configure OAuth
55
58
 
@@ -56,3 +56,9 @@ graph TD;
56
56
  RUNNING-- "work finished" -->FINISHED
57
57
  RUNNING-- "cancel()" -->CANCELLED
58
58
  ```
59
+
60
+ ## Future deprecation
61
+
62
+ Note that [`use_task`](/https://solara.dev/documentation/components/lab/use_task) is an alternative to `use_thread` that will most likely
63
+ replace `use_thread` in the future. Compared to `use_thread`, `use_task` has no intrusive cancel, which turned out to be too large of
64
+ a performance overhead to be useful. Also, `use_task` can run async functions, which is not possible with `use_thread`.
@@ -54,10 +54,10 @@ def Page():
54
54
  return solara.Markdown("This example requires vaex, please install it with `pip install vaex`")
55
55
  with solara.Div() as main:
56
56
  solara.Markdown("# Titanic")
57
- selected, on_selected = solara.use_state({"x": [0, 0]})
57
+ selected, on_selected = solara.use_state({"x": [0, 0]}) # noqa: SH101
58
58
  solara.provide_cross_filter()
59
59
  with solara.VBox():
60
- type, set_type = solara.use_state("view")
60
+ type, set_type = solara.use_state("view") # noqa: SH101
61
61
  with solara.ToggleButtonsSingle(type, on_value=set_type):
62
62
  solara.Button("PivotTableView", value="view")
63
63
  solara.Button("PivotTable", value="df")
@@ -13,6 +13,8 @@ Page = NoPage
13
13
 
14
14
 
15
15
  __doc__ += apidoc(solara.InputText.f) # type: ignore
16
+ __doc__ += "# InputTextArea"
17
+ __doc__ += apidoc(solara.InputTextArea.f) # type: ignore
16
18
  __doc__ += "# InputFloat"
17
19
  __doc__ += apidoc(solara.InputFloat.f) # type: ignore
18
20
  __doc__ += "# InputInt"
@@ -42,8 +42,8 @@ if vaex is not None:
42
42
  def Page():
43
43
  if vaex is None:
44
44
  return solara.Error("Vaex is not installed, run pip install vaex-core vaex-hdf5")
45
- query, set_query = solara.use_state("SELECT * from titanic")
46
- query_executed, set_query_executed = solara.use_state(cast(Optional[str], None))
45
+ query, set_query = solara.use_state("SELECT * from titanic") # noqa: SH101
46
+ query_executed, set_query_executed = solara.use_state(cast(Optional[str], None)) # noqa: SH101
47
47
 
48
48
  def run_query(cancel: threading.Event) -> pd.DataFrame:
49
49
  if not query_executed:
@@ -55,7 +55,7 @@ def Page():
55
55
  df = pd.DataFrame(cursor.fetchall(), columns=[k[0] for k in cursor.description])
56
56
  return df
57
57
 
58
- result: solara.Result[pd.DataFrame] = solara.use_thread(run_query, dependencies=[query_executed])
58
+ result: solara.Result[pd.DataFrame] = solara.use_thread(run_query, dependencies=[query_executed]) # noqa: SH101
59
59
  with solara.VBox() as main:
60
60
  solara.SqlCode(query=query, tables=table_hints, on_query=set_query)
61
61
  enable_execute = (query != query_executed) or result.error is not None
@@ -1,5 +1,5 @@
1
1
  import solara
2
- from solara.website.components import Gallery
2
+ from solara.website.components import Gallery, MarkdownWithMetadata
3
3
 
4
4
  title = "Examples"
5
5
 
@@ -25,28 +25,20 @@ def Layout(children):
25
25
  assert module is not None
26
26
  github_url = solara.util.github_url(module.__file__)
27
27
 
28
- with solara.HBox(grow=False) as main:
29
- if route_current.path == "fullscreen":
30
- with solara.Padding(4, children=children):
31
- pass
32
- else:
33
- with solara.VBox(grow=True, align_items="baseline"):
34
- doc = module.__doc__
35
- if doc:
36
- with solara.VBox(grow=True):
37
- solara.Markdown(doc)
38
- with solara.HBox():
39
- if route_current.path != "/":
40
- solara.Button("View source code on GitHub", icon_name="mdi-github-circle", href=github_url, class_="ma-2", target="_blank", text=True)
41
- # code = inspect.getsource(module)
42
-
43
- # code_quoted = urllib.parse.quote_plus(code)
44
- # url = f"https://test.solara.dev/try?code={code_quoted}"
45
- # solara.Button("Run on solara.dev", icon_name="mdi-pencil", href=url, class_="ma-2", target="_blank")
46
- # with solara.HBox():
28
+ if route_current.path == "fullscreen":
29
+ with solara.Padding(4, children=children):
30
+ pass
31
+ else:
32
+ with solara.Column(align="center", style={"max-width": "100%"}):
33
+ doc = module.__doc__
34
+ if doc:
35
+ with solara.Column():
36
+ MarkdownWithMetadata(doc)
37
+ with solara.Column(style={"max-width": "min(100%, 1024px)", "width": "100%"}):
38
+ if route_current.path != "/":
39
+ solara.Button("View source code on GitHub", icon_name="mdi-github-circle", href=github_url, class_="ma-2", target="_blank", text=True)
47
40
  if not hasattr(module, "Page"):
48
41
  solara.Error(f"No Page component found in {module}")
49
42
  else:
50
- with solara.Padding(4, children=children):
43
+ with solara.Div(children=children):
51
44
  pass
52
- return main
@@ -77,7 +77,7 @@ def Page():
77
77
  task = solara.lab.use_task(call_openai, dependencies=[user_message_count]) # type: ignore
78
78
 
79
79
  with solara.Column(
80
- style={"width": "700px", "height": "50vh"},
80
+ style={"width": "100%", "height": "50vh"},
81
81
  ):
82
82
  with solara.lab.ChatBox():
83
83
  for item in messages.value:
@@ -35,7 +35,7 @@ def Page():
35
35
  sales_data = np.floor(np.cumsum(gen.random(7) - 0.5) * 100 + 100)
36
36
  show_report = solara.use_reactive(False)
37
37
 
38
- with solara.Column(style={"min-width": "600px"}):
38
+ with solara.Column():
39
39
  if show_report.value:
40
40
  with solara.Card("Report"):
41
41
  solara.Markdown("Lorum ipsum dolor sit amet")
@@ -38,6 +38,7 @@ def Page():
38
38
  )
39
39
  .configure_view(step=13, strokeWidth=0)
40
40
  .configure_axis(domain=False)
41
+ .properties(width="container")
41
42
  )
42
43
  with solara.Card("Annual Weather Heatmap for Seattle, WA"):
43
44
  solara.AltairChart(chart, on_click=on_click)
@@ -34,6 +34,6 @@ def Page(x=x0, ymax=5):
34
34
  lines = bqplot.Lines(x=x, y=y, scales={"x": x_scale, "y": y_scale}, stroke_width=3, colors=[color], display_legend=display_legend, labels=[label])
35
35
  x_axis = bqplot.Axis(scale=x_scale)
36
36
  y_axis = bqplot.Axis(scale=y_scale, orientation="vertical")
37
- bqplot.Figure(axes=[x_axis, y_axis], marks=[lines], scale_x=x_scale, scale_y=y_scale, layout={"min_width": "800px"})
37
+ bqplot.Figure(axes=[x_axis, y_axis], marks=[lines], scale_x=x_scale, scale_y=y_scale, layout={"max_width": "100%", "width": "100%"})
38
38
 
39
39
  # return main
@@ -15,7 +15,7 @@ bounds = solara.reactive(None)
15
15
  @solara.component
16
16
  def Page():
17
17
  # Isolation is required to prevent the map from overlapping navigation (when screen width < 960px)
18
- with solara.Column(style={"min-width": "500px", "height": "500px", "isolation": "isolate"}):
18
+ with solara.Column(style={"width": "100%", "height": "500px", "isolation": "isolate"}):
19
19
  # solara components support reactive variables
20
20
  solara.SliderInt(label="Zoom level", value=zoom, min=1, max=20)
21
21
  # using 3rd party widget library require wiring up the events manually
@@ -31,7 +31,7 @@ def Page():
31
31
  # do things with the location
32
32
  marker_location.set(location)
33
33
 
34
- with solara.Column(style={"min-width": "500px", "height": "500px"}):
34
+ with solara.Column(style={"width": "100%", "height": "500px"}):
35
35
  solara.Markdown(f"Market set to: {marker_location.value}", style={"color": "#6e6e6e"})
36
36
 
37
37
  map = maps[map_name.value]
@@ -9,7 +9,6 @@ The UI code demonstrates a lot of conditional rendering.
9
9
  import time
10
10
 
11
11
  import solara
12
- from solara.alias import rv
13
12
 
14
13
 
15
14
  @solara.component
@@ -41,24 +40,23 @@ def Page():
41
40
 
42
41
  solara.use_thread(run_timer, dependencies=[duration, running])
43
42
 
44
- with solara.VBox() as main:
45
- if not running:
46
- if duration < 1:
47
- solara.Error("Duration must be at least 1 second")
48
- else:
49
- solara.Markdown(f"# Timer set to {seconds} seconds")
43
+ if not running:
44
+ if duration < 1:
45
+ solara.Error("Duration must be at least 1 second")
50
46
  else:
51
- if seconds:
52
- solara.Markdown(f"# {seconds} seconds left")
53
- else:
54
- solara.solara.Markdown("# Time's up!")
55
- rv.TextField(type="number", v_model=duration, on_v_model=on_duration, disabled=running)
56
- with solara.HBox():
57
- if running:
58
- solara.Button("Stop", on_click=lambda: set_running(False), icon_name="mdi-stop")
47
+ solara.Markdown(f"# Timer set to {seconds} seconds")
48
+ else:
49
+ if seconds:
50
+ solara.Markdown(f"# {seconds} seconds left")
51
+ else:
52
+ solara.solara.Markdown("# Time's up!")
53
+
54
+ solara.v.TextField(type="number", v_model=duration, on_v_model=on_duration, disabled=running)
55
+ with solara.Row():
56
+ if running:
57
+ solara.Button("Stop", on_click=lambda: set_running(False), icon_name="mdi-stop")
58
+ else:
59
+ if duration != seconds:
60
+ solara.Button("Reset", on_click=lambda: set_seconds(duration), icon_name="mdi-restart")
59
61
  else:
60
- if duration != seconds:
61
- solara.Button("Reset", on_click=lambda: set_seconds(duration), icon_name="mdi-restart")
62
- else:
63
- solara.Button("Start", on_click=lambda: set_running(True), icon_name="mdi-play", disabled=seconds < 1)
64
- return main
62
+ solara.Button("Start", on_click=lambda: set_running(True), icon_name="mdi-play", disabled=seconds < 1)
@@ -45,9 +45,7 @@ def Page():
45
45
  fig = go.FigureWidget(
46
46
  layout=go.Layout(
47
47
  showlegend=False,
48
- autosize=False,
49
- width=600,
50
- height=600,
48
+ autosize=True,
51
49
  dragmode="drawrect",
52
50
  modebar={
53
51
  "add": [
@@ -49,8 +49,8 @@ def ClickScatter(df, x, y, color, click_row, on_click: Callable[[ClickPoint], No
49
49
  click_y = df[y].values[click_row]
50
50
  fig.add_trace(px.scatter(x=[click_x], y=[click_y], text=["⭐️"]).data[0])
51
51
  # make the figure a bit smaller
52
- fig.update_layout(width=400)
53
- with solara.VBox() as main:
52
+ fig.update_layout(width=340)
53
+ with solara.Column(style={"width": "340px"}) as main:
54
54
  solara.FigurePlotly(fig, on_click=on_click_trace)
55
55
  solara.Select(label="X-axis", value=x, values=columns, on_value=set_x)
56
56
  solara.Select(label="Y-axis", value=y, values=columns, on_value=set_y)
@@ -65,8 +65,8 @@ def Page():
65
65
  else:
66
66
  clicked_row = None
67
67
 
68
- with solara.VBox() as main:
69
- with solara.HBox():
68
+ with solara.Column() as main:
69
+ with solara.Row(justify="center", style={"flex-wrap": "wrap"}):
70
70
  ClickScatter(df, "sepal_length", "sepal_width", "species", clicked_row, on_click=set_click_point)
71
71
  ClickScatter(df, "petal_length", "petal_width", "species", clicked_row, on_click=set_click_point)
72
72
  if click_point is not None:
@@ -87,3 +87,21 @@ In case you forgot how to start a notebook server:
87
87
  Or the more modern Jupyter lab:
88
88
 
89
89
  $ jupyter lab
90
+
91
+
92
+ ## Run as app (experimental)
93
+
94
+ You can also run the script as a standalone app. This requires the extra packages `qtpy` and `PySide6` (or `PyQt6`) to be installed.
95
+
96
+ ```bash
97
+ $ pip install pip install qtpy PySide6
98
+ ```
99
+
100
+ Run from the command line in the same directory where you put your file (`sol.py`):
101
+
102
+ ```bash
103
+ $ solara run sol.py --qt
104
+ ```
105
+
106
+
107
+ <img src="https://dxhl76zpt6fap.cloudfront.net/public/solara-quickstart-app.webp" alt="Markdown Monster icon"/>
@@ -35,7 +35,7 @@
35
35
  "\n",
36
36
  "We will use a subsample of the [San Fanfrisco crime dataset](https://www.kaggle.com/competitions/sf-crime/data) which contains information on types of crimes and where they were committed.\n",
37
37
  "\n",
38
- "[Download the CSV file](https://raw.githubusercontent.com/widgetti/solara/master/solara/website/pages/docs/content/04-tutorial/SF_crime_sample.csv.gz) if you want to run this locally, or let the code below sort it out."
38
+ "[Download the CSV file](https://github.com/widgetti/solara/raw/master/solara/website/pages/documentation/getting_started/content/04-tutorials/SF_crime_sample.csv.gz) if you want to run this locally, or let the code below sort it out."
39
39
  ]
40
40
  },
41
41
  {
@@ -350,7 +350,7 @@
350
350
  "\n",
351
351
  "ROOT = Path(solara.__file__).parent / \"website\" / \"pages\" / \"docs\" / \"content\" / \"04-tutorial\"\n",
352
352
  "path = ROOT / Path(\"SF_crime_sample.csv.gz\")\n",
353
- "url = \"https://raw.githubusercontent.com/widgetti/solara/master/solara/website/pages/docs/content/04-tutorial/SF_crime_sample.csv\"\n",
353
+ "url = \"https://github.com/widgetti/solara/raw/master/solara/website/pages/documentation/getting_started/content/04-tutorials/SF_crime_sample.csv.gz\"\n",
354
354
  "\n",
355
355
  "if path.exists():\n",
356
356
  " df_crime = pd.read_csv(path)\n",