import flatpickr from 'flatpickr' const datePickerHelper = (config) => { const { allowInput, defaultDate, disableDate, disableRange, disableWeekdays, format, maxDate, minDate, mode, onChange, pickerId, yearRange, } = config // =========================================================== // | Hook Definitions | // =========================================================== const defaultDateGetter = () => { if (defaultDate !== '') { if (defaultDate === 'blank') { return '' } else { return defaultDate } } if (mode === 'single' && defaultDate === '') { return new Date() } else if (mode === 'range' && defaultDate === '') { const today = new Date() const tomorrow = new Date(today) tomorrow.setDate(tomorrow.getDate() + 1) return [today, tomorrow] } } 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 = '' } } // =========================================================== // | Flatpickr initializer w/ config | // =========================================================== flatpickr(`#${pickerId}`, { disableMobile: true, dateFormat: format, 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(), maxDate: maxDate, minDate: minDate, mode: mode, nextArrow: '', onOpen: [() => { calendarResizer() window.addEventListener('resize', calendarResizer) }], onClose: [() => { window.removeEventListener('resize', calendarResizer) }], onChange: [(selectedDates, dateStr) => { onChange(dateStr, selectedDates) }], onYearChange: [], 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 selecttor 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)) }) // two way binding const yearChangeHook = () => { dropdown.value = picker.currentYear } picker.config.onYearChange.push(yearChangeHook) // Adding dropdown icons to year and month selects picker.monthElements[0].insertAdjacentHTML('afterend', '') dropdown.insertAdjacentHTML('afterend', '') // Set input value attribute on page load picker.input.setAttribute('value', picker.input.value) // logic for updating value when typing document.querySelector(`#${pickerId}`).addEventListener('input', (e) => { picker.input.setAttribute('value', e.target.value) const variant = picker.config.mode if (variant === 'single' && e.target.value.split('').length === 10) { picker.setDate(e.target.value) dropdown.value = picker.currentYear } else if (variant === 'range' && e.target.value.split('').length === 24) { picker.setDate(e.target.value) dropdown.value = picker.currentYear } }) if (allowInput){ picker.input.removeAttribute('readonly') } } export default datePickerHelper