@skyux/core 5.9.6 → 5.11.0

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 (33) hide show
  1. package/bundles/skyux-core-testing.umd.js +30 -0
  2. package/bundles/skyux-core.umd.js +1000 -980
  3. package/documentation.json +104 -104
  4. package/esm2015/lib/modules/adapter-service/adapter.service.js +10 -6
  5. package/esm2015/lib/modules/adapter-service/adapter.service.js.map +1 -1
  6. package/esm2015/lib/modules/affix/affix.service.js +6 -2
  7. package/esm2015/lib/modules/affix/affix.service.js.map +1 -1
  8. package/esm2015/lib/modules/resize-observer/resize-observer-media-query.service.js +28 -21
  9. package/esm2015/lib/modules/resize-observer/resize-observer-media-query.service.js.map +1 -1
  10. package/esm2015/lib/modules/resize-observer/resize-observer.service.js +16 -10
  11. package/esm2015/lib/modules/resize-observer/resize-observer.service.js.map +1 -1
  12. package/esm2015/lib/modules/scrollable-host/scrollable-host.service.js +28 -25
  13. package/esm2015/lib/modules/scrollable-host/scrollable-host.service.js.map +1 -1
  14. package/esm2015/testing/core-testing.module.js +29 -0
  15. package/esm2015/testing/core-testing.module.js.map +1 -0
  16. package/esm2015/testing/mock-media-query.service.js +2 -0
  17. package/esm2015/testing/mock-media-query.service.js.map +1 -1
  18. package/esm2015/testing/mock-ui-config.service.js.map +1 -1
  19. package/esm2015/testing/public-api.js +1 -0
  20. package/esm2015/testing/public-api.js.map +1 -1
  21. package/fesm2015/skyux-core-testing.js +28 -2
  22. package/fesm2015/skyux-core-testing.js.map +1 -1
  23. package/fesm2015/skyux-core.js +85 -64
  24. package/fesm2015/skyux-core.js.map +1 -1
  25. package/lib/modules/adapter-service/adapter.service.d.ts +1 -1
  26. package/lib/modules/affix/affix.service.d.ts +1 -1
  27. package/lib/modules/resize-observer/resize-observer-media-query.service.d.ts +1 -4
  28. package/lib/modules/resize-observer/resize-observer.service.d.ts +1 -2
  29. package/lib/modules/scrollable-host/scrollable-host.service.d.ts +7 -4
  30. package/package.json +2 -2
  31. package/testing/core-testing.module.d.ts +6 -0
  32. package/testing/mock-ui-config.service.d.ts +2 -1
  33. package/testing/public-api.d.ts +1 -0
@@ -1,5 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { NgModule, Injectable, EventEmitter, Directive, Input, Output, Injector, ViewContainerRef, Component, ChangeDetectionStrategy, ViewChild, Pipe, ElementRef, Optional } from '@angular/core';
3
+ import { __classPrivateFieldSet, __classPrivateFieldGet } from 'tslib';
3
4
  import * as i4 from '@angular/common';
4
5
  import { CommonModule } from '@angular/common';
5
6
  import { Subject, fromEvent, BehaviorSubject, ReplaySubject, Observable, of } from 'rxjs';
@@ -44,6 +45,7 @@ var SkyMediaBreakpoints;
44
45
  SkyMediaBreakpoints[SkyMediaBreakpoints["lg"] = 4] = "lg";
45
46
  })(SkyMediaBreakpoints || (SkyMediaBreakpoints = {}));
46
47
 
