codexly-ui 0.0.77 → 0.0.79
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 +202 -257
- package/fesm2022/codexly-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/codexly-ui.d.ts +11 -11
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 = [
|
|
@@ -9804,6 +9801,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
9804
9801
|
}] } });
|
|
9805
9802
|
|
|
9806
9803
|
const SWITCH_SIZE_MAP = {
|
|
9804
|
+
xs: { track: 'w-7 h-4', thumb: 'w-3 h-3', translate: 'translate-x-3', label: 'text-xs' },
|
|
9807
9805
|
sm: { track: 'w-9 h-5', thumb: 'w-4 h-4', translate: 'translate-x-4', label: 'text-xs' },
|
|
9808
9806
|
md: { track: 'w-12 h-6', thumb: 'w-5 h-5', translate: 'translate-x-6', label: 'text-sm' },
|
|
9809
9807
|
lg: { track: 'w-14 h-7', thumb: 'w-6 h-6', translate: 'translate-x-7', label: 'text-base' },
|
|
@@ -13795,45 +13793,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
13795
13793
|
}] } });
|
|
13796
13794
|
|
|
13797
13795
|
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 ────────────────────────────────────────────────────────────
|
|
13796
|
+
_overlay = inject(ClxNativeOverlayService);
|
|
13797
|
+
_injector = inject(Injector);
|
|
13807
13798
|
open(options = {}) {
|
|
13808
13799
|
const backdrop = options.backdrop ?? ALERT_DEFAULTS.backdrop;
|
|
13809
13800
|
const disableClose = options.disableClose ?? ALERT_DEFAULTS.disableClose;
|
|
13810
13801
|
let _resolve;
|
|
13811
13802
|
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
13803
|
const resolve = (result) => {
|
|
13815
|
-
|
|
13816
|
-
overlayRef.dispose();
|
|
13804
|
+
overlayRef.destroy();
|
|
13817
13805
|
_resolve(result);
|
|
13818
13806
|
};
|
|
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
13807
|
const innerInjector = Injector.create({
|
|
13838
13808
|
parent: this._injector,
|
|
13839
13809
|
providers: [
|
|
@@ -13841,19 +13811,25 @@ class ClxAlertService {
|
|
|
13841
13811
|
{ provide: CLX_ALERT_RESOLVE, useValue: resolve },
|
|
13842
13812
|
],
|
|
13843
13813
|
});
|
|
13844
|
-
overlayRef.
|
|
13845
|
-
|
|
13846
|
-
|
|
13814
|
+
const { overlayRef } = this._overlay.mount(ClxAlertComponent, innerInjector, {
|
|
13815
|
+
zIndex: 1000,
|
|
13816
|
+
backdrop,
|
|
13817
|
+
backdropClass: 'clx-alert-backdrop',
|
|
13818
|
+
});
|
|
13819
|
+
if (backdrop && !disableClose && overlayRef.backdrop) {
|
|
13820
|
+
overlayRef.backdrop.addEventListener('click', () => resolve(false));
|
|
13847
13821
|
}
|
|
13848
13822
|
if (!disableClose) {
|
|
13849
|
-
|
|
13850
|
-
|
|
13823
|
+
const onKey = (e) => {
|
|
13824
|
+
if (e.key === 'Escape') {
|
|
13825
|
+
resolve(false);
|
|
13826
|
+
document.removeEventListener('keydown', onKey);
|
|
13827
|
+
}
|
|
13828
|
+
};
|
|
13829
|
+
document.addEventListener('keydown', onKey);
|
|
13851
13830
|
}
|
|
13852
|
-
_focusTrap = this._focusTrapFactory.create(overlayRef.overlayElement);
|
|
13853
|
-
_focusTrap.focusInitialElementWhenReady();
|
|
13854
13831
|
return promise;
|
|
13855
13832
|
}
|
|
13856
|
-
// ─── Convenience shortcuts ────────────────────────────────────────────────
|
|
13857
13833
|
success(title, message, opts = {}) {
|
|
13858
13834
|
return this.open({ type: 'success', title, message, ...opts });
|
|
13859
13835
|
}
|
|
@@ -13867,13 +13843,7 @@ class ClxAlertService {
|
|
|
13867
13843
|
return this.open({ type: 'info', title, message, ...opts });
|
|
13868
13844
|
}
|
|
13869
13845
|
confirm(title, message, opts = {}) {
|
|
13870
|
-
return this.open({
|
|
13871
|
-
type: 'confirm',
|
|
13872
|
-
title,
|
|
13873
|
-
message,
|
|
13874
|
-
showCancelButton: true,
|
|
13875
|
-
...opts,
|
|
13876
|
-
});
|
|
13846
|
+
return this.open({ type: 'confirm', title, message, showCancelButton: true, ...opts });
|
|
13877
13847
|
}
|
|
13878
13848
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxAlertService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
13879
13849
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxAlertService, providedIn: 'root' });
|
|
@@ -13881,42 +13851,23 @@ class ClxAlertService {
|
|
|
13881
13851
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxAlertService, decorators: [{
|
|
13882
13852
|
type: Injectable,
|
|
13883
13853
|
args: [{ providedIn: 'root' }]
|
|
13884
|
-
}]
|
|
13854
|
+
}] });
|
|
13885
13855
|
|
|
13886
13856
|
class ClxDrawerService {
|
|
13887
|
-
_overlay;
|
|
13888
|
-
|
|
13889
|
-
|
|
13890
|
-
constructor() {
|
|
13891
|
-
this._overlay = inject(Overlay);
|
|
13892
|
-
this._injector = inject(Injector);
|
|
13893
|
-
this._focusTrapFactory = inject(FocusTrapFactory);
|
|
13894
|
-
}
|
|
13857
|
+
_overlay = inject(ClxNativeOverlayService);
|
|
13858
|
+
_animate = inject(ClxAnimateService);
|
|
13859
|
+
_injector = inject(Injector);
|
|
13895
13860
|
open(
|
|
13896
13861
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13897
13862
|
component, config = {}) {
|
|
13898
|
-
const { hasBackdrop = false, disableClose = false,
|
|
13863
|
+
const { hasBackdrop = false, disableClose = false, size = 'md', data, } = config;
|
|
13899
13864
|
let _resolve;
|
|
13900
13865
|
const _afterClosed = new Promise(res => (_resolve = res));
|
|
13901
|
-
let
|
|
13866
|
+
let _closing = false;
|
|
13902
13867
|
const drawerRef = {
|
|
13903
|
-
close(result) {
|
|
13904
|
-
|
|
13905
|
-
overlayRef.dispose();
|
|
13906
|
-
_resolve(result);
|
|
13907
|
-
},
|
|
13908
|
-
afterClosed() {
|
|
13909
|
-
return _afterClosed;
|
|
13910
|
-
},
|
|
13868
|
+
close(result) { closeViaAnimation(result); },
|
|
13869
|
+
afterClosed() { return _afterClosed; },
|
|
13911
13870
|
};
|
|
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
13871
|
const innerInjector = Injector.create({
|
|
13921
13872
|
parent: this._injector,
|
|
13922
13873
|
providers: [
|
|
@@ -13925,26 +13876,51 @@ class ClxDrawerService {
|
|
|
13925
13876
|
{ provide: CLX_DRAWER_SIZE, useValue: size },
|
|
13926
13877
|
],
|
|
13927
13878
|
});
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13879
|
+
const { compRef, overlayRef } = this._overlay.mount(component, innerInjector, {
|
|
13880
|
+
zIndex: 1000,
|
|
13881
|
+
backdrop: hasBackdrop,
|
|
13882
|
+
backdropClass: 'clx-modal-backdrop',
|
|
13883
|
+
containerStyle: {
|
|
13884
|
+
alignItems: 'flex-start',
|
|
13885
|
+
justifyContent: 'flex-end',
|
|
13886
|
+
padding: '0',
|
|
13887
|
+
},
|
|
13888
|
+
});
|
|
13889
|
+
const panelEl = compRef.location.nativeElement;
|
|
13890
|
+
panelEl.style.height = '100vh';
|
|
13891
|
+
panelEl.style.pointerEvents = 'auto';
|
|
13892
|
+
// Slide in from right
|
|
13893
|
+
this._animate.animate(panelEl, {
|
|
13894
|
+
animation: 'fadeInRight',
|
|
13895
|
+
duration: 300,
|
|
13896
|
+
trigger: 'manual',
|
|
13897
|
+
});
|
|
13898
|
+
const closeViaAnimation = (result) => {
|
|
13899
|
+
if (_closing)
|
|
13900
|
+
return;
|
|
13901
|
+
_closing = true;
|
|
13902
|
+
this._animate.animate(panelEl, {
|
|
13903
|
+
animation: 'fadeOutRight',
|
|
13904
|
+
duration: 300,
|
|
13905
|
+
trigger: 'manual',
|
|
13906
|
+
fillMode: 'forwards',
|
|
13907
|
+
}).then(() => {
|
|
13908
|
+
overlayRef.destroy();
|
|
13909
|
+
_resolve(result);
|
|
13910
|
+
});
|
|
13911
|
+
};
|
|
13912
|
+
if (hasBackdrop && !disableClose && overlayRef.backdrop) {
|
|
13913
|
+
overlayRef.backdrop.addEventListener('click', () => closeViaAnimation());
|
|
13941
13914
|
}
|
|
13942
13915
|
if (!disableClose) {
|
|
13943
|
-
|
|
13944
|
-
|
|
13916
|
+
const onKey = (e) => {
|
|
13917
|
+
if (e.key === 'Escape') {
|
|
13918
|
+
closeViaAnimation();
|
|
13919
|
+
document.removeEventListener('keydown', onKey);
|
|
13920
|
+
}
|
|
13921
|
+
};
|
|
13922
|
+
document.addEventListener('keydown', onKey);
|
|
13945
13923
|
}
|
|
13946
|
-
_focusTrap = this._focusTrapFactory.create(overlayRef.overlayElement);
|
|
13947
|
-
_focusTrap.focusInitialElementWhenReady();
|
|
13948
13924
|
return drawerRef;
|
|
13949
13925
|
}
|
|
13950
13926
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxDrawerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
@@ -13953,47 +13929,16 @@ class ClxDrawerService {
|
|
|
13953
13929
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxDrawerService, decorators: [{
|
|
13954
13930
|
type: Injectable,
|
|
13955
13931
|
args: [{ providedIn: 'root' }]
|
|
13956
|
-
}]
|
|
13932
|
+
}] });
|
|
13957
13933
|
|
|
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
13934
|
class ClxToastService {
|
|
13935
|
+
_appRef = inject(ApplicationRef);
|
|
13969
13936
|
_injector = inject(Injector);
|
|
13970
|
-
|
|
13937
|
+
// Each position has its own container div at z-index 9000 (above modals)
|
|
13971
13938
|
_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
13939
|
show(options) {
|
|
13990
13940
|
const position = options.position ?? TOAST_DEFAULTS.position;
|
|
13991
13941
|
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
13942
|
const entry = {
|
|
13998
13943
|
id: this._uid(),
|
|
13999
13944
|
type: options.type ?? TOAST_DEFAULTS.type,
|
|
@@ -14014,7 +13959,6 @@ class ClxToastService {
|
|
|
14014
13959
|
const list = container.instance.entries();
|
|
14015
13960
|
container.instance.entries.set(isBottom ? [...list, entry] : [entry, ...list]);
|
|
14016
13961
|
}
|
|
14017
|
-
// ─── Convenience shortcuts ─────────────────────────────────────────────────
|
|
14018
13962
|
success(message, opts = {}) {
|
|
14019
13963
|
this.show({ ...opts, type: 'green', message });
|
|
14020
13964
|
}
|
|
@@ -14030,25 +13974,26 @@ class ClxToastService {
|
|
|
14030
13974
|
dismissAll() {
|
|
14031
13975
|
this._containers.forEach(c => c.instance.entries.set([]));
|
|
14032
13976
|
}
|
|
14033
|
-
// ─── Container management ──────────────────────────────────────────────────
|
|
14034
13977
|
_getOrCreateContainer(position) {
|
|
14035
13978
|
const existing = this._containers.get(position);
|
|
14036
13979
|
if (existing)
|
|
14037
13980
|
return existing;
|
|
14038
|
-
|
|
14039
|
-
const
|
|
14040
|
-
|
|
14041
|
-
|
|
14042
|
-
|
|
14043
|
-
|
|
14044
|
-
|
|
14045
|
-
|
|
14046
|
-
|
|
14047
|
-
|
|
13981
|
+
// Dedicated div — completely separate from modal's DOM tree
|
|
13982
|
+
const el = document.createElement('div');
|
|
13983
|
+
el.style.cssText = 'position:fixed;inset:0;z-index:9000;pointer-events:none;';
|
|
13984
|
+
document.body.appendChild(el);
|
|
13985
|
+
const ref = createComponent(ClxToastContainerComponent, {
|
|
13986
|
+
environmentInjector: this._appRef.injector,
|
|
13987
|
+
elementInjector: this._injector,
|
|
13988
|
+
});
|
|
13989
|
+
ref.setInput('position', position);
|
|
13990
|
+
this._appRef.attachView(ref.hostView);
|
|
13991
|
+
const compEl = ref.location.nativeElement;
|
|
13992
|
+
el.appendChild(compEl);
|
|
13993
|
+
const entry = { el, instance: ref.instance };
|
|
14048
13994
|
this._containers.set(position, entry);
|
|
14049
13995
|
return entry;
|
|
14050
13996
|
}
|
|
14051
|
-
// ─── Utilities ─────────────────────────────────────────────────────────────
|
|
14052
13997
|
_uid() {
|
|
14053
13998
|
return `toast-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
14054
13999
|
}
|