UNPKG

@telekom/scale-components

Version:

Scale is the digital design system for Telekom products and experiences.

166 lines (160 loc) 5.52 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); const index = require('./index-a0ea3d79.js'); const index$1 = require('./index-53f5a5fc.js'); const statusNote = require('./status-note-dceee5a3.js'); const tabNavCss = ":host{--tab-height:3rem;--tab-spacing-horizontal:var(--telekom-spacing-composition-space-05);--tab-spacing-vertical:var(--telekom-spacing-composition-space-06);--tab-radius:var(--telekom-radius-small);--tab-border-size:var(--telekom-line-weight-standard);--tab-border-size-selected:var(--telekom-line-weight-highlight);--tab-border-size-selected:3px;--tab-border-color:var(--telekom-color-ui-subtle);--tab-height-large:3.25rem;--tab-spacing-horizontal-large:var(--telekom-spacing-composition-space-06);--tab-spacing-vertical-large:0.875rem}"; /** * @see https://github.com/GoogleChromeLabs/howto-components/blob/master/elements/howto-tabs/howto-tabs.js */ const ARROW_LEFT = 'ArrowLeft'; const ARROW_RIGHT = 'ArrowRight'; const HOME = 'Home'; const END = 'End'; const TabNav = class { constructor(hostRef) { index.registerInstance(this, hostRef); /** True for smaller height and font size in tab headers. */ /** @deprecated - size should replace small */ this.small = false; /** (optional) size */ this.size = 'small'; } handleSelect(event) { const nextTab = event.target; // Act only if it's a direct child if (this.getAllEnabledTabs().includes(nextTab)) { this.selectTab(nextTab); } } handleKeydown(event) { const target = event.target; let nextTab; if (target.getAttribute('role') !== 'tab') { return; } // Do not handle modifier shortcuts typically used by assistive technology if (event.altKey) { return; } switch (event.key) { case ARROW_LEFT: nextTab = this.getPreviousTab(); break; case ARROW_RIGHT: nextTab = this.getNextTab(); break; case HOME: nextTab = this.getFirstTab(); break; case END: nextTab = this.getLastTab(); break; default: return; } event.preventDefault(); this.selectTab(nextTab); } connectedCallback() { if (!this.el.hasAttribute('role')) { this.el.setAttribute('role', 'tablist'); } } componentDidRender() { Promise.all([ customElements.whenDefined('scale-tab-header'), customElements.whenDefined('scale-tab-panel'), ]).then(() => { this.linkPanels(); this.propagateSizeToTabs(); }); if (this.small !== false) { statusNote.statusNote({ tag: 'deprecated', message: 'Property "small" is deprecated. Please use css overwrite!', type: 'warn', source: this.el, }); } } getAllTabs() { return Array.from(this.el.querySelectorAll('scale-tab-header')); } getAllEnabledTabs() { return Array.from(this.el.querySelectorAll('scale-tab-header:not([disabled])')); } getAllPanels() { return Array.from(this.el.querySelectorAll('scale-tab-panel')); } getPreviousTab() { const tabs = this.getAllEnabledTabs(); const index = tabs.findIndex((tab) => tab.selected) - 1; return tabs[(index + tabs.length) % tabs.length]; } getNextTab() { const tabs = this.getAllEnabledTabs(); const index = tabs.findIndex((tab) => tab.selected) + 1; return tabs[index % tabs.length]; } getFirstTab() { const tabs = this.getAllEnabledTabs(); return tabs[0]; } getLastTab() { const tabs = this.getAllEnabledTabs(); return tabs[tabs.length - 1]; } linkPanels() { const tabs = this.getAllEnabledTabs(); const selectedTab = tabs.find((x) => x.selected) || tabs[0]; tabs.forEach((tab) => { const panel = tab.nextElementSibling; tab.setAttribute('aria-controls', panel.id); panel.setAttribute('aria-labelledby', tab.id); }); this.selectTab(selectedTab); } reset() { const tabs = this.getAllEnabledTabs(); const panels = this.getAllPanels(); tabs.forEach((tab) => (tab.selected = false)); panels.forEach((panel) => (panel.hidden = true)); } findPanelForTab(tab) { const panelId = tab.getAttribute('aria-controls'); return this.el.querySelector(`#${panelId}`); } selectTab(nextTab) { const nextPanel = this.findPanelForTab(nextTab); this.reset(); nextPanel.hidden = false; nextTab.selected = true; } /** * Sets or removes the `large` prop in `scale-tab-header` and `scale-tab-panel` children. */ propagateSizeToTabs() { const action = this.size === 'large' ? 'setAttribute' : 'removeAttribute'; const tabs = this.getAllTabs(); const panels = this.getAllPanels(); [...tabs, ...panels].forEach((child) => child[action]('size', 'large')); } render() { return (index.h(index.Host, { class: "scale-tab-nav" }, this.styles && index.h("style", null, this.styles), index.h("div", { part: this.getBasePartMap(), class: this.getCssClassMap() }, index.h("slot", { name: "tab" }), index.h("slot", { name: "panel" })))); } getBasePartMap() { return this.getCssOrBasePartMap('basePart'); } getCssClassMap() { return this.getCssOrBasePartMap('css'); } getCssOrBasePartMap(mode) { const component = 'tab-nav'; const prefix = mode === 'basePart' ? '' : `${component}--`; return index$1.classnames(component, `${prefix}`); } get el() { return index.getElement(this); } }; TabNav.style = tabNavCss; exports.scale_tab_nav = TabNav;