48
+ var _SkyCoreAdapterService_renderer;
47
49
  const SKY_TABBABLE_SELECTOR = [
48
50
  'a[href]',
49
51
  'area[href]',
@@ -60,7 +62,8 @@ const SKY_TABBABLE_SELECTOR = [
60
62
  class SkyCoreAdapterService {
61
63
  constructor(rendererFactory) {
62
64
  this.rendererFactory = rendererFactory;
63
- this.renderer = this.rendererFactory.createRenderer(undefined, undefined);
65
+ _SkyCoreAdapterService_renderer.set(this, void 0);
66
+ __classPrivateFieldSet(this, _SkyCoreAdapterService_renderer, this.rendererFactory.createRenderer(undefined, null), "f");
64
67
  }
65
68
  /**
66
69
  * Set the responsive container CSS class for a given element.
@@ -71,10 +74,10 @@ class SkyCoreAdapterService {
71
74
  */
72
75
  setResponsiveContainerClass(elementRef, breakpoint) {
73
76
  const nativeEl = elementRef.nativeElement;
74
- this.renderer.removeClass(nativeEl, 'sky-responsive-container-xs');
75
- this.renderer.removeClass(nativeEl, 'sky-responsive-container-sm');
76
- this.renderer.removeClass(nativeEl, 'sky-responsive-container-md');
77
- this.renderer.removeClass(nativeEl, 'sky-responsive-container-lg');
77
+ __classPrivateFieldGet(this, _SkyCoreAdapterService_renderer, "f").removeClass(nativeEl, 'sky-responsive-container-xs');
78
+ __classPrivateFieldGet(this, _SkyCoreAdapterService_renderer, "f").removeClass(nativeEl, 'sky-responsive-container-sm');
79
+ __classPrivateFieldGet(this, _SkyCoreAdapterService_renderer, "f").removeClass(nativeEl, 'sky-responsive-container-md');
80
+ __classPrivateFieldGet(this, _SkyCoreAdapterService_renderer, "f").removeClass(nativeEl, 'sky-responsive-container-lg');
78
81
  let newClass;
79
82
  switch (breakpoint) {
80
83
  case SkyMediaBreakpoints.xs: {
@@ -94,7 +97,7 @@ class SkyCoreAdapterService {
94
97
  break;
95
98
  }
96
99
  }
97
- this.renderer.addClass(nativeEl, newClass);
100
+ __classPrivateFieldGet(this, _SkyCoreAdapterService_renderer, "f").addClass(nativeEl, newClass);
98
101
  }
99
102
  /**
100
103
  * This method temporarily enables/disables pointer events.
@@ -258,6 +261,7 @@ class SkyCoreAdapterService {
258
261
  return hasBounds;
259
262
  }
260
263
  }
264
+ _SkyCoreAdapterService_renderer = new WeakMap();
261
265
  SkyCoreAdapterService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyCoreAdapterService, deps: [{ token: i0.RendererFactory2 }], target: i0.ɵɵFactoryTarget.Injectable });
262
266
  SkyCoreAdapterService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyCoreAdapterService, providedIn: 'root' });
263
267
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyCoreAdapterService, decorators: [{
@@ -719,18 +723,21 @@ class SkyAffixer {
719
723
  }
720
724
  }
721
725
 
726
+ var _SkyAffixService_renderer;
722
727
  class SkyAffixService {
723
728
  constructor(rendererFactory) {
724
- this.renderer = rendererFactory.createRenderer(undefined, undefined);
729
+ _SkyAffixService_renderer.set(this, void 0);
730
+ __classPrivateFieldSet(this, _SkyAffixService_renderer, rendererFactory.createRenderer(undefined, null), "f");
725
731
  }
726
732
  /**
727
733
  * Creates an instance of [[SkyAffixer]].
728
734
  * @param affixed The element to be affixed.
729
735
  */
730
736
  createAffixer(affixed) {
731
- return new SkyAffixer(affixed.nativeElement, this.renderer);
737
+ return new SkyAffixer(affixed.nativeElement, __classPrivateFieldGet(this, _SkyAffixService_renderer, "f"));
732
738
  }
733
739
  }
740
+ _SkyAffixService_renderer = new WeakMap();
734
741
  SkyAffixService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyAffixService, deps: [{ token: i0.RendererFactory2 }], target: i0.ɵɵFactoryTarget.Injectable });
735
742
  SkyAffixService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyAffixService, providedIn: 'root' });
736
743
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyAffixService, decorators: [{
@@ -2416,19 +2423,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
2416
2423
  }]
