fundamental-ngx
Version:
SAP Fiori Fundamentals, implemented in Angular
1,654 lines (1,618 loc) • 395 kB
JavaScript
import Popper from 'popper.js';
import { Subject, fromEvent } from 'rxjs';
import { animate, style, transition, trigger } from '@angular/animations';
import focusTrap from 'focus-trap';
import { Input, Directive, ElementRef, NgModule, Component, HostBinding, Injectable, ChangeDetectorRef, ViewChild, ComponentFactoryResolver, Type, ViewContainerRef, TemplateRef, Optional, Output, EventEmitter, ApplicationRef, Injector, Inject, LOCALE_ID, HostListener, forwardRef, ContentChild, Pipe, ContentChildren, ViewChildren, Renderer2, defineInjectable, inject } from '@angular/core';
import { CommonModule, FormStyle, getLocaleDayNames, getLocaleMonthNames, TranslationWidth } from '@angular/common';
import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/*
This abstract class allows the user to set their own custom styles on a Fundamental NGX directive, in addition to the
styles the library needs to add itself.
When library styles were added through the directive's host: {'[class]'} property, any styles the user added would be
overwritten. By extending this class, we instead add library styles to the user's classList rather than replace them.
*/
/**
* @hidden
* @abstract
*/
class AbstractFdNgxClass {
/**
* @hidden
* @protected
* @param {?} elementRef
*/
constructor(elementRef) {
this._elementRef = elementRef;
this._setProperties();
}
/**
* @hidden
* @param {?} className
* @return {?}
*/
_addClassToElement(className) {
((/** @type {?} */ (this._elementRef.nativeElement))).classList.add(...className.split(' '));
}
/**
* @hidden
* @param {?} attribute
* @param {?} value
* @return {?}
*/
_addStyleToElement(attribute, value) {
((/** @type {?} */ (this._elementRef.nativeElement))).style[attribute] = value;
}
/**
* @hidden
* @return {?}
*/
ngOnChanges() {
/** @type {?} */
const classList = ((/** @type {?} */ (this._elementRef.nativeElement))).classList;
while (classList.length > 0) {
classList.remove(classList.item(0));
}
if (this.class) {
this._addClassToElement(this.class);
}
this._setProperties();
}
/**
* @hidden
* @return {?}
*/
ngOnInit() {
this._setProperties();
}
}
AbstractFdNgxClass.propDecorators = {
class: [{ type: Input }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Button directive, used to enhance standard HTML buttons.
*
* ```html
* <button fd-button>Button Text</button>
* ```
*/
class ButtonDirective extends AbstractFdNgxClass {
/**
* @hidden
* @param {?} elementRef
*/
constructor(elementRef) {
super(elementRef);
this.elementRef = elementRef;
}
// TODO: deprecated, leaving for backwards compatibility
/**
* @hidden
* @return {?}
*/
_setProperties() {
this._addClassToElement('fd-button');
if (this.compact) {
this._addClassToElement('fd-button--compact');
}
if (this.glyph) {
this._addClassToElement('sap-icon--' + this.glyph);
}
if (this.fdType) {
this._addClassToElement('fd-button--' + this.fdType);
}
if (this.options) {
if (typeof this.options === 'string') {
this._addClassToElement('fd-button--' + this.options);
}
else if (Array.isArray(this.options)) {
this.options.forEach((/**
* @param {?} option
* @return {?}
*/
option => {
if (typeof option === 'string') {
this._addClassToElement('fd-button--' + option);
}
}));
}
}
}
}
ButtonDirective.decorators = [
{ type: Directive, args: [{
// TODO to be discussed
// tslint:disable-next-line:directive-selector
selector: '[fd-button]'
},] }
];
/** @nocollapse */
ButtonDirective.ctorParameters = () => [
{ type: ElementRef }
];
ButtonDirective.propDecorators = {
compact: [{ type: Input }],
glyph: [{ type: Input }],
fdType: [{ type: Input }],
semantic: [{ type: Input }],
options: [{ type: Input }],
size: [{ type: Input }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class ButtonModule {
}
ButtonModule.decorators = [
{ type: NgModule, args: [{
imports: [CommonModule],
exports: [ButtonDirective],
declarations: [ButtonDirective]
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @hidden
* The base class for the icon component
* @type {?}
*/
const BASE_ICON_CLASS = 'sap-icon';
/**
* @hidden
* Prefix for icon prop classes
* @type {?}
*/
const PREFIX_ICON_CLASS = BASE_ICON_CLASS + '--';
/**
* The directive that represents an icon.
*
* ```html
* <fd-icon [glyph]="cart-approval" [size]="'l'"></fd-icon>
* ```
*/
class IconDirective extends AbstractFdNgxClass {
/**
* @hidden
* @param {?} elementRef
*/
constructor(elementRef) {
super(elementRef);
this.elementRef = elementRef;
/**
* The size of the icon
* The predefined values for the input size are *xs*, *s*, *l*, and *xl*.
* *size* can accept any other string, for example *xxs*, which will be translated into class *sap-icon--xxs*.
*/
this.size = '';
}
/**
* @hidden
* @return {?}
*/
_setProperties() {
if (this.glyph) {
this._addClassToElement(PREFIX_ICON_CLASS + this.glyph);
}
if (this.size) {
this._addClassToElement(PREFIX_ICON_CLASS + this.size);
}
}
}
IconDirective.decorators = [
{ type: Directive, args: [{
// TODO to be discussed
// tslint:disable-next-line:directive-selector
selector: 'fd-icon',
host: {
role: 'presentation'
}
},] }
];
/** @nocollapse */
IconDirective.ctorParameters = () => [
{ type: ElementRef }
];
IconDirective.propDecorators = {
glyph: [{ type: Input }],
size: [{ type: Input }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class IconModule {
}
IconModule.decorators = [
{ type: NgModule, args: [{
imports: [CommonModule],
exports: [IconDirective],
declarations: [IconDirective]
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* The parent action bar component.
*
* Child components:
* ```html
* <fd-action-bar-actions>
* <fd-action-bar-back>
* <fd-action-bar-description>
* <fd-action-bar-header>
* ```
*/
class ActionBarComponent {
}
ActionBarComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-action-bar',
template: "<div class=\"fd-action-bar\">\n <ng-content></ng-content>\n</div>"
}] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* The action bar title component.
*
* ```html
* <fd-action-bar>
* <fd-action-bar-header>
* <h1 fd-action-bar-title>Page Title</h1>
* </fd-action-bar-header>
* <fd-action-bar>
* ```
*/
class ActionBarTitleDirective {
constructor() {
/**
* @hidden
*/
this.fdActionBarTitleClass = true;
}
}
ActionBarTitleDirective.decorators = [
{ type: Directive, args: [{
// TODO to be discussed
// tslint:disable-next-line:directive-selector
selector: '[fd-action-bar-title]'
},] }
];
ActionBarTitleDirective.propDecorators = {
fdActionBarTitleClass: [{ type: HostBinding, args: ['class.fd-action-bar__title',] }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* The action bar description.
*
* ```html
* <fd-action-bar>
* <fd-action-bar-header>
* <fd-action-bar-description>Page Description</fd-action-bar-description>
* </fd-action-bar-header>
* <fd-action-bar>
* ```
*/
class ActionBarDescriptionComponent {
}
ActionBarDescriptionComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-action-bar-description',
template: "<p class=\"fd-action-bar__description\">\n <ng-content></ng-content>\n</p>"
}] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* The action bar header, which contains the action bar's title and description components.
*
* ```html
* <fd-action-bar>
* <fd-action-bar-header>
* </fd-action-bar-header>
* <fd-action-bar>
* ```
*/
class ActionBarHeaderComponent extends AbstractFdNgxClass {
/**
* @hidden
* @param {?} elementRef
*/
constructor(elementRef) {
super(elementRef);
this.elementRef = elementRef;
}
/**
* @hidden
* @return {?}
*/
_setProperties() {
this._addClassToElement('fd-action-bar__header');
}
}
ActionBarHeaderComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-action-bar-header',
template: "<ng-content></ng-content>\n<ng-content select=\"fd-action-bar-description\"></ng-content>\n"
}] }
];
/** @nocollapse */
ActionBarHeaderComponent.ctorParameters = () => [
{ type: ElementRef }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* This component holds the right-aligned action buttons for the action bar.
*
* ```html
* <fd-action-bar>
* <fd-action-bar-actions>
* <button fd-button [fdType]="'primary'">Cancel</button>
* <button fd-button [fdType]="'main'">Save</button>
* </fd-action-bar-actions>
* <fd-action-bar>
* ```
*/
class ActionBarActionsComponent extends AbstractFdNgxClass {
/**
* @hidden
* @param {?} elementRef
*/
constructor(elementRef) {
super(elementRef);
this.elementRef = elementRef;
}
/**
* @hidden
* @return {?}
*/
_setProperties() {
this._addClassToElement('fd-action-bar__actions');
}
}
ActionBarActionsComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-action-bar-actions',
template: "<ng-content></ng-content>\n"
}] }
];
/** @nocollapse */
ActionBarActionsComponent.ctorParameters = () => [
{ type: ElementRef }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* The left-aligned back button for the action bar.
*
* ```html
* <fd-action-bar>
* <fd-action-bar-back>
* <button aria-label="back" fd-button [fdType]="'light'" [compact]="true" [glyph]="'nav-back'"></button>
* </fd-action-bar-back>
* <fd-action-bar>
* ```
*/
class ActionBarBackComponent extends AbstractFdNgxClass {
/**
* @hidden
* @param {?} elementRef
*/
constructor(elementRef) {
super(elementRef);
this.elementRef = elementRef;
}
/**
* @hidden
* @return {?}
*/
_setProperties() {
this._addClassToElement('fd-action-bar__back');
}
}
ActionBarBackComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-action-bar-back',
template: "<ng-content></ng-content>"
}] }
];
/** @nocollapse */
ActionBarBackComponent.ctorParameters = () => [
{ type: ElementRef }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* The action bar mobile component. This component should wrap all other action bar components, including the <fd-action-bar>.
*
* ```html
* <fd-action-bar-mobile>
* <fd-action-bar>
* </fd-action-bar>
* <fd-action-bar-mobile>
* ```
*/
class ActionBarMobileComponent {
}
ActionBarMobileComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-action-bar-mobile',
template: "<div style=\"width:319px\">\n <ng-content></ng-content>\n</div>"
}] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class ActionBarModule {
}
ActionBarModule.decorators = [
{ type: NgModule, args: [{
declarations: [
ActionBarComponent,
ActionBarTitleDirective,
ActionBarDescriptionComponent,
ActionBarHeaderComponent,
ActionBarActionsComponent,
ActionBarBackComponent,
ActionBarMobileComponent
],
imports: [CommonModule, ButtonModule, IconModule],
exports: [
ActionBarComponent,
ActionBarTitleDirective,
ActionBarDescriptionComponent,
ActionBarHeaderComponent,
ActionBarActionsComponent,
ActionBarBackComponent,
ActionBarMobileComponent
]
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class HashService {
/**
* @return {?}
*/
hash() {
return 'FUI' + Math.floor(Math.random() * 1000000);
}
}
HashService.decorators = [
{ type: Injectable }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class UtilsModule {
}
UtilsModule.decorators = [
{ type: NgModule, args: [{
providers: [HashService]
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Reference to an alert component generated via the AlertService.
* It can be injected into the content component in the same way a service would be injected.
* For a template, add let-alert to your ng-template tag. Now using *alert* in the template refers to this class.
*/
class AlertRef {
constructor() {
this._afterDismissed = new Subject();
/**
* Observable that is triggered when the alert is dismissed.
*/
this.afterDismissed = this._afterDismissed.asObservable();
}
/**
* Dismisses the alert.
*
* @param {?=} reason Data passed back to the calling component through the AfterDismissed observable.
* @return {?}
*/
dismiss(reason) {
this._afterDismissed.next(reason);
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const alertFadeNgIf = trigger('fadeAlertNgIf', [
transition(':enter', [
style({
opacity: 0
}),
animate('250ms ease-in-out', style({
opacity: 1
}))
]),
transition(':leave', [
style({
opacity: 1,
marginTop: '*',
paddingTop: '*',
paddingBottom: '*',
height: '*',
overflow: 'hidden'
}),
animate('400ms ease-in-out', style({
opacity: 0,
marginTop: 0,
paddingTop: 0,
paddingBottom: 0,
height: 0,
overflow: 'hidden'
}))
])
]);
/** @type {?} */
const alertContainerNgIf = trigger('alertContainerNgIf', [
transition(':leave', [
style({ opacity: 1 }),
animate('400ms ease-in-out', style({ opacity: 0 }))
])
]);
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* The component that represents an alert. It can be only be used inline.
* If the AlertService is used, this component is auto-generated.
*/
class AlertComponent extends AbstractFdNgxClass {
/**
* @hidden
* @param {?} hasher
* @param {?} elRef
* @param {?} cdRef
* @param {?} componentFactoryResolver
* @param {?} alertRef
*/
constructor(hasher, elRef, cdRef, componentFactoryResolver, alertRef) {
super(elRef);
this.hasher = hasher;
this.elRef = elRef;
this.cdRef = cdRef;
this.componentFactoryResolver = componentFactoryResolver;
this.alertRef = alertRef;
/**
* Whether the alert is dismissible.
*/
this.dismissible = true;
/**
* Duration of time *in milliseconds* that the alert will be visible. Set to -1 for indefinite.
*/
this.duration = 10000;
/**
* Whether the alert should stay open if the mouse is hovering over it.
*/
this.mousePersist = false;
/**
* Id of the element that labels the alert.
*/
this.ariaLabelledBy = null;
/**
* Aria label for the alert component element.
*/
this.ariaLabel = null;
/**
* Aria label for the dismiss button.
*/
this.dismissLabel = 'Dismiss';
/**
* Event fired when the alert is dismissed.
*/
this.onDismiss = new EventEmitter();
/**
* @hidden
*/
this.mouseInAlert = false;
}
/**
* @hidden
* @return {?}
*/
ngOnInit() {
if (!this.id) {
this.id = this.hasher.hash();
}
if (this.alertRef) {
this.open();
}
this._setProperties();
}
/**
* @hidden
* @return {?}
*/
ngAfterViewInit() {
if (this.childComponentType) {
if (this.childComponentType instanceof Type) {
this.loadFromComponent(this.childComponentType);
}
else if (this.childComponentType instanceof TemplateRef) {
this.loadFromTemplate(this.childComponentType);
}
else {
this.loadFromString(this.childComponentType);
}
this.cdRef.detectChanges();
}
}
/**
* Dismisses the alert. If the alert was generated via the AlertService, it is removed from the DOM.
* Otherwise, it sets the display value to none. Fires the onDismiss event.
*
* @param {?=} reason Data to pass back to the calling component. Only usable if alert is opened using the Service.
*
* @param {?=} manualDismiss Set to true to skip the dismiss animation.
* @return {?}
*/
dismiss(reason, manualDismiss = false) {
if (manualDismiss) {
this.elRef.nativeElement.style.display = 'none';
}
if (this.alertRef) {
this.alertRef.dismiss(reason);
}
else {
this.elRef.nativeElement.style.display = 'none';
}
this.onDismiss.emit();
}
/**
* Opens the alert.
* @return {?}
*/
open() {
if (!this.alertRef) {
if (this.elRef.nativeElement.style.display === 'block') {
return;
}
this.elRef.nativeElement.style.display = 'block';
}
if (this.duration >= 0) {
setTimeout((/**
* @return {?}
*/
() => {
if (this.mousePersist) {
/** @type {?} */
const wait = (/**
* @return {?}
*/
() => {
if (this.mouseInAlert === true) {
setTimeout(wait, 500);
}
else {
this.dismiss();
}
});
wait();
}
else {
this.dismiss();
}
}), this.duration);
}
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
handleAlertMouseEvent(event) {
if (event.type === 'mouseenter') {
this.mouseInAlert = true;
}
else if (event.type === 'mouseleave') {
this.mouseInAlert = false;
}
}
/**
* @hidden
* @return {?}
*/
_setProperties() {
this._addClassToElement('fd-alert');
if (this.type) {
this._addClassToElement('fd-alert--' + this.type);
}
}
/**
* @private
* @param {?} template
* @return {?}
*/
loadFromTemplate(template) {
/** @type {?} */
const context = {
$implicit: this.alertRef
};
this.componentRef = this.containerRef.createEmbeddedView(template, context);
}
/**
* @private
* @param {?} componentType
* @return {?}
*/
loadFromComponent(componentType) {
/** @type {?} */
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentType);
this.containerRef.clear();
this.componentRef = this.containerRef.createComponent(componentFactory);
}
/**
* @private
* @param {?} contentString
* @return {?}
*/
loadFromString(contentString) {
this.containerRef.clear();
this.message = contentString;
}
}
AlertComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-alert',
template: "<button class=\"fd-alert__close\"\n *ngIf=\"dismissible\"\n (click)=\"dismiss(undefined, true)\"\n [attr.aria-controls]=\"id\"\n [attr.aria-label]=\"dismissLabel\">\n</button>\n<ng-container #container>{{message}}</ng-container>\n<ng-content></ng-content>\n",
providers: [HashService],
host: {
'[attr.aria-labelledby]': 'ariaLabelledBy',
'[attr.aria-label]': 'ariaLabel',
'[style.width]': 'width',
'role': 'alert',
'[attr.id]': 'id',
'(mouseenter)': 'handleAlertMouseEvent($event)',
'(mouseleave)': 'handleAlertMouseEvent($event)',
'[@fadeAlertNgIf]': ''
},
animations: [
alertFadeNgIf
],
styles: [":host{display:block}.fd-alert .fd-popover__body{position:fixed;top:auto;left:auto}"]
}] }
];
/** @nocollapse */
AlertComponent.ctorParameters = () => [
{ type: HashService },
{ type: ElementRef },
{ type: ChangeDetectorRef },
{ type: ComponentFactoryResolver },
{ type: AlertRef, decorators: [{ type: Optional }] }
];
AlertComponent.propDecorators = {
containerRef: [{ type: ViewChild, args: ['container', { read: ViewContainerRef },] }],
dismissible: [{ type: Input }],
type: [{ type: Input }],
id: [{ type: Input }],
duration: [{ type: Input }],
mousePersist: [{ type: Input }],
ariaLabelledBy: [{ type: Input }],
ariaLabel: [{ type: Input }],
dismissLabel: [{ type: Input }],
width: [{ type: Input }],
message: [{ type: Input }],
onDismiss: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class AlertContainerComponent {
}
AlertContainerComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-alert-container',
template: ``,
host: {
'[@alertContainerNgIf]': ''
},
animations: [
alertContainerNgIf
],
styles: [`
:host {
position: fixed;
display: flex;
flex-direction: column;
z-index: 5000;
align-items: center;
top: 0;
right: 50%;
left: 50%;
}
`]
}] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Configuration for opening an alert with the AlertService.
*/
class AlertConfig {
constructor() {
/**
* Whether the alert is dismissible.
*/
this.dismissible = true;
/**
* Width of the alert.
*/
this.width = '33vw';
/**
* Duration of time *in milliseconds* that the alert will be visible. Set to -1 for indefinite.
*/
this.duration = 10000;
/**
* Whether the alert should stay open if the mouse is hovering over it.
*/
this.mousePersist = false;
/**
* Id of the element that labels the alert.
*/
this.ariaLabelledBy = null;
/**
* Aria label for the alert component element.
*/
this.ariaLabel = null;
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class AlertInjector {
/**
* @param {?} _parentInjector
* @param {?} _additionalTokens
*/
constructor(_parentInjector, _additionalTokens) {
this._parentInjector = _parentInjector;
this._additionalTokens = _additionalTokens;
}
/**
* @param {?} token
* @param {?=} notFoundValue
* @param {?=} flags
* @return {?}
*/
get(token, notFoundValue, flags) {
/** @type {?} */
const value = this._additionalTokens.get(token);
if (value) {
return value;
}
return this._parentInjector.get(token, notFoundValue);
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Service used to dynamically generate an alert as an overlay.
*/
class AlertService {
/**
* @hidden
* @param {?} componentFactoryResolver
* @param {?} appRef
* @param {?} injector
*/
constructor(componentFactoryResolver, appRef, injector) {
this.componentFactoryResolver = componentFactoryResolver;
this.appRef = appRef;
this.injector = injector;
this.alerts = [];
}
/**
* Returns true if there are some alerts currently open. False otherwise.
* @return {?}
*/
hasOpenAlerts() {
return this.alerts && this.alerts.length > 0;
}
/**
* Opens an alert component with a content of type TemplateRef, Component Type or String.
* @param {?} content Content of the alert component.
* @param {?=} alertConfig Configuration of the alert component.
* @return {?}
*/
open(content, alertConfig = new AlertConfig()) {
// If empty or undefined alert array, create container
if (!this.alerts || this.alerts.length === 0) {
this.openAlertContainer();
}
// Ensure default width
if (alertConfig && !alertConfig.width) {
alertConfig.width = '33vw';
}
// Config setup
/** @type {?} */
const configMap = new WeakMap();
/** @type {?} */
const alertRef = new AlertRef();
alertRef.data = (alertConfig ? alertConfig.data : undefined);
configMap.set(AlertRef, alertRef);
// Prepare new component
/** @type {?} */
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(AlertComponent);
/** @type {?} */
const componentRef = componentFactory.create(new AlertInjector(this.injector, configMap));
componentRef.location.nativeElement.style.marginTop = '10px';
this.appRef.attachView(componentRef.hostView);
// Subscription to close alert from ref
/** @type {?} */
const refSub = alertRef.afterDismissed.subscribe((/**
* @return {?}
*/
() => {
this.destroyAlertComponent(componentRef);
refSub.unsubscribe();
}));
// Prepare component data items
/** @type {?} */
const configObj = Object.assign({}, alertConfig);
Object.keys(configObj).forEach((/**
* @param {?} key
* @return {?}
*/
key => {
if (key !== 'data') {
componentRef.instance[key] = configObj[key];
}
}));
componentRef.instance.childComponentType = content;
// Render new component
/** @type {?} */
const domElem = (/** @type {?} */ (((/** @type {?} */ (componentRef.hostView))).rootNodes[0]));
this.alertContainerRef.location.nativeElement.appendChild(domElem);
// Log new component
this.alerts.push(componentRef);
return alertRef;
}
/**
* Dismisses all service-opened alerts.
* @return {?}
*/
dismissAll() {
this.alerts.forEach((/**
* @param {?} ref
* @return {?}
*/
ref => {
this.destroyAlertComponent(ref);
}));
}
/**
* @private
* @param {?} alert
* @return {?}
*/
destroyAlertComponent(alert) {
this.alerts[this.alerts.indexOf(alert)] = null;
this.alerts = this.alerts.filter((/**
* @param {?} item
* @return {?}
*/
item => item !== null && item !== undefined));
this.appRef.detachView(alert.hostView);
alert.destroy();
if (this.alertContainerRef && (!this.alerts || this.alerts.length === 0)) {
this.destroyAlertContainer();
}
}
/**
* @private
* @return {?}
*/
openAlertContainer() {
/** @type {?} */
const factory = this.componentFactoryResolver.resolveComponentFactory(AlertContainerComponent);
/** @type {?} */
const componentRef = factory.create(this.injector);
this.appRef.attachView(componentRef.hostView);
/** @type {?} */
const domElement = (/** @type {?} */ (((/** @type {?} */ (componentRef.hostView))).rootNodes[0]));
document.body.appendChild(domElement);
this.alertContainerRef = componentRef;
}
/**
* @private
* @return {?}
*/
destroyAlertContainer() {
this.appRef.detachView(this.alertContainerRef.hostView);
this.alertContainerRef.destroy();
this.alertContainerRef = undefined;
}
}
AlertService.decorators = [
{ type: Injectable }
];
/** @nocollapse */
AlertService.ctorParameters = () => [
{ type: ComponentFactoryResolver },
{ type: ApplicationRef },
{ type: Injector }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class AlertModule {
}
AlertModule.decorators = [
{ type: NgModule, args: [{
declarations: [AlertComponent, AlertContainerComponent],
imports: [CommonModule, IconModule, UtilsModule],
exports: [AlertComponent, AlertContainerComponent],
entryComponents: [AlertContainerComponent, AlertComponent],
providers: [AlertService]
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Badge component, used to indicate status.
* Colors, generally in combination with text, are used to easily highlight the state of an object.
*/
class BadgeComponent extends AbstractFdNgxClass {
/**
* @hidden
* @param {?} elementRef
*/
constructor(elementRef) {
super(elementRef);
}
/**
* @hidden
* @return {?}
*/
_setProperties() {
this._addClassToElement('fd-badge');
if (this.status) {
this._addClassToElement('fd-badge--' + this.status);
}
if (this.modifier) {
this._addClassToElement('fd-badge--' + this.modifier);
}
}
}
BadgeComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-badge',
template: "<span><ng-content></ng-content></span>\n"
}] }
];
/** @nocollapse */
BadgeComponent.ctorParameters = () => [
{ type: ElementRef, decorators: [{ type: Inject, args: [ElementRef,] }] }
];
BadgeComponent.propDecorators = {
status: [{ type: Input }],
modifier: [{ type: Input }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Badge component, used to indicate status.
* Colors, generally in combination with text, are used to easily highlight the state of an object.
*/
class LabelComponent extends AbstractFdNgxClass {
/**
* @hidden
* @param {?} elementRef
*/
constructor(elementRef) {
super(elementRef);
/**
* Color coded status for the label. Options are 'success', 'warning', and 'error'. Leave empty for default label.
*/
this.status = '';
/**
* When set to 'true', the type of the label is 'Status Indicator Label'. Leave empty for default type.
*/
this.isStatusLabel = false;
/**
* Built-in status icon. Options include 'available', 'away', 'busy', and 'offline'.
*/
this.statusIcon = '';
/**
* The icon used with the status indicator. See the icon page for the list of icons.
*/
this.icon = '';
}
/**
* @hidden
* @return {?}
*/
_setProperties() {
if (this.isStatusLabel) {
this._addClassToElement('fd-status-label');
if (this.status) {
this._addClassToElement('fd-status-label--' + this.status);
}
if (this.statusIcon) {
this._addClassToElement('fd-status-label--' + this.statusIcon);
}
if (this.icon) {
this._addClassToElement('sap-icon--' + this.icon);
}
}
else {
this._addClassToElement('fd-label');
if (this.status) {
this._addClassToElement('fd-label--' + this.status);
}
}
}
}
LabelComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-label',
template: "<span><ng-content></ng-content></span>\n"
}] }
];
/** @nocollapse */
LabelComponent.ctorParameters = () => [
{ type: ElementRef, decorators: [{ type: Inject, args: [ElementRef,] }] }
];
LabelComponent.propDecorators = {
status: [{ type: Input }],
isStatusLabel: [{ type: Input }],
statusIcon: [{ type: Input }],
icon: [{ type: Input }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class BadgeLabelModule {
}
BadgeLabelModule.decorators = [
{ type: NgModule, args: [{
imports: [CommonModule],
exports: [BadgeComponent, LabelComponent],
declarations: [BadgeComponent, LabelComponent]
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Breadcrumb parent wrapper directive. Must have breadcrumb item child directives.
*
* ```html
* <fd-breadcrumb>
* <fd-breadcrumb-item>
* <a fd-breadcrumb-link [routerLink]="'#'">Breadcrumb Link</a>
* </fd-breadcrumb-item>
* </fd-breadcrumb>
* ```
*/
class BreadcrumbDirective {
}
BreadcrumbDirective.decorators = [
{ type: Directive, args: [{
// TODO to be discussed
// tslint:disable-next-line:directive-selector
selector: 'fd-breadcrumb',
host: {
class: 'fd-breadcrumb'
}
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Breadcrumb item directive. Must have child breadcrumb link directives.
*
* ```html
* <fd-breadcrumb-item>
* <a fd-breadcrumb-link [routerLink]="'#'">Breadcrumb Link</a>
* </fd-breadcrumb-item>
* ```
*/
class BreadcrumbItemDirective {
}
BreadcrumbItemDirective.decorators = [
{ type: Directive, args: [{
// TODO to be discussed
// tslint:disable-next-line:directive-selector
selector: 'fd-breadcrumb-item',
host: {
class: 'fd-breadcrumb__item'
}
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Breadcrumb link directive. Use Angular router options (such as 'routerLink' and 'queryParams') with this directive.
*
* ```html
* <a fd-breadcrumb-link [routerLink]="'some-url'" [queryParams]="'params'">Breadcrumb Link</a>
* ```
*/
class BreadcrumbLinkDirective {
}
BreadcrumbLinkDirective.decorators = [
{ type: Directive, args: [{
// TODO to be discussed
// tslint:disable-next-line:directive-selector
selector: '[fd-breadcrumb-link]',
host: {
class: 'fd-breadcrumb__link'
}
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class BreadcrumbModule {
}
BreadcrumbModule.decorators = [
{ type: NgModule, args: [{
imports: [CommonModule],
exports: [BreadcrumbDirective, BreadcrumbItemDirective, BreadcrumbLinkDirective],
declarations: [BreadcrumbDirective, BreadcrumbItemDirective, BreadcrumbLinkDirective]
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Container for grouped buttons.
*
* ```html
* <fd-button-group>
* <button fd-button-grouped>Button</button>
* </fd-button-group>
* ```
*/
class ButtonGroupComponent {
constructor() {
/**
* @hidden
*/
this.fdButtonGroupClass = true;
}
}
ButtonGroupComponent.decorators = [
{ type: Component, args: [{
selector: 'fd-button-group',
template: "<ng-content></ng-content>\n",
host: {
'role': 'group'
}
}] }
];
ButtonGroupComponent.propDecorators = {
fdButtonGroupClass: [{ type: HostBinding, args: ['class.fd-button-group',] }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Directive to be applied to buttons that are members of a button group.
*
* ```html
* <button fd-button-grouped>Button</button>
* ```
*/
class ButtonGroupedDirective extends AbstractFdNgxClass {
/**
* @hidden
* @param {?} elementRef
*/
constructor(elementRef) {
super(elementRef);
this.elementRef = elementRef;
/**
* Whether the button should be in compact form.
*/
this.compact = false;
/**
* @hidden
*/
this.fdButtonGroupedClass = true;
}
/**
* @hidden
* @return {?}
*/
_setProperties() {
if (this.size) {
this._addClassToElement('fd-button--' + this.size);
}
if (this.glyph) {
this._addClassToElement('sap-icon--' + this.glyph);
}
if (this.state) {
this._addClassToElement('is-' + this.state);
}
}
}
ButtonGroupedDirective.decorators = [
{ type: Directive, args: [{
// TODO to be discussed
// tslint:disable-next-line:directive-selector
selector: '[fd-button-grouped]'
},] }
];
/** @nocollapse */
ButtonGroupedDirective.ctorParameters = () => [
{ type: ElementRef }
];
ButtonGroupedDirective.propDecorators = {
size: [{ type: Input }],
glyph: [{ type: Input }],
state: [{ type: Input }],
compact: [{ type: Input }, { type: HostBinding, args: ['class.fd-button--compact',] }],
fdButtonGroupedClass: [{ type: HostBinding, args: ['class.fd-button--grouped',] }]
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class ButtonGroupModule {
}
ButtonGroupModule.decorators = [
{ type: NgModule, args: [{
imports: [CommonModule],
exports: [ButtonGroupComponent, ButtonGroupedDirective],
declarations: [ButtonGroupComponent, ButtonGroupedDirective]
},] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @param {?} locale
* @return {?}
*/
function CALENDAR_I18N_FACTORY(locale) {
return new CalendarI18nDefault(locale);
}
/**
* Abstract class which defines the behaviour calendar internationalization. See calendar examples for usage details.
* @abstract
*/
class CalendarI18n {
constructor() {
/**
* Stream to call if the values are changed dynamically. Calendar subscribes to this internally.
*/
this.i18nChange = new Subject();
}
}
CalendarI18n.decorators = [
{ type: Injectable, args: [{
providedIn: 'root',
useFactory: CALENDAR_I18N_FACTORY,
deps: [LOCALE_ID]
},] }
];
/** @nocollapse */ CalendarI18n.ngInjectableDef = defineInjectable({ factory: function CalendarI18n_Factory() { return CALENDAR_I18N_FACTORY(inject(LOCALE_ID)); }, token: CalendarI18n, providedIn: "root" });
/**
* Default implementation of the CalendarI18n service. It will get dates from the application locale if it is present.
*/
class CalendarI18nDefault extends CalendarI18n {
/**
* Constructor takes in a locale_id and gets the appropriate data from Angular.
* @param {?} locale
*/
constructor(locale) {
super();
this.locale = locale;
this.weekdaysFallback = [
'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'
];
this.monthsFullFallback = [
'January', 'February', 'March', 'April', 'May', 'June', 'July',
'August', 'September', 'October', 'November', 'December'
];
this.monthsShortFallback = [
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
];
if (locale) {
/** @type {?} */
const sundayStartWeekdays = getLocaleDayNames(locale, FormStyle.Standalone, TranslationWidth.Short);
this.weekdaysShort = sundayStartWeekdays.map((/**
* @param {?} day
* @param {?} index
* @return {?}
*/
(day, index) => sundayStartWeekdays[(index + 1) % 7]));
this.monthsShort = getLocaleMonthNames(locale, FormStyle.Standalone, TranslationWidth.Abbreviated);
this.monthsFull = getLocaleMonthNames(locale, FormStyle.Standalone, TranslationWidth.Wide);
// Used to keep 0 = Sunday, 1 = Monday and so on.
if (this.weekdaysShort) {
this.weekdaysShort.unshift(this.weekdaysShort.pop());
}
}
this.checkForFallback();
}
/**
* Aria label for a specific date. Default implementation produces the label: {Date} {Month} {Year}.
*
* @param {?} date Native date object to use for the label.
* @return {?}
*/
getDayAriaLabel(date) {
return date.getDate() + ' ' + this.monthsFull[date.getMonth()] + ' ' + date.getFullYear();
}
/**
* Get all full month names.
* @return {?}
*/
getAllFullMonthNames() {
return this.monthsFull;
}
/**
* Get all short month names, such as Nov for November.
* @return {?}
*/
getAllShortMonthNames() {
return this.monthsShort;
}
/**
* Get all short week day names, such as Mo for Monday.
* @return {?}
*/
getAllShortWeekdays() {
return this.weekdaysShort;
}
/**
* Checks if a fallback is needed. Older versions of Angular may need this.
* @private
* @return {?}
*/
checkForFallback() {
if (!this.weekdaysShort || this.weekdaysShort.length === 0) {
this.weekdaysShort = this.weekdaysFallback;
}
if (!this.monthsShort || this.monthsShort.length === 0) {
this.monthsShort = this.monthsShortFallback;
}
if (!this.monthsFull || this.monthsFull.length === 0) {
this.monthsFull = this.monthsFullFallback;
}
}
}
CalendarI18nDefault.decorators = [
{ type: Injectable }
];
/** @nocollapse */
CalendarI18nDefault.ctorParameters = () => [
{ type: String, decorators: [{ type: Optional }, { type: Inject, args: [LOCALE_ID,] }] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Provides i18n support for labels inside the calendar component.
*/
class CalendarI18nLabels {
constructor() {
// This will be needed when we use OnPush change detection.
// readonly labelsChange: Subject<void> = new Subject<void>();
/**
* Year selection aria label. Used on the button to navigate to the years view.
*/
this.yearSelectionLabel = 'Year selection';
/**
* Previous year aria label. Used on the button to switch to a previous year in the years view.
*/
this.previousYearLabel = 'Previous year';
/**
* Next year aria label. Used on the button to switch to a next year in the years view.
*/
this.nextYearLabel = 'Next year';
/**
* Month selection aria label. Used on the button to navigate to the months view.
*/
this.monthSelectionLabel = 'Month selection';
/**
* Previous month aria label. Used on the button to switch to a previous month in the months view.
*/
this.previousMonthLabel = 'Previous month';
/**
* Next month aria label. Used on the button to switch to a next month in the months view.
*/
this.nextMonthLabel = 'Next month';
}
}
CalendarI18nLabels.decorators = [
{ type: Injectable, args: [{ providedIn: 'root' },] }
];
/** @nocollapse */ CalendarI18nLabels.ngInjectableDef = defineInjectable({ factory: function CalendarI18nLabels_Factory() { return new CalendarI18nLabels(); }, token: CalendarI18nLabels, providedIn: "root" });
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @return {?}
*/
function DATE_FORMAT_FACTORY() {
return new DateFormatParserDefault();
}
/**
* Abstract class which defines the behaviour of the date format and parser.
* @abstract
*/
class DateFormatParser {
constructor() {
/**
* Delimiter for the range. This should not show up in the string representation of the dates.
*/
this.rangeDelimiter = ' - ';
}
}
DateFormatParser.decorators = [
{ type: Injectable, args: [{
providedIn: 'root',
useFactory: DATE_FORMAT_FACTORY
},] }
];
/** @nocollapse */ DateFormatParser.ngInjectableDef = defineInjectable({ factory: DATE_FORMAT_FACTORY, token: DateFormatParser, providedIn: "root" });
/**
* Default implementation of the DateForma