pyglove 0.4.5.dev202412080808__py3-none-any.whl → 0.4.5.dev202412100720__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.
- pyglove/core/views/html/base.py +1 -1
- pyglove/core/views/html/controls/base.py +41 -4
- pyglove/core/views/html/controls/label.py +12 -1
- pyglove/core/views/html/controls/label_test.py +21 -2
- pyglove/core/views/html/controls/tab.py +138 -65
- pyglove/core/views/html/controls/tab_test.py +13 -15
- {pyglove-0.4.5.dev202412080808.dist-info → pyglove-0.4.5.dev202412100720.dist-info}/METADATA +1 -1
- {pyglove-0.4.5.dev202412080808.dist-info → pyglove-0.4.5.dev202412100720.dist-info}/RECORD +11 -11
- {pyglove-0.4.5.dev202412080808.dist-info → pyglove-0.4.5.dev202412100720.dist-info}/LICENSE +0 -0
- {pyglove-0.4.5.dev202412080808.dist-info → pyglove-0.4.5.dev202412100720.dist-info}/WHEEL +0 -0
- {pyglove-0.4.5.dev202412080808.dist-info → pyglove-0.4.5.dev202412100720.dist-info}/top_level.txt +0 -0
pyglove/core/views/html/base.py
CHANGED
@@ -62,6 +62,7 @@ class HtmlControl(pg_object.Object):
|
|
62
62
|
super()._on_bound()
|
63
63
|
self._rendered = False
|
64
64
|
self._css_styles = []
|
65
|
+
self._dynamic_injected_css = set()
|
65
66
|
self._scripts = []
|
66
67
|
|
67
68
|
def add_style(self, *css: str) -> 'HtmlControl':
|
@@ -76,6 +77,7 @@ class HtmlControl(pg_object.Object):
|
|
76
77
|
def to_html(self, **kwargs) -> Html:
|
77
78
|
"""Returns the HTML representation of the control."""
|
78
79
|
self._rendered = True
|
80
|
+
self._dynamic_injected_css = set()
|
79
81
|
html = self._to_html(**kwargs)
|
80
82
|
return html.add_style(*self._css_styles).add_script(*self._scripts)
|
81
83
|
|
@@ -102,7 +104,7 @@ class HtmlControl(pg_object.Object):
|
|
102
104
|
"""Synchronizes displayed values to members."""
|
103
105
|
self.rebind(fields, skip_notification=True, raise_on_no_change=False)
|
104
106
|
|
105
|
-
def _run_javascript(self, code: str) -> None:
|
107
|
+
def _run_javascript(self, code: str, debug: bool = False) -> None:
|
106
108
|
"""Runs the given JavaScript code."""
|
107
109
|
if not self.interactive:
|
108
110
|
raise ValueError(
|
@@ -113,6 +115,8 @@ class HtmlControl(pg_object.Object):
|
|
113
115
|
return
|
114
116
|
|
115
117
|
code = inspect.cleandoc(code)
|
118
|
+
if debug:
|
119
|
+
print('RUN JAVSCRIPT:\n', code)
|
116
120
|
if _notebook is not None:
|
117
121
|
_notebook.display(_notebook.Javascript(code))
|
118
122
|
|
@@ -121,6 +125,40 @@ class HtmlControl(pg_object.Object):
|
|
121
125
|
for tracked in all_tracked:
|
122
126
|
tracked.append(code)
|
123
127
|
|
128
|
+
def _add_css_rules(self, css: str) -> None:
|
129
|
+
if not self._rendered or not css or css in self._dynamic_injected_css:
|
130
|
+
return
|
131
|
+
self._run_javascript(
|
132
|
+
f"""
|
133
|
+
const style = document.createElement('style');
|
134
|
+
style.type = 'text/css';
|
135
|
+
style.textContent = "{Html.escape(css, javascript_str=True)}";
|
136
|
+
document.head.appendChild(style);
|
137
|
+
"""
|
138
|
+
)
|
139
|
+
self._dynamic_injected_css.add(css)
|
140
|
+
|
141
|
+
def _apply_css_rules(self, html: Html) -> None:
|
142
|
+
self._add_css_rules(html.styles.content)
|
143
|
+
|
144
|
+
def _insert_adjacent_html(
|
145
|
+
self,
|
146
|
+
element_selector_js: str,
|
147
|
+
html: Html,
|
148
|
+
var_name: str = 'elem',
|
149
|
+
position: str = 'beforeend'
|
150
|
+
):
|
151
|
+
self._run_javascript(
|
152
|
+
f"""
|
153
|
+
{element_selector_js}
|
154
|
+
{var_name}.insertAdjacentHTML(
|
155
|
+
"{position}",
|
156
|
+
"{Html.escape(html, javascript_str=True).to_str(content_only=True)}"
|
157
|
+
);
|
158
|
+
""",
|
159
|
+
)
|
160
|
+
self._apply_css_rules(html)
|
161
|
+
|
124
162
|
def element_id(self, child: Optional[str] = None) -> Optional[str]:
|
125
163
|
"""Returns the element id of this control or a child."""
|
126
164
|
if self.id is not None:
|
@@ -163,14 +201,13 @@ class HtmlControl(pg_object.Object):
|
|
163
201
|
child: Optional[str] = None,
|
164
202
|
) -> base.Html:
|
165
203
|
"""Updates the inner HTML of the control."""
|
166
|
-
js_html = Html.escape(html, javascript_str=True)
|
167
|
-
assert isinstance(js_html, Html), js_html
|
168
204
|
self._run_javascript(
|
169
205
|
f"""
|
170
206
|
elem = document.getElementById("{self.element_id(child)}");
|
171
|
-
elem.innerHTML = "{
|
207
|
+
elem.innerHTML = "{Html.escape(html, javascript_str=True).to_str(content_only=True)}";
|
172
208
|
"""
|
173
209
|
)
|
210
|
+
self._add_css_rules(html.styles.content)
|
174
211
|
return html
|
175
212
|
|
176
213
|
def _update_style(
|
@@ -96,6 +96,8 @@ class Label(HtmlControl):
|
|
96
96
|
tooltip: Union[str, Html, None] = None,
|
97
97
|
link: Optional[str] = None,
|
98
98
|
styles: Optional[Dict[str, Any]] = None,
|
99
|
+
add_class: Optional[List[str]] = None,
|
100
|
+
remove_class: Optional[List[str]] = None,
|
99
101
|
) -> None:
|
100
102
|
if text is not None:
|
101
103
|
self._sync_members(text=self._update_content(text))
|
@@ -105,7 +107,16 @@ class Label(HtmlControl):
|
|
105
107
|
self._sync_members(link=self._update_property('href', link))
|
106
108
|
if tooltip is not None:
|
107
109
|
self.tooltip.update(content=tooltip)
|
108
|
-
|
110
|
+
if add_class or remove_class:
|
111
|
+
css_classes = list(self.css_classes)
|
112
|
+
for x in add_class or []:
|
113
|
+
self._add_css_class(x)
|
114
|
+
css_classes.append(x)
|
115
|
+
for x in remove_class or []:
|
116
|
+
self._remove_css_class(x)
|
117
|
+
if x in css_classes:
|
118
|
+
css_classes.remove(x)
|
119
|
+
self._sync_members(css_classes=css_classes)
|
109
120
|
|
110
121
|
# Register converter for automatic conversion.
|
111
122
|
pg_typing.register_converter(str, Label, Label)
|
@@ -60,19 +60,26 @@ class LabelTest(TestCase):
|
|
60
60
|
)
|
61
61
|
|
62
62
|
def test_update(self):
|
63
|
-
label = label_lib.Label(
|
63
|
+
label = label_lib.Label(
|
64
|
+
'foo', 'bar', 'http://google.com',
|
65
|
+
interactive=True,
|
66
|
+
css_classes=['foo', 'bar'],
|
67
|
+
)
|
64
68
|
self.assertIn('id="control-', label.to_html_str(content_only=True))
|
65
69
|
with label.track_scripts() as scripts:
|
66
70
|
label.update(
|
67
71
|
'bar',
|
68
72
|
tooltip='baz',
|
69
73
|
link='http://www.yahoo.com',
|
70
|
-
styles=dict(color='red')
|
74
|
+
styles=dict(color='red'),
|
75
|
+
add_class=['baz'],
|
76
|
+
remove_class=['bar'],
|
71
77
|
)
|
72
78
|
self.assertEqual(label.text, 'bar')
|
73
79
|
self.assertEqual(label.tooltip.content, 'baz')
|
74
80
|
self.assertEqual(label.link, 'http://www.yahoo.com')
|
75
81
|
self.assertEqual(label.styles, dict(color='red'))
|
82
|
+
self.assertEqual(label.css_classes, ['foo', 'baz'])
|
76
83
|
self.assertEqual(
|
77
84
|
scripts,
|
78
85
|
[
|
@@ -106,6 +113,18 @@ class LabelTest(TestCase):
|
|
106
113
|
elem.classList.remove("html-content");
|
107
114
|
"""
|
108
115
|
),
|
116
|
+
inspect.cleandoc(
|
117
|
+
f"""
|
118
|
+
elem = document.getElementById("{label.element_id()}");
|
119
|
+
elem.classList.add("baz");
|
120
|
+
"""
|
121
|
+
),
|
122
|
+
inspect.cleandoc(
|
123
|
+
f"""
|
124
|
+
elem = document.getElementById("{label.element_id()}");
|
125
|
+
elem.classList.remove("bar");
|
126
|
+
"""
|
127
|
+
),
|
109
128
|
]
|
110
129
|
)
|
111
130
|
|
@@ -15,7 +15,9 @@
|
|
15
15
|
|
16
16
|
from typing import Annotated, List, Literal, Union
|
17
17
|
|
18
|
+
from pyglove.core.symbolic import flags as pg_flags
|
18
19
|
from pyglove.core.symbolic import object as pg_object
|
20
|
+
|
19
21
|
# pylint: disable=g-importing-member
|
20
22
|
from pyglove.core.views.html.base import Html
|
21
23
|
from pyglove.core.views.html.base import HtmlConvertible
|
@@ -37,6 +39,11 @@ class Tab(pg_object.Object):
|
|
37
39
|
'The content of the tab.'
|
38
40
|
]
|
39
41
|
|
42
|
+
css_classes: Annotated[
|
43
|
+
List[str],
|
44
|
+
'The CSS classes of the tab.'
|
45
|
+
] = []
|
46
|
+
|
40
47
|
|
41
48
|
@pg_object.use_init_args(
|
42
49
|
['tabs', 'selected', 'tab_position', 'id', 'css_classes', 'styles']
|
@@ -61,109 +68,175 @@ class TabControl(HtmlControl):
|
|
61
68
|
|
62
69
|
interactive = True
|
63
70
|
|
71
|
+
def append(self, tab: Tab) -> None:
|
72
|
+
with pg_flags.notify_on_change(False):
|
73
|
+
self.tabs.append(tab)
|
74
|
+
|
75
|
+
self._insert_adjacent_html(
|
76
|
+
f"""
|
77
|
+
const elem = document.getElementById('{self.element_id()}-button-group');
|
78
|
+
""",
|
79
|
+
self._tab_button(tab, len(self.tabs) - 1),
|
80
|
+
position='beforeend',
|
81
|
+
)
|
82
|
+
self._insert_adjacent_html(
|
83
|
+
f"""
|
84
|
+
const elem = document.getElementById('{self.element_id()}-content-group');
|
85
|
+
""",
|
86
|
+
self._tab_content(tab, len(self.tabs) - 1),
|
87
|
+
position='beforeend',
|
88
|
+
)
|
89
|
+
|
90
|
+
def extend(self, tabs: List[Tab]) -> None:
|
91
|
+
for tab in tabs:
|
92
|
+
self.append(tab)
|
93
|
+
|
64
94
|
def _to_html(self, **kwargs):
|
65
95
|
return Html.element(
|
66
|
-
'
|
96
|
+
'table',
|
67
97
|
[
|
98
|
+
'<tr><td>',
|
68
99
|
Html.element(
|
69
100
|
'div',
|
70
|
-
[
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
css_classes=[
|
77
|
-
'tab-button',
|
78
|
-
'selected' if i == self.selected else None
|
79
|
-
],
|
80
|
-
onclick=(
|
81
|
-
f"""openTab(event, '{self.element_id()}', '{self.element_id(str(i))}')"""
|
82
|
-
)
|
83
|
-
) for i, tab in enumerate(self.tabs)
|
84
|
-
],
|
85
|
-
css_classes=['tab-button-group'],
|
101
|
+
[self._tab_button(tab, i) for i, tab in enumerate(self.tabs)],
|
102
|
+
css_classes=[
|
103
|
+
'tab-button-group',
|
104
|
+
self.tab_position
|
105
|
+
] + self.css_classes,
|
106
|
+
id=self.element_id('button-group'),
|
86
107
|
),
|
87
|
-
|
108
|
+
('</td><td>' if self.tab_position == 'left'
|
109
|
+
else '</td></tr><tr><td>'),
|
88
110
|
Html.element(
|
89
111
|
'div',
|
90
|
-
[
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
) for i, tab in enumerate(self.tabs)
|
112
|
+
[self._tab_content(tab, i) for i, tab in enumerate(self.tabs)],
|
113
|
+
css_classes=[
|
114
|
+
'tab-content-group',
|
115
|
+
self.tab_position
|
116
|
+
] + self.css_classes,
|
117
|
+
id=self.element_id('content-group'),
|
118
|
+
),
|
119
|
+
'</td></tr>'
|
99
120
|
],
|
100
|
-
css_classes=['tab-control'
|
101
|
-
id=self.element_id(),
|
121
|
+
css_classes=['tab-control'],
|
102
122
|
styles=self.styles,
|
103
123
|
).add_script(
|
104
124
|
"""
|
105
125
|
function openTab(event, controlId, tabId) {
|
106
|
-
const tabButtons = document.querySelectorAll('#' + controlId + '
|
126
|
+
const tabButtons = document.querySelectorAll('#' + controlId + '-button-group > .tab-button');
|
107
127
|
for (let i = 0; i < tabButtons.length; i++) {
|
108
128
|
tabButtons[i].classList.remove('selected');
|
109
129
|
}
|
110
|
-
const tabContents = document.querySelectorAll('#' + controlId + '> .tab-content');
|
130
|
+
const tabContents = document.querySelectorAll('#' + controlId + '-content-group > .tab-content');
|
111
131
|
for (let i = 0; i < tabContents.length; i++) {
|
112
|
-
tabContents[i].
|
132
|
+
tabContents[i].classList.remove('selected')
|
113
133
|
}
|
114
134
|
const tabButton = event.currentTarget;
|
115
135
|
tabButton.classList.add('selected');
|
116
|
-
document.getElementById(tabId).
|
136
|
+
document.getElementById(tabId).classList.add('selected');
|
117
137
|
}
|
118
138
|
"""
|
119
139
|
).add_style(
|
120
140
|
"""
|
121
|
-
.
|
122
|
-
|
123
|
-
border-
|
141
|
+
.tab-control {
|
142
|
+
border-spacing: 0px;
|
143
|
+
border-collapse: collapse;
|
144
|
+
height: 100%;
|
145
|
+
margin-top: 10px;
|
124
146
|
}
|
125
|
-
.
|
126
|
-
|
127
|
-
|
147
|
+
.tab-control td {
|
148
|
+
padding: 0px;
|
149
|
+
margin: 0px;
|
150
|
+
vertical-align: top;
|
151
|
+
}
|
152
|
+
.top.tab-button-group {
|
153
|
+
border-left: 1px solid #DDD;
|
154
|
+
border-top: 1px solid #DDD;
|
155
|
+
border-right: 1px solid #DDD;
|
156
|
+
border-radius: 5px 5px 0px 0px;
|
157
|
+
padding: 0px 5px 0px 0px;
|
158
|
+
margin-bottom: -2px;
|
128
159
|
}
|
129
160
|
.tab-button {
|
130
|
-
background-color:
|
131
|
-
border:
|
161
|
+
background-color: transparent;
|
162
|
+
border-radius: 5px;
|
163
|
+
border: 0px;
|
164
|
+
font-weight: bold;
|
165
|
+
color: gray;
|
132
166
|
outline: none;
|
133
167
|
cursor: pointer;
|
134
168
|
transition: 0.3s;
|
135
|
-
padding: 10px 15px 10px 15px;
|
136
169
|
}
|
137
|
-
.
|
138
|
-
|
170
|
+
.tab-button:hover {
|
171
|
+
background-color: #fff1dd;
|
139
172
|
}
|
140
|
-
.
|
141
|
-
|
142
|
-
|
143
|
-
border-left-width: 2px;
|
173
|
+
.tab-button.selected {
|
174
|
+
background-color: #f0ecf9;
|
175
|
+
color: black;
|
144
176
|
}
|
145
|
-
.top
|
146
|
-
border-
|
147
|
-
border-
|
148
|
-
|
177
|
+
.top.tab-content-group {
|
178
|
+
border-left: 1px solid #DDD;
|
179
|
+
border-right: 1px solid #DDD;
|
180
|
+
border-bottom: 1px solid #DDD;
|
181
|
+
border-radius: 0px 0px 5px 5px;
|
182
|
+
margin: 0px;
|
183
|
+
padding: 5px;
|
184
|
+
height: 100%;
|
149
185
|
}
|
150
|
-
.
|
151
|
-
|
152
|
-
border-left-color: #B721FF;
|
153
|
-
background: #fff;
|
154
|
-
}
|
155
|
-
.top .tab-button:hover {
|
156
|
-
border-top-color: orange;
|
157
|
-
}
|
158
|
-
.left .tab-button:hover {
|
159
|
-
border-left-color: orange;
|
186
|
+
.top > .tab-button {
|
187
|
+
margin: 5px 0px 5px 5px;
|
160
188
|
}
|
161
189
|
.tab-content {
|
162
190
|
display: none;
|
163
|
-
padding: 10px;
|
164
191
|
}
|
165
|
-
.
|
166
|
-
|
192
|
+
.tab-content.selected {
|
193
|
+
display: block;
|
194
|
+
}
|
195
|
+
.left.tab-button-group {
|
196
|
+
display: inline-flex;
|
197
|
+
flex-direction: column;
|
198
|
+
border: 1px solid #DDD;
|
199
|
+
border-radius: 5px;
|
200
|
+
margin-right: 5px;
|
201
|
+
padding: 0px 0px 5px 0px;
|
202
|
+
}
|
203
|
+
.left.tab-content-group {
|
204
|
+
border: 0px
|
205
|
+
margin: 0px;
|
206
|
+
padding: 0px;
|
207
|
+
height: 100%;
|
208
|
+
}
|
209
|
+
.left > .tab-button {
|
210
|
+
text-align: left;
|
211
|
+
margin: 5px 5px 0px 5px;
|
167
212
|
}
|
168
213
|
"""
|
169
214
|
)
|
215
|
+
|
216
|
+
def _tab_button(self, tab: Tab, i: int) -> Html:
|
217
|
+
return Html.element(
|
218
|
+
'button',
|
219
|
+
[
|
220
|
+
tab.label
|
221
|
+
],
|
222
|
+
css_classes=[
|
223
|
+
'tab-button',
|
224
|
+
'selected' if i == self.selected else None
|
225
|
+
] + tab.css_classes,
|
226
|
+
onclick=(
|
227
|
+
f"""openTab(event, '{self.element_id()}', '{self.element_id(str(i))}')"""
|
228
|
+
)
|
229
|
+
)
|
230
|
+
|
231
|
+
def _tab_content(self, tab: Tab, i: int) -> Html:
|
232
|
+
return Html.element(
|
233
|
+
'div',
|
234
|
+
[
|
235
|
+
tab.content
|
236
|
+
],
|
237
|
+
css_classes=[
|
238
|
+
'tab-content',
|
239
|
+
'selected' if i == self.selected else None
|
240
|
+
] + tab.css_classes,
|
241
|
+
id=self.element_id(str(i))
|
242
|
+
)
|
@@ -30,26 +30,24 @@ class TabControlTest(unittest.TestCase):
|
|
30
30
|
|
31
31
|
def test_basic(self):
|
32
32
|
tab = tab_lib.TabControl([
|
33
|
-
tab_lib.Tab('foo', base.Html('<h1>foo</h1>')),
|
33
|
+
tab_lib.Tab('foo', base.Html('<h1>foo</h1>'), css_classes=['foo']),
|
34
34
|
tab_lib.Tab('bar', base.Html('<h1>bar</h1>')),
|
35
35
|
])
|
36
|
+
elem_id = tab.element_id()
|
36
37
|
self.assert_html_content(
|
37
38
|
tab,
|
38
|
-
(
|
39
|
-
f'<div class="tab-control top" id="{tab.element_id()}">'
|
40
|
-
'<div class="tab-button-group"><button class="tab-button selected" '
|
41
|
-
f'''onclick="openTab(event, '{tab.element_id()}', '''
|
42
|
-
f''''{tab.element_id(str(0))}')">'''
|
43
|
-
'<a class="label">foo</a></button><button class="tab-button" '
|
44
|
-
f'''onclick="openTab(event, '{tab.element_id()}', '''
|
45
|
-
f''''{tab.element_id(str(1))}')">'''
|
46
|
-
'<a class="label">bar</a></button></div>'
|
47
|
-
'<div class="tab-content" style="display:block;" '
|
48
|
-
f'id="{tab.element_id(str(0))}"><h1>foo</h1></div>'
|
49
|
-
'<div class="tab-content" style="display:none;" '
|
50
|
-
f'id="{tab.element_id(str(1))}"><h1>bar</h1></div></div>'
|
51
|
-
)
|
39
|
+
f"""<table class="tab-control"><tr><td><div class="tab-button-group top" id="{elem_id}-button-group"><button class="tab-button selected foo" onclick="openTab(event, '{elem_id}', '{elem_id}-0')"><a class="label">foo</a></button><button class="tab-button" onclick="openTab(event, '{elem_id}', '{elem_id}-1')"><a class="label">bar</a></button></div></td></tr><tr><td><div class="tab-content-group top" id="{elem_id}-content-group"><div class="tab-content selected foo" id="{elem_id}-0"><h1>foo</h1></div><div class="tab-content" id="{elem_id}-1"><h1>bar</h1></div></div></td></tr></table>"""
|
52
40
|
)
|
41
|
+
with tab.track_scripts() as scripts:
|
42
|
+
tab.extend([
|
43
|
+
tab_lib.Tab(
|
44
|
+
'baz',
|
45
|
+
base.Html(
|
46
|
+
'<h1 class="a">baz</h1>').add_style('.a { color: red; }')
|
47
|
+
),
|
48
|
+
tab_lib.Tab('qux', base.Html('<h1>qux</h1>')),
|
49
|
+
])
|
50
|
+
self.assertEqual(len(scripts), 6)
|
53
51
|
|
54
52
|
|
55
53
|
if __name__ == '__main__':
|
@@ -143,18 +143,18 @@ pyglove/core/views/__init__.py,sha256=gll9ZBRYz4p_-LWOdzSR2a6UTWcJ8nR430trrP0yLC
|
|
143
143
|
pyglove/core/views/base.py,sha256=Eq94AM5lryQ1IKuQsTSb7ZzX-lp2nhuOnS4ztMnCPIM,26447
|
144
144
|
pyglove/core/views/base_test.py,sha256=UKbr_1TANOAnP7V5ICGF0UEkunfSaHiJ4nXZXhA0SaU,16642
|
145
145
|
pyglove/core/views/html/__init__.py,sha256=Ff51MK1AKdzLM0kczTqLR3fRlJSJLDaFUdVyCu_7-eY,1085
|
146
|
-
pyglove/core/views/html/base.py,sha256=
|
146
|
+
pyglove/core/views/html/base.py,sha256=S3dn2i9-yaH3wMUJRJFZDx72puhgDySyl1yFckiS6lM,15062
|
147
147
|
pyglove/core/views/html/base_test.py,sha256=5RVPNm4YTamTFu6yXA1p2lJg3JHQBKNNBoL977qBZvE,22782
|
148
148
|
pyglove/core/views/html/tree_view.py,sha256=3Db0aOke-A7Inp-vgqebsDMwJ0WvaznithkwcrfGbhg,52155
|
149
149
|
pyglove/core/views/html/tree_view_test.py,sha256=whUorrw0eiDaZsEzGB2B3EN3wx0vLFuNEe2RBU03GeU,74707
|
150
150
|
pyglove/core/views/html/controls/__init__.py,sha256=61qs5pnJPCTECCGBtkbNfIV3KcCu7cxfVNBEtIg1lMo,1318
|
151
|
-
pyglove/core/views/html/controls/base.py,sha256=
|
152
|
-
pyglove/core/views/html/controls/label.py,sha256=
|
153
|
-
pyglove/core/views/html/controls/label_test.py,sha256=
|
151
|
+
pyglove/core/views/html/controls/base.py,sha256=VV-dDc_myKYlZeiJUXubIJXYKnm1ncEqjlqibN3d4tM,7710
|
152
|
+
pyglove/core/views/html/controls/label.py,sha256=JVLUByEHZ5uL8Mu65Y4UV33JIBo85Z7pE6Zcug6pOts,5644
|
153
|
+
pyglove/core/views/html/controls/label_test.py,sha256=4h6j4tZjAqhazp4AGnW1d_ohaeihofpggJ3UkK02Oho,5126
|
154
154
|
pyglove/core/views/html/controls/progress_bar.py,sha256=kLdY3JQLCOv00ShldnQg3Qs8l1j_pDk148FoKfrZB64,5275
|
155
155
|
pyglove/core/views/html/controls/progress_bar_test.py,sha256=6u1A6kAV8GY_vUMD6PSl7HuuOkVMELYqU32YEVx6qz8,3500
|
156
|
-
pyglove/core/views/html/controls/tab.py,sha256=
|
157
|
-
pyglove/core/views/html/controls/tab_test.py,sha256=
|
156
|
+
pyglove/core/views/html/controls/tab.py,sha256=HpHKprScIPtAgC4WbSk_ComU_TayC8q_aj54zZUc0ik,6858
|
157
|
+
pyglove/core/views/html/controls/tab_test.py,sha256=4tf8kiECcuY6vEcdgJWCY09UAfqMSwA2eJ-b-hxvLJw,2310
|
158
158
|
pyglove/core/views/html/controls/tooltip.py,sha256=01BbpuM1twf3FYMUT09_Ck5JSSONe8QE9RmyA9nhCnU,3092
|
159
159
|
pyglove/core/views/html/controls/tooltip_test.py,sha256=17BY-WmZKpz9tCbySPcwG6KJyfeE_MeMyKxtfxorBQ0,3194
|
160
160
|
pyglove/ext/__init__.py,sha256=3jp8cJvKW6PENOZlmVAbT0w-GBRn_kjhc0wDX3XjpOE,755
|
@@ -196,8 +196,8 @@ pyglove/ext/scalars/randoms.py,sha256=LkMIIx7lOq_lvJvVS3BrgWGuWl7Pi91-lA-O8x_gZs
|
|
196
196
|
pyglove/ext/scalars/randoms_test.py,sha256=nEhiqarg8l_5EOucp59CYrpO2uKxS1pe0hmBdZUzRNM,2000
|
197
197
|
pyglove/ext/scalars/step_wise.py,sha256=IDw3tuTpv0KVh7AN44W43zqm1-E0HWPUlytWOQC9w3Y,3789
|
198
198
|
pyglove/ext/scalars/step_wise_test.py,sha256=TL1vJ19xVx2t5HKuyIzGoogF7N3Rm8YhLE6JF7i0iy8,2540
|
199
|
-
pyglove-0.4.5.
|
200
|
-
pyglove-0.4.5.
|
201
|
-
pyglove-0.4.5.
|
202
|
-
pyglove-0.4.5.
|
203
|
-
pyglove-0.4.5.
|
199
|
+
pyglove-0.4.5.dev202412100720.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
200
|
+
pyglove-0.4.5.dev202412100720.dist-info/METADATA,sha256=WnMZUYj_ZR0S0v7zMWr1n8O14QNXxOZLt1OBNY4zgWs,6666
|
201
|
+
pyglove-0.4.5.dev202412100720.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
202
|
+
pyglove-0.4.5.dev202412100720.dist-info/top_level.txt,sha256=wITzJSKcj8GZUkbq-MvUQnFadkiuAv_qv5qQMw0fIow,8
|
203
|
+
pyglove-0.4.5.dev202412100720.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{pyglove-0.4.5.dev202412080808.dist-info → pyglove-0.4.5.dev202412100720.dist-info}/top_level.txt
RENAMED
File without changes
|