@oslokommune/punkt-elements
Version:
Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo
87 lines (77 loc) • 2.77 kB
text/typescript
import { PktShadowElement } from '@/base-elements/element'
import { html, PropertyValues } from 'lit'
import { customElement, property } from 'lit/decorators.js'
export type TPktHeadingLevel = 1 | 2 | 3 | 4 | 5 | 6
export type TPktHeadingSize = 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge'
export interface IPktHeading {
size?: TPktHeadingSize
level?: TPktHeadingLevel
visuallyHidden?: boolean
align?: 'start' | 'center' | 'end'
}
('pkt-heading')
export class PktHeading extends PktShadowElement<IPktHeading> implements IPktHeading {
({ type: String, reflect: true }) size: TPktHeadingSize = 'medium'
({ type: Number, reflect: true }) level: TPktHeadingLevel = 2
({ type: Boolean, reflect: true }) visuallyHidden: boolean = false
({ type: String, reflect: true }) align: 'start' | 'center' | 'end' = 'start'
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 === 'size' || name === 'visuallyHidden' || name === 'align') {
this.updateHostClasses()
}
}
protected updated(_changedProperties: PropertyValues): void {
super.updated(_changedProperties)
if (_changedProperties.has('level')) {
this.setLevel(this.level)
}
if (
_changedProperties.has('size') ||
_changedProperties.has('visuallyHidden') ||
_changedProperties.has('align')
) {
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 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',
)
// Add current classes
this.classList.add('pkt-heading')
if (this.size) this.classList.add(`pkt-heading--${this.size}`)
if (this.visuallyHidden) this.classList.add('pkt-sr-only')
if (this.align) this.classList.add(`pkt-heading--${this.align}`)
}
render() {
return html`<slot></slot>`
}
}