2417
2424
  }] });
2418
2425
 
2426
+ var _SkyResizeObserverService_resizeObserver, _SkyResizeObserverService_tracking;
2419
2427
  /**
2420
2428
  * Service to create rxjs observables for changes to the content box dimensions of elements.
2421
2429
  */
2422
2430
  class SkyResizeObserverService {
2423
2431
  constructor(zone) {
2424
2432
  this.zone = zone;
2425
- this._tracking = [];
2426
- this._resizeObserver = new ResizeObserver((entries) => {
2433
+ _SkyResizeObserverService_resizeObserver.set(this, void 0);
2434
+ _SkyResizeObserverService_tracking.set(this, []);
2435
+ __classPrivateFieldSet(this, _SkyResizeObserverService_resizeObserver, new ResizeObserver((entries) => {
2427
2436
  entries.forEach((entry) => this.callback(entry));
2428
- });
2437
+ }), "f");
2429
2438
  }
2430
2439
  ngOnDestroy() {
2431
- this._resizeObserver.disconnect();
2440
+ __classPrivateFieldGet(this, _SkyResizeObserverService_resizeObserver, "f").disconnect();
2432
2441
  }
2433
2442
  /**
2434
2443
  * Create rxjs observable to get size changes for an element ref.
@@ -2437,22 +2446,22 @@ class SkyResizeObserverService {
2437
2446
  return this.observeAndTrack(element).subjectObservable;
2438
2447
  }
2439
2448
  observeAndTrack(element) {
2440
- const checkTracking = this._tracking.findIndex((value) => {
2449
+ const checkTracking = __classPrivateFieldGet(this, _SkyResizeObserverService_tracking, "f").findIndex((value) => {
2441
2450
  return !value.subject.closed && value.element === element.nativeElement;
2442
2451
  });
2443
2452
  if (checkTracking === -1) {
2444
- this._resizeObserver.observe(element.nativeElement);
2453
+ __classPrivateFieldGet(this, _SkyResizeObserverService_resizeObserver, "f").observe(element.nativeElement);
2445
2454
  }
2446
2455
  const subject = new Subject();
2447
2456
  const subjectObservable = subject.pipe(finalize(() => {
2448
2457
  // Are there any other tracking entries still watching this element?
2449
- const checkTracking = this._tracking.findIndex((value) => {
2458
+ const checkTracking = __classPrivateFieldGet(this, _SkyResizeObserverService_tracking, "f").findIndex((value) => {
2450
2459
  return (value.subject !== subject &&
2451
2460
  !value.subject.closed &&
2452
2461
  value.element === element.nativeElement);
2453
2462
  });
2454
2463
  if (checkTracking === -1) {
2455
- this._resizeObserver.unobserve(element.nativeElement);
2464
+ __classPrivateFieldGet(this, _SkyResizeObserverService_resizeObserver, "f").unobserve(element.nativeElement);
2456
2465
  }
2457
2466
  }));
2458
2467
  const tracking = {
@@ -2460,15 +2469,17 @@ class SkyResizeObserverService {
2460
2469
  subject,
2461
2470
  subjectObservable,
2462
2471
  };
2463
- this._tracking.push(tracking);
2472
+ __classPrivateFieldGet(this, _SkyResizeObserverService_tracking, "f").push(tracking);
2464
2473
  return tracking;
2465
2474
  }
2466
2475
  callback(entry) {
2467
- this._tracking
2476
+ __classPrivateFieldGet(this, _SkyResizeObserverService_tracking, "f")
2468
2477
  .filter((value) => !(value.subject.closed || value.subject.isStopped))
2469
2478
  .forEach((value) => {
2470
2479
  /* istanbul ignore else */
2471
2480
  if (value.element === entry.target) {
2481
+ // Execute the callback within NgZone because Angular does not "monkey patch"
2482
+ // ResizeObserver like it does for other features in the DOM.
2472
2483
  this.zone.run(() => {
2473
2484
  value.subject.next(entry);
2474
2485
  });
@@ -2476,6 +2487,7 @@ class SkyResizeObserverService {
2476
2487
  });
2477
2488
  }
