solara-ui 1.40.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.
- solara/__init__.py +1 -1
- solara/__main__.py +23 -10
- solara/components/component_vue.py +3 -2
- solara/server/assets/style.css +2 -0
- solara/server/qt.py +113 -0
- solara/server/settings.py +1 -0
- 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/website/components/sidebar.py +3 -1
- solara/website/pages/__init__.py +13 -7
- solara/website/pages/documentation/advanced/content/20-understanding/40-routing.md +17 -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/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 +4 -4
- solara/website/pages/documentation/getting_started/content/00-quickstart.md +18 -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.41.0.dist-info}/METADATA +1 -1
- {solara_ui-1.40.0.dist-info → solara_ui-1.41.0.dist-info}/RECORD +32 -31
- {solara_ui-1.40.0.data → solara_ui-1.41.0.data}/data/etc/jupyter/jupyter_notebook_config.d/solara.json +0 -0
- {solara_ui-1.40.0.data → solara_ui-1.41.0.data}/data/etc/jupyter/jupyter_server_config.d/solara.json +0 -0
- {solara_ui-1.40.0.dist-info → solara_ui-1.41.0.dist-info}/WHEEL +0 -0
- {solara_ui-1.40.0.dist-info → solara_ui-1.41.0.dist-info}/licenses/LICENSE +0 -0
solara/__init__.py
CHANGED
solara/__main__.py
CHANGED
|
@@ -261,6 +261,12 @@ if "SOLARA_MODE" in os.environ:
|
|
|
261
261
|
default=True,
|
|
262
262
|
help="Check installed version again pypi version.",
|
|
263
263
|
)
|
|
264
|
+
@click.option(
|
|
265
|
+
"--qt",
|
|
266
|
+
is_flag=True,
|
|
267
|
+
default=False,
|
|
268
|
+
help="Instead of opening a browser, open a Qt window. Will also stop the server when the window is closed. (experimental)",
|
|
269
|
+
)
|
|
264
270
|
def run(
|
|
265
271
|
app,
|
|
266
272
|
host,
|
|
@@ -290,6 +296,7 @@ def run(
|
|
|
290
296
|
ssg: bool,
|
|
291
297
|
search: bool,
|
|
292
298
|
check_version: bool = True,
|
|
299
|
+
qt=False,
|
|
293
300
|
):
|
|
294
301
|
"""Run a Solara app."""
|
|
295
302
|
if dev is not None:
|
|
@@ -365,9 +372,16 @@ def run(
|
|
|
365
372
|
while not failed and (server is None or not server.started):
|
|
366
373
|
time.sleep(0.1)
|
|
367
374
|
if not failed:
|
|
368
|
-
|
|
375
|
+
if qt:
|
|
376
|
+
from .server.qt import run_qt
|
|
369
377
|
|
|
370
|
-
|
|
378
|
+
run_qt(url)
|
|
379
|
+
else:
|
|
380
|
+
webbrowser.open(url)
|
|
381
|
+
|
|
382
|
+
# with qt, we open the browser in the main thread (qt wants that)
|
|
383
|
+
# otherwise, we open the browser in a separate thread
|
|
384
|
+
if open and not qt:
|
|
371
385
|
threading.Thread(target=open_browser, daemon=True).start()
|
|
372
386
|
|
|
373
387
|
rich.print(f"Solara server is starting at {url}")
|
|
@@ -397,7 +411,7 @@ def run(
|
|
|
397
411
|
settings.main.timing = timing
|
|
398
412
|
items = (
|
|
399
413
|
"theme_variant_user_selectable dark theme_variant theme_loader use_pdb server open_browser open url failed dev tracer"
|
|
400
|
-
" timing ssg search check_version production".split()
|
|
414
|
+
" timing ssg search check_version production qt".split()
|
|
401
415
|
)
|
|
402
416
|
for item in items:
|
|
403
417
|
del kwargs[item]
|
|
@@ -451,14 +465,13 @@ def run(
|
|
|
451
465
|
|
|
452
466
|
build_index("")
|
|
453
467
|
|
|
454
|
-
start_server()
|
|
455
|
-
|
|
456
468
|
# TODO: if we want to use webview, it should be sth like this
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
469
|
+
if qt:
|
|
470
|
+
server_thread = threading.Thread(target=start_server, daemon=True)
|
|
471
|
+
server_thread.start()
|
|
472
|
+
open_browser()
|
|
473
|
+
else:
|
|
474
|
+
start_server()
|
|
462
475
|
# server_thread.join()
|
|
463
476
|
|
|
464
477
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import inspect
|
|
2
|
+
import os
|
|
2
3
|
from typing import Any, Callable, Dict, Type
|
|
3
4
|
|
|
4
5
|
import ipyvue as vue
|
|
@@ -48,10 +49,10 @@ def _widget_from_signature(classname, base_class: Type[widgets.Widget], func: Ca
|
|
|
48
49
|
def _widget_vue(vue_path: str, vuetify=True) -> Callable[[Callable[P, None]], Type[v.VuetifyTemplate]]:
|
|
49
50
|
def decorator(func: Callable[P, None]):
|
|
50
51
|
class VuetifyWidgetSolara(v.VuetifyTemplate):
|
|
51
|
-
template_file = (inspect.getfile(func), vue_path)
|
|
52
|
+
template_file = (os.path.abspath(inspect.getfile(func)), vue_path)
|
|
52
53
|
|
|
53
54
|
class VueWidgetSolara(vue.VueTemplate):
|
|
54
|
-
template_file = (inspect.getfile(func), vue_path)
|
|
55
|
+
template_file = (os.path.abspath(inspect.getfile(func)), vue_path)
|
|
55
56
|
|
|
56
57
|
base_class = VuetifyWidgetSolara if vuetify else VueWidgetSolara
|
|
57
58
|
widget_class = _widget_from_signature("VueWidgetSolaraSub", base_class, func, "vue_")
|
solara/server/assets/style.css
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
html {
|
|
2
2
|
/* override vuetify's css reset ress.css */
|
|
3
3
|
overflow-y: auto;
|
|
4
|
+
scroll-behavior: smooth;
|
|
4
5
|
}
|
|
5
6
|
|
|
6
7
|
.jupyter-widgets code {
|
|
@@ -124,6 +125,7 @@ div.highlight {
|
|
|
124
125
|
|
|
125
126
|
.solara-autorouter-content {
|
|
126
127
|
height: 100%;
|
|
128
|
+
max-width: 100%;
|
|
127
129
|
}
|
|
128
130
|
|
|
129
131
|
/* originally from index.css */
|
solara/server/qt.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from typing import List
|
|
3
|
+
import webbrowser
|
|
4
|
+
from qtpy.QtWidgets import QApplication
|
|
5
|
+
from qtpy.QtWebEngineWidgets import QWebEngineView
|
|
6
|
+
from qtpy.QtWebChannel import QWebChannel
|
|
7
|
+
from qtpy import QtCore, QtGui
|
|
8
|
+
import signal
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
HERE = Path(__file__).parent
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# setUrlRequestInterceptor, navigationRequested and acceptNavigationRequest
|
|
15
|
+
# all trigger the websocket to disconnect, so we need to block cross origin
|
|
16
|
+
# requests on the frontend/browser side by intercepting clicks on links
|
|
17
|
+
|
|
18
|
+
cross_origin_block_js = """
|
|
19
|
+
var script = document.createElement('script');
|
|
20
|
+
script.src = 'qrc:///qtwebchannel/qwebchannel.js';
|
|
21
|
+
document.head.appendChild(script);
|
|
22
|
+
script.onload = function() {
|
|
23
|
+
new QWebChannel(qt.webChannelTransport, function(channel) {
|
|
24
|
+
let py_callback = channel.objects.py_callback;
|
|
25
|
+
|
|
26
|
+
document.addEventListener('click', function(event) {
|
|
27
|
+
let target = event.target;
|
|
28
|
+
while (target && target.tagName !== 'A') {
|
|
29
|
+
target = target.parentNode;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (target && target.tagName === 'A') {
|
|
33
|
+
const linkOrigin = new URL(target.href).origin;
|
|
34
|
+
const currentOrigin = window.location.origin;
|
|
35
|
+
|
|
36
|
+
if (linkOrigin !== currentOrigin) {
|
|
37
|
+
event.preventDefault();
|
|
38
|
+
console.log("Blocked cross-origin navigation to:", target.href);
|
|
39
|
+
py_callback.open_link(target.href); // Call Python method
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}, true);
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class PyCallback(QtCore.QObject):
|
|
49
|
+
@QtCore.Slot(str)
|
|
50
|
+
def open_link(self, url):
|
|
51
|
+
webbrowser.open(url)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class QWebEngineViewWithPopup(QWebEngineView):
|
|
55
|
+
# keep a strong reference to all windows
|
|
56
|
+
windows: List = []
|
|
57
|
+
|
|
58
|
+
def __init__(self):
|
|
59
|
+
super().__init__()
|
|
60
|
+
self.page().newWindowRequested.connect(self.handle_new_window_request)
|
|
61
|
+
|
|
62
|
+
# Set up WebChannel and py_callback object
|
|
63
|
+
self.py_callback = PyCallback()
|
|
64
|
+
self.channel = QWebChannel()
|
|
65
|
+
self.channel.registerObject("py_callback", self.py_callback)
|
|
66
|
+
self.page().setWebChannel(self.channel)
|
|
67
|
+
|
|
68
|
+
self.loadFinished.connect(self._inject_javascript)
|
|
69
|
+
|
|
70
|
+
def _inject_javascript(self, ok):
|
|
71
|
+
self.page().runJavaScript(cross_origin_block_js)
|
|
72
|
+
|
|
73
|
+
def handle_new_window_request(self, info):
|
|
74
|
+
webview = QWebEngineViewWithPopup()
|
|
75
|
+
geometry = info.requestedGeometry()
|
|
76
|
+
webview.resize(geometry.width(), geometry.height())
|
|
77
|
+
webview.setUrl(info.requestedUrl())
|
|
78
|
+
webview.show()
|
|
79
|
+
QWebEngineViewWithPopup.windows.append(webview)
|
|
80
|
+
return webview
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def run_qt(url):
|
|
84
|
+
app = QApplication([])
|
|
85
|
+
web = QWebEngineViewWithPopup()
|
|
86
|
+
web.setUrl(QtCore.QUrl(url))
|
|
87
|
+
web.resize(1024, 1024)
|
|
88
|
+
web.show()
|
|
89
|
+
|
|
90
|
+
app_name = "Solara"
|
|
91
|
+
app.setApplicationDisplayName(app_name)
|
|
92
|
+
app.setApplicationName(app_name)
|
|
93
|
+
web.setWindowTitle(app_name)
|
|
94
|
+
app.setWindowIcon(QtGui.QIcon(str(HERE.parent / "website/public/logo.svg")))
|
|
95
|
+
if sys.platform.startswith("darwin"):
|
|
96
|
+
# Set app name, if PyObjC is installed
|
|
97
|
+
# Python 2 has PyObjC preinstalled
|
|
98
|
+
# Python 3: pip3 install pyobjc-framework-Cocoa
|
|
99
|
+
try:
|
|
100
|
+
from Foundation import NSBundle
|
|
101
|
+
|
|
102
|
+
bundle = NSBundle.mainBundle()
|
|
103
|
+
if bundle:
|
|
104
|
+
app_info = bundle.localizedInfoDictionary() or bundle.infoDictionary()
|
|
105
|
+
if app_info is not None:
|
|
106
|
+
app_info["CFBundleName"] = app_name
|
|
107
|
+
app_info["CFBundleDisplayName"] = app_name
|
|
108
|
+
except ModuleNotFoundError:
|
|
109
|
+
pass
|
|
110
|
+
|
|
111
|
+
# without this, ctrl-c does not work in the terminal
|
|
112
|
+
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
|
113
|
+
app.exec_()
|
solara/server/settings.py
CHANGED
|
@@ -138,15 +138,25 @@ async function solaraInit(mountId, appName) {
|
|
|
138
138
|
});
|
|
139
139
|
|
|
140
140
|
window.addEventListener('solara.router', function (event) {
|
|
141
|
+
app.$data.urlHasChanged = true;
|
|
141
142
|
if(kernel.status == 'busy') {
|
|
142
143
|
app.$data.loadingPage = true;
|
|
143
144
|
}
|
|
144
145
|
});
|
|
145
146
|
kernel.statusChanged.connect(() => {
|
|
147
|
+
// When navigation is triggered from the front-end, kernel.status becoming busy and
|
|
148
|
+
// solara.router event happen in a different order than when navigating through Python, so
|
|
149
|
+
// if the URL has changed when the kernel becomes busy, we set loadingPage to true
|
|
150
|
+
if (kernel.status == 'busy' && app.$data.urlHasChanged) {
|
|
151
|
+
app.$data.loadingPage = true;
|
|
152
|
+
}
|
|
146
153
|
// the first idle after a loadingPage == true (a router event)
|
|
147
154
|
// will be used as indicator that the page is loaded
|
|
148
155
|
if (app.$data.loadingPage && kernel.status == 'idle') {
|
|
149
156
|
app.$data.loadingPage = false;
|
|
157
|
+
app.$data.urlHasChanged = false;
|
|
158
|
+
const event = new Event('solara.pageReady');
|
|
159
|
+
window.dispatchEvent(event);
|
|
150
160
|
}
|
|
151
161
|
});
|
|
152
162
|
|
|
@@ -119,7 +119,7 @@ async def main():
|
|
|
119
119
|
]
|
|
120
120
|
for dep in requirements:
|
|
121
121
|
await micropip.install(dep, keep_going=True)
|
|
122
|
-
await micropip.install("/wheels/solara-1.
|
|
122
|
+
await micropip.install("/wheels/solara-1.41.0-py2.py3-none-any.whl", keep_going=True)
|
|
123
123
|
import solara
|
|
124
124
|
|
|
125
125
|
el = solara.Warning("lala")
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
<jupyter-widget-mount-point mount-id="solara-main">
|
|
33
33
|
A widget with mount-id="solara-main" should go here
|
|
34
34
|
</jupyter-widget-mount-point>
|
|
35
|
-
<div style="position: absolute; right: 0px; bottom: 0px; padding: 10px;">
|
|
35
|
+
<div v-if="showBanner" style="position: absolute; right: 0px; bottom: 0px; padding: 10px;">
|
|
36
36
|
<b>This website runs on <a href="https://solara.dev">Solara</a></b>
|
|
37
37
|
</div>
|
|
38
38
|
</div>
|
|
@@ -172,7 +172,7 @@
|
|
|
172
172
|
</script>
|
|
173
173
|
{% endraw -%}
|
|
174
174
|
|
|
175
|
-
<body data-base-url="{{root_path}}/
|
|
175
|
+
<body data-base-url="{{root_path}}/jupyter/">
|
|
176
176
|
{% if perform_check %}
|
|
177
177
|
<iframe src="https://solara.dev/static/public/success.html?system=solara&check=html&version={{solara_version}}" style="display: none"></iframe>
|
|
178
178
|
{% endif %}
|
|
@@ -296,6 +296,10 @@
|
|
|
296
296
|
this.forceUpdateTrigger += 1;
|
|
297
297
|
original_$forceUpdate();
|
|
298
298
|
});
|
|
299
|
+
// in case we are showing a popop (e.g. using ipypopout), hide the banner
|
|
300
|
+
if(searchParams.has('modelid')) {
|
|
301
|
+
this.showBanner = false;
|
|
302
|
+
}
|
|
299
303
|
},
|
|
300
304
|
mounted() {
|
|
301
305
|
document.querySelector('#app').removeAttribute("style");
|
|
@@ -413,6 +417,7 @@
|
|
|
413
417
|
loadingPage: false,
|
|
414
418
|
_lastBusyTimer: null,
|
|
415
419
|
kernelBusyLong: false,
|
|
420
|
+
showBanner: theme.show_banner,
|
|
416
421
|
// outputMessages: [{ name: 'stderr', text: 'lala' }],
|
|
417
422
|
}
|
|
418
423
|
}
|
|
@@ -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(
|
|
@@ -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.
|
|
@@ -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:
|
|
@@ -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]
|
|
@@ -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
|
-
|
|
45
|
-
if
|
|
46
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
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)
|
|
@@ -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=
|
|
53
|
-
with solara.
|
|
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.
|
|
69
|
-
with solara.
|
|
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"/>
|
solara/widgets/vue/navigator.vue
CHANGED
|
@@ -14,43 +14,37 @@ modules.export = {
|
|
|
14
14
|
}
|
|
15
15
|
window.solara.router.push = (href) => {
|
|
16
16
|
console.log("external router push", href);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
this.location = href;
|
|
17
|
+
const url = new URL(href, window.location.origin + solara.rootPath);
|
|
18
|
+
this.location = url.pathname + url.search;
|
|
19
|
+
this.hash = url.hash;
|
|
22
20
|
};
|
|
23
21
|
let location = window.location.pathname.slice(solara.rootPath.length);
|
|
24
|
-
// take of the anchor
|
|
25
|
-
if (location.indexOf("#") !== -1) {
|
|
26
|
-
location = location.slice(0, location.indexOf("#"));
|
|
27
|
-
}
|
|
28
22
|
this.location = location + window.location.search;
|
|
23
|
+
this.hash = window.location.hash;
|
|
29
24
|
window.addEventListener("popstate", this.onPopState);
|
|
30
25
|
window.addEventListener("scroll", this.onScroll);
|
|
26
|
+
window.addEventListener("hashchange", this.onHashChange);
|
|
27
|
+
window.addEventListener("solara.pageReady", this.onPageLoad);
|
|
31
28
|
},
|
|
32
29
|
destroyed() {
|
|
33
30
|
window.removeEventListener("popstate", this.onPopState);
|
|
34
31
|
window.removeEventListener("scroll", this.onScroll);
|
|
32
|
+
window.removeEventListener("hashchange", this.onHashChange);
|
|
33
|
+
window.removeEventListener("solara.pageReady", this.onPageLoad);
|
|
35
34
|
},
|
|
36
35
|
methods: {
|
|
37
36
|
onScroll() {
|
|
38
37
|
window.history.replaceState(
|
|
39
38
|
{ top: document.documentElement.scrollTop },
|
|
40
39
|
null,
|
|
41
|
-
|
|
40
|
+
window.location.href
|
|
42
41
|
);
|
|
43
42
|
},
|
|
44
43
|
onPopState(event) {
|
|
45
|
-
console.log("pop state!", event.state, window.location.href);
|
|
46
44
|
if (!window.location.pathname.startsWith(solara.rootPath)) {
|
|
47
45
|
throw `window.location.pathname = ${window.location.pathname}, but it should start with the solara.rootPath = ${solara.rootPath}`;
|
|
48
46
|
}
|
|
49
47
|
let newLocation = window.location.pathname.slice(solara.rootPath.length);
|
|
50
|
-
// the router/server shouldn't care about the hash, that's for the frontend
|
|
51
|
-
if (newLocation.indexOf("#") !== -1) {
|
|
52
|
-
newLocation = newLocation.slice(0, newLocation.indexOf("#"));
|
|
53
|
-
}
|
|
54
48
|
this.location = newLocation + window.location.search;
|
|
55
49
|
if (event.state) {
|
|
56
50
|
const top = event.state.top;
|
|
@@ -63,6 +57,32 @@ modules.export = {
|
|
|
63
57
|
*/
|
|
64
58
|
}
|
|
65
59
|
},
|
|
60
|
+
onHashChange(event) {
|
|
61
|
+
if (!window.location.pathname.startsWith(solara.rootPath)) {
|
|
62
|
+
throw `window.location.pathname = ${window.location.pathname}, but it should start with the solara.rootPath = ${solara.rootPath}`;
|
|
63
|
+
}
|
|
64
|
+
this.hash = window.location.hash;
|
|
65
|
+
},
|
|
66
|
+
onPageLoad(event) {
|
|
67
|
+
if (!window.location.pathname.startsWith(solara.rootPath)) {
|
|
68
|
+
throw `window.location.pathname = ${window.location.pathname}, but it should start with the solara.rootPath = ${solara.rootPath}`;
|
|
69
|
+
}
|
|
70
|
+
// If we've navigated to a hash with the same name on a different page the watch on hash won't trigger
|
|
71
|
+
if (this.hash && this.hash === window.location.hash) {
|
|
72
|
+
this.navigateToHash(this.hash);
|
|
73
|
+
}
|
|
74
|
+
this.hash = window.location.hash;
|
|
75
|
+
},
|
|
76
|
+
makeFullRelativeUrl() {
|
|
77
|
+
const url = new URL(this.location, window.location.origin + solara.rootPath);
|
|
78
|
+
return url.pathname + this.hash + url.search;
|
|
79
|
+
},
|
|
80
|
+
navigateToHash(hash) {
|
|
81
|
+
const targetEl = document.getElementById(hash.slice(1));
|
|
82
|
+
if (targetEl) {
|
|
83
|
+
targetEl.scrollIntoView();
|
|
84
|
+
}
|
|
85
|
+
},
|
|
66
86
|
},
|
|
67
87
|
watch: {
|
|
68
88
|
location(value) {
|
|
@@ -89,7 +109,7 @@ modules.export = {
|
|
|
89
109
|
document.documentElement.scrollTop
|
|
90
110
|
);
|
|
91
111
|
if (oldLocation != this.location) {
|
|
92
|
-
window.history.pushState({ top: 0 }, null,
|
|
112
|
+
window.history.pushState({ top: 0 }, null, this.makeFullRelativeUrl());
|
|
93
113
|
if (pathnameNew != pathnameOld) {
|
|
94
114
|
// we scroll to the top only when we change page, not when we change
|
|
95
115
|
// the search string
|
|
@@ -99,6 +119,16 @@ modules.export = {
|
|
|
99
119
|
window.dispatchEvent(event);
|
|
100
120
|
}
|
|
101
121
|
},
|
|
122
|
+
hash(value) {
|
|
123
|
+
if (value) {
|
|
124
|
+
this.navigateToHash(value);
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
data() {
|
|
129
|
+
return {
|
|
130
|
+
hash: "",
|
|
131
|
+
};
|
|
102
132
|
},
|
|
103
133
|
};
|
|
104
134
|
</script>
|
solara/widgets/vue/vegalite.vue
CHANGED
|
@@ -15,6 +15,11 @@ module.exports = {
|
|
|
15
15
|
mounted() {
|
|
16
16
|
this.do_plot_debounced();
|
|
17
17
|
},
|
|
18
|
+
destroyed() {
|
|
19
|
+
if (this.observer) {
|
|
20
|
+
this.observer.disconnect();
|
|
21
|
+
}
|
|
22
|
+
},
|
|
18
23
|
watch: {
|
|
19
24
|
spec() {
|
|
20
25
|
this.do_plot_debounced();
|
|
@@ -29,7 +34,15 @@ module.exports = {
|
|
|
29
34
|
(async () => {
|
|
30
35
|
const spec = {
|
|
31
36
|
...this.spec,
|
|
37
|
+
"renderer": "svg",
|
|
32
38
|
};
|
|
39
|
+
if (spec.width === "container") {
|
|
40
|
+
this.$refs.plotElement.classList.add("width-container")
|
|
41
|
+
this.observer = new ResizeObserver(() => {
|
|
42
|
+
view.resize();
|
|
43
|
+
});
|
|
44
|
+
this.observer.observe(this.$refs.plotElement);
|
|
45
|
+
}
|
|
33
46
|
const { view } = await vegaEmbed(this.$refs.plotElement, spec);
|
|
34
47
|
// events https://github.com/vega/vega-view#event-handling
|
|
35
48
|
if (this.listen_to_click) {
|
|
@@ -110,3 +123,8 @@ module.exports = {
|
|
|
110
123
|
},
|
|
111
124
|
}
|
|
112
125
|
</script>
|
|
126
|
+
<style id="vega-embed-container-width">
|
|
127
|
+
.width-container.vega-embed {
|
|
128
|
+
width: 100%;
|
|
129
|
+
}
|
|
130
|
+
</style>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
prefix/etc/jupyter/jupyter_notebook_config.d/solara.json,sha256=3UhTBQi6z7F7pPjmqXxfddv79c8VGR9H7zStDLp6AwY,115
|
|
2
2
|
prefix/etc/jupyter/jupyter_server_config.d/solara.json,sha256=D9J-rYxAzyD5GOqWvuPjacGUVFHsYtTfZ4FUbRzRvIA,113
|
|
3
|
-
solara/__init__.py,sha256=
|
|
4
|
-
solara/__main__.py,sha256
|
|
3
|
+
solara/__init__.py,sha256=l1mOv4ngBpoXaXv6PDfspwaZ3lCYhGNgEuiTayMGZrM,3647
|
|
4
|
+
solara/__main__.py,sha256=-OSjoLAVqu7-h15I5X1XFi6FyHpM0XT1z7qTXlyuDqM,24339
|
|
5
5
|
solara/alias.py,sha256=9vfLzud77NP8in3OID9b5mmIO8NyrnFjN2_aE0lSb1k,216
|
|
6
6
|
solara/autorouting.py,sha256=iQ-jP5H-kdu1uZyLEFeiHG1IsOLZLzwKVtQPyXSgGSM,23093
|
|
7
7
|
solara/cache.py,sha256=rZEW_xVIj3vvajntsQDnaglniTQ90izkX8vOqe1mMvE,10500
|
|
@@ -32,7 +32,7 @@ solara/components/checkbox.py,sha256=MLQ9Hxvtv5aKLj4XO3ILWtGc6nKOUH560A2bBt0Z030
|
|
|
32
32
|
solara/components/code_highlight_css.py,sha256=J0fZHuEu8jeEKAq_HKbzgiMR1-VwMVnKA4dAOKE0AQU,235
|
|
33
33
|
solara/components/code_highlight_css.vue,sha256=UX4jtEetV1W25Uvu8xQ-TbEaBzbp_7DlXtXDO9SdZfY,5776
|
|
34
34
|
solara/components/columns.py,sha256=bGCUU9MLxkt2OiS31oLHWrEOlskxT1Xo65dBxXhmhbQ,5564
|
|
35
|
-
solara/components/component_vue.py,sha256=
|
|
35
|
+
solara/components/component_vue.py,sha256=zw7vEfBWDO-jxPHD03e1d96Gci8yGbr6koh0d1Bzfoo,4379
|
|
36
36
|
solara/components/cross_filter.py,sha256=Q5vOkerWXNCtRbSboHjXcnjoys8bHv5b7G_fH1A1lio,13663
|
|
37
37
|
solara/components/dataframe.py,sha256=9Zr-usCz9UkO2xpNlDpooRGu-Bwtn49Cy4cdAaO_KGg,21033
|
|
38
38
|
solara/components/datatable.py,sha256=A64-BRM3d8ZKUURbYSfHCsqqJg7MKQhFpnJ9uqCBGMg,7836
|
|
@@ -113,9 +113,10 @@ solara/server/jupytertools.py,sha256=cYFIUjLX7n0uuEXqWVWvmV6sV7R_MNg8ZZlabQgw8vk
|
|
|
113
113
|
solara/server/kernel.py,sha256=3mwRRBw6BOcKLACL4fCUGgtI_RZ5KTSM1MlAtRlDbmA,11092
|
|
114
114
|
solara/server/kernel_context.py,sha256=RrNVAkoev6u6LZBvDfG86zyVs7eDVUsrp_4Au_FLlgY,16718
|
|
115
115
|
solara/server/patch.py,sha256=W-UG_TXKIbQRV0B9rGkJzg21EGV00ra5kQZAZGQquZc,19111
|
|
116
|
+
solara/server/qt.py,sha256=74ffA2Agk5a1edEeF6_8KS1FlQlJoHrFOkULI2PxT4k,3762
|
|
116
117
|
solara/server/reload.py,sha256=BBH7QhrV1-e9RVyNE3uz1oPj1DagC3t_XSqGPNz0nJE,9747
|
|
117
118
|
solara/server/server.py,sha256=fUb9BpvjCNLlSAOUIjkge6PUO07VGEetdQi1chEFzRM,16569
|
|
118
|
-
solara/server/settings.py,sha256=
|
|
119
|
+
solara/server/settings.py,sha256=b82BNWOntcWithynahDDAZFQyx3-kmyll7FwqIOn1sg,7369
|
|
119
120
|
solara/server/shell.py,sha256=xKox0fvDxdcWleE8p2ffCkihvjLJsWn2FujMbgUjYn0,8677
|
|
120
121
|
solara/server/starlette.py,sha256=yuXCJbpD5tq2JoX0KoRh5YMh67fp33rVCDb3zuwgHxk,29054
|
|
121
122
|
solara/server/telemetry.py,sha256=GPKGA5kCIqJb76wgxQ2_U2uV_s0r-1tKqv-GVxo5hs8,6038
|
|
@@ -126,7 +127,7 @@ solara/server/assets/custom.css,sha256=4p04-uxHTobfr6Xkvf1iOrYiks8NciWLT_EwHZSy6
|
|
|
126
127
|
solara/server/assets/custom.js,sha256=YT-UUYzA5uI5-enmbIsrRhofY_IJAO-HanaMwiNUEos,16
|
|
127
128
|
solara/server/assets/favicon.png,sha256=Ssgmi5eZeGIGABOrxW8AH3hyvy5a9avdDIDYsmEUMpM,1924
|
|
128
129
|
solara/server/assets/favicon.svg,sha256=HXAji-JQGBaGi2_iyk3vHgEDgdFYtsWTVqOE6QmVLKc,1240
|
|
129
|
-
solara/server/assets/style.css,sha256=
|
|
130
|
+
solara/server/assets/style.css,sha256=UYfYkMO5Fs_5L5qLMaA2HCL-CDyHI4EOnjg2HN2YpvI,40867
|
|
130
131
|
solara/server/assets/theme-dark.css,sha256=w9a0BDQoXnhoLC4Uz8QdCiFvZsDYV4XvOL4CoSyAnBM,16733
|
|
131
132
|
solara/server/assets/theme-light.css,sha256=zYjHebS5dGq9o4wNcS8nFyuE1oiqSmhcxVHNf3FYZ3Q,15637
|
|
132
133
|
solara/server/assets/theme.js,sha256=kwXC-5gj9JKcwb8JMaV2sZ5t_F26c6ypqfozLZZ8Izo,21
|
|
@@ -141,18 +142,18 @@ solara/server/pyinstaller/hook-solara.py,sha256=8-tQOtgiNgf3btngI69YPeZp9lLgJpVj
|
|
|
141
142
|
solara/server/static/ansi.js,sha256=Oa3cXY3u5vSSq8-P6JnAqa2S9cymxY0iL6wG449jFJk,7797
|
|
142
143
|
solara/server/static/highlight-dark.css,sha256=xO8-vta9vG4s1OfJNHXWqiLWzx_gM03jouSmQvRmj-I,6809
|
|
143
144
|
solara/server/static/highlight.css,sha256=k8ZdT5iwrGQ5tXTQHAXuxvZrSUq3kwCdEpy3mlFoZjs,2637
|
|
144
|
-
solara/server/static/main-vuetify.js,sha256=
|
|
145
|
+
solara/server/static/main-vuetify.js,sha256=R3qM4xMlstMpRUdRaul78p34z_Av2ONSTXksg2V9TqQ,9503
|
|
145
146
|
solara/server/static/main.js,sha256=mcx4JNQ4Lg4pNdUIqMoZos1mZyYFS48yd_JNFFJUqIE,5679
|
|
146
|
-
solara/server/static/solara_bootstrap.py,sha256=
|
|
147
|
+
solara/server/static/solara_bootstrap.py,sha256=e5_ztDjhDG8AjekuOm_fHFxGT5hhFJbiFg76cvqOQCg,3195
|
|
147
148
|
solara/server/static/sun.svg,sha256=jEKBAGCr7b9zNYv0VUb7lMWKjnU2dX69_Ye_DZWGXJI,6855
|
|
148
149
|
solara/server/static/webworker.js,sha256=cjAFz7-SygStHJnYlJUlJs-gE_7YQeQ-WBDcmKYyjvo,1372
|
|
149
150
|
solara/server/templates/index.html.j2,sha256=JXQo1M-STFHLBOFetgG7509cAq8xUP0VAEtYDzz35fY,31
|
|
150
151
|
solara/server/templates/loader-plain.css,sha256=SjZEbU8s2aUQk9UYwmbWMKXlGZe0XTvy4dfFTBeUWWo,205
|
|
151
152
|
solara/server/templates/loader-plain.html,sha256=VEtMDC8MQj75o2iWJ_gR70Jp05oOoyRBKbhS4o-FXVI,718
|
|
152
153
|
solara/server/templates/loader-solara.css,sha256=QerfzwlenkSJMq8uk_qEtoSdcI-DKMRrH9XXDEPsrUA,1670
|
|
153
|
-
solara/server/templates/loader-solara.html,sha256=
|
|
154
|
+
solara/server/templates/loader-solara.html,sha256=wFPnTevFBcRXQj6ZCZdgkOGTMwAAiOmNlgFdzdJLpXA,2744
|
|
154
155
|
solara/server/templates/plain.html,sha256=yO1r2hidA3bxOclaxtI_vTZtdDTFn2KKeeoldJuinXk,2762
|
|
155
|
-
solara/server/templates/solara.html.j2,sha256=
|
|
156
|
+
solara/server/templates/solara.html.j2,sha256=qbhRj-KYUr-HMlUpFOblGCNXg4ko6QXArIywvpCCirM,21850
|
|
156
157
|
solara/template/button.py,sha256=HM382prl4bNLF8sLBd9Sh43ReMGedG_z_h4XN4mDYRI,311
|
|
157
158
|
solara/template/markdown.py,sha256=31G3ezFooiveSrUH5afz5_nJ8SStjbx-_x5YLXv_hPk,1137
|
|
158
159
|
solara/template/portal/.flake8,sha256=wxWLwamdP33Jm1mPa1sVe3uT0AZkG_wHPbY3Ci7j5-g,136
|
|
@@ -197,8 +198,8 @@ solara/website/components/mailchimp.vue,sha256=f2cFKUfl7gL9FJbGLCtPRUFBghxS8kcGu
|
|
|
197
198
|
solara/website/components/markdown.py,sha256=jWqDYQWiN7_aNIUNjhUePT_weO5UoSowh4P0wZF7bjw,1497
|
|
198
199
|
solara/website/components/markdown_nav.vue,sha256=VK6TBDcocPyfLyripFR1BQITj00tLe0fwauumYQUExE,988
|
|
199
200
|
solara/website/components/notebook.py,sha256=MM73_c5l49SSpK63O4TYMsQ-mA43CwfhfU7VKXjfNC0,6867
|
|
200
|
-
solara/website/components/sidebar.py,sha256=
|
|
201
|
-
solara/website/pages/__init__.py,sha256=
|
|
201
|
+
solara/website/components/sidebar.py,sha256=VRbxGkhsOx26H458gkW1p44NCoTFn8EhWqpyB4ahFso,6071
|
|
202
|
+
solara/website/pages/__init__.py,sha256=h-mETi0N10iKWTs9xYKC1ruAJBYzco0-bWDmjBSsdFY,21181
|
|
202
203
|
solara/website/pages/doc_use_download.py,sha256=wTzDT21FRcHwfDAAxZPmHFqF5lyLvkHZ2mieZ4kfz9Y,3127
|
|
203
204
|
solara/website/pages/docutils.py,sha256=2ne991oUtK4dMj-qN18NtsVYxSfCT1c6o5yYThQnxUE,736
|
|
204
205
|
solara/website/pages/home.vue,sha256=1L3TVvBY7qXkkR0jIW49olDc5ZpglzA8pm06JLMkFQc,43617
|
|
@@ -248,7 +249,7 @@ solara/website/pages/documentation/advanced/content/20-understanding/15-anatomy.
|
|
|
248
249
|
solara/website/pages/documentation/advanced/content/20-understanding/17-rules-of-hooks.md,sha256=A-wHZQwNPcZg1S_hcaE36VG24H1Hx_HXP4jEuWNR5zk,5088
|
|
249
250
|
solara/website/pages/documentation/advanced/content/20-understanding/18-containers.md,sha256=Bkl22GXxO0MhTVpUK1q0l5h_wBWNgkR1ZoCG28p7r40,4905
|
|
250
251
|
solara/website/pages/documentation/advanced/content/20-understanding/20-solara.md,sha256=sNK-mmgbj9rDHOXu5JaP7OMQdX0chOZ72-aMdOEOkug,751
|
|
251
|
-
solara/website/pages/documentation/advanced/content/20-understanding/40-routing.md,sha256=
|
|
252
|
+
solara/website/pages/documentation/advanced/content/20-understanding/40-routing.md,sha256=lb_TDXOv43oq3hqnOwjmUpSWCEhaO5l2ZQSPBL6riEQ,10365
|
|
252
253
|
solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md,sha256=Svb6I84nFJFPr1D-nGcHc5TummZ6TqAU7suCoUWbg5c,6336
|
|
253
254
|
solara/website/pages/documentation/advanced/content/20-understanding/60-voila.md,sha256=jlL0kyzzDdHytNizBBLPx7buFFforlIDdMF724C2RLE,1132
|
|
254
255
|
solara/website/pages/documentation/advanced/content/30-enterprise/00-overview.md,sha256=MmrZWt4KyKVGw7kX3nlcAIgf814RHmf3A5BUQiDZIYA,381
|
|
@@ -367,10 +368,10 @@ solara/website/pages/documentation/components/viz/echarts.py,sha256=__uayej4ttWZ
|
|
|
367
368
|
solara/website/pages/documentation/components/viz/matplotlib.py,sha256=YEvCQyy5lmuV_6NArZ8qYucLMN6ah7pVJNk-xkouDAg,761
|
|
368
369
|
solara/website/pages/documentation/components/viz/plotly.py,sha256=t54SJLkdf7jfO7XwAnbuArotUCq_6aX_CCsXi_Z7c1k,1377
|
|
369
370
|
solara/website/pages/documentation/components/viz/plotly_express.py,sha256=dnBKzdr1IQF5bkSN2f8hkNbW4u7mfEwhNEufmaaDcEM,957
|
|
370
|
-
solara/website/pages/documentation/examples/__init__.py,sha256
|
|
371
|
+
solara/website/pages/documentation/examples/__init__.py,sha256=8bBzOr0LLRIHyaHMFAKkumrXYdcWcoU50_GITvAlIEc,1676
|
|
371
372
|
solara/website/pages/documentation/examples/ipycanvas.py,sha256=58iN7Hby5aeQglhCkDrXQDejszMf_aFvvEQWAEdccPE,1846
|
|
372
373
|
solara/website/pages/documentation/examples/ai/__init__.py,sha256=ZicYzTHeFnnVnfQitWJ8t3-VGUDlMK5g-mXc3Y2HmkY,192
|
|
373
|
-
solara/website/pages/documentation/examples/ai/chatbot.py,sha256=
|
|
374
|
+
solara/website/pages/documentation/examples/ai/chatbot.py,sha256=JP_L61nVdaWIaeG2gRsqBsRZTpvMEqqb2M2p_asBM5s,2877
|
|
374
375
|
solara/website/pages/documentation/examples/ai/tokenizer.py,sha256=vA_ut_9lka-uoDI86qfouzB7CcXu-1OYHTFQKNXtFao,3701
|
|
375
376
|
solara/website/pages/documentation/examples/basics/__init__.py,sha256=1GvAS0idpN-CcfBwmcVZMA6XjoewDjZ75-Vq16QCpQU,159
|
|
376
377
|
solara/website/pages/documentation/examples/basics/sine.py,sha256=0xTkCwBajwAl5z-ayT47kzS5ziRfsa48A7XxQeXgxtQ,554
|
|
@@ -388,24 +389,24 @@ solara/website/pages/documentation/examples/general/live_update.py,sha256=Zte8ii
|
|
|
388
389
|
solara/website/pages/documentation/examples/general/login_oauth.py,sha256=STckaXaDxdEnltl5PkgkSmw-FASqUqr4T5llGI-UwNA,2551
|
|
389
390
|
solara/website/pages/documentation/examples/general/mycard.vue,sha256=j1p32TyRHYpi4OW__K1UxwMElif3R9J-POlTb8ACCMg,1359
|
|
390
391
|
solara/website/pages/documentation/examples/general/pokemon_search.py,sha256=ff6DBH5pCKU175A99VGlvNDEnzO1P27nMVUNcDNo-ag,2079
|
|
391
|
-
solara/website/pages/documentation/examples/general/vue_component.py,sha256=
|
|
392
|
+
solara/website/pages/documentation/examples/general/vue_component.py,sha256=RjzyeGrOtpQzwvAx9Dn5jM4uhDpkD0c_SNM7VrgmI_g,1729
|
|
392
393
|
solara/website/pages/documentation/examples/libraries/__init__.py,sha256=x7Hy8EmHugarFZIP2Wl4K7ACs_70iC4KmOhMVHXQqEo,144
|
|
393
|
-
solara/website/pages/documentation/examples/libraries/altair.py,sha256=
|
|
394
|
-
solara/website/pages/documentation/examples/libraries/bqplot.py,sha256=
|
|
395
|
-
solara/website/pages/documentation/examples/libraries/ipyleaflet.py,sha256=
|
|
396
|
-
solara/website/pages/documentation/examples/libraries/ipyleaflet_advanced.py,sha256=
|
|
394
|
+
solara/website/pages/documentation/examples/libraries/altair.py,sha256=nphFgEWxlgkI14OwRcP59AnL0MMTAIin01-L8_kJAhU,2180
|
|
395
|
+
solara/website/pages/documentation/examples/libraries/bqplot.py,sha256=6b6X5htldc8DzvB4avJRUZkqLONU17ut2gW9cGfzBQE,1180
|
|
396
|
+
solara/website/pages/documentation/examples/libraries/ipyleaflet.py,sha256=zqXX1HZHvfAvVDUc1YUE-9EBx7qH4Zs0_-ijRpw3I3Y,1163
|
|
397
|
+
solara/website/pages/documentation/examples/libraries/ipyleaflet_advanced.py,sha256=IhFr1OHiEAyonDNiUHkpKRVVakZ1MyPqY8pQWrVMKsI,2292
|
|
397
398
|
solara/website/pages/documentation/examples/utilities/__init__.py,sha256=5AtOFUlZpWTOya9fn0jSzKiJ-tpOg_fDzFcb9aJQiFM,155
|
|
398
399
|
solara/website/pages/documentation/examples/utilities/calculator.py,sha256=ysDgp0LRK7E3OeEBalJn07u8-fQagg6hmeG5Juosejs,5529
|
|
399
|
-
solara/website/pages/documentation/examples/utilities/countdown_timer.py,sha256=
|
|
400
|
+
solara/website/pages/documentation/examples/utilities/countdown_timer.py,sha256=0krBNsGghKZ2iPJL3DJWeTOpIukYk694SLiYJ8z_KlI,2017
|
|
400
401
|
solara/website/pages/documentation/examples/utilities/todo.py,sha256=tFsCt429TaOLyWLjb7UW-1ji64Uwv3JhN8y6EQHJHXM,6480
|
|
401
402
|
solara/website/pages/documentation/examples/visualization/__init__.py,sha256=OaLTp4A4J6y0lZS6mVgY78eNRQ0SagOK261KNY4LEVQ,105
|
|
402
|
-
solara/website/pages/documentation/examples/visualization/annotator.py,sha256=
|
|
403
|
-
solara/website/pages/documentation/examples/visualization/linked_views.py,sha256=
|
|
403
|
+
solara/website/pages/documentation/examples/visualization/annotator.py,sha256=CAXT3mjQE9RBQMmaDCJjSHZr1Fv66M0ESR3foFTqUWo,1761
|
|
404
|
+
solara/website/pages/documentation/examples/visualization/linked_views.py,sha256=kPmSGig5Tkyh_Jjye32yKOwjpW6IOVMwc9KKjrJ7jIk,2772
|
|
404
405
|
solara/website/pages/documentation/examples/visualization/plotly.py,sha256=33kKSV-h8cyU6KJ3XfiTrkHtIrtUg7SbYlz0XWLNBN0,1268
|
|
405
406
|
solara/website/pages/documentation/faq/__init__.py,sha256=GcdqdTEWC-xDgIWECQleZbbnmacelt9K1ZyTw2nf9Wc,278
|
|
406
407
|
solara/website/pages/documentation/faq/content/99-faq.md,sha256=UWBlt5nx_GXAJP8b87e7Hw1agiuY6-nCIh9WPLvSTr4,3939
|
|
407
408
|
solara/website/pages/documentation/getting_started/__init__.py,sha256=bLLvasuqVVWJxGN89m77ChZhDivEhVavw9-_CiG3IZA,414
|
|
408
|
-
solara/website/pages/documentation/getting_started/content/00-quickstart.md,sha256=
|
|
409
|
+
solara/website/pages/documentation/getting_started/content/00-quickstart.md,sha256=UP80_MSeh9odXMncnZHYTs6bPRXQVN2WVKpuodznpus,3465
|
|
409
410
|
solara/website/pages/documentation/getting_started/content/01-introduction.md,sha256=43EhX3JhwFICQademwwFgALuCc2chYa2xkUKp8pkid4,6609
|
|
410
411
|
solara/website/pages/documentation/getting_started/content/02-installing.md,sha256=zYn_4b4TR2rsMyi-UloAAI3D0qWaM1Wsbf0Uzz_XYj0,5609
|
|
411
412
|
solara/website/pages/documentation/getting_started/content/80-what-is-lab.md,sha256=4CLyCZYkApsWNdXJ3N6YYShj5s4tJhYH1V6svtVgCcE,307
|
|
@@ -450,11 +451,11 @@ solara/widgets/__init__.py,sha256=D3RfEez9dllmst64_nyzzII-NZXoNMEPDnEog4ov3VE,43
|
|
|
450
451
|
solara/widgets/widgets.py,sha256=AIRcMhSDFpESQ1JzUszlb2NH5FwSImLnmd4kqcc9jkY,2452
|
|
451
452
|
solara/widgets/vue/gridlayout.vue,sha256=hk10RsEQBxkknTmqa0wtBia9LWQGdDsXlejnAj7USU8,3441
|
|
452
453
|
solara/widgets/vue/html.vue,sha256=48K5rjp0AdJDeRV6F3nOHW3J0WXPeHn55r5pGClK2fU,112
|
|
453
|
-
solara/widgets/vue/navigator.vue,sha256=
|
|
454
|
-
solara/widgets/vue/vegalite.vue,sha256=
|
|
455
|
-
solara_ui-1.
|
|
456
|
-
solara_ui-1.
|
|
457
|
-
solara_ui-1.
|
|
458
|
-
solara_ui-1.
|
|
459
|
-
solara_ui-1.
|
|
460
|
-
solara_ui-1.
|
|
454
|
+
solara/widgets/vue/navigator.vue,sha256=7fkX-4_YSnnMIPUMKMvQVVEzrmhY9BFAYvHMqZqTXpI,4790
|
|
455
|
+
solara/widgets/vue/vegalite.vue,sha256=zhocRsUCNIRQCEbD16er5sYnuHU0YThatRHnorA3P18,4596
|
|
456
|
+
solara_ui-1.41.0.data/data/etc/jupyter/jupyter_notebook_config.d/solara.json,sha256=3UhTBQi6z7F7pPjmqXxfddv79c8VGR9H7zStDLp6AwY,115
|
|
457
|
+
solara_ui-1.41.0.data/data/etc/jupyter/jupyter_server_config.d/solara.json,sha256=D9J-rYxAzyD5GOqWvuPjacGUVFHsYtTfZ4FUbRzRvIA,113
|
|
458
|
+
solara_ui-1.41.0.dist-info/METADATA,sha256=hy_TH8LcVZ6PfXD3xNx53kNzx3dfmlMKSW3P5zNxjwU,7285
|
|
459
|
+
solara_ui-1.41.0.dist-info/WHEEL,sha256=L5_n4Kc1NmrSdVgbp6hdnwwVwBnoYOCnbHBRMD-qNJ4,105
|
|
460
|
+
solara_ui-1.41.0.dist-info/licenses/LICENSE,sha256=fFJUz-CWzZ9nEc4QZKu44jMEoDr5fEW-SiqljKpD82E,1086
|
|
461
|
+
solara_ui-1.41.0.dist-info/RECORD,,
|
|
File without changes
|
{solara_ui-1.40.0.data → solara_ui-1.41.0.data}/data/etc/jupyter/jupyter_server_config.d/solara.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|