UNPKG

@alyle/ui

Version:

Minimal Design, a set of components for Angular

465 lines (452 loc) 21.9 kB
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