import { PktElement } from '@/base-elements/element' import { html, nothing, type PropertyValues } from 'lit' import { customElement, property, state } from 'lit/decorators.js' import { classMap } from 'lit/directives/class-map.js' import { ifDefined } from 'lit/directives/if-defined.js' import { FocusModalityController } from '@/controllers/focus-modality-controller' import '@/components/icon' import type { IPktSearchInput, IPktSearchInputSuggestion, TPktSearchInputAppearance, TPktSearchInputMethod, } from 'shared-types/searchinput' import type { TPktInputSize } from 'shared-types/size' export type { IPktSearchInput, IPktSearchInputSuggestion, TPktSearchInputAppearance, TPktSearchInputMethod, } from 'shared-types/searchinput' export class PktSearchInput extends PktElement implements IPktSearchInput { @property({ type: String }) appearance: TPktSearchInputAppearance = 'local' @property({ type: String, attribute: 'input-size' }) inputSize: TPktInputSize = 'medium' @property({ type: Boolean, reflect: true }) disabled: boolean = false @property({ type: Boolean, reflect: true }) fullwidth: boolean = false @property({ type: String, reflect: true }) id: string = '' @property({ type: String }) label: string | undefined @property({ type: String }) name: string | undefined @property({ type: String }) placeholder: string = 'Søk…' @property({ type: String }) value: string = '' @property({ type: Array }) suggestions: IPktSearchInputSuggestion[] | undefined @property({ type: String }) action: string | undefined @property({ type: String }) method: TPktSearchInputMethod | undefined focusModality = new FocusModalityController(this, '.pkt-searchinput') @state() private inputAriaLabel?: string override willUpdate(changed: PropertyValues): void { super.willUpdate(changed) const hostLabel = this.getAttribute('aria-label') if (hostLabel) { this.inputAriaLabel = hostLabel this.removeAttribute('aria-label') } } private get suggestionsId() { return `${this.id}-suggestions` } private dispatchSearch(): void { this.dispatchEvent( new CustomEvent('pkt-search', { detail: { value: this.value }, bubbles: true, composed: true, }), ) } private onInput(event: InputEvent): void { const target = event.target as HTMLInputElement this.value = target.value } private onInputKeydown(event: KeyboardEvent): void { if (event.key !== 'Enter') return // With an `action`, let the form submit natively (Enter triggers submit). if (!this.action) event.preventDefault() this.dispatchSearch() } private onSearchClick(event: Event): void { // With an `action`, let the submit button submit the form natively. if (!this.action) event.preventDefault() this.dispatchSearch() } private onSuggestionClick( event: Event, suggestion: IPktSearchInputSuggestion, index: number, ): void { const customEvent = new CustomEvent('pkt-suggestion-click', { detail: { index, suggestion, }, bubbles: true, composed: true, cancelable: true, }) const allowed = this.dispatchEvent(customEvent) if (!allowed) { event.preventDefault() } } private renderSuggestion(suggestion: IPktSearchInputSuggestion, index: number) { const suggestionContent = html` ${suggestion.title ? html`

${suggestion.title}

` : nothing} ${suggestion.text ? html`

${suggestion.text}

` : nothing} ` if (suggestion.href) { return html` this.onSuggestionClick(event, suggestion, index)} > ${suggestionContent} ` } if (suggestion.nonInteractive) { return html`
${suggestionContent}
` } return html`` } render() { const wrapperClasses = classMap({ 'pkt-searchinput': true, [`pkt-searchinput--${this.appearance}`]: true, [`pkt-searchinput--${this.inputSize}`]: true, 'pkt-searchinput--fullwidth': this.fullwidth, }) const buttonClasses = classMap({ 'pkt-searchinput__button': true, 'pkt-input-icon': this.appearance === 'local', 'pkt-btn': true, [`pkt-btn--${this.inputSize}`]: true, 'pkt-btn--icon-only': true, 'pkt-btn--tertiary': this.appearance === 'local', 'pkt-btn--primary': this.appearance === 'global' || this.appearance === 'local-with-button', 'pkt-btn--yellow': this.appearance === 'global', }) const inputClasses = classMap({ 'pkt-input': true, [`pkt-input--${this.inputSize}`]: true, 'pkt-input--fullwidth': this.fullwidth, }) const fieldClass = this.appearance === 'local' ? `pkt-input__container pkt-input__container--${this.inputSize}` : 'pkt-searchinput__field' const body = html` ${this.label ? html`` : nothing}
${this.suggestions ? html`` : nothing} ` if (this.action) { return html`` } return html`` } } export default PktSearchInput try { customElement('pkt-searchinput')(PktSearchInput) } catch (e) { console.warn('Forsøker å definere , men den er allerede definert') }