import { html, TemplateResult } from 'lit' import { property } from 'lit/decorators.js' import { Ref, createRef } from 'lit/directives/ref.js' import { classMap } from 'lit/directives/class-map.js' import { PktElement } from '@/base-elements/element' import { cssUtils } from './datepicker-utils' import { IDatepickerStrings } from './datepicker-types' import type { TPktInputSize } from 'shared-types/size' import '@/components/icon' /** * Abstract base class for datepicker input components * * Consolidates shared properties, methods, and event dispatchers * used by all three datepicker input types (single, multiple, range). * * Subclasses must implement: * - `strings` property with component-specific defaults * - `render()` method with component-specific template */ export abstract class PktDatepickerBase extends PktElement { // Shared properties (9 identical across all sub-components) @property({ type: String }) inputType: string = 'date' @property({ type: String }) id: string = '' @property({ type: String }) min?: string @property({ type: String }) max?: string @property({ type: String }) placeholder?: string @property({ type: Boolean }) readonly: boolean = false @property({ type: Boolean }) disabled: boolean = false @property({ type: Object }) inputClasses: Record = {} @property({ type: String }) inputSize: TPktInputSize = 'medium' @property({ type: Object }) internals?: ElementInternals // Abstract property - must be implemented by subclasses abstract strings: IDatepickerStrings // Shared refs inputRef: Ref = createRef() btnRef: Ref = createRef() // Shared getters get inputElement(): HTMLInputElement | undefined { return this.inputRef.value } get buttonElement(): HTMLButtonElement | undefined { return this.btnRef.value } get isInputReadonly(): boolean { return this.readonly || this.inputType === 'text' } // Shared event dispatchers (protected so subclasses can use them) protected dispatchToggleCalendar(e: Event): void { if (this.readonly) return this.dispatchEvent( new CustomEvent('toggle-calendar', { detail: e, bubbles: true, composed: true, }), ) } protected dispatchInput(e: Event): void { this.dispatchEvent( new CustomEvent('input-change', { detail: e, bubbles: true, composed: true, }), ) } protected dispatchFocus(): void { this.dispatchEvent( new CustomEvent('input-focus', { bubbles: true, composed: true, }), ) } protected dispatchBlur(e: FocusEvent): void { this.dispatchEvent( new CustomEvent('input-blur', { detail: e, bubbles: true, composed: true, }), ) } protected dispatchChange(e: Event): void { this.dispatchEvent( new CustomEvent('input-changed', { detail: e, bubbles: true, composed: true, }), ) } // Shared render helper for calendar button protected renderCalendarButton(): TemplateResult { return html` ` } // Shared method - no shadow DOM createRenderRoot() { return this } // Abstract render method - must be implemented by subclasses abstract render(): TemplateResult }