solara-ui 1.39.0__py2.py3-none-any.whl → 1.40.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 (67) hide show
  1. solara/__init__.py +1 -1
  2. solara/components/__init__.py +1 -0
  3. solara/components/input_text_area.py +86 -0
  4. solara/components/markdown.py +1 -1
  5. solara/hooks/use_thread.py +4 -4
  6. solara/lab/components/chat.py +8 -2
  7. solara/server/assets/style.css +2 -1
  8. solara/server/flask.py +1 -1
  9. solara/server/jupyter/server_extension.py +11 -1
  10. solara/server/jupyter/solara.py +91 -0
  11. solara/server/patch.py +1 -0
  12. solara/server/pyinstaller/__init__.py +9 -0
  13. solara/server/pyinstaller/hook-ipyreact.py +5 -0
  14. solara/server/pyinstaller/hook-ipyvuetify.py +5 -0
  15. solara/server/pyinstaller/hook-solara.py +9 -0
  16. solara/server/server.py +6 -1
  17. solara/server/starlette.py +18 -6
  18. solara/server/static/highlight-dark.css +1 -1
  19. solara/server/static/main-vuetify.js +1 -1
  20. solara/server/static/solara_bootstrap.py +1 -1
  21. solara/server/templates/solara.html.j2 +30 -6
  22. solara/website/assets/custom.css +20 -57
  23. solara/website/components/__init__.py +2 -2
  24. solara/website/components/algolia_api.vue +23 -6
  25. solara/website/components/breadcrumbs.py +28 -0
  26. solara/website/components/contact.py +144 -0
  27. solara/website/components/docs.py +11 -9
  28. solara/website/components/header.py +31 -20
  29. solara/website/components/markdown.py +12 -1
  30. solara/website/components/markdown_nav.vue +34 -0
  31. solara/website/components/sidebar.py +7 -1
  32. solara/website/pages/__init__.py +87 -254
  33. solara/website/pages/about/__init__.py +9 -0
  34. solara/website/pages/about/about.md +3 -0
  35. solara/website/pages/careers/__init__.py +27 -0
  36. solara/website/pages/changelog/__init__.py +2 -2
  37. solara/website/pages/changelog/changelog.md +12 -0
  38. solara/website/pages/contact/__init__.py +30 -6
  39. solara/website/pages/documentation/__init__.py +25 -33
  40. solara/website/pages/documentation/advanced/content/10-howto/40-embed.md +2 -1
  41. solara/website/pages/documentation/advanced/content/15-reference/41-asset-files.md +1 -1
  42. solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +2 -1
  43. solara/website/pages/documentation/advanced/content/30-enterprise/00-overview.md +1 -1
  44. solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +5 -2
  45. solara/website/pages/documentation/api/hooks/use_thread.md +6 -0
  46. solara/website/pages/documentation/components/data/pivot_table.py +2 -2
  47. solara/website/pages/documentation/components/input/input.py +2 -0
  48. solara/website/pages/documentation/components/output/sql_code.py +3 -3
  49. solara/website/pages/documentation/examples/__init__.py +2 -2
  50. solara/website/pages/documentation/getting_started/content/04-tutorials/_jupyter_dashboard_1.ipynb +2 -2
  51. solara/website/pages/documentation/getting_started/content/05-fundamentals/10-components.md +19 -14
  52. solara/website/pages/documentation/getting_started/content/05-fundamentals/50-state-management.md +205 -15
  53. solara/website/pages/documentation/getting_started/content/07-deploying/10-self-hosted.md +3 -1
  54. solara/website/pages/home.vue +1199 -0
  55. solara/website/pages/our_team/__init__.py +83 -0
  56. solara/website/pages/pricing/__init__.py +31 -0
  57. solara/website/pages/roadmap/__init__.py +11 -0
  58. solara/website/pages/roadmap/roadmap.md +41 -0
  59. solara/website/pages/scale_ipywidgets.py +45 -0
  60. {solara_ui-1.39.0.dist-info → solara_ui-1.40.0.dist-info}/METADATA +2 -2
  61. {solara_ui-1.39.0.dist-info → solara_ui-1.40.0.dist-info}/RECORD +65 -49
  62. solara/website/components/hero.py +0 -15
  63. solara/website/pages/contact/contact.md +0 -17
  64. {solara_ui-1.39.0.data → solara_ui-1.40.0.data}/data/etc/jupyter/jupyter_notebook_config.d/solara.json +0 -0
  65. {solara_ui-1.39.0.data → solara_ui-1.40.0.data}/data/etc/jupyter/jupyter_server_config.d/solara.json +0 -0
  66. {solara_ui-1.39.0.dist-info → solara_ui-1.40.0.dist-info}/WHEEL +0 -0
  67. {solara_ui-1.39.0.dist-info → solara_ui-1.40.0.dist-info}/licenses/LICENSE +0 -0
