codexly-ui 0.0.77 → 0.0.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/codexly-ui.mjs +201 -257
- package/fesm2022/codexly-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/codexly-ui.d.ts +4 -9
package/fesm2022/codexly-ui.mjs
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, computed, ChangeDetectionStrategy, ViewEncapsulation, Component, effect, signal, inject, ElementRef, InjectionToken, PLATFORM_ID, Injectable, Renderer2, ApplicationRef, EnvironmentInjector, DestroyRef, createComponent, Directive, output, contentChildren, NgZone, model, untracked, forwardRef, viewChild, HostListener, ViewChildren, contentChild, Injector, ViewChild, ChangeDetectorRef, ContentChildren, Input, numberAttribute, booleanAttribute
|
|
2
|
+
import { input, computed, ChangeDetectionStrategy, ViewEncapsulation, Component, effect, signal, inject, ElementRef, InjectionToken, PLATFORM_ID, Injectable, Renderer2, ApplicationRef, EnvironmentInjector, DestroyRef, createComponent, Directive, output, contentChildren, NgZone, model, untracked, forwardRef, viewChild, HostListener, ViewChildren, contentChild, Injector, ViewChild, ChangeDetectorRef, ContentChildren, Input, numberAttribute, booleanAttribute } from '@angular/core';
|
|
3
3
|
import { isPlatformBrowser, CurrencyPipe, NgTemplateOutlet, DecimalPipe, NgStyle, DOCUMENT } from '@angular/common';
|
|
4
4
|
import * as i1 from '@angular/forms';
|
|
5
5
|
import { NG_VALUE_ACCESSOR, FormsModule, NgControl, FormControl, ReactiveFormsModule, FormGroup, Validators } from '@angular/forms';
|
|
6
6
|
import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
7
7
|
import { startWith, map, debounceTime, distinctUntilChanged, switchMap, of, catchError } from 'rxjs';
|
|
8
8
|
import * as i1$1 from '@angular/cdk/overlay';
|
|
9
|
-
import { ScrollStrategyOptions, OverlayModule
|
|
9
|
+
import { ScrollStrategyOptions, OverlayModule } from '@angular/cdk/overlay';
|
|
10
10
|
import { Chart, LineController, BarController, PieController, DoughnutController, RadarController, PolarAreaController, CategoryScale, LinearScale, RadialLinearScale, BarElement, LineElement, PointElement, ArcElement, Filler, Tooltip, Legend } from 'chart.js';
|
|
11
|
-
import * as i1$2 from '@angular/cdk/portal';
|
|
12
|
-
import { PortalModule, ComponentPortal } from '@angular/cdk/portal';
|
|
13
|
-
import { FocusTrapFactory } from '@angular/cdk/a11y';
|
|
14
11
|
import { CdkScrollable } from '@angular/cdk/scrolling';
|
|
15
12
|
import { RouterLink, RouterLinkActive } from '@angular/router';
|
|
16
13
|
|
|
@@ -8906,122 +8903,100 @@ const EDITOR_SIZE_MAP = {
|
|
|
8906
8903
|
};
|
|
8907
8904
|
|
|
8908
8905
|
/**
|
|
8909
|
-
*
|
|
8910
|
-
*
|
|
8911
|
-
* Owns the enter / exit animation so every modal gets consistent motion.
|
|
8906
|
+
* Minimal overlay engine — no CDK, no stacking context wars.
|
|
8907
|
+
* Creates a fixed container div in document.body with explicit z-index.
|
|
8912
8908
|
*/
|
|
8913
|
-
class
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8931
|
-
|
|
8909
|
+
class ClxNativeOverlayService {
|
|
8910
|
+
_appRef = inject(ApplicationRef);
|
|
8911
|
+
_injector = inject(Injector);
|
|
8912
|
+
/** Block body scroll like CDK used to */
|
|
8913
|
+
_scrollBlocked = 0;
|
|
8914
|
+
mount(component, injector, options) {
|
|
8915
|
+
// ── backdrop ────────────────────────────────────────────────────────────
|
|
8916
|
+
let backdropEl = null;
|
|
8917
|
+
if (options.backdrop) {
|
|
8918
|
+
backdropEl = document.createElement('div');
|
|
8919
|
+
backdropEl.style.cssText =
|
|
8920
|
+
`position:fixed;inset:0;z-index:${options.zIndex};`;
|
|
8921
|
+
if (options.backdropClass)
|
|
8922
|
+
backdropEl.className = options.backdropClass;
|
|
8923
|
+
document.body.appendChild(backdropEl);
|
|
8924
|
+
}
|
|
8925
|
+
// ── container ────────────────────────────────────────────────────────────
|
|
8926
|
+
const container = document.createElement('div');
|
|
8927
|
+
container.style.cssText =
|
|
8928
|
+
`position:fixed;inset:0;z-index:${options.zIndex + 1};pointer-events:none;display:flex;align-items:center;justify-content:center;padding:1rem;box-sizing:border-box;`;
|
|
8929
|
+
if (options.containerStyle) {
|
|
8930
|
+
Object.assign(container.style, options.containerStyle);
|
|
8931
|
+
}
|
|
8932
|
+
document.body.appendChild(container);
|
|
8933
|
+
// ── component ────────────────────────────────────────────────────────────
|
|
8934
|
+
const compRef = createComponent(component, {
|
|
8935
|
+
environmentInjector: this._appRef.injector,
|
|
8936
|
+
elementInjector: injector,
|
|
8937
|
+
});
|
|
8938
|
+
this._appRef.attachView(compRef.hostView);
|
|
8939
|
+
const el = compRef.location.nativeElement;
|
|
8940
|
+
el.style.pointerEvents = 'auto';
|
|
8941
|
+
container.appendChild(el);
|
|
8942
|
+
// ── scroll block ─────────────────────────────────────────────────────────
|
|
8943
|
+
this._blockScroll();
|
|
8944
|
+
const overlayRef = {
|
|
8945
|
+
backdrop: backdropEl,
|
|
8946
|
+
container,
|
|
8947
|
+
destroy: () => {
|
|
8948
|
+
compRef.destroy();
|
|
8949
|
+
backdropEl?.remove();
|
|
8950
|
+
container.remove();
|
|
8951
|
+
this._unblockScroll();
|
|
8952
|
+
},
|
|
8953
|
+
};
|
|
8954
|
+
return { compRef, overlayRef };
|
|
8932
8955
|
}
|
|
8933
|
-
|
|
8934
|
-
|
|
8935
|
-
|
|
8936
|
-
|
|
8937
|
-
this.onClose?.(result);
|
|
8938
|
-
return;
|
|
8956
|
+
_blockScroll() {
|
|
8957
|
+
this._scrollBlocked++;
|
|
8958
|
+
if (this._scrollBlocked === 1) {
|
|
8959
|
+
document.body.style.overflow = 'hidden';
|
|
8939
8960
|
}
|
|
8940
|
-
this._animate
|
|
8941
|
-
.animate(target, {
|
|
8942
|
-
animation: this._animConfig.animationOut,
|
|
8943
|
-
duration: this._animConfig.animationDuration,
|
|
8944
|
-
trigger: 'manual',
|
|
8945
|
-
fillMode: 'forwards',
|
|
8946
|
-
})
|
|
8947
|
-
.then(() => this.onClose?.(result));
|
|
8948
8961
|
}
|
|
8949
|
-
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
_panel() {
|
|
8955
|
-
return this._el.nativeElement.firstElementChild;
|
|
8962
|
+
_unblockScroll() {
|
|
8963
|
+
this._scrollBlocked = Math.max(0, this._scrollBlocked - 1);
|
|
8964
|
+
if (this._scrollBlocked === 0) {
|
|
8965
|
+
document.body.style.overflow = '';
|
|
8966
|
+
}
|
|
8956
8967
|
}
|
|
8957
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type:
|
|
8958
|
-
static
|
|
8968
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxNativeOverlayService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
8969
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxNativeOverlayService, providedIn: 'root' });
|
|
8959
8970
|
}
|
|
8960
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type:
|
|
8961
|
-
type:
|
|
8962
|
-
args: [{
|
|
8963
|
-
|
|
8964
|
-
standalone: true,
|
|
8965
|
-
imports: [PortalModule],
|
|
8966
|
-
template: `<ng-container [cdkPortalOutlet]="portal()" />`,
|
|
8967
|
-
encapsulation: ViewEncapsulation.None,
|
|
8968
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
8969
|
-
host: { style: 'display:contents' },
|
|
8970
|
-
}]
|
|
8971
|
-
}], propDecorators: { portal: [{ type: i0.Input, args: [{ isSignal: true, alias: "portal", required: false }] }, { type: i0.Output, args: ["portalChange"] }] } });
|
|
8971
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxNativeOverlayService, decorators: [{
|
|
8972
|
+
type: Injectable,
|
|
8973
|
+
args: [{ providedIn: 'root' }]
|
|
8974
|
+
}] });
|
|
8972
8975
|
|
|
8976
|
+
const SIZE_MAX_WIDTH = {
|
|
8977
|
+
sm: '480px',
|
|
8978
|
+
md: '680px',
|
|
8979
|
+
lg: '900px',
|
|
8980
|
+
xl: '1200px',
|
|
8981
|
+
full: '100vw',
|
|
8982
|
+
};
|
|
8973
8983
|
class ClxModalService {
|
|
8974
|
-
_overlay;
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
constructor() {
|
|
8978
|
-
this._overlay = inject(Overlay);
|
|
8979
|
-
this._injector = inject(Injector);
|
|
8980
|
-
this._focusTrapFactory = inject(FocusTrapFactory);
|
|
8981
|
-
}
|
|
8984
|
+
_overlay = inject(ClxNativeOverlayService);
|
|
8985
|
+
_animate = inject(ClxAnimateService);
|
|
8986
|
+
_injector = inject(Injector);
|
|
8982
8987
|
open(
|
|
8983
8988
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8984
8989
|
component, config = {}) {
|
|
8985
|
-
const { hasBackdrop = true, disableClose = false,
|
|
8990
|
+
const { hasBackdrop = true, disableClose = false, size = 'md', data, animationIn = MODAL_ANIM_DEFAULTS.animationIn, animationOut = MODAL_ANIM_DEFAULTS.animationOut, animationDuration = MODAL_ANIM_DEFAULTS.animationDuration, } = config;
|
|
8986
8991
|
const animConfig = { animationIn, animationOut, animationDuration };
|
|
8992
|
+
const maxWidth = SIZE_MAX_WIDTH[size] ?? '680px';
|
|
8987
8993
|
let _resolve;
|
|
8988
8994
|
const _afterClosed = new Promise(res => (_resolve = res));
|
|
8989
|
-
let _focusTrap = null;
|
|
8990
8995
|
let _closing = false;
|
|
8991
|
-
/** Plays exit animation then tears down the overlay. */
|
|
8992
|
-
const closeViaAnimation = (result) => {
|
|
8993
|
-
if (_closing)
|
|
8994
|
-
return;
|
|
8995
|
-
_closing = true;
|
|
8996
|
-
wrapperRef.instance.closeWithAnimation(result);
|
|
8997
|
-
};
|
|
8998
8996
|
const modalRef = {
|
|
8999
8997
|
close(result) { closeViaAnimation(result); },
|
|
9000
8998
|
afterClosed() { return _afterClosed; },
|
|
9001
8999
|
};
|
|
9002
|
-
const extraClasses = Array.isArray(panelClass) ? panelClass : [panelClass];
|
|
9003
|
-
const sizeMaxWidth = {
|
|
9004
|
-
sm: '480px',
|
|
9005
|
-
md: '680px',
|
|
9006
|
-
lg: '900px',
|
|
9007
|
-
xl: '1200px',
|
|
9008
|
-
full: '100vw',
|
|
9009
|
-
};
|
|
9010
|
-
const maxWidth = sizeMaxWidth[size] ?? '600px';
|
|
9011
|
-
const overlayRef = this._overlay.create(new OverlayConfig({
|
|
9012
|
-
hasBackdrop,
|
|
9013
|
-
backdropClass: 'clx-modal-backdrop',
|
|
9014
|
-
panelClass: extraClasses,
|
|
9015
|
-
scrollStrategy: this._overlay.scrollStrategies.block(),
|
|
9016
|
-
positionStrategy: this._overlay.position().global().centerHorizontally().centerVertically(),
|
|
9017
|
-
width: `min(calc(100vw - 2rem), ${maxWidth})`,
|
|
9018
|
-
maxWidth: maxWidth,
|
|
9019
|
-
maxHeight: '90vh',
|
|
9020
|
-
}));
|
|
9021
|
-
Object.assign(overlayRef.overlayElement.style, {
|
|
9022
|
-
display: 'flex',
|
|
9023
|
-
flexDirection: 'column',
|
|
9024
|
-
});
|
|
9025
9000
|
const innerInjector = Injector.create({
|
|
9026
9001
|
parent: this._injector,
|
|
9027
9002
|
providers: [
|
|
@@ -9031,27 +9006,49 @@ class ClxModalService {
|
|
|
9031
9006
|
{ provide: CLX_MODAL_SIZE, useValue: size },
|
|
9032
9007
|
],
|
|
9033
9008
|
});
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9009
|
+
const { compRef, overlayRef } = this._overlay.mount(component, innerInjector, {
|
|
9010
|
+
zIndex: 1000,
|
|
9011
|
+
backdrop: hasBackdrop,
|
|
9012
|
+
backdropClass: 'clx-modal-backdrop',
|
|
9013
|
+
});
|
|
9014
|
+
const panelEl = compRef.location.nativeElement;
|
|
9015
|
+
panelEl.style.width = `min(calc(100vw - 2rem), ${maxWidth})`;
|
|
9016
|
+
panelEl.style.maxWidth = maxWidth;
|
|
9017
|
+
panelEl.style.maxHeight = '90vh';
|
|
9018
|
+
// Enter animation
|
|
9019
|
+
this._animate.animate(panelEl, {
|
|
9020
|
+
animation: animationIn,
|
|
9021
|
+
duration: animationDuration,
|
|
9022
|
+
trigger: 'manual',
|
|
9023
|
+
});
|
|
9024
|
+
const closeViaAnimation = (result) => {
|
|
9025
|
+
if (_closing)
|
|
9026
|
+
return;
|
|
9027
|
+
_closing = true;
|
|
9028
|
+
this._animate.animate(panelEl, {
|
|
9029
|
+
animation: animationOut,
|
|
9030
|
+
duration: animationDuration,
|
|
9031
|
+
trigger: 'manual',
|
|
9032
|
+
fillMode: 'forwards',
|
|
9033
|
+
}).then(() => {
|
|
9034
|
+
overlayRef.destroy();
|
|
9035
|
+
_resolve(result);
|
|
9036
|
+
});
|
|
9042
9037
|
};
|
|
9043
|
-
//
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
if (hasBackdrop && !disableClose) {
|
|
9047
|
-
overlayRef.backdropClick().subscribe(() => closeViaAnimation());
|
|
9038
|
+
// Backdrop click
|
|
9039
|
+
if (hasBackdrop && !disableClose && overlayRef.backdrop) {
|
|
9040
|
+
overlayRef.backdrop.addEventListener('click', () => closeViaAnimation());
|
|
9048
9041
|
}
|
|
9042
|
+
// Escape key
|
|
9049
9043
|
if (!disableClose) {
|
|
9050
|
-
|
|
9051
|
-
|
|
9044
|
+
const onKey = (e) => {
|
|
9045
|
+
if (e.key === 'Escape') {
|
|
9046
|
+
closeViaAnimation();
|
|
9047
|
+
document.removeEventListener('keydown', onKey);
|
|
9048
|
+
}
|
|
9049
|
+
};
|
|
9050
|
+
document.addEventListener('keydown', onKey);
|
|
9052
9051
|
}
|
|
9053
|
-
_focusTrap = this._focusTrapFactory.create(overlayRef.overlayElement);
|
|
9054
|
-
_focusTrap.focusInitialElementWhenReady();
|
|
9055
9052
|
return modalRef;
|
|
9056
9053
|
}
|
|
9057
9054
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxModalService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
@@ -9060,7 +9057,7 @@ class ClxModalService {
|
|
|
9060
9057
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxModalService, decorators: [{
|
|
9061
9058
|
type: Injectable,
|
|
9062
9059
|
args: [{ providedIn: 'root' }]
|
|
9063
|
-
}]
|
|
9060
|
+
}] });
|
|
9064
9061
|
|
|
9065
9062
|
let _clxEditorId = 0;
|
|
9066
9063
|
const TOOLBAR_GROUPS = [
|
|
@@ -13795,45 +13792,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
13795
13792
|
}] } });
|
|
13796
13793
|
|
|
13797
13794
|
class ClxAlertService {
|
|
13798
|
-
_overlay;
|
|
13799
|
-
_injector;
|
|
13800
|
-
_focusTrapFactory;
|
|
13801
|
-
constructor() {
|
|
13802
|
-
this._overlay = inject(Overlay);
|
|
13803
|
-
this._injector = inject(Injector);
|
|
13804
|
-
this._focusTrapFactory = inject(FocusTrapFactory);
|
|
13805
|
-
}
|
|
13806
|
-
// ─── Core open ────────────────────────────────────────────────────────────
|
|
13795
|
+
_overlay = inject(ClxNativeOverlayService);
|
|
13796
|
+
_injector = inject(Injector);
|
|
13807
13797
|
open(options = {}) {
|
|
13808
13798
|
const backdrop = options.backdrop ?? ALERT_DEFAULTS.backdrop;
|
|
13809
13799
|
const disableClose = options.disableClose ?? ALERT_DEFAULTS.disableClose;
|
|
13810
13800
|
let _resolve;
|
|
13811
13801
|
const promise = new Promise(res => (_resolve = res));
|
|
13812
|
-
let _focusTrap = null;
|
|
13813
|
-
// Wrap resolve so we can dispose the overlay after the exit animation
|
|
13814
13802
|
const resolve = (result) => {
|
|
13815
|
-
|
|
13816
|
-
overlayRef.dispose();
|
|
13803
|
+
overlayRef.destroy();
|
|
13817
13804
|
_resolve(result);
|
|
13818
13805
|
};
|
|
13819
|
-
const overlayRef = this._overlay.create(new OverlayConfig({
|
|
13820
|
-
hasBackdrop: backdrop,
|
|
13821
|
-
backdropClass: 'clx-alert-backdrop',
|
|
13822
|
-
scrollStrategy: this._overlay.scrollStrategies.block(),
|
|
13823
|
-
positionStrategy: this._overlay.position().global().centerHorizontally().centerVertically(),
|
|
13824
|
-
}));
|
|
13825
|
-
// Make the overlay pane a flex centering layer
|
|
13826
|
-
Object.assign(overlayRef.overlayElement.style, {
|
|
13827
|
-
position: 'fixed',
|
|
13828
|
-
inset: '0',
|
|
13829
|
-
width: '100vw',
|
|
13830
|
-
height: '100vh',
|
|
13831
|
-
display: 'flex',
|
|
13832
|
-
alignItems: 'center',
|
|
13833
|
-
justifyContent: 'center',
|
|
13834
|
-
padding: '1rem',
|
|
13835
|
-
boxSizing: 'border-box',
|
|
13836
|
-
});
|
|
13837
13806
|
const innerInjector = Injector.create({
|
|
13838
13807
|
parent: this._injector,
|
|
13839
13808
|
providers: [
|
|
@@ -13841,19 +13810,25 @@ class ClxAlertService {
|
|
|
13841
13810
|
{ provide: CLX_ALERT_RESOLVE, useValue: resolve },
|
|
13842
13811
|
],
|
|
13843
13812
|
});
|
|
13844
|
-
overlayRef.
|
|
13845
|
-
|
|
13846
|
-
|
|
13813
|
+
const { overlayRef } = this._overlay.mount(ClxAlertComponent, innerInjector, {
|
|
13814
|
+
zIndex: 1000,
|
|
13815
|
+
backdrop,
|
|
13816
|
+
backdropClass: 'clx-alert-backdrop',
|
|
13817
|
+
});
|
|
13818
|
+
if (backdrop && !disableClose && overlayRef.backdrop) {
|
|
13819
|
+
overlayRef.backdrop.addEventListener('click', () => resolve(false));
|
|
13847
13820
|
}
|
|
13848
13821
|
if (!disableClose) {
|
|
13849
|
-
|
|
13850
|
-
|
|
13822
|
+
const onKey = (e) => {
|
|
13823
|
+
if (e.key === 'Escape') {
|
|
13824
|
+
resolve(false);
|
|
13825
|
+
document.removeEventListener('keydown', onKey);
|
|
13826
|
+
}
|
|
13827
|
+
};
|
|
13828
|
+
document.addEventListener('keydown', onKey);
|
|
13851
13829
|
}
|
|
13852
|
-
_focusTrap = this._focusTrapFactory.create(overlayRef.overlayElement);
|
|
13853
|
-
_focusTrap.focusInitialElementWhenReady();
|
|
13854
13830
|
return promise;
|
|
13855
13831
|
}
|
|
13856
|
-
// ─── Convenience shortcuts ────────────────────────────────────────────────
|
|
13857
13832
|
success(title, message, opts = {}) {
|
|
13858
13833
|
return this.open({ type: 'success', title, message, ...opts });
|
|
13859
13834
|
}
|
|
@@ -13867,13 +13842,7 @@ class ClxAlertService {
|
|
|
13867
13842
|
return this.open({ type: 'info', title, message, ...opts });
|
|
13868
13843
|
}
|
|
13869
13844
|
confirm(title, message, opts = {}) {
|
|
13870
|
-
return this.open({
|
|
13871
|
-
type: 'confirm',
|
|
13872
|
-
title,
|
|
13873
|
-
message,
|
|
13874
|
-
showCancelButton: true,
|
|
13875
|
-
...opts,
|
|
13876
|
-
});
|
|
13845
|
+
return this.open({ type: 'confirm', title, message, showCancelButton: true, ...opts });
|
|
13877
13846
|
}
|
|
13878
13847
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxAlertService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
13879
13848
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxAlertService, providedIn: 'root' });
|
|
@@ -13881,42 +13850,23 @@ class ClxAlertService {
|
|
|
13881
13850
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxAlertService, decorators: [{
|
|
13882
13851
|
type: Injectable,
|
|
13883
13852
|
args: [{ providedIn: 'root' }]
|
|
13884
|
-
}]
|
|
13853
|
+
}] });
|
|
13885
13854
|
|
|
13886
13855
|
class ClxDrawerService {
|
|
13887
|
-
_overlay;
|
|
13888
|
-
|
|
13889
|
-
|
|
13890
|
-
constructor() {
|
|
13891
|
-
this._overlay = inject(Overlay);
|
|
13892
|
-
this._injector = inject(Injector);
|
|
13893
|
-
this._focusTrapFactory = inject(FocusTrapFactory);
|
|
13894
|
-
}
|
|
13856
|
+
_overlay = inject(ClxNativeOverlayService);
|
|
13857
|
+
_animate = inject(ClxAnimateService);
|
|
13858
|
+
_injector = inject(Injector);
|
|
13895
13859
|
open(
|
|
13896
13860
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13897
13861
|
component, config = {}) {
|
|
13898
|
-
const { hasBackdrop = false, disableClose = false,
|
|
13862
|
+
const { hasBackdrop = false, disableClose = false, size = 'md', data, } = config;
|
|
13899
13863
|
let _resolve;
|
|
13900
13864
|
const _afterClosed = new Promise(res => (_resolve = res));
|
|
13901
|
-
let
|
|
13865
|
+
let _closing = false;
|
|
13902
13866
|
const drawerRef = {
|
|
13903
|
-
close(result) {
|
|
13904
|
-
|
|
13905
|
-
overlayRef.dispose();
|
|
13906
|
-
_resolve(result);
|
|
13907
|
-
},
|
|
13908
|
-
afterClosed() {
|
|
13909
|
-
return _afterClosed;
|
|
13910
|
-
},
|
|
13867
|
+
close(result) { closeViaAnimation(result); },
|
|
13868
|
+
afterClosed() { return _afterClosed; },
|
|
13911
13869
|
};
|
|
13912
|
-
const extraClasses = Array.isArray(panelClass) ? panelClass : [panelClass];
|
|
13913
|
-
const overlayRef = this._overlay.create(new OverlayConfig({
|
|
13914
|
-
hasBackdrop,
|
|
13915
|
-
backdropClass: 'clx-modal-backdrop',
|
|
13916
|
-
panelClass: extraClasses,
|
|
13917
|
-
scrollStrategy: this._overlay.scrollStrategies.block(),
|
|
13918
|
-
positionStrategy: this._overlay.position().global().right('0').top('0'),
|
|
13919
|
-
}));
|
|
13920
13870
|
const innerInjector = Injector.create({
|
|
13921
13871
|
parent: this._injector,
|
|
13922
13872
|
providers: [
|
|
@@ -13925,26 +13875,51 @@ class ClxDrawerService {
|
|
|
13925
13875
|
{ provide: CLX_DRAWER_SIZE, useValue: size },
|
|
13926
13876
|
],
|
|
13927
13877
|
});
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13878
|
+
const { compRef, overlayRef } = this._overlay.mount(component, innerInjector, {
|
|
13879
|
+
zIndex: 1000,
|
|
13880
|
+
backdrop: hasBackdrop,
|
|
13881
|
+
backdropClass: 'clx-modal-backdrop',
|
|
13882
|
+
containerStyle: {
|
|
13883
|
+
alignItems: 'flex-start',
|
|
13884
|
+
justifyContent: 'flex-end',
|
|
13885
|
+
padding: '0',
|
|
13886
|
+
},
|
|
13887
|
+
});
|
|
13888
|
+
const panelEl = compRef.location.nativeElement;
|
|
13889
|
+
panelEl.style.height = '100vh';
|
|
13890
|
+
panelEl.style.pointerEvents = 'auto';
|
|
13891
|
+
// Slide in from right
|
|
13892
|
+
this._animate.animate(panelEl, {
|
|
13893
|
+
animation: 'fadeInRight',
|
|
13894
|
+
duration: 300,
|
|
13895
|
+
trigger: 'manual',
|
|
13896
|
+
});
|
|
13897
|
+
const closeViaAnimation = (result) => {
|
|
13898
|
+
if (_closing)
|
|
13899
|
+
return;
|
|
13900
|
+
_closing = true;
|
|
13901
|
+
this._animate.animate(panelEl, {
|
|
13902
|
+
animation: 'fadeOutRight',
|
|
13903
|
+
duration: 300,
|
|
13904
|
+
trigger: 'manual',
|
|
13905
|
+
fillMode: 'forwards',
|
|
13906
|
+
}).then(() => {
|
|
13907
|
+
overlayRef.destroy();
|
|
13908
|
+
_resolve(result);
|
|
13909
|
+
});
|
|
13910
|
+
};
|
|
13911
|
+
if (hasBackdrop && !disableClose && overlayRef.backdrop) {
|
|
13912
|
+
overlayRef.backdrop.addEventListener('click', () => closeViaAnimation());
|
|
13941
13913
|
}
|
|
13942
13914
|
if (!disableClose) {
|
|
13943
|
-
|
|
13944
|
-
|
|
13915
|
+
const onKey = (e) => {
|
|
13916
|
+
if (e.key === 'Escape') {
|
|
13917
|
+
closeViaAnimation();
|
|
13918
|
+
document.removeEventListener('keydown', onKey);
|
|
13919
|
+
}
|
|
13920
|
+
};
|
|
13921
|
+
document.addEventListener('keydown', onKey);
|
|
13945
13922
|
}
|
|
13946
|
-
_focusTrap = this._focusTrapFactory.create(overlayRef.overlayElement);
|
|
13947
|
-
_focusTrap.focusInitialElementWhenReady();
|
|
13948
13923
|
return drawerRef;
|
|
13949
13924
|
}
|
|
13950
13925
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxDrawerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
@@ -13953,47 +13928,16 @@ class ClxDrawerService {
|
|
|
13953
13928
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxDrawerService, decorators: [{
|
|
13954
13929
|
type: Injectable,
|
|
13955
13930
|
args: [{ providedIn: 'root' }]
|
|
13956
|
-
}]
|
|
13931
|
+
}] });
|
|
13957
13932
|
|
|
13958
|
-
/** Dedicated OverlayContainer for toasts — lives in its own div above all modals */
|
|
13959
|
-
class ToastOverlayContainer extends OverlayContainer {
|
|
13960
|
-
_createContainer() {
|
|
13961
|
-
const el = document.createElement('div');
|
|
13962
|
-
el.classList.add('clx-toast-overlay-container');
|
|
13963
|
-
el.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:0;z-index:99999;pointer-events:none;';
|
|
13964
|
-
document.body.appendChild(el);
|
|
13965
|
-
this._containerElement = el;
|
|
13966
|
-
}
|
|
13967
|
-
}
|
|
13968
13933
|
class ClxToastService {
|
|
13934
|
+
_appRef = inject(ApplicationRef);
|
|
13969
13935
|
_injector = inject(Injector);
|
|
13970
|
-
|
|
13936
|
+
// Each position has its own container div at z-index 9000 (above modals)
|
|
13971
13937
|
_containers = new Map();
|
|
13972
|
-
_getOverlay() {
|
|
13973
|
-
if (this._toastOverlay)
|
|
13974
|
-
return this._toastOverlay;
|
|
13975
|
-
const childInjector = Injector.create({
|
|
13976
|
-
parent: this._injector,
|
|
13977
|
-
providers: [
|
|
13978
|
-
{
|
|
13979
|
-
provide: OverlayContainer,
|
|
13980
|
-
useFactory: () => runInInjectionContext(this._injector, () => new ToastOverlayContainer()),
|
|
13981
|
-
},
|
|
13982
|
-
{ provide: Overlay },
|
|
13983
|
-
],
|
|
13984
|
-
});
|
|
13985
|
-
this._toastOverlay = childInjector.get(Overlay);
|
|
13986
|
-
return this._toastOverlay;
|
|
13987
|
-
}
|
|
13988
|
-
// ─── Core show ─────────────────────────────────────────────────────────────
|
|
13989
13938
|
show(options) {
|
|
13990
13939
|
const position = options.position ?? TOAST_DEFAULTS.position;
|
|
13991
13940
|
const container = this._getOrCreateContainer(position);
|
|
13992
|
-
// Move our dedicated overlay container to the end of body on every show
|
|
13993
|
-
// so it always appears after any modal cdk-overlay-container
|
|
13994
|
-
const el = container.overlayRef.overlayElement.closest('.clx-toast-overlay-container');
|
|
13995
|
-
if (el)
|
|
13996
|
-
document.body.appendChild(el);
|
|
13997
13941
|
const entry = {
|
|
13998
13942
|
id: this._uid(),
|
|
13999
13943
|
type: options.type ?? TOAST_DEFAULTS.type,
|
|
@@ -14014,7 +13958,6 @@ class ClxToastService {
|
|
|
14014
13958
|
const list = container.instance.entries();
|
|
14015
13959
|
container.instance.entries.set(isBottom ? [...list, entry] : [entry, ...list]);
|
|
14016
13960
|
}
|
|
14017
|
-
// ─── Convenience shortcuts ─────────────────────────────────────────────────
|
|
14018
13961
|
success(message, opts = {}) {
|
|
14019
13962
|
this.show({ ...opts, type: 'green', message });
|
|
14020
13963
|
}
|
|
@@ -14030,25 +13973,26 @@ class ClxToastService {
|
|
|
14030
13973
|
dismissAll() {
|
|
14031
13974
|
this._containers.forEach(c => c.instance.entries.set([]));
|
|
14032
13975
|
}
|
|
14033
|
-
// ─── Container management ──────────────────────────────────────────────────
|
|
14034
13976
|
_getOrCreateContainer(position) {
|
|
14035
13977
|
const existing = this._containers.get(position);
|
|
14036
13978
|
if (existing)
|
|
14037
13979
|
return existing;
|
|
14038
|
-
|
|
14039
|
-
const
|
|
14040
|
-
|
|
14041
|
-
|
|
14042
|
-
|
|
14043
|
-
|
|
14044
|
-
|
|
14045
|
-
|
|
14046
|
-
|
|
14047
|
-
|
|
13980
|
+
// Dedicated div — completely separate from modal's DOM tree
|
|
13981
|
+
const el = document.createElement('div');
|
|
13982
|
+
el.style.cssText = 'position:fixed;inset:0;z-index:9000;pointer-events:none;';
|
|
13983
|
+
document.body.appendChild(el);
|
|
13984
|
+
const ref = createComponent(ClxToastContainerComponent, {
|
|
13985
|
+
environmentInjector: this._appRef.injector,
|
|
13986
|
+
elementInjector: this._injector,
|
|
13987
|
+
});
|
|
13988
|
+
ref.setInput('position', position);
|
|
13989
|
+
this._appRef.attachView(ref.hostView);
|
|
13990
|
+
const compEl = ref.location.nativeElement;
|
|
13991
|
+
el.appendChild(compEl);
|
|
13992
|
+
const entry = { el, instance: ref.instance };
|
|
14048
13993
|
this._containers.set(position, entry);
|
|
14049
13994
|
return entry;
|
|
14050
13995
|
}
|
|
14051
|
-
// ─── Utilities ─────────────────────────────────────────────────────────────
|
|
14052
13996
|
_uid() {
|
|
14053
13997
|
return `toast-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
14054
13998
|
}
|