solara-ui 1.40.0__py2.py3-none-any.whl → 1.42.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/__main__.py +30 -11
- solara/_stores.py +185 -0
- solara/components/component_vue.py +26 -2
- solara/components/echarts.py +5 -2
- solara/components/echarts.vue +22 -5
- solara/components/file_drop.py +20 -0
- solara/components/input.py +16 -0
- solara/components/markdown.py +22 -13
- solara/components/spinner-solara.vue +2 -2
- solara/components/spinner.py +17 -2
- solara/hooks/use_reactive.py +8 -1
- solara/reactive.py +9 -3
- solara/server/assets/style.css +2 -0
- solara/server/kernel.py +2 -1
- solara/server/qt.py +113 -0
- solara/server/settings.py +1 -0
- solara/server/starlette.py +2 -2
- solara/server/static/main-vuetify.js +10 -0
- solara/server/static/solara_bootstrap.py +1 -1
- solara/server/templates/loader-solara.html +1 -1
- solara/server/templates/solara.html.j2 +6 -1
- solara/settings.py +14 -0
- solara/template/portal/pyproject.toml +1 -1
- solara/test/pytest_plugin.py +3 -0
- solara/toestand.py +139 -16
- solara/util.py +22 -0
- solara/website/components/markdown.py +45 -1
- solara/website/components/sidebar.py +3 -1
- solara/website/pages/__init__.py +13 -7
- solara/website/pages/changelog/changelog.md +9 -0
- solara/website/pages/documentation/advanced/content/20-understanding/40-routing.md +17 -1
- solara/website/pages/documentation/api/cross_filter/cross_filter_dataframe.py +4 -5
- solara/website/pages/documentation/api/cross_filter/cross_filter_report.py +3 -5
- solara/website/pages/documentation/api/cross_filter/cross_filter_select.py +3 -5
- solara/website/pages/documentation/api/cross_filter/cross_filter_slider.py +3 -5
- solara/website/pages/documentation/api/hooks/use_cross_filter.py +3 -5
- solara/website/pages/documentation/api/hooks/use_exception.py +9 -11
- solara/website/pages/documentation/api/hooks/use_previous.py +6 -9
- solara/website/pages/documentation/api/hooks/use_state_or_update.py +23 -26
- solara/website/pages/documentation/api/hooks/use_thread.py +11 -13
- solara/website/pages/documentation/api/utilities/on_kernel_start.py +17 -0
- solara/website/pages/documentation/components/input/input.py +22 -0
- solara/website/pages/documentation/components/viz/echarts.py +3 -1
- solara/website/pages/documentation/examples/__init__.py +13 -21
- solara/website/pages/documentation/examples/ai/chatbot.py +1 -1
- solara/website/pages/documentation/examples/general/pokemon_search.py +3 -3
- solara/website/pages/documentation/examples/general/vue_component.py +1 -1
- solara/website/pages/documentation/examples/libraries/altair.py +1 -0
- solara/website/pages/documentation/examples/libraries/bqplot.py +1 -1
- solara/website/pages/documentation/examples/libraries/ipyleaflet.py +1 -1
- solara/website/pages/documentation/examples/libraries/ipyleaflet_advanced.py +1 -1
- solara/website/pages/documentation/examples/utilities/countdown_timer.py +18 -20
- solara/website/pages/documentation/examples/visualization/annotator.py +1 -3
- solara/website/pages/documentation/examples/visualization/linked_views.py +3 -6
- solara/website/pages/documentation/getting_started/content/00-quickstart.md +19 -1
- solara/website/pages/documentation/getting_started/content/01-introduction.md +1 -1
- solara/website/pages/roadmap/roadmap.md +3 -0
- solara/widgets/vue/navigator.vue +46 -16
- solara/widgets/vue/vegalite.vue +18 -0
- {solara_ui-1.40.0.dist-info → solara_ui-1.42.0.dist-info}/METADATA +8 -5
- {solara_ui-1.40.0.dist-info → solara_ui-1.42.0.dist-info}/RECORD +66 -64
- {solara_ui-1.40.0.dist-info → solara_ui-1.42.0.dist-info}/WHEEL +1 -1
- {solara_ui-1.40.0.data → solara_ui-1.42.0.data}/data/etc/jupyter/jupyter_notebook_config.d/solara.json +0 -0
- {solara_ui-1.40.0.data → solara_ui-1.42.0.data}/data/etc/jupyter/jupyter_server_config.d/solara.json +0 -0
- {solara_ui-1.40.0.dist-info → solara_ui-1.42.0.dist-info}/licenses/LICENSE +0 -0
solara/util.py
CHANGED
|
@@ -31,6 +31,28 @@ except RuntimeError:
|
|
|
31
31
|
has_threads = False
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
from reacton.utils import equals as equals_extra
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def equals_pickle(a, b):
|
|
38
|
+
"""Compare two values for equality.
|
|
39
|
+
|
|
40
|
+
Avoid false negative, e.g. when comparing dataframes, we want to compare
|
|
41
|
+
the data, not the object identity.
|
|
42
|
+
|
|
43
|
+
"""
|
|
44
|
+
if equals_extra(a, b):
|
|
45
|
+
return True
|
|
46
|
+
import pickle
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
if pickle.dumps(a) == pickle.dumps(b):
|
|
50
|
+
return True
|
|
51
|
+
except Exception:
|
|
52
|
+
pass
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
|
|
34
56
|
def github_url(file):
|
|
35
57
|
rel_path = os.path.relpath(file, Path(solara.__file__).parent.parent)
|
|
36
58
|
github_url = solara.github_url + f"/blob/{solara.git_branch}/" + rel_path
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
from typing import Dict, List, Union
|
|
2
2
|
|
|
3
3
|
import yaml
|
|
4
|
+
import markdown
|
|
5
|
+
import mkdocs_pycafe
|
|
6
|
+
import pymdownx.superfences
|
|
4
7
|
|
|
5
8
|
import solara
|
|
9
|
+
from solara.components.markdown import formatter, _no_deep_copy_emojione
|
|
6
10
|
|
|
7
11
|
|
|
8
12
|
# We want to separate metadata from the markdown files before rendering them, which solara.Markdown doesn't support
|
|
@@ -27,12 +31,52 @@ def MarkdownWithMetadata(content: str, unsafe_solara_execute=True):
|
|
|
27
31
|
solara.Meta(property=key, content=value)
|
|
28
32
|
else:
|
|
29
33
|
solara.Meta(name=key, content=value)
|
|
34
|
+
|
|
35
|
+
def make_markdown_object():
|
|
36
|
+
return markdown.Markdown( # type: ignore
|
|
37
|
+
extensions=[
|
|
38
|
+
"pymdownx.highlight",
|
|
39
|
+
"pymdownx.superfences",
|
|
40
|
+
"pymdownx.emoji",
|
|
41
|
+
"toc", # so we get anchors for h1 h2 etc
|
|
42
|
+
"tables",
|
|
43
|
+
],
|
|
44
|
+
extension_configs={
|
|
45
|
+
"pymdownx.emoji": {
|
|
46
|
+
"emoji_index": _no_deep_copy_emojione,
|
|
47
|
+
},
|
|
48
|
+
"pymdownx.superfences": {
|
|
49
|
+
"custom_fences": [
|
|
50
|
+
{
|
|
51
|
+
"name": "mermaid",
|
|
52
|
+
"class": "mermaid",
|
|
53
|
+
"format": pymdownx.superfences.fence_div_format,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "solara",
|
|
57
|
+
"class": "",
|
|
58
|
+
"validator": mkdocs_pycafe.validator,
|
|
59
|
+
"format": mkdocs_pycafe.formatter(type="solara", next_formatter=formatter(unsafe_solara_execute), inside_last_div=False),
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "python",
|
|
63
|
+
"class": "highlight",
|
|
64
|
+
"validator": mkdocs_pycafe.validator,
|
|
65
|
+
"format": mkdocs_pycafe.formatter(type="solara", next_formatter=formatter(unsafe_solara_execute), inside_last_div=False),
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
md_parser = solara.use_memo(make_markdown_object, dependencies=[unsafe_solara_execute])
|
|
73
|
+
|
|
30
74
|
with solara.v.Html(
|
|
31
75
|
tag="div",
|
|
32
76
|
style_="display: flex; flex-direction: row; justify-content: center; gap: 15px; max-width: 90%; margin: 0 auto;",
|
|
33
77
|
attributes={"id": "markdown-to-navigate"},
|
|
34
78
|
):
|
|
35
|
-
solara.Markdown(content, unsafe_solara_execute=unsafe_solara_execute, style="flex-grow: 1; max-width: min(100%, 1024px);")
|
|
79
|
+
solara.Markdown(content, unsafe_solara_execute=unsafe_solara_execute, style="flex-grow: 1; max-width: min(100%, 1024px);", md_parser=md_parser)
|
|
36
80
|
MarkdownNavigation(id="markdown-to-navigate").key("markdown-nav" + str(hash(content)))
|
|
37
81
|
|
|
38
82
|
|
|
@@ -15,7 +15,9 @@ def Sidebar():
|
|
|
15
15
|
break
|
|
16
16
|
|
|
17
17
|
with solara.v.List(
|
|
18
|
-
expand=True,
|
|
18
|
+
expand=True,
|
|
19
|
+
nav=True,
|
|
20
|
+
style_="height: 100%; max-height: 100vh; display: flex; flex-direction: column; background-color: var(--color-material-background); overflow-y: auto;",
|
|
19
21
|
) as main:
|
|
20
22
|
with solara.v.ListItemGroup(v_model=router.path):
|
|
21
23
|
# e.g. getting_started, examples, components, api, advanced, faq
|
solara/website/pages/__init__.py
CHANGED
|
@@ -280,13 +280,19 @@ def Layout(children=[]):
|
|
|
280
280
|
justify="center" if route_current is not None and route_current.path in ["documentation", "showcase"] else "start",
|
|
281
281
|
):
|
|
282
282
|
if route_current is not None and route_current.module is not None and hasattr(route_current.module, "Sidebar"):
|
|
283
|
-
with solara.v.
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
283
|
+
with solara.v.Sheet(
|
|
284
|
+
style_="""
|
|
285
|
+
height: 100vh;
|
|
286
|
+
width: 20rem;
|
|
287
|
+
overflow: auto;
|
|
288
|
+
border-right: 1px solid var(--color-border-appbar);
|
|
289
|
+
position: sticky;
|
|
290
|
+
top: 0;
|
|
291
|
+
flex-direction: column;
|
|
292
|
+
gap: 0;
|
|
293
|
+
""",
|
|
294
|
+
class_="d-md-flex d-none",
|
|
295
|
+
elevation=0,
|
|
290
296
|
):
|
|
291
297
|
route_current.module.Sidebar()
|
|
292
298
|
with rv.Col(
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Solara Changelog
|
|
2
2
|
|
|
3
|
+
## Version 1.41.0
|
|
4
|
+
* Feature: Mutation detection is now available under the `SOLARA_STORAGE_MUTATION_DETECTION` environmental variable. [#595](https://github.com/widgetti/solara/pull/595).
|
|
5
|
+
* Feature: Autofocusing text inputs is now supported. [#788](https://github.com/widgetti/solara/pull/788).
|
|
6
|
+
* Feature: Custom colours are now supported for the Solara loading spinner. [#858](https://github.com/widgetti/solara/pull/858)
|
|
7
|
+
* Bug Fix: Echarts responsive size is now properly supported. [#273](https://github.com/widgetti/solara/pull/273).
|
|
8
|
+
* Bug Fix: Some version checks would prevent Solara from starting. [#904](https://github.com/widgetti/solara/pull/904).
|
|
9
|
+
* Bug Fix: Solara apps running in qt mode (`--qt`) should now always work correctly. [#856](https://github.com/widgetti/solara/pull/856).
|
|
10
|
+
* Bug Fix: Hot reloading of files outside working directory would crash app. [069a205](https://github.com/widgetti/solara/commit/069a205c88a8cbcb0b0ca23f4d56889c8ad6134a) and [#869](https://github.com/widgetti/solara/pull/869).
|
|
11
|
+
|
|
3
12
|
## Version 1.40.0
|
|
4
13
|
* 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
14
|
* Feature: Support styling input field of [ChatInput component](https://solara.dev/documentation/components/lab/chat). [#800](https://github.com/widgetti/solara/pull/800).
|
|
@@ -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/
|
|
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.
|
|
@@ -13,11 +13,10 @@ df = plotly.data.gapminder()
|
|
|
13
13
|
@solara.component
|
|
14
14
|
def Page():
|
|
15
15
|
solara.provide_cross_filter()
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return main
|
|
16
|
+
|
|
17
|
+
solara.CrossFilterReport(df, classes=["py-2"])
|
|
18
|
+
solara.CrossFilterSelect(df, "country")
|
|
19
|
+
solara.CrossFilterDataFrame(df)
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
__doc__ += apidoc(solara.CrossFilterDataFrame.f) # type: ignore
|
|
@@ -12,11 +12,9 @@ df = plotly.data.gapminder()
|
|
|
12
12
|
@solara.component
|
|
13
13
|
def Page():
|
|
14
14
|
solara.provide_cross_filter()
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
solara.CrossFilterSlider(df, "gdpPercap", mode=">")
|
|
19
|
-
return main
|
|
15
|
+
solara.CrossFilterReport(df, classes=["py-2"])
|
|
16
|
+
solara.CrossFilterSelect(df, "country")
|
|
17
|
+
solara.CrossFilterSlider(df, "gdpPercap", mode=">")
|
|
20
18
|
|
|
21
19
|
|
|
22
20
|
__doc__ += apidoc(solara.CrossFilterReport.f) # type: ignore
|
|
@@ -12,11 +12,9 @@ df = plotly.data.tips()
|
|
|
12
12
|
@solara.component
|
|
13
13
|
def Page():
|
|
14
14
|
solara.provide_cross_filter()
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
solara.CrossFilterSelect(df, "time")
|
|
19
|
-
return main
|
|
15
|
+
solara.CrossFilterReport(df, classes=["py-2"])
|
|
16
|
+
solara.CrossFilterSelect(df, "sex")
|
|
17
|
+
solara.CrossFilterSelect(df, "time")
|
|
20
18
|
|
|
21
19
|
|
|
22
20
|
__doc__ += apidoc(solara.CrossFilterSelect.f) # type: ignore
|
|
@@ -12,11 +12,9 @@ df = plotly.data.gapminder()
|
|
|
12
12
|
@solara.component
|
|
13
13
|
def Page():
|
|
14
14
|
solara.provide_cross_filter()
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
solara.CrossFilterSlider(df, "gdpPercap", mode="<")
|
|
19
|
-
return main
|
|
15
|
+
solara.CrossFilterReport(df, classes=["py-2"])
|
|
16
|
+
solara.CrossFilterSlider(df, "pop", mode=">")
|
|
17
|
+
solara.CrossFilterSlider(df, "gdpPercap", mode="<")
|
|
20
18
|
|
|
21
19
|
|
|
22
20
|
__doc__ += apidoc(solara.CrossFilterSlider.f) # type: ignore
|
|
@@ -15,11 +15,9 @@ df = plotly.data.gapminder()
|
|
|
15
15
|
@solara.component
|
|
16
16
|
def Page():
|
|
17
17
|
solara.provide_cross_filter()
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
solara.CrossFilterSlider(df, "gdpPercap", mode=">")
|
|
22
|
-
return main
|
|
18
|
+
solara.CrossFilterReport(df, classes=["py-2"])
|
|
19
|
+
solara.CrossFilterSelect(df, "continent")
|
|
20
|
+
solara.CrossFilterSlider(df, "gdpPercap", mode=">")
|
|
23
21
|
|
|
24
22
|
|
|
25
23
|
__doc__ += apidoc(solara.use_cross_filter) # type: ignore
|
|
@@ -18,16 +18,14 @@ def Page():
|
|
|
18
18
|
value_previous = solara.use_previous(value)
|
|
19
19
|
exception, clear_exception = solara.use_exception()
|
|
20
20
|
# print(exception)
|
|
21
|
-
|
|
22
|
-
if exception:
|
|
21
|
+
if exception:
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
def reset():
|
|
24
|
+
set_value(value_previous)
|
|
25
|
+
clear_exception()
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return main
|
|
27
|
+
solara.Text("Exception: " + str(exception))
|
|
28
|
+
solara.Button(label="Go to previous state", on_click=reset)
|
|
29
|
+
else:
|
|
30
|
+
solara.IntSlider(value=value, min=0, max=10, on_value=set_value, label="Pick a number, except 3")
|
|
31
|
+
UnstableComponent(value)
|
|
@@ -20,14 +20,11 @@ title = "use_previous"
|
|
|
20
20
|
def Page():
|
|
21
21
|
value, set_value = solara.use_state(4)
|
|
22
22
|
value_previous = solara.use_previous(value)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
**Current**: `{value}`
|
|
23
|
+
solara.IntSlider("value", value=value, on_value=set_value)
|
|
24
|
+
solara.Markdown(
|
|
25
|
+
f"""
|
|
26
|
+
**Current**: `{value}`
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
**Previous**: `{value_previous}`
|
|
30
29
|
"""
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return main
|
|
30
|
+
)
|
|
@@ -41,29 +41,26 @@ def Page():
|
|
|
41
41
|
parent_value, set_parent_value = solara.use_state(4)
|
|
42
42
|
# used to force rerenders
|
|
43
43
|
rerender_counter, set_rerender_counter = solara.use_state(4)
|
|
44
|
-
with solara.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
SliderWithState(parent_value).key(f"slider-{parent_value}")
|
|
68
|
-
|
|
69
|
-
return main
|
|
44
|
+
with solara.Card("Parent value selection"):
|
|
45
|
+
solara.Info("This slider value gets passed down to the child components")
|
|
46
|
+
solara.IntSlider("parent value", value=parent_value, on_value=set_parent_value)
|
|
47
|
+
solara.Button("Force redraw", on_click=lambda: set_rerender_counter(rerender_counter + 1))
|
|
48
|
+
|
|
49
|
+
with solara.Card("Child without state"):
|
|
50
|
+
solara.Info("This child will simply render the value passed into the argument, a redraw will reset it to its parent value.")
|
|
51
|
+
SliderWithoutState(parent_value)
|
|
52
|
+
|
|
53
|
+
with solara.Card("Child with state"):
|
|
54
|
+
solara.Info("This child will not care about the value passed into the prop, it manages its own state.")
|
|
55
|
+
SliderWithState(parent_value)
|
|
56
|
+
|
|
57
|
+
with solara.Card("Child with state (or update)"):
|
|
58
|
+
solara.Info("This child will update when the passes in a new value, but a redraw will not reset it.")
|
|
59
|
+
SliderWithStateOrUpdate(parent_value)
|
|
60
|
+
|
|
61
|
+
with solara.Card("Child with state + key"):
|
|
62
|
+
solara.Info(
|
|
63
|
+
"We can also use the `.key(...)` method to force the component to forget its state, this will however cause the widget to be re-created"
|
|
64
|
+
"(a performance penalty)."
|
|
65
|
+
)
|
|
66
|
+
SliderWithState(parent_value).key(f"slider-{parent_value}")
|
|
@@ -3,7 +3,7 @@ from pathlib import Path
|
|
|
3
3
|
from typing import Optional, cast
|
|
4
4
|
|
|
5
5
|
import solara
|
|
6
|
-
from solara.alias import
|
|
6
|
+
from solara.alias import rw
|
|
7
7
|
|
|
8
8
|
HERE = Path(__file__).parent
|
|
9
9
|
title = "use_thread"
|
|
@@ -29,16 +29,14 @@ def Page():
|
|
|
29
29
|
# work will be cancelled/restarted every time the dependency changes
|
|
30
30
|
result: solara.Result[bool] = solara.use_thread(work, dependencies=[number])
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if result.
|
|
35
|
-
|
|
36
|
-
solara.Success(f"{number} is a prime!")
|
|
37
|
-
else:
|
|
38
|
-
solara.Error(f"{number} is not a prime, it can be divided by {proof} ")
|
|
39
|
-
elif result.state == solara.ResultState.ERROR:
|
|
40
|
-
solara.Error(f"Error occurred: {result.error}")
|
|
32
|
+
rw.IntText(value=number, on_value=set_number)
|
|
33
|
+
if result.state == solara.ResultState.FINISHED:
|
|
34
|
+
if result.value:
|
|
35
|
+
solara.Success(f"{number} is a prime!")
|
|
41
36
|
else:
|
|
42
|
-
solara.
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
solara.Error(f"{number} is not a prime, it can be divided by {proof} ")
|
|
38
|
+
elif result.state == solara.ResultState.ERROR:
|
|
39
|
+
solara.Error(f"Error occurred: {result.error}")
|
|
40
|
+
else:
|
|
41
|
+
solara.Info(f"Running... (status = {result.state})")
|
|
42
|
+
solara.v.ProgressLinear(indeterminate=True)
|
|
@@ -19,6 +19,23 @@ The return value of on_kernel_start is a cleanup function that will remove the c
|
|
|
19
19
|
|
|
20
20
|
During hot reload, the callbacks that are added from scripts or modules that will be reloaded will be removed before the app is loaded
|
|
21
21
|
again. This can cause the order of the callbacks to be different than at first run.
|
|
22
|
+
|
|
23
|
+
## Example
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
import solara
|
|
27
|
+
import solara.lab
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@solara.lab.on_kernel_start
|
|
31
|
+
def on_kernel_start():
|
|
32
|
+
id = solara.get_kernel_id()
|
|
33
|
+
print("Kernel started", id)
|
|
34
|
+
def cleanup():
|
|
35
|
+
print("Kernel stopped", id)
|
|
36
|
+
return cleanup # this function will be called on kernel shutdown
|
|
37
|
+
```
|
|
38
|
+
|
|
22
39
|
"""
|
|
23
40
|
|
|
24
41
|
from solara.website.components import NoPage
|
|
@@ -19,3 +19,25 @@ __doc__ += "# InputFloat"
|
|
|
19
19
|
__doc__ += apidoc(solara.InputFloat.f) # type: ignore
|
|
20
20
|
__doc__ += "# InputInt"
|
|
21
21
|
__doc__ += apidoc(solara.InputInt.f) # type: ignore
|
|
22
|
+
|
|
23
|
+
__doc__ += """
|
|
24
|
+
# Autofocus Example
|
|
25
|
+
|
|
26
|
+
```solara
|
|
27
|
+
import solara
|
|
28
|
+
import solara.lab
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@solara.component
|
|
32
|
+
def Page():
|
|
33
|
+
show_dialog = solara.use_reactive(False)
|
|
34
|
+
show_conditional = solara.use_reactive(False)
|
|
35
|
+
with solara.Row():
|
|
36
|
+
solara.Button("Show dialog", on_click=lambda: show_dialog.set(True))
|
|
37
|
+
solara.Button("Show conditionally rendered element", on_click=lambda: show_conditional.set(not show_conditional.value))
|
|
38
|
+
with solara.lab.ConfirmationDialog(open=show_dialog):
|
|
39
|
+
solara.InputFloat("Float here", autofocus=True)
|
|
40
|
+
if show_conditional.value:
|
|
41
|
+
solara.InputFloat("Float here", autofocus=True)
|
|
42
|
+
```
|
|
43
|
+
"""
|
|
@@ -63,7 +63,9 @@ def Page():
|
|
|
63
63
|
with solara.ToggleButtonsSingle("bars", on_value=set_option):
|
|
64
64
|
solara.Button("bars")
|
|
65
65
|
solara.Button("pie")
|
|
66
|
-
solara.FigureEcharts(
|
|
66
|
+
solara.FigureEcharts(
|
|
67
|
+
option=options[option], on_click=set_click_data, on_mouseover=set_mouseover_data, on_mouseout=set_mouseout_data, responsive=True
|
|
68
|
+
)
|
|
67
69
|
with solara.Card("Event data"):
|
|
68
70
|
solara.Markdown(f"**Click data**: {click_data}")
|
|
69
71
|
solara.Markdown(f"**Mouseover data**: {mouseover_data}")
|
|
@@ -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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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.
|
|
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": "
|
|
80
|
+
style={"width": "100%", "height": "50vh"},
|
|
81
81
|
):
|
|
82
82
|
with solara.lab.ChatBox():
|
|
83
83
|
for item in messages.value:
|
|
@@ -10,8 +10,8 @@ from solara import use_fetch
|
|
|
10
10
|
from solara.alias import rv
|
|
11
11
|
|
|
12
12
|
github_url = solara.util.github_url(__file__)
|
|
13
|
-
|
|
14
|
-
json_url = "
|
|
13
|
+
pokemon_base_url = "https://raw.githubusercontent.com/jherr/pokemon/0722479d4153b1db0d0326956b08b37f44a95a5f"
|
|
14
|
+
json_url = f"{pokemon_base_url}/index.json"
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
@solara.component
|
|
@@ -40,7 +40,7 @@ def Page():
|
|
|
40
40
|
for pokemon in pokemons[:20]:
|
|
41
41
|
with solara.Div():
|
|
42
42
|
name = pokemon["name"]
|
|
43
|
-
url =
|
|
43
|
+
url = f'{pokemon_base_url}/{pokemon["image"]}'
|
|
44
44
|
# TODO: how to do this with solara
|
|
45
45
|
rv.Img(src=url, contain=True, max_height="200px")
|
|
46
46
|
solara.Text(name)
|
|
@@ -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(
|
|
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")
|
|
@@ -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={"
|
|
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={"
|
|
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={"
|
|
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]
|