UNPKG

@govbr-ds/core

Version:

Padrão Digital de Governo

314 lines (285 loc) 9.69 kB
/** Classe para instanciar um objeto BRTab*/ class BRTab { /** * Instancia do objeto * @param {string} name - Nome do componente em minúsculo * @param {object} component - Objeto referenciando a raiz do componente DOM */ constructor(name, component) { this.name = name this.component = component this._setBehavior() } /** * Define comportamentos do componente * @private */ _setBehavior() { for (const ancor of this.component.querySelectorAll('.tab-nav')) { this.height = ancor.clientHeight this.scollsizes = ancor.scrollHeight - ancor.clientHeight this.scrollHeight = Math.max( this.component.scrollWidth, document.documentElement.scrollWidth, this.component.offsetWidth, document.documentElement.offsetWidth, this.component.clientWidth, document.documentElement.clientWidth ) this.leftPosition = this.component.offsetWidth - 1 // debugger ancor.style.setProperty('--height-nav', `${this.height}px`) ancor.style.setProperty('--right-gradient-nav', `${this.leftPosition}px`) this.positionScroll(ancor) this.navigationRight = this.navigationRight + 4 if (this.navigationRight <= this.lastItempos - 5) { ancor.classList.add('tab-nav-right') } ancor.onscroll = () => { this.positionScroll(ancor) if (this.navigationLeft <= 0) { ancor.classList.add('tab-nav-left') } else { ancor.classList.remove('tab-nav-left') } if (this.navigationRight <= this.lastItempos - 5) { ancor.classList.add('tab-nav-right') } else { ancor.classList.remove('tab-nav-right') } } } for (const ancor of this.component.querySelectorAll('.tab-nav .tab-item:not([not-tab="true"]) button')) { ancor.addEventListener( 'click', (event) => { event.currentTarget.setAttribute('aria-selected', 'false') this._switchTab(event.currentTarget.parentElement) this._switchContent(event.currentTarget.parentElement) }, false ) ancor.addEventListener('keyup', (e) => { e.preventDefault() this.positionKeyboard(e) }) ancor.addEventListener('blur', () => { this.hiddenTooltips() }) } this.tabitems = this.component.querySelectorAll('tab-item') } /** * Mapeia as teclas pressionadas * @param {event} event - evento que disparou a ação */ positionKeyboard(event) { const keys = { end: 35, home: 36, left: 37, right: 39, space: 32, tab: 9, } const key = event.keyCode this.tabitems = this.component.querySelectorAll('.tab-item') this.buttons = this.component.querySelectorAll('button') switch (key) { case keys.end: event.preventDefault() this.clean() this._switchTab(this.tabitems[this.tabitems.length - 1]) this._switchContent(this.tabitems[this.tabitems.length - 1]) this.tabitems[this.tabitems.length - 1].focus() break case keys.home: event.preventDefault() this.clean() this._switchTab(this.tabitems[0]) this._switchContent(this.tabitems[0]) this.tabitems[0].focus() event.stopPropagation() break case keys.left: event.preventDefault() this.position(event.target, -1) event.stopPropagation() break case keys.right: event.preventDefault() this.position(event.target, 1) event.stopPropagation() break case keys.tab: event.preventDefault() this.position(event.target, 0) event.stopPropagation() break case 32: event.preventDefault() this.hiddenTooltips() event.target.click() event.stopPropagation() break default: break } } /** * Esconde todos tooltip * */ hiddenTooltips() { const tooltips = document.querySelectorAll('.br-tooltip') tooltips.forEach((element) => { element.hidden = true element.style.visbility = 'hidden' element.removeAttribute('data-show') }) } /** * Define o deslocamento da posição ativa * @property {object} target - referencia ao objeto DOM * @property {number} direction - incremento à posição */ positionActive(target, direction) { let contComponent = 0 let contComponentActive = 0 const tabItems2 = target.parentElement.parentElement.querySelectorAll('.tab-item') for (const component of tabItems2) { if (component.classList.contains('is-active') || component.classList.contains('active')) { contComponentActive = contComponent } contComponent += 1 } if (tabItems2.length > contComponentActive + direction && contComponentActive + direction >= 0) { this._switchTab(tabItems2[contComponentActive + direction]) tabItems2[contComponentActive + direction].focus() let x = '' if (tabItems2[contComponentActive + direction].querySelector('button')) { x = tabItems2[contComponentActive + direction].querySelector('button') x.focus() } } } /** * Define o deslocamento da posição ativa do tab-item interno * @property {object} target - referencia ao objeto DOM * @property {number} direction - incremento à posição */ position(target, direction) { this.positionQuery(target, direction, '.tab-item') } /** * Define o deslocamento da posição ativa do elemento referenciado * @property {object} target - referencia ao objeto DOM * @property {number} direction - incremento à posição * @property {string} query - string de referencia */ positionQuery(target, direction, query) { let contComponent = 0 // const contComponentActive = 0 let contComponentFocus = 0 const tabItems2 = target.parentElement.parentElement.querySelectorAll(query) for (const component of tabItems2) { if (component.querySelector('.focus-visible')) { contComponentFocus = contComponent } contComponent += 1 } tabItems2[contComponentFocus + direction].querySelector('button').focus() if (tabItems2.length > contComponentFocus + direction && contComponentFocus + direction >= 0) { if (tabItems2[contComponentFocus + direction].querySelector('button')) { tabItems2[contComponentFocus + direction].querySelector('button').focus() } } } /** * Define a posição ativa do elemento referenciado * @property {object} target - referencia ao objeto DOM */ setPosition(target) { let contComponent = 0 let contComponentActive = 0 const tabItems2 = target.parentElement.parentElement.querySelectorAll('.tab-item') for (const component of tabItems2) { if (component.classList.contains('is-active') || component.classList.contains('active')) { contComponentActive = contComponent } contComponent += 1 } if (tabItems2.length > contComponentActive && contComponentActive >= 0) { this.clean() this._switchContent(tabItems2[contComponentActive]) } } /** * Reinicia estados */ clean() { for (const ancor of event.currentTarget.parentElement.querySelectorAll('button')) { ancor.classList.remove('focus-visible') ancor.classList.remove('is-active') ancor.classList.remove('active') } for (const ancor of event.currentTarget.parentElement.querySelectorAll('tab-item')) { ancor.classList.remove('is-active') ancor.classList.remove('active') } } /** * Realiza rolagem até a âncora * @property {object} ancor - referencia ao objeto DOM */ positionScroll(ancor) { this.navItems = ancor.querySelectorAll('.tab-item') this.lastItempos = Math.ceil(this.navItems[this.navItems.length - 1].getBoundingClientRect().right) this.navigationLeft = Math.floor(this.navItems[0].getBoundingClientRect().left) this.navigationRight = Math.floor(ancor.getBoundingClientRect().right) } /** * Muda para a aba referenciada * @property {object} currentTab - referencia ao objeto DOM */ _switchTab(currentTab) { for (const tabItem of this.component.querySelectorAll('.tab-nav .tab-item:not([not-tab="true"])')) { if (tabItem === currentTab) { tabItem.classList.add('active') this._selectTab(tabItem, true) } else { tabItem.classList.remove('is-active') tabItem.classList.remove('active') this._selectTab(tabItem, false) } } } /** * Muda para o conteudo da aba referenciada * @property {object} currentTab - referencia ao objeto DOM * @property {boolean} value - valor a ser aplicado no aria selected */ _selectTab(tabItem, value) { tabItem.querySelector('button').setAttribute('aria-selected', value) } /** * Muda para o conteudo da aba referenciada * @property {object} currentTab - referencia ao objeto DOM */ _switchContent(currentTab) { for (const button of currentTab.querySelectorAll('button')) { for (const tabPanel of this.component.querySelectorAll('.tab-content .tab-panel')) { if ( button.getAttribute('data-panel') === tabPanel.getAttribute('id') || button.getAttribute('data-target') === tabPanel.getAttribute('id') ) { tabPanel.classList.add('active') } else { tabPanel.classList.remove('is-active') tabPanel.classList.remove('active') } } } } } export default BRTab