routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+384
@@ -0,0 +1,384 @@
|
||||
import { createElementVNode as _createElementVNode, createVNode as _createVNode, mergeProps as _mergeProps, Fragment as _Fragment } from "vue";
|
||||
// Styles
|
||||
import "./VDatePicker.css";
|
||||
|
||||
// Components
|
||||
import { makeVDatePickerControlsProps, VDatePickerControls } from "./VDatePickerControls.js";
|
||||
import { VDatePickerHeader } from "./VDatePickerHeader.js";
|
||||
import { makeVDatePickerMonthProps, VDatePickerMonth } from "./VDatePickerMonth.js";
|
||||
import { makeVDatePickerMonthsProps, VDatePickerMonths } from "./VDatePickerMonths.js";
|
||||
import { makeVDatePickerYearsProps, VDatePickerYears } from "./VDatePickerYears.js";
|
||||
import { VFadeTransition } from "../transitions/index.js";
|
||||
import { VDefaultsProvider } from "../VDefaultsProvider/index.js";
|
||||
import { makeVPickerProps, VPicker } from "../../labs/VPicker/VPicker.js"; // Composables
|
||||
import { useCalendarRange } from "../../composables/calendar.js";
|
||||
import { useDate } from "../../composables/date/index.js";
|
||||
import { daysDiff } from "../../composables/date/date.js";
|
||||
import { useLocale, useRtl } from "../../composables/locale.js";
|
||||
import { useProxiedModel } from "../../composables/proxiedModel.js"; // Utilities
|
||||
import { computed, shallowRef, toRef, watch } from 'vue';
|
||||
import { convertToUnit, genericComponent, omit, propsFactory, useRender, wrapInArray } from "../../util/index.js"; // Types
|
||||
// Types
|
||||
export const makeVDatePickerProps = propsFactory({
|
||||
// TODO: implement in v3.5
|
||||
// calendarIcon: {
|
||||
// type: String,
|
||||
// default: '$calendar',
|
||||
// },
|
||||
// keyboardIcon: {
|
||||
// type: String,
|
||||
// default: '$edit',
|
||||
// },
|
||||
// inputMode: {
|
||||
// type: String as PropType<'calendar' | 'keyboard'>,
|
||||
// default: 'calendar',
|
||||
// },
|
||||
// inputText: {
|
||||
// type: String,
|
||||
// default: '$vuetify.datePicker.input.placeholder',
|
||||
// },
|
||||
// inputPlaceholder: {
|
||||
// type: String,
|
||||
// default: 'dd/mm/yyyy',
|
||||
// },
|
||||
header: {
|
||||
type: String,
|
||||
default: '$vuetify.datePicker.header'
|
||||
},
|
||||
headerColor: String,
|
||||
headerDateFormat: {
|
||||
type: String,
|
||||
default: 'normalDateWithWeekday'
|
||||
},
|
||||
landscapeHeaderWidth: [Number, String],
|
||||
...omit(makeVDatePickerControlsProps(), ['active', 'monthText', 'yearText']),
|
||||
...makeVDatePickerMonthProps({
|
||||
weeksInMonth: 'static'
|
||||
}),
|
||||
...omit(makeVDatePickerMonthsProps(), ['modelValue']),
|
||||
...omit(makeVDatePickerYearsProps(), ['modelValue']),
|
||||
...makeVPickerProps({
|
||||
title: '$vuetify.datePicker.title'
|
||||
}),
|
||||
modelValue: null
|
||||
}, 'VDatePicker');
|
||||
export const VDatePicker = genericComponent()({
|
||||
name: 'VDatePicker',
|
||||
props: makeVDatePickerProps(),
|
||||
emits: {
|
||||
'update:modelValue': date => true,
|
||||
'update:month': date => true,
|
||||
'update:year': date => true,
|
||||
// 'update:inputMode': (date: any) => true,
|
||||
'update:viewMode': date => true
|
||||
},
|
||||
setup(props, {
|
||||
emit,
|
||||
slots
|
||||
}) {
|
||||
const adapter = useDate();
|
||||
const {
|
||||
t
|
||||
} = useLocale();
|
||||
const {
|
||||
rtlClasses
|
||||
} = useRtl();
|
||||
const model = useProxiedModel(props, 'modelValue', undefined, v => wrapInArray(v).map(i => adapter.date(i)), v => props.multiple ? v : v[0]);
|
||||
const viewMode = useProxiedModel(props, 'viewMode');
|
||||
// const inputMode = useProxiedModel(props, 'inputMode')
|
||||
|
||||
const {
|
||||
minDate,
|
||||
maxDate,
|
||||
clampDate
|
||||
} = useCalendarRange(props);
|
||||
const internal = computed(() => {
|
||||
const today = adapter.date();
|
||||
const value = model.value?.[0] ? adapter.date(model.value[0]) : clampDate(today);
|
||||
return value && adapter.isValid(value) ? value : today;
|
||||
});
|
||||
const headerColor = toRef(() => props.headerColor ?? props.color);
|
||||
const _month = useProxiedModel(props, 'month');
|
||||
const month = computed({
|
||||
get: () => Number(_month.value ?? adapter.getMonth(adapter.startOfMonth(internal.value))),
|
||||
set: v => _month.value = v
|
||||
});
|
||||
const _year = useProxiedModel(props, 'year');
|
||||
const year = computed({
|
||||
get: () => Number(_year.value ?? adapter.getYear(adapter.startOfYear(adapter.setMonth(internal.value, month.value)))),
|
||||
set: v => _year.value = v
|
||||
});
|
||||
const isReversing = shallowRef(false);
|
||||
const header = computed(() => {
|
||||
if (props.multiple === 'range' && model.value.length === 2) {
|
||||
const [startDate, endDate] = model.value;
|
||||
const daysBetween = adapter.getDiff(endDate, startDate, 'days') + 1;
|
||||
return t('$vuetify.datePicker.itemsSelected', daysBetween);
|
||||
}
|
||||
if (props.multiple && model.value.length > 1) {
|
||||
return t('$vuetify.datePicker.itemsSelected', model.value.length);
|
||||
}
|
||||
const formattedDate = model.value[0] && adapter.isValid(model.value[0]) ? adapter.format(adapter.date(model.value[0]), props.headerDateFormat) : t(props.header);
|
||||
return props.landscape && formattedDate.split(' ').length === 3 ? formattedDate.replace(' ', '\n') : formattedDate;
|
||||
});
|
||||
const monthStart = toRef(() => {
|
||||
let date = adapter.date();
|
||||
date = adapter.setDate(date, 1);
|
||||
date = adapter.setMonth(date, month.value);
|
||||
date = adapter.setYear(date, year.value); // year is not always ISO
|
||||
return date;
|
||||
});
|
||||
const monthYearText = toRef(() => adapter.format(monthStart.value, 'monthAndYear'));
|
||||
const monthText = toRef(() => adapter.format(monthStart.value, 'monthShort'));
|
||||
const yearText = toRef(() => adapter.format(monthStart.value, 'year'));
|
||||
|
||||
// const headerIcon = toRef(() => props.inputMode === 'calendar' ? props.keyboardIcon : props.calendarIcon)
|
||||
const headerTransition = toRef(() => `date-picker-header${isReversing.value ? '-reverse' : ''}-transition`);
|
||||
const disabled = computed(() => {
|
||||
if (props.disabled) return true;
|
||||
const targets = [];
|
||||
if (viewMode.value !== 'month') {
|
||||
targets.push(...['prev-month', 'next-month', 'prev-year', 'next-year']);
|
||||
} else {
|
||||
let _date = adapter.date();
|
||||
_date = adapter.startOfMonth(_date);
|
||||
_date = adapter.setMonth(_date, month.value);
|
||||
_date = adapter.setYear(_date, year.value);
|
||||
if (minDate.value) {
|
||||
const prevMonthEnd = adapter.addDays(adapter.startOfMonth(_date), -1);
|
||||
const prevYearEnd = adapter.addDays(adapter.startOfYear(_date), -1);
|
||||
adapter.isAfter(minDate.value, prevMonthEnd) && targets.push('prev-month');
|
||||
adapter.isAfter(minDate.value, prevYearEnd) && targets.push('prev-year');
|
||||
}
|
||||
if (maxDate.value) {
|
||||
const nextMonthStart = adapter.addDays(adapter.endOfMonth(_date), 1);
|
||||
const nextYearStart = adapter.addDays(adapter.endOfYear(_date), 1);
|
||||
adapter.isAfter(nextMonthStart, maxDate.value) && targets.push('next-month');
|
||||
adapter.isAfter(nextYearStart, maxDate.value) && targets.push('next-year');
|
||||
}
|
||||
}
|
||||
return targets;
|
||||
});
|
||||
const allowedYears = computed(() => {
|
||||
return props.allowedYears || isYearAllowed;
|
||||
});
|
||||
const allowedMonths = computed(() => {
|
||||
return props.allowedMonths || isMonthAllowed;
|
||||
});
|
||||
function isAllowedInRange(start, end) {
|
||||
const allowedDates = props.allowedDates;
|
||||
if (typeof allowedDates !== 'function') return true;
|
||||
const days = 1 + daysDiff(adapter, start, end);
|
||||
for (let i = 0; i < days; i++) {
|
||||
if (allowedDates(adapter.addDays(start, i))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isYearAllowed(year) {
|
||||
if (typeof props.allowedDates === 'function') {
|
||||
const startOfYear = adapter.parseISO(`${year}-01-01`);
|
||||
return isAllowedInRange(startOfYear, adapter.endOfYear(startOfYear));
|
||||
}
|
||||
if (Array.isArray(props.allowedDates) && props.allowedDates.length) {
|
||||
for (const date of props.allowedDates) {
|
||||
if (adapter.getYear(adapter.date(date)) === year) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function isMonthAllowed(month) {
|
||||
if (typeof props.allowedDates === 'function') {
|
||||
const monthTwoDigits = String(month + 1).padStart(2, '0');
|
||||
const startOfMonth = adapter.parseISO(`${year.value}-${monthTwoDigits}-01`);
|
||||
return isAllowedInRange(startOfMonth, adapter.endOfMonth(startOfMonth));
|
||||
}
|
||||
if (Array.isArray(props.allowedDates) && props.allowedDates.length) {
|
||||
for (const date of props.allowedDates) {
|
||||
if (adapter.getYear(adapter.date(date)) === year.value && adapter.getMonth(adapter.date(date)) === month) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// function onClickAppend () {
|
||||
// inputMode.value = inputMode.value === 'calendar' ? 'keyboard' : 'calendar'
|
||||
// }
|
||||
|
||||
function onClickNextMonth() {
|
||||
if (month.value < 11) {
|
||||
month.value++;
|
||||
} else {
|
||||
year.value++;
|
||||
month.value = 0;
|
||||
onUpdateYear();
|
||||
}
|
||||
onUpdateMonth();
|
||||
}
|
||||
function onClickPrevMonth() {
|
||||
if (month.value > 0) {
|
||||
month.value--;
|
||||
} else {
|
||||
year.value--;
|
||||
month.value = 11;
|
||||
onUpdateYear();
|
||||
}
|
||||
onUpdateMonth();
|
||||
}
|
||||
function onClickNextYear() {
|
||||
year.value++;
|
||||
if (maxDate.value) {
|
||||
const monthTwoDigits = String(month.value + 1).padStart(2, '0');
|
||||
const monthStart = adapter.parseISO(`${year.value}-${monthTwoDigits}-01`);
|
||||
if (adapter.isAfter(monthStart, maxDate.value)) {
|
||||
month.value = adapter.getMonth(maxDate.value);
|
||||
}
|
||||
}
|
||||
onUpdateYear();
|
||||
}
|
||||
function onClickPrevYear() {
|
||||
year.value--;
|
||||
if (minDate.value) {
|
||||
const monthTwoDigits = String(month.value + 1).padStart(2, '0');
|
||||
const monthStart = adapter.endOfMonth(adapter.parseISO(`${year.value}-${monthTwoDigits}-01`));
|
||||
if (adapter.isAfter(minDate.value, monthStart)) {
|
||||
month.value = adapter.getMonth(minDate.value);
|
||||
}
|
||||
}
|
||||
onUpdateYear();
|
||||
}
|
||||
function onClickDate() {
|
||||
viewMode.value = 'month';
|
||||
}
|
||||
function onClickMonth() {
|
||||
viewMode.value = viewMode.value === 'months' ? 'month' : 'months';
|
||||
}
|
||||
function onClickYear() {
|
||||
viewMode.value = viewMode.value === 'year' ? 'month' : 'year';
|
||||
}
|
||||
function onUpdateMonth() {
|
||||
if (viewMode.value === 'months') onClickMonth();
|
||||
}
|
||||
function onUpdateYear() {
|
||||
if (viewMode.value === 'year') onClickYear();
|
||||
}
|
||||
watch(model, (val, oldVal) => {
|
||||
const arrBefore = wrapInArray(oldVal);
|
||||
const arrAfter = wrapInArray(val);
|
||||
if (!arrAfter.length) return;
|
||||
const before = adapter.date(arrBefore[arrBefore.length - 1]);
|
||||
const after = adapter.date(arrAfter[arrAfter.length - 1]);
|
||||
if (adapter.isSameDay(before, after)) return;
|
||||
const newMonth = adapter.getMonth(after);
|
||||
const newYear = adapter.getYear(after);
|
||||
if (newMonth !== month.value) {
|
||||
month.value = newMonth;
|
||||
onUpdateMonth();
|
||||
}
|
||||
if (newYear !== year.value) {
|
||||
year.value = newYear;
|
||||
onUpdateYear();
|
||||
}
|
||||
isReversing.value = adapter.isBefore(before, after);
|
||||
});
|
||||
useRender(() => {
|
||||
const pickerProps = VPicker.filterProps(props);
|
||||
const datePickerControlsProps = omit(VDatePickerControls.filterProps(props), ['viewMode']);
|
||||
const datePickerHeaderProps = VDatePickerHeader.filterProps(props);
|
||||
const datePickerMonthProps = VDatePickerMonth.filterProps(props);
|
||||
const datePickerMonthsProps = omit(VDatePickerMonths.filterProps(props), ['modelValue']);
|
||||
const datePickerYearsProps = omit(VDatePickerYears.filterProps(props), ['modelValue']);
|
||||
const headerProps = {
|
||||
color: headerColor.value,
|
||||
header: header.value,
|
||||
transition: headerTransition.value
|
||||
};
|
||||
return _createVNode(VPicker, _mergeProps(pickerProps, {
|
||||
"color": headerColor.value,
|
||||
"class": ['v-date-picker', `v-date-picker--${viewMode.value}`, {
|
||||
'v-date-picker--show-week': props.showWeek
|
||||
}, rtlClasses.value, props.class],
|
||||
"style": [{
|
||||
'--v-date-picker-landscape-header-width': convertToUnit(props.landscapeHeaderWidth)
|
||||
}, props.style]
|
||||
}), {
|
||||
title: () => slots.title?.() ?? _createElementVNode("div", {
|
||||
"class": "v-date-picker__title"
|
||||
}, [t(props.title)]),
|
||||
header: () => slots.header ? _createVNode(VDefaultsProvider, {
|
||||
"defaults": {
|
||||
VDatePickerHeader: {
|
||||
...headerProps
|
||||
}
|
||||
}
|
||||
}, {
|
||||
default: () => [slots.header?.(headerProps)]
|
||||
}) : _createVNode(VDatePickerHeader, _mergeProps({
|
||||
"key": "header"
|
||||
}, datePickerHeaderProps, headerProps, {
|
||||
"onClick": viewMode.value !== 'month' ? onClickDate : undefined
|
||||
}), {
|
||||
prepend: slots.prepend,
|
||||
append: slots.append
|
||||
}),
|
||||
default: () => _createElementVNode(_Fragment, null, [_createVNode(VDatePickerControls, _mergeProps(datePickerControlsProps, {
|
||||
"disabled": disabled.value,
|
||||
"viewMode": viewMode.value,
|
||||
"text": monthYearText.value,
|
||||
"monthText": monthText.value,
|
||||
"yearText": yearText.value,
|
||||
"onClick:next": onClickNextMonth,
|
||||
"onClick:prev": onClickPrevMonth,
|
||||
"onClick:nextYear": onClickNextYear,
|
||||
"onClick:prevYear": onClickPrevYear,
|
||||
"onClick:month": onClickMonth,
|
||||
"onClick:year": onClickYear
|
||||
}), {
|
||||
default: slots.controls
|
||||
}), _createVNode(VFadeTransition, {
|
||||
"hideOnLeave": true
|
||||
}, {
|
||||
default: () => [viewMode.value === 'months' ? _createVNode(VDatePickerMonths, _mergeProps({
|
||||
"key": "date-picker-months"
|
||||
}, datePickerMonthsProps, {
|
||||
"modelValue": month.value,
|
||||
"onUpdate:modelValue": [$event => month.value = $event, onUpdateMonth],
|
||||
"min": minDate.value,
|
||||
"max": maxDate.value,
|
||||
"year": year.value,
|
||||
"allowedMonths": allowedMonths.value
|
||||
}), {
|
||||
month: slots.month
|
||||
}) : viewMode.value === 'year' ? _createVNode(VDatePickerYears, _mergeProps({
|
||||
"key": "date-picker-years"
|
||||
}, datePickerYearsProps, {
|
||||
"modelValue": year.value,
|
||||
"onUpdate:modelValue": [$event => year.value = $event, onUpdateYear],
|
||||
"min": minDate.value,
|
||||
"max": maxDate.value,
|
||||
"allowedYears": allowedYears.value
|
||||
}), {
|
||||
year: slots.year
|
||||
}) : _createVNode(VDatePickerMonth, _mergeProps({
|
||||
"key": "date-picker-month"
|
||||
}, datePickerMonthProps, {
|
||||
"modelValue": model.value,
|
||||
"onUpdate:modelValue": $event => model.value = $event,
|
||||
"month": month.value,
|
||||
"onUpdate:month": [$event => month.value = $event, onUpdateMonth],
|
||||
"year": year.value,
|
||||
"onUpdate:year": [$event => year.value = $event, onUpdateYear],
|
||||
"min": minDate.value,
|
||||
"max": maxDate.value
|
||||
}), {
|
||||
day: slots.day
|
||||
})]
|
||||
})]),
|
||||
actions: slots.actions
|
||||
});
|
||||
});
|
||||
return {};
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=VDatePicker.js.map
|
||||
Reference in New Issue
Block a user