@shival99/z-ui 2.0.52 → 2.0.54

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.
Files changed (31) hide show
  1. package/fesm2022/shival99-z-ui-components-z-autocomplete.mjs +1 -1
  2. package/fesm2022/shival99-z-ui-components-z-autocomplete.mjs.map +1 -1
  3. package/fesm2022/shival99-z-ui-components-z-calendar.mjs +1 -1
  4. package/fesm2022/shival99-z-ui-components-z-calendar.mjs.map +1 -1
  5. package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs +1 -1
  6. package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs.map +1 -1
  7. package/fesm2022/shival99-z-ui-components-z-editor.mjs +1 -1
  8. package/fesm2022/shival99-z-ui-components-z-editor.mjs.map +1 -1
  9. package/fesm2022/shival99-z-ui-components-z-filter.mjs +1 -1
  10. package/fesm2022/shival99-z-ui-components-z-filter.mjs.map +1 -1
  11. package/fesm2022/shival99-z-ui-components-z-input.mjs +1 -1
  12. package/fesm2022/shival99-z-ui-components-z-input.mjs.map +1 -1
  13. package/fesm2022/shival99-z-ui-components-z-media-player.mjs +1 -1
  14. package/fesm2022/shival99-z-ui-components-z-media-player.mjs.map +1 -1
  15. package/fesm2022/shival99-z-ui-components-z-menu.mjs +2 -2
  16. package/fesm2022/shival99-z-ui-components-z-menu.mjs.map +1 -1
  17. package/fesm2022/shival99-z-ui-components-z-popover.mjs +171 -41
  18. package/fesm2022/shival99-z-ui-components-z-popover.mjs.map +1 -1
  19. package/fesm2022/shival99-z-ui-components-z-select.mjs +22 -13
  20. package/fesm2022/shival99-z-ui-components-z-select.mjs.map +1 -1
  21. package/fesm2022/shival99-z-ui-components-z-table.mjs +722 -19
  22. package/fesm2022/shival99-z-ui-components-z-table.mjs.map +1 -1
  23. package/fesm2022/shival99-z-ui-components-z-tabs.mjs +1 -1
  24. package/fesm2022/shival99-z-ui-components-z-tabs.mjs.map +1 -1
  25. package/fesm2022/shival99-z-ui-i18n.mjs +12 -0
  26. package/fesm2022/shival99-z-ui-i18n.mjs.map +1 -1
  27. package/package.json +1 -1
  28. package/types/shival99-z-ui-components-z-modal.d.ts +1 -1
  29. package/types/shival99-z-ui-components-z-popover.d.ts +21 -3
  30. package/types/shival99-z-ui-components-z-select.d.ts +1 -0
  31. package/types/shival99-z-ui-components-z-table.d.ts +91 -4
