// Mockup https://www.figma.com/design/zsq2ahat30acTnumyy9aqC/00.Small-System?node-id=1235-8660&m=dev import { LitElement, css, html, nothing, unsafeCSS } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import "~icons/mdi-light/chevron-double-left"; import "~icons/mdi-light/chevron-double-right"; import "~icons/mdi-light/chevron-left"; import "~icons/mdi-light/chevron-right"; import ComponentStyle from "@styles/forms/tems-datepicker.scss?inline"; export type TemsDatepickerProps = { value: Date; }; @customElement("tems-datepicker") export class TemsDatepicker extends LitElement { static styles = css` ${unsafeCSS(ComponentStyle)} `; @property({ type: Date }) value: TemsDatepickerProps["value"] = new Date(); @state() private currentMonth: number = this.value.getMonth(); @state() private currentYear: number = this.value.getFullYear(); private getDaysInMonth(month: number, year: number): number { return new Date(year, month + 1, 0).getDate(); } private getFirstDayOfMonth(month: number, year: number): number { return new Date(year, month, 1).getDay(); } private goToPreviousMonth() { this.currentMonth--; if (this.currentMonth < 0) { this.currentMonth = 11; this.currentYear--; } } private goToNextMonth() { this.currentMonth++; if (this.currentMonth > 11) { this.currentMonth = 0; this.currentYear++; } } private goToPreviousYear() { this.currentYear--; } private goToNextYear() { this.currentYear++; } private selectDate(day: number) { this.value = new Date(this.currentYear, this.currentMonth, day); this._emitChangeEvent(); } private selectPrevMonthDay(day: number) { const prevMonth = new Date(this.currentYear, this.currentMonth - 1); const year = prevMonth.getFullYear(); const month = prevMonth.getMonth(); this.value = new Date(year, month, day); this.currentMonth = month; this.currentYear = year; this._emitChangeEvent(); } private selectNextMonthDay(day: number) { const nextMonth = new Date(this.currentYear, this.currentMonth + 1); const year = nextMonth.getFullYear(); const month = nextMonth.getMonth(); this.value = new Date(year, month, day); this.currentMonth = month; this.currentYear = year; this._emitChangeEvent(); } private _emitChangeEvent() { this.dispatchEvent( new CustomEvent("change", { detail: { value: this.value, }, }), ); } render() { const daysInMonth = this.getDaysInMonth( this.currentMonth, this.currentYear, ); const firstDayOfMonth = this.getFirstDayOfMonth( this.currentMonth, this.currentYear, ); const dayNames = Array.from({ length: 7 }, (_, i) => new Date(1970, 0, i + 4) .toLocaleDateString("en-US", { weekday: "short" }) .substring(0, 2), ); let day = 1; return html`
${new Date(this.currentYear, this.currentMonth, 1).toLocaleDateString( "en-US", { month: "long", year: "numeric", }, )}
${dayNames.map( (dayName) => html``, )} ${Array(firstDayOfMonth) .fill(null) .map((_, index) => { const prevMonthDay = new Date(this.currentYear, this.currentMonth, 0).getDate() - firstDayOfMonth + index + 1; return html` this.selectPrevMonthDay(prevMonthDay)} >`; })} ${Array(daysInMonth) .fill(null) .map(() => { const tempDay = day; day++; const isSelected = this.value.getDate() === tempDay && this.value.getMonth() === this.currentMonth && this.value.getFullYear() === this.currentYear; return html` this.selectDate(tempDay)} > `; })} ${Array(42 - firstDayOfMonth - daysInMonth) .fill(null) .map((_, index) => { const nextMonthDay = index + 1; return html` this.selectNextMonthDay(nextMonthDay)} >`; })}
`; } }