UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

148 lines (135 loc) 5.63 kB
import { PktElementWithSlot } from '@/base-elements/element-with-slot' import { slotContent } from '@/directives/slot-content' import { html, nothing, PropertyValues } from 'lit' import { customElement, property } from 'lit/decorators.js' import { ifDefined } from 'lit/directives/if-defined.js' import { User, Representing, UserMenuItem, THeaderMenu, TLogOutButtonPlacement, THeaderPosition, THeaderScrollBehavior, TSlotMenuVariant, IPktHeader, Booleanish, booleanishConverter, } from './types' import './header-service' /** * PktHeader - Main header component for Oslo kommune services * * This component provides a complete header solution with: * - Logo and service name * - User menu with login/logout functionality * - Search functionality * - Responsive mobile menu * - Fixed positioning with scroll-to-hide * * TODO: Add `type` prop to switch between `service` and `global` header types */ export class PktHeader extends PktElementWithSlot<IPktHeader> implements IPktHeader { @property({ type: String, attribute: 'service-name' }) serviceName?: string @property({ type: String, attribute: 'service-link' }) serviceLink?: string @property({ type: String, attribute: 'logo-link' }) logoLink?: string @property({ type: String, attribute: 'search-placeholder' }) searchPlaceholder = 'Søk' @property({ type: String, attribute: 'search-value' }) searchValue = '' @property({ type: Number, attribute: 'mobile-breakpoint' }) mobileBreakpoint: number = 768 @property({ type: Number, attribute: 'tablet-breakpoint' }) tabletBreakpoint: number = 1280 @property({ type: String, attribute: 'opened-menu' }) openedMenu: THeaderMenu = 'none' @property({ type: String, attribute: 'log-out-button-placement' }) logOutButtonPlacement: TLogOutButtonPlacement = 'none' @property({ type: String }) position: THeaderPosition = 'fixed' @property({ type: String, attribute: 'scroll-behavior' }) scrollBehavior: THeaderScrollBehavior = 'hide' @property({ type: String, attribute: 'slot-menu-variant' }) slotMenuVariant: TSlotMenuVariant = 'icon-only' @property({ type: String, attribute: 'slot-menu-text' }) slotMenuText = 'Meny' @property({ type: Boolean, attribute: 'hide-logo', converter: booleanishConverter }) hideLogo: Booleanish = false @property({ type: Boolean, converter: booleanishConverter }) compact: Booleanish = false @property({ type: Boolean, attribute: 'show-search', converter: booleanishConverter }) showSearch: Booleanish = false @property({ type: Boolean, attribute: 'can-change-representation', converter: booleanishConverter, }) canChangeRepresentation: Booleanish = false @property({ type: Boolean, attribute: 'has-log-out', converter: booleanishConverter }) hasLogOut: Booleanish = false @property({ type: Object }) user?: User @property({ type: Array, attribute: 'user-menu' }) userMenu?: UserMenuItem[] @property({ type: Object }) representing?: Representing // Deprecated props - emit warnings @property({ type: Array, attribute: 'user-menu-footer' }) userMenuFooter?: UserMenuItem[] @property({ type: Array, attribute: 'user-options' }) userOptions?: UserMenuItem[] firstUpdated(changedProperties: PropertyValues) { super.firstUpdated(changedProperties) this.emitDeprecationWarnings() } private emitDeprecationWarnings() { if (this.userMenuFooter !== undefined) { // eslint-disable-next-line no-console -- Deprecation warnings are intentional for library consumers console.warn('[PktHeader] userMenuFooter is deprecated. Use userMenu instead.') } if (this.userOptions !== undefined) { // eslint-disable-next-line no-console -- Deprecation warnings are intentional for library consumers console.warn('[PktHeader] userOptions is deprecated. Use userMenu instead.') } } /** * Convert deprecated props to new props */ private get effectiveUserMenu(): UserMenuItem[] | undefined { const menu = this.userMenu || [] const footer = this.userMenuFooter || [] const options = this.userOptions || [] if (footer.length || options.length) { return [...menu, ...options, ...footer] } return this.userMenu } render() { return html` <pkt-header-service service-name=${ifDefined(this.serviceName)} service-link=${ifDefined(this.serviceLink)} logo-link=${ifDefined(this.logoLink)} search-placeholder=${this.searchPlaceholder} search-value=${this.searchValue} mobile-breakpoint=${this.mobileBreakpoint} tablet-breakpoint=${this.tabletBreakpoint} opened-menu=${this.openedMenu} log-out-button-placement=${this.logOutButtonPlacement} position=${this.position} scroll-behavior=${this.scrollBehavior} slot-menu-variant=${this.slotMenuVariant} slot-menu-text=${this.slotMenuText} .hideLogo=${this.hideLogo} .compact=${this.compact} .showSearch=${this.showSearch} .canChangeRepresentation=${this.canChangeRepresentation} .hasLogOut=${this.hasLogOut} .user=${this.user} .userMenu=${this.effectiveUserMenu} .representing=${this.representing} > ${this.hasSlotContent() ? html`<div class="pkt-contents">${slotContent(this)}</div>` : nothing} </pkt-header-service> ` } } declare global { interface HTMLElementTagNameMap { 'pkt-header': PktHeader } } try { customElement('pkt-header')(PktHeader) } catch (e) { console.warn('Forsøker å definere <pkt-header>, men den er allerede definert') }