@@ -5,12 +5,11 @@ from solara.components.title import Title
5
5
  from solara.server import server
6
6
  from solara.website.components.algolia import Algolia
7
7
 
8
- from ..components import Header, Hero
9
- from ..components.mailchimp import MailChimp
8
+ from ..components import Header
10
9
 
11
10
  title = "Home"
12
11
 
13
- route_order = ["/", "showcase", "documentation", "apps", "contact", "changelog"]
12
+ route_order = ["/", "showcase", "documentation", "apps", "contact", "changelog", "roadmap", "pricing", "our_team", "careers", "about", "scale_ipywidgets"]
14
13
 
15
14
 
16
15
  _redirects = {
@@ -236,6 +235,11 @@ def List(children=[], class_: str = None):
236
235
  return rv.Html(tag="ul", children=children, attributes={"class": class_})
237
236
 
238
237
 
238
+ @solara.component_vue("home.vue")
239
+ def Home(children=[]):
240
+ pass
241
+
242
+
239
243
  @solara.component
240
244
  def Layout(children=[]):
241
245
  router = solara.use_router()
@@ -247,265 +251,94 @@ def Layout(children=[]):
247
251
 
248
252
  target, set_target = solara.use_state(0)
249
253
 
250
- if route_current and route_current.path == "apps":
254
+ if route_current is not None:
255
+ with solara.Div(style={"display": "none"}):
256
+ solara.Meta(name="twitter:card", content="summary_large_image")
257
+ solara.Meta(name="twitter:site", content="@solara_dev")
258
+ solara.Meta(name="twitter:image", content="https://solara.dev/static/assets/images/logo-small.png")
259
+ solara.Meta(property="og:url", content="https://solara.dev" + router.path)
260
+ solara.Meta(property="og:image", content="https://solara.dev/static/assets/images/logo-small.png")
261
+ solara.Meta(property="og:type", content="website")
262
+ if route_current is not None and route_current.path == "apps":
251
263
  return children[0]
252
- with solara.VBox(grow=False) as main:
253
- Title(title="Solara documentation")
254
- solara.Meta(name="twitter:card", content="summary_large_image")
255
- solara.Meta(name="twitter:site", content="@solara_dev")
256
- solara.Meta(name="twitter:image", content="https://solara.dev/static/assets/images/logo-small.png")
257
- solara.Meta(property="og:url", content="https://solara.dev" + router.path)
258
- solara.Meta(property="og:image", content="https://solara.dev/static/assets/images/logo-small.png")
259
- solara.Meta(property="og:type", content="website")
260
- Header(
261
- on_toggle_left_menu=lambda: set_show_left_menu(not show_left_menu),
262
- on_toggle_right_menu=lambda: set_show_right_menu(not show_right_menu),
263
- )
264
- if route_current is not None and route_current.path == "/":
265
- Hero(
266
- title="A pure Python, React-style web framework",
267
- sub_title="Solara helps you build powerful & scalable Jupyter and web apps <b>faster</b> and <b>easier</b>.",
268
- button_text="Quickstart",
264
+ elif route_current is not None and route_current.path == "/":
265
+ Title(title="Solara: Build high-quality web applications in pure Python")
266
+ Home()
267
+ else:
268
+ with solara.VBox(grow=False) as main:
269
+ Title(title="Solara documentation")
270
+ Header(
271
+ on_toggle_left_menu=lambda: set_show_left_menu(not show_left_menu),
272
+ on_toggle_right_menu=lambda: set_show_right_menu(not show_right_menu),
269
273
  )
270
-
271
- with rv.Container(tag="section", fluid=True, ma_0=True, pa_0=True, class_="fill-height solara-content-main"):
272
- if route_current is None:
273
- return solara.Error("Page not found")
274
- elif route_current.path == "/":
275
- description = "Use ipywidgets with Solara to build powerful and scalable web apps for Jupyter and production in Python."
276
- # both tags in one
277
- solara.Meta(name="description", property="og:description", content=description)
278
- solara.Meta(name="twitter:description", content=description)
279
- solara.Meta(property="og:title", content="Solara documentation")
280
- solara.Meta(name="twitter:title", content="Solara documentation")
281
-
282
- with rv.Row(class_="ma-2"):
283
- with rv.Col(md=6, offset_md=3, sm=8, offset_sm=2):
284
- solara.Markdown(
285
- """
286
- # What is Solara?
287
-
288
- Solara lets you build web apps from pure Python using ipywidgets or a React-like API on
289
- top of ipywidgets.
290
- These apps work both inside the Jupyter Notebook and as standalone web apps with frameworks like FastAPI.
291
-
292
- With Solara, you benefit from a paradigm that promotes component-based code and simplifies state management,
293
- making your development process more efficient and your applications more maintainable.
294
-
295
- Solara provides you with access to the full strength of the Python ecosystem.
296
- This means you can continue using your favorite libraries while expanding your web development capabilities.
297
- """
298
- )
299
- with solara.HBox():
300
- with solara.Link("/documentation"):
301
- solara.Button(label="Read more", class_="ma-1 homepage-button", href="/documentation", color="primary", dark=True)
302
- with solara.Link("/documentation/getting_started"):
303
- solara.Button(label="Quickstart", class_="ma-1 homepage-button", color="primary", dark=True)
304
- # with rv.Col(md=4, sm=5):
305
- # rv.Img(src="https://dxhl76zpt6fap.cloudfront.net/public/landing/what.webp", style_="width:900px")
306
-
307
- with solara.Column(style={"width": "100%"}, gap="2.5em", classes=["pt-10", "mt-8"], align="center"):
308
- with solara.Row(justify="center", gap="2.5em", classes=["ma-2", "row-container"]):
309
- rv.Img(src="https://dxhl76zpt6fap.cloudfront.net/public/landing/complexity.webp", contain=True)
310
- solara.Markdown(
311
- """
312
- # Build **large** apps with **low** code complexity
313
-
314
- With Solara, you can build large scale apps without hitting a complexity wall.
315
-
316
- With other tools you may hit a dead end due to missing features or implementing features
317
- adds too much complexity to your code base.
318
-
319
- Solara offers the **flexibility** to build complex apps, but keeps the **simplicity** of a small code base.
320
- """
321
- )
322
- with solara.Row(justify="center", gap="2.5em", classes=["ma-2", "row-container"]):
323
- solara.Markdown(
324
- """
325
- # The trustworthiness of React
326
-
327
- Using the same API as React, but ported to Python, Solara lets you build apps with the same
328
- trustworthiness as React.
329
-
330
- With a decade of experience, React is battle-tested and proven to be
331
- a reliable and robust framework to build large scale apps.
332
- """
333
- )
334
- with solara.Row(justify="center", style={"width": "500px"}):
335
- rv.Img(src="https://dxhl76zpt6fap.cloudfront.net/public/landing/python-love-react.webp", style_="max-width:300px", contain=True)
336
- with solara.Row(justify="center", gap="2.5em", classes=["ma-2", "row-container"]):
337
- with solara.Column():
338
- if target == 0:
339
- solara.Markdown("#### Running in: Jupyter notebook")
340
- solara.Image(
341
- "https://global.discourse-cdn.com/standard11/uploads/jupyter/original/2X/8/8bc875c0c3845ae077168575a4f8a49cf1b35bc6.gif"
342
- )
343
- else:
344
- solara.Markdown("#### Running in: FastAPI")
345
- solara.Image(
346
- "https://global.discourse-cdn.com/standard11/uploads/jupyter/original/2X/9/9442fc70e2a1fcd201f4f900fa073698a1f8c937.gif"
347
- )
348
- import solara.website.pages.apps.scatter as scatter
349
-
350
- github_url = solara.util.github_url(scatter.__file__)
351
- solara.Button(
352
- label="View source",
353
- icon_name="mdi-github-circle",
354
- attributes={"href": github_url, "target": "_blank"},
355
- text=True,
356
- outlined=False,
357
- )
358
- with solara.Link("/documentation/examples"):
359
- with solara.Column(style="width: 100%;"):
360
- solara.Button(
361
- label="More examples",
362
- icon_name="mdi-brain",
363
- text=True,
364
- outlined=False,
365
- )
366
- with solara.Column():
367
- solara.Markdown(
368
- """
369
- ## Create apps
370
-
371
- In Jupyter or standalone, and run them in production
372
- using FastAPI or starlette.
373
-
374
- Get more inspiration from our [examples](/documentation/examples).
375
- """
376
- )
377
- with rv.ExpansionPanels(v_model=target, on_v_model=set_target, mandatory=True, flat=True):
378
- with rv.ExpansionPanel():
379
- rv.ExpansionPanelHeader(children=["Jupyter notebook"])
380
- with rv.ExpansionPanelContent():
381
- solara.Markdown("Build on top of ipywidgets, solara components work in all Jupyter notebook environments.")
382
- with rv.ExpansionPanel():
383
- rv.ExpansionPanelHeader(children=["FastAPI"])
384
- with rv.ExpansionPanelContent():
385
- solara.Markdown(
386
- """Using [solara-server](documentation/advanced/understanding/solara-server),
387
- we can run our app in production using FastAPI."""
388
- )
389
-
390
- with solara.Column(style={"width": "100%"}):
391
- solara.v.Divider()
392
-
393
- with solara.Column(align="center", gap="2.5em", style={"width": "100%", "padding-bottom": "50px"}):
394
- solara.Markdown("# Testimonials", style="text-align:center")
395
- with solara.Row(justify="center", gap="2.5em", style={"align-items": "stretch", "flex-wrap": "wrap", "row-gap": "2.5em"}):
396
- Testimonial(
397
- "Solara is like streamlit, but for Jupyter. I am really excited to see where this goes!",
398
- "Jack Parmer",
399
- "Former CEO and Co-Founder of Plotly",
400
- "https://dxhl76zpt6fap.cloudfront.net/public/avatar/jack-parmer.jpg",
401
- )
402
- Testimonial(
403
- "Solara has been transformative, allowing us to rapidly create a Jupyter app and iterate with impressive speed.",
404
- "Nick Elprin",
405
- "CEO and Co-Founder of Domino Data Lab",
406
- "https://dxhl76zpt6fap.cloudfront.net/public/avatar/nick-elprin.jpg",
407
- )
408
- Testimonial(
409
- "Solara allows us to go from prototype to production with the same stack.",
410
- "Jonathan Chambers",
411
- "Co-founder of Planeto",
412
- "https://dxhl76zpt6fap.cloudfront.net/public/avatar/jonathan-chambers.jpg",
413
- )
414
-
415
- with solara.Column(style={"width": "100%"}):
416
- solara.v.Divider()
417
-
418
- with solara.Column(align="center", gap="2.5em", style={"width": "100%", "padding-bottom": "50px"}):
419
- solara.Markdown("# Sponsors", style="text-align:center")
420
- with solara.Row(justify="center", gap="2.5em", style={"align-items": "stretch"}):
421
- with solara.v.Html(tag="a", attributes={"href": "https://www.dominodatalab.com/", "target": "_blank"}):
422
- solara.Image("https://dxhl76zpt6fap.cloudfront.net/public/sponsors/domino.png", width="300px")
423
-
424
- with solara.Column(style={"width": "100%"}):
425
- solara.v.Divider()
426
-
427
- with solara.Row(justify="center", gap="2.5em", classes=["footer-wrapper"]):
428
- with solara.Column(align="center", style={"min-width": "300px"}):
429
- solara.Markdown(
430
- """
431
- #### For any consulting, training or support needs
432
- [contact@solara.dev](mailto:contact@solara.dev)
433
- """
434
- )
435
- solara.v.Divider(vertical=True)
436
- with solara.Column(align="center", style={"min-width": "300px"}):
437
- solara.Markdown("#### Join our Mailing list to get the latest news")
438
- with solara.Div(style={"width": "80%"}):
439
- MailChimp(location=router.path)
440
- else:
441
- with rv.Row(
442
- style_="flex-wrap: nowrap; margin: 0; min-height: calc(100vh - 215.5px);",
443
- justify="center" if route_current is not None and route_current.path in ["documentation", "showcase"] else "start",
444
- ):
445
- if route_current is not None and route_current.module is not None and hasattr(route_current.module, "Sidebar"):
446
- with solara.v.NavigationDrawer(
447
- clipped=True,
448
- class_="d-none d-md-block",
449
- height="unset",
450
- style_="min-height: calc(100vh - 215.5px);",
451
- width="20rem",
452
- v_model=True, # Forces menu to display even if it had somehow been closed
453
- ):
454
- route_current.module.Sidebar()
455
- with rv.Col(
456
- tag="main",
457
- md=True,
458
- class_="pa-0",
459
- style_=f"""max-width: {'1024px' if route_current.path not in ['documentation', 'contact', 'changelog']
460
- else 'unset'}; overflow-x: hidden;""",
274
+ with rv.Container(tag="section", fluid=True, ma_0=True, pa_0=True, class_="fill-height solara-content-main"):
275
+ if route_current is None:
276
+ return solara.Error("Page not found")
277
+ else:
278
+ with rv.Row(
279
+ style_="flex-wrap: nowrap; margin: 0; min-height: calc(100vh - 64px);",
280
+ justify="center" if route_current is not None and route_current.path in ["documentation", "showcase"] else "start",
461
281
  ):
462
- if route_current is not None and route_current.path == "/":
463
- with rv.Row(align="center"):
464
- pass
465
- with solara.Row(
466
- children=children,
467
- justify="center",
468
- classes=["solara-page-content-search"],
469
- style=f"height: {'100%' if route_current.path == 'documentation' else 'unset'};",
282
+ if route_current is not None and route_current.module is not None and hasattr(route_current.module, "Sidebar"):
283
+ with solara.v.NavigationDrawer(
284
+ clipped=True,
285
+ class_="d-none d-md-block",
286
+ height="unset",
287
+ style_="min-height: calc(100vh - 64px);",
288
+ width="20rem",
289
+ v_model=True, # Forces menu to display even if it had somehow been closed
290
+ ):
291
+ route_current.module.Sidebar()
292
+ with rv.Col(
293
+ tag="main",
294
+ md=True,
295
+ class_="pa-0",
296
+ style_="max-width: 1024px" if route_current.path == "showcase" else "",
470
297
  ):
471
- pass
472
-
473
- # absolute = True prevents the drawer from being below the overlay it generates
474
- # Drawer navigation for top menu
475
- with rv.NavigationDrawer(
476
- v_model=show_right_menu,
477
- on_v_model=set_show_right_menu,
478
- fixed=True,
479
- absolute=True,
480
- right=True,
481
- hide_overlay=False,
482
- overlay_color="#000000",
483
- overlay_opacity=0.5,
484
- style_="height: 100vh",
485
- ):
486
- Algolia()
487
- with rv.List(nav=True):
488
- with rv.ListItemGroup(active_class="text--primary"):
489
- for route in all_routes:
490
- if route.path == "apps":
491
- continue
492
- with solara.Link(route):
493
- solara.ListItem(route.label)
298
+ with solara.Row(
299
+ children=children,
300
+ justify="center",
301
+ classes=["solara-page-content-search"],
302
+ style="height: unset",
303
+ ):
304
+ pass
494
305
 
495
- if route_current is not None and route_current.module is not None and hasattr(route_current.module, "Sidebar"):
496
- with solara.v.NavigationDrawer(
306
+ # absolute = True prevents the drawer from being below the overlay it generates
307
+ # Drawer navigation for top menu
308
+ with rv.NavigationDrawer(
309
+ v_model=show_right_menu,
310
+ on_v_model=set_show_right_menu,
311
+ fixed=True,
497
312
  absolute=True,
498
- clipped=True,
499
- class_="d-md-none d-block",
500
- height="unset",
501
- style_="min-height: 100vh;",
502
- v_model=show_left_menu,
503
- on_v_model=set_show_left_menu,
504
- width="20rem",
313
+ right=True,
314
+ hide_overlay=False,
315
+ overlay_color="#000000",
316
+ overlay_opacity=0.5,
317
+ style_="height: 100vh",
505
318
  ):
506
- route_current.module.Sidebar()
319
+ Algolia()
320
+ with rv.List(nav=True):
321
+ with rv.ListItemGroup(active_class="text--primary"):
322
+ for route in all_routes:
323
+ if route.path == "apps":
324
+ continue
325
+ with solara.Link(route):
326
+ solara.ListItem(route.label)
327
+
328
+ if route_current is not None and route_current.module is not None and hasattr(route_current.module, "Sidebar"):
329
+ with solara.v.NavigationDrawer(
330
+ absolute=True,
331
+ clipped=True,
332
+ class_="d-md-none d-block",
333
+ height="unset",
334
+ style_="min-height: 100vh;",
335
+ v_model=show_left_menu,
336
+ on_v_model=set_show_left_menu,
337
+ width="20rem",
338
+ ):
339
+ route_current.module.Sidebar()
507
340
 
508
- return main
341
+ return main
509
342
 
510
343
 
511
344
  @solara.component
@@ -0,0 +1,9 @@
1
+ from pathlib import Path
2
+
3
+ from solara.website.components.markdown import MarkdownWithMetadata
4
+
5
+
6
+ title = "About Us"
7
+ HERE = Path(__file__)
8
+
9
+ Page = MarkdownWithMetadata(Path(HERE.parent / "about.md").read_text())
@@ -0,0 +1,3 @@
1
+ # About Us
2
+
3
+ Solara is a framework created by Maarten Breddels, and developed by [Widgetti](https://widgetti.io). Widgetti is a small company based in the Netherlands, focusing on developing tools for the Jupyter ecosystem. We combine ipywidgets and python experience with expertise in front-end development to help data scientists and python app developers make the most of their time. If you could use our years of diverse industry experience, reach out [here](/contact). You can find out more about Solara [here](/documentation/getting_started/introduction), or get to know our team [here](/our_team).
@@ -0,0 +1,27 @@
1
+ import solara
2
+
3
+
4
+ @solara.component
5
+ def Page():
6
+ with solara.Column():
7
+ solara.Markdown(
8
+ """
9
+ # Careers
10
+ We are always looking for talented individuals to join our team. If you're still be interested after reading the rest of this page, reach out at [contact@widgetti.io](mailto:contact@widgetti.io).
11
+
12
+ ## Who Are We?
13
+ We are a small team of developers working in the gap between Jupyter notebooks and web applications. We are passionate about making data science more accessible and app development painless.
14
+ We are based in Groningen, The Netherlands, but work remote first.
15
+
16
+ ## What Do We Offer?
17
+ We offer a flexible work environment, competitive salary, and the opportunity to do meaningful, crossdisciplinary work with scientists and companies worldwide.
18
+ We are a small team, so you will have a lot of freedom in your work, and the chance to get your hands dirty with many projects.
19
+
20
+ ### Open Source
21
+ We are strong believers in open source software. When working with us, you can expect the majority of the software you write to be open source, with contributions to Solara as well as other open source projects.
22
+
23
+ ## Who Are We Looking For?
24
+ We are looking for developers, technical writers, designers, and everything in between.
25
+ """,
26
+ style={"max-width": "90%", "margin": "0 auto"},
27
+ )
@@ -1,10 +1,10 @@
1
1
  from pathlib import Path
2
2
 
3
- import solara
4
3
  from solara.website.components.sidebar import Sidebar
4
+ from solara.website.components import MarkdownWithMetadata
5
5
 
6
6
  title = "Changelog"
7
7
  HERE = Path(__file__)
8
8
 
9
- Page = solara.Markdown(Path(HERE.parent / "changelog.md").read_text())
9
+ Page = MarkdownWithMetadata(Path(HERE.parent / "changelog.md").read_text())
10
10
  Sidebar = Sidebar
@@ -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).
@@ -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