@skyux/core 4.8.1 → 4.9.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 (39) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/bundles/skyux-core.umd.js +155 -33
  3. package/bundles/skyux-core.umd.js.map +1 -1
  4. package/bundles/skyux-core.umd.min.js +1 -1
  5. package/bundles/skyux-core.umd.min.js.map +1 -1
  6. package/esm2015/modules/dock/dock.component.js +1 -1
  7. package/esm2015/modules/scrollable-host/scrollable-host.module.js +16 -0
  8. package/esm2015/modules/scrollable-host/scrollable-host.service.js +89 -0
  9. package/esm2015/modules/viewkeeper/viewkeeper-host-options.js +1 -1
  10. package/esm2015/modules/viewkeeper/viewkeeper-options.js +1 -1
  11. package/esm2015/modules/viewkeeper/viewkeeper.directive.js +35 -16
  12. package/esm2015/modules/viewkeeper/viewkeeper.js +16 -11
  13. package/esm2015/modules/viewkeeper/viewkeeper.module.js +5 -1
  14. package/esm2015/public_api.js +2 -1
  15. package/esm2015/skyux-core.js +2 -1
  16. package/esm5/modules/dock/dock.component.js +1 -1
  17. package/esm5/modules/scrollable-host/scrollable-host.module.js +19 -0
  18. package/esm5/modules/scrollable-host/scrollable-host.service.js +91 -0
  19. package/esm5/modules/viewkeeper/viewkeeper-host-options.js +1 -1
  20. package/esm5/modules/viewkeeper/viewkeeper-options.js +1 -1
  21. package/esm5/modules/viewkeeper/viewkeeper.directive.js +45 -25
  22. package/esm5/modules/viewkeeper/viewkeeper.js +16 -11
  23. package/esm5/modules/viewkeeper/viewkeeper.module.js +5 -1
  24. package/esm5/public_api.js +2 -1
  25. package/esm5/skyux-core.js +2 -1
  26. package/fesm2015/skyux-core.js +140 -26
  27. package/fesm2015/skyux-core.js.map +1 -1
  28. package/fesm5/skyux-core.js +155 -35
  29. package/fesm5/skyux-core.js.map +1 -1
  30. package/modules/scrollable-host/scrollable-host.module.d.ts +2 -0
  31. package/modules/scrollable-host/scrollable-host.service.d.ts +13 -0
  32. package/modules/viewkeeper/viewkeeper-host-options.d.ts +1 -0
  33. package/modules/viewkeeper/viewkeeper-options.d.ts +5 -0
  34. package/modules/viewkeeper/viewkeeper.d.ts +1 -0
  35. package/modules/viewkeeper/viewkeeper.directive.d.ts +4 -1
  36. package/package.json +1 -1
  37. package/public_api.d.ts +1 -0
  38. package/skyux-core.d.ts +1 -0
  39. package/skyux-core.metadata.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ # 4.9.0 (2021-11-02)
2
+
3
+ - Added the `SkyScrollableHostService` to be able to get and watch for an element's scrollable host. [#269](https://github.com/blackbaud/skyux-core/pull/269)
4
+ - Updated the viewkeeper directive to watch for scrollable hosts when positioning elements. [#269](https://github.com/blackbaud/skyux-core/pull/269)
5
+
1
6
  # 4.8.1 (2021-09-29)
2
7
 
3
8
  - Fixed the dock component to properly position elements when docked to the bottom of the screen and the `body` element does not fill the entire height of the viewport. [#258](https://github.com/blackbaud/skyux-core/pull/258)
@@ -1491,7 +1491,7 @@
1491
1491
  SkyDockDomAdapterService
1492
1492
  ],
1493
1493
  changeDetection: core.ChangeDetectionStrategy.OnPush,
1494
- styles: [":host{display:flex;flex-direction:column;width:100%}:host:not(.sky-dock-unbound){position:fixed;left:0;bottom:0;right:0}:host.sky-dock-sticky{position:sticky}"]
1494
+ styles: [":host{display:flex;flex-direction:column;width:100%}:host:not(.sky-dock-unbound){position:fixed;left:0;bottom:0;right:0}:host.sky-dock-sticky{position:-webkit-sticky;position:sticky}"]
1495
1495
  })
