@hxui/angular
Version:
This README includes the steps that are necessary to import the HxUi-angular into a project or to contribute with development.
1,473 lines (1,456 loc) • 642 kB
JavaScript
import { Injectable, ElementRef, Directive, HostListener, NgModule, Component, EventEmitter, Output, Input, forwardRef, TemplateRef, ReflectiveInjector, NgZone, ComponentFactoryResolver, Injector, Renderer2, ViewContainerRef, HostBinding, Optional, Inject, ViewChild, IterableDiffers, ViewEncapsulation, Pipe, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { NG_VALUE_ACCESSOR, NG_VALIDATORS, FormsModule, NgControl } from '@angular/forms';
import { CommonModule, DOCUMENT } from '@angular/common';
import { filter, takeUntil, take, debounceTime, mergeMap, toArray } from 'rxjs/operators';
import { __decorate } from 'tslib';
import { FocusTrapFactory, A11yModule } from '@angular/cdk/a11y';
import { cloneDeep, isEqual } from 'lodash';
import sortBy from 'array-sort-by';
import { Subject, Observable, from } from 'rxjs';
import { ComponentPortal, PortalModule } from '@angular/cdk/portal';
import { Overlay, ScrollDispatcher, OverlayModule } from '@angular/cdk/overlay';
import { Directionality } from '@angular/cdk/bidi';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule } from '@angular/router';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @copyright Valor Software
* @copyright Angular ng-bootstrap team
*/
class Positioning {
/**
* @param {?} element
* @param {?=} round
* @return {?}
*/
position(element, round = true) {
let /** @type {?} */ elPosition;
let /** @type {?} */ parentOffset = { width: 0, height: 0, top: 0, bottom: 0, left: 0, right: 0 };
if (this.getStyle(element, 'position') === 'fixed') {
elPosition = element.getBoundingClientRect();
}
else {
const /** @type {?} */ offsetParentEl = this.offsetParent(element);
elPosition = this.offset(element, false);
if (offsetParentEl !== document.documentElement) {
parentOffset = this.offset(offsetParentEl, false);
}
parentOffset.top += offsetParentEl.clientTop;
parentOffset.left += offsetParentEl.clientLeft;
}
elPosition.top -= parentOffset.top;
elPosition.bottom -= parentOffset.top;
elPosition.left -= parentOffset.left;
elPosition.right -= parentOffset.left;
if (round) {
elPosition.top = Math.round(elPosition.top);
elPosition.bottom = Math.round(elPosition.bottom);
elPosition.left = Math.round(elPosition.left);
elPosition.right = Math.round(elPosition.right);
}
return elPosition;
}
/**
* @param {?} element
* @param {?=} round
* @return {?}
*/
offset(element, round = true) {
const /** @type {?} */ elBcr = element.getBoundingClientRect();
const /** @type {?} */ viewportOffset = {
top: window.pageYOffset - document.documentElement.clientTop,
left: window.pageXOffset - document.documentElement.clientLeft
};
let /** @type {?} */ elOffset = {
height: elBcr.height || element.offsetHeight,
width: elBcr.width || element.offsetWidth,
top: elBcr.top + viewportOffset.top,
bottom: elBcr.bottom + viewportOffset.top,
left: elBcr.left + viewportOffset.left,
right: elBcr.right + viewportOffset.left
};
if (round) {
elOffset.height = Math.round(elOffset.height);
elOffset.width = Math.round(elOffset.width);
elOffset.top = Math.round(elOffset.top);
elOffset.bottom = Math.round(elOffset.bottom);
elOffset.left = Math.round(elOffset.left);
elOffset.right = Math.round(elOffset.right);
}
return elOffset;
}
/**
* @param {?} hostElement
* @param {?} targetElement
* @param {?} placement
* @param {?=} appendToBody
* @return {?}
*/
positionElements(hostElement, targetElement, placement, appendToBody) {
const /** @type {?} */ hostElPosition = appendToBody ? this.offset(hostElement, false) : this.position(hostElement, false);
const /** @type {?} */ shiftWidth = {
left: hostElPosition.left,
center: hostElPosition.left + hostElPosition.width / 2 - targetElement.offsetWidth / 2,
right: hostElPosition.left + hostElPosition.width
};
const /** @type {?} */ shiftHeight = {
top: hostElPosition.top,
center: hostElPosition.top + hostElPosition.height / 2 - targetElement.offsetHeight / 2,
bottom: hostElPosition.top + hostElPosition.height
};
const /** @type {?} */ targetElBCR = targetElement.getBoundingClientRect();
const /** @type {?} */ placementPrimary = placement.split(' ')[0] || 'top';
const /** @type {?} */ placementSecondary = placement.split(' ')[1] || 'center';
let /** @type {?} */ targetElPosition = {
height: targetElBCR.height || targetElement.offsetHeight,
width: targetElBCR.width || targetElement.offsetWidth,
top: 0,
bottom: targetElBCR.height || targetElement.offsetHeight,
left: 0,
right: targetElBCR.width || targetElement.offsetWidth
};
switch (placementPrimary) {
case 'top':
targetElPosition.top = hostElPosition.top - targetElement.offsetHeight;
targetElPosition.bottom += hostElPosition.top - targetElement.offsetHeight;
targetElPosition.left = shiftWidth[placementSecondary];
targetElPosition.right += shiftWidth[placementSecondary];
break;
case 'bottom':
targetElPosition.top = shiftHeight[placementPrimary];
targetElPosition.bottom += shiftHeight[placementPrimary];
targetElPosition.left = shiftWidth[placementSecondary];
targetElPosition.right += shiftWidth[placementSecondary];
break;
case 'left':
targetElPosition.top = shiftHeight[placementSecondary];
targetElPosition.bottom += shiftHeight[placementSecondary];
targetElPosition.left = hostElPosition.left - targetElement.offsetWidth;
targetElPosition.right += hostElPosition.left - targetElement.offsetWidth;
break;
case 'right':
targetElPosition.top = shiftHeight[placementSecondary];
targetElPosition.bottom += shiftHeight[placementSecondary];
targetElPosition.left = shiftWidth[placementPrimary];
targetElPosition.right += shiftWidth[placementPrimary];
break;
}
targetElPosition.top = Math.round(targetElPosition.top);
targetElPosition.bottom = Math.round(targetElPosition.bottom);
targetElPosition.left = Math.round(targetElPosition.left);
targetElPosition.right = Math.round(targetElPosition.right);
return targetElPosition;
}
/**
* @param {?} element
* @param {?} prop
* @return {?}
*/
getStyle(element, prop) { return (/** @type {?} */ (window.getComputedStyle(element)))[prop]; }
/**
* @param {?} element
* @return {?}
*/
isStaticPositioned(element) {
return (this.getStyle(element, 'position') || 'static') === 'static';
}
/**
* @param {?} element
* @return {?}
*/
offsetParent(element) {
let /** @type {?} */ offsetParentEl = /** @type {?} */ (element.offsetParent) || document.documentElement;
while (offsetParentEl && offsetParentEl !== document.documentElement && this.isStaticPositioned(offsetParentEl)) {
offsetParentEl = /** @type {?} */ (offsetParentEl.offsetParent);
}
return offsetParentEl || document.documentElement;
}
}
const /** @type {?} */ positionService = new Positioning();
/**
* @param {?} hostElement
* @param {?} targetElement
* @param {?} placement
* @param {?=} appendToBody
* @return {?}
*/
function positionElements(hostElement, targetElement, placement, appendToBody) {
const /** @type {?} */ pos = positionService.positionElements(hostElement, targetElement, placement, appendToBody);
targetElement.style.top = `${pos.top}px`;
targetElement.style.left = `${pos.left}px`;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class PositioningService {
/**
* @param {?} options
* @return {?}
*/
position(options) {
const { element, target, attachment, appendToBody } = options;
positionElements(this._getHtmlElement(target), this._getHtmlElement(element), /** @type {?} */ (attachment), appendToBody);
}
/**
* @param {?} element
* @return {?}
*/
isElementBelowTheFold(element) {
const /** @type {?} */ rect = element.getBoundingClientRect();
return ((rect.top + rect.height) > document.body.clientHeight);
}
/**
* @param {?} element
* @return {?}
*/
_getHtmlElement(element) {
// it means that we got a selector
if (typeof element === 'string') {
return /** @type {?} */ (document.querySelector(element));
}
if (element instanceof ElementRef) {
return element.nativeElement;
}
return /** @type {?} */ (element);
}
}
PositioningService.decorators = [
{ type: Injectable },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @abstract
*/
class PositioningOptions {
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class AutoGrowDirective {
/**
* @param {?} element
*/
constructor(element) {
this.element = element;
}
/**
* @return {?}
*/
onInput() {
this.resize();
}
/**
* @return {?}
*/
ngAfterViewInit() {
const /** @type {?} */ style = this.element.nativeElement.style;
style.overflow = 'hidden';
style.height = 'auto';
}
/**
* @return {?}
*/
resize() {
const /** @type {?} */ el = this.element.nativeElement;
if (el.style.height === el.scrollHeight + 'px') {
return;
}
el.style.overflow = 'hidden';
el.style.height = 'auto';
el.style.height = `${el.scrollHeight}px`;
}
}
AutoGrowDirective.decorators = [
{ type: Directive, args: [{
selector: 'textarea[autogrow]'
},] },
];
/** @nocollapse */
AutoGrowDirective.ctorParameters = () => [
{ type: ElementRef, },
];
AutoGrowDirective.propDecorators = {
"onInput": [{ type: HostListener, args: ['input', ['$event.target'],] },],
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class AutoGrowModule {
/**
* @return {?}
*/
static forRoot() {
return {
ngModule: AutoGrowModule, providers: []
};
}
;
}
AutoGrowModule.decorators = [
{ type: NgModule, args: [{
declarations: [
AutoGrowDirective
],
exports: [
AutoGrowDirective
]
},] },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class DatepickerComponent {
/**
* @param {?} hostElement
* @param {?} positioningService
*/
constructor(hostElement, positioningService) {
this.hostElement = hostElement;
this.positioningService = positioningService;
this.onDateSelected = new EventEmitter();
this.days = new Array();
this.week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
this.cellCount = 41;
}
/**
* @return {?}
*/
renderCalendar() {
for (let /** @type {?} */ i = 0; i <= this.cellCount; i++) {
// date will be set to the first day of the month set in this.viewDate
const /** @type {?} */ date = new Date(this.viewDate.getFullYear(), this.viewDate.getMonth());
// Shifts the week to start from Monday, rather than Sunday, this causes the index to start at 1
const /** @type {?} */ dayOffset = date.getDay() === 0 ? 7 : date.getDay();
this.days[i] = new Date(date.setDate(2 - dayOffset + i));
}
}
/**
* @return {?}
*/
positionCalendar() {
const /** @type {?} */ rect = this.hostElement.nativeElement.getBoundingClientRect();
const /** @type {?} */ buffer = 10;
if (this.positioningService.isElementBelowTheFold(this.hostElement.nativeElement)) {
this.hostElement.nativeElement.style.top = (rect.top - (rect.top + rect.height + buffer)) + 'px';
}
}
/**
* @return {?}
*/
previousMonth() {
this.viewDate = new Date(this.viewDate.getFullYear(), this.viewDate.getMonth() - 1);
this.renderCalendar();
}
/**
* @return {?}
*/
nextMonth() {
this.viewDate = new Date(this.viewDate.getFullYear(), this.viewDate.getMonth() + 1);
this.renderCalendar();
}
/**
* @param {?} inputDate
* @return {?}
*/
isCurrentMonth(inputDate) {
return inputDate.getMonth() === this.viewDate.getMonth();
}
/**
* @param {?} inputDate
* @return {?}
*/
isCurrentDay(inputDate) {
return inputDate.getTime() === this.presentDate.getTime();
}
/**
* @param {?} inputDate
* @return {?}
*/
isSelectedDay(inputDate) {
if (this.selectedDate) {
return inputDate.getTime() === this.selectedDate.getTime();
}
return false;
}
/**
* @param {?} inputDate
* @return {?}
*/
isInvalidDay(inputDate) {
return this.validators.map((fn) => fn(inputDate)).reduce((prev, next) => prev || next, false);
}
/**
* @param {?} date
* @return {?}
*/
setSelectedDate(date) {
if (!this.isInvalidDay(date)) {
this.selectedDate = date;
this.onDateSelected.emit(date);
}
}
/**
* @param {?} changes
* @return {?}
*/
ngOnChanges(changes) {
if (!!changes["selectedDate"].currentValue) {
this.viewDate = new Date(this.selectedDate.getFullYear(), this.selectedDate.getMonth());
}
}
/**
* @return {?}
*/
ngOnInit() {
const /** @type {?} */ date = new Date();
this.presentDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
this.viewDate = this.viewDate || new Date(date.getFullYear(), date.getMonth());
this.renderCalendar();
this.positionCalendar();
}
}
DatepickerComponent.decorators = [
{ type: Component, args: [{
selector: 'hxa-datepicker',
template: `<div class="hxui-reset">
<div class="hx-card hxa-datepicker-container">
<div class="hx-card-header hxa-datepicker-header">
<div class="hxa-datepicker-month">
<div class="hxa-datepicker-icon" title="Previous Month" (click)="previousMonth()">
<a class="hx-button is-transparent"><i class="hx-icon icon-angle-left"></i></a>
</div>
<div class="hxa-datepicker-month-title">
<span>{{viewDate.toLocaleString("en-au", { month: "long", year: "numeric" })}}</span></div>
<div class="hxa-datepicker-icon" title="Next Month" (click)="nextMonth()">
<a class="hx-button is-transparent"><i class="hx-icon icon-angle-right"></i></a>
</div>
</div>
<div class="hxa-datepicker-week">
<div class="hxa-datepicker-weekday" *ngFor="let weekday of week">
{{weekday | slice:0:3}}
</div>
</div>
</div>
<div class="hxa-datepicker-contents">
<div class="hxa-datepicker-day" *ngFor="let day of days"
[ngClass]="{'hxa-datepicker-day-siblingmonth': !isCurrentMonth(day),
'hxa-datepicker-day-currentday': isCurrentDay(day),
'hxa-datepicker-day-selectedday': isSelectedDay(day),
'hxa-datepicker-day-invalidday': isInvalidDay(day)}"
(click)="setSelectedDate(day)">
<a class="hx-button is-transparent">{{day.getDate()}}</a>
</div>
</div>
</div>
</div>`,
styles: [`.hxa-datepicker-container{max-width:21em;width:21em;height:24em;display:flex;flex-direction:column;font-size:1rem}.hxa-datepicker-header{padding:1rem 1rem 0;flex-direction:column;align-items:initial;justify-content:space-around;font-weight:100}.hxa-datepicker-icon{cursor:pointer;display:flex;flex:1;flex-direction:column;justify-content:center;align-items:center}.hxa-datepicker-icon .hx-button{position:initial!important;top:initial!important}.hxa-datepicker-icon .hx-button.is-transparent:hover{color:#000}.hxa-datepicker-icon .hx-icon{font-size:2.3em;position:initial!important;top:initial!important;color:#0d4d78}.hxa-datepicker-month{display:flex;text-align:center;margin-bottom:1rem}.hxa-datepicker-month-title{font-size:1.5em;flex:3;display:flex;justify-content:center;align-items:center;color:#0d4d78}.hxa-datepicker-week{display:flex;width:100%;text-align:center}.hxa-datepicker-weekday{flex:1;color:#0d4d78}.hxa-datepicker-contents{padding:1rem;background-color:rgba(246,246,249,.5);display:flex;flex-flow:row wrap;flex:1;justify-content:space-around;align-content:space-around}.hxa-datepicker-day{flex:1 1 14%;height:16.666%;display:flex;justify-content:center;align-items:center}.hxa-datepicker-day .hx-button{position:initial;top:initial;flex:1;font-weight:400;height:100%;padding:0;color:#41b987}.hxa-datepicker-day-siblingmonth .hx-button{color:#3b3b3b;font-weight:100}.hxa-datepicker-day-selectedday .hx-button{color:#fff;background:#41b987}.hxa-datepicker-day-invalidday .hx-button{color:#e0e0e1!important;pointer-events:none}.hxa-datepicker-day-currentday .hx-button{border:2px solid #41b987}`]
},] },
];
/** @nocollapse */
DatepickerComponent.ctorParameters = () => [
{ type: ElementRef, },
{ type: PositioningService, },
];
DatepickerComponent.propDecorators = {
"selectedDate": [{ type: Input },],
"validators": [{ type: Input },],
"onDateSelected": [{ type: Output },],
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class DatepickerFormComponent {
/**
* @param {?} element
*/
constructor(element) {
this.element = element;
this.disabled = false;
this.readonly = false;
this.required = false;
this.defaultToPresentDate = true;
this.allowPreviousDates = true;
this.allowFutureDates = true;
this.dateFormat = "dd/MM/y";
this.placeholder = "Date";
this.align = "bottom";
this.from = '';
this.to = '';
this.onDateChange = new EventEmitter();
this.visible = false;
this.dateValidators = new Array();
this.onChanged = new Array();
this.onTouched = new Array();
}
/**
* @return {?}
*/
ngOnInit() {
const /** @type {?} */ date = new Date();
this.presentDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
if (this.defaultToPresentDate) {
setTimeout(() => {
this.setDate(this.presentDate);
});
}
// Close to the minimum and maxium possible dates, but still normalisable
// http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1
const /** @type {?} */ from$$1 = this.parseDate(this.from) || new Date(-8630000000000000);
const /** @type {?} */ to = this.parseDate(this.to) || new Date(8630000000000000);
if (!!this.from || !!this.to) {
this.validateDateRange = this.createDateRangeValidator(from$$1, to);
this.dateValidators.push(this.validateDateRange.bind(this));
}
if (!this.allowPreviousDates)
this.dateValidators.push(this.validateIsNotBeforeDate.bind(this));
if (!this.allowFutureDates)
this.dateValidators.push(this.validateIsNotAfterDate.bind(this));
}
/**
* @param {?} date
* @return {?}
*/
setDate(date) {
this.date = date;
this.onDateChange.emit(date);
this.propogateChange(date);
}
/**
* @return {?}
*/
setVisible() {
this.visible = true;
}
/**
* @return {?}
*/
unsetVisible() {
this.visible = false;
}
/**
* @param {?} targetElement
* @return {?}
*/
onClickOutsideComponent(targetElement) {
if (!this.element.nativeElement.firstChild.contains(targetElement)) {
this.unsetVisible();
}
}
/**
* @param {?} inputDate
* @return {?}
*/
onDateSelectEvent(inputDate) {
this.unsetVisible();
this.setDate(inputDate);
}
/**
* @param {?} inputDate
* @return {?}
*/
onChange(inputDate) {
const /** @type {?} */ date = this.parseDate(inputDate);
if (inputDate == "") {
this.setDate(null);
}
else if (!!date) {
this.setDate(date);
}
else {
this.propogateChange(inputDate);
}
}
/**
* @return {?}
*/
onFocus() {
this.setVisible();
this.propogateTouched();
}
/**
* @param {?} inputDate
* @return {?}
*/
onTab(inputDate) {
this.onChange(inputDate);
this.unsetVisible();
this.propogateTouched();
}
/**
* @param {?} inputDate
* @return {?}
*/
parseDate(inputDate) {
// Since Date.Parse() only acceps m/d/y dates, we have to swap the day and month
let /** @type {?} */ dateArray = inputDate.split(/[.,\/ -]/);
if (dateArray.length == 3 && dateArray[2].length != 0) {
let /** @type {?} */ day = dateArray.shift();
dateArray.splice(1, 0, day);
let /** @type {?} */ parseInput = Date.parse(dateArray.join("/"));
if (!isNaN(parseInput)) {
return new Date(parseInput);
}
}
return null;
}
/**
* @param {?} date
* @return {?}
*/
validateIsNotBeforeDate(date) {
const /** @type {?} */ normalisedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
return normalisedDate.getTime() < this.presentDate.getTime();
}
/**
* @param {?} date
* @return {?}
*/
validateIsNotAfterDate(date) {
const /** @type {?} */ normalisedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
return normalisedDate.getTime() > this.presentDate.getTime();
}
/**
* @param {?} from
* @param {?} to
* @return {?}
*/
createDateRangeValidator(from$$1, to) {
const /** @type {?} */ normalisedFromDate = new Date(from$$1.getFullYear(), from$$1.getMonth(), from$$1.getDate());
const /** @type {?} */ normalisedToDate = new Date(to.getFullYear(), to.getMonth(), to.getDate());
return (date) => {
const /** @type {?} */ normalisedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
return !(normalisedFromDate.getTime() <= normalisedDate.getTime() &&
normalisedDate.getTime() <= normalisedToDate.getTime());
};
}
/**
* @param {?} value
* @return {?}
*/
writeValue(value) {
this.setDate(value);
}
/**
* @param {?} fn
* @return {?}
*/
registerOnChange(fn) {
this.onChanged.push(fn);
}
/**
* @param {?} fn
* @return {?}
*/
registerOnTouched(fn) {
this.onTouched.push(fn);
}
/**
* @return {?}
*/
propogateTouched() {
this.onTouched.forEach(fn => fn());
}
/**
* @param {?} value
* @return {?}
*/
propogateChange(value) {
this.onChanged.forEach(fn => fn(value));
}
/**
* @param {?} control
* @return {?}
*/
validate(control) {
const /** @type {?} */ date = Date.parse(control.value);
if (!this.required && (control.value === null || control.value === undefined)) {
this.isValid = true;
return null;
}
if (isNaN(date)) {
this.isValid = false;
return {
dateParseError: {
valid: false
}
};
}
if (!this.allowPreviousDates && this.validateIsNotBeforeDate(this.date)) {
this.isValid = false;
return {
previousDateError: {
valid: false
}
};
}
if (!this.allowFutureDates && this.validateIsNotAfterDate(this.date)) {
this.isValid = false;
return {
futureDateError: {
valid: false
}
};
}
if (this.validateDateRange && this.validateDateRange(this.date)) {
this.isValid = false;
return {
dateRangeError: {
valid: false
}
};
}
if (this.required && !this.date) {
this.isValid = false;
return {
dateRequiredError: {
valid: false
}
};
}
this.isValid = true;
return null;
}
}
DatepickerFormComponent.decorators = [
{ type: Component, args: [{
selector: 'hxa-datepicker-input, hxa-datepicker-form',
template: `<div class="hx-input-group hxa-datepicker-form">
<div class="hx-input-control" [ngClass]="{'is-danger': !isValid && datePickerForm.touched}">
<input class="hx-input" type="text" #datePickerForm="ngModel"
[required]="required ? true : null"
[disabled]="disabled"
[readonly]="readonly ? true : null"
[ngModel]="date | date:dateFormat"
(change)="onChange(datePickerForm.value)"
(focus)="onFocus()"
(keydown.Tab)="onTab(datePickerForm.value)">
<label class="hx-label" *ngIf="placeholder">{{placeholder}} <sup *ngIf="required">*</sup></label>
<div class="hx-help"></div>
<div class="hxa-datepicker-help">Please select a date</div>
</div>
<i class="hx-icon icon-calendar"></i>
<hxa-datepicker class="hxa-datepicker-calendar" *ngIf="visible"
[selectedDate]="date"
[validators]="dateValidators"
(onDateSelected)="onDateSelectEvent($event)"
[ngClass]="{'hxa-datepicker-calendar-top': align == 'top', 'hxa-datepicker-calendar-bottom': align == 'bottom'}"></hxa-datepicker>
</div>
`,
styles: [`.hxa-datepicker-form{position:relative;max-width:21rem}.hxa-datepicker-calendar{position:absolute;z-index:99;left:0}.hxa-datepicker-calendar-top{bottom:100%}.hxa-datepicker-calendar-bottom{top:70%}.hxa-datepicker-help{font-size:.75rem;margin-top:.25rem;color:#63605f}.hxa-datepicker-form input[readonly]~.hx-label{top:-.5rem;font-size:.75rem;color:#41b987}`],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DatepickerFormComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => DatepickerFormComponent),
multi: true,
}]
},] },
];
/** @nocollapse */
DatepickerFormComponent.ctorParameters = () => [
{ type: ElementRef, },
];
DatepickerFormComponent.propDecorators = {
"disabled": [{ type: Input },],
"readonly": [{ type: Input },],
"required": [{ type: Input },],
"defaultToPresentDate": [{ type: Input },],
"allowPreviousDates": [{ type: Input },],
"allowFutureDates": [{ type: Input },],
"dateFormat": [{ type: Input },],
"placeholder": [{ type: Input },],
"align": [{ type: Input },],
"from": [{ type: Input },],
"to": [{ type: Input },],
"onDateChange": [{ type: Output },],
"onClickOutsideComponent": [{ type: HostListener, args: ['document:click', ['$event.target'],] },],
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class DatepickerModule {
/**
* @return {?}
*/
static forRoot() {
return { ngModule: DatepickerModule, providers: [] };
}
}
DatepickerModule.decorators = [
{ type: NgModule, args: [{
imports: [CommonModule, FormsModule],
declarations: [DatepickerComponent, DatepickerFormComponent],
exports: [DatepickerComponent, DatepickerFormComponent]
},] },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* Default dropdown configuration
*/
class DropdownConfig {
constructor() {
/**
* default dropdown auto closing behavior
*/
this.autoClose = true;
}
}
DropdownConfig.decorators = [
{ type: Injectable },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class ContentRef {
/**
* @param {?} nodes
* @param {?=} viewRef
* @param {?=} componentRef
*/
constructor(nodes, viewRef, componentRef) {
this.nodes = nodes;
this.viewRef = viewRef;
this.componentRef = componentRef;
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @copyright Valor Software
* @copyright Angular ng-bootstrap team
*/
class Trigger {
/**
* @param {?} open
* @param {?=} close
*/
constructor(open, close) {
this.open = open;
this.close = close || open;
}
/**
* @return {?}
*/
isManual() { return this.open === 'manual' || this.close === 'manual'; }
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
const /** @type {?} */ DEFAULT_ALIASES = {
hover: ['mouseenter', 'mouseleave'],
focus: ['focusin', 'focusout']
};
/**
* @param {?} triggers
* @param {?=} aliases
* @return {?}
*/
function parseTriggers(triggers, aliases = DEFAULT_ALIASES) {
const /** @type {?} */ trimmedTriggers = (triggers || '').trim();
if (trimmedTriggers.length === 0) {
return [];
}
const /** @type {?} */ parsedTriggers = trimmedTriggers.split(/\s+/)
.map((trigger) => trigger.split(':'))
.map((triggerPair) => {
const /** @type {?} */ alias = aliases[triggerPair[0]] || triggerPair;
return new Trigger(alias[0], alias[1]);
});
const /** @type {?} */ manualTriggers = parsedTriggers
.filter((triggerPair) => triggerPair.isManual());
if (manualTriggers.length > 1) {
throw new Error('Triggers parse error: only one manual trigger is allowed');
}
if (manualTriggers.length === 1 && parsedTriggers.length > 1) {
throw new Error('Triggers parse error: manual trigger can\'t be mixed with other triggers');
}
return parsedTriggers;
}
/**
* @param {?} renderer
* @param {?} target
* @param {?} triggers
* @param {?} showFn
* @param {?} hideFn
* @param {?} toggleFn
* @return {?}
*/
function listenToTriggers(renderer, target, triggers, showFn, hideFn, toggleFn) {
const /** @type {?} */ parsedTriggers = parseTriggers(triggers);
const /** @type {?} */ listeners = [];
if (parsedTriggers.length === 1 && parsedTriggers[0].isManual()) {
return Function.prototype;
}
parsedTriggers.forEach((trigger) => {
if (trigger.open === trigger.close) {
listeners.push(renderer.listen(target, trigger.open, toggleFn));
return;
}
listeners.push(renderer.listen(target, /** @type {?} */ (trigger.open), showFn), renderer.listen(target, /** @type {?} */ (trigger.close), hideFn));
});
return () => { listeners.forEach((unsubscribeFn) => /** @type {?} */ (unsubscribeFn())); };
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @template T
*/
class ComponentLoader {
/**
* Do not use this directly, it should be instanced via
* `ComponentLoadFactory.attach`
* \@internal
* @param {?} _viewContainerRef
* @param {?} _renderer
* @param {?} _elementRef
* @param {?} _injector
* @param {?} _componentFactoryResolver
* @param {?} _ngZone
* @param {?} _posService
*/
constructor(_viewContainerRef, _renderer, _elementRef, _injector, _componentFactoryResolver, _ngZone, _posService) {
this.onBeforeShow = new EventEmitter();
this.onShown = new EventEmitter();
this.onBeforeHide = new EventEmitter();
this.onHidden = new EventEmitter();
this._providers = [];
this._ngZone = _ngZone;
this._injector = _injector;
this._renderer = _renderer;
this._elementRef = _elementRef;
this._posService = _posService;
this._viewContainerRef = _viewContainerRef;
this._componentFactoryResolver = _componentFactoryResolver;
}
/**
* @return {?}
*/
get isShown() {
return !!this._componentRef;
}
;
/**
* @param {?} compType
* @return {?}
*/
attach(compType) {
this._componentFactory = this._componentFactoryResolver
.resolveComponentFactory(compType);
return this;
}
/**
* @param {?=} container
* @return {?}
*/
to(container) {
this.container = container || this.container;
return this;
}
/**
* @param {?=} opts
* @return {?}
*/
position(opts) {
this.attachment = opts.attachment || this.attachment;
this._elementRef = /** @type {?} */ (opts.target) || this._elementRef;
return this;
}
/**
* @param {?} provider
* @return {?}
*/
provide(provider) {
this._providers.push(provider);
return this;
}
/**
* @param {?=} opts
* @return {?}
*/
show(opts = {}) {
this._subscribePositioning();
if (!this._componentRef) {
this.onBeforeShow.emit();
this._contentRef = this._getContentRef(opts.content);
const /** @type {?} */ injector = ReflectiveInjector.resolveAndCreate(this._providers, this._injector);
this._componentRef = this._viewContainerRef
.createComponent(this._componentFactory, 0, injector, this._contentRef.nodes);
this.instance = this._componentRef.instance;
Object.assign(this._componentRef.instance, opts);
if (this.container === 'body' && typeof document !== 'undefined') {
document.querySelector(/** @type {?} */ (this.container))
.appendChild(this._componentRef.location.nativeElement);
}
// we need to manually invoke change detection since events registered
// via
// Renderer::listen() are not picked up by change detection with the
// OnPush strategy
this._componentRef.changeDetectorRef.markForCheck();
this.onShown.emit(this._componentRef.instance);
}
return this._componentRef;
}
/**
* @return {?}
*/
hide() {
if (this._componentRef) {
this.onBeforeHide.emit(this._componentRef.instance);
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._componentRef.hostView));
this._componentRef = null;
if (this._contentRef.viewRef) {
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._contentRef.viewRef));
this._contentRef = null;
}
this._componentRef = null;
this.onHidden.emit();
}
return this;
}
/**
* @return {?}
*/
toggle() {
if (this.isShown) {
this.hide();
return;
}
this.show();
}
/**
* @return {?}
*/
dispose() {
if (this.isShown) {
this.hide();
}
this._unsubscribePositioning();
if (this._unregisterListenersFn) {
this._unregisterListenersFn();
}
}
/**
* @param {?} listenOpts
* @return {?}
*/
listen(listenOpts) {
this.triggers = listenOpts.triggers || this.triggers;
listenOpts.target = listenOpts.target || this._elementRef;
listenOpts.show = listenOpts.show || (() => this.show());
listenOpts.hide = listenOpts.hide || (() => this.hide());
listenOpts.toggle = listenOpts.toggle || (() => this.isShown
? listenOpts.hide()
: listenOpts.show());
this._unregisterListenersFn = listenToTriggers(this._renderer, listenOpts.target.nativeElement, this.triggers, listenOpts.show, listenOpts.hide, listenOpts.toggle);
return this;
}
/**
* @return {?}
*/
_subscribePositioning() {
if (this._zoneSubscription || !this.attachment) {
return;
}
this._zoneSubscription = this._ngZone
.onStable.subscribe(() => {
if (!this._componentRef) {
return;
}
this._posService.position({
element: this._componentRef.location,
target: this._elementRef,
attachment: this.attachment,
appendToBody: this.container === 'body'
});
});
}
/**
* @return {?}
*/
_unsubscribePositioning() {
if (!this._zoneSubscription) {
return;
}
this._zoneSubscription.unsubscribe();
this._zoneSubscription = null;
}
/**
* @param {?} content
* @return {?}
*/
_getContentRef(content) {
if (!content) {
return new ContentRef([]);
}
if (content instanceof TemplateRef) {
const /** @type {?} */ viewRef = this._viewContainerRef
.createEmbeddedView(content);
return new ContentRef([viewRef.rootNodes], viewRef);
}
return new ContentRef([[this._renderer.createText(`${content}`)]]);
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class ComponentLoaderFactory {
/**
* @param {?} componentFactoryResolver
* @param {?} ngZone
* @param {?} injector
* @param {?} posService
*/
constructor(componentFactoryResolver, ngZone, injector, posService) {
this._ngZone = ngZone;
this._injector = injector;
this._posService = posService;
this._componentFactoryResolver = componentFactoryResolver;
}
/**
* @template T
* @param {?} _elementRef
* @param {?} _viewContainerRef
* @param {?} _renderer
* @return {?}
*/
createLoader(_elementRef, _viewContainerRef, _renderer) {
return new ComponentLoader(_viewContainerRef, _renderer, _elementRef, this._injector, this._componentFactoryResolver, this._ngZone, this._posService);
}
}
ComponentLoaderFactory.decorators = [
{ type: Injectable },
];
/** @nocollapse */
ComponentLoaderFactory.ctorParameters = () => [
{ type: ComponentFactoryResolver, },
{ type: NgZone, },
{ type: Injector, },
{ type: PositioningService, },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class DropdownState {
constructor() {
this.direction = 'down';
this.isOpenChange = new EventEmitter();
this.isDisabledChange = new EventEmitter();
this.toggleClick = new EventEmitter();
this.dropdownMenu = new Promise((resolve) => {
this.resolveDropdownMenu = resolve;
});
this.isOpenChange.subscribe((value) => {
this.isOpen = value;
});
}
}
DropdownState.decorators = [
{ type: Injectable },
];
/** @nocollapse */
DropdownState.ctorParameters = () => [];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class DropdownContainerComponent {
/**
* @param {?} _state
*/
constructor(_state) {
this._state = _state;
this.isOpen = false;
this._subscription = _state.isOpenChange.subscribe((value) => {
this.isOpen = value;
});
}
/**
* @return {?}
*/
get direction() {
return this._state.direction;
}
/**
* @return {?}
*/
ngOnDestroy() {
this._subscription.unsubscribe();
}
}
DropdownContainerComponent.decorators = [
{ type: Component, args: [{
selector: 'hx-dropdown-container',
host: {
style: 'display:block;position: absolute;'
},
template: `
<div [class.is-dropup]="direction === 'up'"
[class.is-dropdown]="direction === 'down'"
[class.is-open]="isOpen"><ng-content></ng-content></div>
`
},] },
];
/** @nocollapse */
DropdownContainerComponent.ctorParameters = () => [
{ type: DropdownState, },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class DropdownDirective {
/**
* @param {?} _elementRef
* @param {?} _renderer
* @param {?} _viewContainerRef
* @param {?} _cis
* @param {?} _config
* @param {?} _state
*/
constructor(_elementRef, _renderer, _viewContainerRef, _cis, _config, _state) {
this._elementRef = _elementRef;
this._renderer = _renderer;
this._viewContainerRef = _viewContainerRef;
this._cis = _cis;
this._config = _config;
this._state = _state;
this._isInlineOpen = false;
this._isInlineRight = false;
this._subscriptions = [];
this._isInited = false;
// create dropdown component loader
this._dropdown = this._cis
.createLoader(this._elementRef, this._viewContainerRef, this._renderer)
.provide({ provide: DropdownState, useValue: this._state });
this.onShown = this._dropdown.onShown;
this.onHidden = this._dropdown.onHidden;
this.isOpenChange = this._state.isOpenChange;
// set initial dropdown state from config
this._state.autoClose = this._config.autoClose;
}
/**
* Indicates that dropdown will be closed on item or document click,
* and after pressing ESC
* @param {?} value
* @return {?}
*/
set autoClose(value) {
if (typeof value === 'boolean') {
this._state.autoClose = value;
}
}
;
/**
* @return {?}
*/
get autoClose() {
return this._state.autoClose;
}
/**
* Disables dropdown toggle and hides dropdown menu if opened
* @param {?} value
* @return {?}
*/
set isDisabled(value) {
this._isDisabled = value;
this._state.isDisabledChange.emit(value);
if (value) {
this.hide();
}
}
/**
* @return {?}
*/
get isDisabled() { return this._isDisabled; }
/**
* Returns whether or not dropdown is position right of the toggle
* @return {?}
*/
get isRight() {
return this._isInlineRight;
}
/**
* @param {?} value
* @return {?}
*/
set isRight(value) {
this._isInlineRight = value;
}
/**
* Returns whether or not the dropdown is currently being shown
* @return {?}
*/
get isOpen() {
if (this._showInline) {
return this._isInlineOpen;
}
return this._dropdown.isShown;
}
/**
* @param {?} value
* @return {?}
*/
set isOpen(value) {
if (value) {
this.show();
}
else {
this.hide();
}
}
/**
* @return {?}
*/
ngOnInit() {
// fix: seems there are an issue with `routerLinkActive`
// which result in duplicated call ngOnInit without call to ngOnDestroy
// read more: https://github.com/valor-software/ngx-bootstrap/issues/1885
if (this._isInited) {
return;
}
this._isInited = true;
this._showInline = !this.container;
// attach DOM listeners
this._dropdown.listen({
triggers: this.triggers,
show: () => this.show()
});
// toggle visibility on toggle element click
this._subscriptions.push(this._state
.toggleClick.subscribe((value) => this.toggle(value)));
// hide dropdown if set disabled while opened
this._subscriptions.push(this._state
.isDisabledChange.pipe(filter((value) => value === true)).subscribe((value) => this.hide()));
// attach dropdown menu inside of dropdown
if (this._showInline) {
this._state.dropdownMenu
.then((dropdownMenu) => {
this._inlinedMenu = dropdownMenu.viewContainer.createEmbeddedView(dropdownMenu.templateRef);
});
}
}
/**
* Opens an element’s popover. This is considered a “manual” triggering of
* the popover.
* @return {?}
*/
show() {
if (this.isOpen || this.isDisabled) {
return;
}
if (this._showInline) {
this._isInlineOpen = true;
this.onShown.emit(true);
this._state.isOpenChange.emit(true);
return;
}
this._state.dropdownMenu
.then((dropdownMenu) => {
// check direction in which dropdown should be opened
const /** @type {?} */ _dropup = this.dropup === true ||
(typeof this.dropup !== 'undefined' && this.dropup !== false);
this._state.direction = _dropup ? 'up' : 'down';
const /** @type {?} */ _placement = this.placement ||
(_dropup ? 'top left' : 'bottom left');
// show dropdown
this._dropdown
.attach(DropdownContainerComponent)
.to(this.container)
.position({ attachment: _placement })
.show({
content: dropdownMenu.templateRef,
placement: _placement
});
this._state.isOpenChange.emit(true);
});
}
/**
* Closes an element’s popover. This is considered a “manual” triggering of
* the popover.
* @return {?}
*/
hide() {
if (!this.isOpen) {
return;
}
if (this._showInline) {
this._isInlineOpen = false;
this.onHidden.emit(true);
}
else {
this._dropdown.hide();
}
this._state.isOpenChange.emit(false);
}
/**
* Toggles an element’s popover. This is considered a “manual” triggering of
* the popover.
* @param {?=} value
* @return {?}
*/
toggle(value) {
if (this.isOpen || value === false) {
return this.hide();
}
return this.show();
}
/**
* @return {?}
*/
ngOnDestroy() {
// clean up subscriptions and destroy dropdown
for (const /** @type {?} */ sub of this._subscriptions) {
sub.unsubscribe();
}
this._dropdown.dispose();
}
}
DropdownDirective.decorators = [
{ type: Directive, args: [{
selector: '[hxDropdown],[dropdown]',
exportAs: 'hx-dropdown',
providers: [DropdownState],
host: {
'[class.is-dropup]': 'dropup',
'[class.is-open]': 'isOpen',
'[class.is-right]': 'isRight'
}
},] },
];
/** @nocollapse */
DropdownDirective.ctorParameters = () => [
{ type: ElementRef, },
{ type: Renderer2, },
{ type: ViewContainerRef, },
{ type: ComponentLoaderFactory, },
{ type: DropdownConfig, },
{ type: DropdownState, },
];
DropdownDirective