staticdash 2025.16__py3-none-any.whl → 2025.17__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.
@@ -85,6 +85,25 @@ document.addEventListener("DOMContentLoaded", () => {
85
85
  return link ? link.getAttribute('href') : null;
86
86
  }
87
87
 
88
+ function saveSidebarState() {
89
+ const openGroups = Array.from(document.querySelectorAll('.sidebar-group.open'))
90
+ .map(getGroupSlug)
91
+ .filter(Boolean);
92
+ localStorage.setItem("sidebar-open-groups", JSON.stringify(openGroups));
93
+ }
94
+
95
+ function restoreSidebarState() {
96
+ const openGroups = JSON.parse(localStorage.getItem("sidebar-open-groups") || "[]");
97
+ document.querySelectorAll('.sidebar-group').forEach(group => {
98
+ const slug = getGroupSlug(group);
99
+ if (slug && openGroups.includes(slug)) {
100
+ group.classList.add('open');
101
+ } else {
102
+ group.classList.remove('open');
103
+ }
104
+ });
105
+ }
106
+
88
107
  // Restore open groups from localStorage
89
108
  const openGroups = JSON.parse(localStorage.getItem("sidebar-open-groups") || "[]");
90
109
  document.querySelectorAll('.sidebar-group').forEach(group => {
@@ -102,13 +121,7 @@ document.addEventListener("DOMContentLoaded", () => {
102
121
  const group = parent.closest('.sidebar-group');
103
122
  if (group) {
104
123
  group.classList.toggle('open');
105
- // Save open groups to localStorage
106
- const allGroups = Array.from(document.querySelectorAll('.sidebar-group'));
107
- const open = allGroups
108
- .filter(g => g.classList.contains('open'))
109
- .map(getGroupSlug)
110
- .filter(Boolean);
111
- localStorage.setItem("sidebar-open-groups", JSON.stringify(open));
124
+ saveSidebarState();
112
125
  }
113
126
  }
114
127
  });
@@ -131,4 +144,56 @@ document.addEventListener("DOMContentLoaded", () => {
131
144
  setTimeout(() => {
132
145
  document.body.classList.add("sidebar-animate");
133
146
  }, 0);
134
- });
147
+
148
+ // --- Sidebar collapse/expand memory ---
149
+ function saveSidebarState() {
150
+ const expanded = [];
151
+ document.querySelectorAll('.sidebar-group .sidebar-children').forEach(el => {
152
+ if (el.classList.contains('expanded')) {
153
+ // Use parent page slug as key
154
+ const parent = el.parentElement.querySelector('.sidebar-parent, .nav-link');
155
+ if (parent && parent.getAttribute('href')) {
156
+ expanded.push(parent.getAttribute('href'));
157
+ }
158
+ }
159
+ });
160
+ localStorage.setItem('sidebarExpanded', JSON.stringify(expanded));
161
+ }
162
+
163
+ function restoreSidebarState() {
164
+ const expanded = JSON.parse(localStorage.getItem('sidebarExpanded') || '[]');
165
+ document.querySelectorAll('.sidebar-group').forEach(group => {
166
+ const parent = group.querySelector('.sidebar-parent, .nav-link');
167
+ const children = group.querySelector('.sidebar-children');
168
+ if (parent && children) {
169
+ if (expanded.includes(parent.getAttribute('href'))) {
170
+ children.classList.add('expanded');
171
+ } else {
172
+ children.classList.remove('expanded');
173
+ }
174
+ }
175
+ });
176
+ }
177
+
178
+ restoreSidebarState();
179
+
180
+ document.querySelectorAll('.sidebar-group .sidebar-parent, .sidebar-group .nav-link').forEach(parent => {
181
+ parent.addEventListener('click', function(e) {
182
+ // Only toggle if arrow or parent link is clicked
183
+ if (e.target.classList.contains('sidebar-arrow') || e.currentTarget === e.target) {
184
+ const group = parent.closest('.sidebar-group');
185
+ const children = group.querySelector('.sidebar-children');
186
+ if (children) {
187
+ children.classList.toggle('expanded');
188
+ saveSidebarState();
189
+ }
190
+ }
191
+ });
192
+ });
193
+ });
194
+
195
+ /* CSS */
196
+ /* Add this CSS to handle the rotation of the arrow icon */
197
+ body.sidebar-animate .sidebar-group.open .sidebar-arrow {
198
+ transform: rotate(90deg);
199
+ }
staticdash/dashboard.py CHANGED
@@ -398,12 +398,19 @@ class Dashboard:
398
398
  story.append(PageBreak())
