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.
- solara/__init__.py +1 -1
- solara/components/__init__.py +1 -0
- solara/components/input_text_area.py +86 -0
- solara/components/markdown.py +1 -1
- solara/hooks/use_thread.py +4 -4
- solara/lab/components/chat.py +8 -2
- solara/server/assets/style.css +2 -1
- solara/server/flask.py +1 -1
- solara/server/jupyter/server_extension.py +11 -1
- solara/server/jupyter/solara.py +91 -0
- solara/server/patch.py +1 -0
- solara/server/pyinstaller/__init__.py +9 -0
- solara/server/pyinstaller/hook-ipyreact.py +5 -0
- solara/server/pyinstaller/hook-ipyvuetify.py +5 -0
- solara/server/pyinstaller/hook-solara.py +9 -0
- solara/server/server.py +6 -1
- solara/server/starlette.py +18 -6
- solara/server/static/highlight-dark.css +1 -1
- solara/server/static/main-vuetify.js +1 -1
- solara/server/static/solara_bootstrap.py +1 -1
- solara/server/templates/solara.html.j2 +30 -6
- solara/website/assets/custom.css +20 -57
- solara/website/components/__init__.py +2 -2
- solara/website/components/algolia_api.vue +23 -6
- solara/website/components/breadcrumbs.py +28 -0
- solara/website/components/contact.py +144 -0
- solara/website/components/docs.py +11 -9
- solara/website/components/header.py +31 -20
- solara/website/components/markdown.py +12 -1
- solara/website/components/markdown_nav.vue +34 -0
- solara/website/components/sidebar.py +7 -1
- solara/website/pages/__init__.py +87 -254
- solara/website/pages/about/__init__.py +9 -0
- solara/website/pages/about/about.md +3 -0
- solara/website/pages/careers/__init__.py +27 -0
- solara/website/pages/changelog/__init__.py +2 -2
- solara/website/pages/changelog/changelog.md +12 -0
- solara/website/pages/contact/__init__.py +30 -6
- solara/website/pages/documentation/__init__.py +25 -33
- solara/website/pages/documentation/advanced/content/10-howto/40-embed.md +2 -1
- solara/website/pages/documentation/advanced/content/15-reference/41-asset-files.md +1 -1
- solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +2 -1
- solara/website/pages/documentation/advanced/content/30-enterprise/00-overview.md +1 -1
- solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +5 -2
- solara/website/pages/documentation/api/hooks/use_thread.md +6 -0
- solara/website/pages/documentation/components/data/pivot_table.py +2 -2
- solara/website/pages/documentation/components/input/input.py +2 -0
- solara/website/pages/documentation/components/output/sql_code.py +3 -3
- solara/website/pages/documentation/examples/__init__.py +2 -2
- solara/website/pages/documentation/getting_started/content/04-tutorials/_jupyter_dashboard_1.ipynb +2 -2
- solara/website/pages/documentation/getting_started/content/05-fundamentals/10-components.md +19 -14
- solara/website/pages/documentation/getting_started/content/05-fundamentals/50-state-management.md +205 -15
- solara/website/pages/documentation/getting_started/content/07-deploying/10-self-hosted.md +3 -1
- solara/website/pages/home.vue +1199 -0
- solara/website/pages/our_team/__init__.py +83 -0
- solara/website/pages/pricing/__init__.py +31 -0
- solara/website/pages/roadmap/__init__.py +11 -0
- solara/website/pages/roadmap/roadmap.md +41 -0
- solara/website/pages/scale_ipywidgets.py +45 -0
- {solara_ui-1.39.0.dist-info → solara_ui-1.40.0.dist-info}/METADATA +2 -2
- {solara_ui-1.39.0.dist-info → solara_ui-1.40.0.dist-info}/RECORD +65 -49
- solara/website/components/hero.py +0 -15
- solara/website/pages/contact/contact.md +0 -17
- {solara_ui-1.39.0.data → solara_ui-1.40.0.data}/data/etc/jupyter/jupyter_notebook_config.d/solara.json +0 -0
- {solara_ui-1.39.0.data → solara_ui-1.40.0.data}/data/etc/jupyter/jupyter_server_config.d/solara.json +0 -0
- {solara_ui-1.39.0.dist-info → solara_ui-1.40.0.dist-info}/WHEEL +0 -0
- {solara_ui-1.39.0.dist-info → solara_ui-1.40.0.dist-info}/licenses/LICENSE +0 -0
solara/website/assets/custom.css
CHANGED
|
@@ -34,6 +34,17 @@
|
|
|
34
34
|
--docs-social-twitter: #000000;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
.theme--dark {
|
|
38
|
+
--color-border-appbar: hsla(0,0%,100%,.12);
|
|
39
|
+
--color-material-background: #1e1e1e;
|
|
40
|
+
--color-text-fade: hsla(0,0%,100%,.7);
|
|
41
|
+
}
|
|
42
|
+
.theme--light {
|
|
43
|
+
--color-border-appbar: rgba(0,0,0,.12);
|
|
44
|
+
--color-material-background: #fff;
|
|
45
|
+
--color-text-fade: rgba(0,0,0,.6);
|
|
46
|
+
}
|
|
47
|
+
|
|
37
48
|
html,
|
|
38
49
|
body,
|
|
39
50
|
p,
|
|
@@ -199,9 +210,8 @@ blockquote p:last-child {
|
|
|
199
210
|
}
|
|
200
211
|
.v-sheet.docs-card-container{
|
|
201
212
|
width: 100%;
|
|
202
|
-
padding: 0 10%;
|
|
203
213
|
justify-content: start;
|
|
204
|
-
align-content:
|
|
214
|
+
align-content: stretch;
|
|
205
215
|
flex-wrap: wrap !important;
|
|
206
216
|
flex-grow: 1;
|
|
207
217
|
row-gap: 20px;
|
|
@@ -211,11 +221,14 @@ blockquote p:last-child {
|
|
|
211
221
|
}
|
|
212
222
|
.v-sheet.docs-card-container > a > .docs-card{
|
|
213
223
|
display: flex;
|
|
214
|
-
|
|
215
|
-
height:
|
|
224
|
+
flex-grow: 1;
|
|
225
|
+
height: 4rem;
|
|
216
226
|
border-radius: 16px !important;
|
|
217
227
|
color: var(--color-grey-light);
|
|
218
228
|
}
|
|
229
|
+
.v-sheet.docs-card-container > a > .docs-card > h2 {
|
|
230
|
+
padding: 0 24px;
|
|
231
|
+
}
|
|
219
232
|
.v-sheet.docs-card-container > a .docs-card-icon{
|
|
220
233
|
padding-right: 1.5rem;
|
|
221
234
|
transition: ease padding 0.25s;
|
|
@@ -274,6 +287,8 @@ blockquote p:last-child {
|
|
|
274
287
|
/* header */
|
|
275
288
|
.header-logo {
|
|
276
289
|
display: block;
|
|
290
|
+
height: 100%;
|
|
291
|
+
margin: 0;
|
|
277
292
|
}
|
|
278
293
|
.news {
|
|
279
294
|
background-color: var(--color-primary);
|
|
@@ -289,46 +304,6 @@ blockquote p:last-child {
|
|
|
289
304
|
color: white !important;
|
|
290
305
|
}
|
|
291
306
|
|
|
292
|
-
/* hero */
|
|
293
|
-
.hero {
|
|
294
|
-
background: var(--color-primary-lightest) url(https://dxhl76zpt6fap.cloudfront.net/public/hero.webp);
|
|
295
|
-
background-size: cover;
|
|
296
|
-
min-height: 660px;
|
|
297
|
-
padding: 7rem 0;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
.theme--dark .hero {
|
|
301
|
-
background: var(--dark-color-primary-lightest) url(https://dxhl76zpt6fap.cloudfront.net/public/hero.webp);
|
|
302
|
-
background-size: cover;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
.hero h1 {
|
|
306
|
-
font-size: 4.5rem;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
.hero h2 {
|
|
310
|
-
padding-left: 150px;
|
|
311
|
-
padding-right: 150px;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
.hero b {
|
|
315
|
-
color: var(--color-primary);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
.theme--dark .hero b {
|
|
319
|
-
color: var(--dark-color-primary);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
@media screen and (max-width: 960px) {
|
|
323
|
-
.hero {
|
|
324
|
-
padding: 4rem 0;
|
|
325
|
-
min-height: auto;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
.hero h1 {
|
|
329
|
-
font-size: 3rem;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
307
|
|
|
333
308
|
/* fixes padding issue on drawer menu */
|
|
334
309
|
.v-list-group__items {
|
|
@@ -362,7 +337,7 @@ blockquote p:last-child {
|
|
|
362
337
|
|
|
363
338
|
.menu li a:link {
|
|
364
339
|
display: block;
|
|
365
|
-
padding:
|
|
340
|
+
padding: 0.75rem;
|
|
366
341
|
}
|
|
367
342
|
|
|
368
343
|
.menu .active {
|
|
@@ -427,11 +402,6 @@ blockquote p:last-child {
|
|
|
427
402
|
font-weight: bolder;
|
|
428
403
|
}
|
|
429
404
|
|
|
430
|
-
.solara-autorouter-content {
|
|
431
|
-
padding-top: 2rem;
|
|
432
|
-
max-width: 100%;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
405
|
.jp-RenderedHTMLCommon {
|
|
436
406
|
padding-right: 0;
|
|
437
407
|
}
|
|
@@ -457,13 +427,6 @@ blockquote p:last-child {
|
|
|
457
427
|
/* MOBILE */
|
|
458
428
|
|
|
459
429
|
@media screen and (aspect-ratio < 1) {
|
|
460
|
-
.hero{
|
|
461
|
-
background-position-x: 29%;
|
|
462
|
-
}
|
|
463
|
-
.hero h2{
|
|
464
|
-
padding-left: 0;
|
|
465
|
-
padding-right: 0;
|
|
466
|
-
}
|
|
467
430
|
.container.fill-height > .ma-8.row{
|
|
468
431
|
max-width: 80%;
|
|
469
432
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from .docs import CategoryLayout, Gallery, NoPage, SubCategoryLayout, WithCode # noqa
|
|
2
2
|
from .header import Header
|
|
3
|
-
from .
|
|
3
|
+
from .markdown import MarkdownWithMetadata
|
|
4
4
|
|
|
5
|
-
__all__ = ["Header", "
|
|
5
|
+
__all__ = ["Header", "MarkdownWithMetadata", "CategoryLayout", "Gallery", "NoPage", "SubCategoryLayout", "WithCode"]
|
|
@@ -7,14 +7,19 @@
|
|
|
7
7
|
v-model="query"
|
|
8
8
|
prepend-inner-icon="mdi-magnify"
|
|
9
9
|
hide-details
|
|
10
|
+
dense
|
|
10
11
|
:placeholder="mac ? '⌘K to search' : 'Ctrl+K to search'"
|
|
12
|
+
filled
|
|
11
13
|
outlined
|
|
12
|
-
rounded
|
|
13
14
|
clearable
|
|
14
15
|
ref="search"
|
|
15
16
|
style="flex-grow: 1; max-width: 650px;"
|
|
16
17
|
@click="show($event, on);"
|
|
17
|
-
@keyup.enter="item = 0"
|
|
18
|
+
@keyup.enter="hoverItem === null ? item = 0 : item = hoverItem"
|
|
19
|
+
@keyup.esc="close();"
|
|
20
|
+
@keyup.down="hoverItem = hoverItem == null ? 0 : Math.min(hoverItem + 1, results.hits.length - 1, 9)"
|
|
21
|
+
@keyup.up="hoverItem = hoverItem == null ? 9 : Math.max(hoverItem - 1, 0)"
|
|
22
|
+
@focus="selectText();"
|
|
18
23
|
class="algolia"
|
|
19
24
|
></v-text-field>
|
|
20
25
|
</template>
|
|
@@ -27,7 +32,7 @@
|
|
|
27
32
|
</v-list>
|
|
28
33
|
<v-list v-else :style="{width: menuWidth + 'px'}">
|
|
29
34
|
<v-list-item-group v-model="item">
|
|
30
|
-
<v-list-item v-for="(element, index) in this.results.hits" :key="element['url']">
|
|
35
|
+
<v-list-item v-for="(element, index) in this.results.hits" :key="element['url']" :input-value="index === hoverItem">
|
|
31
36
|
<v-list-item-content>
|
|
32
37
|
<v-list-item-title>
|
|
33
38
|
{{ element.hierarchy.lvl1 }}
|
|
@@ -39,7 +44,7 @@
|
|
|
39
44
|
</v-list-item-content>
|
|
40
45
|
</v-list-item>
|
|
41
46
|
</v-list-item-group>
|
|
42
|
-
<v-list-item>
|
|
47
|
+
<v-list-item v-if="this.results.nbHits > 10">
|
|
43
48
|
<v-list-item-content>
|
|
44
49
|
<v-list-item-title>And {{ this.results.nbHits - 10}} More...</v-list-item-title>
|
|
45
50
|
</v-list-item-content>
|
|
@@ -58,7 +63,6 @@ module.exports = {
|
|
|
58
63
|
window.search = this;
|
|
59
64
|
this.updateMenuWidth();
|
|
60
65
|
window.addEventListener('resize', this.updateMenuWidth);
|
|
61
|
-
|
|
62
66
|
},
|
|
63
67
|
watch: {
|
|
64
68
|
query ( value ) {
|
|
@@ -66,12 +70,17 @@ module.exports = {
|
|
|
66
70
|
this.search();
|
|
67
71
|
},
|
|
68
72
|
item ( value ) {
|
|
69
|
-
if (
|
|
73
|
+
if ( value === null ) return;
|
|
74
|
+
if ( this.results.hits != null && this.results.hits.length >= value ) {
|
|
70
75
|
let url = this.results.hits[value].url;
|
|
71
76
|
if (url.startsWith("https://solara.dev")) {
|
|
72
77
|
url = url.slice(18);
|
|
73
78
|
}
|
|
74
79
|
solara.router.push( url );
|
|
80
|
+
this.close();
|
|
81
|
+
// reset the search
|
|
82
|
+
this.item = null;
|
|
83
|
+
this.hoverItem = null;
|
|
75
84
|
}
|
|
76
85
|
},
|
|
77
86
|
},
|
|
@@ -82,6 +91,10 @@ module.exports = {
|
|
|
82
91
|
on.click( e )
|
|
83
92
|
} );
|
|
84
93
|
},
|
|
94
|
+
close() {
|
|
95
|
+
this.show_results = false;
|
|
96
|
+
this.$refs.search.blur();
|
|
97
|
+
},
|
|
85
98
|
initSearch() {
|
|
86
99
|
this.client = this.algoliasearch( '9KW9L7O5EQ', '647ca12ba642437cc40c2adee4a78d08' );
|
|
87
100
|
this.index = this.client.initIndex( 'solara' );
|
|
@@ -107,6 +120,9 @@ module.exports = {
|
|
|
107
120
|
this.$set(this.results, []);
|
|
108
121
|
}
|
|
109
122
|
},
|
|
123
|
+
selectText() {
|
|
124
|
+
this.$refs.search.$refs.input.select();
|
|
125
|
+
},
|
|
110
126
|
getSnippet( element ) {
|
|
111
127
|
if (element.type == "content") {
|
|
112
128
|
return element._highlightResult.content.value;
|
|
@@ -176,6 +192,7 @@ module.exports = {
|
|
|
176
192
|
query: '',
|
|
177
193
|
results: [],
|
|
178
194
|
item: null,
|
|
195
|
+
hoverItem: null,
|
|
179
196
|
show_results: false,
|
|
180
197
|
mac: false,
|
|
181
198
|
menuWidth: 0,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
import solara
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@solara.component
|
|
6
|
+
def BreadCrumbs():
|
|
7
|
+
router = solara.use_router()
|
|
8
|
+
routes = router.path_routes
|
|
9
|
+
|
|
10
|
+
with solara.Row(style={"align-items": "center", "flex-wrap": "wrap"}) as main:
|
|
11
|
+
for i, route in enumerate(routes):
|
|
12
|
+
if i == len(routes) - 1:
|
|
13
|
+
solara.Text(route.label or route.path, style={"color": "var(--color-text-fade)"})
|
|
14
|
+
else:
|
|
15
|
+
with solara.Link(solara.resolve_path(route), style={"color": "var(--color-text-fade)"}):
|
|
16
|
+
solara.Text(route.label or route.path)
|
|
17
|
+
if i != len(routes) - 1:
|
|
18
|
+
solara.Text("/", style={"font-size": "1.5rem", "color": "var(--color-text-fade)"})
|
|
19
|
+
return main
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _resolve_path_to_route(path_to_find: List[str], all_routes: List[solara.Route], routes: List[solara.Route] = []):
|
|
23
|
+
if len(path_to_find) == 0:
|
|
24
|
+
return routes
|
|
25
|
+
for route in all_routes:
|
|
26
|
+
if path_to_find[0] == route.path:
|
|
27
|
+
routes += [route]
|
|
28
|
+
return _resolve_path_to_route(path_to_find[1:], route.children, routes)
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import requests
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, Optional
|
|
6
|
+
import solara
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
postmark_api_key = None
|
|
10
|
+
contact_email_address = None
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
postmark_api_key = os.environ["POSTMARK_API_KEY"]
|
|
14
|
+
contact_email_address = os.environ["SOLARA_CONTACT_EMAIL_ADDRESS"]
|
|
15
|
+
except Exception:
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@solara.component
|
|
20
|
+
def Contact(
|
|
21
|
+
style: Dict[str, Any] = {},
|
|
22
|
+
title="Contact Us",
|
|
23
|
+
subtitle="We'd love to hear from you!",
|
|
24
|
+
submit_label="Submit",
|
|
25
|
+
email_subject="Contact Form Submission",
|
|
26
|
+
):
|
|
27
|
+
first_name = solara.use_reactive("")
|
|
28
|
+
last_name = solara.use_reactive("")
|
|
29
|
+
email = solara.use_reactive("")
|
|
30
|
+
company = solara.use_reactive("")
|
|
31
|
+
message = solara.use_reactive("")
|
|
32
|
+
error: solara.Reactive[Optional[str]] = solara.use_reactive(None)
|
|
33
|
+
success = solara.use_reactive(False)
|
|
34
|
+
|
|
35
|
+
def send(*_ignore):
|
|
36
|
+
if postmark_api_key is None or contact_email_address is None:
|
|
37
|
+
error.set("Email service not properly configured. Please contact the site administrator at solara@widgetti.io.")
|
|
38
|
+
elif not first_name.value or not last_name.value or not email.value or not message.value:
|
|
39
|
+
error.set("Please fill out all required fields.")
|
|
40
|
+
else:
|
|
41
|
+
# Create the email content
|
|
42
|
+
msg = {}
|
|
43
|
+
msg["From"] = contact_email_address
|
|
44
|
+
msg["To"] = contact_email_address
|
|
45
|
+
msg["Subject"] = email_subject
|
|
46
|
+
msg["ReplyTo"] = email.value
|
|
47
|
+
|
|
48
|
+
# Email body
|
|
49
|
+
msg["HtmlBody"] = f"""
|
|
50
|
+
<b>First Name</b>: {first_name.value}<br />
|
|
51
|
+
<b>Last Name</b>: {last_name.value}<br />
|
|
52
|
+
<b>Email</b>: {email.value}<br />
|
|
53
|
+
<b>Company</b>: {company.value}<br />
|
|
54
|
+
<b>Message</b>: {message.value}<br />
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
# Send emails
|
|
58
|
+
try:
|
|
59
|
+
requests.post(
|
|
60
|
+
"https://api.postmarkapp.com/email",
|
|
61
|
+
headers={
|
|
62
|
+
"Accept": "application/json",
|
|
63
|
+
"Content-Type": "application/json",
|
|
64
|
+
"X-Postmark-Server-Token": postmark_api_key,
|
|
65
|
+
},
|
|
66
|
+
data=json.dumps(msg),
|
|
67
|
+
)
|
|
68
|
+
requests.post(
|
|
69
|
+
"https://api.postmarkapp.com/email",
|
|
70
|
+
headers={
|
|
71
|
+
"Accept": "application/json",
|
|
72
|
+
"Content-Type": "application/json",
|
|
73
|
+
"X-Postmark-Server-Token": postmark_api_key,
|
|
74
|
+
},
|
|
75
|
+
data=json.dumps(
|
|
76
|
+
{
|
|
77
|
+
"From": contact_email_address,
|
|
78
|
+
"To": email.value,
|
|
79
|
+
"Subject": "Thank you for contacting Solara",
|
|
80
|
+
"HtmlBody": f"""
|
|
81
|
+
<p>Hi {first_name.value},</p>
|
|
82
|
+
<p>Thank you for contacting us! We will get back to you as soon as possible.</p>
|
|
83
|
+
<p>Best regards,<br />The Solara Team</p>
|
|
84
|
+
""",
|
|
85
|
+
}
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
except Exception as e:
|
|
89
|
+
error.set(f"Error sending email: {e}")
|
|
90
|
+
else:
|
|
91
|
+
success.set(True)
|
|
92
|
+
error.set(None)
|
|
93
|
+
first_name.set("")
|
|
94
|
+
last_name.set("")
|
|
95
|
+
email.set("")
|
|
96
|
+
company.set("")
|
|
97
|
+
message.set("")
|
|
98
|
+
|
|
99
|
+
with solara.Card(title=title, style={"width": "100%", "max-width": "1024px", **style}):
|
|
100
|
+
solara.Markdown(subtitle)
|
|
101
|
+
solara.Text("* Required fields")
|
|
102
|
+
with solara.Row():
|
|
103
|
+
solara.InputText(label="First Name *", value=first_name)
|
|
104
|
+
solara.InputText(label="Last Name *", value=last_name)
|
|
105
|
+
with solara.Row():
|
|
106
|
+
solara.InputText(label="Email *", value=email)
|
|
107
|
+
solara.InputText(label="Company", value=company)
|
|
108
|
+
solara.v.Textarea(placeholder="Message *", v_model=message.value, on_v_model=message.set)
|
|
109
|
+
with solara.CardActions():
|
|
110
|
+
solara.Button(label=submit_label, color="primary", on_click=send)
|
|
111
|
+
solara.Button(
|
|
112
|
+
label="Clear",
|
|
113
|
+
color="secondary",
|
|
114
|
+
text=True,
|
|
115
|
+
on_click=lambda: [first_name.set(""), last_name.set(""), email.set(""), company.set(""), message.set("")],
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
solara.Style(
|
|
119
|
+
"""
|
|
120
|
+
.v-snack__wrapper {
|
|
121
|
+
box-shadow: none;
|
|
122
|
+
}
|
|
123
|
+
"""
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
with solara.v.Snackbar(
|
|
127
|
+
v_model=error.value is not None,
|
|
128
|
+
timeout=5000,
|
|
129
|
+
on_v_model=lambda *_: error.set(None),
|
|
130
|
+
left=True,
|
|
131
|
+
color="error",
|
|
132
|
+
):
|
|
133
|
+
solara.Markdown(error.value or "", style={"--dark-color-text": "white", "--color-text": "white"})
|
|
134
|
+
solara.Button(icon=True, icon_name="mdi-close", color="white", on_click=lambda: error.set(None))
|
|
135
|
+
|
|
136
|
+
with solara.v.Snackbar(
|
|
137
|
+
v_model=success.value,
|
|
138
|
+
timeout=5000,
|
|
139
|
+
on_v_model=lambda *_: success.set(False),
|
|
140
|
+
left=True,
|
|
141
|
+
color="success",
|
|
142
|
+
):
|
|
143
|
+
solara.Markdown("Your message has been sent!", style={"--dark-color-text": "white", "--color-text": "white"})
|
|
144
|
+
solara.Button(icon=True, icon_name="mdi-close", color="white", on_click=lambda: success.set(False))
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import solara
|
|
2
|
-
from
|
|
2
|
+
from .markdown import MarkdownWithMetadata
|
|
3
|
+
from .breadcrumbs import BreadCrumbs
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
@solara.component
|
|
@@ -66,18 +67,19 @@ def NoPage():
|
|
|
66
67
|
|
|
67
68
|
|
|
68
69
|
@solara.component
|
|
69
|
-
def WithCode(
|
|
70
|
-
component = getattr(module, "Page", None)
|
|
71
|
-
with
|
|
70
|
+
def WithCode(route_current):
|
|
71
|
+
component = getattr(route_current.module, "Page", None)
|
|
72
|
+
with solara.Column(style={"flex-grow": 1, "padding-top": "56px"}) as main:
|
|
73
|
+
BreadCrumbs()
|
|
72
74
|
# It renders code better
|
|
73
|
-
|
|
74
|
-
module.__doc__ or "# no docs yet",
|
|
75
|
+
MarkdownWithMetadata(
|
|
76
|
+
route_current.module.__doc__ or "# no docs yet",
|
|
75
77
|
unsafe_solara_execute=True,
|
|
76
78
|
)
|
|
77
79
|
if component and component != NoPage:
|
|
78
80
|
with solara.Card("Example", margin=0, classes=["mt-8"]):
|
|
79
81
|
component()
|
|
80
|
-
github_url = solara.util.github_url(module.__file__)
|
|
82
|
+
github_url = solara.util.github_url(route_current.module.__file__)
|
|
81
83
|
solara.Button(
|
|
82
84
|
label="View source",
|
|
83
85
|
icon_name="mdi-github-circle",
|
|
@@ -97,7 +99,7 @@ def SubCategoryLayout(children=[]):
|
|
|
97
99
|
elif route_current.path == "/":
|
|
98
100
|
return solara.Error("Not supposed to be rendered")
|
|
99
101
|
elif route_current.module:
|
|
100
|
-
WithCode(route_current
|
|
102
|
+
WithCode(route_current)
|
|
101
103
|
else:
|
|
102
104
|
with solara.Column(align="center", children=children, style={"flex-grow": 1, "padding": "0"}) as main:
|
|
103
105
|
pass
|
|
@@ -113,6 +115,6 @@ def CategoryLayout(children=[]):
|
|
|
113
115
|
if route_current.path == "/":
|
|
114
116
|
return Gallery()
|
|
115
117
|
else:
|
|
116
|
-
with solara.Column(align="stretch", style={"width": "
|
|
118
|
+
with solara.Column(align="stretch", children=children, style={"max-width": "100%"}) as main:
|
|
117
119
|
pass
|
|
118
120
|
return main
|
|
@@ -20,34 +20,44 @@ def Header(
|
|
|
20
20
|
|
|
21
21
|
# set states for menu
|
|
22
22
|
with solara.Column(gap="0px"):
|
|
23
|
-
with solara.Div(classes=["news"]):
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
with solara.v.AppBar(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
# with solara.Div(classes=["news"]):
|
|
24
|
+
# solara.HTML(
|
|
25
|
+
# "div",
|
|
26
|
+
# unsafe_innerHTML="<a href='https://github.com/widgetti/solara' target='_blank' >Star us on github 🤩</a>",
|
|
27
|
+
# )
|
|
28
|
+
with solara.v.AppBar(
|
|
29
|
+
tag="header", flat=True, clipped_left=True, style_="background-color: transparent; border-bottom: 1px solid var(--color-border-appbar);"
|
|
30
|
+
):
|
|
31
|
+
if route_current is not None and route_current.module is not None and hasattr(route_current.module, "Sidebar"):
|
|
32
|
+
with solara.Button(icon=True, class_="hidden-md-and-up", on_click=lambda: on_toggle_left_menu and on_toggle_left_menu()):
|
|
33
|
+
rv.Icon(children=["mdi-menu"])
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
display = " d-none d-sm-flex" if route_current is not None and route_current.path not in ["about", "pricing", "careers"] else " d-flex"
|
|
36
|
+
with solara.v.Html(
|
|
37
|
+
tag="div",
|
|
38
|
+
class_="header-logo-container" + display,
|
|
39
|
+
style_="""
|
|
40
|
+
background-color: transparent;
|
|
41
|
+
flex-grow: 1;
|
|
42
|
+
align-items: stretch;
|
|
43
|
+
max-height: 65%;
|
|
44
|
+
""",
|
|
36
45
|
):
|
|
37
|
-
with solara.Link(path_or_route="/"):
|
|
46
|
+
with solara.Link(path_or_route="/", style={"display": "flex", "align-items": "center", "flex-direction": "row", "gap": "10px"}):
|
|
38
47
|
solara.Image(router.root_path + f"/static/assets/images/logo{'_white' if dark_effective else ''}.svg", classes=["header-logo"])
|
|
48
|
+
solara.Text("API", style={"font-size": "20px", "font-weight": "600"})
|
|
39
49
|
|
|
40
|
-
|
|
50
|
+
if route_current is not None and route_current.path not in ["about", "pricing", "careers"]:
|
|
41
51
|
if settings.search.enabled:
|
|
42
52
|
from solara_enterprise.search.search import Search
|
|
43
53
|
|
|
44
54
|
Search()
|
|
45
55
|
else:
|
|
46
|
-
|
|
47
|
-
Algolia()
|
|
56
|
+
Algolia()
|
|
48
57
|
|
|
58
|
+
with rv.Html(tag="ul", class_="main-menu menu d-none d-md-flex", style_="justify-content: flex-end;"):
|
|
49
59
|
for route in all_routes:
|
|
50
|
-
if route.path in ["apps", "contact", "changelog"]:
|
|
60
|
+
if route.path in ["apps", "contact", "changelog", "our_team", "about", "pricing", "roadmap", "careers"]:
|
|
51
61
|
continue
|
|
52
62
|
current = route_current == route
|
|
53
63
|
with rv.Html(tag="li", class_="active" if current else None):
|
|
@@ -58,7 +68,8 @@ def Header(
|
|
|
58
68
|
with rv.Btn(icon=True, tag="a", class_="d-none d-md-flex", attributes={"href": "https://discord.solara.dev", "target": "_blank"}):
|
|
59
69
|
rv.Icon(children=["mdi-discord"])
|
|
60
70
|
|
|
61
|
-
solara.
|
|
71
|
+
with solara.v.Html(tag="div", class_="d-none d-md-flex"):
|
|
72
|
+
solara.lab.ThemeToggle()
|
|
62
73
|
|
|
63
|
-
with solara.Button(icon=True, class_="hidden-md-and-up", on_click=lambda: on_toggle_right_menu and on_toggle_right_menu()):
|
|
64
|
-
|
|
74
|
+
# with solara.Button(icon=True, class_="hidden-md-and-up", on_click=lambda: on_toggle_right_menu and on_toggle_right_menu()):
|
|
75
|
+
# rv.Icon(children=["mdi-menu"])
|
|
@@ -27,4 +27,15 @@ def MarkdownWithMetadata(content: str, unsafe_solara_execute=True):
|
|
|
27
27
|
solara.Meta(property=key, content=value)
|
|
28
28
|
else:
|
|
29
29
|
solara.Meta(name=key, content=value)
|
|
30
|
-
solara.
|
|
30
|
+
with solara.v.Html(
|
|
31
|
+
tag="div",
|
|
32
|
+
style_="display: flex; flex-direction: row; justify-content: center; gap: 15px; max-width: 90%; margin: 0 auto;",
|
|
33
|
+
attributes={"id": "markdown-to-navigate"},
|
|
34
|
+
):
|
|
35
|
+
solara.Markdown(content, unsafe_solara_execute=unsafe_solara_execute, style="flex-grow: 1; max-width: min(100%, 1024px);")
|
|
36
|
+
MarkdownNavigation(id="markdown-to-navigate").key("markdown-nav" + str(hash(content)))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@solara.component_vue("markdown_nav.vue")
|
|
40
|
+
def MarkdownNavigation(id: str):
|
|
41
|
+
pass
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-list dense :style="`margin: 40px 24px 0 24px; position: sticky; top: 88px; align-self: flex-start;`" class="d-none d-lg-inline-block">
|
|
3
|
+
<v-list-item
|
|
4
|
+
v-for="(element, index) in this.sections"
|
|
5
|
+
:key="index"
|
|
6
|
+
:href="'#' + element.id"
|
|
7
|
+
:style="'padding-left: ' + (16 + (element.nodeName[1] - 1) * 20) + 'px;'"
|
|
8
|
+
>
|
|
9
|
+
<v-list-item-content>
|
|
10
|
+
<v-list-item-title>
|
|
11
|
+
{{ element.innerText }}
|
|
12
|
+
</v-list-item-title>
|
|
13
|
+
</v-list-item-content>
|
|
14
|
+
</v-list-item>
|
|
15
|
+
</v-list>
|
|
16
|
+
</template>
|
|
17
|
+
<script>
|
|
18
|
+
module.exports = {
|
|
19
|
+
mounted() {
|
|
20
|
+
this.getSections();
|
|
21
|
+
},
|
|
22
|
+
methods: {
|
|
23
|
+
getSections() {
|
|
24
|
+
const parentToSearch = document.getElementById(this.id);
|
|
25
|
+
this.sections = parentToSearch.querySelectorAll('h1, h2, h3, h4');
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
data() {
|
|
29
|
+
return {
|
|
30
|
+
sections: []
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
</script>
|
|
@@ -14,7 +14,9 @@ def Sidebar():
|
|
|
14
14
|
all_routes = route.children
|
|
15
15
|
break
|
|
16
16
|
|
|
17
|
-
with solara.v.List(
|
|
17
|
+
with solara.v.List(
|
|
18
|
+
expand=True, nav=True, style_="height: 100%; display: flex; flex-direction: column; background-color: var(--color-material-background);"
|
|
19
|
+
) as main:
|
|
18
20
|
with solara.v.ListItemGroup(v_model=router.path):
|
|
19
21
|
# e.g. getting_started, examples, components, api, advanced, faq
|
|
20
22
|
for route in all_routes:
|
|
@@ -93,5 +95,9 @@ def Sidebar():
|
|
|
93
95
|
with solara.v.ListItem(value="/changelog"):
|
|
94
96
|
solara.v.ListItemIcon(children=[solara.v.Icon(children=["mdi-history"])])
|
|
95
97
|
solara.v.ListItemTitle(style_="padding: 0 20px;", children=["Changelog"])
|
|
98
|
+
with solara.Link("/roadmap"):
|
|
99
|
+
with solara.v.ListItem(value="/roadmap"):
|
|
100
|
+
solara.v.ListItemIcon(children=[solara.v.Icon(children=["mdi-road"])])
|
|
101
|
+
solara.v.ListItemTitle(style_="padding: 0 20px;", children=["Roadmap"])
|
|
96
102
|
|
|
97
103
|
return main
|