@docmd/ui 0.4.6 → 0.4.8

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.
@@ -12,277 +12,294 @@
12
12
  * --------------------------------------------------------------------
13
13
  */
14
14
 
15
- /*
16
- * Main client-side script for docmd UI interactions
17
- */
18
-
19
- // --- Collapsible Navigation Logic ---
20
- function initializeCollapsibleNav() {
21
- const nav = document.querySelector('.sidebar-nav');
22
- if (!nav) return;
23
-
24
- // 1. Initial Cleanup (ensure classes match aria states)
25
- nav.querySelectorAll('li.collapsible').forEach(item => {
26
- // If server rendered it as expanded, ensure aria matches
27
- if (item.classList.contains('expanded')) {
28
- item.setAttribute('aria-expanded', 'true');
29
- } else {
30
- item.setAttribute('aria-expanded', 'false');
31
- }
32
- });
33
-
34
- // 2. Event Delegation
35
- nav.addEventListener('click', (e) => {
36
- // Check if the click target is the arrow or inside the arrow wrapper
37
- const arrow = e.target.closest('.collapse-icon-wrapper');
38
-
39
- if (arrow) {
40
- // STOP everything. Do not follow the link.
41
- e.preventDefault();
42
- e.stopPropagation();
43
-
44
- const item = arrow.closest('li.collapsible');
15
+ (function() {
16
+ // =========================================================================
17
+ // 1. EVENT DELEGATION
18
+ // =========================================================================
19
+ document.addEventListener('click', (e) => {
20
+ // Collapsible Navigation
21
+ const navLabel = e.target.closest('.nav-label, .collapse-icon-wrapper');
22
+ if (navLabel) {
23
+ const item = navLabel.closest('li.collapsible');
45
24
  if (item) {
46
- // Toggle State
25
+ e.preventDefault();
47
26
  const isExpanded = item.classList.contains('expanded');
48
-
49
- if (isExpanded) {
50
- item.classList.remove('expanded');
51
- item.setAttribute('aria-expanded', 'false');
52
- } else {
53
- item.classList.add('expanded');
54
- item.setAttribute('aria-expanded', 'true');
55
- }
27
+ item.classList.toggle('expanded', !isExpanded);
28
+ item.setAttribute('aria-expanded', !isExpanded);
56
29
  }
57
- return false;
30
+ if (navLabel.classList.contains('collapse-icon-wrapper')) return;
58
31
  }
59
- });
60
- }
61
-
62
- // --- Mobile Menu Logic ---
63
- function initializeMobileMenus() {
64
- const sidebarBtn = document.querySelector('.sidebar-menu-button');
65
- const sidebar = document.querySelector('.sidebar');
66
-
67
- if (sidebarBtn && sidebar) {
68
- sidebarBtn.addEventListener('click', (e) => {
69
- e.stopPropagation();
70
- sidebar.classList.toggle('mobile-expanded');
71
- });
72
- }
73
-
74
- const tocBtn = document.querySelector('.toc-menu-button');
75
- const tocContainer = document.querySelector('.toc-container');
76
- const tocTitle = document.querySelector('.toc-title');
77
-
78
- const toggleToc = (e) => {
79
- if (window.getComputedStyle(tocBtn).display === 'none') return;
80
- e.stopPropagation();
81
- tocContainer.classList.toggle('mobile-expanded');
82
- };
83
-
84
- if (tocBtn && tocContainer) {
85
- tocBtn.addEventListener('click', toggleToc);
86
- if (tocTitle) tocTitle.addEventListener('click', toggleToc);
87
- }
88
- }
89
-
90
- // --- Sidebar Scroll Preservation (Instant Center) ---
91
- function initializeSidebarScroll() {
92
- const sidebar = document.querySelector('.sidebar');
93
- if (!sidebar) return;
94
-
95
- // Wait for the layout to be stable
96
- requestAnimationFrame(() => {
97
- // Find the active link
98
- const activeElement = sidebar.querySelector('a.active');
99
32
 
100
- if (activeElement) {
101
- activeElement.scrollIntoView({
102
- behavior: 'auto', // INSTANT jump (prevents scrolling animation jitter)
103
- block: 'center', // Center it vertically in the sidebar
104
- inline: 'nearest'
105
- });
33
+ // Toggles
34
+ if (e.target.closest('.toc-menu-button, .toc-title')) {
35
+ document.querySelector('.toc-container')?.classList.toggle('mobile-expanded');
36
+ }
37
+ if (e.target.closest('.sidebar-menu-button')) {
38
+ document.querySelector('.sidebar')?.classList.toggle('mobile-expanded');
39
+ }
40
+ if (e.target.closest('#sidebar-toggle-button')) {
41
+ document.body.classList.toggle('sidebar-collapsed');
42
+ localStorage.setItem('docmd-sidebar-collapsed', document.body.classList.contains('sidebar-collapsed'));
106
43
  }
107
- });
108
- }
109
-
110
- // --- Theme Toggle Logic ---
111
- function setupThemeToggleListener() {
112
- const toggleButtons = document.querySelectorAll('.theme-toggle-button');
113
-
114
- function applyTheme(theme) {
115
- const validThemes = ['light', 'dark'];
116
- const selectedTheme = validThemes.includes(theme) ? theme : 'light';
117
-
118
- // 1. Update DOM & Storage
119
- document.documentElement.setAttribute('data-theme', selectedTheme);
120
- document.body.setAttribute('data-theme', selectedTheme);
121
- localStorage.setItem('docmd-theme', selectedTheme);
122
44
 
123
- // 2. Toggle Highlight.js Stylesheets
124
- const lightLink = document.getElementById('hljs-light');
125
- const darkLink = document.getElementById('hljs-dark');
45
+ // Tabs System
46
+ const tabItem = e.target.closest('.docmd-tabs-nav-item');
47
+ if (tabItem) {
48
+ const tabsContainer = tabItem.closest('.docmd-tabs');
49
+ const navItems = Array.from(tabsContainer.querySelectorAll('.docmd-tabs-nav-item'));
50
+ const tabPanes = Array.from(tabsContainer.querySelectorAll('.docmd-tab-pane'));
51
+ const index = navItems.indexOf(tabItem);
52
+
53
+ navItems.forEach(item => item.classList.remove('active'));
54
+ tabPanes.forEach(pane => pane.classList.remove('active'));
55
+
56
+ tabItem.classList.add('active');
57
+ if (tabPanes[index]) tabPanes[index].classList.add('active');
58
+ }
126
59
 
127
- if (lightLink && darkLink) {
128
- if (selectedTheme === 'dark') {
129
- lightLink.disabled = true;
130
- darkLink.disabled = false;
131
- } else {
132
- lightLink.disabled = false;
133
- darkLink.disabled = true;
134
- }
60
+ // Copy Code Button
61
+ const copyBtn = e.target.closest('.copy-code-button');
62
+ if (copyBtn) {
63
+ const code = copyBtn.closest('.code-wrapper')?.querySelector('code');
64
+ if (code) {
65
+ navigator.clipboard.writeText(code.innerText).then(() => {
66
+ copyBtn.classList.add('copied');
67
+ copyBtn.innerHTML = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check"><polyline points="20 6 9 17 4 12"></polyline></svg>`;
68
+ setTimeout(() => {
69
+ copyBtn.classList.remove('copied');
70
+ copyBtn.innerHTML = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-copy"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path></svg>`;
71
+ }, 2000);
72
+ });
73
+ }
135
74
  }
136
- }
75
+ });
137
76
 
138
- toggleButtons.forEach(btn => {
139
- // Clone button to remove old listeners if any (safety measure)
140
- const newBtn = btn.cloneNode(true);
141
- btn.parentNode.replaceChild(newBtn, btn);
77
+ // =========================================================================
78
+ // 2. COMPONENT INITIALIZERS
79
+ // =========================================================================
80
+ function injectCopyButtons() {
81
+ if (document.body.dataset.copyCodeEnabled !== 'true') return;
82
+ const svg = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-copy"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path></svg>`;
142
83
 
143
- newBtn.addEventListener('click', () => {
144
- const currentTheme = document.documentElement.getAttribute('data-theme') || 'light';
145
- const newTheme = currentTheme === 'light' ? 'dark' : 'light';
146
- applyTheme(newTheme);
84
+ document.querySelectorAll('pre').forEach(preElement => {
85
+ if (preElement.closest('.code-wrapper')) return;
86
+ const wrapper = document.createElement('div');
87
+ wrapper.className = 'code-wrapper';
88
+ wrapper.style.position = 'relative';
89
+ preElement.parentNode.insertBefore(wrapper, preElement);
90
+ wrapper.appendChild(preElement);
91
+
92
+ const copyButton = document.createElement('button');
93
+ copyButton.className = 'copy-code-button';
94
+ copyButton.innerHTML = svg;
95
+ wrapper.appendChild(copyButton);
147
96
  });
148
- });
149
- }
150
-
151
- // --- Sidebar Collapse Logic ---
152
- function initializeSidebarToggle() {
153
- const toggleButton = document.getElementById('sidebar-toggle-button');
154
- const body = document.body;
97
+ }
155
98
 
156
- if (!body.classList.contains('sidebar-collapsible') || !toggleButton) return;
99
+ let scrollObserver = null;
100
+ function initializeScrollSpy() {
101
+ if (scrollObserver) scrollObserver.disconnect();
102
+ const tocLinks = document.querySelectorAll('.toc-link');
103
+ const headings = document.querySelectorAll('.main-content h2, .main-content h3, .main-content h4');
104
+ const tocContainer = document.querySelector('.toc-list');
105
+
106
+ if (tocLinks.length === 0 || headings.length === 0) return;
107
+
108
+ scrollObserver = new IntersectionObserver((entries) => {
109
+ entries.forEach(entry => {
110
+ if (entry.isIntersecting) {
111
+ tocLinks.forEach(link => link.classList.remove('active'));
112
+ const id = entry.target.getAttribute('id');
113
+ const activeLink = document.querySelector(`.toc-link[href="#${id}"]`);
114
+
115
+ if (activeLink) {
116
+ activeLink.classList.add('active');
117
+ if (tocContainer) {
118
+ const linkRect = activeLink.getBoundingClientRect();
119
+ const containerRect = tocContainer.getBoundingClientRect();
120
+ if (linkRect.bottom > containerRect.bottom || linkRect.top < containerRect.top) {
121
+ tocContainer.scrollTo({ top: activeLink.offsetTop - (containerRect.height / 2) + (linkRect.height / 2), behavior: 'smooth' });
122
+ }
123
+ }
124
+ }
125
+ }
126
+ });
127
+ }, { rootMargin: '-15% 0px -80% 0px', threshold: 0 });
157
128
 
158
- const defaultConfigCollapsed = body.dataset.defaultCollapsed === 'true';
159
- let isCollapsed = localStorage.getItem('docmd-sidebar-collapsed');
129
+ headings.forEach(h => scrollObserver.observe(h));
130
+ }
160
131
 
161
- if (isCollapsed === null) isCollapsed = defaultConfigCollapsed;
162
- else isCollapsed = isCollapsed === 'true';
132
+ function executeScripts(container) {
133
+ container.querySelectorAll('script').forEach(oldScript => {
134
+ const newScript = document.createElement('script');
135
+ Array.from(oldScript.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value));
136
+ newScript.text = oldScript.innerHTML;
137
+ oldScript.parentNode.replaceChild(newScript, oldScript);
138
+ });
139
+ }
163
140
 
164
- if (isCollapsed) body.classList.add('sidebar-collapsed');
141
+ // =========================================================================
142
+ // 3. TARGETED SPA ROUTER
143
+ // =========================================================================
144
+ function initializeSPA() {
145
+ if (location.protocol === 'file:') return;
146
+ if (document.body.dataset.spaEnabled !== 'true') return;
165
147
 
166
- toggleButton.addEventListener('click', () => {
167
- body.classList.toggle('sidebar-collapsed');
168
- const currentlyCollapsed = body.classList.contains('sidebar-collapsed');
169
- localStorage.setItem('docmd-sidebar-collapsed', currentlyCollapsed);
170
- });
171
- }
148
+ let currentPath = window.location.pathname;
172
149
 
173
- // --- Tabs Container Logic ---
174
- function initializeTabs() {
175
- document.querySelectorAll('.docmd-tabs').forEach(tabsContainer => {
176
- const navItems = tabsContainer.querySelectorAll('.docmd-tabs-nav-item');
177
- const tabPanes = tabsContainer.querySelectorAll('.docmd-tab-pane');
150
+ document.addEventListener('click', async (e) => {
178
151
 
179
- navItems.forEach((navItem, index) => {
180
- navItem.addEventListener('click', () => {
181
- navItems.forEach(item => item.classList.remove('active'));
182
- tabPanes.forEach(pane => pane.classList.remove('active'));
152
+ if (e.target.closest('.collapse-icon-wrapper')) return;
183
153
 
184
- navItem.classList.add('active');
185
- if (tabPanes[index]) tabPanes[index].classList.add('active');
186
- });
154
+ const link = e.target.closest('.sidebar-nav a, .page-navigation a');
155
+ if (!link || link.target === '_blank' || link.hasAttribute('download')) return;
156
+
157
+ const url = new URL(link.href);
158
+ if (url.origin !== location.origin) return;
159
+ if (url.pathname === window.location.pathname && url.hash) return;
160
+
161
+ e.preventDefault();
162
+ await navigateTo(url.href);
187
163
  });
188
- });
189
- }
190
-
191
- // --- Copy Code Button Logic ---
192
- function initializeCopyCodeButtons() {
193
- if (document.body.dataset.copyCodeEnabled !== 'true') return;
194
-
195
- const copyIconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-copy"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path></svg>`;
196
- const checkIconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check"><polyline points="20 6 9 17 4 12"></polyline></svg>`;
197
164
 
198
- document.querySelectorAll('pre').forEach(preElement => {
199
- const codeElement = preElement.querySelector('code');
200
- if (!codeElement) return;
201
-
202
- const wrapper = document.createElement('div');
203
- wrapper.style.position = 'relative';
204
- wrapper.style.display = 'block';
165
+ // Handle Back/Forward browser buttons & TOC Hash clicks
166
+ window.addEventListener('popstate', () => {
167
+ // If the path is identical, it means ONLY the #hash changed. Do not reload!
168
+ if (window.location.pathname === currentPath) return;
169
+
170
+ navigateTo(window.location.href, false);
171
+ });
205
172
 
206
- preElement.parentNode.insertBefore(wrapper, preElement);
207
- wrapper.appendChild(preElement);
208
- preElement.style.position = 'static';
173
+ async function navigateTo(url, pushHistory = true) {
174
+ const mainContentWrapper = document.querySelector('.main-content-wrapper');
175
+
176
+ try {
177
+ if (mainContentWrapper) mainContentWrapper.style.opacity = '0.5';
178
+
179
+ const res = await fetch(url);
180
+ if (!res.ok) throw new Error('Fetch failed');
181
+ const finalUrl = res.url;
182
+ const html = await res.text();
183
+ const parser = new DOMParser();
184
+ const doc = parser.parseFromString(html, 'text/html');
185
+
186
+ // 1. UPDATE URL FIRST
187
+ if (pushHistory) history.pushState({}, '', finalUrl);
188
+ currentPath = new URL(finalUrl).pathname;
189
+ document.title = doc.title;
190
+
191
+ // 2. SAFELY SYNC HEAD ASSETS (Favicon & CSS)
192
+ const assetSelectors = 'link[rel="stylesheet"], link[rel="icon"], link[rel="shortcut icon"]';
193
+ const oldAssets = Array.from(document.head.querySelectorAll(assetSelectors));
194
+ const newAssets = Array.from(doc.head.querySelectorAll(assetSelectors));
195
+
196
+ newAssets.forEach((newAsset, index) => {
197
+ if (oldAssets[index]) {
198
+ // Only update if the relative path actually changed
199
+ if (oldAssets[index].getAttribute('href') !== newAsset.getAttribute('href')) {
200
+ oldAssets[index].setAttribute('href', newAsset.getAttribute('href'));
201
+ }
202
+ } else {
203
+ document.head.appendChild(newAsset.cloneNode(true));
204
+ }
205
+ });
206
+
207
+ // 3. MEMORIZE SIDEBAR STATE
208
+ const openMenus = new Set();
209
+ document.querySelectorAll('.sidebar-nav li.collapsible.expanded > .nav-label .nav-item-title, .sidebar-nav li.collapsible.expanded > a .nav-item-title').forEach(el => {
210
+ openMenus.add(el.textContent.trim());
211
+ });
212
+
213
+ // 4. SWAP BODY COMPONENTS
214
+ const selectorsToSwap =[
215
+ '.main-content', '.toc-sidebar', '.sidebar-nav',
216
+ '.page-header .header-title', '.page-footer', '.footer-complete',
217
+ '.page-footer-actions'
218
+ ];
219
+
220
+ selectorsToSwap.forEach(selector => {
221
+ const oldEl = document.querySelector(selector);
222
+ const newEl = doc.querySelector(selector);
223
+ if (oldEl && newEl) oldEl.innerHTML = newEl.innerHTML;
224
+ });
225
+
226
+ // 5. RESTORE SIDEBAR STATE
227
+ document.querySelectorAll('.sidebar-nav li.collapsible').forEach(li => {
228
+ const title = li.querySelector('.nav-item-title')?.textContent.trim();
229
+ if (openMenus.has(title)) {
230
+ li.classList.add('expanded');
231
+ li.setAttribute('aria-expanded', 'true');
232
+ }
233
+ });
234
+
235
+ // 6. SCROLL & RE-INIT
236
+ const hash = new URL(finalUrl).hash;
237
+ if (hash) {
238
+ document.querySelector(hash)?.scrollIntoView();
239
+ } else {
240
+ if (mainContentWrapper) mainContentWrapper.scrollTo(0, 0);
241
+ window.scrollTo(0, 0);
242
+ }
209
243
 
210
- const copyButton = document.createElement('button');
211
- copyButton.className = 'copy-code-button';
212
- copyButton.innerHTML = copyIconSvg;
213
- copyButton.setAttribute('aria-label', 'Copy code to clipboard');
214
- wrapper.appendChild(copyButton);
244
+ if (mainContentWrapper) mainContentWrapper.style.opacity = '1';
245
+ injectCopyButtons();
246
+ initializeScrollSpy();
247
+
248
+ const newMainContent = document.querySelector('.main-content');
249
+ if (newMainContent) executeScripts(newMainContent);
215
250
 
216
- copyButton.addEventListener('click', () => {
217
- navigator.clipboard.writeText(codeElement.innerText).then(() => {
218
- copyButton.innerHTML = checkIconSvg;
219
- copyButton.classList.add('copied');
220
- setTimeout(() => {
221
- copyButton.innerHTML = copyIconSvg;
222
- copyButton.classList.remove('copied');
223
- }, 2000);
224
- }).catch(err => {
225
- console.error('Failed to copy text: ', err);
226
- copyButton.innerText = 'Error';
227
- });
228
- });
229
- });
230
- }
251
+ document.dispatchEvent(new CustomEvent('docmd:page-mounted', { detail: { url: finalUrl } }));
231
252
 
232
- // --- Theme Sync Function ---
233
- function syncBodyTheme() {
234
- const currentTheme = document.documentElement.getAttribute('data-theme');
235
- if (currentTheme && document.body) {
236
- document.body.setAttribute('data-theme', currentTheme);
253
+ } catch(e) {
254
+ window.location.assign(url);
255
+ }
256
+ }
237
257
  }
238
- }
239
-
240
- // --- Scroll Spy Logic ---
241
- function initializeScrollSpy() {
242
- const tocLinks = document.querySelectorAll('.toc-link');
243
- const headings = document.querySelectorAll('.main-content h2, .main-content h3');
244
-
245
- if (tocLinks.length === 0 || headings.length === 0) return;
246
-
247
- const observerOptions = {
248
- root: null,
249
- // Trigger when heading crosses the top 10% of screen
250
- rootMargin: '-10% 0px -80% 0px',
251
- threshold: 0
252
- };
253
258
 
254
- const observer = new IntersectionObserver((entries) => {
255
- entries.forEach(entry => {
256
- if (entry.isIntersecting) {
257
- // 1. Clear current active state
258
- tocLinks.forEach(link => link.classList.remove('active'));
259
-
260
- // 2. Find link corresponding to this heading
261
- const id = entry.target.getAttribute('id');
262
- const activeLink = document.querySelector(`.toc-link[href="#${id}"]`);
259
+ // =========================================================================
260
+ // 4. BOOTSTRAP
261
+ // =========================================================================
262
+ document.addEventListener('DOMContentLoaded', () => {
263
+ if (localStorage.getItem('docmd-sidebar-collapsed') === 'true') {
264
+ document.body.classList.add('sidebar-collapsed');
265
+ }
266
+
267
+ document.querySelectorAll('.theme-toggle-button').forEach(btn => {
268
+ btn.addEventListener('click', () => {
269
+ const t = document.documentElement.getAttribute('data-theme') === 'light' ? 'dark' : 'light';
270
+ document.documentElement.setAttribute('data-theme', t);
271
+ document.body.setAttribute('data-theme', t);
272
+ localStorage.setItem('docmd-theme', t);
263
273
 
264
- if (activeLink) {
265
- activeLink.classList.add('active');
266
-
267
- // Optional: Auto-scroll the TOC sidebar itself if needed
268
- // activeLink.scrollIntoView({ block: 'nearest' });
274
+ // Highlight.js CSS swap
275
+ const lightLink = document.getElementById('hljs-light');
276
+ const darkLink = document.getElementById('hljs-dark');
277
+ if (lightLink && darkLink) {
278
+ lightLink.disabled = t === 'dark';
279
+ darkLink.disabled = t === 'light';
269
280
  }
270
- }
281
+ });
271
282
  });
272
- }, observerOptions);
273
283
 
274
- headings.forEach(heading => observer.observe(heading));
275
- }
284
+ injectCopyButtons();
285
+ initializeScrollSpy();
286
+ initializeSPA();
287
+
288
+ // Auto-scroll sidebar safely
289
+ setTimeout(() => {
290
+ const activeNav = document.querySelector('.sidebar-nav a.active');
291
+ const sidebarNav = document.querySelector('.sidebar-nav');
292
+ if (activeNav && sidebarNav) {
293
+ // Calculate scroll top safely instead of scrollIntoView which causes page jump
294
+ sidebarNav.scrollTo({ top: activeNav.offsetTop - (sidebarNav.clientHeight / 2), behavior: 'instant' });
295
+ }
296
+
297
+ // Ensure Hash anchors work on direct link visits (New Tab)
298
+ if (window.location.hash) {
299
+ const el = document.querySelector(window.location.hash);
300
+ if (el) el.scrollIntoView();
301
+ }
302
+ }, 100);
303
+ });
276
304
 
277
- // --- Main Execution ---
278
- document.addEventListener('DOMContentLoaded', () => {
279
- syncBodyTheme();
280
- setupThemeToggleListener();
281
- initializeSidebarToggle();
282
- initializeTabs();
283
- initializeCopyCodeButtons();
284
- initializeCollapsibleNav();
285
- initializeMobileMenus();
286
- initializeSidebarScroll();
287
- initializeScrollSpy();
288
- });
305
+ })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docmd/ui",
3
- "version": "0.4.6",
3
+ "version": "0.4.8",
4
4
  "description": "Base UI templates and assets for docmd",
5
5
  "main": "index.js",
6
6
  "files": [