399
399
 
400
400
  if include_title_page:
401
- story.append(Paragraph(self.title, styles['Heading1']))
401
+ story.append(Spacer(1, 120))
402
+ # Title, centered and bold
403
+ story.append(Paragraph(f"<b>{self.title}</b>", styles['Title']))
404
+ story.append(Spacer(1, 48))
405
+ # Centered info block (no labels)
406
+ info_lines = []
402
407
  if author:
403
- story.append(Paragraph(f"Author: {author}", normal_style))
408
+ info_lines.append(str(author))
404
409
  if affiliation:
405
- story.append(Paragraph(f"Affiliation: {affiliation}", normal_style))
406
- story.append(Paragraph(f"Date: {pd.Timestamp.now().strftime('%B %d, %Y')}", normal_style))
410
+ info_lines.append(str(affiliation))
411
+ info_lines.append(pd.Timestamp.now().strftime('%B %d, %Y'))
412
+ info_html = "<br/>".join(info_lines)
413
+ story.append(Paragraph(f'<para align="center">{info_html}</para>', styles['Normal']))
407
414
  story.append(PageBreak())
408
415
 
409
416
  for page in self.pages:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: staticdash
3
- Version: 2025.16
3
+ Version: 2025.17
4
4
  Summary: A lightweight static HTML dashboard generator with Plotly and pandas support.
5
5
  Author-email: Brian Day <brian.day1@gmail.com>
6
6
  License: CC0-1.0
@@ -0,0 +1,8 @@
1
+ staticdash/__init__.py,sha256=UN_-h8wFGfTPHYjnEb7N9CsxqXo-DQVo0cmREOtvRXE,244
2
+ staticdash/dashboard.py,sha256=jMUKft0qxqUcO7tg3WpzfRCtyUhROIXG7DHkuP4XbSk,21653
3
+ staticdash/assets/css/style.css,sha256=RVqNdwBsaDv8izdOQjGmUZ4NROWF8uZhiq8DTNvUB1M,5962
4
+ staticdash/assets/js/script.js,sha256=7xBRlz_19wybbNVwAcfuKNXtDEojGB4EB0Yj4klsoTA,6998
5
+ staticdash-2025.17.dist-info/METADATA,sha256=sZnMrJks-Q5mmJjsp-ZP-kMnI2UbpfE5SIr8WpI7FBM,1934
6
+ staticdash-2025.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
+ staticdash-2025.17.dist-info/top_level.txt,sha256=3MzZU6SptkUkjcHV1cvPji0H4aRzPphLHnpStgGEcxM,11
8
+ staticdash-2025.17.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- staticdash/__init__.py,sha256=UN_-h8wFGfTPHYjnEb7N9CsxqXo-DQVo0cmREOtvRXE,244
2
- staticdash/dashboard.py,sha256=798Itq6FgsU3OY4sq7PQIttLdkX0Au2ls0iyp5Pkxtc,21395
3
- staticdash/assets/css/style.css,sha256=RVqNdwBsaDv8izdOQjGmUZ4NROWF8uZhiq8DTNvUB1M,5962
4
- staticdash/assets/js/script.js,sha256=vBFL98da30_zHUKVqhLDBL2HzrI9huSHsea-e8A2qUk,4818
5
- staticdash-2025.16.dist-info/METADATA,sha256=Nwms4u35b4I231PGM0KFL2MUQwUeUlZAb3xA1yEyTJE,1934
6
- staticdash-2025.16.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
- staticdash-2025.16.dist-info/top_level.txt,sha256=3MzZU6SptkUkjcHV1cvPji0H4aRzPphLHnpStgGEcxM,11
8
- staticdash-2025.16.dist-info/RECORD,,