@alyle/ui
Version:
Minimal Design, a set of components for Angular
465 lines (452 loc) • 21.9 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, InjectionToken, TemplateRef, ViewContainerRef, ViewChild, ChangeDetectionStrategy, Component, Injector, Directive, NgModule } from '@angular/core';
import * as i1 from '@alyle/ui';
import { shadowBuilder, st2c, StyleCollection, StyleRenderer, STYLES_BACKDROP_DARK, createStyle, LyStyle, LyOverlayRef, LyCommonModule, LyOverlayModule } from '@alyle/ui';
import { trigger, state, transition, style, animate } from '@angular/animations';
import { Subject } from 'rxjs';
import { _getFocusedElementPierceShadowDom } from '@angular/cdk/platform';
import * as i2 from '@angular/cdk/a11y';
import { A11yModule } from '@angular/cdk/a11y';
import { ESCAPE } from '@angular/cdk/keycodes';
import { CommonModule } from '@angular/common';
class LyDialogRef {
get afterOpened() {
return this._overlayRef.componentRef.instance._afterOpened.asObservable();
}
get beforeClosed() {
return this._overlayRef.componentRef.instance._beforeClosed.asObservable();
}
get afterClosed() {
return this._overlayRef.componentRef.instance._afterClosed.asObservable();
}
/**
* @internal
* @docs-private
*/
get result() {
return this._result;
}
constructor(_overlayRef) {
this._overlayRef = _overlayRef;
}
close(result) {
const dialogContainer = this._overlayRef.componentRef.instance;
dialogContainer._beforeClosed.next(result);
dialogContainer._beforeClosed.complete();
dialogContainer._startClose();
this._result = result;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogRef, deps: [{ token: i1.LyOverlayRef }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogRef }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogRef, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.LyOverlayRef }] });
/**
* Configuration for opening a modal dialog with the LyDialog service.
*/
class LyDialogConfig {
constructor() {
/**
* Max-height of the dialog container. If a number is provided, pixel units are assumed.
* Defaults to `['calc(100vw - 90px)']`
* Support beakpoints
*/
this.maxHeight = ['calc(100vh - 64px)'];
/**
* Max-width of the dialog container. If a number is provided, pixel units are assumed.
* Defaults to `['calc(100vw - 90px)']`
* Support beakpoints
*/
this.maxWidth = ['calc(100vw - 64px)'];
/** Whether the dialog has a backdrop. */
this.hasBackdrop = true;
}
}
const LY_DIALOG_DATA = new InjectionToken('LyDialogData');
const STYLE_PRIORITY$3 = -2;
/** @docs-private */
const STYLES = (theme, ref) => {
const dialog = ref.selectorsOf(STYLES);
return {
root: () => (_className) => `${_className}{display:flex;position:relative;background-color:${theme.background.primary.default};border-radius:4px;box-shadow:${shadowBuilder(12)};overflow:auto;pointer-events:auto;}${_className} > :first-child{display:flex;flex-direction:column;width:100%;}${st2c(((theme.dialog
&& theme.dialog.root
&& (theme.dialog.root instanceof StyleCollection
? theme.dialog.root.setTransformer(fn => fn(dialog))
: theme.dialog.root(dialog)))), `${_className}`)}`
};
};
/** @docs-private */
class LyDialogContainer {
constructor(sRenderer, _appRef, _overlayRef, _theme, _el, _cd, _renderer, _trapFactory) {
this.sRenderer = sRenderer;
this._appRef = _appRef;
this._overlayRef = _overlayRef;
this._theme = _theme;
this._el = _el;
this._cd = _cd;
this._renderer = _renderer;
this._trapFactory = _trapFactory;
/** @docs-private */
this.classes = this._theme.addStyleSheet(STYLES, STYLE_PRIORITY$3);
/** Previously focused element to restore focus to upon destroy when using autoCapture. */
this._previouslyFocusedElement = null;
/** @internal */
this._afterOpened = new Subject();
/** @internal */
this._beforeClosed = new Subject();
/** @internal */
this._afterClosed = new Subject();
/**
* State of the dialog animation.
* @internal
*/
this._state = 'enter';
_renderer.addClass(_el.nativeElement, this.classes.root);
}
ngOnInit() {
if (this._componentFactoryOrTemplate instanceof TemplateRef) {
const context = new LyDialogContext(this._newInjector);
this._embeddedViewRef = this.viewContainerRef
.createEmbeddedView(this._componentFactoryOrTemplate, context);
}
else {
this._componentRef = this.viewContainerRef
.createComponent(this._componentFactoryOrTemplate, undefined, this._newInjector);
}
// If exist dialogStyleBlock apply for this component, else do nothing.
const { containerClass } = this._newInjector.get(LyDialogConfig);
if (containerClass) {
this._renderer.addClass(this._el.nativeElement, containerClass);
}
}
ngAfterContentInit() {
this._focusTrap = this._trapFactory.create(this._el.nativeElement);
this._captureFocus();
}
ngOnDestroy() {
this._focusTrap.destroy();
if (this._previouslyFocusedElement) {
this._previouslyFocusedElement.focus();
this._previouslyFocusedElement = null;
}
}
/** @internal */
_init(componentFactoryOrTemplate, newInjector) {
this._componentFactoryOrTemplate = componentFactoryOrTemplate;
this._newInjector = newInjector;
}
/**
* Start to close, starts the dialog exit animation.
* @internal
*/
_startClose() {
this._state = 'exit';
this._cd.markForCheck();
}
_onAnimationStart(event) {
if (event.toState === 'enter') {
this._overlayRef.onResizeScroll();
}
}
/** @internal */
_onAnimationDone(event) {
if (event.toState === 'exit') {
const dialogRef = this._newInjector.get(LyDialogRef);
this._destroy();
this._overlayRef.destroy();
this._afterClosed.next(dialogRef.result);
this._afterClosed.complete();
}
else if (event.toState === 'enter') {
this._afterOpened.next();
this._afterOpened.complete();
}
}
_destroy() {
if (this._componentRef) {
this._appRef.detachView(this._componentRef.hostView);
this._componentRef.destroy();
}
else {
this._appRef.detachView(this._embeddedViewRef);
this._embeddedViewRef.detach();
this._embeddedViewRef.destroy();
}
}
/** @internal */
_getHostElement() {
return this._el.nativeElement;
}
_captureFocus() {
this._previouslyFocusedElement = _getFocusedElementPierceShadowDom();
this._focusTrap.focusInitialElementWhenReady();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogContainer, deps: [{ token: i1.StyleRenderer }, { token: i0.ApplicationRef }, { token: i1.LyOverlayRef }, { token: i1.LyTheme2 }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i2.FocusTrapFactory }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: LyDialogContainer, isStandalone: false, selector: "ly-dialog-container", host: { listeners: { "@dialogContainer.start": "_onAnimationStart($event)", "@dialogContainer.done": "_onAnimationDone($event)" }, properties: { "@dialogContainer": "_state" } }, providers: [
StyleRenderer
], viewQueries: [{ propertyName: "viewContainerRef", first: true, predicate: TemplateRef, descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: '<ng-template></ng-template>', isInline: true, animations: [
trigger('dialogContainer', [
state('void, exit', style({ opacity: 0, transform: 'scale(0.7)' })),
state('enter', style({ transform: 'none' })),
transition('* => enter', animate('150ms cubic-bezier(0, 0, 0.2, 1)', style({ transform: 'none', opacity: 1 }))),
transition('* => void, * => exit', animate('75ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({ opacity: 0 })))
])
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogContainer, decorators: [{
type: Component,
args: [{
selector: 'ly-dialog-container',
template: '<ng-template></ng-template>',
changeDetection: ChangeDetectionStrategy.OnPush,
animations: [
trigger('dialogContainer', [
state('void, exit', style({ opacity: 0, transform: 'scale(0.7)' })),
state('enter', style({ transform: 'none' })),
transition('* => enter', animate('150ms cubic-bezier(0, 0, 0.2, 1)', style({ transform: 'none', opacity: 1 }))),
transition('* => void, * => exit', animate('75ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({ opacity: 0 })))
])
],
host: {
'[@dialogContainer]': '_state',
'(@dialogContainer.start)': '_onAnimationStart($event)',
'(@dialogContainer.done)': '_onAnimationDone($event)'
},
providers: [
StyleRenderer
],
standalone: false
}]
}], ctorParameters: () => [{ type: i1.StyleRenderer }, { type: i0.ApplicationRef }, { type: i1.LyOverlayRef }, { type: i1.LyTheme2 }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: i2.FocusTrapFactory }], propDecorators: { viewContainerRef: [{
type: ViewChild,
args: [TemplateRef, { read: ViewContainerRef, static: true }]
}] } });
class LyDialogContext {
get data() {
return this._injector.get(LY_DIALOG_DATA);
}
constructor(_injector) {
this._injector = _injector;
this.$implicit = this._injector.get(LyDialogRef);
this.dialogRef = this._injector.get(LyDialogRef);
}
}
class DynamicInjector {
constructor(_newInjector, _parentInjector) {
this._newInjector = _newInjector;
this._parentInjector = _parentInjector;
}
get(token, notFoundValue, _flags) {
const value = this._newInjector.get(token, notFoundValue);
if (value) {
return value;
}
return this._parentInjector.get(token, notFoundValue);
}
}
const dialogContainerStyleProperties = [
'width',
'maxWidth',
'minWidth',
'height',
'maxHeight',
'minHeight',
];
class LyDialog {
constructor(_overlay, _componentFactoryResolver, _theme, _injector) {
this._overlay = _overlay;
this._componentFactoryResolver = _componentFactoryResolver;
this._theme = _theme;
this._injector = _injector;
}
open(componentOrTemplateRef, config) {
// merge with default config
config = { ...new LyDialogConfig(), ...config };
let componentFactoryOrTemplate;
if (componentOrTemplateRef instanceof TemplateRef) {
componentFactoryOrTemplate = componentOrTemplateRef;
}
else {
componentFactoryOrTemplate = this._componentFactoryResolver.resolveComponentFactory(componentOrTemplateRef);
}
const noop = () => { };
const overlayRef = this._overlay.create(LyDialogContainer, null, {
styles: {
top: 0,
left: 0,
right: 0,
bottom: 0
},
hasBackdrop: config.hasBackdrop,
onResizeScroll: noop,
disableClose: config.disableClose,
backdropClass: config.backdropClass || this._theme.style(STYLES_BACKDROP_DARK),
fnDestroy: () => {
dialogRef.close();
keydownEventsSuscription.unsubscribe();
}
});
const keydownEvents = overlayRef.keydownEvents();
const keydownEventsSuscription = keydownEvents.subscribe((event) => {
if (!(config?.disableClose) && event.keyCode === ESCAPE) {
dialogRef.close();
}
});
const instance = overlayRef.componentRef.instance;
dialogContainerStyleProperties.forEach(property => {
if (config[property]) {
createStyle(instance, { key: property, и: LyStyle.и }, config[property], LyStyle[property], LyStyle.$priority);
}
});
const providers = [
{
provide: LyDialogRef,
useValue: new LyDialogRef(overlayRef.componentRef.injector.get(LyOverlayRef))
},
{
provide: LyDialogConfig,
useValue: config
}
];
if (config.data != null) {
providers.push({
provide: LY_DIALOG_DATA,
useValue: config.data
});
}
const newInjector = new DynamicInjector(Injector.create(providers, overlayRef.componentRef.injector), this._injector);
instance._init(componentFactoryOrTemplate, newInjector);
const dialogRef = newInjector.get(LyDialogRef);
return dialogRef;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialog, deps: [{ token: i1.LyOverlay }, { token: i0.ComponentFactoryResolver }, { token: i1.LyTheme2 }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialog }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialog, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.LyOverlay }, { type: i0.ComponentFactoryResolver }, { type: i1.LyTheme2 }, { type: i0.Injector }] });
/** @docs-private */
const STYLE_PRIORITY$2 = -2;
/** @docs-private */
const STYLES_DIALOG_TITLE = (theme) => (_className) => `${_className}{display:block;flex:0 0 auto;margin:20px 0 16px;padding:0 24px;font-size:20px;line-height:24px;font-weight:500;font-family:${theme.typography.fontFamily};}`;
class LyDialogTitle {
constructor(_renderer, _el, _theme) {
this._renderer = _renderer;
this._el = _el;
this._theme = _theme;
}
ngOnInit() {
this._renderer.addClass(this._el.nativeElement, this._theme.renderStyle(STYLES_DIALOG_TITLE, STYLE_PRIORITY$2));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogTitle, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i1.LyTheme2 }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.10", type: LyDialogTitle, isStandalone: false, selector: "[ly-dialog-title], [lyDialogTitle]", exportAs: ["lyDialogTitle"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogTitle, decorators: [{
type: Directive,
args: [{
selector: '[ly-dialog-title], [lyDialogTitle]',
exportAs: 'lyDialogTitle',
standalone: false
}]
}], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i1.LyTheme2 }] });
/** @docs-private */
const STYLE_PRIORITY$1 = -2;
/** @docs-private */
const STYLES_DIALOG_CONTENT = () => (_className) => `${_className}{display:block;overflow-y:auto;flex:1 1 auto;padding:0 24px 24px;-webkit-overflow-scrolling:touch;}`;
class LyDialogContent {
constructor(_renderer, _el, _theme) {
this._renderer = _renderer;
this._el = _el;
this._theme = _theme;
}
ngOnInit() {
this._renderer.addClass(this._el.nativeElement, this._theme.renderStyle(STYLES_DIALOG_CONTENT, STYLE_PRIORITY$1));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogContent, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i1.LyTheme2 }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.10", type: LyDialogContent, isStandalone: false, selector: "ly-dialog-content, [ly-dialog-content], [lyDialogContent]", exportAs: ["lyDialogContent"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogContent, decorators: [{
type: Directive,
args: [{
selector: 'ly-dialog-content, [ly-dialog-content], [lyDialogContent]',
exportAs: 'lyDialogContent',
standalone: false
}]
}], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i1.LyTheme2 }] });
/** @docs-private */
const STYLE_PRIORITY = -2;
/** @docs-private */
const STYLES_DIALOG_ACTIONS = () => (_className) => `${_className}{display:flex;flex:0 0 auto;padding:8px;flex-wrap:wrap;min-height:52px;align-items:center;}`;
class LyDialogActions {
constructor(_renderer, _el, _theme) {
this._renderer = _renderer;
this._el = _el;
this._theme = _theme;
}
ngOnInit() {
this._renderer.addClass(this._el.nativeElement, this._theme.renderStyle(STYLES_DIALOG_ACTIONS, STYLE_PRIORITY));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogActions, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i1.LyTheme2 }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.10", type: LyDialogActions, isStandalone: false, selector: "ly-dialog-actions, [ly-dialog-actions], [lyDialogActions]", exportAs: ["lyDialogActions"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogActions, decorators: [{
type: Directive,
args: [{
selector: 'ly-dialog-actions, [ly-dialog-actions], [lyDialogActions]',
exportAs: 'lyDialogActions',
standalone: false
}]
}], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i1.LyTheme2 }] });
class LyDialogModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.10", ngImport: i0, type: LyDialogModule, declarations: [LyDialogContainer,
LyDialogTitle,
LyDialogContent,
LyDialogActions], imports: [CommonModule,
LyCommonModule,
LyOverlayModule,
A11yModule], exports: [LyCommonModule,
LyDialogContainer,
LyDialogTitle,
LyDialogContent,
LyDialogActions] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogModule, providers: [
LyDialog
], imports: [CommonModule,
LyCommonModule,
LyOverlayModule,
A11yModule, LyCommonModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyDialogModule, decorators: [{
type: NgModule,
args: [{
declarations: [
LyDialogContainer,
LyDialogTitle,
LyDialogContent,
LyDialogActions
],
imports: [
CommonModule,
LyCommonModule,
LyOverlayModule,
A11yModule
],
exports: [
LyCommonModule,
LyDialogContainer,
LyDialogTitle,
LyDialogContent,
LyDialogActions
],
providers: [
LyDialog
]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { LY_DIALOG_DATA, LyDialog, LyDialogActions, LyDialogContainer, LyDialogContent, LyDialogContext, LyDialogModule, LyDialogRef, LyDialogTitle };
//# sourceMappingURL=alyle-ui-dialog.mjs.map