diff --git a/src/Calendar.scss b/src/Calendar.scss
index fd95545..d5c7920 100644
--- a/src/Calendar.scss
+++ b/src/Calendar.scss
@@ -1,6 +1,7 @@
@import 'bootstrap/scss/functions';
@import 'bootstrap/scss/variables';
@import 'bootstrap/scss/mixins';
+@import 'bootstrap/scss/forms';
@import 'bootstrap/scss/grid';
@import 'bootstrap/scss/buttons';
@@ -111,3 +112,20 @@
.Day-today {
background: $gray-300;
}
+
+.Calendar-month-name.input-group {
+ justify-content: center;
+ font-size: 0.75em;
+}
+
+.Calendar-month-input {
+ max-width: 12.5em;
+}
+
+.Calendar-year-input {
+ max-width: 6em;
+}
+
+.Calendar-today-button {
+ max-width: 5em;
+}
diff --git a/src/Calendar.tsx b/src/Calendar.tsx
index 3e20cf5..f0760b8 100644
--- a/src/Calendar.tsx
+++ b/src/Calendar.tsx
@@ -1,6 +1,17 @@
import React from 'react';
import './Calendar.scss';
-import {dateName, Day, decadeNames, frIsLeap, frJDN, jdnGregorian, jdnLongCount, Month, monthName} from './dates';
+import {
+ dateName,
+ Day,
+ decadeNames,
+ frIsLeap,
+ frJDN,
+ jdnFrench,
+ jdnGregorian,
+ jdnLongCount,
+ Month,
+ monthName
+} from './dates';
type MonthProps = {
year: number;
@@ -11,13 +22,6 @@ type DateProps = MonthProps & {
day: Day;
};
-export type CalendarProps = MonthProps & {
- todayJDN: number;
- onSwitch?: (year: number, month: Month) => void,
-};
-
-type CalendarState = {};
-
function DecadeName({name}: { name: string }): JSX.Element {
return
{name}
;
}
@@ -61,7 +65,7 @@ function ComplementaryDay({year, month, day, todayJDN}: DateProps & { todayJDN:
;
}
-function ComplementaryDays({year, todayJDN}: {year: number, todayJDN: number}): JSX.Element {
+function ComplementaryDays({year, todayJDN}: { year: number, todayJDN: number }): JSX.Element {
return {
Array.from(Array(frIsLeap(year) ? 6 : 5).keys()).map(i => <>
@@ -70,7 +74,37 @@ function ComplementaryDays({year, todayJDN}: {year: number, todayJDN: number}):
}
;
}
+export type CalendarProps = MonthProps & {
+ todayJDN: number;
+ onSwitch?: (year: number, month: Month) => void,
+};
+
+type CalendarState = {
+ selecting: boolean,
+ yearStr: string,
+};
+
export class Calendar extends React.Component {
+ selection: React.RefObject;
+
+ constructor(props: CalendarProps) {
+ super(props);
+ this.state = {
+ selecting: false,
+ yearStr: this.props.year.toString(),
+ };
+ this.selection = React.createRef();
+ this.handleClickOutside = this.handleClickOutside.bind(this);
+ }
+
+ componentDidMount() {
+ document.addEventListener('click', this.handleClickOutside, true);
+ }
+
+ componentWillUnmount() {
+ document.removeEventListener('click', this.handleClickOutside, true);
+ }
+
private goToNormalized(year: number, month: number) {
if (month < 1) {
--year;
@@ -101,6 +135,49 @@ export class Calendar extends React.Component {
this.goToNormalized(this.props.year, this.props.month + 1);
}
+ startSelection() {
+ this.setState({selecting: true});
+ }
+
+ handleClickOutside(event: any) {
+ if (this.state.selecting && this.selection.current && !this.selection.current.contains(event.target))
+ this.setState({selecting: false});
+ }
+
+ handleKeyUp(event: any) {
+ if (event.key === 'Escape')
+ this.setState({selecting: false});
+ }
+
+ monthChange(event: any) {
+ this.props.onSwitch && this.props.onSwitch(this.props.year, event.target.value as Month);
+ }
+
+ yearChange(event: any) {
+ console.log(/^-?\d+/.test(event.target.value));
+ if (/^-?\d+/.test(event.target.value)) {
+ this.props.onSwitch && this.props.onSwitch(+event.target.value, this.props.month);
+ }
+ this.setState({yearStr: event.target.value});
+ }
+
+ componentDidUpdate(prevProps: CalendarProps) {
+ if (prevProps.year !== this.props.year) {
+ const yearStr = this.props.year.toString();
+ if (this.state.yearStr !== yearStr) {
+ this.setState({
+ yearStr: yearStr,
+ });
+ }
+ }
+ }
+
+ goToToday() {
+ const {year, month} = jdnFrench(this.props.todayJDN);
+ this.goToNormalized(year, month);
+ this.setState({selecting: false});
+ }
+
render(): JSX.Element {
return
@@ -112,9 +189,24 @@ export class Calendar extends React.Component {
onClick={this.prevMonth.bind(this)}>‹
-
+ {!this.state.selecting &&
{this.props.month < 13 && monthName(this.props.month)} {this.props.year}
-
+
}
+ {this.state.selecting &&
+
+
+
+
}
- {this.props.month < 13 && }
+ {this.props.month < 13 &&
+ }
{this.props.month === 13 && }
;
}