init component
This commit is contained in:
541
node_modules/buetify/lib/components/form/datepicker/BDatepicker.js
generated
vendored
Executable file
541
node_modules/buetify/lib/components/form/datepicker/BDatepicker.js
generated
vendored
Executable file
@@ -0,0 +1,541 @@
|
||||
import "../../../../src/components/pagination/pagination.sass";
|
||||
import "../../../../src/components/dropdown/dropdown.sass";
|
||||
import "../../../../src/components/form/datepicker/datepicker.sass";
|
||||
import { useDisable, UseDisablePropsDefinition } from '../../../composables/disable';
|
||||
import { useEqRef } from '../../../composables/eqRef';
|
||||
import { useFieldData } from '../../../composables/fieldData';
|
||||
import { getUseInputPropsDefinition } from '../../../composables/input/useInput';
|
||||
import { useProxy } from '../../../composables/proxy/useProxy';
|
||||
import { DEFAULT_DAY_NAMES, DEFAULT_MONTH_NAMES } from './shared';
|
||||
import { addDays, eqSerialDate, isDate } from './utils';
|
||||
import { BInput } from '../input/BInput';
|
||||
import { isArrowDownEvent, isArrowLeftEvent, isArrowRightEvent, isArrowUpEvent, isEnterEvent, isEscEvent, isSpaceEvent } from '../../../utils/eventHelpers';
|
||||
import { head, isNonEmpty, range } from 'fp-ts/lib/Array';
|
||||
import { constant } from 'fp-ts/lib/function';
|
||||
import { alt, chain, fromNullable, getEq, isNone, isSome, some } from 'fp-ts/lib/Option';
|
||||
import { pipe } from 'fp-ts/lib/pipeable';
|
||||
import BDropdown, { BDropdownPropsDefinition } from '../../dropdown/BDropdown';
|
||||
import BDatepickerTable from './BDatepickerTable';
|
||||
import BField from '../field/BField';
|
||||
import { BSelect } from '../select/BSelect';
|
||||
import { computed, onUnmounted, onMounted, defineAsyncComponent, defineComponent, h, shallowRef, watch, toRef } from 'vue';
|
||||
import { constEmptyArray, isString, toggleListItem } from '../../../utils/helpers';
|
||||
const DEFAULT_DATEPICKER_ICONS = {
|
||||
previous: defineAsyncComponent(() => import('../../icons/angleLeft')),
|
||||
next: defineAsyncComponent(() => import('../../icons/angleRight')),
|
||||
calendar: defineAsyncComponent(() => import('../../icons/calendar'))
|
||||
};
|
||||
export function getDatepickerIcons(icons) {
|
||||
return { ...DEFAULT_DATEPICKER_ICONS,
|
||||
...icons
|
||||
};
|
||||
}
|
||||
const BDatepickerPropsDefinition = { ...BDropdownPropsDefinition,
|
||||
...UseDisablePropsDefinition,
|
||||
...getUseInputPropsDefinition(),
|
||||
modelValue: {
|
||||
type: [Array, Date]
|
||||
},
|
||||
'onUpdate:modelValue': {
|
||||
type: Function,
|
||||
required: true
|
||||
},
|
||||
year: {
|
||||
type: Number,
|
||||
default: new Date().getFullYear()
|
||||
},
|
||||
'onUpdate:year': {
|
||||
type: Function,
|
||||
required: false
|
||||
},
|
||||
month: {
|
||||
type: Number,
|
||||
default: new Date().getMonth()
|
||||
},
|
||||
'onUpdate:month': {
|
||||
type: Function,
|
||||
required: false
|
||||
},
|
||||
dayNames: {
|
||||
type: Array,
|
||||
default: constant(DEFAULT_DAY_NAMES)
|
||||
},
|
||||
monthNames: {
|
||||
type: Array,
|
||||
default: constant(DEFAULT_MONTH_NAMES)
|
||||
},
|
||||
firstDayOfWeek: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
events: {
|
||||
type: Array,
|
||||
default: constEmptyArray
|
||||
},
|
||||
minDate: {
|
||||
type: Date,
|
||||
required: false
|
||||
},
|
||||
maxDate: {
|
||||
type: Date,
|
||||
required: false
|
||||
},
|
||||
isDisabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
unselectableDates: {
|
||||
type: Array,
|
||||
default: constEmptyArray
|
||||
},
|
||||
unselectableDaysOfWeek: {
|
||||
type: Array,
|
||||
default: constEmptyArray
|
||||
},
|
||||
selectableDates: {
|
||||
type: Object
|
||||
},
|
||||
showWeekNumber: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isMultiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
placeholder: {
|
||||
type: String
|
||||
},
|
||||
useMobileNative: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
position: {
|
||||
type: String
|
||||
},
|
||||
indicators: {
|
||||
type: String,
|
||||
default: 'bars'
|
||||
},
|
||||
yearsRange: {
|
||||
type: Array,
|
||||
default: constant([-5, 3])
|
||||
},
|
||||
closeOnSelect: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
isReadonly: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
useNativeValidation: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// openOnFocus: {
|
||||
// type: Boolean as PropType<boolean>,
|
||||
// default: true
|
||||
// },
|
||||
icons: {
|
||||
type: Object,
|
||||
default: constant(DEFAULT_DATEPICKER_ICONS)
|
||||
}
|
||||
};
|
||||
|
||||
function useNative(props) {
|
||||
return props.useMobileNative && !props.isInline;
|
||||
}
|
||||
|
||||
const useFormattedDate = Intl.DateTimeFormat('default', {
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
day: 'numeric'
|
||||
}).format;
|
||||
|
||||
function useFormattedModelValue(modelValue) {
|
||||
return Array.isArray(modelValue) ? modelValue.map(useFormattedDate).join(', ') : modelValue ? useFormattedDate(modelValue) : null;
|
||||
}
|
||||
|
||||
function parseInputString(str) {
|
||||
const splits = str.split(',').map(s => s.trim());
|
||||
return splits.map(s => new Date(s)).filter(d => isDate(d) && !isNaN(d.getTime()));
|
||||
}
|
||||
|
||||
function generateInput(props, context, data) {
|
||||
const isMobile = useNative(props);
|
||||
return h(BInput, {
|
||||
max: props.maxDate ? useFormattedDate(props.maxDate) : null,
|
||||
min: props.minDate ? useFormattedDate(props.minDate) : null,
|
||||
autocomplete: 'off',
|
||||
type: isMobile ? 'date' : 'text',
|
||||
modelValue: useFormattedModelValue(data.modelValue.value),
|
||||
'onUpdate:modelValue': val => {
|
||||
data.modelValue.value = parseInputString(val);
|
||||
},
|
||||
placeholder: props.placeholder,
|
||||
size: props.size,
|
||||
icon: props.icons.calendar,
|
||||
isRounded: props.isRounded,
|
||||
isDisabled: props.isDisabled,
|
||||
isReadonly: props.isReadonly,
|
||||
isLoading: props.isLoading,
|
||||
useNativeValidation: props.useNativeValidation // onFocus: () => {
|
||||
// if (!isMobile && props.openOnFocus && toggle) {
|
||||
// if (toggle.isOff.value) {
|
||||
// console.log('focus-set-on')
|
||||
// toggle.setOn();
|
||||
// Date.now()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function generateButton(props, data, isNext) {
|
||||
return h('button', {
|
||||
class: isNext ? 'pagination-next datepicker-next' : 'pagination-previous datepicker-previous',
|
||||
disabled: data.isDisabled,
|
||||
onClick: isNext ? data.nextMonth : data.previousMonth,
|
||||
onKeydown: e => {
|
||||
if (isEnterEvent(e) || isSpaceEvent(e)) {
|
||||
e.preventDefault();
|
||||
isNext ? data.nextMonth() : data.previousMonth();
|
||||
}
|
||||
}
|
||||
}, [h(isNext ? props.icons.next : props.icons.previous, {
|
||||
variant: 'is-link',
|
||||
isThemeable: false
|
||||
})]);
|
||||
}
|
||||
|
||||
function generateYearSelect(props, data) {
|
||||
return h(BSelect, {
|
||||
items: data.years,
|
||||
modelValue: data.year.value,
|
||||
isDisabled: data.isDisabled,
|
||||
size: props.size,
|
||||
'onUpdate:modelValue': data.setYear
|
||||
});
|
||||
}
|
||||
|
||||
function generateMonthSelect(props, data) {
|
||||
return h(BSelect, {
|
||||
items: data.months,
|
||||
isDisabled: data.isDisabled,
|
||||
size: props.size,
|
||||
modelValue: data.month.value,
|
||||
'onUpdate:modelValue': data.setMonth
|
||||
});
|
||||
}
|
||||
|
||||
function generateSelects(props, data) {
|
||||
return h('div', {
|
||||
class: 'pagination-list'
|
||||
}, [h(BField, {
|
||||
class: 'is-marginless'
|
||||
}, () => [generateMonthSelect(props, data), generateYearSelect(props, data)])]);
|
||||
}
|
||||
|
||||
function generateDefaultHeaderContents(props, data) {
|
||||
return h('div', {
|
||||
class: ['pagination field is-centered', props.size]
|
||||
}, [generateButton(props, data, false), generateSelects(props, data), generateButton(props, data, true)]);
|
||||
}
|
||||
|
||||
function generateHeader(props, context, data) {
|
||||
return h('header', {
|
||||
class: 'datepicker-header'
|
||||
}, context.slots.header ? context.slots.header(data) : [generateDefaultHeaderContents(props, data)]);
|
||||
}
|
||||
|
||||
function generateDatepickerTable(props, context, data) {
|
||||
return h(BDatepickerTable, {
|
||||
modelValue: data.modelValue.value,
|
||||
'onUpdate:modelValue': val => {
|
||||
data.modelValue.value = val;
|
||||
},
|
||||
focusedDate: data.focusedDate.value,
|
||||
'onUpdate:focusedDate': val => {
|
||||
data.focusedDate.value = val;
|
||||
},
|
||||
dayNames: props.dayNames,
|
||||
monthNames: props.monthNames,
|
||||
firstDayOfWeek: props.firstDayOfWeek,
|
||||
minDate: props.minDate,
|
||||
maxDate: props.maxDate,
|
||||
month: data.month.value,
|
||||
year: data.year.value,
|
||||
isDisabled: data.isDisabled,
|
||||
unselectableDates: props.unselectableDates,
|
||||
unselectableDaysOfWeek: props.unselectableDaysOfWeek,
|
||||
selectableDates: props.selectableDates,
|
||||
events: props.events,
|
||||
indicators: props.indicators,
|
||||
showWeekNumber: props.showWeekNumber
|
||||
});
|
||||
}
|
||||
|
||||
function generateFooter(context) {
|
||||
return h('footer', {
|
||||
class: 'datepicker-footer'
|
||||
}, context.slots.footer && context.slots.footer());
|
||||
}
|
||||
|
||||
function generateCalendar(props, context, data) {
|
||||
return h('section', {
|
||||
class: 'datepicker-content',
|
||||
'aria-label': 'Datepicker calendar'
|
||||
}, [generateDatepickerTable(props, context, data)]);
|
||||
}
|
||||
|
||||
function generateDatepickerBody(props, context, data) {
|
||||
const nodes = [generateHeader(props, context, data), generateCalendar(props, context, data)];
|
||||
|
||||
if (context.slots.footer) {
|
||||
nodes.push(generateFooter(context));
|
||||
}
|
||||
|
||||
return h('div', nodes);
|
||||
}
|
||||
|
||||
function generateDropdown(props, context, data, dropdown) {
|
||||
return h(BDropdown, {
|
||||
ref: dropdown,
|
||||
position: props.position,
|
||||
isDisabled: props.isDisabled,
|
||||
isInline: props.isInline
|
||||
}, {
|
||||
trigger: () => {
|
||||
return generateInput(props, context, data);
|
||||
},
|
||||
default: () => generateDatepickerBody(props, context, data)
|
||||
});
|
||||
}
|
||||
|
||||
function getMonths(props, focusedMonth) {
|
||||
return props.monthNames.map((month, index) => ({
|
||||
value: index,
|
||||
text: month,
|
||||
isDisabled: false,
|
||||
isSelected: focusedMonth === index
|
||||
}));
|
||||
}
|
||||
|
||||
function getYears(props, focusedYear) {
|
||||
const currentYear = new Date().getFullYear();
|
||||
return range(props.yearsRange[0], props.yearsRange[1]).map(inc => currentYear + inc).map(year => ({
|
||||
value: year,
|
||||
text: year.toString(),
|
||||
isDisabled: false,
|
||||
isSelected: focusedYear === year
|
||||
}));
|
||||
}
|
||||
|
||||
function getSetPreviousMonth(props, month, year) {
|
||||
return e => {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
if (!props.isDisabled) {
|
||||
if (month.value > 0) {
|
||||
month.value = month.value - 1;
|
||||
} else {
|
||||
month.value = 11;
|
||||
year.value = year.value - 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getSetNextMonth(props, month, year) {
|
||||
return e => {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
if (!props.isDisabled) {
|
||||
const mv = month.value;
|
||||
|
||||
if (mv < 11) {
|
||||
month.value = mv + 1;
|
||||
} else {
|
||||
month.value = 0;
|
||||
year.value = year.value + 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getSetMonth(monthRef) {
|
||||
return month => {
|
||||
if (isString(month)) {
|
||||
const newVal = fromNullable(parseInt(month, 10));
|
||||
|
||||
if (isSome(newVal)) {
|
||||
monthRef.value = newVal.value;
|
||||
}
|
||||
} else {
|
||||
monthRef.value = month;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getSetYear(yearRef) {
|
||||
return year => {
|
||||
if (isString(year)) {
|
||||
const newVal = fromNullable(parseInt(year, 10));
|
||||
|
||||
if (isSome(newVal)) {
|
||||
yearRef.value = newVal.value;
|
||||
}
|
||||
} else {
|
||||
yearRef.value = year;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const toggleSerialDate = toggleListItem(eqSerialDate);
|
||||
export default defineComponent({
|
||||
name: 'b-datepicker',
|
||||
props: BDatepickerPropsDefinition,
|
||||
|
||||
setup(props, context) {
|
||||
const fieldData = useFieldData();
|
||||
const isDisabled = useDisable(props);
|
||||
const dropdown = shallowRef(null);
|
||||
const internalValue = shallowRef(props.modelValue);
|
||||
watch(() => props.modelValue, newVal => {
|
||||
internalValue.value = newVal;
|
||||
});
|
||||
const modelValue = computed({
|
||||
get() {
|
||||
return internalValue.value;
|
||||
},
|
||||
|
||||
set(val) {
|
||||
if (!val) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(val) && props.isMultiple || isDate(val)) {
|
||||
props['onUpdate:modelValue'](val);
|
||||
internalValue.value = val;
|
||||
} else if (props.isMultiple && isDate(val)) {
|
||||
const newVal = toggleSerialDate(val, internalValue.value == undefined ? [] : Array.isArray(internalValue.value) ? internalValue.value : [internalValue.value]);
|
||||
props['onUpdate:modelValue'](newVal);
|
||||
internalValue.value = newVal;
|
||||
} else if (Array.isArray(val) && isNonEmpty(val)) {
|
||||
props['onUpdate:modelValue'](val[0]);
|
||||
internalValue.value = val[0];
|
||||
}
|
||||
|
||||
if (props.closeOnSelect) {
|
||||
dropdown.value && dropdown.value.toggle.setOff();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
const focusedDate = useEqRef(getEq(eqSerialDate))(pipe(fromNullable(props.modelValue), chain(v => Array.isArray(v) ? head(v) : some(v)), alt(() => some(new Date()))));
|
||||
const {
|
||||
value: month
|
||||
} = useProxy(toRef(props, 'month'), toRef(props, 'onUpdate:month'));
|
||||
const {
|
||||
value: year
|
||||
} = useProxy(toRef(props, 'year'), toRef(props, 'onUpdate:year'));
|
||||
const nextMonth = getSetNextMonth(props, month, year);
|
||||
const previousMonth = getSetPreviousMonth(props, month, year);
|
||||
const setMonth = getSetMonth(month);
|
||||
const setYear = getSetYear(year);
|
||||
|
||||
function onKeydown(e) {
|
||||
if (dropdown.value === undefined || dropdown.value?.$el === undefined || !dropdown.value.$el.contains(e.target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEscEvent(e)) {
|
||||
dropdown.value && dropdown.value.toggle.setOff();
|
||||
return;
|
||||
}
|
||||
|
||||
const fd = pipe(focusedDate.value, alt(() => pipe(fromNullable(modelValue.value), chain(v => Array.isArray(v) ? head(v) : some(v)))));
|
||||
|
||||
if (isNone(fd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEnterEvent(e) || isSpaceEvent(e)) {
|
||||
e.preventDefault();
|
||||
modelValue.value = fd.value;
|
||||
} else if (isArrowUpEvent(e)) {
|
||||
e.preventDefault();
|
||||
focusedDate.value = some(addDays(fd.value, -7));
|
||||
} else if (isArrowRightEvent(e)) {
|
||||
e.preventDefault();
|
||||
focusedDate.value = some(addDays(fd.value, 1));
|
||||
} else if (isArrowDownEvent(e)) {
|
||||
e.preventDefault();
|
||||
focusedDate.value = some(addDays(fd.value, 7));
|
||||
} else if (isArrowLeftEvent(e)) {
|
||||
e.preventDefault();
|
||||
focusedDate.value = some(addDays(fd.value, -1));
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
document.addEventListener('keyup', onKeydown);
|
||||
}
|
||||
});
|
||||
onUnmounted(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
document.removeEventListener('keyup', onKeydown);
|
||||
}
|
||||
});
|
||||
watch(focusedDate, fd => {
|
||||
const m = month.value;
|
||||
const y = year.value;
|
||||
|
||||
if (isSome(fd)) {
|
||||
const fdValue = fd.value;
|
||||
const nMonth = fdValue.getMonth();
|
||||
|
||||
if (nMonth !== m) {
|
||||
month.value = nMonth;
|
||||
}
|
||||
|
||||
const nYear = fdValue.getFullYear();
|
||||
|
||||
if (nYear !== y) {
|
||||
year.value = nYear;
|
||||
}
|
||||
}
|
||||
}, {
|
||||
immediate: true
|
||||
});
|
||||
return () => {
|
||||
const data = {
|
||||
modelValue,
|
||||
month,
|
||||
year,
|
||||
isDisabled: isDisabled.value,
|
||||
focusedDate: focusedDate,
|
||||
nextMonth,
|
||||
previousMonth,
|
||||
setMonth,
|
||||
setYear,
|
||||
months: getMonths(props, month.value),
|
||||
years: getYears(props, year.value)
|
||||
};
|
||||
return h('article', {
|
||||
class: ['b-datepicker control', props.size, {
|
||||
'is-expanded': props.isExpanded || fieldData.attrs.isExpanded.value
|
||||
}]
|
||||
}, [useNative(props) ? generateInput(props, context, data) : generateDropdown(props, context, data, dropdown)]);
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
//# sourceMappingURL=BDatepicker.js.map
|
||||
Reference in New Issue
Block a user