nova-trame 0.13.1__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.
@@ -0,0 +1,85 @@
1
+ """View implementation for Interactive2DPlot."""
2
+
3
+ from typing import Any, Optional
4
+
5
+ from altair import Chart
6
+ from trame.widgets import client, vega
7
+
8
+
9
+ class Interactive2DPlot(vega.Figure):
10
+ """Creates an interactive 2D plot in Trame using Vega.
11
+
12
+ Trame provides two primary mechanisms for composing 2D plots: `Plotly <https://github.com/Kitware/trame-plotly>`_
13
+ and `Vega-Lite/Altair <https://github.com/Kitware/trame-vega>`_. If you only need static plots or basic browser
14
+ event handling, then please use these libraries directly.
15
+
16
+ If you need to capture complex front-end interactions, then you can
17
+ use our provided Interactive2DPlot widget that is based on Vega-Lite. This uses the same API as Trame's vega.Figure,
18
+ except that it will automatically sync Vega's signal states as the user interacts with the plot.
19
+
20
+ The following allows the user to select a region of the plot and tracks the selected region in Python:
21
+
22
+ .. literalinclude:: ../tests/test_interactive_2d_plot.py
23
+ :start-after: setup 2d plot
24
+ :end-before: setup 2d plot complete
25
+ :dedent:
26
+ """
27
+
28
+ def __init__(self, figure: Optional[Chart] = None, **kwargs: Any) -> None:
29
+ """Constructor for Interactive2DPlot.
30
+
31
+ Parameters
32
+ ----------
33
+ figure : `altair.Chart <https://altair-viz.github.io/user_guide/generated/toplevel/altair.Chart.html#altair.Chart>`_
34
+ Altair chart object
35
+ kwargs
36
+ Arguments to be passed to `AbstractElement <https://trame.readthedocs.io/en/latest/core.widget.html#trame_client.widgets.core.AbstractElement>`_
37
+
38
+ Returns
39
+ -------
40
+ None
41
+ """
42
+ self._initialized = False
43
+
44
+ super().__init__(figure=figure, **kwargs)
45
+ self.ref = f"nova__vega_{self._id}"
46
+ self.server.state[self.ref] = {}
47
+ self._start_update_handlers = client.JSEval(
48
+ exec=(
49
+ "async () => {"
50
+ f" let ref = window.trame.refs['{self.ref}'];"
51
+ " await ref.mountVis();" # wait for the new visualization to be rendered in the front-end
52
+ " if (ref.viz === undefined) { return; }" # If the component is not mounted, do nothing
53
+ " for (const [key, value] of Object.entries(ref.viz.view._signals)) {"
54
+ " if (key === 'unit') { continue; }" # this causes a JSError for some reason if not skipped
55
+ " ref.viz.view.addSignalListener(key, (name, value) => {"
56
+ f" window.trame.state.state['{self.ref}'][name] = value;" # sync front-end state
57
+ f" flushState('{self.ref}');" # sync back-end state
58
+ " })"
59
+ " }"
60
+ "}"
61
+ )
62
+ ).exec
63
+
64
+ client.ClientTriggers(mounted=self.update)
65
+
66
+ def get_signal_state(self, name: str) -> Any:
67
+ """Retrieves a Vega signal's state by name.
68
+
69
+ Parameters
70
+ ----------
71
+ name : str
72
+ The name of the signal to retrieve.
73
+
74
+ Returns
75
+ -------
76
+ typing.Any
77
+ The current value of the Vega signal.
78
+ """
79
+ return self.server.state[self.ref].get(name, None)
80
+
81
+ def update(self, figure: Optional[Chart] = None, **kwargs: Any) -> None:
82
+ super().update(figure=figure, **kwargs)
83
+
84
+ if hasattr(self, "_start_update_handlers"):
85
+ self._start_update_handlers()
@@ -0,0 +1,5 @@
1
+ from .grid import GridLayout
2
+ from .hbox import HBoxLayout
3
+ from .vbox import VBoxLayout
4
+
5
+ __all__ = ["GridLayout", "HBoxLayout", "VBoxLayout"]
@@ -0,0 +1,148 @@
1
+ """Trame implementation of the GridLayout class."""
2
+
3
+ from typing import Any, Optional, Union
4
+
5
+ from trame.widgets import html
6
+ from trame_client.widgets.core import AbstractElement
7
+
8
+
9
+ class GridLayout(html.Div):
10
+ """Creates a grid with a specified number of columns."""
11
+
12
+ def __init__(
13
+ self,
14
+ columns: int = 1,
15
+ height: Optional[Union[int, str]] = None,
16
+ width: Optional[Union[int, str]] = None,
17
+ halign: Optional[str] = None,
18
+ valign: Optional[str] = None,
19
+ **kwargs: Any,
20
+ ) -> None:
21
+ """Constructor for GridLayout.
22
+
23
+ Parameters
24
+ ----------
25
+ columns : int
26
+ The number of columns in the grid.
27
+ height : optional[int | str]
28
+ The height of this grid. If an integer is provided, it is interpreted as pixels. If a string is provided,
29
+ the string is treated as a CSS value.
30
+ width : optional[int | str]
31
+ The width of this grid. If an integer is provided, it is interpreted as pixels. If a string is provided,
32
+ the string is treated as a CSS value.
33
+ halign : optional[str]
34
+ The horizontal alignment of items in the grid. See `MDN
35
+ <https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items>`__ for available options.
36
+ valign : optional[str]
37
+ The vertical alignment of items in the grid. See `MDN
38
+ <https://developer.mozilla.org/en-US/docs/Web/CSS/align-items>`__ for available options.
39
+ kwargs : Any
40
+ Additional keyword arguments to pass to html.Div.
41
+
42
+ Returns
43
+ -------
44
+ None
45
+
46
+ Examples
47
+ --------
48
+ Basic usage:
49
+
50
+ .. literalinclude:: ../tests/gallery/app.py
51
+ :start-after: setup grid
52
+ :end-before: setup grid complete
53
+ :dedent:
54
+
55
+ Building a custom left-middle-right layout:
56
+
57
+ .. literalinclude:: ../tests/test_layouts.py
58
+ :start-after: setup complex layout example
59
+ :end-before: setup complex layout example complete
60
+ :dedent:
61
+ """
62
+ classes = kwargs.pop("classes", [])
63
+ if isinstance(classes, list):
64
+ classes = " ".join(classes)
65
+ classes += " d-grid"
66
+
67
+ style = self.get_root_styles(columns, height, width, halign, valign) | kwargs.pop("style", {})
68
+
69
+ super().__init__(classes=classes, style=style, **kwargs)
70
+
71
+ def get_root_styles(
72
+ self,
73
+ columns: int,
74
+ height: Optional[Union[int, str]],
75
+ width: Optional[Union[int, str]],
76
+ halign: Optional[str],
77
+ valign: Optional[str],
78
+ ) -> dict[str, str]:
79
+ height = f"{height}px" if isinstance(height, int) else height
80
+ width = f"{width}px" if isinstance(width, int) else width
81
+
82
+ styles = {
83
+ "grid-template-columns": f"repeat({columns}, 1fr)",
84
+ }
85
+
86
+ if height:
87
+ styles["height"] = height
88
+ if width:
89
+ styles["width"] = width
90
+ if halign:
91
+ styles["justify-items"] = halign
92
+ if valign:
93
+ styles["align-items"] = valign
94
+
95
+ return styles
96
+
97
+ def get_row_style(self, row_span: int) -> str:
98
+ return f"grid-row-end: span {row_span};"
99
+
100
+ def get_column_style(self, column_span: int) -> str:
101
+ return f"grid-column-end: span {column_span};"
102
+
103
+ def add_child(self, child: Union[AbstractElement, str]) -> AbstractElement:
104
+ """Add a child to the grid.
105
+
106
+ Do not call this directly. Instead, use Trame's `with` syntax, which will call this method internally. This
107
+ method is documented here as a reference for the span parameters.
108
+
109
+ Parameters
110
+ ----------
111
+ child : `AbstractElement \
112
+ <https://trame.readthedocs.io/en/latest/core.widget.html#trame_client.widgets.core.AbstractElement>`_ | str
113
+ The child to add to the grid.
114
+ row_span : int
115
+ The number of rows this child should span.
116
+ column_span : int
117
+ The number of columns this child should span.
118
+
119
+ Returns
120
+ -------
121
+ None
122
+
123
+ Example
124
+ -------
125
+ .. literalinclude:: ../tests/gallery/app.py
126
+ :start-after: grid row and column span example
127
+ :end-before: grid row and column span example end
128
+ :dedent:
129
+ """
130
+ if isinstance(child, str):
131
+ child = html.Div(child)
132
+
133
+ row_span = 1
134
+ column_span = 1
135
+ if "row_span" in child._py_attr:
136
+ row_span = child._py_attr["row_span"]
137
+ if "column_span" in child._py_attr:
138
+ column_span = child._py_attr["column_span"]
139
+
140
+ if "style" not in child._py_attr or child.style is None:
141
+ child.style = ""
142
+ child.style += f"; {self.get_row_style(row_span)} {self.get_column_style(column_span)}"
143
+
144
+ if "classes" not in child._py_attr or child.classes is None:
145
+ child.classes = ""
146
+ child.classes += " d-grid-item"
147
+
148
+ super().add_child(child)
@@ -0,0 +1,79 @@
1
+ """Trame implementation of the HBoxLayout class."""
2
+
3
+ from typing import Any, Optional, Union
4
+
5
+ from trame.widgets import html
6
+
7
+
8
+ class HBoxLayout(html.Div):
9
+ """Creates an element that horizontally stacks its children."""
10
+
11
+ def __init__(
12
+ self,
13
+ height: Optional[Union[int, str]] = None,
14
+ width: Optional[Union[int, str]] = None,
15
+ halign: Optional[str] = None,
16
+ valign: Optional[str] = None,
17
+ **kwargs: Any,
18
+ ) -> None:
19
+ """Constructor for HBoxLayout.
20
+
21
+ Parameters
22
+ ----------
23
+ height : optional[int | str]
24
+ The height of this box. If an integer is provided, it is interpreted as pixels. If a string is provided,
25
+ the string is treated as a CSS value.
26
+ width : optional[int | str]
27
+ The width of this box. If an integer is provided, it is interpreted as pixels. If a string is provided,
28
+ the string is treated as a CSS value.
29
+ halign : optional[str]
30
+ The horizontal alignment of items in the grid. See `MDN
31
+ <https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items>`__ for available options.
32
+ valign : optional[str]
33
+ The vertical alignment of items in the grid. See `MDN
34
+ <https://developer.mozilla.org/en-US/docs/Web/CSS/align-items>`__ for available options.
35
+ kwargs : Any
36
+ Additional keyword arguments to pass to html.Div.
37
+
38
+ Returns
39
+ -------
40
+ None
41
+
42
+ Example
43
+ -------
44
+ .. literalinclude:: ../tests/gallery/app.py
45
+ :start-after: setup hbox
46
+ :end-before: setup hbox complete
47
+ :dedent:
48
+ """
49
+ classes = kwargs.pop("classes", [])
50
+ if isinstance(classes, list):
51
+ classes = " ".join(classes)
52
+ classes += " d-flex flex-row"
53
+
54
+ style = self.get_root_styles(height, width, halign, valign) | kwargs.pop("style", {})
55
+
56
+ super().__init__(classes=classes, style=style, **kwargs)
57
+
58
+ def get_root_styles(
59
+ self,
60
+ height: Optional[Union[int, str]],
61
+ width: Optional[Union[int, str]],
62
+ halign: Optional[str],
63
+ valign: Optional[str],
64
+ ) -> dict:
65
+ height = f"{height}px" if isinstance(height, int) else height
66
+ width = f"{width}px" if isinstance(width, int) else width
67
+
68
+ styles = {}
69
+
70
+ if height:
71
+ styles["height"] = height
72
+ if width:
73
+ styles["width"] = width
74
+ if halign:
75
+ styles["justify-content"] = halign
76
+ if valign:
77
+ styles["align-items"] = valign
78
+
79
+ return styles
@@ -0,0 +1,79 @@
1
+ """Trame implementation of the VBoxLayout class."""
2
+
3
+ from typing import Any, Optional, Union
4
+
5
+ from trame.widgets import html
6
+
7
+
8
+ class VBoxLayout(html.Div):
9
+ """Creates an element that vertically stacks its children."""
10
+
11
+ def __init__(
12
+ self,
13
+ height: Optional[Union[int, str]] = None,
14
+ width: Optional[Union[int, str]] = None,
15
+ halign: Optional[str] = None,
16
+ valign: Optional[str] = None,
17
+ **kwargs: Any,
18
+ ) -> None:
19
+ """Constructor for VBoxLayout.
20
+
21
+ Parameters
22
+ ----------
23
+ height : optional[int | str]
24
+ The height of this box. If an integer is provided, it is interpreted as pixels. If a string is provided,
25
+ the string is treated as a CSS value.
26
+ width : optional[int | str]
27
+ The width of this box. If an integer is provided, it is interpreted as pixels. If a string is provided,
28
+ the string is treated as a CSS value.
29
+ halign : optional[str]
30
+ The horizontal alignment of items in the grid. See `MDN
31
+ <https://developer.mozilla.org/en-US/docs/Web/CSS/align-items>`__ for available options.
32
+ valign : optional[str]
33
+ The vertical alignment of items in the grid. See `MDN
34
+ <https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items>`__ for available options.
35
+ kwargs : Any
36
+ Additional keyword arguments to pass to html.Div.
37
+
38
+ Returns
39
+ -------
40
+ None
41
+
42
+ Example
43
+ -------
44
+ .. literalinclude:: ../tests/gallery/app.py
45
+ :start-after: setup vbox
46
+ :end-before: setup vbox complete
47
+ :dedent:
48
+ """
49
+ classes = kwargs.pop("classes", [])
50
+ if isinstance(classes, list):
51
+ classes = " ".join(classes)
52
+ classes += " d-flex flex-column"
53
+
54
+ style = self.get_root_styles(height, width, halign, valign) | kwargs.pop("style", {})
55
+
56
+ super().__init__(classes=classes, style=style, **kwargs)
57
+
58
+ def get_root_styles(
59
+ self,
60
+ height: Optional[Union[int, str]],
61
+ width: Optional[Union[int, str]],
62
+ halign: Optional[str],
63
+ valign: Optional[str],
64
+ ) -> dict:
65
+ height = f"{height}px" if isinstance(height, int) else height
66
+ width = f"{width}px" if isinstance(width, int) else width
67
+
68
+ styles = {}
69
+
70
+ if height:
71
+ styles["height"] = height
72
+ if width:
73
+ styles["width"] = width
74
+ if halign:
75
+ styles["align-items"] = halign
76
+ if valign:
77
+ styles["justify-content"] = valign
78
+
79
+ return styles
@@ -0,0 +1,3 @@
1
+ from .theme import ThemedApp
2
+
3
+ __all__ = ["ThemedApp"]
@@ -0,0 +1,30 @@
1
+ html {
2
+ overflow-y: auto;
3
+ }
4
+
5
+ .d-grid {
6
+ display: grid;
7
+ gap: 0.25em;
8
+ grid-auto-rows: auto;
9
+ }
10
+
11
+ @media only screen and (max-width: 959px) {
12
+ .d-grid {
13
+ grid-template-columns: repeat(1, 1fr) !important;
14
+ }
15
+
16
+ .d-grid-item {
17
+ grid-column: 1 / 1 !important;
18
+ }
19
+ }
20
+
21
+ /* Global font sizes can't be set through the Vuetify configuration. */
22
+ .v-theme--CompactTheme {
23
+ font-size: 0.85rem;
24
+
25
+ .v-card-title,
26
+ .v-list-item-title,
27
+ .v-toolbar-title {
28
+ font-size: 1rem;
29
+ }
30
+ }
Binary file
@@ -0,0 +1,180 @@
1
+ {
2
+ "defaults": {
3
+ "global": {
4
+ "hideDetails": "auto",
5
+ "hideSpinButtons": true,
6
+ "persistentPlaceholder": true
7
+ },
8
+ "VAlert": {
9
+ "color": "secondary"
10
+ },
11
+ "VAppBar": {
12
+ "color": "primary",
13
+ "VBtn": {
14
+ "color": false
15
+ }
16
+ },
17
+ "VBadge": {
18
+ "color": "secondary"
19
+ },
20
+ "VBtn": {
21
+ "color": "primary"
22
+ },
23
+ "VBtnToggle": {
24
+ "color": "primary",
25
+ "VBtn": {
26
+ "class": "border-primary border-sm"
27
+ }
28
+ },
29
+ "VCard": {
30
+ "VCardSubtitle": {
31
+ "style": {
32
+ "white-space": "normal"
33
+ }
34
+ },
35
+ "VCardTitle": {
36
+ "style": {
37
+ "line-height": 1.2,
38
+ "white-space": "normal"
39
+ }
40
+ }
41
+ },
42
+ "VCardSubtitle": {
43
+ "opacity": 0.8
44
+ },
45
+ "VCheckbox": {
46
+ "color": "primary"
47
+ },
48
+ "VChip": {
49
+ "color": "primary"
50
+ },
51
+ "VDivider": {
52
+ "color": "primary"
53
+ },
54
+ "VExpansionPanels": {
55
+ "color": "primary"
56
+ },
57
+ "VFileInput": {
58
+ "color": "primary",
59
+ "prependIcon": false
60
+ },
61
+ "VLabel": {
62
+ "style": {
63
+ "opacity": 1.0
64
+ }
65
+ },
66
+ "VList": {
67
+ "VListItemAction": {
68
+ "VBtn": {
69
+ "class": "ml-2"
70
+ },
71
+ "VProgressCircular": {
72
+ "class": "ml-2"
73
+ }
74
+ }
75
+ },
76
+ "VListItem": {
77
+ "VBtn": {
78
+ "color": "secondary"
79
+ }
80
+ },
81
+ "VListItemSubtitle": {
82
+ "opacity": 0.8
83
+ },
84
+ "VProgressCircular": {
85
+ "color": "secondary"
86
+ },
87
+ "VProgressLinear": {
88
+ "color": "secondary"
89
+ },
90
+ "VRadioGroup": {
91
+ "color": "primary"
92
+ },
93
+ "VSelect": {
94
+ "color": "primary"
95
+ },
96
+ "VSlider": {
97
+ "color": "primary"
98
+ },
99
+ "VSnackbar": {
100
+ "color": "primary",
101
+ "VBtn": {
102
+ "color": false
103
+ }
104
+ },
105
+ "VSwitch": {
106
+ "color": "primary"
107
+ },
108
+ "VTextarea": {
109
+ "color": "primary"
110
+ },
111
+ "VTextField": {
112
+ "color": "primary"
113
+ },
114
+ "VWindowItem": {
115
+ "reverseTransition": "fade-transition",
116
+ "transition": "fade-transition"
117
+ }
118
+ },
119
+ "theme": {
120
+ "defaultTheme": "ModernTheme",
121
+ "themes": {
122
+ "ModernTheme": {
123
+ "colors": {
124
+ "background": "#f0f0f0",
125
+ "primary": "#007833",
126
+ "secondary": "#f48e5c"
127
+ },
128
+ "defaults": {
129
+ "VCard": {
130
+ "class": "pa-4",
131
+ "VCard": {
132
+ "class": "border-primary border-sm pa-4",
133
+ "style": {
134
+ "background-color": "rgba(var(--v-theme-primary), 0.1)"
135
+ }
136
+ },
137
+ "VListItem": {
138
+ "class": "border-primary border-sm",
139
+ "style": {
140
+ "background-color": "rgba(var(--v-theme-primary), 0.1)"
141
+ }
142
+ }
143
+ }
144
+ },
145
+ "title": "Modern",
146
+ "value": "ModernTheme"
147
+ },
148
+ "CompactTheme": {
149
+ "colors": {
150
+ "background": "#f0f0f0",
151
+ "primary": "#007833",
152
+ "secondary": "#f48e5c"
153
+ },
154
+ "defaults": {
155
+ "global": {
156
+ "density": "compact"
157
+ },
158
+ "VBadge": {
159
+ "dot": true
160
+ },
161
+ "VBtn": {
162
+ "density": "default"
163
+ },
164
+ "VTextField": {
165
+ "VBtn": {
166
+ "size": "small"
167
+ }
168
+ }
169
+ },
170
+ "title": "Compact",
171
+ "value": "CompactTheme"
172
+ }
173
+ },
174
+ "variations": {
175
+ "colors": ["primary", "secondary", "accent"],
176
+ "darken": 5,
177
+ "lighten": 5
178
+ }
179
+ }
180
+ }