UNPKG

ngx-bootstrap-ci

Version:
1,474 lines (1,453 loc) • 422 kB
import { Injectable, Component, EventEmitter, Directive, ElementRef, Input, Output, Renderer2, ViewContainerRef, ChangeDetectorRef, forwardRef, Host, ChangeDetectionStrategy, NgModule, ViewChild } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { filter, map } from 'rxjs/operators'; import { getFullYear, getMonth, getDay, isFirstDayOfWeek, isAfter, isBefore, shiftDate, endOf, startOf, isSame, getFirstDayOfMonth, formatDate, getLocale, isDisabledDay, isSameDay, isSameMonth, isSameYear, setFullDate, isArray, isDateValid, parseDate, isDate } from 'ngx-bootstrap/chronos'; import { MiniStore, MiniState } from 'ngx-bootstrap/mini-ngrx'; import { PositioningService } from 'ngx-bootstrap/positioning'; import { ComponentLoaderFactory } from 'ngx-bootstrap/component-loader'; import { NG_VALIDATORS, NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; import { isBs3 } from 'ngx-bootstrap/utils'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * For date range picker there are `BsDaterangepickerConfig` which inherits all properties, * except `displayMonths`, for range picker it default to `2` */ class BsDatepickerConfig { constructor() { /** * sets use adaptive position */ this.adaptivePosition = false; /** * CSS class which will be applied to datepicker container, * usually used to set color theme */ this.containerClass = 'theme-green'; // DatepickerRenderOptions this.displayMonths = 1; /** * Allows to hide week numbers in datepicker */ this.showWeekNumbers = true; this.dateInputFormat = 'L'; // range picker this.rangeSeparator = ' - '; /** * Date format for date range input field */ this.rangeInputFormat = 'L'; // DatepickerFormatOptions this.monthTitle = 'MMMM'; this.yearTitle = 'YYYY'; this.dayLabel = 'D'; this.monthLabel = 'MMMM'; this.yearLabel = 'YYYY'; this.weekNumbers = 'w'; } } BsDatepickerConfig.decorators = [ { type: Injectable } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @abstract */ class BsDatepickerAbstractComponent { constructor() { this._customRangesFish = []; } /** * @param {?} value * @return {?} */ set minDate(value) { this._effects.setMinDate(value); } /** * @param {?} value * @return {?} */ set maxDate(value) { this._effects.setMaxDate(value); } /** * @param {?} value * @return {?} */ set daysDisabled(value) { this._effects.setDaysDisabled(value); } /** * @param {?} value * @return {?} */ set datesDisabled(value) { this._effects.setDatesDisabled(value); } /** * @param {?} value * @return {?} */ set isDisabled(value) { this._effects.setDisabled(value); } /** * @param {?} event * @return {?} */ setViewMode(event) { } /** * @param {?} event * @return {?} */ navigateTo(event) { } /** * @param {?} event * @return {?} */ dayHoverHandler(event) { } /** * @param {?} event * @return {?} */ weekHoverHandler(event) { } /** * @param {?} event * @return {?} */ monthHoverHandler(event) { } /** * @param {?} event * @return {?} */ yearHoverHandler(event) { } /** * @param {?} day * @return {?} */ daySelectHandler(day) { } /** * @param {?} event * @return {?} */ monthSelectHandler(event) { } /** * @param {?} event * @return {?} */ yearSelectHandler(event) { } /** * @param {?} event * @return {?} */ _stopPropagation(event) { event.stopPropagation(); } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class BsDatepickerActions { /** * @return {?} */ calculate() { return { type: BsDatepickerActions.CALCULATE }; } /** * @return {?} */ format() { return { type: BsDatepickerActions.FORMAT }; } /** * @return {?} */ flag() { return { type: BsDatepickerActions.FLAG }; } /** * @param {?} date * @return {?} */ select(date) { return { type: BsDatepickerActions.SELECT, payload: date }; } /** * @param {?} event * @return {?} */ changeViewMode(event) { return { type: BsDatepickerActions.CHANGE_VIEWMODE, payload: event }; } /** * @param {?} event * @return {?} */ navigateTo(event) { return { type: BsDatepickerActions.NAVIGATE_TO, payload: event }; } /** * @param {?} step * @return {?} */ navigateStep(step) { return { type: BsDatepickerActions.NAVIGATE_OFFSET, payload: step }; } /** * @param {?} options * @return {?} */ setOptions(options) { return { type: BsDatepickerActions.SET_OPTIONS, payload: options }; } /** * @param {?} value * @return {?} */ selectRange(value) { return { type: BsDatepickerActions.SELECT_RANGE, payload: value }; } /** * @param {?} event * @return {?} */ hoverDay(event) { return { type: BsDatepickerActions.HOVER, payload: event.isHovered ? event.cell.date : null }; } /** * @param {?} date * @return {?} */ minDate(date) { return { type: BsDatepickerActions.SET_MIN_DATE, payload: date }; } /** * @param {?} date * @return {?} */ maxDate(date) { return { type: BsDatepickerActions.SET_MAX_DATE, payload: date }; } /** * @param {?} days * @return {?} */ daysDisabled(days) { return { type: BsDatepickerActions.SET_DAYSDISABLED, payload: days }; } /** * @param {?} dates * @return {?} */ datesDisabled(dates) { return { type: BsDatepickerActions.SET_DATESDISABLED, payload: dates }; } /** * @param {?} value * @return {?} */ isDisabled(value) { return { type: BsDatepickerActions.SET_IS_DISABLED, payload: value }; } /** * @param {?} locale * @return {?} */ setLocale(locale) { return { type: BsDatepickerActions.SET_LOCALE, payload: locale }; } } BsDatepickerActions.CALCULATE = '[datepicker] calculate dates matrix'; BsDatepickerActions.FORMAT = '[datepicker] format datepicker values'; BsDatepickerActions.FLAG = '[datepicker] set flags'; BsDatepickerActions.SELECT = '[datepicker] select date'; BsDatepickerActions.NAVIGATE_OFFSET = '[datepicker] shift view date'; BsDatepickerActions.NAVIGATE_TO = '[datepicker] change view date'; BsDatepickerActions.SET_OPTIONS = '[datepicker] update render options'; BsDatepickerActions.HOVER = '[datepicker] hover date'; BsDatepickerActions.CHANGE_VIEWMODE = '[datepicker] switch view mode'; BsDatepickerActions.SET_MIN_DATE = '[datepicker] set min date'; BsDatepickerActions.SET_MAX_DATE = '[datepicker] set max date'; BsDatepickerActions.SET_DAYSDISABLED = '[datepicker] set days disabled'; BsDatepickerActions.SET_DATESDISABLED = '[datepicker] set dates disabled'; BsDatepickerActions.SET_IS_DISABLED = '[datepicker] set is disabled'; BsDatepickerActions.SET_LOCALE = '[datepicker] set datepicker locale'; BsDatepickerActions.SELECT_RANGE = '[daterangepicker] select dates range'; BsDatepickerActions.decorators = [ { type: Injectable } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class BsLocaleService { constructor() { this._defaultLocale = 'en'; this._locale = new BehaviorSubject(this._defaultLocale); this._localeChange = this._locale.asObservable(); } /** * @return {?} */ get locale() { return this._locale; } /** * @return {?} */ get localeChange() { return this._localeChange; } /** * @return {?} */ get currentLocale() { return this._locale.getValue(); } /** * @param {?} locale * @return {?} */ use(locale) { if (locale === this.currentLocale) { return; } this._locale.next(locale); } } BsLocaleService.decorators = [ { type: Injectable } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class BsDatepickerEffects { /** * @param {?} _actions * @param {?} _localeService */ constructor(_actions, _localeService) { this._actions = _actions; this._localeService = _localeService; this._subs = []; } /** * @param {?} _bsDatepickerStore * @return {?} */ init(_bsDatepickerStore) { this._store = _bsDatepickerStore; return this; } /** * setters * @param {?} value * @return {?} */ setValue(value) { this._store.dispatch(this._actions.select(value)); } /** * @param {?} value * @return {?} */ setRangeValue(value) { this._store.dispatch(this._actions.selectRange(value)); } /** * @param {?} value * @return {?} */ setMinDate(value) { this._store.dispatch(this._actions.minDate(value)); return this; } /** * @param {?} value * @return {?} */ setMaxDate(value) { this._store.dispatch(this._actions.maxDate(value)); return this; } /** * @param {?} value * @return {?} */ setDaysDisabled(value) { this._store.dispatch(this._actions.daysDisabled(value)); return this; } /** * @param {?} value * @return {?} */ setDatesDisabled(value) { this._store.dispatch(this._actions.datesDisabled(value)); return this; } /** * @param {?} value * @return {?} */ setDisabled(value) { this._store.dispatch(this._actions.isDisabled(value)); return this; } /** * @param {?} _config * @return {?} */ setOptions(_config) { const /** @type {?} */ _options = Object.assign({ locale: this._localeService.currentLocale }, _config); this._store.dispatch(this._actions.setOptions(_options)); return this; } /** * view to mode bindings * @param {?} container * @return {?} */ setBindings(container) { container.daysCalendar = this._store .select(state => state.flaggedMonths) .pipe(filter(months => !!months)); // month calendar container.monthsCalendar = this._store .select(state => state.flaggedMonthsCalendar) .pipe(filter(months => !!months)); // year calendar container.yearsCalendar = this._store .select(state => state.yearsCalendarFlagged) .pipe(filter(years => !!years)); container.viewMode = this._store.select(state => state.view.mode); container.options = this._store .select(state => state.showWeekNumbers) .pipe(map(showWeekNumbers => ({ showWeekNumbers }))); return this; } /** * event handlers * @param {?} container * @return {?} */ setEventHandlers(container) { container.setViewMode = (event) => { this._store.dispatch(this._actions.changeViewMode(event)); }; container.navigateTo = (event) => { this._store.dispatch(this._actions.navigateStep(event.step)); }; container.dayHoverHandler = (event) => { const /** @type {?} */ _cell = /** @type {?} */ (event.cell); if (_cell.isOtherMonth || _cell.isDisabled) { return; } this._store.dispatch(this._actions.hoverDay(event)); _cell.isHovered = event.isHovered; }; container.monthHoverHandler = (event) => { event.cell.isHovered = event.isHovered; }; container.yearHoverHandler = (event) => { event.cell.isHovered = event.isHovered; }; container.monthSelectHandler = (event) => { if (event.isDisabled) { return; } this._store.dispatch(this._actions.navigateTo({ unit: { month: getMonth(event.date), year: getFullYear(event.date) }, viewMode: 'day' })); }; container.yearSelectHandler = (event) => { if (event.isDisabled) { return; } this._store.dispatch(this._actions.navigateTo({ unit: { year: getFullYear(event.date) }, viewMode: 'month' })); }; return this; } /** * @return {?} */ registerDatepickerSideEffects() { this._subs.push(this._store.select(state => state.view).subscribe(view => { this._store.dispatch(this._actions.calculate()); })); // format calendar values on month model change this._subs.push(this._store .select(state => state.monthsModel) .pipe(filter(monthModel => !!monthModel)) .subscribe(month => this._store.dispatch(this._actions.format()))); // flag day values this._subs.push(this._store .select(state => state.formattedMonths) .pipe(filter(month => !!month)) .subscribe(month => this._store.dispatch(this._actions.flag()))); // flag day values this._subs.push(this._store .select(state => state.selectedDate) .pipe(filter(selectedDate => !!selectedDate)) .subscribe(selectedDate => this._store.dispatch(this._actions.flag()))); // flag for date range picker this._subs.push(this._store .select(state => state.selectedRange) .pipe(filter(selectedRange => !!selectedRange)) .subscribe(selectedRange => this._store.dispatch(this._actions.flag()))); // monthsCalendar this._subs.push(this._store .select(state => state.monthsCalendar) .subscribe(() => this._store.dispatch(this._actions.flag()))); // years calendar this._subs.push(this._store .select(state => state.yearsCalendarModel) .pipe(filter(state => !!state)) .subscribe(() => this._store.dispatch(this._actions.flag()))); // on hover this._subs.push(this._store .select(state => state.hoveredDate) .pipe(filter(hoveredDate => !!hoveredDate)) .subscribe(hoveredDate => this._store.dispatch(this._actions.flag()))); // on locale change this._subs.push(this._localeService.localeChange .subscribe(locale => this._store.dispatch(this._actions.setLocale(locale)))); return this; } /** * @return {?} */ destroy() { for (const /** @type {?} */ sub of this._subs) { sub.unsubscribe(); } } } BsDatepickerEffects.decorators = [ { type: Injectable } ]; /** @nocollapse */ BsDatepickerEffects.ctorParameters = () => [ { type: BsDatepickerActions, }, { type: BsLocaleService, }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ defaultMonthOptions = { width: 7, height: 6 }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ _initialView = { date: new Date(), mode: 'day' }; const /** @type {?} */ initialDatepickerState = Object.assign(new BsDatepickerConfig(), { locale: 'en', view: _initialView, selectedRange: [], monthViewOptions: defaultMonthOptions }); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?} date * @param {?} options * @return {?} */ function getStartingDayOfCalendar(date, options) { if (isFirstDayOfWeek(date, options.firstDayOfWeek)) { return date; } const /** @type {?} */ weekDay = getDay(date); const /** @type {?} */ offset = calculateDateOffset(weekDay, options.firstDayOfWeek); return shiftDate(date, { day: -offset }); } /** * @param {?} weekday * @param {?} startingDayOffset * @return {?} */ function calculateDateOffset(weekday, startingDayOffset) { if (startingDayOffset === 0) { return weekday; } const /** @type {?} */ offset = weekday - startingDayOffset % 7; return offset < 0 ? offset + 7 : offset; } /** * @param {?} date * @param {?} min * @param {?} max * @return {?} */ function isMonthDisabled(date, min, max) { const /** @type {?} */ minBound = min && isBefore(endOf(date, 'month'), min, 'day'); const /** @type {?} */ maxBound = max && isAfter(startOf(date, 'month'), max, 'day'); return minBound || maxBound; } /** * @param {?} date * @param {?} min * @param {?} max * @return {?} */ function isYearDisabled(date, min, max) { const /** @type {?} */ minBound = min && isBefore(endOf(date, 'year'), min, 'day'); const /** @type {?} */ maxBound = max && isAfter(startOf(date, 'year'), max, 'day'); return minBound || maxBound; } /** * @param {?} date * @param {?} datesDisabled * @return {?} */ function isDisabledDate(date, datesDisabled) { if (datesDisabled === undefined || !datesDisabled || !datesDisabled.length) { return false; } return datesDisabled.some((dateDisabled) => isSame(date, dateDisabled, 'date')); } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @template T * @param {?} options * @param {?} fn * @return {?} */ function createMatrix(options, fn) { let /** @type {?} */ prevValue = options.initialDate; const /** @type {?} */ matrix = new Array(options.height); for (let /** @type {?} */ i = 0; i < options.height; i++) { matrix[i] = new Array(options.width); for (let /** @type {?} */ j = 0; j < options.width; j++) { matrix[i][j] = fn(prevValue); prevValue = shiftDate(prevValue, options.shift); } } return matrix; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?} startingDate * @param {?} options * @return {?} */ function calcDaysCalendar(startingDate, options) { const /** @type {?} */ firstDay = getFirstDayOfMonth(startingDate); const /** @type {?} */ initialDate = getStartingDayOfCalendar(firstDay, options); const /** @type {?} */ matrixOptions = { width: options.width, height: options.height, initialDate, shift: { day: 1 } }; const /** @type {?} */ daysMatrix = createMatrix(matrixOptions, date => date); return { daysMatrix, month: firstDay }; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?} daysCalendar * @param {?} formatOptions * @param {?} monthIndex * @return {?} */ function formatDaysCalendar(daysCalendar, formatOptions, monthIndex) { return { month: daysCalendar.month, monthTitle: formatDate(daysCalendar.month, formatOptions.monthTitle, formatOptions.locale), yearTitle: formatDate(daysCalendar.month, formatOptions.yearTitle, formatOptions.locale), weekNumbers: getWeekNumbers(daysCalendar.daysMatrix, formatOptions.weekNumbers, formatOptions.locale), weekdays: getShiftedWeekdays(formatOptions.locale), weeks: daysCalendar.daysMatrix.map((week, weekIndex) => ({ days: week.map((date, dayIndex) => ({ date, label: formatDate(date, formatOptions.dayLabel, formatOptions.locale), monthIndex, weekIndex, dayIndex })) })) }; } /** * @param {?} daysMatrix * @param {?} format * @param {?} locale * @return {?} */ function getWeekNumbers(daysMatrix, format, locale) { return daysMatrix.map((days) => (days[0] ? formatDate(days[0], format, locale) : '')); } /** * @param {?} locale * @return {?} */ function getShiftedWeekdays(locale) { const /** @type {?} */ _locale = getLocale(locale); const /** @type {?} */ weekdays = /** @type {?} */ (_locale.weekdaysShort()); const /** @type {?} */ firstDayOfWeek = _locale.firstDayOfWeek(); return [...weekdays.slice(firstDayOfWeek), ...weekdays.slice(0, firstDayOfWeek)]; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?} formattedMonth * @param {?} options * @return {?} */ function flagDaysCalendar(formattedMonth, options) { formattedMonth.weeks.forEach((week) => { /* tslint:disable-next-line: cyclomatic-complexity */ week.days.forEach((day, dayIndex) => { // datepicker const /** @type {?} */ isOtherMonth = !isSameMonth(day.date, formattedMonth.month); const /** @type {?} */ isHovered = !isOtherMonth && isSameDay(day.date, options.hoveredDate); // date range picker const /** @type {?} */ isSelectionStart = !isOtherMonth && options.selectedRange && isSameDay(day.date, options.selectedRange[0]); const /** @type {?} */ isSelectionEnd = !isOtherMonth && options.selectedRange && isSameDay(day.date, options.selectedRange[1]); const /** @type {?} */ isSelected = (!isOtherMonth && isSameDay(day.date, options.selectedDate)) || isSelectionStart || isSelectionEnd; const /** @type {?} */ isInRange = !isOtherMonth && options.selectedRange && isDateInRange(day.date, options.selectedRange, options.hoveredDate); const /** @type {?} */ isDisabled = options.isDisabled || isBefore(day.date, options.minDate, 'day') || isAfter(day.date, options.maxDate, 'day') || isDisabledDay(day.date, options.daysDisabled) || isDisabledDate(day.date, options.datesDisabled); const /** @type {?} */ currentDate = new Date(); const /** @type {?} */ isToday = !isOtherMonth && isSameDay(day.date, currentDate); // decide update or not const /** @type {?} */ newDay = Object.assign({}, day, { isOtherMonth, isHovered, isSelected, isSelectionStart, isSelectionEnd, isInRange, isDisabled, isToday }); if (day.isOtherMonth !== newDay.isOtherMonth || day.isHovered !== newDay.isHovered || day.isSelected !== newDay.isSelected || day.isSelectionStart !== newDay.isSelectionStart || day.isSelectionEnd !== newDay.isSelectionEnd || day.isDisabled !== newDay.isDisabled || day.isInRange !== newDay.isInRange) { week.days[dayIndex] = newDay; } }); }); // todo: add check for linked calendars formattedMonth.hideLeftArrow = options.isDisabled || (options.monthIndex > 0 && options.monthIndex !== options.displayMonths); formattedMonth.hideRightArrow = options.isDisabled || (options.monthIndex < options.displayMonths && options.monthIndex + 1 !== options.displayMonths); formattedMonth.disableLeftArrow = isMonthDisabled(shiftDate(formattedMonth.month, { month: -1 }), options.minDate, options.maxDate); formattedMonth.disableRightArrow = isMonthDisabled(shiftDate(formattedMonth.month, { month: 1 }), options.minDate, options.maxDate); return formattedMonth; } /** * @param {?} date * @param {?} selectedRange * @param {?} hoveredDate * @return {?} */ function isDateInRange(date, selectedRange, hoveredDate) { if (!date || !selectedRange[0]) { return false; } if (selectedRange[1]) { return date > selectedRange[0] && date <= selectedRange[1]; } if (hoveredDate) { return date > selectedRange[0] && date <= hoveredDate; } return false; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?} mode * @param {?=} minMode * @return {?} */ function canSwitchMode(mode, minMode) { return minMode ? mode >= minMode : true; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ height = 4; const /** @type {?} */ width = 3; const /** @type {?} */ shift = { month: 1 }; /** * @param {?} viewDate * @param {?} formatOptions * @return {?} */ function formatMonthsCalendar(viewDate, formatOptions) { const /** @type {?} */ initialDate = startOf(viewDate, 'year'); const /** @type {?} */ matrixOptions = { width, height, initialDate, shift }; const /** @type {?} */ monthMatrix = createMatrix(matrixOptions, date => ({ date, label: formatDate(date, formatOptions.monthLabel, formatOptions.locale) })); return { months: monthMatrix, monthTitle: '', yearTitle: formatDate(viewDate, formatOptions.yearTitle, formatOptions.locale) }; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?} monthCalendar * @param {?} options * @return {?} */ function flagMonthsCalendar(monthCalendar, options) { monthCalendar.months.forEach((months, rowIndex) => { months.forEach((month, monthIndex) => { const /** @type {?} */ isHovered = isSameMonth(month.date, options.hoveredMonth); const /** @type {?} */ isDisabled = options.isDisabled || isMonthDisabled(month.date, options.minDate, options.maxDate); const /** @type {?} */ newMonth = Object.assign(/*{},*/ month, { isHovered, isDisabled }); if (month.isHovered !== newMonth.isHovered || month.isDisabled !== newMonth.isDisabled) { monthCalendar.months[rowIndex][monthIndex] = newMonth; } }); }); // todo: add check for linked calendars monthCalendar.hideLeftArrow = options.monthIndex > 0 && options.monthIndex !== options.displayMonths; monthCalendar.hideRightArrow = options.monthIndex < options.displayMonths && options.monthIndex + 1 !== options.displayMonths; monthCalendar.disableLeftArrow = isYearDisabled(shiftDate(monthCalendar.months[0][0].date, { year: -1 }), options.minDate, options.maxDate); monthCalendar.disableRightArrow = isYearDisabled(shiftDate(monthCalendar.months[0][0].date, { year: 1 }), options.minDate, options.maxDate); return monthCalendar; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ height$1 = 4; const /** @type {?} */ width$1 = 4; const /** @type {?} */ yearsPerCalendar = height$1 * width$1; const /** @type {?} */ initialShift = (Math.floor(yearsPerCalendar / 2) - 1) * -1; const /** @type {?} */ shift$1 = { year: 1 }; /** * @param {?} viewDate * @param {?} formatOptions * @return {?} */ function formatYearsCalendar(viewDate, formatOptions) { const /** @type {?} */ initialDate = shiftDate(viewDate, { year: initialShift }); const /** @type {?} */ matrixOptions = { width: width$1, height: height$1, initialDate, shift: shift$1 }; const /** @type {?} */ yearsMatrix = createMatrix(matrixOptions, date => ({ date, label: formatDate(date, formatOptions.yearLabel, formatOptions.locale) })); const /** @type {?} */ yearTitle = formatYearRangeTitle(yearsMatrix, formatOptions); return { years: yearsMatrix, monthTitle: '', yearTitle }; } /** * @param {?} yearsMatrix * @param {?} formatOptions * @return {?} */ function formatYearRangeTitle(yearsMatrix, formatOptions) { const /** @type {?} */ from = formatDate(yearsMatrix[0][0].date, formatOptions.yearTitle, formatOptions.locale); const /** @type {?} */ to = formatDate(yearsMatrix[height$1 - 1][width$1 - 1].date, formatOptions.yearTitle, formatOptions.locale); return `${from} - ${to}`; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?} yearsCalendar * @param {?} options * @return {?} */ function flagYearsCalendar(yearsCalendar, options) { yearsCalendar.years.forEach((years, rowIndex) => { years.forEach((year, yearIndex) => { const /** @type {?} */ isHovered = isSameYear(year.date, options.hoveredYear); const /** @type {?} */ isDisabled = options.isDisabled || isYearDisabled(year.date, options.minDate, options.maxDate); const /** @type {?} */ newMonth = Object.assign(/*{},*/ year, { isHovered, isDisabled }); if (year.isHovered !== newMonth.isHovered || year.isDisabled !== newMonth.isDisabled) { yearsCalendar.years[rowIndex][yearIndex] = newMonth; } }); }); // todo: add check for linked calendars yearsCalendar.hideLeftArrow = options.yearIndex > 0 && options.yearIndex !== options.displayMonths; yearsCalendar.hideRightArrow = options.yearIndex < options.displayMonths && options.yearIndex + 1 !== options.displayMonths; yearsCalendar.disableLeftArrow = isYearDisabled(shiftDate(yearsCalendar.years[0][0].date, { year: -1 }), options.minDate, options.maxDate); const /** @type {?} */ i = yearsCalendar.years.length - 1; const /** @type {?} */ j = yearsCalendar.years[i].length - 1; yearsCalendar.disableRightArrow = isYearDisabled(shiftDate(yearsCalendar.years[i][j].date, { year: 1 }), options.minDate, options.maxDate); return yearsCalendar; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?=} state * @param {?=} action * @return {?} */ function bsDatepickerReducer(state = initialDatepickerState, action) { switch (action.type) { case BsDatepickerActions.CALCULATE: { return calculateReducer(state); } case BsDatepickerActions.FORMAT: { return formatReducer(state, action); } case BsDatepickerActions.FLAG: { return flagReducer(state, action); } case BsDatepickerActions.NAVIGATE_OFFSET: { const /** @type {?} */ date = shiftDate(startOf(state.view.date, 'month'), action.payload); const /** @type {?} */ newState = { view: { mode: state.view.mode, date } }; return Object.assign({}, state, newState); } case BsDatepickerActions.NAVIGATE_TO: { const /** @type {?} */ payload = action.payload; const /** @type {?} */ date = setFullDate(state.view.date, payload.unit); let /** @type {?} */ newState; let /** @type {?} */ mode; if (canSwitchMode(payload.viewMode, state.minMode)) { mode = payload.viewMode; newState = { view: { date, mode } }; } else { mode = state.view.mode; newState = { selectedDate: date, view: { date, mode } }; } return Object.assign({}, state, newState); } case BsDatepickerActions.CHANGE_VIEWMODE: { if (!canSwitchMode(action.payload, state.minMode)) { return state; } const /** @type {?} */ date = state.view.date; const /** @type {?} */ mode = action.payload; const /** @type {?} */ newState = { view: { date, mode } }; return Object.assign({}, state, newState); } case BsDatepickerActions.HOVER: { return Object.assign({}, state, { hoveredDate: action.payload }); } case BsDatepickerActions.SELECT: { const /** @type {?} */ newState = { selectedDate: action.payload, view: state.view }; const /** @type {?} */ mode = state.view.mode; const /** @type {?} */ _date = action.payload || state.view.date; const /** @type {?} */ date = getViewDate(_date, state.minDate, state.maxDate); newState.view = { mode, date }; return Object.assign({}, state, newState); } case BsDatepickerActions.SET_OPTIONS: { const /** @type {?} */ newState = action.payload; // preserve view mode const /** @type {?} */ mode = newState.minMode ? newState.minMode : state.view.mode; const /** @type {?} */ _viewDate = isDateValid(newState.value) && newState.value || isArray(newState.value) && isDateValid(newState.value[0]) && newState.value[0] || state.view.date; const /** @type {?} */ date = getViewDate(_viewDate, newState.minDate, newState.maxDate); newState.view = { mode, date }; // update selected value if (newState.value) { // if new value is array we work with date range if (isArray(newState.value)) { newState.selectedRange = newState.value; } // if new value is a date -> datepicker if (newState.value instanceof Date) { newState.selectedDate = newState.value; } // provided value is not supported :) // need to report it somehow } return Object.assign({}, state, newState); } // date range picker case BsDatepickerActions.SELECT_RANGE: { const /** @type {?} */ newState = { selectedRange: action.payload, view: state.view }; const /** @type {?} */ mode = state.view.mode; const /** @type {?} */ _date = action.payload && action.payload[0] || state.view.date; const /** @type {?} */ date = getViewDate(_date, state.minDate, state.maxDate); newState.view = { mode, date }; return Object.assign({}, state, newState); } case BsDatepickerActions.SET_MIN_DATE: { return Object.assign({}, state, { minDate: action.payload }); } case BsDatepickerActions.SET_MAX_DATE: { return Object.assign({}, state, { maxDate: action.payload }); } case BsDatepickerActions.SET_IS_DISABLED: { return Object.assign({}, state, { isDisabled: action.payload }); } default: return state; } } /** * @param {?} state * @return {?} */ function calculateReducer(state) { // how many calendars const /** @type {?} */ displayMonths = state.displayMonths; // use selected date on initial rendering if set let /** @type {?} */ viewDate = state.view.date; if (state.view.mode === 'day') { state.monthViewOptions.firstDayOfWeek = getLocale(state.locale).firstDayOfWeek(); const /** @type {?} */ monthsModel = new Array(displayMonths); for (let /** @type {?} */ monthIndex = 0; monthIndex < displayMonths; monthIndex++) { // todo: for unlinked calendars it will be harder monthsModel[monthIndex] = calcDaysCalendar(viewDate, state.monthViewOptions); viewDate = shiftDate(viewDate, { month: 1 }); } return Object.assign({}, state, { monthsModel }); } if (state.view.mode === 'month') { const /** @type {?} */ monthsCalendar = new Array(displayMonths); for (let /** @type {?} */ calendarIndex = 0; calendarIndex < displayMonths; calendarIndex++) { // todo: for unlinked calendars it will be harder monthsCalendar[calendarIndex] = formatMonthsCalendar(viewDate, getFormatOptions(state)); viewDate = shiftDate(viewDate, { year: 1 }); } return Object.assign({}, state, { monthsCalendar }); } if (state.view.mode === 'year') { const /** @type {?} */ yearsCalendarModel = new Array(displayMonths); for (let /** @type {?} */ calendarIndex = 0; calendarIndex < displayMonths; calendarIndex++) { // todo: for unlinked calendars it will be harder yearsCalendarModel[calendarIndex] = formatYearsCalendar(viewDate, getFormatOptions(state)); viewDate = shiftDate(viewDate, { year: yearsPerCalendar }); } return Object.assign({}, state, { yearsCalendarModel }); } return state; } /** * @param {?} state * @param {?} action * @return {?} */ function formatReducer(state, action) { if (state.view.mode === 'day') { const /** @type {?} */ formattedMonths = state.monthsModel.map((month, monthIndex) => formatDaysCalendar(month, getFormatOptions(state), monthIndex)); return Object.assign({}, state, { formattedMonths }); } // how many calendars const /** @type {?} */ displayMonths = state.displayMonths; // check initial rendering // use selected date on initial rendering if set let /** @type {?} */ viewDate = state.view.date; if (state.view.mode === 'month') { const /** @type {?} */ monthsCalendar = new Array(displayMonths); for (let /** @type {?} */ calendarIndex = 0; calendarIndex < displayMonths; calendarIndex++) { // todo: for unlinked calendars it will be harder monthsCalendar[calendarIndex] = formatMonthsCalendar(viewDate, getFormatOptions(state)); viewDate = shiftDate(viewDate, { year: 1 }); } return Object.assign({}, state, { monthsCalendar }); } if (state.view.mode === 'year') { const /** @type {?} */ yearsCalendarModel = new Array(displayMonths); for (let /** @type {?} */ calendarIndex = 0; calendarIndex < displayMonths; calendarIndex++) { // todo: for unlinked calendars it will be harder yearsCalendarModel[calendarIndex] = formatYearsCalendar(viewDate, getFormatOptions(state)); viewDate = shiftDate(viewDate, { year: 16 }); } return Object.assign({}, state, { yearsCalendarModel }); } return state; } /** * @param {?} state * @param {?} action * @return {?} */ function flagReducer(state, action) { if (state.view.mode === 'day') { const /** @type {?} */ flaggedMonths = state.formattedMonths.map((formattedMonth, monthIndex) => flagDaysCalendar(formattedMonth, { isDisabled: state.isDisabled, minDate: state.minDate, maxDate: state.maxDate, daysDisabled: state.daysDisabled, datesDisabled: state.datesDisabled, hoveredDate: state.hoveredDate, selectedDate: state.selectedDate, selectedRange: state.selectedRange, displayMonths: state.displayMonths, monthIndex })); return Object.assign({}, state, { flaggedMonths }); } if (state.view.mode === 'month') { const /** @type {?} */ flaggedMonthsCalendar = state.monthsCalendar.map((formattedMonth, monthIndex) => flagMonthsCalendar(formattedMonth, { isDisabled: state.isDisabled, minDate: state.minDate, maxDate: state.maxDate, hoveredMonth: state.hoveredMonth, displayMonths: state.displayMonths, monthIndex })); return Object.assign({}, state, { flaggedMonthsCalendar }); } if (state.view.mode === 'year') { const /** @type {?} */ yearsCalendarFlagged = state.yearsCalendarModel.map((formattedMonth, yearIndex) => flagYearsCalendar(formattedMonth, { isDisabled: state.isDisabled, minDate: state.minDate, maxDate: state.maxDate, hoveredYear: state.hoveredYear, displayMonths: state.displayMonths, yearIndex })); return Object.assign({}, state, { yearsCalendarFlagged }); } return state; } /** * @param {?} state * @return {?} */ function getFormatOptions(state) { return { locale: state.locale, monthTitle: state.monthTitle, yearTitle: state.yearTitle, dayLabel: state.dayLabel, monthLabel: state.monthLabel, yearLabel: state.yearLabel, weekNumbers: state.weekNumbers }; } /** * if view date is provided (bsValue|ngModel) it should be shown * if view date is not provider: * if minDate>currentDate (default view value), show minDate * if maxDate<currentDate(default view value) show maxDate * @param {?} viewDate * @param {?} minDate * @param {?} maxDate * @return {?} */ function getViewDate(viewDate, minDate, maxDate) { const /** @type {?} */ _date = Array.isArray(viewDate) ? viewDate[0] : viewDate; if (minDate && isAfter(minDate, _date, 'day')) { return minDate; } if (maxDate && isBefore(maxDate, _date, 'day')) { return maxDate; } return _date; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class BsDatepickerStore extends MiniStore { constructor() { const /** @type {?} */ _dispatcher = new BehaviorSubject({ type: '[datepicker] dispatcher init' }); const /** @type {?} */ state = new MiniState(initialDatepickerState, _dispatcher, bsDatepickerReducer); super(_dispatcher, bsDatepickerReducer, state); } } BsDatepickerStore.decorators = [ { type: Injectable } ]; /** @nocollapse */ BsDatepickerStore.ctorParameters = () => []; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class BsDatepickerContainerComponent extends BsDatepickerAbstractComponent { /** * @param {?} _config * @param {?} _store * @param {?} _actions * @param {?} _effects * @param {?} _positionService */ constructor(_config, _store, _actions, _effects, _positionService) { super(); this._config = _config; this._store = _store; this._actions = _actions; this._positionService = _positionService; this.valueChange = new EventEmitter(); this._subs = []; this._effects = _effects; } /** * @param {?} value * @return {?} */ set value(value) { this._effects.setValue(value); } /** * @return {?} */ ngOnInit() { this._positionService.setOptions({ modifiers: { flip: { enabled: this._config.adaptivePosition } } }); this.isOtherMonthsActive = this._config.selectFromOtherMonth; this.containerClass = this._config.containerClass; this._effects .init(this._store) .setOptions(this._config) .setBindings(this) .setEventHandlers(this) .registerDatepickerSideEffects(); // todo: move it somewhere else // on selected date change this._subs.push(this._store .select((state) => state.selectedDate) .subscribe((date) => this.valueChange.emit(date))); } /** * @param {?} day * @return {?} */ daySelectHandler(day) { const /** @type {?} */ isDisabled = this.isOtherMonthsActive ? day.isDisabled : (day.isOtherMonth || day.isDisabled); if (isDisabled) { return; } this._store.dispatch(this._actions.select(day.date)); } /** * @return {?} */ ngOnDestroy() { for (const /** @type {?} */ sub of this._subs) { sub.unsubscribe(); } this._effects.destroy(); } } BsDatepickerContainerComponent.decorators = [ { type: Component, args: [{ selector: 'bs-datepicker-container', providers: [BsDatepickerStore, BsDatepickerEffects], template: "<!-- days calendar view mode -->\n<div class=\"bs-datepicker\" [ngClass]=\"containerClass\" *ngIf=\"viewMode | async\">\n <div class=\"bs-datepicker-container\">\n\n <!--calendars-->\n <div class=\"bs-calendar-container\" [ngSwitch]=\"viewMode | async\" role=\"application\">\n <!--days calendar-->\n <div *ngSwitchCase=\"'day'\" class=\"bs-media-container\">\n <bs-days-calendar-view\n *ngFor=\"let calendar of (daysCalendar | async)\"\n [class.bs-datepicker-multiple]=\"(daysCalendar | async)?.length > 1\"\n [calendar]=\"calendar\"\n [options]=\"options | async\"\n (onNavigate)=\"navigateTo($event)\"\n (onViewMode)=\"setViewMode($event)\"\n (onHover)=\"dayHoverHandler($event)\"\n (onHoverWeek)=\"weekHoverHandler($event)\"\n (onSelect)=\"daySelectHandler($event)\"\n ></bs-days-calendar-view>\n </div>\n\n <!--months calendar-->\n <div *ngSwitchCase=\"'month'\" class=\"bs-media-container\">\n <bs-month-calendar-view\n *ngFor=\"let calendar of (monthsCalendar | async)\"\n [class.bs-datepicker-multiple]=\"(daysCalendar | async)?.length > 1\"\n [calendar]=\"calendar\"\n (onNavigate)=\"navigateTo($event)\"\n (onViewMode)=\"setViewMode($event)\"\n (onHover)=\"monthHoverHandler($event)\"\n (onSelect)=\"monthSelectHandler($event)\"\n ></bs-month-calendar-view>\n </div>\n\n <!--years calendar-->\n <div *ngSwitchCase=\"'year'\" class=\"bs-media-container\">\n <bs-years-calendar-view\n *ngFor=\"let calendar of (yearsCalendar | async)\"\n [class.bs-datepicker-multiple]=\"(daysCalendar | async )?.length > 1\"\n [calendar]=\"calendar\"\n (onNavigate)=\"navigateTo($event)\"\n (onViewMode)=\"setViewMode($event)\"\n (onHover)=\"yearHoverHandler($event)\"\n (onSelect)=\"yearSelectHandler($event)\"\n ></bs-years-calendar-view>\n </div>\n\n </div>\n\n <!--applycancel buttons-->\n <div class=\"bs-datepicker-buttons\" *ngIf=\"false\">\n <button class=\"btn btn-success\">Apply</button>\n <button class=\"btn btn-default\">Cancel</button>\n </div>\n\n </div>\n\n <!--custom dates or date ranges picker-->\n <div class=\"bs-datepicker-custom-range\" *ngIf=\"false\">\n <bs-custom-date-view [ranges]=\"_customRangesFish\"></bs-custom-date-view>\n </div>\n</div>\n", host: { '(click)': '_stopPropagation($event)', style: 'position: absolute; display: block;', role: 'dialog', 'aria-label': 'calendar' } }] } ]; /** @nocollapse */ BsDatepickerContainerComponent.ctorParameters = () => [ { type: BsDatepickerConfig, }, { type: BsDatepickerStore, }, { type: BsDatepickerActions, }, { type: BsDatepickerEffects, }, { type: PositioningService, }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class BsDatepickerDirective { /** * @param {?} _config * @param {?} _elementRef * @param {?} _renderer * @param {?} _viewContainerRef * @param {?} cis */ constructor(_config, _elementRef, _renderer, _viewContainerRef, cis) { this._config = _config; /** * Placement of a datepicker. Accepts: "top", "bottom", "left", "right" */ this.placement = 'bottom'; /** * Specifies events that should trigger. Supports a space separated list of * event names. */ this.triggers = 'click'; /** * Close datepicker on outside click */ this.outsideClick = true; /** * A selector specifying the element the datepicker should be appended to. * Currently only supports "body". */ this.container = 'body'; this.outsideEsc = true; /** * Emits when datepicker value has been changed */ this.bsValueChange = new EventEmitter(); this._subs = []; // todo: assign only subset of fields Object.assign(this, this._config); this._datepicker = cis.createLoader(_elementRef, _viewContainerRef, _renderer); this.onShown = this._datepicker.onShown; this.onHidden = this._datepicker.onHidden; } /** * Returns whether or not the datepicker is currently being shown * @return {?} */ get isOpen() { return this._datepicker.isShown; } /** * @param {?} value * @return {?} */ set isOpen(value) { if (value) { this.show(); } else { this.hide(); } } /** * Init