line_push/node_modules/vuetify/lib/components/VCalendar/VCalendar.js
2022-07-17 13:16:16 +08:00

390 lines
9.3 KiB
JavaScript

// Styles
// import '../../stylus/components/_calendar-daily.styl'
// Mixins
import CalendarWithEvents from './mixins/calendar-with-events'; // Util
import props from './util/props';
import { DAYS_IN_MONTH_MAX, DAY_MIN, DAYS_IN_WEEK, parseTimestamp, validateTimestamp, relativeDays, nextDay, prevDay, copyTimestamp, updateFormatted, updateWeekday, updateRelative, getStartOfMonth, getEndOfMonth, timestampToDate } from './util/timestamp'; // Calendars
import VCalendarMonthly from './VCalendarMonthly';
import VCalendarDaily from './VCalendarDaily';
import VCalendarWeekly from './VCalendarWeekly';
import VCalendarCategory from './VCalendarCategory';
/* @vue/component */
export default CalendarWithEvents.extend({
name: 'v-calendar',
props: { ...props.calendar,
...props.weeks,
...props.intervals,
...props.category
},
data: () => ({
lastStart: null,
lastEnd: null
}),
computed: {
parsedValue() {
return validateTimestamp(this.value) ? parseTimestamp(this.value, true) : this.parsedStart || this.times.today;
},
parsedCategoryDays() {
return parseInt(this.categoryDays) || 1;
},
renderProps() {
const around = this.parsedValue;
let component = null;
let maxDays = this.maxDays;
let weekdays = this.parsedWeekdays;
let categories = this.parsedCategories;
let start = around;
let end = around;
switch (this.type) {
case 'month':
component = VCalendarMonthly;
start = getStartOfMonth(around);
end = getEndOfMonth(around);
break;
case 'week':
component = VCalendarDaily;
start = this.getStartOfWeek(around);
end = this.getEndOfWeek(around);
maxDays = 7;
break;
case 'day':
component = VCalendarDaily;
maxDays = 1;
weekdays = [start.weekday];
break;
case '4day':
component = VCalendarDaily;
end = relativeDays(copyTimestamp(end), nextDay, 4);
updateFormatted(end);
maxDays = 4;
weekdays = [start.weekday, (start.weekday + 1) % 7, (start.weekday + 2) % 7, (start.weekday + 3) % 7];
break;
case 'custom-weekly':
component = VCalendarWeekly;
start = this.parsedStart || around;
end = this.parsedEnd;
break;
case 'custom-daily':
component = VCalendarDaily;
start = this.parsedStart || around;
end = this.parsedEnd;
break;
case 'category':
const days = this.parsedCategoryDays;
component = VCalendarCategory;
end = relativeDays(copyTimestamp(end), nextDay, days);
updateFormatted(end);
maxDays = days;
weekdays = [];
for (let i = 0; i < days; i++) {
weekdays.push((start.weekday + i) % 7);
}
categories = this.getCategoryList(categories);
break;
default:
throw new Error(this.type + ' is not a valid Calendar type');
}
return {
component,
start,
end,
maxDays,
weekdays,
categories
};
},
eventWeekdays() {
return this.renderProps.weekdays;
},
categoryMode() {
return this.type === 'category';
},
title() {
const {
start,
end
} = this.renderProps;
const spanYears = start.year !== end.year;
const spanMonths = spanYears || start.month !== end.month;
if (spanYears) {
return this.monthShortFormatter(start, true) + ' ' + start.year + ' - ' + this.monthShortFormatter(end, true) + ' ' + end.year;
}
if (spanMonths) {
return this.monthShortFormatter(start, true) + ' - ' + this.monthShortFormatter(end, true) + ' ' + end.year;
} else {
return this.monthLongFormatter(start, false) + ' ' + start.year;
}
},
monthLongFormatter() {
return this.getFormatter({
timeZone: 'UTC',
month: 'long'
});
},
monthShortFormatter() {
return this.getFormatter({
timeZone: 'UTC',
month: 'short'
});
},
parsedCategories() {
return typeof this.categories === 'string' && this.categories ? this.categories.split(/\s*,\s*/) : Array.isArray(this.categories) ? this.categories : [];
}
},
watch: {
renderProps: 'checkChange'
},
mounted() {
this.updateEventVisibility();
this.checkChange();
},
updated() {
window.requestAnimationFrame(this.updateEventVisibility);
},
methods: {
checkChange() {
const {
lastStart,
lastEnd
} = this;
const {
start,
end
} = this.renderProps;
if (!lastStart || !lastEnd || start.date !== lastStart.date || end.date !== lastEnd.date) {
this.lastStart = start;
this.lastEnd = end;
this.$emit('change', {
start,
end
});
}
},
move(amount = 1) {
const moved = copyTimestamp(this.parsedValue);
const forward = amount > 0;
const mover = forward ? nextDay : prevDay;
const limit = forward ? DAYS_IN_MONTH_MAX : DAY_MIN;
let times = forward ? amount : -amount;
while (--times >= 0) {
switch (this.type) {
case 'month':
moved.day = limit;
mover(moved);
break;
case 'week':
relativeDays(moved, mover, DAYS_IN_WEEK);
break;
case 'day':
relativeDays(moved, mover, 1);
break;
case '4day':
relativeDays(moved, mover, 4);
break;
case 'category':
relativeDays(moved, mover, this.parsedCategoryDays);
break;
}
}
updateWeekday(moved);
updateFormatted(moved);
updateRelative(moved, this.times.now);
if (this.value instanceof Date) {
this.$emit('input', timestampToDate(moved));
} else if (typeof this.value === 'number') {
this.$emit('input', timestampToDate(moved).getTime());
} else {
this.$emit('input', moved.date);
}
this.$emit('moved', moved);
},
next(amount = 1) {
this.move(amount);
},
prev(amount = 1) {
this.move(-amount);
},
timeToY(time, clamp = true) {
const c = this.$children[0];
if (c && c.timeToY) {
return c.timeToY(time, clamp);
} else {
return false;
}
},
timeDelta(time) {
const c = this.$children[0];
if (c && c.timeDelta) {
return c.timeDelta(time);
} else {
return false;
}
},
minutesToPixels(minutes) {
const c = this.$children[0];
if (c && c.minutesToPixels) {
return c.minutesToPixels(minutes);
} else {
return -1;
}
},
scrollToTime(time) {
const c = this.$children[0];
if (c && c.scrollToTime) {
return c.scrollToTime(time);
} else {
return false;
}
},
parseTimestamp(input, required) {
return parseTimestamp(input, required, this.times.now);
},
timestampToDate(timestamp) {
return timestampToDate(timestamp);
},
getCategoryList(categories) {
if (!this.noEvents) {
const categoryMap = categories.reduce((map, category, index) => {
map[category] = {
index,
count: 0
};
return map;
}, Object.create(null));
if (!this.categoryHideDynamic || !this.categoryShowAll) {
let categoryLength = categories.length;
this.parsedEvents.forEach(ev => {
let category = ev.category;
if (typeof category !== 'string') {
category = this.categoryForInvalid;
}
if (!category) {
return;
}
if (category in categoryMap) {
categoryMap[category].count++;
} else if (!this.categoryHideDynamic) {
categoryMap[category] = {
index: categoryLength++,
count: 1
};
}
});
}
if (!this.categoryShowAll) {
for (const category in categoryMap) {
if (categoryMap[category].count === 0) {
delete categoryMap[category];
}
}
}
categories = Object.keys(categoryMap);
}
return categories;
}
},
render(h) {
const {
start,
end,
maxDays,
component,
weekdays,
categories
} = this.renderProps;
return h(component, {
staticClass: 'v-calendar',
class: {
'v-calendar-events': !this.noEvents
},
props: { ...this.$props,
start: start.date,
end: end.date,
maxDays,
weekdays,
categories
},
directives: [{
modifiers: {
quiet: true
},
name: 'resize',
value: this.updateEventVisibility
}],
on: { ...this.$listeners,
'click:date': day => {
if (this.$listeners['input']) {
this.$emit('input', day.date);
}
if (this.$listeners['click:date']) {
this.$emit('click:date', day);
}
}
},
scopedSlots: this.getScopedSlots()
});
}
});
//# sourceMappingURL=VCalendar.js.map