ng-zenduit 2.3.12 → 2.3.15

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.
@@ -221,8 +221,18 @@ class ZenduOverlayService {
221
221
  if (config.minWidth != null) {
222
222
  overlayConfig.minWidth = config.minWidth;
223
223
  }
224
+ if (config.minHeight != null) {
225
+ overlayConfig.minHeight = config.minHeight;
226
+ }
224
227
  const overlayRef = this._overlay.create(overlayConfig);
225
228
  overlayRef.attach(new TemplatePortal(config.content, config.viewContainerRef));
229
+ // scrollBehavior: 'block' — freeze the trigger's scroll container while
230
+ // the panel is open (mat-select-style). CDK's BlockScrollStrategy only
231
+ // locks <html>, which is useless in an app-shell that scrolls inside a
232
+ // nested overflow:auto pane, so we lock that pane directly instead.
233
+ const unlockScroll = config.scrollBehavior === 'block'
234
+ ? this._lockScrollContainer(originEl)
235
+ : null;
226
236
  const closed = new Subject();
227
237
  const destroyed = new Subject();
228
238
  // Ignore the pointer interaction that OPENED the panel. open() is
@@ -305,6 +315,7 @@ class ZenduOverlayService {
305
315
  closed: closed.asObservable(),
306
316
  updatePosition: () => overlayRef.updatePosition(),
307
317
  close: () => {
318
+ unlockScroll?.();
308
319
  removeViewportListeners();
309
320
  destroyed.next();
310
321
  destroyed.complete();
@@ -329,6 +340,47 @@ class ZenduOverlayService {
329
340
  { originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -offsetY }
330
341
  ];
331
342
  }
343
+ /**
344
+ * Lock the trigger's nearest scrollable ancestor (or the document) with
345
+ * `overflow: hidden` so the page can't scroll while the panel is open, and
346
+ * pad for the now-missing scrollbar so content doesn't jump. Returns an
347
+ * idempotent restore fn that puts the inline styles back.
348
+ */
349
+ _lockScrollContainer(originEl) {
350
+ const el = this._findScrollContainer(originEl);
351
+ if (!el) {
352
+ return () => { };
353
+ }
354
+ const prevOverflow = el.style.overflow;
355
+ const prevPaddingRight = el.style.paddingRight;
356
+ const scrollbarWidth = el.offsetWidth - el.clientWidth;
357
+ el.style.overflow = 'hidden';
358
+ if (scrollbarWidth > 0) {
359
+ const computed = getComputedStyle(el).paddingRight;
360
+ el.style.paddingRight = `calc(${computed} + ${scrollbarWidth}px)`;
361
+ }
362
+ return () => {
363
+ el.style.overflow = prevOverflow;
364
+ el.style.paddingRight = prevPaddingRight;
365
+ };
366
+ }
367
+ /**
368
+ * Walk up from the trigger to the first ancestor that actually scrolls
369
+ * (overflow-y auto/scroll AND content taller than the box). Falls back to
370
+ * the document scrolling element so block always has something to lock.
371
+ */
372
+ _findScrollContainer(originEl) {
373
+ let node = originEl.parentElement;
374
+ while (node && node !== document.body && node !== document.documentElement) {
375
+ const overflowY = getComputedStyle(node).overflowY;
376
+ const scrolls = overflowY === 'auto' || overflowY === 'scroll';
377
+ if (scrolls && node.scrollHeight > node.clientHeight) {
378
+ return node;
379
+ }
380
+ node = node.parentElement;
381
+ }
382
+ return document.scrollingElement ?? document.documentElement;
383
+ }
332
384
  _panelClasses(extra) {
333
385
  const classes = ['zen-overlay-panel'];
334
386
  if (Array.isArray(extra)) {
@@ -2862,8 +2914,11 @@ class ZenduDatePickerDropdownComponent {
2862
2914
  return formatted;
2863
2915
  }
2864
2916
  formatTime(date) {
2865
- let h = date.getHours();
2866
- const m = date.getMinutes();
2917
+ // Normalize through moment so a string/moment input (the declared type is
2918
+ // Date, but consumers often bind ISO strings) doesn't break native getters.
2919
+ const mDate = moment(date);
2920
+ let h = mDate.hours();
2921
+ const m = mDate.minutes();
2867
2922
  const period = h >= 12 ? 'PM' : 'AM';
2868
2923
  if (h === 0)
2869
2924
  h = 12;
@@ -3637,6 +3692,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImpor
3637
3692
  type: Input
3638
3693
  }] } });
3639
3694
 
3695
+ // Lets a tall filter panel clamp to the viewport and scroll instead of being
3696
+ // pushed off-screen. Gates CDK's flexible path; not the panel's actual height.
3697
+ const FILTER_PANEL_MIN_HEIGHT = 120;
3640
3698
  class ZenduFilterComponent {
3641
3699
  set isVisible(open) {
3642
3700
  open = !!open;
@@ -3741,6 +3799,7 @@ class ZenduFilterComponent {
3741
3799
  // The panel has its own fixed width (.filter-menu); let it size to content
3742
3800
  // and the overlay's flexible dimensions clamp it on small viewports.
3743
3801
  width: 'auto',
3802
+ minHeight: FILTER_PANEL_MIN_HEIGHT,
3744
3803
  scrollBehavior: 'reposition',
3745
3804
  positions: this._buildConnectedPositions(),
3746
3805
  });
@@ -4827,7 +4886,11 @@ class ZenduSelectComponent {
4827
4886
  width: 'origin',
4828
4887
  minWidth: this.panelMinWidth,
4829
4888
  panelClass: this.panelClass,
4830
- scrollBehavior: 'reposition'
4889
+ // Freeze the page while the dropdown is open (mat-select-style) instead
4890
+ // of chasing the trigger on scroll. The overlay service locks the
4891
+ // trigger's nearest scroll container, which works in app shells that
4892
+ // scroll inner panes rather than the document root.
4893
+ scrollBehavior: 'block'
4831
4894
  });
4832
4895
  // Outside click / Escape / detach → close (and emit, as a user action).
4833
4896
  this._panelRef.closed.subscribe(() => this.hideDropDown(true));