import flatpickr from 'flatpickr'
import monthSelectPlugin from 'flatpickr/dist/plugins/monthSelect'
import weekSelect from "flatpickr/dist/plugins/weekSelect/weekSelect"
import timeSelectPlugin from './plugins/timeSelect'
const datePickerHelper = (config) => {
const {
allowInput,
defaultDate,
disableDate,
disableRange,
disableWeekdays,
enableTime,
format,
maxDate,
minDate,
mode,
onChange = () => {},
pickerId,
plugins,
required,
selectionType,
showTimezone,
timeCaption = 'Select Time',
timeFormat = 'at h:i K',
yearRange,
} = config
// ===========================================================
// | Hook Definitions |
// ===========================================================
const defaultDateGetter = () => {
if (defaultDate === '') {
return null
} else {
return defaultDate
}
}
const disabledParser = () => {
if (disableDate && disableDate.length > 0) {
return disableDate
} else if (disableRange && disableRange.length > 0) {
return disableRange
} else {
return []
}
}
const calendarResizer = () => {
const cal = document.querySelector(`#cal-${pickerId}.open`)
const parentInput = cal.parentElement
if (cal.getBoundingClientRect().right > window.innerWidth) {
parentInput.style.display = 'flex'
parentInput.style.justifyContent = 'center'
}
if (cal.offsetWidth <= parentInput.offsetWidth) {
parentInput.style.display = ''
parentInput.style.justifyContent = ''
}
}
const setPlugins = () => {
let pluginList = []
// month and week selection
if (selectionType === "month" || plugins === true) {
pluginList.push(monthSelectPlugin({ shorthand: true, dateFormat: 'F Y', altFormat: 'F Y' }))
} else if ( selectionType === "week") {
pluginList.push(weekSelect({}))
}
// time selection
if (enableTime) pluginList.push(timeSelectPlugin({ caption: timeCaption, showTimezone: showTimezone}))
return pluginList
}
const getDateFormat = () => {
return enableTime ? `${format} ${timeFormat}` : format
}
// ===========================================================
// | Flatpickr initializer w/ config |
// ===========================================================
flatpickr(`#${pickerId}`, {
disableMobile: true,
dateFormat: getDateFormat(),
defaultDate: defaultDateGetter(),
disable: disableWeekdays && disableWeekdays.length > 0 ? [
(date) => {
const weekdayObj = {
Sunday: 0,
Monday: 1,
Tuesday: 2,
Wednesday: 3,
Thursday: 4,
Friday: 5,
Saturday: 6,
}
return (
date.getDay() === weekdayObj[disableWeekdays[0]] ||
date.getDay() === weekdayObj[disableWeekdays[1]] ||
date.getDay() === weekdayObj[disableWeekdays[2]] ||
date.getDay() === weekdayObj[disableWeekdays[3]] ||
date.getDay() === weekdayObj[disableWeekdays[4]] ||
date.getDay() === weekdayObj[disableWeekdays[5]] ||
date.getDay() === weekdayObj[disableWeekdays[6]]
)
},
] : disabledParser(),
enableTime,
maxDate,
minDate,
mode,
nextArrow: '',
onOpen: [() => {
calendarResizer()
window.addEventListener('resize', calendarResizer)
}],
onClose: [() => {
window.removeEventListener('resize', calendarResizer)
}],
onChange: [(selectedDates, dateStr) => {
onChange(dateStr, selectedDates)
}],
onYearChange: [() => {
yearChangeHook()
}],
plugins: setPlugins(),
prevArrow: '',
static: true,
})
// ===========================================================
// Additional JS Functionality |
// ===========================================================
// Assign dynamically sourced flatpickr instance to variable
const picker = document.querySelector(`#${pickerId}`)._flatpickr
picker.innerContainer.parentElement.id = `cal-${pickerId}`
// replace year selector with dropdown
picker.yearElements[0].parentElement.innerHTML = ``
// create html option tags for desired years
let years = ''
for (let year = yearRange[1]; year >= yearRange[0]; year--) {
years += ``
}
// variablize each dropdown selector
const dropdown = document.querySelector(`#year-${pickerId}`)
// inject year options into dropdown and assign it the flatpickr's current year value
dropdown.innerHTML = years
dropdown.value = picker.currentYear
// whenever a new year is selected from dropdown update flatpickr's current year value
dropdown.addEventListener('input', (e) => {
picker.changeYear(Number(e.target.value))
})
// Reverse month and year dropdown reset on form.reset()
if (picker.input.form) {
picker.input.form.addEventListener('reset', () => {
// Code block triggers after form.reset() is called and executed
setTimeout(() => {
dropdown.value = picker.currentYear
picker.monthsDropdownContainer.value = picker.currentMonth
/* Reset date picker to default value on form.reset() */
if (defaultDate){
picker.setDate(defaultDate)
yearChangeHook()
}
}, 0)
})
}
// two way binding
const yearChangeHook = () => {
dropdown.value = picker.currentYear
}
// Adding dropdown icons to year and month selects
dropdown.insertAdjacentHTML('afterend', '')
if (picker.monthElements[0].parentElement) {
return picker.monthElements[0].insertAdjacentHTML('afterend', '')}
// if (picker.weekElements[0].parentElement){
// return picker.weekElements[0].insertAdjacentHTML('afterend', '')
// }
// Remove readonly attribute for validation and or text input
if (allowInput){
picker.input.removeAttribute('readonly')
}
if (required){
picker.input.removeAttribute('readonly')
picker.input.addEventListener('keydown', (e) => e.preventDefault())
picker.input.style.caretColor = 'transparent'
picker.input.style.cursor = 'pointer'
}
// Fix event bubbling bug on wrapper
document.querySelector(`#${pickerId}`).parentElement.addEventListener('click', (e) => e.stopPropagation())
}
export default datePickerHelper