/* eslint-disable max-len */ import { convertRemToPixels, isElementWithClassNameInEventPath, isViewportBelow } from './helpers'; const lockBodyScroll = (): void => { const body = document.querySelector('body'); if (isViewportBelow('--bp-medium') || isViewportBelow('--bp-low-height')) { body?.classList.add('body--no-scroll'); } }; const unlockBodyScroll = (): void => { const body = document.querySelector('body'); body?.classList.remove('body--no-scroll'); }; /* eslint-env browser */ const closeAllContentTogglesInToolbar = (toolbar: HTMLElement): void => { const contentToggles = toolbar.querySelectorAll('.content-toggle__toggle'); contentToggles.forEach((toggle) => { const content = toggle.parentElement?.querySelector('.content-toggle__content'); toggle.setAttribute('aria-expanded', 'false'); content?.setAttribute('hidden', 'hidden'); }); }; const setOverflow = (toolbarElement: Element): void => { if (!toolbarElement.classList.contains('toolbar--no-collapse')) { toolbarElement.classList.remove('toolbar--toggled'); } toolbarElement.classList.remove('toolbar--fully-overflown'); toolbarElement.classList.remove('toolbar--has-popout'); const toolbarItemsParent = toolbarElement.querySelector('.toolbar__items'); const toolbarItems = toolbarItemsParent?.children as HTMLCollection; const isOverflownClass = 'toolbar__item--is-overflown'; const hasOverflowClass = 'toolbar--has-overflow'; let hasOverflown = false; let overflownCount = 0; const addOverflowClass = (item: HTMLElement, index: number) => { if (item) { const top = item.offsetTop; if (top > 25) { item.classList.add(isOverflownClass); toolbarElement.classList.add(hasOverflowClass); hasOverflown = true; overflownCount += 1; } else { item.classList.remove(isOverflownClass); } if (!hasOverflown) { toolbarElement.classList.remove(hasOverflowClass); } else if (index - 1 >= 0) { addOverflowClass(toolbarItems[index - 1] as HTMLElement, index - 1); } } }; addOverflowClass(toolbarItems[toolbarItems.length - 1] as HTMLElement, toolbarItems.length - 1); if (overflownCount > 0 && overflownCount === toolbarItems.length) { toolbarElement.classList.add('toolbar--fully-overflown'); } }; const setToolbarToggle = (toolbar: HTMLElement): ExtendedCleanUpPair[] => { const cleanUp: ExtendedCleanUpPair[] = []; const buttons = toolbar.querySelectorAll('.toolbar__toggle'); buttons.forEach((button) => { const clickEvent = () => { button?.parentElement?.classList.toggle('toolbar--toggled'); const ariaExpanded = button.getAttribute('aria-expanded'); if (ariaExpanded !== 'true') { const focusable = 'a.toolbar__item--is-overflown, button.toolbar__item--is-overflown, input.toolbar__item--is-overflown, select.toolbar__item--is-overflown, .toolbar__item--is-overflown a, .toolbar__item--is-overflown button, .toolbar__item--is-overflown input, .toolbar__item--is-overflown select'; const firstWithOverflow = button?.parentElement?.querySelector(focusable) as HTMLElement; if (firstWithOverflow) { setTimeout(() => { firstWithOverflow.focus(); }, 0); } } button.setAttribute('aria-expanded', ariaExpanded === 'false' ? 'true' : 'false'); }; cleanUp.push({ element: button, clickEvent, }); button.addEventListener('click', clickEvent); }); return cleanUp; }; const setToolbar = ( toolbar: HTMLElement, onCloseContentToggle: (toolbarElement: HTMLElement) => void, setOverflowOnly = true, ): ExtendedCleanUpPair[] => { let cleanUp: ExtendedCleanUpPair[] = []; setOverflow(toolbar); onCloseContentToggle(toolbar); cleanUp = cleanUp.concat(setToolbarToggle(toolbar)); if (!setOverflowOnly) { const bodyClickEvent = (event: Event) => { if (!(event.target as HTMLElement).classList.contains('content-toggle__toggle') && !isElementWithClassNameInEventPath(event as MouseEvent, 'content-toggle__content')) { onCloseContentToggle(toolbar); } }; const escKeyEvent = (event: Event) => { if ((event as KeyboardEvent).key === 'Escape') { if (event.target && (event.target as HTMLElement).getAttribute('type') !== 'search') { onCloseContentToggle(toolbar); } } }; const body = document.querySelector('body'); cleanUp.push({ element: body as Element, clickEvent: bodyClickEvent, }); cleanUp.push({ element: window, keyUpEvent: escKeyEvent, }); body?.addEventListener('click', bodyClickEvent); window.addEventListener('keyup', escKeyEvent); } return cleanUp; }; const findToolbar = (element: HTMLElement): HTMLElement => { const parent = element.parentElement; if (parent) { if (parent.classList.contains('toolbar')) { return parent; } return findToolbar(parent); } return element; }; const contentToggleEdgeHandling = (element: HTMLElement): void => { if (!isViewportBelow('--bp-medium') && !isViewportBelow('--bp-low-height')) { const allowedDistance = convertRemToPixels(parseInt(getComputedStyle(document.documentElement).getPropertyValue('--toolbar-popout-allowed-edge-distance').replace('rem,', ''), 10)); const popoutX = parseInt(getComputedStyle(element).width.replace('px', ''), 10); const popoutWidth = element.getBoundingClientRect().x; const distance = document.body.offsetWidth - allowedDistance - popoutX - popoutWidth; if (distance < 0) { element.style.setProperty('--toolbar-popout-edge-overflow', `${distance}px`); } } }; export { setToolbar, setOverflow, findToolbar, closeAllContentTogglesInToolbar, contentToggleEdgeHandling, lockBodyScroll, unlockBodyScroll, };