@turquoisehealth/pit-viper 2.104.1 → 2.105.0

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.
@@ -178,4 +178,137 @@ class PVAutoClose extends HTMLElement {
178
178
 
179
179
  }
180
180
  customElements.define('pv-data-grid', PVDataGrid);
181
+
182
+ class PvGlobalNav extends HTMLElement {
183
+ constructor() {
184
+ super();
185
+ this.hoverTimeout = null;
186
+ this.layout = document.querySelector('.pv-layout-primary');
187
+ this.minimizeButton = this.querySelector('#global-sidebar-toggle');
188
+ }
189
+
190
+ connectedCallback() {
191
+ this.minimizeButton?.addEventListener('click', (e) => this.toggleSidebar(e.currentTarget));
192
+ this.addEventListener('mouseenter', () => this.handleHoverIn());
193
+ this.addEventListener('mouseleave', () => this.handleHoverOut());
194
+ document.addEventListener('click', (e) => this.handleMenuClick(e));
195
+ this.initializeSidebar();
196
+ }
197
+
198
+ setState(attributes) {
199
+ Object.entries(attributes).forEach(([key, value]) => {
200
+ if (value) {
201
+ this.layout.setAttribute(key, '');
202
+ } else {
203
+ this.layout.removeAttribute(key);
204
+ }
205
+ });
206
+ }
207
+
208
+ isExpandedState() {
209
+ return !this.layout.hasAttribute('data-collapsed') && !this.layout.hasAttribute('data-hovering');
210
+ }
211
+
212
+ collapseState() {
213
+ this.setState({ 'data-collapsed': true, 'data-expanded': false, 'data-hovering': false });
214
+ }
215
+
216
+ expandState() {
217
+ this.setState({ 'data-collapsed': false, 'data-hovering': false, 'data-expanded': true });
218
+ }
219
+
220
+ hoverExpandState() {
221
+ this.setState({ 'data-collapsed': false, 'data-hovering': true });
222
+ }
223
+
224
+ hoverCollapseState() {
225
+ this.setState({ 'data-collapsed': true, 'data-hovering': false });
226
+ }
227
+
228
+ getSidebarMinimizeState() {
229
+ const stored = localStorage.getItem('global-nav-sidebar-minimize');
230
+ return stored === 'true';
231
+ }
232
+
233
+ setSidebarMinimizeState(value) {
234
+ localStorage.setItem('global-nav-sidebar-minimize', value.toString());
235
+ }
236
+
237
+ updateIcons(button, isExpanded) {
238
+ const use = button.querySelector('svg use');
239
+ const tooltip = document.getElementById('description');
240
+ use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', isExpanded ? '#panel-left-close' : '#panel-left-open');
241
+ if (tooltip) tooltip.querySelector('p').textContent = isExpanded ? 'Close Sidebar' : 'Open Sidebar';
242
+ }
243
+
244
+ toggleSidebar(button) {
245
+ const isExpanded = this.isExpandedState();
246
+ if (isExpanded) {
247
+ this.setSidebarMinimizeState(true);
248
+ this.collapseState();
249
+ this.updateIcons(button, false);
250
+ } else {
251
+ this.setSidebarMinimizeState(false);
252
+ this.expandState();
253
+ this.updateIcons(button, true);
254
+ }
255
+ }
256
+
257
+ handleHoverIn() {
258
+ clearTimeout(this.hoverTimeout);
259
+ if (this.layout.hasAttribute('data-collapsed')) {
260
+ this.hoverTimeout = setTimeout(() => this.hoverExpandState(), 200);
261
+ }
262
+ }
263
+
264
+ handleHoverOut() {
265
+ clearTimeout(this.hoverTimeout);
266
+ if (this.layout.hasAttribute('data-hovering') && !this.hasOpenMenu()) {
267
+ this.hoverCollapseState();
268
+ }
269
+ }
270
+
271
+ hasOpenMenu() {
272
+ return this.querySelector('.pv-popover-menu[data-active]') !== null;
273
+ }
274
+
275
+ handleMenuClick(event) {
276
+ const clickedMenu = event.target.closest('.pv-popover-menu');
277
+ const allMenus = this.querySelectorAll('.pv-popover-menu');
278
+
279
+ if (clickedMenu && this.contains(clickedMenu)) {
280
+ allMenus.forEach(menu => menu.removeAttribute('data-active'));
281
+ clickedMenu.setAttribute('data-active', '');
282
+ this.style.overflow = 'initial';
283
+ if (!this.layout.hasAttribute('data-expanded')) {
284
+ this.hoverExpandState();
285
+ }
286
+ return;
287
+ }
288
+ allMenus.forEach(menu => menu.removeAttribute('data-active'));
289
+ this.style.overflow = 'hidden';
290
+ if (this.layout.hasAttribute('data-hovering') && !this.layout.hasAttribute('data-expanded')) {
291
+ console.log('Collapsing sidebar after menu close');
292
+ this.hoverCollapseState();
293
+ }
294
+ }
295
+
296
+ initializeSidebar() {
297
+ const currentSidebarMinimize = this.layout.hasAttribute('data-collapsed');
298
+ if (currentSidebarMinimize) {
299
+ return;
300
+ }
301
+ const storedValue = this.getSidebarMinimizeState();
302
+
303
+ if (storedValue) {
304
+ this.collapseState();
305
+ this.updateIcons(this.minimizeButton, false);
306
+ } else {
307
+ this.expandState();
308
+ this.updateIcons(this.minimizeButton, true);
309
+ }
310
+ }
311
+ }
312
+
313
+ customElements.define('pv-global-nav', PvGlobalNav, { extends: 'aside' });
181
314
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turquoisehealth/pit-viper",
3
- "version": "2.104.1",
3
+ "version": "2.105.0",
4
4
  "description": "Turquoise Health's design system.",
5
5
  "main": "README.md",
6
6
  "publishConfig": {
@@ -1,4 +1,5 @@
1
1
  export { default as PvButton } from './PvButton/PvButton.vue';
2
+ export { default as PvAiButton } from './PvAiButton/PvAiButton.vue';
2
3
  export { default as PvButtonWithTooltip } from './PvButton/PvButtonWithTooltip.vue';
3
4
  export { default as PvCounterBadge } from './PvCounterBadge/PvCounterBadge.vue';
4
5
  export { default as PvReleaseBadge } from './PvReleaseBadge/PvReleaseBadge.vue';