1496
1496
  ], SkyDockComponent);
1497
1497
  return SkyDockComponent;
@@ -2743,6 +2743,87 @@
2743
2743
  return SkyPercentPipeModule;
2744
2744
  }());
2745
2745
 
2746
+ var SkyScrollableHostService = /** @class */ (function () {
2747
+ function SkyScrollableHostService(mutationObserverSvc, windowRef) {
2748
+ this.mutationObserverSvc = mutationObserverSvc;
2749
+ this.windowRef = windowRef;
2750
+ }
2751
+ SkyScrollableHostService.prototype.getScrollabeHost = function (elementRef) {
2752
+ return this.findScrollableHost(elementRef.nativeElement);
2753
+ };
2754
+ SkyScrollableHostService.prototype.watchScrollableHost = function (elementRef, completionObservable) {
2755
+ var _this = this;
2756
+ var scrollableHost = this.findScrollableHost(elementRef.nativeElement);
2757
+ var behaviorSubject = new rxjs.BehaviorSubject(scrollableHost);
2758
+ var mutationObserver = this.mutationObserverSvc.create(function () {
2759
+ var newScrollableHost = _this.findScrollableHost(elementRef.nativeElement);
2760
+ if (newScrollableHost !== scrollableHost) {
2761
+ scrollableHost = newScrollableHost;
2762
+ _this.observeForScrollableHostChanges(scrollableHost, mutationObserver);
2763
+ behaviorSubject.next(scrollableHost);
2764
+ }
2765
+ });
2766
+ this.observeForScrollableHostChanges(scrollableHost, mutationObserver);
2767
+ completionObservable.pipe(operators.take(1)).subscribe(function () {
2768
+ mutationObserver.disconnect();
2769
+ });
2770
+ return behaviorSubject;
2771
+ };
2772
+ SkyScrollableHostService.prototype.findScrollableHost = function (element) {
2773
+ var regex = /(auto|scroll)/;
2774
+ var windowObj = this.windowRef.nativeWindow;
2775
+ var bodyObj = windowObj.document.body;
2776
+ /* Sanity check */
2777
+ if (!element) {
2778
+ return windowObj;
2779
+ }
2780
+ var style = windowObj.getComputedStyle(element);
2781
+ var parent = element;
2782
+ do {
2783
+ parent = parent.parentNode;
2784
+ /* Sanity check for if this function is called for an element which has been removed from the DOM */
2785
+ if (!(parent instanceof HTMLElement)) {
2786
+ return windowObj;
2787
+ }
2788
+ style = windowObj.getComputedStyle(parent);
2789
+ } while (!regex.test(style.overflow) &&
2790
+ !regex.test(style.overflowY) &&
2791
+ parent !== bodyObj);
2792
+ if (parent === bodyObj) {
2793
+ return windowObj;
2794
+ }
2795
+ return parent;
2796
+ };
2797
+ SkyScrollableHostService.prototype.observeForScrollableHostChanges = function (element, mutationObserver) {
2798
+ mutationObserver.disconnect();
2799
+ if (element instanceof HTMLElement) {
2800
+ mutationObserver.observe(element, {
2801
+ attributes: true,
2802
+ attributeFilter: ['class', 'style.overflow', 'style.overflow-y'],
2803
+ subtree: true
2804
+ });
2805
+ }
2806
+ else {
2807
+ mutationObserver.observe(document.documentElement, {
2808
+ attributes: true,
2809
+ attributeFilter: ['class', 'style.overflow', 'style.overflow-y'],
2810
+ subtree: true
2811
+ });
2812
+ }
2813
+ };
2814
+ SkyScrollableHostService.ctorParameters = function () { return [
2815
+ { type: MutationObserverService },
2816
+ { type: SkyAppWindowRef }
2817
+ ]; };
2818
+ SkyScrollableHostService.ɵprov = core.ɵɵdefineInjectable({ factory: function SkyScrollableHostService_Factory() { return new SkyScrollableHostService(core.ɵɵinject(MutationObserverService), core.ɵɵinject(SkyAppWindowRef)); }, token: SkyScrollableHostService, providedIn: "root" });
2819
+ SkyScrollableHostService = __decorate([
2820
+ core.Injectable({
2821
+ providedIn: 'root'
2822
+ })
2823
+ ], SkyScrollableHostService);
2824
+ return SkyScrollableHostService;
2825
+ }());
2826
+
2746
2827
  /**
2747
2828
  * Provides a method for setting a formatted title on the current window.
2748
2829
  */
