UNPKG

@postnord/web-components

Version:

PostNord Web Components

228 lines (220 loc) 11.9 kB
/*! * Built with Stencil * By PostNord. */ import { proxyCustomElement, HTMLElement, createEvent, forceUpdate, h, Host } from '@stencil/core/internal/client'; import { j as awaitTopbar, e as en } from './helpers.js'; import { d as defineCustomElement$4 } from './pn-button2.js'; import { d as defineCustomElement$3 } from './pn-icon2.js'; import { d as defineCustomElement$2 } from './pn-spinner2.js'; const icon$1 = '<svg class="pn-icon-svg" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M6.293 12.707a1 1 0 0 1 0-1.414l8-8a1 1 0 1 1 1.414 1.414L8.414 12l7.293 7.293a1 1 0 0 1-1.414 1.414z" clip-rule="evenodd"/></svg>'; const angle_left = icon$1; const icon = '<svg class="pn-icon-svg" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M17.707 11.293a1 1 0 0 1 0 1.414l-8 8a1 1 0 0 1-1.414-1.414L15.586 12 8.293 4.707a1 1 0 0 1 1.414-1.414z" clip-rule="evenodd"/></svg>'; const angle_right = icon; const translations = { LEFT: { sv: 'Bläddra åt vänster', en: 'Scroll to the left', da: 'Rul til venstre', fi: 'Vieritä vasemmalle', no: 'Rull til venstre', }, RIGHT: { sv: 'Bläddra åt höger', en: 'Scroll to the right', da: 'Rul til højre', fi: 'Vieritä oikealle', no: 'Rull til høyre', }, }; const pnTablistCss = "pn-tablist{width:100%;min-width:0;position:relative;border-bottom:0.0625em solid #d3cecb;display:block}pn-tablist .pn-tablist,pn-tablist ol,pn-tablist ul{display:flex;width:100%;flex-direction:row;gap:1em;position:relative;list-style:none;padding:0;margin:0}pn-tablist .pn-tablist[data-stacked] .pn-tab,pn-tablist ol[data-stacked] .pn-tab,pn-tablist ul[data-stacked] .pn-tab{margin:0.5em 0.25em 0.75em;gap:0.25em;flex-direction:column}pn-tablist .pn-tablist[data-small] .pn-tab,pn-tablist ol[data-small] .pn-tab,pn-tablist ul[data-small] .pn-tab{margin:0.25em 0.25em 0.75em}pn-tablist .pn-tablist[data-small] .pn-tab>*:not(pn-icon),pn-tablist ol[data-small] .pn-tab>*:not(pn-icon),pn-tablist ul[data-small] .pn-tab>*:not(pn-icon){font-size:0.875em}pn-tablist .pn-tablist[data-large] .pn-tab>*:not(pn-icon),pn-tablist ol[data-large] .pn-tab>*:not(pn-icon),pn-tablist ul[data-large] .pn-tab>*:not(pn-icon){font-size:1.25em}pn-tablist .pn-tablist[data-scroll],pn-tablist ol[data-scroll],pn-tablist ul[data-scroll]{overflow-y:hidden;overflow-x:auto;scroll-snap-type:x mandatory}pn-tablist .pn-tablist::-webkit-scrollbar,pn-tablist ol::-webkit-scrollbar,pn-tablist ul::-webkit-scrollbar{display:none}pn-tablist>.pn-scroll-arrows{position:absolute;top:50%;left:0;right:0;pointer-events:none;transform:translateY(-50%);display:flex;justify-content:space-between;align-items:center;z-index:1;height:100%}pn-tablist>.pn-scroll-arrows>.pn-arrow{pointer-events:all;transition-property:transform, opacity, visibility;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1);transform:scaleY(0);opacity:0;visibility:hidden}pn-tablist>.pn-scroll-arrows>.pn-arrow[data-show]{opacity:1;visibility:visible;transform:scaleY(1)}pn-tablist .pn-line{height:0.25em;position:absolute;bottom:0}pn-tablist .pn-line-item{position:absolute;transform-origin:left center;width:100%;height:inherit;border-radius:0.25em 0.25em 0 0;opacity:0;transition-property:transform, width, opacity;transition-duration:0.3s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)}pn-tablist .pn-line-active{z-index:1;background-color:#005d92;width:var(--pn-active-width);transform:translateX(var(--pn-active-offset));opacity:var(--pn-active-opacity)}pn-tablist .pn-line-hovered{background-color:#00a0d6;width:var(--pn-hover-width);transform:translateX(var(--pn-hover-offset));opacity:var(--pn-hover-opacity)}"; const PnTablistStyle0 = pnTablistCss; const PnTablist$1 = /*@__PURE__*/ proxyCustomElement(class PnTablist extends HTMLElement { constructor() { super(); this.__registerHost(); this.tabchange = createEvent(this, "tabchange", 7); } mo; isMenu = false; isTabHovered = false; tabListEl; lineActive; lineHovered; tabElement; get hostElement() { return this; } /** Display the scrolling arrows */ showScrollArrows = false; /** Display the scroll arrow to the left */ arrowLeft = false; /** Display the scroll arrow to the right */ arrowRight = false; /** Give the tablist a name for screenreaders */ label; /** The value of the tab that is currently active, each `<pn-tab value="example-value">` also expects a unique value */ value; /** Make the tablist smaller */ small; /** Icons are stacked vertically instead of the default rows */ stackedicons = false; /** Manually set the language. */ language = null; /** * This will emit when a tab is changed. The detail property of the event will contain the value of the selected tab. * This is the event and value you listen to when you toggle the visibility among your tabpanels. **/ tabchange; setValue() { const tabs = Array.from(this.hostElement.querySelectorAll('pn-tab')); tabs.forEach(tab => { tab.activeTab = this.value; }); } scrollHandler() { if (this.showScrollArrows) { this.tabListEl.addEventListener('scroll', this.scrollIndicators.bind(this)); } else { this.tabListEl.removeEventListener('scroll', this.scrollIndicators); } } setActiveTabHandler({ detail }) { this.tabElement = detail.el; requestAnimationFrame(() => this.activateTab(detail.el)); if (this.value === detail.val) return; this.value = detail.val; this.tabchange.emit(this.value); this.tabElement.querySelector(this.isMenu ? 'a' : 'button').focus(); } rerender() { requestAnimationFrame(() => { this.scrollIndicators(); this.isTabHovered = false; }); } handleEnter(e) { this.isTabHovered = true; this.styleLines(e.target); } handleLeave() { this.isTabHovered = false; setTimeout(() => { if (!this.isTabHovered) this.lineHovered.style.setProperty('--pn-hover-opacity', '0'); }, 500); } async componentWillLoad() { this.isMenu = this.hostElement.slot === 'menu'; if (this.language === null) return await awaitTopbar(this.hostElement); } componentDidLoad() { if (this.mo) this.mo.disconnect(); this.mo = new MutationObserver(() => { forceUpdate(this.hostElement); this.rerender(); }); this.mo.observe(this.hostElement, { childList: true, subtree: true }); } componentDidRender() { this.rerender(); this.setValue(); } getRect(element) { return element.getBoundingClientRect(); } activateTab(element) { this.styleLines(element, true); } styleLines(element, active = false) { const tabListCoords = this.getRect(this.tabListEl); const scrollOffset = this.tabListEl.scrollLeft; const line = this.getRect(element); const width = line.width; const offset = line.left + scrollOffset - tabListCoords.left; const cssVar = active ? 'active' : 'hover'; const prop = active ? 'lineActive' : 'lineHovered'; this[prop].style.setProperty(`--pn-${cssVar}-width`, `${width}px`); this[prop].style.setProperty(`--pn-${cssVar}-offset`, `${offset}px`); this[prop].style.setProperty(`--pn-${cssVar}-opacity`, '1'); } scrollIndicators() { const { scrollWidth, scrollLeft } = this.tabListEl; const { clientWidth } = this.hostElement; this.showScrollArrows = scrollWidth > clientWidth; this.arrowLeft = this.showScrollArrows && scrollLeft > 0; this.arrowRight = this.showScrollArrows && clientWidth + 16 + scrollLeft < scrollWidth; } scroll({ right = false } = {}) { const tabList = this.tabListEl; const { scrollLeft, clientWidth } = tabList; let left = scrollLeft; // The width of the scroll arrow is 32px, so we remove that from this calculation so the scroll const scrollAmount = clientWidth - 64; if (right) left += scrollAmount; else left -= scrollAmount; tabList.scrollTo({ left, behavior: 'smooth', }); } translate(prop) { return translations?.[prop]?.[this.language || en]; } render() { return (h(Host, { key: '4d0d29f48ee2952b58fdae8738795e3247c7257e' }, h("nav", { key: 'c1efeea1978a6157572652e7ff8ad7a9d9905f5b', class: "pn-tablist", role: this.isMenu ? null : 'tablist', "aria-label": this.label, "data-stacked": this.stackedicons, "data-small": !this.isMenu && this.small, "data-large": this.isMenu, "data-scroll": this.showScrollArrows, ref: el => (this.tabListEl = el) }, h("slot", { key: 'bd1d7ddee497d0c737e254d97dfda435964cfbb3' }), h("div", { key: '660b591ce4d462c7d390b4479094fb2452ef9dbd', class: "pn-line" }, h("div", { key: 'daf52564a72d07a7fbb29e77752a9ec1e4cc2289', ref: el => (this.lineActive = el), class: "pn-line-item pn-line-active" }), h("div", { key: 'fcdf804b3b6589b9e971bd72b033741c34874989', ref: el => (this.lineHovered = el), class: "pn-line-item pn-line-hovered" }))), h("div", { key: 'e46e9ba8bdf7334ed5f6ca82499e97a798cb2bfb', class: "pn-scroll-arrows" }, h("pn-button", { key: '54b83c42942c072976e39d222957f673eb8015ac', class: "pn-arrow", "data-show": this.arrowLeft, onClick: () => this.scroll(), noTab: true, appearance: "light", variant: "outlined", icon: angle_left, iconOnly: true, arialabel: this.translate('LEFT'), small: true }), h("pn-button", { key: 'bc171ec91d1025111a7ec8f16549be969ac8e55b', class: "pn-arrow", "data-show": this.arrowRight, onClick: () => this.scroll({ right: true }), noTab: true, appearance: "light", variant: "outlined", icon: angle_right, iconOnly: true, arialabel: this.translate('RIGHT'), small: true })))); } static get watchers() { return { "value": ["setValue"], "showScrollArrows": ["scrollHandler"] }; } static get style() { return PnTablistStyle0; } }, [4, "pn-tablist", { "label": [1], "value": [1537], "small": [4], "stackedicons": [4], "language": [1], "showScrollArrows": [32], "arrowLeft": [32], "arrowRight": [32] }, [[0, "setActiveTab", "setActiveTabHandler"], [9, "resize", "rerender"], [0, "tabEnter", "handleEnter"], [0, "tabLeave", "handleLeave"]], { "value": ["setValue"], "showScrollArrows": ["scrollHandler"] }]); function defineCustomElement$1() { if (typeof customElements === "undefined") { return; } const components = ["pn-tablist", "pn-button", "pn-icon", "pn-spinner"]; components.forEach(tagName => { switch (tagName) { case "pn-tablist": if (!customElements.get(tagName)) { customElements.define(tagName, PnTablist$1); } break; case "pn-button": if (!customElements.get(tagName)) { defineCustomElement$4(); } break; case "pn-icon": if (!customElements.get(tagName)) { defineCustomElement$3(); } break; case "pn-spinner": if (!customElements.get(tagName)) { defineCustomElement$2(); } break; } }); } const PnTablist = PnTablist$1; const defineCustomElement = defineCustomElement$1; export { PnTablist, defineCustomElement }; //# sourceMappingURL=pn-tablist.js.map