ngx-kit 1.0.0 → 2.0.1
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/dialog/README.md +169 -0
- package/fesm2022/{ngx-input-angle-selector.mjs → ngx-kit-angle-selector.mjs} +16 -16
- package/fesm2022/ngx-kit-angle-selector.mjs.map +1 -0
- package/fesm2022/{ngx-input-box-shadow.mjs → ngx-kit-box-shadow.mjs} +10 -10
- package/fesm2022/ngx-kit-box-shadow.mjs.map +1 -0
- package/fesm2022/{ngx-input-color-picker.mjs → ngx-kit-color-picker.mjs} +30 -14
- package/fesm2022/ngx-kit-color-picker.mjs.map +1 -0
- package/fesm2022/ngx-kit-date-picker.mjs +2280 -0
- package/fesm2022/ngx-kit-date-picker.mjs.map +1 -0
- package/fesm2022/ngx-kit-dialog.mjs +378 -0
- package/fesm2022/ngx-kit-dialog.mjs.map +1 -0
- package/fesm2022/{ngx-input-gradient-picker.mjs → ngx-kit-gradient-picker.mjs} +11 -11
- package/fesm2022/ngx-kit-gradient-picker.mjs.map +1 -0
- package/fesm2022/ngx-kit-menu.mjs +229 -0
- package/fesm2022/ngx-kit-menu.mjs.map +1 -0
- package/fesm2022/ngx-kit-notify.mjs +292 -0
- package/fesm2022/ngx-kit-notify.mjs.map +1 -0
- package/fesm2022/{ngx-input-shared.mjs → ngx-kit-shared.mjs} +267 -162
- package/fesm2022/ngx-kit-shared.mjs.map +1 -0
- package/fesm2022/{ngx-input.mjs → ngx-kit.mjs} +1 -1
- package/fesm2022/ngx-kit.mjs.map +1 -0
- package/package.json +31 -15
- package/styles/all.css +22 -0
- package/styles/overlay.css +22 -0
- package/types/{ngx-input-angle-selector.d.ts → ngx-kit-angle-selector.d.ts} +6 -5
- package/types/{ngx-input-box-shadow.d.ts → ngx-kit-box-shadow.d.ts} +7 -7
- package/types/{ngx-input-color-picker.d.ts → ngx-kit-color-picker.d.ts} +7 -7
- package/types/ngx-kit-date-picker.d.ts +294 -0
- package/types/ngx-kit-dialog.d.ts +139 -0
- package/types/{ngx-input-gradient-picker.d.ts → ngx-kit-gradient-picker.d.ts} +7 -7
- package/types/ngx-kit-menu.d.ts +69 -0
- package/types/ngx-kit-notify.d.ts +60 -0
- package/types/{ngx-input-shared.d.ts → ngx-kit-shared.d.ts} +87 -40
- package/fesm2022/ngx-input-angle-selector.mjs.map +0 -1
- package/fesm2022/ngx-input-box-shadow.mjs.map +0 -1
- package/fesm2022/ngx-input-color-picker.mjs.map +0 -1
- package/fesm2022/ngx-input-gradient-picker.mjs.map +0 -1
- package/fesm2022/ngx-input-shared.mjs.map +0 -1
- package/fesm2022/ngx-input.mjs.map +0 -1
- /package/types/{ngx-input.d.ts → ngx-kit.d.ts} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i1 from '@angular/common';
|
|
2
2
|
import { CommonModule, isPlatformBrowser, DOCUMENT } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { EventEmitter, forwardRef, HostListener, ViewChild, Output, Input, ChangeDetectionStrategy, Component, PLATFORM_ID, Inject, Injectable, inject } from '@angular/core';
|
|
4
|
+
import { EventEmitter, forwardRef, HostListener, ViewChild, Output, Input, ChangeDetectionStrategy, Component, InjectionToken, PLATFORM_ID, Inject, Injectable, inject } from '@angular/core';
|
|
5
5
|
import { NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl, Validators } from '@angular/forms';
|
|
6
6
|
|
|
7
7
|
function getOffsetPosition(evt, parent) {
|
|
@@ -648,6 +648,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
648
648
|
args: ['document:touchend', ['$event']]
|
|
649
649
|
}] } });
|
|
650
650
|
|
|
651
|
+
const WINDOW = new InjectionToken('WINDOW', {
|
|
652
|
+
factory: () => (typeof window !== 'undefined' ? window : null),
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
function randomStrnig(extraLength = 4, useNumeric = false) {
|
|
656
|
+
const len = Math.max(0, Math.floor(extraLength));
|
|
657
|
+
if (len === 0)
|
|
658
|
+
return '';
|
|
659
|
+
let charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
660
|
+
if (useNumeric) {
|
|
661
|
+
charset += '0123456789';
|
|
662
|
+
}
|
|
663
|
+
const cryptoObj = typeof globalThis !== 'undefined'
|
|
664
|
+
? globalThis.crypto
|
|
665
|
+
: undefined;
|
|
666
|
+
const out = new Array(len);
|
|
667
|
+
if (cryptoObj?.getRandomValues) {
|
|
668
|
+
const bytes = new Uint8Array(len);
|
|
669
|
+
cryptoObj.getRandomValues(bytes);
|
|
670
|
+
for (let i = 0; i < len; i++) {
|
|
671
|
+
out[i] = charset[bytes[i] % charset.length];
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
for (let i = 0; i < len; i++) {
|
|
676
|
+
out[i] = charset[Math.floor(Math.random() * charset.length)];
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
return `${Date.now().toString(36)}-${out.join('')}`;
|
|
680
|
+
}
|
|
681
|
+
|
|
651
682
|
class BrowserService {
|
|
652
683
|
platformId;
|
|
653
684
|
constructor(platformId) {
|
|
@@ -674,14 +705,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
674
705
|
args: [PLATFORM_ID]
|
|
675
706
|
}] }] });
|
|
676
707
|
|
|
677
|
-
class
|
|
678
|
-
componentRef;
|
|
708
|
+
class OverlayRef {
|
|
679
709
|
dialogEl;
|
|
680
710
|
teardownFn;
|
|
681
|
-
|
|
682
|
-
|
|
711
|
+
componentRef;
|
|
712
|
+
templateRef;
|
|
713
|
+
constructor(dialogEl, teardownFn, componentRef, templateRef) {
|
|
683
714
|
this.dialogEl = dialogEl;
|
|
684
715
|
this.teardownFn = teardownFn;
|
|
716
|
+
this.componentRef = componentRef;
|
|
717
|
+
this.templateRef = templateRef;
|
|
685
718
|
}
|
|
686
719
|
close() {
|
|
687
720
|
this.teardownFn();
|
|
@@ -691,128 +724,236 @@ class DialogOverlayRef {
|
|
|
691
724
|
}
|
|
692
725
|
}
|
|
693
726
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
globalResizeListener;
|
|
702
|
-
globalClickListener;
|
|
727
|
+
const FOCUSABLE_SELECTOR = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
728
|
+
const DIALOG_OVERLAY_CLASSNAME = 'ngx-ui-overlay';
|
|
729
|
+
class OverlayService {
|
|
730
|
+
overlayStacks = [];
|
|
731
|
+
zIndexCounter = 1000;
|
|
732
|
+
listenersAttached = false;
|
|
733
|
+
resizeRafPending = false;
|
|
703
734
|
doc = inject(DOCUMENT);
|
|
704
|
-
|
|
705
|
-
this.globalKeyDownListener = (e) => {
|
|
706
|
-
if (e.key === 'Escape') {
|
|
707
|
-
const lastDialog = this.getLastDialog();
|
|
708
|
-
if (lastDialog) {
|
|
709
|
-
lastDialog.cleanup();
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
};
|
|
713
|
-
this.globalResizeListener = () => {
|
|
714
|
-
this.repositionAll();
|
|
715
|
-
};
|
|
716
|
-
this.globalClickListener = (e) => {
|
|
717
|
-
this.handleClickOnBackdrop(e);
|
|
718
|
-
};
|
|
719
|
-
}
|
|
735
|
+
abortController = new AbortController();
|
|
720
736
|
ngOnDestroy() {
|
|
721
737
|
this.closeAll();
|
|
722
|
-
|
|
723
|
-
handleGlobalListeners() {
|
|
724
|
-
// مطمئن شویم لیسنرها فقط یک بار اضافه شدهاند
|
|
725
|
-
if (!this.globalKeyDownAdded) {
|
|
726
|
-
this.doc.addEventListener('keydown', this.globalKeyDownListener);
|
|
727
|
-
this.globalKeyDownAdded = true;
|
|
728
|
-
}
|
|
729
|
-
if (!this.globalResizeAdded) {
|
|
730
|
-
window.addEventListener('resize', this.globalResizeListener);
|
|
731
|
-
this.globalResizeAdded = true;
|
|
732
|
-
}
|
|
733
|
-
if (!this.globalClickAdded) {
|
|
734
|
-
this.doc.addEventListener('click', this.globalClickListener);
|
|
735
|
-
this.globalClickAdded = true;
|
|
736
|
-
}
|
|
738
|
+
this.abortController.abort();
|
|
737
739
|
}
|
|
738
740
|
open(options) {
|
|
739
|
-
const { anchor, component, viewContainerRef, configure, onClosed } = options;
|
|
741
|
+
const { anchor, point, component, viewContainerRef, configure, onClosed, placement, alignment, margin, } = options;
|
|
740
742
|
if (!viewContainerRef) {
|
|
741
|
-
throw new Error('ViewContainerRef is required to render
|
|
742
|
-
}
|
|
743
|
-
this.
|
|
744
|
-
const
|
|
745
|
-
const dialogElement = this.doc.createElement('dialog');
|
|
746
|
-
dialogElement.style.position = 'absolute';
|
|
747
|
-
dialogElement.style.outline = 'none';
|
|
748
|
-
dialogElement.style.padding = '0';
|
|
749
|
-
dialogElement.style.margin = '0';
|
|
750
|
-
dialogElement.style.border = 'none';
|
|
751
|
-
dialogElement.style.background = 'transparent';
|
|
752
|
-
dialogElement.style.maxWidth = '100vw';
|
|
753
|
-
dialogElement.style.maxHeight = '100vh';
|
|
754
|
-
dialogElement.style.overflow = 'visible';
|
|
755
|
-
dialogElement.style.zIndex = `${1000 + this.openDialogs.size}`;
|
|
756
|
-
this.doc.body.appendChild(dialogElement);
|
|
743
|
+
throw new Error('ViewContainerRef is required to render overlay content.');
|
|
744
|
+
}
|
|
745
|
+
this.attachGlobalListeners();
|
|
746
|
+
const element = this.createDialogElement();
|
|
757
747
|
const componentRef = viewContainerRef.createComponent(component);
|
|
758
748
|
if (componentRef.location.nativeElement) {
|
|
759
|
-
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
this.
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
onClosed?.();
|
|
749
|
+
element.appendChild(componentRef.location.nativeElement);
|
|
750
|
+
}
|
|
751
|
+
const instance = {
|
|
752
|
+
element,
|
|
753
|
+
anchor,
|
|
754
|
+
point,
|
|
755
|
+
placementConfig: this.resolvePlacementConfig(placement, alignment, margin),
|
|
756
|
+
componentRef,
|
|
757
|
+
onClosed,
|
|
758
|
+
rafId: null,
|
|
759
|
+
focusTimeoutId: null,
|
|
760
|
+
cleanup: () => { },
|
|
772
761
|
};
|
|
762
|
+
instance.cleanup = () => this.destroyInstance(instance);
|
|
763
|
+
this.overlayStacks.push(instance);
|
|
764
|
+
element.showModal();
|
|
765
|
+
const ref = new OverlayRef(element, instance.cleanup, componentRef);
|
|
766
|
+
configure?.(componentRef.instance, ref);
|
|
767
|
+
this.scheduleInitialLayout(instance);
|
|
768
|
+
return ref;
|
|
769
|
+
}
|
|
770
|
+
openTemplate(options) {
|
|
771
|
+
const { anchor, point, template, appRef, configure, onClosed, placement, alignment, margin } = options;
|
|
772
|
+
this.attachGlobalListeners();
|
|
773
|
+
const element = this.createDialogElement();
|
|
774
|
+
const view = template.createEmbeddedView({});
|
|
775
|
+
appRef.attachView(view);
|
|
776
|
+
element.append(...view.rootNodes);
|
|
773
777
|
const instance = {
|
|
774
|
-
|
|
778
|
+
element,
|
|
775
779
|
anchor,
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
+
point,
|
|
781
|
+
placementConfig: this.resolvePlacementConfig(placement, alignment, margin),
|
|
782
|
+
embeddedView: view,
|
|
783
|
+
appRef,
|
|
784
|
+
onClosed,
|
|
785
|
+
rafId: null,
|
|
786
|
+
focusTimeoutId: null,
|
|
787
|
+
cleanup: () => { },
|
|
780
788
|
};
|
|
781
|
-
this.
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
789
|
+
instance.cleanup = () => this.destroyInstance(instance);
|
|
790
|
+
this.overlayStacks.push(instance);
|
|
791
|
+
element.showModal();
|
|
792
|
+
const ref = new OverlayRef(element, instance.cleanup, undefined, template);
|
|
793
|
+
configure?.(instance, ref);
|
|
794
|
+
this.scheduleInitialLayout(instance);
|
|
795
|
+
return ref;
|
|
796
|
+
}
|
|
797
|
+
closeAll() {
|
|
798
|
+
// اسنپشات میگیریم چون cleanup حین اجرا آرایهی اصلی رو تغییر میده
|
|
799
|
+
[...this.overlayStacks].forEach((instance) => instance.cleanup());
|
|
800
|
+
}
|
|
801
|
+
// ---------------------------------------------------------------------
|
|
802
|
+
// lifecycle
|
|
803
|
+
// ---------------------------------------------------------------------
|
|
804
|
+
resolvePlacementConfig(placement, alignment, margin) {
|
|
805
|
+
return {
|
|
806
|
+
placement: placement ?? 'auto',
|
|
807
|
+
alignment: alignment ?? 'start',
|
|
808
|
+
margin: margin ?? 8,
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
createDialogElement() {
|
|
812
|
+
const element = this.doc.createElement('dialog');
|
|
813
|
+
element.className = DIALOG_OVERLAY_CLASSNAME;
|
|
814
|
+
const style = element.style;
|
|
815
|
+
style.position = 'absolute';
|
|
816
|
+
style.outline = 'none';
|
|
817
|
+
style.padding = '0';
|
|
818
|
+
style.margin = '0';
|
|
819
|
+
style.border = 'none';
|
|
820
|
+
style.background = 'transparent';
|
|
821
|
+
style.maxWidth = '100vw';
|
|
822
|
+
style.maxHeight = '100vh';
|
|
823
|
+
style.overflow = 'visible';
|
|
824
|
+
style.visibility = 'hidden';
|
|
825
|
+
// شمارندهی صعودی مستقل از تعداد فعلی دیالوگهای باز؛ در نسخهی قبلی
|
|
826
|
+
// با استفاده از openDialogs.size محاسبه میشد که بعد از بستن دیالوگها
|
|
827
|
+
// میتونست باعث تکرار zIndex بین دو دیالوگ بشه.
|
|
828
|
+
style.zIndex = `${++this.zIndexCounter}`;
|
|
829
|
+
this.doc.body.appendChild(element);
|
|
830
|
+
return element;
|
|
831
|
+
}
|
|
832
|
+
scheduleInitialLayout(instance) {
|
|
833
|
+
instance.rafId = requestAnimationFrame(() => {
|
|
834
|
+
instance.rafId = null;
|
|
788
835
|
this.positionDialog(instance);
|
|
789
836
|
});
|
|
790
|
-
setTimeout(() => {
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
}
|
|
837
|
+
instance.focusTimeoutId = setTimeout(() => {
|
|
838
|
+
instance.focusTimeoutId = null;
|
|
839
|
+
const focusable = instance.element.querySelector(FOCUSABLE_SELECTOR);
|
|
840
|
+
focusable?.focus();
|
|
795
841
|
}, 0);
|
|
796
|
-
const ref = new DialogOverlayRef(componentRef, dialogElement, cleanup);
|
|
797
|
-
return ref;
|
|
798
842
|
}
|
|
843
|
+
destroyInstance(instance) {
|
|
844
|
+
const index = this.overlayStacks.indexOf(instance);
|
|
845
|
+
if (index === -1)
|
|
846
|
+
return; // جلوگیری از پاکسازی دوباره
|
|
847
|
+
this.overlayStacks.splice(index, 1);
|
|
848
|
+
// لغو کارهای زمانبندیشدهای که هنوز اجرا نشدن (نشتی حافظه در نسخهی قبلی)
|
|
849
|
+
if (instance.rafId !== null)
|
|
850
|
+
cancelAnimationFrame(instance.rafId);
|
|
851
|
+
if (instance.focusTimeoutId !== null)
|
|
852
|
+
clearTimeout(instance.focusTimeoutId);
|
|
853
|
+
if (instance.componentRef) {
|
|
854
|
+
instance.componentRef.location.nativeElement?.remove();
|
|
855
|
+
instance.componentRef.destroy();
|
|
856
|
+
}
|
|
857
|
+
if (instance.embeddedView && instance.appRef) {
|
|
858
|
+
instance.appRef.detachView(instance.embeddedView);
|
|
859
|
+
instance.embeddedView.destroy();
|
|
860
|
+
}
|
|
861
|
+
instance.element.remove();
|
|
862
|
+
instance.onClosed?.();
|
|
863
|
+
}
|
|
864
|
+
// ---------------------------------------------------------------------
|
|
865
|
+
// global listeners (فقط یکبار در کل عمر سرویس attach میشن)
|
|
866
|
+
// ---------------------------------------------------------------------
|
|
867
|
+
attachGlobalListeners() {
|
|
868
|
+
if (this.listenersAttached)
|
|
869
|
+
return;
|
|
870
|
+
this.listenersAttached = true;
|
|
871
|
+
const { signal } = this.abortController;
|
|
872
|
+
this.doc.addEventListener('keydown', this.onGlobalKeyDown, { signal });
|
|
873
|
+
window.addEventListener('resize', this.onGlobalResize, { signal, passive: true });
|
|
874
|
+
this.doc.addEventListener('click', this.onGlobalPointerEvent, { signal });
|
|
875
|
+
this.doc.addEventListener('contextmenu', this.onGlobalPointerEvent, { signal });
|
|
876
|
+
}
|
|
877
|
+
onGlobalKeyDown = (e) => {
|
|
878
|
+
if (e.key !== 'Escape')
|
|
879
|
+
return;
|
|
880
|
+
this.getLastDialog()?.cleanup();
|
|
881
|
+
};
|
|
882
|
+
onGlobalResize = () => {
|
|
883
|
+
// چند رویداد resize پشتسرهم فقط یک reposition واقعی اجرا میکنن
|
|
884
|
+
if (this.resizeRafPending)
|
|
885
|
+
return;
|
|
886
|
+
this.resizeRafPending = true;
|
|
887
|
+
requestAnimationFrame(() => {
|
|
888
|
+
this.resizeRafPending = false;
|
|
889
|
+
this.repositionAll();
|
|
890
|
+
});
|
|
891
|
+
};
|
|
892
|
+
onGlobalPointerEvent = (e) => {
|
|
893
|
+
this.handleClickOnBackdrop(e);
|
|
894
|
+
};
|
|
895
|
+
handleClickOnBackdrop(event) {
|
|
896
|
+
const lastDialog = this.getLastDialog();
|
|
897
|
+
if (!lastDialog || !lastDialog.element.open)
|
|
898
|
+
return;
|
|
899
|
+
// کلیک باید دقیقاً روی خودِ دیالوگ (بکدراپ) باشه، نه محتوای داخلش
|
|
900
|
+
if (event.target !== lastDialog.element)
|
|
901
|
+
return;
|
|
902
|
+
// اگه فرم داخل دیالوگه، با کلیک بیرون بسته نشه
|
|
903
|
+
if (lastDialog.element.querySelector('form'))
|
|
904
|
+
return;
|
|
905
|
+
const rect = lastDialog.element.getBoundingClientRect();
|
|
906
|
+
const clickWasInsideDialog = rect.top <= event.clientY &&
|
|
907
|
+
event.clientY <= rect.bottom &&
|
|
908
|
+
rect.left <= event.clientX &&
|
|
909
|
+
event.clientX <= rect.right;
|
|
910
|
+
const anchRect = lastDialog.anchor.getBoundingClientRect();
|
|
911
|
+
const clickWasInsideAnchor = anchRect.top <= event.clientY &&
|
|
912
|
+
event.clientY <= anchRect.bottom &&
|
|
913
|
+
anchRect.left <= event.clientX &&
|
|
914
|
+
event.clientX <= anchRect.right;
|
|
915
|
+
if (!clickWasInsideDialog) {
|
|
916
|
+
if (event.type == 'contextmenu' && lastDialog.point && clickWasInsideAnchor) {
|
|
917
|
+
event.preventDefault();
|
|
918
|
+
lastDialog.point = {
|
|
919
|
+
x: event.clientX,
|
|
920
|
+
y: event.clientY,
|
|
921
|
+
};
|
|
922
|
+
this.positionDialog(lastDialog);
|
|
923
|
+
}
|
|
924
|
+
else {
|
|
925
|
+
lastDialog.cleanup();
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
getLastDialog() {
|
|
930
|
+
return this.overlayStacks[this.overlayStacks.length - 1];
|
|
931
|
+
}
|
|
932
|
+
// ---------------------------------------------------------------------
|
|
933
|
+
// positioning
|
|
934
|
+
// ---------------------------------------------------------------------
|
|
799
935
|
repositionAll() {
|
|
800
|
-
|
|
801
|
-
if (instance.
|
|
936
|
+
this.overlayStacks.forEach((instance) => {
|
|
937
|
+
if (instance.element.isConnected) {
|
|
802
938
|
this.positionDialog(instance);
|
|
803
939
|
}
|
|
804
940
|
});
|
|
805
941
|
}
|
|
806
|
-
positionDialog(
|
|
807
|
-
const anchor =
|
|
808
|
-
const
|
|
809
|
-
|
|
810
|
-
if (!anchor || !dialog)
|
|
942
|
+
positionDialog(instance) {
|
|
943
|
+
const { anchor, element: dialog, placementConfig, point } = instance;
|
|
944
|
+
const { placement, alignment, margin } = placementConfig;
|
|
945
|
+
if (!dialog.isConnected)
|
|
811
946
|
return;
|
|
812
|
-
|
|
947
|
+
let anchorRect;
|
|
948
|
+
if (point) {
|
|
949
|
+
anchorRect = new DOMRect(point.x, point.y, 0, 0);
|
|
950
|
+
}
|
|
951
|
+
else {
|
|
952
|
+
anchorRect = anchor.getBoundingClientRect();
|
|
953
|
+
}
|
|
813
954
|
const dialogRect = dialog.getBoundingClientRect();
|
|
814
|
-
const vw = window.innerWidth;
|
|
815
|
-
const vh = window.innerHeight;
|
|
955
|
+
const vw = Math.min(document.body.clientWidth, window.innerWidth);
|
|
956
|
+
const vh = Math.min(document.body.clientHeight, window.innerHeight);
|
|
816
957
|
const isRTL = getComputedStyle(this.doc.documentElement).direction === 'rtl';
|
|
817
958
|
let top = 0;
|
|
818
959
|
let left = 'auto';
|
|
@@ -820,8 +961,8 @@ class DialogService {
|
|
|
820
961
|
const spaceBelow = vh - anchorRect.bottom;
|
|
821
962
|
const spaceAbove = anchorRect.top;
|
|
822
963
|
let verticalPos = 'above';
|
|
823
|
-
|
|
824
|
-
|
|
964
|
+
if (placement === 'bottom' ||
|
|
965
|
+
(placement === 'auto' && spaceBelow >= dialogRect.height + margin)) {
|
|
825
966
|
top = anchorRect.bottom + margin;
|
|
826
967
|
verticalPos = 'above';
|
|
827
968
|
if (top + dialogRect.height > vh - margin) {
|
|
@@ -837,13 +978,11 @@ class DialogService {
|
|
|
837
978
|
verticalPos = 'above';
|
|
838
979
|
}
|
|
839
980
|
}
|
|
840
|
-
// horizontal position
|
|
841
981
|
if (alignment === 'center') {
|
|
842
982
|
left = anchorRect.left + anchorRect.width / 2 - dialogRect.width / 2;
|
|
843
983
|
}
|
|
844
984
|
else if (alignment === 'start') {
|
|
845
985
|
if (isRTL) {
|
|
846
|
-
left = 'auto';
|
|
847
986
|
right = vw - anchorRect.right;
|
|
848
987
|
}
|
|
849
988
|
else {
|
|
@@ -851,65 +990,31 @@ class DialogService {
|
|
|
851
990
|
}
|
|
852
991
|
}
|
|
853
992
|
else {
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
}
|
|
863
|
-
dialog.
|
|
864
|
-
dialog.style.
|
|
865
|
-
dialog.style.
|
|
866
|
-
dialog.style.
|
|
867
|
-
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
if (this.openDialogs.size === 0)
|
|
871
|
-
return undefined;
|
|
872
|
-
const lastKey = Array.from(this.openDialogs.keys()).pop();
|
|
873
|
-
return lastKey ? this.openDialogs.get(lastKey) : undefined;
|
|
874
|
-
}
|
|
875
|
-
closeAll() {
|
|
876
|
-
const ids = Array.from(this.openDialogs.keys());
|
|
877
|
-
ids.forEach((id) => {
|
|
878
|
-
const instance = this.openDialogs.get(id);
|
|
879
|
-
instance?.cleanup();
|
|
880
|
-
});
|
|
881
|
-
}
|
|
882
|
-
handleClickOnBackdrop(event) {
|
|
883
|
-
const target = event.target;
|
|
884
|
-
const lastDialog = this.getLastDialog();
|
|
885
|
-
if (!lastDialog)
|
|
886
|
-
return;
|
|
887
|
-
// The click target _must_ be the dialog element itself, and not elements underneath or inside.
|
|
888
|
-
if (target !== lastDialog.element || !lastDialog.element?.open)
|
|
889
|
-
return;
|
|
890
|
-
// If the dialog contains a form, do not close the dialog when clicking outside of the dialog
|
|
891
|
-
if (lastDialog.element.querySelector('form'))
|
|
892
|
-
return;
|
|
893
|
-
const rect = lastDialog.element.getBoundingClientRect();
|
|
894
|
-
const clickWasInsideDialog = rect.top <= event.clientY &&
|
|
895
|
-
event.clientY <= rect.top + rect.height &&
|
|
896
|
-
rect.left <= event.clientX &&
|
|
897
|
-
event.clientX <= rect.left + rect.width;
|
|
898
|
-
if (!clickWasInsideDialog) {
|
|
899
|
-
lastDialog.cleanup();
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: DialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
903
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: DialogService, providedIn: 'root' });
|
|
993
|
+
left = isRTL ? anchorRect.left : anchorRect.right; //- dialogRect.width;
|
|
994
|
+
}
|
|
995
|
+
if (left !== 'auto') {
|
|
996
|
+
left = Math.min(Math.max(left, margin), vw - dialogRect.width - margin);
|
|
997
|
+
}
|
|
998
|
+
dialog.className = `${DIALOG_OVERLAY_CLASSNAME} tips-${verticalPos}`;
|
|
999
|
+
dialog.style.top = `${top + window.scrollY}px`;
|
|
1000
|
+
dialog.style.left = left !== 'auto' ? `${left + window.scrollX}px` : 'auto';
|
|
1001
|
+
dialog.style.right = right !== 'auto' ? `${right + window.scrollX}px` : 'auto';
|
|
1002
|
+
dialog.style.transformOrigin = verticalPos == 'above' ? 'left top' : 'left bottom';
|
|
1003
|
+
// dialog.style.transform = 'none';
|
|
1004
|
+
dialog.style.visibility = 'visible';
|
|
1005
|
+
dialog.style.animation = 'menu-enter 120ms cubic-bezier(0, 0, 0.2, 1)';
|
|
1006
|
+
}
|
|
1007
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: OverlayService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1008
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: OverlayService, providedIn: 'root' });
|
|
904
1009
|
}
|
|
905
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type:
|
|
1010
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: OverlayService, decorators: [{
|
|
906
1011
|
type: Injectable,
|
|
907
1012
|
args: [{ providedIn: 'root' }]
|
|
908
|
-
}]
|
|
1013
|
+
}] });
|
|
909
1014
|
|
|
910
1015
|
/**
|
|
911
1016
|
* Generated bundle index. Do not edit.
|
|
912
1017
|
*/
|
|
913
1018
|
|
|
914
|
-
export { BrowserService,
|
|
915
|
-
//# sourceMappingURL=ngx-
|
|
1019
|
+
export { BrowserService, DIALOG_OVERLAY_CLASSNAME, FOCUSABLE_SELECTOR, OverlayRef, OverlayService, RangeSliderComponent, SaturationComponent, SliderComponent, ValueModel, WINDOW, getOffsetPosition, randomStrnig };
|
|
1020
|
+
//# sourceMappingURL=ngx-kit-shared.mjs.map
|