@gitlab/ui
Version:
GitLab UI Components
326 lines (315 loc) • 10.2 kB
JavaScript
import uniqueId from 'lodash/uniqueId';
import { GlTooltipDirective } from '../../../directives/tooltip/tooltip';
import { getDateInPast, getDateInFuture, getDayDifference } from '../../../utils/datetime_utility';
import GlDatepicker from '../datepicker/datepicker';
import GlIcon from '../icon/icon';
import { datepickerWidthOptionsMap } from '../../../utils/constants';
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
const CONTAINER_CLASSES = ['gl-flex', 'gl-items-baseline', 'gl-flex-wrap', 'sm:gl-flex-nowrap', 'sm:gl-gap-3'];
var script = {
name: 'GlDaterangePicker',
components: {
GlDatepicker,
GlIcon
},
directives: {
GlTooltip: GlTooltipDirective
},
props: {
fromLabel: {
type: String,
required: false,
default: 'From'
},
toLabel: {
type: String,
required: false,
default: 'To'
},
fromAriaLabel: {
type: String,
required: false,
default: 'From date'
},
toAriaLabel: {
type: String,
required: false,
default: 'To date'
},
value: {
type: Object,
required: false,
default: null
},
i18n: {
type: Object,
required: false,
default: null
},
defaultMinDate: {
type: Date,
required: false,
default: null
},
defaultMaxDate: {
type: Date,
required: false,
default: null
},
defaultStartDate: {
type: Date,
required: false,
default: null
},
defaultEndDate: {
type: Date,
required: false,
default: null
},
maxDateRange: {
type: Number,
required: false,
default: 0
},
startPickerClass: {
type: String,
required: false,
default: ''
},
startPickerTarget: {
type: String,
required: false,
default: ''
},
startPickerContainer: {
type: String,
required: false,
default: ''
},
startPickerState: {
type: Boolean,
required: false,
default: null
},
endPickerClass: {
type: String,
required: false,
default: ''
},
endPickerTarget: {
type: String,
required: false,
default: ''
},
endPickerContainer: {
type: String,
required: false,
default: ''
},
endPickerState: {
type: Boolean,
required: false,
default: null
},
labelClass: {
type: String,
required: false,
default: ''
},
theme: {
type: String,
required: false,
default: ''
},
sameDaySelection: {
type: Boolean,
required: false,
default: false
},
/**
* If provided, renders an info icon with a tooltip.
*/
tooltip: {
type: String,
required: false,
default: ''
},
/**
* Additional class(es) to apply to the date range indicator section.
*/
dateRangeIndicatorClass: {
type: [String, Object, Array],
required: false,
default: ''
},
startOpened: {
type: Boolean,
required: false,
default: false
},
/**
* Maximum width of the Datepicker
*/
width: {
type: String,
required: false,
default: null,
validator: value => Object.keys(datepickerWidthOptionsMap).includes(value)
}
},
data() {
return {
fromCalendarMaxDate: this.defaultMaxDate ? getDateInPast(this.defaultMaxDate, 1) : null,
startDate: this.defaultStartDate,
endDate: this.defaultEndDate,
openToCalendar: false
};
},
computed: {
effectiveMaxDateRange() {
return this.sameDaySelection ? this.maxDateRange - 1 : this.maxDateRange;
},
toCalendarMinDate() {
if (!this.startDate) return null;
return this.sameDaySelection ? this.startDate : getDateInFuture(this.startDate, 1);
},
toCalendarMaxDate() {
if (!this.startDate || !this.maxDateRange) return this.defaultMaxDate;
const computedMaxEndDate = getDateInFuture(this.startDate, this.effectiveMaxDateRange);
return new Date(Math.min(computedMaxEndDate, this.defaultMaxDate));
},
dateRangeViolation() {
return this.startDate >= this.endDate || this.exceedsDateRange;
},
exceedsDateRange() {
if (this.numberOfDays < 0) {
return false;
}
return this.maxDateRange && this.numberOfDays > this.maxDateRange;
},
toCalendarDefaultDate() {
return this.endDate || this.toCalendarMinDate;
},
numericStartTime() {
return this.startDate ? this.startDate.getTime() : null;
},
numberOfDays() {
if (!this.startDate || !this.endDate) {
return -1;
}
const numberOfDays = getDayDifference(this.startDate, this.endDate);
return this.sameDaySelection ? numberOfDays + 1 : numberOfDays;
},
startContainerClasses() {
return [this.startPickerClass, ...CONTAINER_CLASSES];
},
endContainerClasses() {
return [this.endPickerClass, ...CONTAINER_CLASSES];
},
showIndicator() {
return Boolean(this.$scopedSlots.default || this.tooltip);
},
fromId() {
return uniqueId('date-from-field-');
},
toId() {
return uniqueId('date-to-field-');
}
},
watch: {
value(val) {
const {
startDate,
endDate
} = val;
this.startDate = startDate;
this.endDate = endDate;
}
},
methods: {
onStartDateSelected(startDate) {
this.startDate = startDate;
if (this.dateRangeViolation) {
this.openToCalendar = true;
this.endDate = null;
} else this.$emit('input', {
startDate,
endDate: this.endDate
});
},
onEndDateSelected(endDate) {
this.openToCalendar = false;
this.endDate = endDate;
/**
* Emitted when start or end date selected with {startDate, endDate} value
*
* @event input
* */
this.$emit('input', {
startDate: this.startDate,
endDate
});
},
onStartPickerOpen() {
/**
* Emitted when the primary action button is clicked.
*
* @event start-picker-open
* */
this.$emit('start-picker-open');
},
onStartPickerClose() {
/**
* Emitted when the start date datepicker is hidden.
*
* @event start-picker-close
* */
this.$emit('start-picker-close');
},
onEndPickerOpen() {
/**
* Emitted when the end date datepicker becomes visible.
*
* @event end-picker-open
* */
this.$emit('end-picker-open');
},
onEndPickerClose() {
/**
* Emitted when the end date datepicker is hidden.
*
* @event end-picker-close
* */
this.$emit('end-picker-close');
}
}
};
/* script */
const __vue_script__ = script;
/* template */
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-daterange-picker gl-flex gl-gap-5"},[_c('div',{class:_vm.startContainerClasses,attrs:{"data-testid":"daterange-picker-start-container"}},[_c('label',{class:_vm.labelClass,attrs:{"for":_vm.fromId}},[_vm._v(_vm._s(_vm.fromLabel))]),_vm._v(" "),_c('gl-datepicker',{attrs:{"input-id":_vm.fromId,"input-label":_vm.fromAriaLabel,"min-date":_vm.defaultMinDate,"max-date":_vm.fromCalendarMaxDate,"start-range":_vm.defaultMinDate,"end-range":_vm.fromCalendarMaxDate,"theme":_vm.theme,"i18n":_vm.i18n,"target":_vm.startPickerTarget,"container":_vm.startPickerContainer,"start-opened":_vm.startOpened,"state":_vm.startPickerState,"width":_vm.width},on:{"input":_vm.onStartDateSelected,"open":_vm.onStartPickerOpen,"close":_vm.onStartPickerClose},scopedSlots:_vm._u([{key:"after",fn:function(){return [_vm._t("after-start")]},proxy:true}],null,true),model:{value:(_vm.startDate),callback:function ($$v) {_vm.startDate=$$v;},expression:"startDate"}})],1),_vm._v(" "),_c('div',{class:_vm.endContainerClasses,attrs:{"data-testid":"daterange-picker-end-container"}},[_c('label',{class:_vm.labelClass,attrs:{"for":_vm.toId}},[_vm._v(_vm._s(_vm.toLabel))]),_vm._v(" "),_c('gl-datepicker',{key:_vm.numericStartTime,attrs:{"input-id":_vm.toId,"input-label":_vm.toAriaLabel,"min-date":_vm.toCalendarMinDate,"max-date":_vm.toCalendarMaxDate,"start-range":_vm.toCalendarMinDate,"end-range":_vm.toCalendarMaxDate,"theme":_vm.theme,"i18n":_vm.i18n,"target":_vm.endPickerTarget,"container":_vm.endPickerContainer,"start-opened":_vm.openToCalendar,"default-date":_vm.toCalendarDefaultDate,"width":_vm.width,"state":_vm.endPickerState},on:{"input":_vm.onEndDateSelected,"open":_vm.onEndPickerOpen,"close":_vm.onEndPickerClose},scopedSlots:_vm._u([{key:"after",fn:function(){return [_vm._t("after-end")]},proxy:true}],null,true),model:{value:(_vm.endDate),callback:function ($$v) {_vm.endDate=$$v;},expression:"endDate"}})],1),_vm._v(" "),(_vm.showIndicator)?_c('div',{staticClass:"gl-daterange-picker-indicator",class:_vm.dateRangeIndicatorClass,attrs:{"data-testid":"daterange-picker-indicator"}},[_vm._t("default",null,null,{ daysSelected: _vm.numberOfDays }),_vm._v(" "),(_vm.tooltip)?_c('gl-icon',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],attrs:{"name":"information-o","title":_vm.tooltip,"size":16,"variant":"info"}}):_vm._e()],2):_vm._e()])};
var __vue_staticRenderFns__ = [];
/* style */
const __vue_inject_styles__ = undefined;
/* scoped */
const __vue_scope_id__ = undefined;
/* module identifier */
const __vue_module_identifier__ = undefined;
/* functional template */
const __vue_is_functional_template__ = false;
/* style inject */
/* style inject SSR */
/* style inject shadow dom */
const __vue_component__ = /*#__PURE__*/__vue_normalize__(
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
__vue_inject_styles__,
__vue_script__,
__vue_scope_id__,
__vue_is_functional_template__,
__vue_module_identifier__,
false,
undefined,
undefined,
undefined
);
export { __vue_component__ as default };