routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+330
@@ -0,0 +1,330 @@
|
||||
import { mergeProps as _mergeProps, createVNode as _createVNode, withDirectives as _withDirectives } from "vue";
|
||||
// Styles
|
||||
import "./VCalendarCategory.css";
|
||||
import "./VCalendarDaily.css";
|
||||
import "./VCalendarWeekly.css";
|
||||
|
||||
// Components
|
||||
import { VCalendarCategory } from "./VCalendarCategory.js";
|
||||
import { VCalendarDaily } from "./VCalendarDaily.js";
|
||||
import { VCalendarWeekly } from "./VCalendarWeekly.js"; // Composables
|
||||
import { makeCalendarBaseProps } from "./composables/calendarBase.js";
|
||||
import { makeCalendarWithEventsProps, useCalendarWithEvents } from "./composables/calendarWithEvents.js";
|
||||
import { forwardRefs } from "../../composables/forwardRefs.js"; // Directives
|
||||
import vResize from "../../directives/resize/index.js"; // Utilities
|
||||
import { computed, onMounted, onUpdated, ref, watch } from 'vue';
|
||||
import { getParsedCategories } from "./util/parser.js";
|
||||
import { copyTimestamp, DAY_MIN, DAYS_IN_MONTH_MAX, DAYS_IN_WEEK, getEndOfMonth, getStartOfMonth, nextDay, prevDay, relativeDays, timestampToDate, updateFormatted, updateRelative, updateWeekday, validateTimestamp } from "./util/timestamp.js";
|
||||
import { genericComponent, useRender } from "../../util/index.js"; // Types
|
||||
// Types
|
||||
export const VCalendar = genericComponent()({
|
||||
name: 'VCalendar',
|
||||
directives: {
|
||||
vResize
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: [String, Number, Date],
|
||||
validate: validateTimestamp
|
||||
},
|
||||
categoryDays: {
|
||||
type: [Number, String],
|
||||
default: 1,
|
||||
validate: x => isFinite(parseInt(x)) && parseInt(x) > 0
|
||||
},
|
||||
categories: {
|
||||
type: [Array, String],
|
||||
default: ''
|
||||
},
|
||||
categoryText: {
|
||||
type: [String, Function]
|
||||
},
|
||||
maxDays: {
|
||||
type: Number,
|
||||
default: 7
|
||||
},
|
||||
categoryHideDynamic: {
|
||||
type: Boolean
|
||||
},
|
||||
categoryShowAll: {
|
||||
type: Boolean
|
||||
},
|
||||
categoryForInvalid: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
...makeCalendarBaseProps(),
|
||||
...makeCalendarWithEventsProps()
|
||||
},
|
||||
setup(props, {
|
||||
slots,
|
||||
attrs,
|
||||
emit
|
||||
}) {
|
||||
const root = ref();
|
||||
const base = useCalendarWithEvents(props, slots, attrs);
|
||||
const lastStart = ref(null);
|
||||
const lastEnd = ref(null);
|
||||
const parsedCategoryDays = computed(() => {
|
||||
return parseInt(String(props.categoryDays)) || 1;
|
||||
});
|
||||
const parsedCategories = computed(() => {
|
||||
return getParsedCategories(props.categories, props.categoryText);
|
||||
});
|
||||
const renderProps = computed(() => {
|
||||
const around = base.parsedValue.value;
|
||||
let component = null;
|
||||
let maxDays = props.maxDays;
|
||||
let categories = parsedCategories.value;
|
||||
let start = around;
|
||||
let end = around;
|
||||
switch (props.type) {
|
||||
case 'month':
|
||||
component = VCalendarWeekly;
|
||||
start = getStartOfMonth(around);
|
||||
end = getEndOfMonth(around);
|
||||
break;
|
||||
case 'week':
|
||||
component = VCalendarDaily;
|
||||
start = base.getStartOfWeek(around);
|
||||
end = base.getEndOfWeek(around);
|
||||
maxDays = 7;
|
||||
break;
|
||||
case 'day':
|
||||
component = VCalendarDaily;
|
||||
maxDays = 1;
|
||||
break;
|
||||
case '4day':
|
||||
component = VCalendarDaily;
|
||||
end = relativeDays(copyTimestamp(end), nextDay, 3);
|
||||
updateFormatted(end);
|
||||
maxDays = 4;
|
||||
break;
|
||||
case 'custom-weekly':
|
||||
component = VCalendarWeekly;
|
||||
start = base.parsedStart.value || around;
|
||||
end = base.parsedEnd.value;
|
||||
break;
|
||||
case 'custom-daily':
|
||||
component = VCalendarDaily;
|
||||
start = base.parsedStart.value || around;
|
||||
end = base.parsedEnd.value;
|
||||
break;
|
||||
case 'category':
|
||||
const days = parsedCategoryDays.value;
|
||||
component = VCalendarCategory;
|
||||
end = relativeDays(copyTimestamp(end), nextDay, days);
|
||||
updateFormatted(end);
|
||||
maxDays = days;
|
||||
categories = getCategoryList(categories);
|
||||
break;
|
||||
default:
|
||||
const type = props.type;
|
||||
throw new Error(`${type} is not a valid Calendar type`);
|
||||
}
|
||||
return {
|
||||
component,
|
||||
start,
|
||||
end,
|
||||
maxDays,
|
||||
categories
|
||||
};
|
||||
});
|
||||
const eventWeekdays = computed(() => {
|
||||
return base.effectiveWeekdays.value;
|
||||
});
|
||||
const categoryMode = computed(() => {
|
||||
return props.type === 'category';
|
||||
});
|
||||
const monthLongFormatter = computed(() => {
|
||||
return base.getFormatter({
|
||||
timeZone: 'UTC',
|
||||
month: 'long'
|
||||
});
|
||||
});
|
||||
const monthShortFormatter = computed(() => {
|
||||
return base.getFormatter({
|
||||
timeZone: 'UTC',
|
||||
month: 'short'
|
||||
});
|
||||
});
|
||||
const title = computed(() => {
|
||||
const {
|
||||
start,
|
||||
end
|
||||
} = renderProps.value;
|
||||
const spanYears = start.year !== end.year;
|
||||
const spanMonths = spanYears || start.month !== end.month;
|
||||
if (spanYears) {
|
||||
return monthShortFormatter.value(start, true) + ' ' + start.year + ' - ' + monthShortFormatter.value(end, true) + ' ' + end.year;
|
||||
}
|
||||
if (spanMonths) {
|
||||
return monthShortFormatter.value(start, true) + ' - ' + monthShortFormatter.value(end, true) + ' ' + end.year;
|
||||
} else {
|
||||
return monthLongFormatter.value(start, false) + ' ' + start.year;
|
||||
}
|
||||
});
|
||||
function checkChange() {
|
||||
const {
|
||||
start,
|
||||
end
|
||||
} = renderProps.value;
|
||||
if (!lastStart.value || !lastEnd.value || start.date !== lastStart.value.date || end.date !== lastEnd.value.date) {
|
||||
lastStart.value = start;
|
||||
lastEnd.value = end;
|
||||
emit('change', {
|
||||
start,
|
||||
end
|
||||
});
|
||||
}
|
||||
}
|
||||
function move(amount = 1) {
|
||||
const moved = copyTimestamp(base.parsedValue.value);
|
||||
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 (props.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, parsedCategoryDays.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
updateWeekday(moved);
|
||||
updateFormatted(moved);
|
||||
updateRelative(moved, base.times.now);
|
||||
if (props.modelValue instanceof Date) {
|
||||
emit('update:modelValue', timestampToDate(moved));
|
||||
} else if (typeof props.modelValue === 'number') {
|
||||
emit('update:modelValue', timestampToDate(moved).getTime());
|
||||
} else {
|
||||
emit('update:modelValue', moved.date);
|
||||
}
|
||||
emit('moved', moved);
|
||||
}
|
||||
function next(amount = 1) {
|
||||
move(amount);
|
||||
}
|
||||
function prev(amount = 1) {
|
||||
move(-amount);
|
||||
}
|
||||
function getCategoryList(categories) {
|
||||
if (!base.noEvents.value) {
|
||||
const categoryMap = categories.reduce((map, category, index) => {
|
||||
if (typeof category === 'object' && category.categoryName) map[category.categoryName] = {
|
||||
index,
|
||||
count: 0
|
||||
};else if (typeof category === 'string') map[category] = {
|
||||
index,
|
||||
count: 0
|
||||
};
|
||||
return map;
|
||||
}, {});
|
||||
if (!props.categoryHideDynamic || !props.categoryShowAll) {
|
||||
let categoryLength = categories.length;
|
||||
base.parsedEvents.value.forEach(ev => {
|
||||
let category = ev.category;
|
||||
if (typeof category !== 'string') {
|
||||
category = props.categoryForInvalid;
|
||||
}
|
||||
if (!category) {
|
||||
return;
|
||||
}
|
||||
if (category in categoryMap) {
|
||||
categoryMap[category].count++;
|
||||
} else if (!props.categoryHideDynamic) {
|
||||
categoryMap[category] = {
|
||||
index: categoryLength++,
|
||||
count: 1
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!props.categoryShowAll) {
|
||||
for (const category in categoryMap) {
|
||||
if (categoryMap[category].count === 0) {
|
||||
delete categoryMap[category];
|
||||
}
|
||||
}
|
||||
}
|
||||
categories = categories.filter(category => {
|
||||
if (typeof category === 'object' && category.categoryName) {
|
||||
return categoryMap.hasOwnProperty(category.categoryName);
|
||||
} else if (typeof category === 'string') {
|
||||
return categoryMap.hasOwnProperty(category);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
return categories;
|
||||
}
|
||||
watch(renderProps, checkChange);
|
||||
onMounted(() => {
|
||||
base.updateEventVisibility();
|
||||
checkChange();
|
||||
});
|
||||
onUpdated(() => {
|
||||
window.requestAnimationFrame(base.updateEventVisibility);
|
||||
});
|
||||
useRender(() => {
|
||||
const {
|
||||
start,
|
||||
end,
|
||||
maxDays,
|
||||
component: Component,
|
||||
categories
|
||||
} = renderProps.value;
|
||||
return _withDirectives(_createVNode(Component, _mergeProps({
|
||||
"ref": root,
|
||||
"class": ['v-calendar', {
|
||||
'v-calendar-events': !base.noEvents.value
|
||||
}],
|
||||
"role": "grid"
|
||||
}, Component.filterProps(props), {
|
||||
"start": start.date,
|
||||
"end": end.date,
|
||||
"maxDays": maxDays,
|
||||
"weekdays": base.effectiveWeekdays.value,
|
||||
"categories": categories,
|
||||
"onClick:date": (e, day) => {
|
||||
if (attrs['onUpdate:modelValue']) emit('update:modelValue', day.date);
|
||||
}
|
||||
}), base.getScopedSlots()), [[vResize, base.updateEventVisibility, void 0, {
|
||||
quiet: true
|
||||
}]]);
|
||||
});
|
||||
return forwardRefs({
|
||||
...base,
|
||||
lastStart,
|
||||
lastEnd,
|
||||
parsedCategoryDays,
|
||||
renderProps,
|
||||
eventWeekdays,
|
||||
categoryMode,
|
||||
title,
|
||||
monthLongFormatter,
|
||||
monthShortFormatter,
|
||||
parsedCategories,
|
||||
checkChange,
|
||||
move,
|
||||
next,
|
||||
prev,
|
||||
getCategoryList
|
||||
}, root);
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=VCalendar.js.map
|
||||
Reference in New Issue
Block a user