@@ -6,7 +6,7 @@ import { signal, computed, ChangeDetectionStrategy, Component, inject, Renderer2
6
6
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
7
7
  import { ZOverlayContainerService } from '@shival99/z-ui/services';
8
8
  import { zMergeClasses, zIsMobileViewport, zTransform } from '@shival99/z-ui/utils';
9
- import { Subject, switchMap, of, timer, map, filter, fromEvent, throttleTime } from 'rxjs';
9
+ import { Subject, switchMap, of, timer, map, filter } from 'rxjs';
10
10
  import { cva } from 'class-variance-authority';
11
11
 
12
12
  const zPopoverVariants = cva([
@@ -194,11 +194,11 @@ function getPopoverOverlaySize(widthConfig = {}) {
194
194
  function getPopoverRenderPosition(position, _mobile = isMobilePopoverViewport()) {
195
195
  return position;
196
196
  }
197
- function getMobilePopoverFallbackPositions(position) {
198
- return getPopoverFallbackPositions(position, 0).map(pos => ({
197
+ function getMobilePopoverFallbackPositions(position, offset) {
198
+ return getPopoverFallbackPositions(position, offset).map(pos => ({
199
199
  ...pos,
200
- offsetX: 0,
201
- offsetY: 0,
200
+ offsetX: pos.offsetX ?? 0,
201
+ offsetY: pos.offsetY ?? 0,
202
202
  }));
203
203
  }
204
204
  function clampPopoverPosition(value, min, max) {
@@ -384,7 +384,7 @@ function getPopoverFallbackPositions(position, offset) {
384
384
  function createPopoverPositionStrategy(overlayPositionBuilder, origin, position, offset) {
385
385
  const mobile = isMobilePopoverViewport();
386
386
  const positions = mobile
387
- ? getMobilePopoverFallbackPositions(position)
387
+ ? getMobilePopoverFallbackPositions(position, offset)
388
388
  : getPopoverFallbackPositions(position, offset);
389
389
  return overlayPositionBuilder
390
390
  .flexibleConnectedTo(origin)
@@ -463,6 +463,7 @@ class ZPopoverComponent {
463
463
  zScrollClose = input(false, { ...(ngDevMode ? { debugName: "zScrollClose" } : {}), transform: zTransform });
464
464
  zSticky = input(false, { ...(ngDevMode ? { debugName: "zSticky" } : {}), transform: zTransform });
465
465
  zShowArrow = input(false, { ...(ngDevMode ? { debugName: "zShowArrow" } : {}), transform: zTransform });
466
+ zKeyboardSafe = input(false, { ...(ngDevMode ? { debugName: "zKeyboardSafe" } : {}), transform: zTransform });
466
467
  _overlayRef = null;
467
468
  _componentRef = null;
468
469
  _delaySubject = new Subject();
@@ -472,7 +473,9 @@ class ZPopoverComponent {
472
473
  _viewportResizeSubscription = null;
473
474
  _resizeObserver = null;
474
475
  _hideTimeout = null;
476
+ _viewportResizeTimeouts = [];
475
477
  _positionFrame = null;
478
+ _viewportSettlingUntil = 0;
476
479
  _isVisible = signal(false, ...(ngDevMode ? [{ debugName: "_isVisible" }] : []));
477
480
  ngOnInit() {
478
481
  if (!isPlatformBrowser(this._platformId)) {
@@ -542,7 +545,7 @@ class ZPopoverComponent {
542
545
  if (!this._isVisible()) {
543
546
  return;
544
547
  }
545
- this._updatePositionNow();
548
+ this._schedulePositionUpdate();
546
549
  }
547
550
  _createOverlay() {
548
551
  const positionStrategy = createPopoverPositionStrategy(this._overlayPositionBuilder, this._trigger(), this.zPosition(), this.zOffset());
@@ -557,7 +560,7 @@ class ZPopoverComponent {
557
560
  if (this.zScrollClose()) {
558
561
  return this._overlay.scrollStrategies.close();
559
562
  }
560
- if (isMobilePopoverViewport() && this.zSticky()) {
563
+ if (isMobilePopoverViewport() && (this.zSticky() || this.zKeyboardSafe())) {
561
564
  return this._overlay.scrollStrategies.noop();
562
565
  }
563
566
  return this._overlay.scrollStrategies.reposition({ scrollThrottle: 10, autoClose: false });
@@ -569,6 +572,8 @@ class ZPopoverComponent {
569
572
  this._scrollSubscription = null;
570
573
  this._viewportResizeSubscription?.unsubscribe();
571
574
  this._viewportResizeSubscription = null;
575
+ this._clearViewportResizeTimeout();
576
+ this._viewportSettlingUntil = 0;
572
577
  this._resizeObserver?.disconnect();
573
578
  this._resizeObserver = null;
574
579
  this._cancelScheduledPositionUpdate();
@@ -647,6 +652,11 @@ class ZPopoverComponent {
647
652
  if (ticking) {
648
653
  return;
649
654
  }
655
+ if (this._shouldDeferForMobileKeyboard()) {
656
+ this._markViewportSettling();
657
+ this._scheduleSettledPositionUpdate();
658
+ return;
659
+ }
650
660
  ticking = true;
651
661
  requestAnimationFrame(() => {
652
662
  if (this.zSticky() && !this._isTriggerVisibleInViewport()) {
@@ -666,14 +676,27 @@ class ZPopoverComponent {
666
676
  }
667
677
  _setupViewportResizeReposition() {
668
678
  this._viewportResizeSubscription?.unsubscribe();
669
- this._viewportResizeSubscription = fromEvent(window, 'resize')
670
- .pipe(throttleTime(60), takeUntilDestroyed(this._destroyRef))
671
- .subscribe(() => {
679
+ this._clearViewportResizeTimeout();
680
+ const onResize = () => {
672
681
  if (!this._overlayRef?.hasAttached()) {
673
682
  return;
674
683
  }
675
- this._updatePositionNow();
676
- });
684
+ if (this._shouldDeferForMobileKeyboard()) {
685
+ this._markViewportSettling();
686
+ this._scheduleSettledPositionUpdate();
687
+ return;
688
+ }
689
+ this._schedulePositionUpdate();
690
+ };
691
+ window.addEventListener('resize', onResize);
692
+ window.visualViewport?.addEventListener('resize', onResize);
693
+ this._viewportResizeSubscription = {
694
+ unsubscribe: () => {
695
+ window.removeEventListener('resize', onResize);
696
+ window.visualViewport?.removeEventListener('resize', onResize);
697
+ this._clearViewportResizeTimeout();
698
+ },
699
+ };
677
700
  }
678
701
  _showPopover() {
679
702
  const content = this.zContent();
@@ -740,10 +763,6 @@ class ZPopoverComponent {
740
763
  }
741
764
  });
742
765
  this._resizeObserver.observe(this._trigger().nativeElement);
743
- const overlayElement = this._overlayRef?.overlayElement;
744
- if (overlayElement) {
745
- this._resizeObserver.observe(overlayElement);
746
- }
747
766
  const wrapper = this._trigger().nativeElement.parentElement?.parentElement;
748
767
  if (wrapper && wrapper !== document.body) {
749
768
  this._resizeObserver.observe(wrapper);
@@ -752,15 +771,25 @@ class ZPopoverComponent {
752
771
  _updatePositionAfterContentSettles() {
753
772
  this._schedulePositionUpdate();
754
773
  }
755
- _schedulePositionUpdate() {
774
+ _schedulePositionUpdate(force = false) {
756
775
  if (this._positionFrame !== null) {
757
776
  return;
758
777
  }
759
778
  this._positionFrame = requestAnimationFrame(() => {
760
779
  this._positionFrame = null;
761
- this._updatePositionNow();
780
+ this._updatePositionNow(force);
762
781
  });
763
782
  }
783
+ _scheduleSettledPositionUpdate() {
784
+ this._clearViewportResizeTimeout();
785
+ for (const delay of [80, 180, 320]) {
786
+ const timeout = setTimeout(() => {
787
+ this._viewportResizeTimeouts = this._viewportResizeTimeouts.filter(item => item !== timeout);
788
+ this._schedulePositionUpdate(true);
789
+ }, delay);
790
+ this._viewportResizeTimeouts.push(timeout);
791
+ }
792
+ }
764
793
  _cancelScheduledPositionUpdate() {
765
794
  if (this._positionFrame === null) {
766
795
  return;
@@ -768,16 +797,54 @@ class ZPopoverComponent {
768
797
  cancelAnimationFrame(this._positionFrame);
769
798
  this._positionFrame = null;
770
799
  }
771
- _updatePositionNow() {
800
+ _updatePositionNow(force = false) {
772
801
  if (!this._overlayRef?.hasAttached()) {
773
802
  return;
774
803
  }
775
804
  if (isMobilePopoverViewport() && this.zSticky() && !this._isTriggerVisibleInViewport()) {
776
805
  return;
777
806
  }
807
+ if (!force && this._shouldSkipMobileKeyboardUpdate()) {
808
+ return;
809
+ }
778
810
  this._overlayRef.updatePosition();
779
811
  this._applyMobilePopoverPosition(this._componentRef?.instance.position() ?? this.zPosition());
780
812
  }
813
+ _markViewportSettling() {
814
+ this._viewportSettlingUntil = Date.now() + 260;
815
+ }
816
+ _shouldDeferForMobileKeyboard() {
817
+ return this._isMobileOverlayTextInputFocused();
818
+ }
819
+ _shouldSkipMobileKeyboardUpdate() {
820
+ if (!this._isMobileOverlayTextInputFocused()) {
821
+ return false;
822
+ }
823
+ return Date.now() < this._viewportSettlingUntil;
824
+ }
825
+ _isMobileOverlayTextInputFocused() {
826
+ if (!this.zKeyboardSafe() || !isMobilePopoverViewport()) {
827
+ return false;
828
+ }
829
+ const { activeElement } = this._document;
830
+ if (!(activeElement instanceof HTMLElement)) {
831
+ return false;
832
+ }
833
+ const overlayElement = this._overlayRef?.overlayElement;
834
+ if (!overlayElement?.contains(activeElement)) {
835
+ return false;
836
+ }
837
+ if (activeElement.isContentEditable) {
838
+ return true;
839
+ }
840
+ return activeElement.matches('input, textarea, select');
841
+ }
842
+ _clearViewportResizeTimeout() {
843
+ for (const timeout of this._viewportResizeTimeouts) {
844
+ clearTimeout(timeout);
845
+ }
846
+ this._viewportResizeTimeouts = [];
847
+ }
781
848
  _applyMobilePopoverPosition(position) {
782
849
  if (!isMobilePopoverViewport() || !this._overlayRef?.hasAttached()) {
783
850
  return;
@@ -851,7 +918,7 @@ class ZPopoverComponent {
851
918
  this._listenerCleanups = [];
852
919
  }
853
920
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
854
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.0.9", type: ZPopoverComponent, isStandalone: true, selector: "z-popover", inputs: { zContent: { classPropertyName: "zContent", publicName: "zContent", isSignal: true, isRequired: false, transformFunction: null }, zPosition: { classPropertyName: "zPosition", publicName: "zPosition", isSignal: true, isRequired: false, transformFunction: null }, zTrigger: { classPropertyName: "zTrigger", publicName: "zTrigger", isSignal: true, isRequired: false, transformFunction: null }, zClass: { classPropertyName: "zClass", publicName: "zClass", isSignal: true, isRequired: false, transformFunction: null }, zShowDelay: { classPropertyName: "zShowDelay", publicName: "zShowDelay", isSignal: true, isRequired: false, transformFunction: null }, zHideDelay: { classPropertyName: "zHideDelay", publicName: "zHideDelay", isSignal: true, isRequired: false, transformFunction: null }, zDisabled: { classPropertyName: "zDisabled", publicName: "zDisabled", isSignal: true, isRequired: false, transformFunction: null }, zOffset: { classPropertyName: "zOffset", publicName: "zOffset", isSignal: true, isRequired: false, transformFunction: null }, zManualClose: { classPropertyName: "zManualClose", publicName: "zManualClose", isSignal: true, isRequired: false, transformFunction: null }, zOutsideClickClose: { classPropertyName: "zOutsideClickClose", publicName: "zOutsideClickClose", isSignal: true, isRequired: false, transformFunction: null }, zScrollClose: { classPropertyName: "zScrollClose", publicName: "zScrollClose", isSignal: true, isRequired: false, transformFunction: null }, zSticky: { classPropertyName: "zSticky", publicName: "zSticky", isSignal: true, isRequired: false, transformFunction: null }, zShowArrow: { classPropertyName: "zShowArrow", publicName: "zShowArrow", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zShow: "zShow", zHide: "zHide", zControl: "zControl", zOutsideClick: "zOutsideClick" }, host: { classAttribute: "inline-block" }, viewQueries: [{ propertyName: "_trigger", first: true, predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: `
921
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.0.9", type: ZPopoverComponent, isStandalone: true, selector: "z-popover", inputs: { zContent: { classPropertyName: "zContent", publicName: "zContent", isSignal: true, isRequired: false, transformFunction: null }, zPosition: { classPropertyName: "zPosition", publicName: "zPosition", isSignal: true, isRequired: false, transformFunction: null }, zTrigger: { classPropertyName: "zTrigger", publicName: "zTrigger", isSignal: true, isRequired: false, transformFunction: null }, zClass: { classPropertyName: "zClass", publicName: "zClass", isSignal: true, isRequired: false, transformFunction: null }, zShowDelay: { classPropertyName: "zShowDelay", publicName: "zShowDelay", isSignal: true, isRequired: false, transformFunction: null }, zHideDelay: { classPropertyName: "zHideDelay", publicName: "zHideDelay", isSignal: true, isRequired: false, transformFunction: null }, zDisabled: { classPropertyName: "zDisabled", publicName: "zDisabled", isSignal: true, isRequired: false, transformFunction: null }, zOffset: { classPropertyName: "zOffset", publicName: "zOffset", isSignal: true, isRequired: false, transformFunction: null }, zManualClose: { classPropertyName: "zManualClose", publicName: "zManualClose", isSignal: true, isRequired: false, transformFunction: null }, zOutsideClickClose: { classPropertyName: "zOutsideClickClose", publicName: "zOutsideClickClose", isSignal: true, isRequired: false, transformFunction: null }, zScrollClose: { classPropertyName: "zScrollClose", publicName: "zScrollClose", isSignal: true, isRequired: false, transformFunction: null }, zSticky: { classPropertyName: "zSticky", publicName: "zSticky", isSignal: true, isRequired: false, transformFunction: null }, zShowArrow: { classPropertyName: "zShowArrow", publicName: "zShowArrow", isSignal: true, isRequired: false, transformFunction: null }, zKeyboardSafe: { classPropertyName: "zKeyboardSafe", publicName: "zKeyboardSafe", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zShow: "zShow", zHide: "zHide", zControl: "zControl", zOutsideClick: "zOutsideClick" }, host: { classAttribute: "inline-block" }, viewQueries: [{ propertyName: "_trigger", first: true, predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: `
855
922
  <span #trigger class="z-popover-trigger inline-block">
856
923
  <ng-content />
857
924
  </span>
@@ -872,7 +939,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImpor
872
939
  class: 'inline-block',
873
940
  },
874
941
  }]
875
- }], propDecorators: { _trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], zShow: [{ type: i0.Output, args: ["zShow"] }], zHide: [{ type: i0.Output, args: ["zHide"] }], zControl: [{ type: i0.Output, args: ["zControl"] }], zOutsideClick: [{ type: i0.Output, args: ["zOutsideClick"] }], zContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "zContent", required: false }] }], zPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPosition", required: false }] }], zTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTrigger", required: false }] }], zClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "zClass", required: false }] }], zShowDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowDelay", required: false }] }], zHideDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "zHideDelay", required: false }] }], zDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDisabled", required: false }] }], zOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOffset", required: false }] }], zManualClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "zManualClose", required: false }] }], zOutsideClickClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOutsideClickClose", required: false }] }], zScrollClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "zScrollClose", required: false }] }], zSticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSticky", required: false }] }], zShowArrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowArrow", required: false }] }] } });
942
+ }], propDecorators: { _trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], zShow: [{ type: i0.Output, args: ["zShow"] }], zHide: [{ type: i0.Output, args: ["zHide"] }], zControl: [{ type: i0.Output, args: ["zControl"] }], zOutsideClick: [{ type: i0.Output, args: ["zOutsideClick"] }], zContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "zContent", required: false }] }], zPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPosition", required: false }] }], zTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTrigger", required: false }] }], zClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "zClass", required: false }] }], zShowDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowDelay", required: false }] }], zHideDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "zHideDelay", required: false }] }], zDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDisabled", required: false }] }], zOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOffset", required: false }] }], zManualClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "zManualClose", required: false }] }], zOutsideClickClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOutsideClickClose", required: false }] }], zScrollClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "zScrollClose", required: false }] }], zSticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSticky", required: false }] }], zShowArrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowArrow", required: false }] }], zKeyboardSafe: [{ type: i0.Input, args: [{ isSignal: true, alias: "zKeyboardSafe", required: false }] }] } });
876
943
 
