second commit
This commit is contained in:
250
node_modules/flowbite-datepicker/js/picker/views/DaysView.js
generated
vendored
Normal file
250
node_modules/flowbite-datepicker/js/picker/views/DaysView.js
generated
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
import {hasProperty, pushUnique} from '../../lib/utils.js';
|
||||
import {today, dateValue, addDays, addWeeks, dayOfTheWeekOf, getWeek} from '../../lib/date.js';
|
||||
import {formatDate} from '../../lib/date-format.js';
|
||||
import {parseHTML, showElement, hideElement} from '../../lib/dom.js';
|
||||
import daysTemplate from '../templates/daysTemplate.js';
|
||||
import calendarWeeksTemplate from '../templates/calendarWeeksTemplate.js';
|
||||
import View from './View.js';
|
||||
|
||||
export default class DaysView extends View {
|
||||
constructor(picker) {
|
||||
super(picker, {
|
||||
id: 0,
|
||||
name: 'days',
|
||||
cellClass: 'day',
|
||||
});
|
||||
}
|
||||
|
||||
init(options, onConstruction = true) {
|
||||
if (onConstruction) {
|
||||
const inner = parseHTML(daysTemplate).firstChild;
|
||||
this.dow = inner.firstChild;
|
||||
this.grid = inner.lastChild;
|
||||
this.element.appendChild(inner);
|
||||
}
|
||||
super.init(options);
|
||||
}
|
||||
|
||||
setOptions(options) {
|
||||
let updateDOW;
|
||||
|
||||
if (hasProperty(options, 'minDate')) {
|
||||
this.minDate = options.minDate;
|
||||
}
|
||||
if (hasProperty(options, 'maxDate')) {
|
||||
this.maxDate = options.maxDate;
|
||||
}
|
||||
if (options.datesDisabled) {
|
||||
this.datesDisabled = options.datesDisabled;
|
||||
}
|
||||
if (options.daysOfWeekDisabled) {
|
||||
this.daysOfWeekDisabled = options.daysOfWeekDisabled;
|
||||
updateDOW = true;
|
||||
}
|
||||
if (options.daysOfWeekHighlighted) {
|
||||
this.daysOfWeekHighlighted = options.daysOfWeekHighlighted;
|
||||
}
|
||||
if (options.todayHighlight !== undefined) {
|
||||
this.todayHighlight = options.todayHighlight;
|
||||
}
|
||||
if (options.weekStart !== undefined) {
|
||||
this.weekStart = options.weekStart;
|
||||
this.weekEnd = options.weekEnd;
|
||||
updateDOW = true;
|
||||
}
|
||||
if (options.locale) {
|
||||
const locale = this.locale = options.locale;
|
||||
this.dayNames = locale.daysMin;
|
||||
this.switchLabelFormat = locale.titleFormat;
|
||||
updateDOW = true;
|
||||
}
|
||||
if (options.beforeShowDay !== undefined) {
|
||||
this.beforeShow = typeof options.beforeShowDay === 'function'
|
||||
? options.beforeShowDay
|
||||
: undefined;
|
||||
}
|
||||
|
||||
if (options.calendarWeeks !== undefined) {
|
||||
if (options.calendarWeeks && !this.calendarWeeks) {
|
||||
const weeksElem = parseHTML(calendarWeeksTemplate).firstChild;
|
||||
this.calendarWeeks = {
|
||||
element: weeksElem,
|
||||
dow: weeksElem.firstChild,
|
||||
weeks: weeksElem.lastChild,
|
||||
};
|
||||
this.element.insertBefore(weeksElem, this.element.firstChild);
|
||||
} else if (this.calendarWeeks && !options.calendarWeeks) {
|
||||
this.element.removeChild(this.calendarWeeks.element);
|
||||
this.calendarWeeks = null;
|
||||
}
|
||||
}
|
||||
if (options.showDaysOfWeek !== undefined) {
|
||||
if (options.showDaysOfWeek) {
|
||||
showElement(this.dow);
|
||||
if (this.calendarWeeks) {
|
||||
showElement(this.calendarWeeks.dow);
|
||||
}
|
||||
} else {
|
||||
hideElement(this.dow);
|
||||
if (this.calendarWeeks) {
|
||||
hideElement(this.calendarWeeks.dow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update days-of-week when locale, daysOfweekDisabled or weekStart is changed
|
||||
if (updateDOW) {
|
||||
Array.from(this.dow.children).forEach((el, index) => {
|
||||
const dow = (this.weekStart + index) % 7;
|
||||
el.textContent = this.dayNames[dow];
|
||||
el.className = this.daysOfWeekDisabled.includes(dow) ? 'dow disabled text-center h-6 leading-6 text-sm font-medium text-gray-500 dark:text-gray-400 cursor-not-allowed' : 'dow text-center h-6 leading-6 text-sm font-medium text-gray-500 dark:text-gray-400';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Apply update on the focused date to view's settings
|
||||
updateFocus() {
|
||||
const viewDate = new Date(this.picker.viewDate);
|
||||
const viewYear = viewDate.getFullYear();
|
||||
const viewMonth = viewDate.getMonth();
|
||||
const firstOfMonth = dateValue(viewYear, viewMonth, 1);
|
||||
const start = dayOfTheWeekOf(firstOfMonth, this.weekStart, this.weekStart);
|
||||
|
||||
this.first = firstOfMonth;
|
||||
this.last = dateValue(viewYear, viewMonth + 1, 0);
|
||||
this.start = start;
|
||||
this.focused = this.picker.viewDate;
|
||||
}
|
||||
|
||||
// Apply update on the selected dates to view's settings
|
||||
updateSelection() {
|
||||
const {dates, rangepicker} = this.picker.datepicker;
|
||||
this.selected = dates;
|
||||
if (rangepicker) {
|
||||
this.range = rangepicker.dates;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the entire view UI
|
||||
render() {
|
||||
// update today marker on ever render
|
||||
this.today = this.todayHighlight ? today() : undefined;
|
||||
// refresh disabled dates on every render in order to clear the ones added
|
||||
// by beforeShow hook at previous render
|
||||
this.disabled = [...this.datesDisabled];
|
||||
|
||||
const switchLabel = formatDate(this.focused, this.switchLabelFormat, this.locale);
|
||||
this.picker.setViewSwitchLabel(switchLabel);
|
||||
this.picker.setPrevBtnDisabled(this.first <= this.minDate);
|
||||
this.picker.setNextBtnDisabled(this.last >= this.maxDate);
|
||||
|
||||
if (this.calendarWeeks) {
|
||||
// start of the UTC week (Monday) of the 1st of the month
|
||||
const startOfWeek = dayOfTheWeekOf(this.first, 1, 1);
|
||||
Array.from(this.calendarWeeks.weeks.children).forEach((el, index) => {
|
||||
el.textContent = getWeek(addWeeks(startOfWeek, index));
|
||||
});
|
||||
}
|
||||
Array.from(this.grid.children).forEach((el, index) => {
|
||||
const classList = el.classList;
|
||||
const current = addDays(this.start, index);
|
||||
const date = new Date(current);
|
||||
const day = date.getDay();
|
||||
|
||||
el.className = `datepicker-cell hover:bg-gray-100 dark:hover:bg-gray-600 block flex-1 leading-9 border-0 rounded-lg cursor-pointer text-center text-gray-900 dark:text-white font-semibold text-sm ${this.cellClass}`;
|
||||
el.dataset.date = current;
|
||||
el.textContent = date.getDate();
|
||||
|
||||
if (current < this.first) {
|
||||
classList.add('prev', 'text-gray-500', 'dark:text-white');
|
||||
} else if (current > this.last) {
|
||||
classList.add('next', 'text-gray-500', 'dark:text-white');
|
||||
}
|
||||
if (this.today === current) {
|
||||
classList.add('today', 'bg-gray-100', 'dark:bg-gray-600');
|
||||
}
|
||||
if (current < this.minDate || current > this.maxDate || this.disabled.includes(current)) {
|
||||
classList.add('disabled', 'cursor-not-allowed', 'text-gray-400', 'dark:text-gray-500');
|
||||
classList.remove('hover:bg-gray-100', 'dark:hover:bg-gray-600', 'text-gray-900', 'dark:text-white', 'cursor-pointer');
|
||||
}
|
||||
if (this.daysOfWeekDisabled.includes(day)) {
|
||||
classList.add('disabled', 'cursor-not-allowed', 'text-gray-400', 'dark:text-gray-500');
|
||||
classList.remove('hover:bg-gray-100', 'dark:hover:bg-gray-600', 'text-gray-900', 'dark:text-white', 'cursor-pointer');
|
||||
pushUnique(this.disabled, current);
|
||||
}
|
||||
if (this.daysOfWeekHighlighted.includes(day)) {
|
||||
classList.add('highlighted');
|
||||
}
|
||||
if (this.range) {
|
||||
const [rangeStart, rangeEnd] = this.range;
|
||||
if (current > rangeStart && current < rangeEnd) {
|
||||
classList.add('range', 'bg-gray-200', 'dark:bg-gray-600');
|
||||
classList.remove('rounded-lg', 'rounded-l-lg', 'rounded-r-lg')
|
||||
}
|
||||
if (current === rangeStart) {
|
||||
classList.add('range-start', 'bg-gray-100', 'dark:bg-gray-600', 'rounded-l-lg');
|
||||
classList.remove('rounded-lg', 'rounded-r-lg');
|
||||
}
|
||||
if (current === rangeEnd) {
|
||||
classList.add('range-end', 'bg-gray-100', 'dark:bg-gray-600', 'rounded-r-lg');
|
||||
classList.remove('rounded-lg', 'rounded-l-lg');
|
||||
}
|
||||
}
|
||||
if (this.selected.includes(current)) {
|
||||
classList.add('selected', 'bg-blue-700', '!bg-primary-700', 'text-white', 'dark:bg-blue-600', 'dark:!bg-primary-600', 'dark:text-white');
|
||||
classList.remove('text-gray-900', 'text-gray-500', 'hover:bg-gray-100', 'dark:text-white', 'dark:hover:bg-gray-600', 'dark:bg-gray-600', 'bg-gray-100', 'bg-gray-200');
|
||||
}
|
||||
if (current === this.focused) {
|
||||
classList.add('focused');
|
||||
}
|
||||
|
||||
if (this.beforeShow) {
|
||||
this.performBeforeHook(el, current, current);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update the view UI by applying the changes of selected and focused items
|
||||
refresh() {
|
||||
const [rangeStart, rangeEnd] = this.range || [];
|
||||
this.grid
|
||||
.querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
|
||||
.forEach((el) => {
|
||||
el.classList.remove('range', 'range-start', 'range-end', 'selected', 'bg-blue-700', '!bg-primary-700', 'text-white', 'dark:bg-blue-600', 'dark:!bg-primary-600', 'dark:text-white', 'focused');
|
||||
el.classList.add('text-gray-900', 'rounded-lg', 'dark:text-white');
|
||||
});
|
||||
Array.from(this.grid.children).forEach((el) => {
|
||||
const current = Number(el.dataset.date);
|
||||
const classList = el.classList;
|
||||
classList.remove('bg-gray-200', 'dark:bg-gray-600', 'rounded-l-lg', 'rounded-r-lg')
|
||||
if (current > rangeStart && current < rangeEnd) {
|
||||
classList.add('range', 'bg-gray-200', 'dark:bg-gray-600');
|
||||
classList.remove('rounded-lg');
|
||||
}
|
||||
if (current === rangeStart) {
|
||||
classList.add('range-start', 'bg-gray-200', 'dark:bg-gray-600', 'rounded-l-lg');
|
||||
classList.remove('rounded-lg',);
|
||||
}
|
||||
if (current === rangeEnd) {
|
||||
classList.add('range-end', 'bg-gray-200', 'dark:bg-gray-600', 'rounded-r-lg');
|
||||
classList.remove('rounded-lg',);
|
||||
}
|
||||
if (this.selected.includes(current)) {
|
||||
classList.add('selected', 'bg-blue-700', '!bg-primary-700', 'text-white', 'dark:bg-blue-600', 'dark:!bg-primary-600', 'dark:text-white');
|
||||
classList.remove('text-gray-900', 'hover:bg-gray-100', 'dark:text-white', 'dark:hover:bg-gray-600', 'bg-gray-100', 'bg-gray-200', 'dark:bg-gray-600');
|
||||
}
|
||||
if (current === this.focused) {
|
||||
classList.add('focused');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update the view UI by applying the change of focused item
|
||||
refreshFocus() {
|
||||
const index = Math.round((this.focused - this.start) / 86400000);
|
||||
this.grid.querySelectorAll('.focused').forEach((el) => {
|
||||
el.classList.remove('focused');
|
||||
});
|
||||
this.grid.children[index].classList.add('focused');
|
||||
}
|
||||
}
|
198
node_modules/flowbite-datepicker/js/picker/views/MonthsView.js
generated
vendored
Normal file
198
node_modules/flowbite-datepicker/js/picker/views/MonthsView.js
generated
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
import {hasProperty, pushUnique, createTagRepeat} from '../../lib/utils.js';
|
||||
import {dateValue} from '../../lib/date.js';
|
||||
import {parseHTML} from '../../lib/dom.js';
|
||||
import View from './View.js';
|
||||
|
||||
function computeMonthRange(range, thisYear) {
|
||||
if (!range || !range[0] || !range[1]) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [[startY, startM], [endY, endM]] = range;
|
||||
if (startY > thisYear || endY < thisYear) {
|
||||
return;
|
||||
}
|
||||
return [
|
||||
startY === thisYear ? startM : -1,
|
||||
endY === thisYear ? endM : 12,
|
||||
];
|
||||
}
|
||||
|
||||
export default class MonthsView extends View {
|
||||
constructor(picker) {
|
||||
super(picker, {
|
||||
id: 1,
|
||||
name: 'months',
|
||||
cellClass: 'month',
|
||||
});
|
||||
}
|
||||
|
||||
init(options, onConstruction = true) {
|
||||
if (onConstruction) {
|
||||
this.grid = this.element;
|
||||
this.element.classList.add('months', 'datepicker-grid', 'w-64', 'grid', 'grid-cols-4');
|
||||
this.grid.appendChild(parseHTML(createTagRepeat('span', 12, {'data-month': ix => ix})));
|
||||
}
|
||||
super.init(options);
|
||||
}
|
||||
|
||||
setOptions(options) {
|
||||
if (options.locale) {
|
||||
this.monthNames = options.locale.monthsShort;
|
||||
}
|
||||
if (hasProperty(options, 'minDate')) {
|
||||
if (options.minDate === undefined) {
|
||||
this.minYear = this.minMonth = this.minDate = undefined;
|
||||
} else {
|
||||
const minDateObj = new Date(options.minDate);
|
||||
this.minYear = minDateObj.getFullYear();
|
||||
this.minMonth = minDateObj.getMonth();
|
||||
this.minDate = minDateObj.setDate(1);
|
||||
}
|
||||
}
|
||||
if (hasProperty(options, 'maxDate')) {
|
||||
if (options.maxDate === undefined) {
|
||||
this.maxYear = this.maxMonth = this.maxDate = undefined;
|
||||
} else {
|
||||
const maxDateObj = new Date(options.maxDate);
|
||||
this.maxYear = maxDateObj.getFullYear();
|
||||
this.maxMonth = maxDateObj.getMonth();
|
||||
this.maxDate = dateValue(this.maxYear, this.maxMonth + 1, 0);
|
||||
}
|
||||
}
|
||||
if (options.beforeShowMonth !== undefined) {
|
||||
this.beforeShow = typeof options.beforeShowMonth === 'function'
|
||||
? options.beforeShowMonth
|
||||
: undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Update view's settings to reflect the viewDate set on the picker
|
||||
updateFocus() {
|
||||
const viewDate = new Date(this.picker.viewDate);
|
||||
this.year = viewDate.getFullYear();
|
||||
this.focused = viewDate.getMonth();
|
||||
}
|
||||
|
||||
// Update view's settings to reflect the selected dates
|
||||
updateSelection() {
|
||||
const {dates, rangepicker} = this.picker.datepicker;
|
||||
this.selected = dates.reduce((selected, timeValue) => {
|
||||
const date = new Date(timeValue);
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth();
|
||||
if (selected[year] === undefined) {
|
||||
selected[year] = [month];
|
||||
} else {
|
||||
pushUnique(selected[year], month);
|
||||
}
|
||||
return selected;
|
||||
}, {});
|
||||
if (rangepicker && rangepicker.dates) {
|
||||
this.range = rangepicker.dates.map(timeValue => {
|
||||
const date = new Date(timeValue);
|
||||
return isNaN(date) ? undefined : [date.getFullYear(), date.getMonth()];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Update the entire view UI
|
||||
render() {
|
||||
// refresh disabled months on every render in order to clear the ones added
|
||||
// by beforeShow hook at previous render
|
||||
this.disabled = [];
|
||||
|
||||
this.picker.setViewSwitchLabel(this.year);
|
||||
this.picker.setPrevBtnDisabled(this.year <= this.minYear);
|
||||
this.picker.setNextBtnDisabled(this.year >= this.maxYear);
|
||||
|
||||
const selected = this.selected[this.year] || [];
|
||||
const yrOutOfRange = this.year < this.minYear || this.year > this.maxYear;
|
||||
const isMinYear = this.year === this.minYear;
|
||||
const isMaxYear = this.year === this.maxYear;
|
||||
const range = computeMonthRange(this.range, this.year);
|
||||
|
||||
Array.from(this.grid.children).forEach((el, index) => {
|
||||
const classList = el.classList;
|
||||
const date = dateValue(this.year, index, 1);
|
||||
|
||||
el.className = `datepicker-cell hover:bg-gray-100 dark:hover:bg-gray-600 block flex-1 leading-9 border-0 rounded-lg cursor-pointer text-center text-gray-900 dark:text-white font-semibold text-sm ${this.cellClass}`;
|
||||
if (this.isMinView) {
|
||||
el.dataset.date = date;
|
||||
}
|
||||
// reset text on every render to clear the custom content set
|
||||
// by beforeShow hook at previous render
|
||||
el.textContent = this.monthNames[index];
|
||||
|
||||
if (
|
||||
yrOutOfRange
|
||||
|| isMinYear && index < this.minMonth
|
||||
|| isMaxYear && index > this.maxMonth
|
||||
) {
|
||||
classList.add('disabled');
|
||||
}
|
||||
if (range) {
|
||||
const [rangeStart, rangeEnd] = range;
|
||||
if (index > rangeStart && index < rangeEnd) {
|
||||
classList.add('range');
|
||||
}
|
||||
if (index === rangeStart) {
|
||||
classList.add('range-start');
|
||||
}
|
||||
if (index === rangeEnd) {
|
||||
classList.add('range-end');
|
||||
}
|
||||
}
|
||||
if (selected.includes(index)) {
|
||||
classList.add('selected', 'bg-blue-700', '!bg-primary-700', 'text-white', 'dark:bg-blue-600', 'dark:!bg-primary-600', 'dark:text-white');
|
||||
classList.remove('text-gray-900', 'hover:bg-gray-100', 'dark:text-white', 'dark:hover:bg-gray-600');
|
||||
}
|
||||
if (index === this.focused) {
|
||||
classList.add('focused');
|
||||
}
|
||||
|
||||
if (this.beforeShow) {
|
||||
this.performBeforeHook(el, index, date);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update the view UI by applying the changes of selected and focused items
|
||||
refresh() {
|
||||
const selected = this.selected[this.year] || [];
|
||||
const [rangeStart, rangeEnd] = computeMonthRange(this.range, this.year) || [];
|
||||
this.grid
|
||||
.querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
|
||||
.forEach((el) => {
|
||||
el.classList.remove('range', 'range-start', 'range-end', 'selected', 'bg-blue-700', '!bg-primary-700', 'dark:bg-blue-600', 'dark:!bg-primary-700', 'dark:text-white', 'text-white', 'focused');
|
||||
el.classList.add('text-gray-900', 'hover:bg-gray-100', 'dark:text-white', 'dark:hover:bg-gray-600');
|
||||
});
|
||||
Array.from(this.grid.children).forEach((el, index) => {
|
||||
const classList = el.classList;
|
||||
if (index > rangeStart && index < rangeEnd) {
|
||||
classList.add('range');
|
||||
}
|
||||
if (index === rangeStart) {
|
||||
classList.add('range-start');
|
||||
}
|
||||
if (index === rangeEnd) {
|
||||
classList.add('range-end');
|
||||
}
|
||||
if (selected.includes(index)) {
|
||||
classList.add('selected', 'bg-blue-700', '!bg-primary-700', 'text-white', 'dark:bg-blue-600', 'dark:!bg-primary-600', 'dark:text-white');
|
||||
classList.remove('text-gray-900', 'hover:bg-gray-100', 'dark:text-white', 'dark:hover:bg-gray-600');
|
||||
}
|
||||
if (index === this.focused) {
|
||||
classList.add('focused');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update the view UI by applying the change of focused item
|
||||
refreshFocus() {
|
||||
this.grid.querySelectorAll('.focused').forEach((el) => {
|
||||
el.classList.remove('focused');
|
||||
});
|
||||
this.grid.children[this.focused].classList.add('focused');
|
||||
}
|
||||
}
|
55
node_modules/flowbite-datepicker/js/picker/views/View.js
generated
vendored
Normal file
55
node_modules/flowbite-datepicker/js/picker/views/View.js
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
import {pushUnique} from '../../lib/utils.js';
|
||||
import {parseHTML, replaceChildNodes} from '../../lib/dom.js';
|
||||
|
||||
// Base class of the view classes
|
||||
export default class View {
|
||||
constructor(picker, config) {
|
||||
Object.assign(this, config, {
|
||||
picker,
|
||||
element: parseHTML(`<div class="datepicker-view flex"></div>`).firstChild,
|
||||
selected: [],
|
||||
});
|
||||
this.init(this.picker.datepicker.config);
|
||||
}
|
||||
|
||||
init(options) {
|
||||
if (options.pickLevel !== undefined) {
|
||||
this.isMinView = this.id === options.pickLevel;
|
||||
}
|
||||
this.setOptions(options);
|
||||
this.updateFocus();
|
||||
this.updateSelection();
|
||||
}
|
||||
|
||||
// Execute beforeShow() callback and apply the result to the element
|
||||
// args:
|
||||
// - current - current value on the iteration on view rendering
|
||||
// - timeValue - time value of the date to pass to beforeShow()
|
||||
performBeforeHook(el, current, timeValue) {
|
||||
let result = this.beforeShow(new Date(timeValue));
|
||||
switch (typeof result) {
|
||||
case 'boolean':
|
||||
result = {enabled: result};
|
||||
break;
|
||||
case 'string':
|
||||
result = {classes: result};
|
||||
}
|
||||
|
||||
if (result) {
|
||||
if (result.enabled === false) {
|
||||
el.classList.add('disabled');
|
||||
pushUnique(this.disabled, current);
|
||||
}
|
||||
if (result.classes) {
|
||||
const extraClasses = result.classes.split(/\s+/);
|
||||
el.classList.add(...extraClasses);
|
||||
if (extraClasses.includes('disabled')) {
|
||||
pushUnique(this.disabled, current);
|
||||
}
|
||||
}
|
||||
if (result.content) {
|
||||
replaceChildNodes(el, result.content);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
170
node_modules/flowbite-datepicker/js/picker/views/YearsView.js
generated
vendored
Normal file
170
node_modules/flowbite-datepicker/js/picker/views/YearsView.js
generated
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
import {hasProperty, pushUnique, createTagRepeat} from '../../lib/utils.js';
|
||||
import {dateValue, startOfYearPeriod} from '../../lib/date.js';
|
||||
import {parseHTML} from '../../lib/dom.js';
|
||||
import View from './View.js';
|
||||
|
||||
function toTitleCase(word) {
|
||||
return [...word].reduce((str, ch, ix) => str += ix ? ch : ch.toUpperCase(), '');
|
||||
}
|
||||
|
||||
// Class representing the years and decades view elements
|
||||
export default class YearsView extends View {
|
||||
constructor(picker, config) {
|
||||
super(picker, config);
|
||||
}
|
||||
|
||||
init(options, onConstruction = true) {
|
||||
if (onConstruction) {
|
||||
this.navStep = this.step * 10;
|
||||
this.beforeShowOption = `beforeShow${toTitleCase(this.cellClass)}`;
|
||||
this.grid = this.element;
|
||||
this.element.classList.add(this.name, 'datepicker-grid', 'w-64', 'grid', 'grid-cols-4');
|
||||
this.grid.appendChild(parseHTML(createTagRepeat('span', 12)));
|
||||
}
|
||||
super.init(options);
|
||||
}
|
||||
|
||||
setOptions(options) {
|
||||
if (hasProperty(options, 'minDate')) {
|
||||
if (options.minDate === undefined) {
|
||||
this.minYear = this.minDate = undefined;
|
||||
} else {
|
||||
this.minYear = startOfYearPeriod(options.minDate, this.step);
|
||||
this.minDate = dateValue(this.minYear, 0, 1);
|
||||
}
|
||||
}
|
||||
if (hasProperty(options, 'maxDate')) {
|
||||
if (options.maxDate === undefined) {
|
||||
this.maxYear = this.maxDate = undefined;
|
||||
} else {
|
||||
this.maxYear = startOfYearPeriod(options.maxDate, this.step);
|
||||
this.maxDate = dateValue(this.maxYear, 11, 31);
|
||||
}
|
||||
}
|
||||
if (options[this.beforeShowOption] !== undefined) {
|
||||
const beforeShow = options[this.beforeShowOption];
|
||||
this.beforeShow = typeof beforeShow === 'function' ? beforeShow : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Update view's settings to reflect the viewDate set on the picker
|
||||
updateFocus() {
|
||||
const viewDate = new Date(this.picker.viewDate);
|
||||
const first = startOfYearPeriod(viewDate, this.navStep);
|
||||
const last = first + 9 * this.step;
|
||||
|
||||
this.first = first;
|
||||
this.last = last;
|
||||
this.start = first - this.step;
|
||||
this.focused = startOfYearPeriod(viewDate, this.step);
|
||||
}
|
||||
|
||||
// Update view's settings to reflect the selected dates
|
||||
updateSelection() {
|
||||
const {dates, rangepicker} = this.picker.datepicker;
|
||||
this.selected = dates.reduce((years, timeValue) => {
|
||||
return pushUnique(years, startOfYearPeriod(timeValue, this.step));
|
||||
}, []);
|
||||
if (rangepicker && rangepicker.dates) {
|
||||
this.range = rangepicker.dates.map(timeValue => {
|
||||
if (timeValue !== undefined) {
|
||||
return startOfYearPeriod(timeValue, this.step);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Update the entire view UI
|
||||
render() {
|
||||
// refresh disabled years on every render in order to clear the ones added
|
||||
// by beforeShow hook at previous render
|
||||
this.disabled = [];
|
||||
|
||||
this.picker.setViewSwitchLabel(`${this.first}-${this.last}`);
|
||||
this.picker.setPrevBtnDisabled(this.first <= this.minYear);
|
||||
this.picker.setNextBtnDisabled(this.last >= this.maxYear);
|
||||
|
||||
Array.from(this.grid.children).forEach((el, index) => {
|
||||
const classList = el.classList;
|
||||
const current = this.start + (index * this.step);
|
||||
const date = dateValue(current, 0, 1);
|
||||
|
||||
el.className = `datepicker-cell hover:bg-gray-100 dark:hover:bg-gray-600 block flex-1 leading-9 border-0 rounded-lg cursor-pointer text-center text-gray-900 dark:text-white font-semibold text-sm ${this.cellClass}`;
|
||||
if (this.isMinView) {
|
||||
el.dataset.date = date;
|
||||
}
|
||||
el.textContent = el.dataset.year = current;
|
||||
|
||||
if (index === 0) {
|
||||
classList.add('prev');
|
||||
} else if (index === 11) {
|
||||
classList.add('next');
|
||||
}
|
||||
if (current < this.minYear || current > this.maxYear) {
|
||||
classList.add('disabled');
|
||||
}
|
||||
if (this.range) {
|
||||
const [rangeStart, rangeEnd] = this.range;
|
||||
if (current > rangeStart && current < rangeEnd) {
|
||||
classList.add('range');
|
||||
}
|
||||
if (current === rangeStart) {
|
||||
classList.add('range-start');
|
||||
}
|
||||
if (current === rangeEnd) {
|
||||
classList.add('range-end');
|
||||
}
|
||||
}
|
||||
if (this.selected.includes(current)) {
|
||||
classList.add('selected', 'bg-blue-700', '!bg-primary-700', 'text-white', 'dark:bg-blue-600', 'dark:!bg-primary-600', 'dark:text-white');
|
||||
classList.remove('text-gray-900', 'hover:bg-gray-100', 'dark:text-white', 'dark:hover:bg-gray-600');
|
||||
}
|
||||
if (current === this.focused) {
|
||||
classList.add('focused');
|
||||
}
|
||||
|
||||
if (this.beforeShow) {
|
||||
this.performBeforeHook(el, current, date);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update the view UI by applying the changes of selected and focused items
|
||||
refresh() {
|
||||
const [rangeStart, rangeEnd] = this.range || [];
|
||||
this.grid
|
||||
.querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
|
||||
.forEach((el) => {
|
||||
el.classList.remove('range', 'range-start', 'range-end', 'selected', 'bg-blue-700', '!bg-primary-700', 'text-white', 'dark:bg-blue-600', 'dark!bg-primary-600', 'dark:text-white', 'focused');
|
||||
});
|
||||
Array.from(this.grid.children).forEach((el) => {
|
||||
const current = Number(el.textContent);
|
||||
const classList = el.classList;
|
||||
if (current > rangeStart && current < rangeEnd) {
|
||||
classList.add('range');
|
||||
}
|
||||
if (current === rangeStart) {
|
||||
classList.add('range-start');
|
||||
}
|
||||
if (current === rangeEnd) {
|
||||
classList.add('range-end');
|
||||
}
|
||||
if (this.selected.includes(current)) {
|
||||
classList.add('selected', 'bg-blue-700', '!bg-primary-700', 'text-white', 'dark:bg-blue-600', 'dark:!bg-primary-600', 'dark:text-white');
|
||||
classList.remove('text-gray-900', 'hover:bg-gray-100', 'dark:text-white', 'dark:hover:bg-gray-600');
|
||||
}
|
||||
if (current === this.focused) {
|
||||
classList.add('focused');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update the view UI by applying the change of focused item
|
||||
refreshFocus() {
|
||||
const index = Math.round((this.focused - this.start) / this.step);
|
||||
this.grid.querySelectorAll('.focused').forEach((el) => {
|
||||
el.classList.remove('focused');
|
||||
});
|
||||
this.grid.children[index].classList.add('focused');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user