UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

159 lines (143 loc) 4.57 kB
import { PktShadowElement } from '@/base-elements/element' import { html, PropertyValues } from 'lit' import { customElement, property } from 'lit/decorators.js' import type { THeadingLevel, THeadingSize, THeadingWeight } from 'shared-types' export type TPktHeadingLevel = THeadingLevel export type TPktHeadingSize = THeadingSize export type TPktHeadingWeight = THeadingWeight export interface IPktHeading { size?: TPktHeadingSize level?: TPktHeadingLevel weight?: TPktHeadingWeight visuallyHidden?: boolean align?: 'start' | 'center' | 'end' } export class PktHeading extends PktShadowElement<IPktHeading> implements IPktHeading { @property({ type: String, reflect: true }) size: TPktHeadingSize | undefined = undefined @property({ type: Number, reflect: true }) level: TPktHeadingLevel = 2 @property({ type: String, reflect: true }) weight: TPktHeadingWeight | undefined = undefined @property({ type: Boolean, reflect: true }) visuallyHidden: boolean = false @property({ type: String, reflect: true }) align: 'start' | 'center' | 'end' | undefined = undefined connectedCallback(): void { super.connectedCallback() this.setAttribute('role', 'heading') this.setAttribute('aria-level', String(this.level)) this.updateHostClasses() } attributeChangedCallback(name: string, _old: string | null, value: string | null): void { super.attributeChangedCallback(name, _old, value) if (name === 'level' && value) { this.setLevel(Number(value) as TPktHeadingLevel) } if (name === 'visuallyHidden') { this.visuallyHidden = value !== null && value !== 'false' } if (name === 'size' || name === 'visuallyHidden' || name === 'align' || name === 'weight') { this.updateHostClasses() } } protected updated(_changedProperties: PropertyValues): void { super.updated(_changedProperties) if (_changedProperties.has('level')) { this.setLevel(this.level) if (!this.hasAttribute('size')) { this.size = this.defaultSizeForLevel } if (!this.hasAttribute('weight')) { this.weight = this.defaultWeightForLevel } } if ( !this.hasAttribute('size') && (_changedProperties.has('level') || this.size === undefined) ) { this.size = this.defaultSizeForLevel } if ( _changedProperties.has('size') || _changedProperties.has('visuallyHidden') || _changedProperties.has('align') || _changedProperties.has('weight') ) { this.updateHostClasses() } } private setLevel(level: TPktHeadingLevel): void { if (level >= 1 && level <= 6) { this.level = level this.setAttribute('aria-level', String(level)) } else { console.warn(`Invalid heading level: ${level}. Must be between 1 and 6.`) } } private get defaultSizeForLevel(): TPktHeadingSize { switch (this.level) { case 1: return 'xlarge' case 2: return 'large' case 3: return 'medium' case 4: return 'small' case 5: return 'xsmall' case 6: return 'xsmall' default: return 'medium' } } private get defaultWeightForLevel(): TPktHeadingWeight { switch (this.level) { case 1: return 'regular' case 2: return 'regular' case 3: return 'medium' case 4: return 'medium' case 5: return 'medium' case 6: return 'medium' default: return 'medium' } } private updateHostClasses() { // Remove all possible classes first this.classList.remove( 'pkt-heading', 'pkt-heading--xsmall', 'pkt-heading--small', 'pkt-heading--medium', 'pkt-heading--large', 'pkt-heading--xlarge', 'pkt-sr-only', 'pkt-heading--start', 'pkt-heading--center', 'pkt-heading--end', 'pkt-heading--light', 'pkt-heading--regular', 'pkt-heading--medium', 'pkt-heading--bold', ) // Add current classes this.classList.add('pkt-heading') if (this.size) this.classList.add(`pkt-heading--${this.size}`) if (this.weight) this.classList.add(`pkt-heading--fw-${this.weight}`) if (this.visuallyHidden) this.classList.add('pkt-sr-only') if (this.align) this.classList.add(`pkt-heading--${this.align}`) } render() { return html`<slot></slot>` } } try { customElement('pkt-heading')(PktHeading) } catch (e) { console.warn('Forsøker å definere <pkt-heading>, men den er allerede definert') }