1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | <template> <calendar :attributes='attributes_' @dayselect='selectDay' @daymouseenter='enterDay' v-bind='$attrs' v-on='$listeners'> </calendar> </template> <script> import Calendar from './Calendar'; import DateInfo from '../utils/dateInfo'; import defaults from '../utils/defaults'; import { rangeHasValue } from '../utils/pickerProfiles'; export default { components: { Calendar, }, props: { value: { type: Object, default: () => {} }, selectColor: { type: String, default: () => defaults.datePickerSelectColor }, dragColor: { type: String, default: () => defaults.datePickerDragColor }, showCaps: { type: Boolean, default: () => defaults.datePickerShowCaps }, dragAttribute: Object, selectAttribute: Object, disabledAttribute: Object, dayContentHoverStyle: Object, attributes: Array, }, data() { return { dragValue: null, }; }, computed: { dragAttribute_() { const normValue = this.normalizeRange(this.dragValue); if (!normValue) return null; return { ...defaults.datePickerDragAttribute(this.dragColor, this.showCaps), ...this.dragAttribute, dates: [this.dragValue], }; }, selectAttribute_() { const normValue = this.normalizeRange(this.value); if (!normValue) return null; return { ...defaults.datePickerSelectAttribute(this.selectColor, this.showCaps), ...this.selectAttribute, dates: [normValue], }; }, attributes_() { const attributes = [...(this.attributes || [])]; if (this.dragAttribute_) attributes.push(this.dragAttribute_); else if (this.selectAttribute_) attributes.push(this.selectAttribute_); if (this.disabledAttribute) attributes.push(this.disabledAttribute); return attributes; }, }, watch: { dragValue(val) { this.$emit('drag', this.normalizeRange(val)); }, }, created() { // Clear drag on escape keydown document.addEventListener('keydown', (e) => { if (this.dragValue && e.keyCode === 27) { this.dragValue = null; } }); }, methods: { touchStartDay(day) { this.selectDay(day); this.$emit('daytouchstart', day); }, selectDay(day) { // Done if date selection is invalid if (this.disabledAttribute && this.disabledAttribute.includesDay(day)) return; // Start new drag selection if not dragging if (!this.dragValue) { // Make sure date selection is valid const date = new Date(day.dateTime); // Start new drag selection this.dragValue = { start: date, end: date }; } else { // Construct new value const newValue = new DateInfo({ start: new Date(this.dragValue.start.getTime()), end: new Date(day.dateTime), }); // Clear drag selection this.dragValue = null; // Signal new value selected this.$emit('input', newValue.toRange()); } }, enterDay(day) { // Make sure drag has been initialized if (this.dragValue) { // Make sure dragged value is valid if (this.disabledAttribute && this.disabledAttribute.includesDay(day)) { // Assign disabled content hover style this.dayContentHoverStyle_ = this.disabledAttribute.contentHoverStyle; } else { // Update drag selection this.dragValue = { start: new Date(this.dragValue.start.getTime()), end: new Date(day.dateTime), }; // Assign default content hover style this.dayContentHoverStyle_ = this.dayContentHoverStyle; } } }, // Ranges can privately have end date earlier than start date // This function will correct the order before exposing it to to other components normalizeRange(range) { if (!rangeHasValue(range)) return null; const { start, end } = range; const startTime = start.getTime(); const endTime = end.getTime(); const isNormal = start < end; return { start: isNormal ? start : end, startTime: isNormal ? startTime : endTime, end: isNormal ? end : start, endTime: isNormal ? endTime : startTime, }; }, }, }; </script> |