2025-07-13 15:23:24 -04:00
|
|
|
|
import React from 'react';
|
|
|
|
|
import './Calendar.scss';
|
|
|
|
|
import {jdnDate} from '@common/gregorian';
|
|
|
|
|
import {jdnLongCount} from '@common/longCount';
|
|
|
|
|
import {MonthBasedCalendar} from '@common/ui/MonthBasedCalendar';
|
2025-07-13 15:35:04 -04:00
|
|
|
|
import {
|
2025-07-13 15:44:15 -04:00
|
|
|
|
formatLordOfNight, formatTzolkin,
|
2025-07-13 15:35:04 -04:00
|
|
|
|
HaabDay,
|
|
|
|
|
haabExtJDN,
|
|
|
|
|
HaabMonth,
|
|
|
|
|
haabMonthDays,
|
|
|
|
|
haabNames,
|
|
|
|
|
HaabYear,
|
|
|
|
|
jdnHaabExt,
|
2025-07-13 15:44:15 -04:00
|
|
|
|
jdnLordOfNight, jdnTzolkin,
|
2025-07-13 15:35:04 -04:00
|
|
|
|
} from '@common/mayan';
|
2025-07-14 00:19:03 -04:00
|
|
|
|
import {useMobileTooltipProps} from '@common/ui/MobileTooltip';
|
2025-07-13 15:23:24 -04:00
|
|
|
|
|
|
|
|
|
type MonthProps = {
|
2025-07-13 15:35:04 -04:00
|
|
|
|
year: HaabYear;
|
|
|
|
|
month: HaabMonth;
|
2025-07-13 15:23:24 -04:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type DateProps = MonthProps & {
|
2025-07-13 15:35:04 -04:00
|
|
|
|
day: HaabDay;
|
2025-07-13 15:23:24 -04:00
|
|
|
|
};
|
|
|
|
|
|
2025-07-13 15:44:15 -04:00
|
|
|
|
function Day({year, month, day, todayJDN}: DateProps & { todayJDN: number }): JSX.Element {
|
2025-07-13 15:35:04 -04:00
|
|
|
|
const jdn = haabExtJDN({year, month, day});
|
2025-07-14 00:19:03 -04:00
|
|
|
|
const mobile = useMobileTooltipProps();
|
2025-07-13 15:23:24 -04:00
|
|
|
|
return <div className={`Day ${jdn === todayJDN ? 'Day-today' : ''}`}>
|
2025-07-13 15:44:15 -04:00
|
|
|
|
<div className="Day-name">{day}<span className="Day-haabMonth"> {haabNames[month]}</span></div>
|
2025-07-14 00:19:03 -04:00
|
|
|
|
<div className="Day-tzolkin">
|
|
|
|
|
<abbr title="Tzolkʼin" {...mobile}>T.</abbr> {formatTzolkin(jdnTzolkin(jdn))}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="Day-lc">
|
|
|
|
|
<abbr title="Long count" {...mobile}>L.</abbr> {jdnLongCount(jdn)?.join('.')}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="Day-lordOfNight">
|
|
|
|
|
<abbr title="Lord of the Night" {...mobile}>N.</abbr> {formatLordOfNight(jdnLordOfNight(jdn))
|
|
|
|
|
}</div>
|
|
|
|
|
<div className="Day-gregorian">
|
|
|
|
|
<abbr title="Gregorian date" {...mobile}>G.</abbr> {jdnDate(jdn).toDateString()}
|
|
|
|
|
</div>
|
2025-07-13 15:23:24 -04:00
|
|
|
|
</div>;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-13 15:35:04 -04:00
|
|
|
|
function Month({year, month, todayJDN}: MonthProps & { todayJDN: number }): JSX.Element {
|
2025-07-13 15:23:24 -04:00
|
|
|
|
return <div className="Month">
|
|
|
|
|
<div className="Month-days">{
|
2025-07-13 15:44:15 -04:00
|
|
|
|
Array.from(Array(haabMonthDays(month)).keys()).map(i => <div key={i} className="DayOuter">
|
|
|
|
|
<Day year={year} month={month} day={i + 1 as HaabDay} todayJDN={todayJDN}/>
|
2025-07-13 15:23:24 -04:00
|
|
|
|
</div>)
|
|
|
|
|
}</div>
|
|
|
|
|
</div>;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-13 15:35:04 -04:00
|
|
|
|
export class Calendar extends MonthBasedCalendar<HaabYear, HaabMonth> {
|
|
|
|
|
override parseYear(year: string): HaabYear {
|
2025-07-13 15:23:24 -04:00
|
|
|
|
return +year;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-13 15:35:04 -04:00
|
|
|
|
override parseMonth(month: string): HaabMonth {
|
|
|
|
|
return +month as HaabMonth;
|
2025-07-13 15:23:24 -04:00
|
|
|
|
}
|
|
|
|
|
|
2025-07-13 15:35:04 -04:00
|
|
|
|
override yearToString(year: HaabYear): string {
|
2025-07-13 15:23:24 -04:00
|
|
|
|
return year.toString();
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-13 15:35:04 -04:00
|
|
|
|
override monthToString(month: HaabMonth): string {
|
2025-07-13 15:23:24 -04:00
|
|
|
|
return month.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private goToNormalized(year: number, month: number) {
|
|
|
|
|
while (month < 1) {
|
|
|
|
|
--year;
|
2025-07-13 15:35:04 -04:00
|
|
|
|
month += 19;
|
2025-07-13 15:23:24 -04:00
|
|
|
|
}
|
|
|
|
|
|
2025-07-13 15:35:04 -04:00
|
|
|
|
while (month > 19) {
|
2025-07-13 15:23:24 -04:00
|
|
|
|
++year;
|
2025-07-13 15:35:04 -04:00
|
|
|
|
month -= 19;
|
2025-07-13 15:23:24 -04:00
|
|
|
|
}
|
|
|
|
|
|
2025-07-13 15:35:04 -04:00
|
|
|
|
this.goTo(year, month as HaabMonth);
|
2025-07-13 15:23:24 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override prevYear = () => {
|
|
|
|
|
this.goToNormalized(this.props.year - 1, this.props.month);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
override prevMonth = () => {
|
|
|
|
|
this.goToNormalized(this.props.year, this.props.month - 1);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
override nextYear = () => {
|
|
|
|
|
this.goToNormalized(this.props.year + 1, this.props.month);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
override nextMonth = () => {
|
|
|
|
|
this.goToNormalized(this.props.year, this.props.month + 1);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
override isValidYear(year: string): boolean {
|
|
|
|
|
return /^-?\d+/.test(year);
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-13 15:35:04 -04:00
|
|
|
|
override jdnLookup(jdn: number): { year: HaabYear; month: HaabMonth } {
|
|
|
|
|
return jdnHaabExt(jdn);
|
2025-07-13 15:23:24 -04:00
|
|
|
|
}
|
|
|
|
|
|
2025-07-13 15:35:04 -04:00
|
|
|
|
override monthName(year: HaabYear, month: HaabMonth): string {
|
|
|
|
|
return `${haabNames[month]} ${year}`;
|
2025-07-13 15:23:24 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override renderMonthOptions(): JSX.Element[] {
|
2025-07-13 15:35:04 -04:00
|
|
|
|
return Array.from(Array(19).keys()).map(i => {
|
|
|
|
|
const month = i + 1 as HaabMonth;
|
|
|
|
|
return <option key={i} value={month}>{haabNames[month]}</option>;
|
2025-07-13 15:23:24 -04:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override renderBody(): JSX.Element {
|
2025-07-13 15:35:04 -04:00
|
|
|
|
return <Month year={this.props.year} month={this.props.month} todayJDN={this.props.todayJDN}/>;
|
2025-07-13 15:23:24 -04:00
|
|
|
|
}
|
|
|
|
|
}
|