877
944
  class ZPopoverDirective {
878
945
  static _openPopovers = new Set();
@@ -892,6 +959,7 @@ class ZPopoverDirective {
892
959
  zScrollClose = input(false, { ...(ngDevMode ? { debugName: "zScrollClose" } : {}), transform: zTransform });
893
960
  zSticky = input(false, { ...(ngDevMode ? { debugName: "zSticky" } : {}), transform: zTransform });
894
961
  zShowArrow = input(false, { ...(ngDevMode ? { debugName: "zShowArrow" } : {}), transform: zTransform });
962
+ zKeyboardSafe = input(false, { ...(ngDevMode ? { debugName: "zKeyboardSafe" } : {}), transform: zTransform });
895
963
  zShow = output();
896
964
  zHide = output();
897
965
  zHideStart = output();
@@ -916,7 +984,9 @@ class ZPopoverDirective {
916
984
  _viewportResizeSubscription = null;
917
985
  _resizeObserver = null;
918
986
  _hideTimeout = null;
987
+ _viewportResizeTimeouts = [];
919
988
  _positionFrame = null;
989
+ _viewportSettlingUntil = 0;
920
990
  _isDestroyed = signal(false, ...(ngDevMode ? [{ debugName: "_isDestroyed" }] : []));
921
991
  _isVisible = signal(false, ...(ngDevMode ? [{ debugName: "_isVisible" }] : []));
922
992
  ngOnInit() {
@@ -995,7 +1065,7 @@ class ZPopoverDirective {
995
1065
  if (!this._isVisible()) {
996
1066
  return;
997
1067
  }
998
- this._updatePositionNow();
1068
+ this._schedulePositionUpdate();
999
1069
  }
1000
1070
  _createOverlay() {
1001
1071
  const positionStrategy = createPopoverPositionStrategy(this._overlayPositionBuilder, this._getTriggerElement(), this.zPosition(), this.zOffset());
@@ -1011,7 +1081,7 @@ class ZPopoverDirective {
1011
1081
  if (this.zScrollClose()) {
1012
1082
  return this._overlay.scrollStrategies.close();
1013
1083
  }
1014
- if (isMobilePopoverViewport() && this.zSticky()) {
1084
+ if (isMobilePopoverViewport() && (this.zSticky() || this.zKeyboardSafe())) {
1015
1085
  return this._overlay.scrollStrategies.noop();
1016
1086
  }
1017
1087
  return this._overlay.scrollStrategies.reposition();
@@ -1041,6 +1111,8 @@ class ZPopoverDirective {
1041
1111
  this._scrollSubscription = null;
1042
1112
  this._viewportResizeSubscription?.unsubscribe();
1043
1113
  this._viewportResizeSubscription = null;
1114
+ this._clearViewportResizeTimeout();
1115
+ this._viewportSettlingUntil = 0;
1044
1116
  this._resizeObserver?.disconnect();
1045
1117
  this._resizeObserver = null;
1046
1118
  this._cancelScheduledPositionUpdate();
@@ -1131,6 +1203,11 @@ class ZPopoverDirective {
1131
1203
  if (ticking) {
1132
1204
  return;
1133
1205
  }
1206
+ if (this._shouldDeferForMobileKeyboard()) {
1207
+ this._markViewportSettling();
1208
+ this._scheduleSettledPositionUpdate();
1209
+ return;
1210
+ }
1134
1211
  ticking = true;
1135
1212
  requestAnimationFrame(() => {
1136
1213
  if (this.zSticky() && !this._isTriggerVisibleInViewport()) {
@@ -1150,18 +1227,27 @@ class ZPopoverDirective {
1150
1227
  }
1151
1228
  _setupViewportResizeReposition() {
1152
1229
  this._viewportResizeSubscription?.unsubscribe();
1153
- this._viewportResizeSubscription = fromEvent(window, 'resize')
1154
- .pipe(throttleTime(60), takeUntilDestroyed(this._destroyRef))
1155
- .subscribe(() => {
1230
+ this._clearViewportResizeTimeout();
1231
+ const onResize = () => {
1156
1232
  if (!this._overlayRef?.hasAttached()) {
1157
1233
  return;
1158
1234
  }
1159
- const widthConfig = this._getWidthConfig();
1160
- if (widthConfig.width) {
1161
- this._overlayRef.updateSize(widthConfig);
1235
+ if (this._shouldDeferForMobileKeyboard()) {
1236
+ this._markViewportSettling();
1237
+ this._scheduleSettledPositionUpdate();
1238
+ return;
1162
1239
  }
1163
- this._updatePositionNow();
1164
- });
1240
+ this._schedulePositionUpdate();
1241
+ };
1242
+ window.addEventListener('resize', onResize);
1243
+ window.visualViewport?.addEventListener('resize', onResize);
1244
+ this._viewportResizeSubscription = {
1245
+ unsubscribe: () => {
1246
+ window.removeEventListener('resize', onResize);
1247
+ window.visualViewport?.removeEventListener('resize', onResize);
1248
+ this._clearViewportResizeTimeout();
1249
+ },
1250
+ };
1165
1251
  }
1166
1252
  _delay(show, delay) {
1167
1253
  this._delaySubject.next({ show, delay });
@@ -1254,10 +1340,6 @@ class ZPopoverDirective {
1254
1340
  });
1255
1341
  const originElement = this._getTriggerElement();
1256
1342
  this._resizeObserver.observe(originElement);
1257
- const overlayElement = this._overlayRef?.overlayElement;
1258
- if (overlayElement) {
1259
- this._resizeObserver.observe(overlayElement);
1260
- }
1261
1343
  if (originElement !== this._elementRef.nativeElement) {
1262
1344
  this._resizeObserver.observe(this._elementRef.nativeElement);
1263
1345
  }
@@ -1269,15 +1351,25 @@ class ZPopoverDirective {
1269
1351
  _updatePositionAfterContentSettles() {
1270
1352
  this._schedulePositionUpdate();
1271
1353
  }
1272
- _schedulePositionUpdate() {
1354
+ _schedulePositionUpdate(force = false) {
1273
1355
  if (this._positionFrame !== null) {
1274
1356
  return;
1275
1357
  }
1276
1358
  this._positionFrame = requestAnimationFrame(() => {
1277
1359
  this._positionFrame = null;
1278
- this._updatePositionNow();
1360
+ this._updatePositionNow(force);
1279
1361
  });
1280
1362
  }
1363
+ _scheduleSettledPositionUpdate() {
1364
+ this._clearViewportResizeTimeout();
1365
+ for (const delay of [80, 180, 320]) {
1366
+ const timeout = setTimeout(() => {
1367
+ this._viewportResizeTimeouts = this._viewportResizeTimeouts.filter(item => item !== timeout);
1368
+ this._schedulePositionUpdate(true);
1369
+ }, delay);
1370
+ this._viewportResizeTimeouts.push(timeout);
1371
+ }
1372
+ }
1281
1373
  _cancelScheduledPositionUpdate() {
1282
1374
  if (this._positionFrame === null) {
1283
1375
  return;
@@ -1285,13 +1377,16 @@ class ZPopoverDirective {
1285
1377
  cancelAnimationFrame(this._positionFrame);
1286
1378
  this._positionFrame = null;
1287
1379
  }
1288
- _updatePositionNow() {
1380
+ _updatePositionNow(force = false) {
1289
1381
  if (!this._overlayRef?.hasAttached()) {
1290
1382
  return;
1291
1383
  }
1292
1384
  if (isMobilePopoverViewport() && this.zSticky() && !this._isTriggerVisibleInViewport()) {
1293
1385
  return;
1294
1386
  }
1387
+ if (!force && this._shouldSkipMobileKeyboardUpdate()) {
1388
+ return;
1389
+ }
1295
1390
  const widthConfig = this._getWidthConfig();
1296
1391
  if (widthConfig.width) {
1297
1392
  this._overlayRef.updateSize(widthConfig);
@@ -1299,6 +1394,41 @@ class ZPopoverDirective {
1299
1394
  this._overlayRef.updatePosition();
1300
1395
  this._applyMobilePopoverPosition(this._componentRef?.instance.position() ?? this.zPosition());
1301
1396
  }
1397
+ _markViewportSettling() {
1398
+ this._viewportSettlingUntil = Date.now() + 260;
1399
+ }
1400
+ _shouldDeferForMobileKeyboard() {
1401
+ return this._isMobileOverlayTextInputFocused();
1402
+ }
1403
+ _shouldSkipMobileKeyboardUpdate() {
1404
+ if (!this._isMobileOverlayTextInputFocused()) {
1405
+ return false;
1406
+ }
1407
+ return Date.now() < this._viewportSettlingUntil;
1408
+ }
1409
+ _isMobileOverlayTextInputFocused() {
1410
+ if (!this.zKeyboardSafe() || !isMobilePopoverViewport()) {
1411
+ return false;
1412
+ }
1413
+ const { activeElement } = this._document;
1414
+ if (!(activeElement instanceof HTMLElement)) {
1415
+ return false;
1416
+ }
1417
+ const overlayElement = this._overlayRef?.overlayElement;
1418
+ if (!overlayElement?.contains(activeElement)) {
1419
+ return false;
1420
+ }
1421
+ if (activeElement.isContentEditable) {
1422
+ return true;
1423
+ }
1424
+ return activeElement.matches('input, textarea, select');
1425
+ }
1426
+ _clearViewportResizeTimeout() {
1427
+ for (const timeout of this._viewportResizeTimeouts) {
1428
+ clearTimeout(timeout);
1429
+ }
1430
+ this._viewportResizeTimeouts = [];
1431
+ }
1302
1432
  _applyMobilePopoverPosition(position) {
1303
1433
  if (!isMobilePopoverViewport() || !this._overlayRef?.hasAttached()) {
1304
1434
  return;
@@ -1374,7 +1504,7 @@ class ZPopoverDirective {
1374
1504
  this._listenerCleanups = [];
1375
1505
  }
1376
1506
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZPopoverDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1377
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.9", type: ZPopoverDirective, isStandalone: true, selector: "[z-popover]", inputs: { zContent: { classPropertyName: "zContent", publicName: "zPopoverContent", isSignal: true, isRequired: false, transformFunction: null }, zPosition: { classPropertyName: "zPosition", publicName: "zPosition", isSignal: true, isRequired: false, transformFunction: null }, zTrigger: { classPropertyName: "zTrigger", publicName: "zTrigger", isSignal: true, isRequired: false, transformFunction: null }, zPopoverTrigger: { classPropertyName: "zPopoverTrigger", publicName: "zPopoverTrigger", isSignal: true, isRequired: false, transformFunction: null }, zClass: { classPropertyName: "zClass", publicName: "zClass", isSignal: true, isRequired: false, transformFunction: null }, zShowDelay: { classPropertyName: "zShowDelay", publicName: "zShowDelay", isSignal: true, isRequired: false, transformFunction: null }, zHideDelay: { classPropertyName: "zHideDelay", publicName: "zHideDelay", isSignal: true, isRequired: false, transformFunction: null }, zDisabled: { classPropertyName: "zDisabled", publicName: "zDisabled", isSignal: true, isRequired: false, transformFunction: null }, zOffset: { classPropertyName: "zOffset", publicName: "zOffset", isSignal: true, isRequired: false, transformFunction: null }, zPopoverWidth: { classPropertyName: "zPopoverWidth", publicName: "zPopoverWidth", isSignal: true, isRequired: false, transformFunction: null }, zTriggerRef: { classPropertyName: "zTriggerRef", publicName: "zTriggerRef", isSignal: true, isRequired: false, transformFunction: null }, zManualClose: { classPropertyName: "zManualClose", publicName: "zManualClose", isSignal: true, isRequired: false, transformFunction: null }, zOutsideClickClose: { classPropertyName: "zOutsideClickClose", publicName: "zOutsideClickClose", isSignal: true, isRequired: false, transformFunction: null }, zScrollClose: { classPropertyName: "zScrollClose", publicName: "zScrollClose", isSignal: true, isRequired: false, transformFunction: null }, zSticky: { classPropertyName: "zSticky", publicName: "zSticky", isSignal: true, isRequired: false, transformFunction: null }, zShowArrow: { classPropertyName: "zShowArrow", publicName: "zShowArrow", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zShow: "zShow", zHide: "zHide", zHideStart: "zHideStart", zControl: "zControl", zPositionChange: "zPositionChange", zOutsideClick: "zOutsideClick" }, exportAs: ["zPopover"], ngImport: i0 });
1507
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.9", type: ZPopoverDirective, isStandalone: true, selector: "[z-popover]", inputs: { zContent: { classPropertyName: "zContent", publicName: "zPopoverContent", isSignal: true, isRequired: false, transformFunction: null }, zPosition: { classPropertyName: "zPosition", publicName: "zPosition", isSignal: true, isRequired: false, transformFunction: null }, zTrigger: { classPropertyName: "zTrigger", publicName: "zTrigger", isSignal: true, isRequired: false, transformFunction: null }, zPopoverTrigger: { classPropertyName: "zPopoverTrigger", publicName: "zPopoverTrigger", isSignal: true, isRequired: false, transformFunction: null }, zClass: { classPropertyName: "zClass", publicName: "zClass", isSignal: true, isRequired: false, transformFunction: null }, zShowDelay: { classPropertyName: "zShowDelay", publicName: "zShowDelay", isSignal: true, isRequired: false, transformFunction: null }, zHideDelay: { classPropertyName: "zHideDelay", publicName: "zHideDelay", isSignal: true, isRequired: false, transformFunction: null }, zDisabled: { classPropertyName: "zDisabled", publicName: "zDisabled", isSignal: true, isRequired: false, transformFunction: null }, zOffset: { classPropertyName: "zOffset", publicName: "zOffset", isSignal: true, isRequired: false, transformFunction: null }, zPopoverWidth: { classPropertyName: "zPopoverWidth", publicName: "zPopoverWidth", isSignal: true, isRequired: false, transformFunction: null }, zTriggerRef: { classPropertyName: "zTriggerRef", publicName: "zTriggerRef", isSignal: true, isRequired: false, transformFunction: null }, zManualClose: { classPropertyName: "zManualClose", publicName: "zManualClose", isSignal: true, isRequired: false, transformFunction: null }, zOutsideClickClose: { classPropertyName: "zOutsideClickClose", publicName: "zOutsideClickClose", isSignal: true, isRequired: false, transformFunction: null }, zScrollClose: { classPropertyName: "zScrollClose", publicName: "zScrollClose", isSignal: true, isRequired: false, transformFunction: null }, zSticky: { classPropertyName: "zSticky", publicName: "zSticky", isSignal: true, isRequired: false, transformFunction: null }, zShowArrow: { classPropertyName: "zShowArrow", publicName: "zShowArrow", isSignal: true, isRequired: false, transformFunction: null }, zKeyboardSafe: { classPropertyName: "zKeyboardSafe", publicName: "zKeyboardSafe", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zShow: "zShow", zHide: "zHide", zHideStart: "zHideStart", zControl: "zControl", zPositionChange: "zPositionChange", zOutsideClick: "zOutsideClick" }, exportAs: ["zPopover"], ngImport: i0 });
1378
1508
  }
1379
1509
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZPopoverDirective, decorators: [{
1380
1510
  type: Directive,
@@ -1383,7 +1513,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImpor
1383
1513
  standalone: true,
1384
1514
  exportAs: 'zPopover',
1385
1515
  }]
1386
- }], propDecorators: { zContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPopoverContent", required: false }] }], zPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPosition", required: false }] }], zTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTrigger", required: false }] }], zPopoverTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPopoverTrigger", required: false }] }], zClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "zClass", required: false }] }], zShowDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowDelay", required: false }] }], zHideDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "zHideDelay", required: false }] }], zDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDisabled", required: false }] }], zOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOffset", required: false }] }], zPopoverWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPopoverWidth", required: false }] }], zTriggerRef: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTriggerRef", required: false }] }], zManualClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "zManualClose", required: false }] }], zOutsideClickClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOutsideClickClose", required: false }] }], zScrollClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "zScrollClose", required: false }] }], zSticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSticky", required: false }] }], zShowArrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowArrow", required: false }] }], zShow: [{ type: i0.Output, args: ["zShow"] }], zHide: [{ type: i0.Output, args: ["zHide"] }], zHideStart: [{ type: i0.Output, args: ["zHideStart"] }], zControl: [{ type: i0.Output, args: ["zControl"] }], zPositionChange: [{ type: i0.Output, args: ["zPositionChange"] }], zOutsideClick: [{ type: i0.Output, args: ["zOutsideClick"] }] } });
1516
+ }], propDecorators: { zContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPopoverContent", required: false }] }], zPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPosition", required: false }] }], zTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTrigger", required: false }] }], zPopoverTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPopoverTrigger", required: false }] }], zClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "zClass", required: false }] }], zShowDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowDelay", required: false }] }], zHideDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "zHideDelay", required: false }] }], zDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDisabled", required: false }] }], zOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOffset", required: false }] }], zPopoverWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPopoverWidth", required: false }] }], zTriggerRef: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTriggerRef", required: false }] }], zManualClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "zManualClose", required: false }] }], zOutsideClickClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOutsideClickClose", required: false }] }], zScrollClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "zScrollClose", required: false }] }], zSticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSticky", required: false }] }], zShowArrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowArrow", required: false }] }], zKeyboardSafe: [{ type: i0.Input, args: [{ isSignal: true, alias: "zKeyboardSafe", required: false }] }], zShow: [{ type: i0.Output, args: ["zShow"] }], zHide: [{ type: i0.Output, args: ["zHide"] }], zHideStart: [{ type: i0.Output, args: ["zHideStart"] }], zControl: [{ type: i0.Output, args: ["zControl"] }], zPositionChange: [{ type: i0.Output, args: ["zPositionChange"] }], zOutsideClick: [{ type: i0.Output, args: ["zOutsideClick"] }] } });
1387
1517
 
1388
1518
  /**
1389
1519
  * Generated bundle index. Do not edit.