@postnord/web-components
Version: 
PostNord Web Components
122 lines (118 loc) • 7.02 kB
JavaScript
/*!
 * Built with Stencil
 * By PostNord.
 */
import { r as registerInstance, c as createEvent, g as getElement, h, a as Host } from './index-C247oTEA.js';
import { ripple } from './index.js';
const pnTabCss = "pn-tab{position:relative;overflow:hidden;flex-shrink:0;scroll-snap-align:center;display:inline-block;border-radius:0.5em}pn-tab .pn-tab{position:relative;cursor:pointer;margin:1em 0.25em;padding:0 0.25em;border:none;border-radius:0.5em;color:#2d2013;background-color:transparent;font-family:inherit;font-size:1em;font-weight:500;text-decoration:none;display:flex;gap:0.5em;align-items:center;justify-content:center;-webkit-tap-highlight-color:transparent}pn-tab .pn-tab .pn-ripple{animation:ripple 0.4s cubic-bezier(0.7, 0, 0.3, 1);position:absolute;border-radius:50%;background-color:#005d92;transform:translate(-50%, -50%) scale(0);opacity:0.1;pointer-events:none;z-index:3}@keyframes ripple{to{transform:translate(-50%, -50%) scale(1);opacity:0}}pn-tab .pn-tab{transition-property:color, outline-color, background-color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)}@media (prefers-reduced-motion: reduce){pn-tab .pn-tab{transition-duration:0s;transition-delay:0s}}pn-tab .pn-tab{outline:0.2rem solid transparent;outline-offset:0.2rem}pn-tab .pn-tab>span{line-height:1.5em}pn-tab .pn-tab>pn-icon>.pn-icon-svg path,pn-tab .pn-tab>pn-icon>.pn-icon-svg polygon{fill:#2d2013}pn-tab .pn-tab:focus-visible{overflow:hidden;outline-color:#005d92;background-color:#ffffff}pn-tab .pn-tab[aria-selected=true],pn-tab .pn-tab[aria-current=page]{color:#005d92}pn-tab .pn-tab[aria-selected=true]>pn-icon>.pn-icon-svg path,pn-tab .pn-tab[aria-selected=true]>pn-icon>.pn-icon-svg polygon,pn-tab .pn-tab[aria-current=page]>pn-icon>.pn-icon-svg path,pn-tab .pn-tab[aria-current=page]>pn-icon>.pn-icon-svg polygon{fill:#005d92}pn-tab .pn-tab[aria-selected=true]:focus,pn-tab .pn-tab[aria-current=page]:focus{color:#0d234b}pn-tab .pn-tab[aria-selected=true]:focus pn-icon>.pn-icon-svg path,pn-tab .pn-tab[aria-selected=true]:focus pn-icon>.pn-icon-svg polygon,pn-tab .pn-tab[aria-current=page]:focus pn-icon>.pn-icon-svg path,pn-tab .pn-tab[aria-current=page]:focus pn-icon>.pn-icon-svg polygon{fill:#0d234b}";
const PnTab = class {
    constructor(hostRef) {
        registerInstance(this, hostRef);
        this.setActiveTab = createEvent(this, "setActiveTab");
        this.tabEnter = createEvent(this, "tabEnter");
        this.tabLeave = createEvent(this, "tabLeave");
    }
    tag = 'button';
    get hostElement() { return getElement(this); }
    /** Set a label for the tab. */
    label;
    /** This is the value that will be matched with `pn-tablist` value. (required) */
    value;
    /** Turns the tab from a `button` to an `a` element, but only if the `pn-tablist` is inside a `pn-header`. */
    href;
    /** The SVG content of the icon you want to display */
    icon;
    /** Use the ID of the container that this tab controls.  */
    ariacontrols;
    /** Tab ID, use if you want to have the tab container be `aria-labelledby` by this tab. */
    tabid;
    /** Is set by `pn-tablist`, don't use this prop. @hide true */
    activeTab;
    /** Used by `pn-tab` to communicate with `pn-tablist`. Emits the selected tab value and element. */
    setActiveTab;
    setActiveTabHandler({ click = false, element } = {}) {
        if (click || this.isActive()) {
            const val = element?.value || this.value;
            const el = ((element?.value && element) || this.hostElement);
            this.setActiveTab.emit({
                val,
                el,
            });
        }
    }
    /** Used by `pn-tab` to communicate with `pn-tablist`. Emits when the tab gets focus. */
    tabEnter;
    triggerEnter(event) {
        this.tabEnter.emit(event);
    }
    /** Used by `pn-tab` to communicate with `pn-tablist`. Emits when the tab is blured.  */
    tabLeave;
    triggerLeave(event) {
        this.tabLeave.emit(event);
    }
    componentWillLoad() {
        this.tabTag();
    }
    componentDidUpdate() {
        this.setActiveTabHandler();
    }
    componentDidLoad() {
        this.setActiveTabHandler();
    }
    arrowKeyNav(event) {
        if (!/^(ArrowRight|ArrowLeft|Home|End)$/.test(event.key))
            return;
        event.preventDefault();
        // Get tablist parent
        const parent = event.target.closest('pn-tablist');
        const list = Array.from(parent.querySelectorAll('pn-tab'));
        const first = list[0];
        const last = list[list.length - 1];
        const nextElement = this.hostElement.nextElementSibling;
        const previousElement = this.hostElement.previousElementSibling;
        if (event.key === 'Home')
            this.setActiveTabHandler({ element: first });
        if (event.key === 'End')
            this.setActiveTabHandler({ element: last });
        if (event.key === 'ArrowRight') {
            // Check the next element value. We do this because the last element i a DIV element. If no value, go to the first element.
            this.setActiveTabHandler({ element: nextElement?.value ? nextElement : first });
        }
        if (event.key === 'ArrowLeft') {
            // Go to the last element if there is no element to your left.
            this.setActiveTabHandler({ element: previousElement?.value ? previousElement : last });
        }
    }
    isActive() {
        return this.activeTab === this.value;
    }
    tabTag() {
        const isMenu = this.hostElement.closest('pn-tablist');
        this.tag = isMenu.slot === 'menu' ? 'a' : 'button';
    }
    renderProperties() {
        return this.tag === 'a'
            ? {
                'href': this.href,
                'aria-current': this.isActive() ? 'page' : 'false',
            }
            : {
                'tabindex': this.isActive() ? 0 : -1,
                'type': 'button',
                'role': 'tab',
                'aria-selected': this.isActive().toString(),
                'aria-controls': this.ariacontrols,
            };
    }
    handleClick(e) {
        this.setActiveTabHandler({ click: true });
        ripple(e, this.hostElement, '.pn-tab');
    }
    render() {
        const Tag = this.tag;
        return (h(Host, { key: 'a86f77aeeeff1646eae6d67de7dbe5236c8ac84d' }, h(Tag, { key: 'a01a44d4525937e0e7485081a65f003a6f633d80', id: this.tabid, class: "pn-tab", ...this.renderProperties(), onClick: (e) => this.handleClick(e), onMouseEnter: (e) => this.triggerEnter(e), onFocus: (e) => this.triggerEnter(e), onMouseLeave: (e) => this.triggerLeave(e), onBlur: (e) => this.triggerLeave(e), onKeyDown: (e) => this.arrowKeyNav(e) }, !!this.icon && h("pn-icon", { key: 'a2303c20a50edf2563989139da38eeaf3206b245', icon: this.icon }), h("slot", { key: 'bb76f4d998b72825750d1bb11630e70f82a932d2' }), h("span", { key: '1a0eb41dbcdf02537baf128e7436adde37db206e' }, this.label))));
    }
};
PnTab.style = pnTabCss;
export { PnTab as pn_tab };
//# sourceMappingURL=pn-tab.entry.js.map