2478
2489
  }
2490
+ _SkyResizeObserverService_resizeObserver = new WeakMap(), _SkyResizeObserverService_tracking = new WeakMap();
2479
2491
  SkyResizeObserverService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyResizeObserverService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
2480
2492
  SkyResizeObserverService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyResizeObserverService, providedIn: 'any' });
2481
2493
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyResizeObserverService, decorators: [{
@@ -2485,13 +2497,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
2485
2497
  }]
2486
2498
  }], ctorParameters: function () { return [{ type: i0.NgZone }]; } });
2487
2499
 
2500
+ var _SkyResizeObserverMediaQueryService_breakpoints, _SkyResizeObserverMediaQueryService_currentBreakpointObservable, _SkyResizeObserverMediaQueryService_stopListening, _SkyResizeObserverMediaQueryService_target;
2488
2501
  /**
2489
2502
  * Acts like `SkyMediaQueryService` for a container element, emitting the same responsive breakpoints.
2490
2503
  */
2491
2504
  class SkyResizeObserverMediaQueryService {
2492
2505
  constructor(resizeObserverService) {
2493
2506
  this.resizeObserverService = resizeObserverService;
2494
- this._breakpoints = [
2507
+ _SkyResizeObserverMediaQueryService_breakpoints.set(this, [
2495
2508
  {
2496
2509
  check: (width) => width > 0 && width <= 767,
2497
2510
  name: SkyMediaBreakpoints.xs,
@@ -2508,11 +2521,12 @@ class SkyResizeObserverMediaQueryService {
2508
2521
  check: (width) => width > 1199,
2509
2522
  name: SkyMediaBreakpoints.lg,
2510
2523
  },
2511
- ];
2512
- this._currentBreakpointObservable = new ReplaySubject(1);
2513
- this._stopListening = new Subject();
2514
- this._stopListening.subscribe(() => {
2515
- this._target = undefined;
2524
+ ]);
2525
+ _SkyResizeObserverMediaQueryService_currentBreakpointObservable.set(this, new ReplaySubject(1));
2526
+ _SkyResizeObserverMediaQueryService_stopListening.set(this, new Subject());
2527
+ _SkyResizeObserverMediaQueryService_target.set(this, void 0);
2528
+ __classPrivateFieldGet(this, _SkyResizeObserverMediaQueryService_stopListening, "f").subscribe(() => {
2529
+ __classPrivateFieldSet(this, _SkyResizeObserverMediaQueryService_target, undefined, "f");
2516
2530
  this.updateBreakpoint(undefined);
2517
2531
  });
2518
2532
  }
@@ -2523,10 +2537,10 @@ class SkyResizeObserverMediaQueryService {
2523
2537
  return this._currentBreakpoint;
2524
2538
  }
2525
2539
  ngOnDestroy() {
2526
- this._stopListening.next();
2540
+ __classPrivateFieldGet(this, _SkyResizeObserverMediaQueryService_stopListening, "f").next();
2527
2541
  this._currentBreakpoint = undefined;
2528
- this._stopListening.complete();
2529
- this._currentBreakpointObservable.complete();
2542
+ __classPrivateFieldGet(this, _SkyResizeObserverMediaQueryService_stopListening, "f").complete();
2543
+ __classPrivateFieldGet(this, _SkyResizeObserverMediaQueryService_currentBreakpointObservable, "f").complete();
2530
2544
  }
2531
2545
  /**
2532
2546
  * @internal
@@ -2539,21 +2553,21 @@ class SkyResizeObserverMediaQueryService {
2539
2553
  * time. Any previous subscriptions will be unsubscribed when a new element is observed.
2540
2554
  */
2541
2555
  observe(element) {
2542
- if (this._target) {
2543
- if (this._target === element) {
2556
+ if (__classPrivateFieldGet(this, _SkyResizeObserverMediaQueryService_target, "f")) {
2557
+ if (__classPrivateFieldGet(this, _SkyResizeObserverMediaQueryService_target, "f") === element) {
2544
2558
  return this;
2545
2559
  }
2546
- this._stopListening.next();
2560
+ __classPrivateFieldGet(this, _SkyResizeObserverMediaQueryService_stopListening, "f").next();
2547
2561
  }
2548
- this._target = element;
2562
+ __classPrivateFieldSet(this, _SkyResizeObserverMediaQueryService_target, element, "f");
2549
2563
  this.checkWidth(element);
2550
2564
  this.resizeObserverService
2551
2565
  .observe(element)
2552
- .pipe(takeUntil(this._stopListening))
2566
+ .pipe(takeUntil(__classPrivateFieldGet(this, _SkyResizeObserverMediaQueryService_stopListening, "f")))
2553
2567
  .subscribe((value) => {
2554
2568
  const breakpoint = this.checkBreakpoint(value.contentRect.width);
2555
2569
  /* istanbul ignore else */
2556
- if (breakpoint !== this._currentBreakpoint) {
2570
+ if (breakpoint !== this.current) {
2557
2571
  this.updateBreakpoint(breakpoint);
2558
2572
  }
2559
2573
  });
@@ -2563,25 +2577,28 @@ class SkyResizeObserverMediaQueryService {
2563
2577
  * Stop watching the container element.
2564
2578
  */
2565
2579
  unobserve() {
2566
- this._stopListening.next();
2580
+ __classPrivateFieldGet(this, _SkyResizeObserverMediaQueryService_stopListening, "f").next();
2567
2581
  }
2568
2582
  /**
2569
2583
  * Subscribes to element size changes that cross breakpoints.
2570
2584
  */
2571
2585
  subscribe(listener) {
2572
- return this._currentBreakpointObservable
2573
- .pipe(takeUntil(this._stopListening))
2586
+ return __classPrivateFieldGet(this, _SkyResizeObserverMediaQueryService_currentBreakpointObservable, "f")
2587
+ .pipe(takeUntil(__classPrivateFieldGet(this, _SkyResizeObserverMediaQueryService_stopListening, "f")))
2574
2588
  .subscribe((value) => {
2575
2589
  listener(value);
2576
2590
  });
2577
2591
  }
2578
2592
  updateBreakpoint(breakpoint) {
2579
2593
  this._currentBreakpoint = breakpoint;
2580
- this._currentBreakpointObservable.next(breakpoint);
2594
+ __classPrivateFieldGet(this, _SkyResizeObserverMediaQueryService_currentBreakpointObservable, "f").next(breakpoint);
2581
2595
  }
2582
2596
  checkBreakpoint(width) {
2583
- var _a;
2584
- return (_a = this._breakpoints.find((breakpoint) => breakpoint.check(width))) === null || _a === void 0 ? void 0 : _a.name;
2597
+ const breakpoint = __classPrivateFieldGet(this, _SkyResizeObserverMediaQueryService_breakpoints, "f").find((breakpoint) => breakpoint.check(width));
2598
+ /* istanbul ignore else */
2599
+ if (breakpoint) {
2600
+ return breakpoint.name;
2601
+ }
2585
2602
  }
2586
2603
  checkWidth(element) {
2587
2604
  const width = element.nativeElement.offsetWidth || 0;
@@ -2592,6 +2609,7 @@ class SkyResizeObserverMediaQueryService {
2592
2609
  }
2593
2610
  }
2594
2611
  }
2612
+ _SkyResizeObserverMediaQueryService_breakpoints = new WeakMap(), _SkyResizeObserverMediaQueryService_currentBreakpointObservable = new WeakMap(), _SkyResizeObserverMediaQueryService_stopListening = new WeakMap(), _SkyResizeObserverMediaQueryService_target = new WeakMap();
2595
2613
  SkyResizeObserverMediaQueryService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyResizeObserverMediaQueryService, deps: [{ token: SkyResizeObserverService }], target: i0.ɵɵFactoryTarget.Injectable });
2596
2614
  SkyResizeObserverMediaQueryService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyResizeObserverMediaQueryService, providedIn: 'any' });
2597
2615
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyResizeObserverMediaQueryService, decorators: [{
@@ -2622,8 +2640,7 @@ class SkyScrollableHostService {
2622
2640
  /**
2623
2641
  * Returns an observable which emits the given element's current scrollable host
2624
2642
  * @param elementRef The element whose scrollable host is being requested
2625
- * @param completionObservable An observable which alerts the internal observers that they should complete
2626
- * @returns An observable which emits the current scrollable host
2643
+ * @returns An observable which emits the current scrollable host element.
2627
2644
  * @internal
2628
2645
  */
2629
2646
  watchScrollableHost(elementRef) {
@@ -2633,11 +2650,13 @@ class SkyScrollableHostService {
2633
2650
  return new Observable((subscriber) => {
2634
2651
  subscribers.push(subscriber);
2635
2652
  let scrollableHost = this.findScrollableHost(elementRef.nativeElement);
2653
+ // Setup mutation observers only once, for all subscribers.
2636
2654
  if (subscribers.length === 1) {
2637
2655
  parentMutationObserver = this.mutationObserverSvc.create(() => {
2638
2656
  const newScrollableHost = this.findScrollableHost(elementRef.nativeElement);
2657
+ // Reset observer if scrollable host changes.
2639
2658
  if (newScrollableHost !== scrollableHost &&
2640
- elementRef.nativeElement.offsetParent) {
2659
+ this.isElementVisible(elementRef)) {
2641
2660
  scrollableHost = newScrollableHost;
2642
2661
  this.observeForScrollableHostChanges(scrollableHost, parentMutationObserver);
2643
2662
  notifySubscribers(subscribers, scrollableHost);
@@ -2645,7 +2664,9 @@ class SkyScrollableHostService {
2645
2664
  });
2646
2665
  this.observeForScrollableHostChanges(scrollableHost, parentMutationObserver);
2647
2666
  documentHiddenElementMutationObserver = this.mutationObserverSvc.create(() => {
2648
- if (scrollableHost && !elementRef.nativeElement.offsetParent) {
2667
+ if (scrollableHost && !this.isElementVisible(elementRef)) {
2668
+ // If the scrollable host is not visible, set it to undefined and unsubscribe from its mutation changes.
2669
+ // Then, observe the document element so that a new scrollable host can be found.
2649
2670
  scrollableHost = undefined;
2650
2671
  this.observeForScrollableHostChanges(scrollableHost, parentMutationObserver);
2651
2672
  notifySubscribers(subscribers, scrollableHost);
@@ -2653,10 +2674,11 @@ class SkyScrollableHostService {
2653
2674
  });
2654
2675
  this.observeDocumentHiddenElementChanges(documentHiddenElementMutationObserver);
2655
2676
  }
2677
+ // Emit the scrollable host to the subscriber.
2656
2678
  subscriber.next(scrollableHost);
2679
+ // Teardown callback for the subscription.
2657
2680
  subscriber.add(() => {
2658
2681
  const subIndex = subscribers.indexOf(subscriber);
2659
- /* sanity check */
2660
2682
  /* istanbul ignore else */
2661
2683
  if (subIndex >= 0) {
2662
2684
  subscribers.splice(subIndex, 1);
@@ -2671,7 +2693,6 @@ class SkyScrollableHostService {
2671
2693
  /**
2672
2694
  * Returns an observable which emits whenever the element's scrollable host emits a scroll event. The observable will always emit the scroll events from the elements current scrollable host and will update based on any scrollable host changes. The observable will also emit once whenever the scrollable host changes.
2673
2695
  * @param elementRef The element whose scrollable host scroll events are being requested
2674
- * @param completionObservable An observable which alerts the internal observers that they should complete
2675
2696
  * @returns An observable which emits when the elements scrollable host is scrolled or is changed
2676
2697
  */
2677
2698
  watchScrollableHostScrollEvents(elementRef) {
@@ -2682,6 +2703,7 @@ class SkyScrollableHostService {
2682
2703
  let scrollEventSubscription;
2683
2704
  return new Observable((subscriber) => {
2684
2705
  subscribers.push(subscriber);
2706
+ // Setup mutation observers only once, for all subscribers.
2685
2707
  if (subscribers.length === 1) {
2686
2708
  scrollableHostSubscription = this.watchScrollableHost(elementRef).subscribe((newScrollableHost) => {
2687
2709
  newScrollableHostObservable.next();
@@ -2691,6 +2713,8 @@ class SkyScrollableHostService {
2691
2713
  }
2692
2714
  scrollableHost = newScrollableHost;
2693
2715
  newScrollableHostObservable = new Subject();
2716
+ // Only subscribe to scroll events if the host element is defined.
2717
+ /* istanbul ignore else */
2694
2718
  if (newScrollableHost) {
2695
2719
  scrollEventSubscription = fromEvent(newScrollableHost, 'scroll')
2696
2720
  .pipe(takeUntil(newScrollableHostObservable))
@@ -2700,9 +2724,9 @@ class SkyScrollableHostService {
2700
2724
  }
2701
2725
  });
2702
2726
  }
2727
+ // Teardown callback for the subscription.
2703
2728
  subscriber.add(() => {
2704
2729
  const subIndex = subscribers.indexOf(subscriber);
2705
- /* sanity check */
2706
2730
  /* istanbul ignore else */
2707
2731
  if (subIndex >= 0) {
2708
2732
  subscribers.splice(subIndex, 1);
@@ -2719,7 +2743,6 @@ class SkyScrollableHostService {
2719
2743
  const regex = /(auto|scroll)/;
2720
2744
  const windowObj = this.windowRef.nativeWindow;
2721
2745
  const bodyObj = windowObj.document.body;
2722
- /* Sanity check */
2723
2746
  if (!element) {
2724
2747
  return windowObj;
2725
2748
  }
@@ -2727,7 +2750,7 @@ class SkyScrollableHostService {
2727
2750
  let parent = element;
2728
2751
  do {
2729
2752
  parent = parent.parentNode;
2730
- /* Sanity check for if this function is called for an element which has been removed from the DOM */
2753
+ // Return `window` if the parent element has been removed from the DOM.
2731
2754
  if (!(parent instanceof HTMLElement)) {
2732
2755
  return windowObj;
2733
2756
  }
@@ -2750,22 +2773,20 @@ class SkyScrollableHostService {
2750
2773
  }
2751
2774
  observeForScrollableHostChanges(element, mutationObserver) {
2752
2775
  mutationObserver.disconnect();
2753
- if (element instanceof HTMLElement) {
2754
- mutationObserver.observe(element, {
2755
- attributes: true,
2756
- attributeFilter: ['class', 'style'],
2757
- childList: true,
2758
- subtree: true,
2759
- });
2760
- }
2761
- else {
2762
- mutationObserver.observe(document.documentElement, {
2763
- attributes: true,
2764
- attributeFilter: ['class', 'style'],
2765
- childList: true,
2766
- subtree: true,
2767
- });
2768
- }
2776
+ const target = element instanceof HTMLElement ? element : document.documentElement;
2777
+ mutationObserver.observe(target, {
2778
+ attributes: true,
2779
+ attributeFilter: ['class', 'style'],
2780
+ childList: true,
2781
+ subtree: true,
2782
+ });
2783
+ }
2784
+ /**
2785
+ * Determines if an element is "visible" in the DOM.
2786
+ * @see https://stackoverflow.com/a/11639664/6178885
2787
+ */
2788
+ isElementVisible(elementRef) {
2789
+ return elementRef.nativeElement.offsetParent;
2769
2790
  }
2770
2791
  }
2771
2792
  SkyScrollableHostService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyScrollableHostService, deps: [{ token: MutationObserverService }, { token: SkyAppWindowRef }], target: i0.ɵɵFactoryTarget.Injectable });