UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

221 lines (202 loc) 6.78 kB
import { PktElement } from '@/base-elements/element' import { html, nothing } from 'lit' import { customElement, property } from 'lit/decorators.js' import { classMap } from 'lit/directives/class-map.js' import { User, Representing, UserMenuItem, TInternalMenuItem, convertUserMenuItem, Booleanish, booleanishConverter, } from './types' import '@/components/icon' import '@/components/link' export interface IPktHeaderUserMenu { user: User formattedLastLoggedIn?: string representing?: Representing userMenu?: UserMenuItem[] canChangeRepresentation?: Booleanish logoutOnClick?: Booleanish } export class PktHeaderUserMenu extends PktElement<IPktHeaderUserMenu> implements IPktHeaderUserMenu { @property({ type: Object }) user!: User @property({ type: String, attribute: 'formatted-last-logged-in' }) formattedLastLoggedIn?: string @property({ type: Object }) representing?: Representing @property({ type: Array, attribute: 'user-menu' }) userMenu?: UserMenuItem[] @property({ type: Boolean, attribute: 'can-change-representation', converter: booleanishConverter, }) canChangeRepresentation: Booleanish = false @property({ type: Boolean, attribute: 'logout-on-click', converter: booleanishConverter }) logoutOnClick: Booleanish = false private handleChangeRepresentation() { this.dispatchEvent( new CustomEvent('change-representation', { bubbles: true, composed: true, }), ) } private handleLogout() { this.dispatchEvent( new CustomEvent('log-out', { bubbles: true, composed: true, }), ) } private handleMenuItemClick(item: TInternalMenuItem) { if ('onClick' in item && typeof item.onClick === 'function') { item.onClick() } } private renderLinkOrButton(item: TInternalMenuItem, className?: string) { const isLink = 'href' in item const classes = classMap({ 'pkt-user-menu__link': true, 'pkt-link-button': !isLink, 'pkt-link': !isLink, 'pkt-link--icon-left': !isLink, [className || '']: !!className, }) if (isLink) { return html` <pkt-link icon-name=${item.iconName || nothing} href=${item.href} aria-hidden="true" class="pkt-user-menu__link ${className || ''}" > ${item.title} </pkt-link> ` } return html` <button class=${classes} type="button" @click=${() => this.handleMenuItemClick(item)}> ${item.iconName ? html`<pkt-icon name=${item.iconName} class="pkt-link__icon" aria-hidden="true" ></pkt-icon>` : nothing} ${item.title} </button> ` } private renderLinkSection(links: TInternalMenuItem[]) { return html` <ul class="pkt-user-menu__sublist"> ${links.map( (item) => html` <li class="pkt-user-menu__subitem">${this.renderLinkOrButton(item)}</li> `, )} </ul> ` } render() { const internalMenuItems = this.userMenu?.map(convertUserMenuItem) return html` <nav class="pkt-user-menu" aria-label="Meny for innlogget bruker"> <ul class="pkt-user-menu__list"> <!-- User section --> ${this.user ? html` <li class="pkt-user-menu__item"> <div class="pkt-user-menu__label">Pålogget som</div> <div class="pkt-user-menu__name" translate="no">${this.user.name}</div> ${this.formattedLastLoggedIn ? html` <div class="pkt-user-menu__last-logged-in"> Sist pålogget: <time>${this.formattedLastLoggedIn}</time> </div> ` : nothing} </li> ` : nothing} <!-- User menu items --> ${internalMenuItems && internalMenuItems.length > 0 ? html` <li class="pkt-user-menu__item">${this.renderLinkSection(internalMenuItems)}</li> ` : nothing} <!-- Representing section --> ${this.representing ? html` <li class="pkt-user-menu__item"> <div class="pkt-user-menu__label">Representerer</div> <div class="pkt-user-menu__name" translate="no">${this.representing.name}</div> ${this.representing.orgNumber ? html`<div class="pkt-user-menu__org-number"> Org.nr. ${this.representing.orgNumber} </div>` : nothing} ${this.canChangeRepresentation ? html` <ul class="pkt-user-menu__sublist mt-size-16"> <li class="pkt-user-menu__subitem"> ${this.renderLinkOrButton({ title: 'Endre organisasjon', iconName: 'cogwheel', onClick: () => this.handleChangeRepresentation(), })} </li> </ul> ` : nothing} </li> ` : nothing} <!-- Change representation without representing object --> ${!this.representing && this.canChangeRepresentation ? html` <li class="pkt-user-menu__item"> <ul class="pkt-user-menu__sublist"> <li class="pkt-user-menu__subitem"> ${this.renderLinkOrButton({ title: 'Endre organisasjon', iconName: 'cogwheel', onClick: () => this.handleChangeRepresentation(), })} </li> </ul> </li> ` : nothing} <!-- Logout --> ${this.logoutOnClick ? html` <li class="pkt-user-menu__item"> ${this.renderLinkOrButton({ title: 'Logg ut', iconName: 'exit', onClick: () => this.handleLogout(), })} </li> ` : nothing} </ul> </nav> ` } } declare global { interface HTMLElementTagNameMap { 'pkt-header-user-menu': PktHeaderUserMenu } } try { customElement('pkt-header-user-menu')(PktHeaderUserMenu) } catch (e) { console.warn('Forsøker å definere <pkt-header-user-menu>, men den er allerede definert') }