pyglove 0.4.5.dev202412110809__py3-none-any.whl → 0.4.5.dev202412112352__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/controls/label.py +1 -1
- pyglove/core/views/html/controls/label_test.py +6 -6
- pyglove/core/views/html/controls/progress_bar_test.py +2 -2
- pyglove/core/views/html/controls/tab.py +80 -1
- pyglove/core/views/html/controls/tab_test.py +34 -1
- {pyglove-0.4.5.dev202412110809.dist-info → pyglove-0.4.5.dev202412112352.dist-info}/METADATA +1 -1
- {pyglove-0.4.5.dev202412110809.dist-info → pyglove-0.4.5.dev202412112352.dist-info}/RECORD +10 -10
- {pyglove-0.4.5.dev202412110809.dist-info → pyglove-0.4.5.dev202412112352.dist-info}/LICENSE +0 -0
- {pyglove-0.4.5.dev202412110809.dist-info → pyglove-0.4.5.dev202412112352.dist-info}/WHEEL +0 -0
- {pyglove-0.4.5.dev202412110809.dist-info → pyglove-0.4.5.dev202412112352.dist-info}/top_level.txt +0 -0
@@ -34,7 +34,7 @@ class LabelTest(TestCase):
|
|
34
34
|
label = label_lib.Label('foo')
|
35
35
|
self.assertIsNone(label.tooltip)
|
36
36
|
self.assertIsNone(label.link)
|
37
|
-
self.assert_html_content(label, '<
|
37
|
+
self.assert_html_content(label, '<span class="label">foo</span>')
|
38
38
|
with self.assertRaisesRegex(ValueError, 'Non-interactive .*'):
|
39
39
|
label.update('bar')
|
40
40
|
|
@@ -54,7 +54,7 @@ class LabelTest(TestCase):
|
|
54
54
|
self.assert_html_content(
|
55
55
|
label,
|
56
56
|
(
|
57
|
-
'<div class="label-container"><
|
57
|
+
'<div class="label-container"><span class="label">foo</span>'
|
58
58
|
'<span class="tooltip">bar</span></div>'
|
59
59
|
)
|
60
60
|
)
|
@@ -130,7 +130,7 @@ class LabelTest(TestCase):
|
|
130
130
|
|
131
131
|
def test_badge(self):
|
132
132
|
badge = label_lib.Badge('foo')
|
133
|
-
self.assert_html_content(badge, '<
|
133
|
+
self.assert_html_content(badge, '<span class="label badge">foo</span>')
|
134
134
|
|
135
135
|
|
136
136
|
class LabelGroupTest(TestCase):
|
@@ -140,9 +140,9 @@ class LabelGroupTest(TestCase):
|
|
140
140
|
self.assert_html_content(
|
141
141
|
group,
|
142
142
|
(
|
143
|
-
'<div class="label-group"><
|
144
|
-
'<
|
145
|
-
'<
|
143
|
+
'<div class="label-group"><span class="label group-name">baz</span>'
|
144
|
+
'<span class="label group-value">foo</span>'
|
145
|
+
'<span class="label group-value">bar</span></div>'
|
146
146
|
)
|
147
147
|
)
|
148
148
|
|
@@ -42,8 +42,8 @@ class ProgressBarTest(unittest.TestCase):
|
|
42
42
|
f'<div class="sub-progress foo" id="{bar["foo"].element_id()}">'
|
43
43
|
'</div><div class="sub-progress bar" '
|
44
44
|
f'id="{bar["bar"].element_id()}"></div></div>'
|
45
|
-
'<div class="label-container"><
|
46
|
-
f' id="{bar._progress_label.element_id()}">n/a</
|
45
|
+
'<div class="label-container"><span class="label progress-label"'
|
46
|
+
f' id="{bar._progress_label.element_id()}">n/a</span><span class='
|
47
47
|
f'"tooltip" id="{bar._progress_label.tooltip.element_id()}">'
|
48
48
|
'Not started</span></div></div>'
|
49
49
|
)
|
@@ -13,7 +13,7 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
"""Tab control."""
|
15
15
|
|
16
|
-
from typing import Annotated, List, Literal, Union
|
16
|
+
from typing import Annotated, List, Literal, Optional, Union
|
17
17
|
|
18
18
|
from pyglove.core.symbolic import flags as pg_flags
|
19
19
|
from pyglove.core.symbolic import object as pg_object
|
@@ -44,6 +44,11 @@ class Tab(pg_object.Object):
|
|
44
44
|
'The CSS classes of the tab.'
|
45
45
|
] = []
|
46
46
|
|
47
|
+
name: Annotated[
|
48
|
+
Optional[str],
|
49
|
+
'An optional name that can be used to identify a tab under a tab control'
|
50
|
+
] = None
|
51
|
+
|
47
52
|
|
48
53
|
@pg_object.use_init_args(
|
49
54
|
['tabs', 'selected', 'tab_position', 'id', 'css_classes', 'styles']
|
@@ -87,10 +92,84 @@ class TabControl(HtmlControl):
|
|
87
92
|
position='beforeend',
|
88
93
|
)
|
89
94
|
|
95
|
+
def insert(self, index_or_name: Union[int, str], tab: Tab) -> None:
|
96
|
+
"""Inserts a tab before a tab identified by index or name."""
|
97
|
+
index = self.indexof(index_or_name)
|
98
|
+
if index == -1:
|
99
|
+
raise ValueError(f'Tab not found: {index_or_name!r}')
|
100
|
+
with pg_flags.notify_on_change(False):
|
101
|
+
self.tabs.insert(index, tab)
|
102
|
+
|
103
|
+
self._insert_adjacent_html(
|
104
|
+
f"""
|
105
|
+
const elem = document.querySelectorAll('#{self.element_id()}-button-group > .tab-button')[{index}];
|
106
|
+
""",
|
107
|
+
self._tab_button(tab, len(self.tabs) - 1),
|
108
|
+
position='beforebegin',
|
109
|
+
)
|
110
|
+
self._insert_adjacent_html(
|
111
|
+
f"""
|
112
|
+
const elem = document.querySelectorAll('#{self.element_id()}-content-group > .tab-content')[{index}];
|
113
|
+
""",
|
114
|
+
self._tab_content(tab, len(self.tabs) - 1),
|
115
|
+
position='beforebegin',
|
116
|
+
)
|
117
|
+
|
118
|
+
def indexof(self, index_or_name: Union[int, str]) -> int:
|
119
|
+
if isinstance(index_or_name, int):
|
120
|
+
index = index_or_name
|
121
|
+
if index >= len(self.tabs):
|
122
|
+
return len(self.tabs) - 1
|
123
|
+
elif index < -len(self.tabs):
|
124
|
+
return -1
|
125
|
+
elif index < 0:
|
126
|
+
index = index + len(self.tabs)
|
127
|
+
return index
|
128
|
+
else:
|
129
|
+
name = index_or_name
|
130
|
+
assert isinstance(name, str), name
|
131
|
+
for i, tab in enumerate(self.tabs):
|
132
|
+
if tab.name == name:
|
133
|
+
return i
|
134
|
+
return -1
|
135
|
+
|
90
136
|
def extend(self, tabs: List[Tab]) -> None:
|
91
137
|
for tab in tabs:
|
92
138
|
self.append(tab)
|
93
139
|
|
140
|
+
def select(
|
141
|
+
self,
|
142
|
+
index_or_name: Union[int, str, List[str]]) -> Union[int, str]:
|
143
|
+
"""Selects a tab identified by an index or name.
|
144
|
+
|
145
|
+
Args:
|
146
|
+
index_or_name: The index or name of the tab to select. If a list of names
|
147
|
+
is provided, the first name in the list that is found will be selected.
|
148
|
+
|
149
|
+
Returns:
|
150
|
+
The index (if the index was provided) or name of the selected tab.
|
151
|
+
"""
|
152
|
+
selected_name = index_or_name if isinstance(index_or_name, str) else None
|
153
|
+
index = -1
|
154
|
+
if isinstance(index_or_name, list):
|
155
|
+
for name in index_or_name:
|
156
|
+
index = self.indexof(name)
|
157
|
+
if index != -1:
|
158
|
+
selected_name = name
|
159
|
+
break
|
160
|
+
else:
|
161
|
+
index = self.indexof(index_or_name)
|
162
|
+
if index == -1:
|
163
|
+
raise ValueError(f'Tab not found: {index_or_name!r}')
|
164
|
+
self._sync_members(selected=index)
|
165
|
+
self._run_javascript(
|
166
|
+
f"""
|
167
|
+
const tabButtons = document.querySelectorAll('#{self.element_id()}-button-group > .tab-button');
|
168
|
+
tabButtons[{index}].click();
|
169
|
+
"""
|
170
|
+
)
|
171
|
+
return selected_name or index
|
172
|
+
|
94
173
|
def _to_html(self, **kwargs):
|
95
174
|
return Html.element(
|
96
175
|
'table',
|
@@ -36,7 +36,7 @@ class TabControlTest(unittest.TestCase):
|
|
36
36
|
elem_id = tab.element_id()
|
37
37
|
self.assert_html_content(
|
38
38
|
tab,
|
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')"><
|
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')"><span class="label">foo</span></button><button class="tab-button" onclick="openTab(event, '{elem_id}', '{elem_id}-1')"><span class="label">bar</span></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>"""
|
40
40
|
)
|
41
41
|
with tab.track_scripts() as scripts:
|
42
42
|
tab.extend([
|
@@ -48,6 +48,39 @@ class TabControlTest(unittest.TestCase):
|
|
48
48
|
tab_lib.Tab('qux', base.Html('<h1>qux</h1>')),
|
49
49
|
])
|
50
50
|
self.assertEqual(len(scripts), 6)
|
51
|
+
with tab.track_scripts() as scripts:
|
52
|
+
tab.insert(0, tab_lib.Tab('x', 'foo', name='x'))
|
53
|
+
self.assertEqual(len(scripts), 2)
|
54
|
+
self.assertEqual(len(tab.tabs), 5)
|
55
|
+
self.assertEqual(tab.indexof(-1), 4)
|
56
|
+
self.assertEqual(tab.indexof(3), 3)
|
57
|
+
self.assertEqual(tab.indexof(10), 4)
|
58
|
+
self.assertEqual(tab.indexof(-10), -1)
|
59
|
+
self.assertEqual(tab.indexof('x'), 0)
|
60
|
+
self.assertEqual(tab.indexof('y'), -1)
|
61
|
+
self.assertEqual(tab.select(0), 0)
|
62
|
+
self.assertEqual(tab.select('x'), 'x')
|
63
|
+
self.assertEqual(tab.select(['y', 'x']), 'x')
|
64
|
+
|
65
|
+
with self.assertRaisesRegex(ValueError, 'Tab not found'):
|
66
|
+
tab.select('y')
|
67
|
+
with self.assertRaisesRegex(ValueError, 'Tab not found'):
|
68
|
+
tab.insert('y', tab_lib.Tab('z', 'bar'))
|
69
|
+
|
70
|
+
with tab.track_scripts() as scripts:
|
71
|
+
tab.insert('x', tab_lib.Tab('y', 'bar'))
|
72
|
+
self.assertEqual(len(scripts), 2)
|
73
|
+
self.assertEqual(len(tab.tabs), 6)
|
74
|
+
|
75
|
+
with tab.track_scripts() as scripts:
|
76
|
+
tab.select(3)
|
77
|
+
self.assertEqual(len(scripts), 1)
|
78
|
+
self.assertEqual(tab.selected, 3)
|
79
|
+
|
80
|
+
with tab.track_scripts() as scripts:
|
81
|
+
tab.select('x')
|
82
|
+
self.assertEqual(len(scripts), 1)
|
83
|
+
self.assertEqual(tab.selected, 1)
|
51
84
|
|
52
85
|
|
53
86
|
if __name__ == '__main__':
|
@@ -149,12 +149,12 @@ pyglove/core/views/html/tree_view.py,sha256=3Db0aOke-A7Inp-vgqebsDMwJ0Wvaznithkw
|
|
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
151
|
pyglove/core/views/html/controls/base.py,sha256=VV-dDc_myKYlZeiJUXubIJXYKnm1ncEqjlqibN3d4tM,7710
|
152
|
-
pyglove/core/views/html/controls/label.py,sha256=
|
153
|
-
pyglove/core/views/html/controls/label_test.py,sha256=
|
152
|
+
pyglove/core/views/html/controls/label.py,sha256=dXcYId7ASuNqkzKsWMjJ0iQtecoSsUlUgynNNQZOFAM,5681
|
153
|
+
pyglove/core/views/html/controls/label_test.py,sha256=uUYqBSZ0XLOuv4qG20gmoZzA3RxYxpfqT63K0azHEfU,5162
|
154
154
|
pyglove/core/views/html/controls/progress_bar.py,sha256=kLdY3JQLCOv00ShldnQg3Qs8l1j_pDk148FoKfrZB64,5275
|
155
|
-
pyglove/core/views/html/controls/progress_bar_test.py,sha256=
|
156
|
-
pyglove/core/views/html/controls/tab.py,sha256=
|
157
|
-
pyglove/core/views/html/controls/tab_test.py,sha256=
|
155
|
+
pyglove/core/views/html/controls/progress_bar_test.py,sha256=kKOJDZQtBPkmNcgIBrRQkNNzcTm51ojuFBTRUEDSsp0,3506
|
156
|
+
pyglove/core/views/html/controls/tab.py,sha256=ELyroRb3qKQ8ULM_BMq2j-tqV_mnHOvrYv2kbuIe65o,9430
|
157
|
+
pyglove/core/views/html/controls/tab_test.py,sha256=wr1msQjZHxp1TFKQ5LxtppY2Dys736JCmmEJ8WBC3Fo,3531
|
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.dev202412112352.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
200
|
+
pyglove-0.4.5.dev202412112352.dist-info/METADATA,sha256=FbCvpxkWCk8XZHVO3_4YFvwei61xS1PotsLu9bqyZq0,6666
|
201
|
+
pyglove-0.4.5.dev202412112352.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
202
|
+
pyglove-0.4.5.dev202412112352.dist-info/top_level.txt,sha256=wITzJSKcj8GZUkbq-MvUQnFadkiuAv_qv5qQMw0fIow,8
|
203
|
+
pyglove-0.4.5.dev202412112352.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{pyglove-0.4.5.dev202412110809.dist-info → pyglove-0.4.5.dev202412112352.dist-info}/top_level.txt
RENAMED
File without changes
|