Created
January 15, 2022 16:09
-
-
Save ksassnowski/8629ff5ee8ced9984d997f93bba772c4 to your computer and use it in GitHub Desktop.
Datepicker Framework, I guess
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {computed, ref} from "vue"; | |
import { | |
addMonths, addYears, | |
eachDayOfInterval, | |
endOfISOWeek, | |
getYear, | |
getDate, | |
isSameMonth, | |
startOfISOWeek, | |
startOfMonth, | |
subMonths, | |
subYears, addWeeks, startOfYear, endOfYear, eachMonthOfInterval, format, isSameDay, | |
} from "date-fns"; | |
interface Day { | |
date: Date; | |
number: number; | |
active: boolean; | |
currentMonth: boolean; | |
} | |
interface Month { | |
date: Date; | |
label: string; | |
active: boolean; | |
} | |
enum ViewMode { | |
Days, | |
Months, | |
Years, | |
} | |
function getVisibleDays(selectedDate: Date, startOfCurrentMonth: Date): Day[] { | |
const startDate = startOfISOWeek(startOfCurrentMonth); | |
const endDate = endOfISOWeek(addWeeks(startDate, 5)); | |
return eachDayOfInterval({ | |
start: startDate, | |
end: endDate | |
}).map((day: Date) => ({ | |
date: day, | |
number: getDate(day), | |
active: isSameDay(day, selectedDate), | |
currentMonth: isSameMonth(day, startOfCurrentMonth), | |
})); | |
} | |
function getVisibleMonths(startOfCurrentYear: Date, startOfCurrentMonth: Date): Month[] { | |
const startDate = startOfCurrentYear; | |
const endDate = endOfYear(startOfCurrentYear); | |
return eachMonthOfInterval({ | |
start: startDate, | |
end: endDate, | |
}).map(month => ({ | |
date: month, | |
label: format(month, 'MMMM'), | |
active: isSameMonth(month, startOfCurrentMonth), | |
})); | |
} | |
export default function (initialDate?: Date|string|number) { | |
const visible = ref(false); | |
const selectedDate = ref(initialDate ? new Date(initialDate) : new Date()); | |
const startOfCurrentMonth = ref(startOfMonth(selectedDate.value)); | |
const currentYear = computed(() => getYear(startOfCurrentMonth.value)); | |
const visibleDays = computed(() => getVisibleDays(selectedDate.value, startOfCurrentMonth.value)); | |
const visibleMonths = computed(() => getVisibleMonths( | |
startOfYear(startOfCurrentMonth.value), | |
startOfCurrentMonth.value) | |
); | |
const viewMode = ref(ViewMode.Days); | |
const showingDays = computed(() => viewMode.value === ViewMode.Days); | |
const showingMonths = computed(() => viewMode.value === ViewMode.Months); | |
return { | |
selectedDate, | |
currentYear, | |
visibleDays, | |
visibleMonths, | |
visible, | |
startOfCurrentMonth, | |
showingDays, | |
showingMonths, | |
open() { | |
visible.value = true; | |
}, | |
close() { | |
visible.value = false; | |
}, | |
toggle() { | |
visible.value = !visible.value; | |
}, | |
select(date: Date, close: boolean = false) { | |
selectedDate.value = date; | |
startOfCurrentMonth.value = startOfMonth(date) | |
if (close) { | |
visible.value = false; | |
} | |
}, | |
showMonths() { | |
viewMode.value = ViewMode.Months; | |
}, | |
selectMonth(month: Month) { | |
startOfCurrentMonth.value = month.date; | |
viewMode.value = ViewMode.Days; | |
}, | |
nextMonth() { | |
startOfCurrentMonth.value = startOfMonth(addMonths(startOfCurrentMonth.value, 1)); | |
}, | |
previousMonth() { | |
startOfCurrentMonth.value = startOfMonth(subMonths(startOfCurrentMonth.value, 1)); | |
}, | |
nextYear() { | |
startOfCurrentMonth.value = startOfMonth(addYears(startOfCurrentMonth.value, 1)); | |
}, | |
previousYear() { | |
startOfCurrentMonth.value = startOfMonth(subYears(startOfCurrentMonth.value, 1)); | |
}, | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
And then build a component on top of that. Boom, instant date picker.
Note, the point is not to use this component but that you can build whatever UI you want on top of it.
(This is still incomplete, like the
ViewState.Year
isn’t even used anywhere, but you get the point)https://play.tailwindcss.com/P73Vdh29uV