routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+236
@@ -0,0 +1,236 @@
|
||||
import { createVNode as _createVNode, createElementVNode as _createElementVNode, createTextVNode as _createTextVNode, normalizeClass as _normalizeClass } from "vue";
|
||||
// Styles
|
||||
import "./VDatePickerMonth.css";
|
||||
|
||||
// Components
|
||||
import { VBadge } from "../VBadge/index.js";
|
||||
import { VBtn } from "../VBtn/index.js"; // Composables
|
||||
import { makeCalendarProps, useCalendar } from "../../composables/calendar.js";
|
||||
import { useDate } from "../../composables/date/date.js";
|
||||
import { useLocale } from "../../composables/locale.js";
|
||||
import { MaybeTransition } from "../../composables/transition.js"; // Utilities
|
||||
import { computed, ref, shallowRef, toRef, watch } from 'vue';
|
||||
import { genericComponent, omit, propsFactory, useRender, wrapInArray } from "../../util/index.js"; // Types
|
||||
export const makeVDatePickerMonthProps = propsFactory({
|
||||
color: String,
|
||||
hideWeekdays: Boolean,
|
||||
multiple: [Boolean, Number, String],
|
||||
showWeek: Boolean,
|
||||
readonly: Boolean,
|
||||
transition: {
|
||||
type: String,
|
||||
default: 'picker-transition'
|
||||
},
|
||||
reverseTransition: {
|
||||
type: String,
|
||||
default: 'picker-reverse-transition'
|
||||
},
|
||||
events: {
|
||||
type: [Array, Function, Object],
|
||||
default: () => null
|
||||
},
|
||||
eventColor: {
|
||||
type: [Array, Function, Object, String],
|
||||
default: () => null
|
||||
},
|
||||
...omit(makeCalendarProps(), ['displayValue'])
|
||||
}, 'VDatePickerMonth');
|
||||
export const VDatePickerMonth = genericComponent()({
|
||||
name: 'VDatePickerMonth',
|
||||
props: makeVDatePickerMonthProps(),
|
||||
emits: {
|
||||
'update:modelValue': date => true,
|
||||
'update:month': date => true,
|
||||
'update:year': date => true
|
||||
},
|
||||
setup(props, {
|
||||
emit,
|
||||
slots
|
||||
}) {
|
||||
const daysRef = ref();
|
||||
const {
|
||||
t
|
||||
} = useLocale();
|
||||
const {
|
||||
daysInMonth,
|
||||
model,
|
||||
weekNumbers,
|
||||
weekdayLabels
|
||||
} = useCalendar(props);
|
||||
const adapter = useDate();
|
||||
const rangeStart = shallowRef();
|
||||
const rangeStop = shallowRef();
|
||||
const isReverse = shallowRef(false);
|
||||
const transition = toRef(() => {
|
||||
return !isReverse.value ? props.transition : props.reverseTransition;
|
||||
});
|
||||
if (props.multiple === 'range' && model.value.length > 0) {
|
||||
rangeStart.value = model.value[0];
|
||||
if (model.value.length > 1) {
|
||||
rangeStop.value = model.value[model.value.length - 1];
|
||||
}
|
||||
}
|
||||
const atMax = computed(() => {
|
||||
const max = ['number', 'string'].includes(typeof props.multiple) ? Number(props.multiple) : Infinity;
|
||||
return model.value.length >= max;
|
||||
});
|
||||
watch(daysInMonth, (val, oldVal) => {
|
||||
if (!oldVal) return;
|
||||
isReverse.value = adapter.isBefore(val[0].date, oldVal[0].date);
|
||||
});
|
||||
function onRangeClick(value) {
|
||||
const _value = adapter.startOfDay(value);
|
||||
if (model.value.length === 0) {
|
||||
rangeStart.value = undefined;
|
||||
} else if (model.value.length === 1) {
|
||||
rangeStart.value = model.value[0];
|
||||
rangeStop.value = undefined;
|
||||
}
|
||||
if (!rangeStart.value) {
|
||||
rangeStart.value = _value;
|
||||
model.value = [rangeStart.value];
|
||||
} else if (!rangeStop.value) {
|
||||
if (adapter.isSameDay(_value, rangeStart.value)) {
|
||||
rangeStart.value = undefined;
|
||||
model.value = [];
|
||||
return;
|
||||
} else if (adapter.isBefore(_value, rangeStart.value)) {
|
||||
rangeStop.value = adapter.endOfDay(rangeStart.value);
|
||||
rangeStart.value = _value;
|
||||
} else {
|
||||
rangeStop.value = adapter.endOfDay(_value);
|
||||
}
|
||||
model.value = [rangeStart.value, rangeStop.value];
|
||||
} else {
|
||||
rangeStart.value = value;
|
||||
rangeStop.value = undefined;
|
||||
model.value = [rangeStart.value];
|
||||
}
|
||||
}
|
||||
function getDateAriaLabel(item) {
|
||||
const fullDate = adapter.format(item.date, 'fullDateWithWeekday');
|
||||
const localeKey = item.isToday ? 'currentDate' : 'selectDate';
|
||||
return t(`$vuetify.datePicker.ariaLabel.${localeKey}`, fullDate);
|
||||
}
|
||||
function onMultipleClick(value) {
|
||||
const index = model.value.findIndex(selection => adapter.isSameDay(selection, value));
|
||||
if (index === -1) {
|
||||
model.value = [...model.value, value];
|
||||
} else {
|
||||
const value = [...model.value];
|
||||
value.splice(index, 1);
|
||||
model.value = value;
|
||||
}
|
||||
}
|
||||
function onClick(value) {
|
||||
if (props.multiple === 'range') {
|
||||
onRangeClick(value);
|
||||
} else if (props.multiple) {
|
||||
onMultipleClick(value);
|
||||
} else {
|
||||
model.value = [value];
|
||||
}
|
||||
}
|
||||
function getEventColors(date) {
|
||||
const {
|
||||
events,
|
||||
eventColor
|
||||
} = props;
|
||||
let eventData;
|
||||
let eventColors = [];
|
||||
if (Array.isArray(events)) {
|
||||
eventData = events.includes(date);
|
||||
} else if (events instanceof Function) {
|
||||
eventData = events(date) || false;
|
||||
} else if (events) {
|
||||
eventData = events[date] || false;
|
||||
} else {
|
||||
eventData = false;
|
||||
}
|
||||
if (!eventData) {
|
||||
return [];
|
||||
} else if (eventData !== true) {
|
||||
eventColors = wrapInArray(eventData);
|
||||
} else if (typeof eventColor === 'string') {
|
||||
eventColors = [eventColor];
|
||||
} else if (typeof eventColor === 'function') {
|
||||
eventColors = wrapInArray(eventColor(date));
|
||||
} else if (Array.isArray(eventColor)) {
|
||||
eventColors = eventColor;
|
||||
} else if (typeof eventColor === 'object' && eventColor !== null) {
|
||||
eventColors = wrapInArray(eventColor[date]);
|
||||
}
|
||||
|
||||
// Fallback to default color if no color is found
|
||||
return !eventColors.length ? ['surface-variant'] : eventColors.filter(Boolean).map(color => typeof color === 'string' ? color : 'surface-variant');
|
||||
}
|
||||
function genEvents(date) {
|
||||
const eventColors = getEventColors(date);
|
||||
if (!eventColors.length) return null;
|
||||
return _createElementVNode("div", {
|
||||
"class": "v-date-picker-month__events"
|
||||
}, [eventColors.map(color => _createVNode(VBadge, {
|
||||
"dot": true,
|
||||
"color": color
|
||||
}, null))]);
|
||||
}
|
||||
useRender(() => _createElementVNode("div", {
|
||||
"class": "v-date-picker-month",
|
||||
"style": {
|
||||
'--v-date-picker-days-in-week': props.weekdays.length
|
||||
}
|
||||
}, [props.showWeek && _createElementVNode("div", {
|
||||
"key": "weeks",
|
||||
"class": "v-date-picker-month__weeks"
|
||||
}, [!props.hideWeekdays && _createElementVNode("div", {
|
||||
"key": "hide-week-days",
|
||||
"class": "v-date-picker-month__day"
|
||||
}, [_createTextVNode("\xA0")]), weekNumbers.value.map(week => _createElementVNode("div", {
|
||||
"class": _normalizeClass(['v-date-picker-month__day', 'v-date-picker-month__day--adjacent'])
|
||||
}, [week]))]), _createVNode(MaybeTransition, {
|
||||
"name": transition.value
|
||||
}, {
|
||||
default: () => [_createElementVNode("div", {
|
||||
"ref": daysRef,
|
||||
"key": daysInMonth.value[0].date?.toString(),
|
||||
"class": "v-date-picker-month__days"
|
||||
}, [!props.hideWeekdays && weekdayLabels.value.map(weekDay => _createElementVNode("div", {
|
||||
"class": _normalizeClass(['v-date-picker-month__day', 'v-date-picker-month__weekday'])
|
||||
}, [weekDay])), daysInMonth.value.map((item, i) => {
|
||||
const slotProps = {
|
||||
props: {
|
||||
class: 'v-date-picker-month__day-btn',
|
||||
color: item.isSelected || item.isToday ? props.color : undefined,
|
||||
disabled: item.isDisabled,
|
||||
readonly: props.readonly,
|
||||
icon: true,
|
||||
ripple: false,
|
||||
variant: item.isSelected ? 'flat' : item.isToday ? 'outlined' : 'text',
|
||||
'aria-label': getDateAriaLabel(item),
|
||||
'aria-current': item.isToday ? 'date' : undefined,
|
||||
onClick: () => onClick(item.date)
|
||||
},
|
||||
item,
|
||||
i
|
||||
};
|
||||
const isSelected = props.multiple === 'range' && model.value.length === 2 ? adapter.isWithinRange(item.date, model.value) : model.value.some(selectedDate => adapter.isSameDay(selectedDate, item.date));
|
||||
if (atMax.value && !isSelected) {
|
||||
item.isDisabled = true;
|
||||
}
|
||||
return _createElementVNode("div", {
|
||||
"class": _normalizeClass(['v-date-picker-month__day', {
|
||||
'v-date-picker-month__day--adjacent': item.isAdjacent,
|
||||
'v-date-picker-month__day--hide-adjacent': item.isHidden,
|
||||
'v-date-picker-month__day--selected': isSelected,
|
||||
'v-date-picker-month__day--week-end': item.isWeekEnd,
|
||||
'v-date-picker-month__day--week-start': item.isWeekStart
|
||||
}]),
|
||||
"data-v-date": !item.isDisabled ? item.isoDate : undefined
|
||||
}, [(props.showAdjacentMonths || !item.isAdjacent) && (slots.day?.(slotProps) ?? _createVNode(VBtn, slotProps.props, {
|
||||
default: () => [item.localized, genEvents(item.isoDate)]
|
||||
}))]);
|
||||
})])]
|
||||
})]));
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=VDatePickerMonth.js.map
|
||||
Reference in New Issue
Block a user