@@ -2810,11 +2891,12 @@
2810
2891
  nextIdIndex = (nextIdIndex || 0) + 1;
2811
2892
  return 'viewkeeper-' + nextIdIndex;
2812
2893
  }
2813
- function getOffset(el) {
2894
+ function getOffset(el, scrollableHost) {
2814
2895
  var rect = el.getBoundingClientRect();
2896
+ var parent = scrollableHost ? scrollableHost : document.documentElement;
2815
2897
  return {
2816
- top: rect.top + document.documentElement.scrollTop,
2817
- left: rect.left + document.documentElement.scrollLeft
2898
+ top: rect.top + parent.scrollTop,
2899
+ left: rect.left + parent.scrollLeft
2818
2900
  };
2819
2901
  }
2820
2902
  function px(value) {
@@ -2851,6 +2933,7 @@
2851
2933
  this.id = nextId();
2852
2934
  this.el = options.el;
2853
2935
  this.boundaryEl = options.boundaryEl;
2936
+ this.scrollableHost = options.scrollableHost;
2854
2937
  this.verticalOffset = options.verticalOffset || 0;
2855
2938
  this.verticalOffsetEl = options.verticalOffsetEl;
2856
2939
  this.viewportMarginTop = options.viewportMarginTop || 0;
@@ -2858,7 +2941,7 @@
2858
2941
  if (this.verticalOffsetEl) {
2859
2942
  this.verticalOffsetEl.addEventListener(EVT_AFTER_VIEWKEEPER_SYNC, this.syncElPositionHandler);
2860
2943
  }
2861
- window.addEventListener('scroll', this.syncElPositionHandler);
2944
+ window.addEventListener('scroll', this.syncElPositionHandler, true);
2862
2945
  window.addEventListener('resize', this.syncElPositionHandler);
2863
2946
  window.addEventListener('orientationchange', this.syncElPositionHandler);
2864
2947
  ensureStyleEl();
@@ -2886,7 +2969,7 @@
2886
2969
  };
2887
2970
  SkyViewkeeper.prototype.destroy = function () {
2888
2971
  if (!this.isDestroyed) {
2889
- window.removeEventListener('scroll', this.syncElPositionHandler);
2972
+ window.removeEventListener('scroll', this.syncElPositionHandler, true);
2890
2973
  window.removeEventListener('resize', this.syncElPositionHandler);
2891
2974
  window.removeEventListener('orientationchange', this.syncElPositionHandler);
2892
2975
  this.unfixEl();
@@ -2924,16 +3007,19 @@
2924
3007
  var verticalOffsetElTop = parseInt(verticalOffsetElTopStyle, 10) || 0;
2925
3008
  offset += (this.verticalOffsetEl.offsetHeight + verticalOffsetElTop);
2926
3009
  }
3010
+ else if (this.scrollableHost) {
3011
+ offset += this.scrollableHost.getBoundingClientRect().top;
3012
+ }
2927
3013
  return offset;
2928
3014
  };
2929
3015
  SkyViewkeeper.prototype.shouldFixEl = function (boundaryInfo, verticalOffset) {
2930
3016
  var anchorTop;
2931
3017
  var doFixEl;
2932
3018
  if (boundaryInfo.spacerEl) {
2933
- anchorTop = getOffset(boundaryInfo.spacerEl).top;
3019
+ anchorTop = getOffset(boundaryInfo.spacerEl, this.scrollableHost).top;
2934
3020
  }
2935
3021
  else {
2936
- anchorTop = getOffset(this.el).top;
3022
+ anchorTop = getOffset(this.el, this.scrollableHost).top;
2937
3023
  }
2938
3024
  doFixEl = boundaryInfo.scrollTop + verticalOffset + this.viewportMarginTop > anchorTop;
2939
3025
  return doFixEl;
@@ -2992,11 +3078,11 @@
2992
3078
  var spacerId = this.getSpacerId();
2993
3079
  var spacerEl = document.getElementById(spacerId);
2994
3080
  var boundaryEl = this.boundaryEl;
2995
- var boundaryOffset = getOffset(boundaryEl);
3081
+ var boundaryOffset = getOffset(boundaryEl, this.scrollableHost);
2996
3082
  var boundaryTop = boundaryOffset.top;
2997
3083
  var boundaryBottom = boundaryTop + boundaryEl.getBoundingClientRect().height;
2998
- var scrollLeft = document.documentElement.scrollLeft;
2999
- var scrollTop = document.documentElement.scrollTop;
3084
+ var scrollLeft = this.scrollableHost ? this.scrollableHost.scrollLeft : document.documentElement.scrollLeft;
3085
+ var scrollTop = this.scrollableHost ? this.scrollableHost.scrollTop : document.documentElement.scrollTop;
3000
3086
  var elHeight = getHeightWithMargin(this.el);
3001
3087
  return {
3002
3088
  boundaryBottom: boundaryBottom,
@@ -3045,11 +3131,13 @@
3045
3131
  }());
3046
3132
 
3047
3133
  var SkyViewkeeperDirective = /** @class */ (function () {
3048
- function SkyViewkeeperDirective(el, mutationObserverSvc, viewkeeperSvc) {
3134
+ function SkyViewkeeperDirective(el, mutationObserverSvc, viewkeeperSvc, scrollableHostService) {
3049
3135
  this.el = el;
3050
3136
  this.mutationObserverSvc = mutationObserverSvc;
3051
3137
  this.viewkeeperSvc = viewkeeperSvc;
3138
+ this.scrollableHostService = scrollableHostService;
3052
3139
  this.viewkeepers = [];
3140
+ this.scrollableHostWatchUnsubscribe = undefined;
3053
3141
  }
3054
3142
  Object.defineProperty(SkyViewkeeperDirective.prototype, "skyViewkeeper", {
3055
3143
  get: function () {
@@ -3130,37 +3218,51 @@
3130
3218
  return false;
3131
3219
  };
3132
3220
  SkyViewkeeperDirective.prototype.detectElements = function () {
3133
- var e_3, _a;
3221
+ var _this = this;
3134
3222
  var viewkeeperEls = this.getViewkeeperEls();
3135
3223
  if (this.viewkeeperElsChanged(viewkeeperEls)) {
3136
- this.destroyViewkeepers();
3137
- var previousViewkeeperEl = void 0;
3138
- try {
3139
- for (var viewkeeperEls_1 = __values(viewkeeperEls), viewkeeperEls_1_1 = viewkeeperEls_1.next(); !viewkeeperEls_1_1.done; viewkeeperEls_1_1 = viewkeeperEls_1.next()) {
3140
- var viewkeeperEl = viewkeeperEls_1_1.value;
3141
- this.viewkeepers.push(this.viewkeeperSvc.create({
3142
- boundaryEl: this.el.nativeElement,
3143
- el: viewkeeperEl,
3144
- setWidth: true,
3145
- verticalOffsetEl: previousViewkeeperEl
3146
- }));
3147
- previousViewkeeperEl = viewkeeperEl;
3148
- }
3224
+ if (this.scrollableHostWatchUnsubscribe) {
3225
+ this.scrollableHostWatchUnsubscribe.next();
3226
+ this.scrollableHostWatchUnsubscribe = new rxjs.Subject();
3149
3227
  }
3150
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
3151
- finally {
3228
+ else {
3229
+ this.scrollableHostWatchUnsubscribe = new rxjs.Subject();
3230
+ }
3231
+ this.scrollableHostService.watchScrollableHost(this.el, this.scrollableHostWatchUnsubscribe)
3232
+ .pipe(operators.takeUntil(this.scrollableHostWatchUnsubscribe))
3233
+ .subscribe(function (scrollableHost) {
3234
+ var e_3, _a;
3235
+ _this.destroyViewkeepers();
3236
+ var previousViewkeeperEl;
3152
3237
  try {
3153
- if (viewkeeperEls_1_1 && !viewkeeperEls_1_1.done && (_a = viewkeeperEls_1.return)) _a.call(viewkeeperEls_1);
3238
+ for (var viewkeeperEls_1 = __values(viewkeeperEls), viewkeeperEls_1_1 = viewkeeperEls_1.next(); !viewkeeperEls_1_1.done; viewkeeperEls_1_1 = viewkeeperEls_1.next()) {
3239
+ var viewkeeperEl = viewkeeperEls_1_1.value;
3240
+ _this.viewkeepers.push(_this.viewkeeperSvc.create({
3241
+ boundaryEl: _this.el.nativeElement,
3242
+ scrollableHost: scrollableHost instanceof HTMLElement ? scrollableHost : undefined,
3243
+ el: viewkeeperEl,
3244
+ setWidth: true,
3245
+ verticalOffsetEl: previousViewkeeperEl
3246
+ }));
3247
+ previousViewkeeperEl = viewkeeperEl;
3248
+ }
3154
3249
  }
3155
- finally { if (e_3) throw e_3.error; }
3156
- }
3250
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
3251
+ finally {
3252
+ try {
3253
+ if (viewkeeperEls_1_1 && !viewkeeperEls_1_1.done && (_a = viewkeeperEls_1.return)) _a.call(viewkeeperEls_1);
3254
+ }
3255
+ finally { if (e_3) throw e_3.error; }
3256
+ }
3257
+ });
3157
3258
  this.currentViewkeeperEls = viewkeeperEls;
3158
3259
  }
3159
3260
  };
3160
3261
  SkyViewkeeperDirective.ctorParameters = function () { return [
3161
3262
  { type: core.ElementRef },
3162
3263
  { type: MutationObserverService },
3163
- { type: SkyViewkeeperService }
3264
+ { type: SkyViewkeeperService },
3265
+ { type: SkyScrollableHostService, decorators: [{ type: core.Optional }] }
3164
3266
  ]; };
3165
3267
  __decorate([
3166
3268
  core.Input()
@@ -3168,11 +3270,26 @@
3168
3270
  SkyViewkeeperDirective = __decorate([
3169
3271
  core.Directive({
3170
3272
  selector: '[skyViewkeeper]'
3171
- })
3273
+ }),
3274
+ __param(3, core.Optional())
3172
3275
  ], SkyViewkeeperDirective);
3173
3276
  return SkyViewkeeperDirective;
3174
3277
  }());
3175
3278
 
3279
+ var SkyScrollableHostModule = /** @class */ (function () {
3280
+ function SkyScrollableHostModule() {
3281
+ }
3282
+ SkyScrollableHostModule = __decorate([
3283
+ core.NgModule({
3284
+ providers: [
3285
+ MutationObserverService,
3286
+ SkyAppWindowRef
3287
+ ]
3288
+ })
3289
+ ], SkyScrollableHostModule);
3290
+ return SkyScrollableHostModule;
3291
+ }());
3292
+
3176
3293
  var SkyViewkeeperModule = /** @class */ (function () {
3177
3294
  function SkyViewkeeperModule() {
3178
3295
  }
@@ -3181,6 +3298,9 @@
3181
3298
  declarations: [
3182
3299
  SkyViewkeeperDirective
3183
3300
  ],
3301
+ imports: [
3302
+ SkyScrollableHostModule
3303
+ ],
3184
3304
  exports: [
3185
3305
  SkyViewkeeperDirective
3186
3306
  ],
@@ -3221,6 +3341,7 @@
3221
3341
  exports.SkyOverlayService = SkyOverlayService;
3222
3342
  exports.SkyPercentPipe = SkyPercentPipe;
3223
3343
  exports.SkyPercentPipeModule = SkyPercentPipeModule;
3344
+ exports.SkyScrollableHostService = SkyScrollableHostService;
3224
3345
  exports.SkyUIConfigService = SkyUIConfigService;
3225
3346
  exports.SkyViewkeeperHostOptions = SkyViewkeeperHostOptions;
3226
3347
  exports.SkyViewkeeperModule = SkyViewkeeperModule;
@@ -3236,6 +3357,7 @@
3236
3357
  exports.ɵh = SkyOverlayContext;
3237
3358
  exports.ɵi = SkyOverlayAdapterService;
3238
3359
  exports.ɵj = SkyViewkeeperDirective;
3360
+ exports.ɵk = SkyScrollableHostModule;
3239
3361
 
3240
3362
  Object.defineProperty(exports, '__esModule', { value: true });
3241
3363