@angular/cdk
Version:
Angular Material Component Development Kit
1,394 lines (1,381 loc) • 48.3 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, forwardRef, Directive, Input, inject, NgZone, RendererFactory2, Injectable, ElementRef, Renderer2, DOCUMENT, ChangeDetectorRef, signal, Injector, effect, ApplicationRef, DestroyRef, untracked, afterNextRender, booleanAttribute, Component, ViewEncapsulation, ChangeDetectionStrategy, Output, ViewChild, ViewContainerRef, TemplateRef, IterableDiffers, NgModule } from '@angular/core';
import { Subject, of, Observable, Subscription, animationFrameScheduler, asapScheduler, isObservable } from 'rxjs';
import { distinctUntilChanged, auditTime, filter, startWith, takeUntil, pairwise, switchMap, shareReplay } from 'rxjs/operators';
import { coerceNumberProperty, coerceElement } from './_element-chunk.mjs';
import { Platform } from './_platform-chunk.mjs';
import { Directionality } from './_directionality-chunk.mjs';
import { getRtlScrollAxisType, RtlScrollAxisType, supportsScrollBehavior } from './_scrolling-chunk.mjs';
import { BidiModule } from './bidi.mjs';
export { Dir as ɵɵDir } from './bidi.mjs';
import { _VIEW_REPEATER_STRATEGY, ArrayDataSource, _RecycleViewRepeaterStrategy } from './_recycle-view-repeater-strategy-chunk.mjs';
import { isDataSource } from './_data-source-chunk.mjs';
import '@angular/common';
const VIRTUAL_SCROLL_STRATEGY = new InjectionToken('VIRTUAL_SCROLL_STRATEGY');
class FixedSizeVirtualScrollStrategy {
_scrolledIndexChange = new Subject();
scrolledIndexChange = this._scrolledIndexChange.pipe(distinctUntilChanged());
_viewport = null;
_itemSize;
_minBufferPx;
_maxBufferPx;
constructor(itemSize, minBufferPx, maxBufferPx) {
this._itemSize = itemSize;
this._minBufferPx = minBufferPx;
this._maxBufferPx = maxBufferPx;
}
attach(viewport) {
this._viewport = viewport;
this._updateTotalContentSize();
this._updateRenderedRange();
}
detach() {
this._scrolledIndexChange.complete();
this._viewport = null;
}
updateItemAndBufferSize(itemSize, minBufferPx, maxBufferPx) {
if (maxBufferPx < minBufferPx && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw Error('CDK virtual scroll: maxBufferPx must be greater than or equal to minBufferPx');
}
this._itemSize = itemSize;
this._minBufferPx = minBufferPx;
this._maxBufferPx = maxBufferPx;
this._updateTotalContentSize();
this._updateRenderedRange();
}
onContentScrolled() {
this._updateRenderedRange();
}
onDataLengthChanged() {
this._updateTotalContentSize();
this._updateRenderedRange();
}
onContentRendered() {}
onRenderedOffsetChanged() {}
scrollToIndex(index, behavior) {
if (this._viewport) {
this._viewport.scrollToOffset(index * this._itemSize, behavior);
}
}
_updateTotalContentSize() {
if (!this._viewport) {
return;
}
this._viewport.setTotalContentSize(this._viewport.getDataLength() * this._itemSize);
}
_updateRenderedRange() {
if (!this._viewport) {
return;
}
const renderedRange = this._viewport.getRenderedRange();
const newRange = {
start: renderedRange.start,
end: renderedRange.end
};
const viewportSize = this._viewport.getViewportSize();
const dataLength = this._viewport.getDataLength();
let scrollOffset = this._viewport.measureScrollOffset();
let firstVisibleIndex = this._itemSize > 0 ? scrollOffset / this._itemSize : 0;
if (newRange.end > dataLength) {
const maxVisibleItems = Math.ceil(viewportSize / this._itemSize);
const newVisibleIndex = Math.max(0, Math.min(firstVisibleIndex, dataLength - maxVisibleItems));
if (firstVisibleIndex != newVisibleIndex) {
firstVisibleIndex = newVisibleIndex;
scrollOffset = newVisibleIndex * this._itemSize;
newRange.start = Math.floor(firstVisibleIndex);
}
newRange.end = Math.max(0, Math.min(dataLength, newRange.start + maxVisibleItems));
}
const startBuffer = scrollOffset - newRange.start * this._itemSize;
if (startBuffer < this._minBufferPx && newRange.start != 0) {
const expandStart = Math.ceil((this._maxBufferPx - startBuffer) / this._itemSize);
newRange.start = Math.max(0, newRange.start - expandStart);
newRange.end = Math.min(dataLength, Math.ceil(firstVisibleIndex + (viewportSize + this._minBufferPx) / this._itemSize));
} else {
const endBuffer = newRange.end * this._itemSize - (scrollOffset + viewportSize);
if (endBuffer < this._minBufferPx && newRange.end != dataLength) {
const expandEnd = Math.ceil((this._maxBufferPx - endBuffer) / this._itemSize);
if (expandEnd > 0) {
newRange.end = Math.min(dataLength, newRange.end + expandEnd);
newRange.start = Math.max(0, Math.floor(firstVisibleIndex - this._minBufferPx / this._itemSize));
}
}
}
this._viewport.setRenderedRange(newRange);
this._viewport.setRenderedContentOffset(Math.round(this._itemSize * newRange.start));
this._scrolledIndexChange.next(Math.floor(firstVisibleIndex));
}
}
function _fixedSizeVirtualScrollStrategyFactory(fixedSizeDir) {
return fixedSizeDir._scrollStrategy;
}
class CdkFixedSizeVirtualScroll {
get itemSize() {
return this._itemSize;
}
set itemSize(value) {
this._itemSize = coerceNumberProperty(value);
}
_itemSize = 20;
get minBufferPx() {
return this._minBufferPx;
}
set minBufferPx(value) {
this._minBufferPx = coerceNumberProperty(value);
}
_minBufferPx = 100;
get maxBufferPx() {
return this._maxBufferPx;
}
set maxBufferPx(value) {
this._maxBufferPx = coerceNumberProperty(value);
}
_maxBufferPx = 200;
_scrollStrategy = new FixedSizeVirtualScrollStrategy(this.itemSize, this.minBufferPx, this.maxBufferPx);
ngOnChanges() {
this._scrollStrategy.updateItemAndBufferSize(this.itemSize, this.minBufferPx, this.maxBufferPx);
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkFixedSizeVirtualScroll,
deps: [],
target: i0.ɵɵFactoryTarget.Directive
});
static ɵdir = i0.ɵɵngDeclareDirective({
minVersion: "14.0.0",
version: "21.0.0",
type: CdkFixedSizeVirtualScroll,
isStandalone: true,
selector: "cdk-virtual-scroll-viewport[itemSize]",
inputs: {
itemSize: "itemSize",
minBufferPx: "minBufferPx",
maxBufferPx: "maxBufferPx"
},
providers: [{
provide: VIRTUAL_SCROLL_STRATEGY,
useFactory: _fixedSizeVirtualScrollStrategyFactory,
deps: [forwardRef(() => CdkFixedSizeVirtualScroll)]
}],
usesOnChanges: true,
ngImport: i0
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkFixedSizeVirtualScroll,
decorators: [{
type: Directive,
args: [{
selector: 'cdk-virtual-scroll-viewport[itemSize]',
providers: [{
provide: VIRTUAL_SCROLL_STRATEGY,
useFactory: _fixedSizeVirtualScrollStrategyFactory,
deps: [forwardRef(() => CdkFixedSizeVirtualScroll)]
}]
}]
}],
propDecorators: {
itemSize: [{
type: Input
}],
minBufferPx: [{
type: Input
}],
maxBufferPx: [{
type: Input
}]
}
});
const DEFAULT_SCROLL_TIME = 20;
class ScrollDispatcher {
_ngZone = inject(NgZone);
_platform = inject(Platform);
_renderer = inject(RendererFactory2).createRenderer(null, null);
_cleanupGlobalListener;
constructor() {}
_scrolled = new Subject();
_scrolledCount = 0;
scrollContainers = new Map();
register(scrollable) {
if (!this.scrollContainers.has(scrollable)) {
this.scrollContainers.set(scrollable, scrollable.elementScrolled().subscribe(() => this._scrolled.next(scrollable)));
}
}
deregister(scrollable) {
const scrollableReference = this.scrollContainers.get(scrollable);
if (scrollableReference) {
scrollableReference.unsubscribe();
this.scrollContainers.delete(scrollable);
}
}
scrolled(auditTimeInMs = DEFAULT_SCROLL_TIME) {
if (!this._platform.isBrowser) {
return of();
}
return new Observable(observer => {
if (!this._cleanupGlobalListener) {
this._cleanupGlobalListener = this._ngZone.runOutsideAngular(() => this._renderer.listen('document', 'scroll', () => this._scrolled.next()));
}
const subscription = auditTimeInMs > 0 ? this._scrolled.pipe(auditTime(auditTimeInMs)).subscribe(observer) : this._scrolled.subscribe(observer);
this._scrolledCount++;
return () => {
subscription.unsubscribe();
this._scrolledCount--;
if (!this._scrolledCount) {
this._cleanupGlobalListener?.();
this._cleanupGlobalListener = undefined;
}
};
});
}
ngOnDestroy() {
this._cleanupGlobalListener?.();
this._cleanupGlobalListener = undefined;
this.scrollContainers.forEach((_, container) => this.deregister(container));
this._scrolled.complete();
}
ancestorScrolled(elementOrElementRef, auditTimeInMs) {
const ancestors = this.getAncestorScrollContainers(elementOrElementRef);
return this.scrolled(auditTimeInMs).pipe(filter(target => !target || ancestors.indexOf(target) > -1));
}
getAncestorScrollContainers(elementOrElementRef) {
const scrollingContainers = [];
this.scrollContainers.forEach((_subscription, scrollable) => {
if (this._scrollableContainsElement(scrollable, elementOrElementRef)) {
scrollingContainers.push(scrollable);
}
});
return scrollingContainers;
}
_scrollableContainsElement(scrollable, elementOrElementRef) {
let element = coerceElement(elementOrElementRef);
let scrollableElement = scrollable.getElementRef().nativeElement;
do {
if (element == scrollableElement) {
return true;
}
} while (element = element.parentElement);
return false;
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: ScrollDispatcher,
deps: [],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: ScrollDispatcher,
providedIn: 'root'
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: ScrollDispatcher,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}],
ctorParameters: () => []
});
class CdkScrollable {
elementRef = inject(ElementRef);
scrollDispatcher = inject(ScrollDispatcher);
ngZone = inject(NgZone);
dir = inject(Directionality, {
optional: true
});
_scrollElement = this.elementRef.nativeElement;
_destroyed = new Subject();
_renderer = inject(Renderer2);
_cleanupScroll;
_elementScrolled = new Subject();
constructor() {}
ngOnInit() {
this._cleanupScroll = this.ngZone.runOutsideAngular(() => this._renderer.listen(this._scrollElement, 'scroll', event => this._elementScrolled.next(event)));
this.scrollDispatcher.register(this);
}
ngOnDestroy() {
this._cleanupScroll?.();
this._elementScrolled.complete();
this.scrollDispatcher.deregister(this);
this._destroyed.next();
this._destroyed.complete();
}
elementScrolled() {
return this._elementScrolled;
}
getElementRef() {
return this.elementRef;
}
scrollTo(options) {
const el = this.elementRef.nativeElement;
const isRtl = this.dir && this.dir.value == 'rtl';
if (options.left == null) {
options.left = isRtl ? options.end : options.start;
}
if (options.right == null) {
options.right = isRtl ? options.start : options.end;
}
if (options.bottom != null) {
options.top = el.scrollHeight - el.clientHeight - options.bottom;
}
if (isRtl && getRtlScrollAxisType() != RtlScrollAxisType.NORMAL) {
if (options.left != null) {
options.right = el.scrollWidth - el.clientWidth - options.left;
}
if (getRtlScrollAxisType() == RtlScrollAxisType.INVERTED) {
options.left = options.right;
} else if (getRtlScrollAxisType() == RtlScrollAxisType.NEGATED) {
options.left = options.right ? -options.right : options.right;
}
} else {
if (options.right != null) {
options.left = el.scrollWidth - el.clientWidth - options.right;
}
}
this._applyScrollToOptions(options);
}
_applyScrollToOptions(options) {
const el = this.elementRef.nativeElement;
if (supportsScrollBehavior()) {
el.scrollTo(options);
} else {
if (options.top != null) {
el.scrollTop = options.top;
}
if (options.left != null) {
el.scrollLeft = options.left;
}
}
}
measureScrollOffset(from) {
const LEFT = 'left';
const RIGHT = 'right';
const el = this.elementRef.nativeElement;
if (from == 'top') {
return el.scrollTop;
}
if (from == 'bottom') {
return el.scrollHeight - el.clientHeight - el.scrollTop;
}
const isRtl = this.dir && this.dir.value == 'rtl';
if (from == 'start') {
from = isRtl ? RIGHT : LEFT;
} else if (from == 'end') {
from = isRtl ? LEFT : RIGHT;
}
if (isRtl && getRtlScrollAxisType() == RtlScrollAxisType.INVERTED) {
if (from == LEFT) {
return el.scrollWidth - el.clientWidth - el.scrollLeft;
} else {
return el.scrollLeft;
}
} else if (isRtl && getRtlScrollAxisType() == RtlScrollAxisType.NEGATED) {
if (from == LEFT) {
return el.scrollLeft + el.scrollWidth - el.clientWidth;
} else {
return -el.scrollLeft;
}
} else {
if (from == LEFT) {
return el.scrollLeft;
} else {
return el.scrollWidth - el.clientWidth - el.scrollLeft;
}
}
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkScrollable,
deps: [],
target: i0.ɵɵFactoryTarget.Directive
});
static ɵdir = i0.ɵɵngDeclareDirective({
minVersion: "14.0.0",
version: "21.0.0",
type: CdkScrollable,
isStandalone: true,
selector: "[cdk-scrollable], [cdkScrollable]",
ngImport: i0
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkScrollable,
decorators: [{
type: Directive,
args: [{
selector: '[cdk-scrollable], [cdkScrollable]'
}]
}],
ctorParameters: () => []
});
const DEFAULT_RESIZE_TIME = 20;
class ViewportRuler {
_platform = inject(Platform);
_listeners;
_viewportSize;
_change = new Subject();
_document = inject(DOCUMENT);
constructor() {
const ngZone = inject(NgZone);
const renderer = inject(RendererFactory2).createRenderer(null, null);
ngZone.runOutsideAngular(() => {
if (this._platform.isBrowser) {
const changeListener = event => this._change.next(event);
this._listeners = [renderer.listen('window', 'resize', changeListener), renderer.listen('window', 'orientationchange', changeListener)];
}
this.change().subscribe(() => this._viewportSize = null);
});
}
ngOnDestroy() {
this._listeners?.forEach(cleanup => cleanup());
this._change.complete();
}
getViewportSize() {
if (!this._viewportSize) {
this._updateViewportSize();
}
const output = {
width: this._viewportSize.width,
height: this._viewportSize.height
};
if (!this._platform.isBrowser) {
this._viewportSize = null;
}
return output;
}
getViewportRect() {
const scrollPosition = this.getViewportScrollPosition();
const {
width,
height
} = this.getViewportSize();
return {
top: scrollPosition.top,
left: scrollPosition.left,
bottom: scrollPosition.top + height,
right: scrollPosition.left + width,
height,
width
};
}
getViewportScrollPosition() {
if (!this._platform.isBrowser) {
return {
top: 0,
left: 0
};
}
const document = this._document;
const window = this._getWindow();
const documentElement = document.documentElement;
const documentRect = documentElement.getBoundingClientRect();
const top = -documentRect.top || document.body.scrollTop || window.scrollY || documentElement.scrollTop || 0;
const left = -documentRect.left || document.body.scrollLeft || window.scrollX || documentElement.scrollLeft || 0;
return {
top,
left
};
}
change(throttleTime = DEFAULT_RESIZE_TIME) {
return throttleTime > 0 ? this._change.pipe(auditTime(throttleTime)) : this._change;
}
_getWindow() {
return this._document.defaultView || window;
}
_updateViewportSize() {
const window = this._getWindow();
this._viewportSize = this._platform.isBrowser ? {
width: window.innerWidth,
height: window.innerHeight
} : {
width: 0,
height: 0
};
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: ViewportRuler,
deps: [],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: ViewportRuler,
providedIn: 'root'
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: ViewportRuler,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}],
ctorParameters: () => []
});
const VIRTUAL_SCROLLABLE = new InjectionToken('VIRTUAL_SCROLLABLE');
class CdkVirtualScrollable extends CdkScrollable {
constructor() {
super();
}
measureViewportSize(orientation) {
const viewportEl = this.elementRef.nativeElement;
return orientation === 'horizontal' ? viewportEl.clientWidth : viewportEl.clientHeight;
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkVirtualScrollable,
deps: [],
target: i0.ɵɵFactoryTarget.Directive
});
static ɵdir = i0.ɵɵngDeclareDirective({
minVersion: "14.0.0",
version: "21.0.0",
type: CdkVirtualScrollable,
isStandalone: true,
usesInheritance: true,
ngImport: i0
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkVirtualScrollable,
decorators: [{
type: Directive
}],
ctorParameters: () => []
});
function rangesEqual(r1, r2) {
return r1.start == r2.start && r1.end == r2.end;
}
const SCROLL_SCHEDULER = typeof requestAnimationFrame !== 'undefined' ? animationFrameScheduler : asapScheduler;
class CdkVirtualScrollViewport extends CdkVirtualScrollable {
elementRef = inject(ElementRef);
_changeDetectorRef = inject(ChangeDetectorRef);
_scrollStrategy = inject(VIRTUAL_SCROLL_STRATEGY, {
optional: true
});
scrollable = inject(VIRTUAL_SCROLLABLE, {
optional: true
});
_platform = inject(Platform);
_detachedSubject = new Subject();
_renderedRangeSubject = new Subject();
get orientation() {
return this._orientation;
}
set orientation(orientation) {
if (this._orientation !== orientation) {
this._orientation = orientation;
this._calculateSpacerSize();
}
}
_orientation = 'vertical';
appendOnly = false;
scrolledIndexChange = new Observable(observer => this._scrollStrategy.scrolledIndexChange.subscribe(index => Promise.resolve().then(() => this.ngZone.run(() => observer.next(index)))));
_contentWrapper;
renderedRangeStream = this._renderedRangeSubject;
_totalContentSize = 0;
_totalContentWidth = signal('', ...(ngDevMode ? [{
debugName: "_totalContentWidth"
}] : []));
_totalContentHeight = signal('', ...(ngDevMode ? [{
debugName: "_totalContentHeight"
}] : []));
_renderedContentTransform;
_renderedRange = {
start: 0,
end: 0
};
_dataLength = 0;
_viewportSize = 0;
_forOf;
_renderedContentOffset = 0;
_renderedContentOffsetNeedsRewrite = false;
_changeDetectionNeeded = signal(false, ...(ngDevMode ? [{
debugName: "_changeDetectionNeeded"
}] : []));
_runAfterChangeDetection = [];
_viewportChanges = Subscription.EMPTY;
_injector = inject(Injector);
_isDestroyed = false;
constructor() {
super();
const viewportRuler = inject(ViewportRuler);
if (!this._scrollStrategy && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw Error('Error: cdk-virtual-scroll-viewport requires the "itemSize" property to be set.');
}
this._viewportChanges = viewportRuler.change().subscribe(() => {
this.checkViewportSize();
});
if (!this.scrollable) {
this.elementRef.nativeElement.classList.add('cdk-virtual-scrollable');
this.scrollable = this;
}
const ref = effect(() => {
if (this._changeDetectionNeeded()) {
this._doChangeDetection();
}
}, ...(ngDevMode ? [{
debugName: "ref",
injector: inject(ApplicationRef).injector
}] : [{
injector: inject(ApplicationRef).injector
}]));
inject(DestroyRef).onDestroy(() => void ref.destroy());
}
ngOnInit() {
if (!this._platform.isBrowser) {
return;
}
if (this.scrollable === this) {
super.ngOnInit();
}
this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => {
this._measureViewportSize();
this._scrollStrategy.attach(this);
this.scrollable.elementScrolled().pipe(startWith(null), auditTime(0, SCROLL_SCHEDULER), takeUntil(this._destroyed)).subscribe(() => this._scrollStrategy.onContentScrolled());
this._markChangeDetectionNeeded();
}));
}
ngOnDestroy() {
this.detach();
this._scrollStrategy.detach();
this._renderedRangeSubject.complete();
this._detachedSubject.complete();
this._viewportChanges.unsubscribe();
this._isDestroyed = true;
super.ngOnDestroy();
}
attach(forOf) {
if (this._forOf && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw Error('CdkVirtualScrollViewport is already attached.');
}
this.ngZone.runOutsideAngular(() => {
this._forOf = forOf;
this._forOf.dataStream.pipe(takeUntil(this._detachedSubject)).subscribe(data => {
const newLength = data.length;
if (newLength !== this._dataLength) {
this._dataLength = newLength;
this._scrollStrategy.onDataLengthChanged();
}
this._doChangeDetection();
});
});
}
detach() {
this._forOf = null;
this._detachedSubject.next();
}
getDataLength() {
return this._dataLength;
}
getViewportSize() {
return this._viewportSize;
}
getRenderedRange() {
return this._renderedRange;
}
measureBoundingClientRectWithScrollOffset(from) {
return this.getElementRef().nativeElement.getBoundingClientRect()[from];
}
setTotalContentSize(size) {
if (this._totalContentSize !== size) {
this._totalContentSize = size;
this._calculateSpacerSize();
this._markChangeDetectionNeeded();
}
}
setRenderedRange(range) {
if (!rangesEqual(this._renderedRange, range)) {
if (this.appendOnly) {
range = {
start: 0,
end: Math.max(this._renderedRange.end, range.end)
};
}
this._renderedRangeSubject.next(this._renderedRange = range);
this._markChangeDetectionNeeded(() => this._scrollStrategy.onContentRendered());
}
}
getOffsetToRenderedContentStart() {
return this._renderedContentOffsetNeedsRewrite ? null : this._renderedContentOffset;
}
setRenderedContentOffset(offset, to = 'to-start') {
offset = this.appendOnly && to === 'to-start' ? 0 : offset;
const isRtl = this.dir && this.dir.value == 'rtl';
const isHorizontal = this.orientation == 'horizontal';
const axis = isHorizontal ? 'X' : 'Y';
const axisDirection = isHorizontal && isRtl ? -1 : 1;
let transform = `translate${axis}(${Number(axisDirection * offset)}px)`;
this._renderedContentOffset = offset;
if (to === 'to-end') {
transform += ` translate${axis}(-100%)`;
this._renderedContentOffsetNeedsRewrite = true;
}
if (this._renderedContentTransform != transform) {
this._renderedContentTransform = transform;
this._markChangeDetectionNeeded(() => {
if (this._renderedContentOffsetNeedsRewrite) {
this._renderedContentOffset -= this.measureRenderedContentSize();
this._renderedContentOffsetNeedsRewrite = false;
this.setRenderedContentOffset(this._renderedContentOffset);
} else {
this._scrollStrategy.onRenderedOffsetChanged();
}
});
}
}
scrollToOffset(offset, behavior = 'auto') {
const options = {
behavior
};
if (this.orientation === 'horizontal') {
options.start = offset;
} else {
options.top = offset;
}
this.scrollable.scrollTo(options);
}
scrollToIndex(index, behavior = 'auto') {
this._scrollStrategy.scrollToIndex(index, behavior);
}
measureScrollOffset(from) {
let measureScrollOffset;
if (this.scrollable == this) {
measureScrollOffset = _from => super.measureScrollOffset(_from);
} else {
measureScrollOffset = _from => this.scrollable.measureScrollOffset(_from);
}
return Math.max(0, measureScrollOffset(from ?? (this.orientation === 'horizontal' ? 'start' : 'top')) - this.measureViewportOffset());
}
measureViewportOffset(from) {
let fromRect;
const LEFT = 'left';
const RIGHT = 'right';
const isRtl = this.dir?.value == 'rtl';
if (from == 'start') {
fromRect = isRtl ? RIGHT : LEFT;
} else if (from == 'end') {
fromRect = isRtl ? LEFT : RIGHT;
} else if (from) {
fromRect = from;
} else {
fromRect = this.orientation === 'horizontal' ? 'left' : 'top';
}
const scrollerClientRect = this.scrollable.measureBoundingClientRectWithScrollOffset(fromRect);
const viewportClientRect = this.elementRef.nativeElement.getBoundingClientRect()[fromRect];
return viewportClientRect - scrollerClientRect;
}
measureRenderedContentSize() {
const contentEl = this._contentWrapper.nativeElement;
return this.orientation === 'horizontal' ? contentEl.offsetWidth : contentEl.offsetHeight;
}
measureRangeSize(range) {
if (!this._forOf) {
return 0;
}
return this._forOf.measureRangeSize(range, this.orientation);
}
checkViewportSize() {
this._measureViewportSize();
this._scrollStrategy.onDataLengthChanged();
}
_measureViewportSize() {
this._viewportSize = this.scrollable.measureViewportSize(this.orientation);
}
_markChangeDetectionNeeded(runAfter) {
if (runAfter) {
this._runAfterChangeDetection.push(runAfter);
}
if (untracked(this._changeDetectionNeeded)) {
return;
}
this.ngZone.runOutsideAngular(() => {
Promise.resolve().then(() => {
this.ngZone.run(() => {
this._changeDetectionNeeded.set(true);
});
});
});
}
_doChangeDetection() {
if (this._isDestroyed) {
return;
}
this.ngZone.run(() => {
this._changeDetectorRef.markForCheck();
this._contentWrapper.nativeElement.style.transform = this._renderedContentTransform;
afterNextRender(() => {
this._changeDetectionNeeded.set(false);
const runAfterChangeDetection = this._runAfterChangeDetection;
this._runAfterChangeDetection = [];
for (const fn of runAfterChangeDetection) {
fn();
}
}, {
injector: this._injector
});
});
}
_calculateSpacerSize() {
this._totalContentHeight.set(this.orientation === 'horizontal' ? '' : `${this._totalContentSize}px`);
this._totalContentWidth.set(this.orientation === 'horizontal' ? `${this._totalContentSize}px` : '');
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkVirtualScrollViewport,
deps: [],
target: i0.ɵɵFactoryTarget.Component
});
static ɵcmp = i0.ɵɵngDeclareComponent({
minVersion: "16.1.0",
version: "21.0.0",
type: CdkVirtualScrollViewport,
isStandalone: true,
selector: "cdk-virtual-scroll-viewport",
inputs: {
orientation: "orientation",
appendOnly: ["appendOnly", "appendOnly", booleanAttribute]
},
outputs: {
scrolledIndexChange: "scrolledIndexChange"
},
host: {
properties: {
"class.cdk-virtual-scroll-orientation-horizontal": "orientation === \"horizontal\"",
"class.cdk-virtual-scroll-orientation-vertical": "orientation !== \"horizontal\""
},
classAttribute: "cdk-virtual-scroll-viewport"
},
providers: [{
provide: CdkScrollable,
useFactory: () => inject(VIRTUAL_SCROLLABLE, {
optional: true
}) || inject(CdkVirtualScrollViewport)
}],
viewQueries: [{
propertyName: "_contentWrapper",
first: true,
predicate: ["contentWrapper"],
descendants: true,
static: true
}],
usesInheritance: true,
ngImport: i0,
template: "<!--\n Wrap the rendered content in an element that will be used to offset it based on the scroll\n position.\n-->\n<div #contentWrapper class=\"cdk-virtual-scroll-content-wrapper\">\n <ng-content></ng-content>\n</div>\n<!--\n Spacer used to force the scrolling container to the correct size for the *total* number of items\n so that the scrollbar captures the size of the entire data set.\n-->\n<div class=\"cdk-virtual-scroll-spacer\"\n [style.width]=\"_totalContentWidth()\" [style.height]=\"_totalContentHeight()\"></div>\n",
styles: ["cdk-virtual-scroll-viewport{display:block;position:relative;transform:translateZ(0)}.cdk-virtual-scrollable{overflow:auto;will-change:scroll-position;contain:strict}.cdk-virtual-scroll-content-wrapper{position:absolute;top:0;left:0;contain:content}[dir=rtl] .cdk-virtual-scroll-content-wrapper{right:0;left:auto}.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper{min-height:100%}.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-left:0;padding-right:0;margin-left:0;margin-right:0;border-left-width:0;border-right-width:0;outline:none}.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper{min-width:100%}.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;border-top-width:0;border-bottom-width:0;outline:none}.cdk-virtual-scroll-spacer{height:1px;transform-origin:0 0;flex:0 0 auto}[dir=rtl] .cdk-virtual-scroll-spacer{transform-origin:100% 0}\n"],
changeDetection: i0.ChangeDetectionStrategy.OnPush,
encapsulation: i0.ViewEncapsulation.None
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkVirtualScrollViewport,
decorators: [{
type: Component,
args: [{
selector: 'cdk-virtual-scroll-viewport',
host: {
'class': 'cdk-virtual-scroll-viewport',
'[class.cdk-virtual-scroll-orientation-horizontal]': 'orientation === "horizontal"',
'[class.cdk-virtual-scroll-orientation-vertical]': 'orientation !== "horizontal"'
},
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [{
provide: CdkScrollable,
useFactory: () => inject(VIRTUAL_SCROLLABLE, {
optional: true
}) || inject(CdkVirtualScrollViewport)
}],
template: "<!--\n Wrap the rendered content in an element that will be used to offset it based on the scroll\n position.\n-->\n<div #contentWrapper class=\"cdk-virtual-scroll-content-wrapper\">\n <ng-content></ng-content>\n</div>\n<!--\n Spacer used to force the scrolling container to the correct size for the *total* number of items\n so that the scrollbar captures the size of the entire data set.\n-->\n<div class=\"cdk-virtual-scroll-spacer\"\n [style.width]=\"_totalContentWidth()\" [style.height]=\"_totalContentHeight()\"></div>\n",
styles: ["cdk-virtual-scroll-viewport{display:block;position:relative;transform:translateZ(0)}.cdk-virtual-scrollable{overflow:auto;will-change:scroll-position;contain:strict}.cdk-virtual-scroll-content-wrapper{position:absolute;top:0;left:0;contain:content}[dir=rtl] .cdk-virtual-scroll-content-wrapper{right:0;left:auto}.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper{min-height:100%}.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-left:0;padding-right:0;margin-left:0;margin-right:0;border-left-width:0;border-right-width:0;outline:none}.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper{min-width:100%}.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;border-top-width:0;border-bottom-width:0;outline:none}.cdk-virtual-scroll-spacer{height:1px;transform-origin:0 0;flex:0 0 auto}[dir=rtl] .cdk-virtual-scroll-spacer{transform-origin:100% 0}\n"]
}]
}],
ctorParameters: () => [],
propDecorators: {
orientation: [{
type: Input
}],
appendOnly: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}],
scrolledIndexChange: [{
type: Output
}],
_contentWrapper: [{
type: ViewChild,
args: ['contentWrapper', {
static: true
}]
}]
}
});
function getOffset(orientation, direction, node) {
const el = node;
if (!el.getBoundingClientRect) {
return 0;
}
const rect = el.getBoundingClientRect();
if (orientation === 'horizontal') {
return direction === 'start' ? rect.left : rect.right;
}
return direction === 'start' ? rect.top : rect.bottom;
}
class CdkVirtualForOf {
_viewContainerRef = inject(ViewContainerRef);
_template = inject(TemplateRef);
_differs = inject(IterableDiffers);
_viewRepeater = inject(_VIEW_REPEATER_STRATEGY);
_viewport = inject(CdkVirtualScrollViewport, {
skipSelf: true
});
viewChange = new Subject();
_dataSourceChanges = new Subject();
get cdkVirtualForOf() {
return this._cdkVirtualForOf;
}
set cdkVirtualForOf(value) {
this._cdkVirtualForOf = value;
if (isDataSource(value)) {
this._dataSourceChanges.next(value);
} else {
this._dataSourceChanges.next(new ArrayDataSource(isObservable(value) ? value : Array.from(value || [])));
}
}
_cdkVirtualForOf;
get cdkVirtualForTrackBy() {
return this._cdkVirtualForTrackBy;
}
set cdkVirtualForTrackBy(fn) {
this._needsUpdate = true;
this._cdkVirtualForTrackBy = fn ? (index, item) => fn(index + (this._renderedRange ? this._renderedRange.start : 0), item) : undefined;
}
_cdkVirtualForTrackBy;
set cdkVirtualForTemplate(value) {
if (value) {
this._needsUpdate = true;
this._template = value;
}
}
get cdkVirtualForTemplateCacheSize() {
return this._viewRepeater.viewCacheSize;
}
set cdkVirtualForTemplateCacheSize(size) {
this._viewRepeater.viewCacheSize = coerceNumberProperty(size);
}
dataStream = this._dataSourceChanges.pipe(startWith(null), pairwise(), switchMap(([prev, cur]) => this._changeDataSource(prev, cur)), shareReplay(1));
_differ = null;
_data;
_renderedItems;
_renderedRange;
_needsUpdate = false;
_destroyed = new Subject();
constructor() {
const ngZone = inject(NgZone);
this.dataStream.subscribe(data => {
this._data = data;
this._onRenderedDataChange();
});
this._viewport.renderedRangeStream.pipe(takeUntil(this._destroyed)).subscribe(range => {
this._renderedRange = range;
if (this.viewChange.observers.length) {
ngZone.run(() => this.viewChange.next(this._renderedRange));
}
this._onRenderedDataChange();
});
this._viewport.attach(this);
}
measureRangeSize(range, orientation) {
if (range.start >= range.end) {
return 0;
}
if ((range.start < this._renderedRange.start || range.end > this._renderedRange.end) && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw Error(`Error: attempted to measure an item that isn't rendered.`);
}
const renderedStartIndex = range.start - this._renderedRange.start;
const rangeLen = range.end - range.start;
let firstNode;
let lastNode;
for (let i = 0; i < rangeLen; i++) {
const view = this._viewContainerRef.get(i + renderedStartIndex);
if (view && view.rootNodes.length) {
firstNode = lastNode = view.rootNodes[0];
break;
}
}
for (let i = rangeLen - 1; i > -1; i--) {
const view = this._viewContainerRef.get(i + renderedStartIndex);
if (view && view.rootNodes.length) {
lastNode = view.rootNodes[view.rootNodes.length - 1];
break;
}
}
return firstNode && lastNode ? getOffset(orientation, 'end', lastNode) - getOffset(orientation, 'start', firstNode) : 0;
}
ngDoCheck() {
if (this._differ && this._needsUpdate) {
const changes = this._differ.diff(this._renderedItems);
if (!changes) {
this._updateContext();
} else {
this._applyChanges(changes);
}
this._needsUpdate = false;
}
}
ngOnDestroy() {
this._viewport.detach();
this._dataSourceChanges.next(undefined);
this._dataSourceChanges.complete();
this.viewChange.complete();
this._destroyed.next();
this._destroyed.complete();
this._viewRepeater.detach();
}
_onRenderedDataChange() {
if (!this._renderedRange) {
return;
}
this._renderedItems = this._data.slice(this._renderedRange.start, this._renderedRange.end);
if (!this._differ) {
this._differ = this._differs.find(this._renderedItems).create((index, item) => {
return this.cdkVirtualForTrackBy ? this.cdkVirtualForTrackBy(index, item) : item;
});
}
this._needsUpdate = true;
}
_changeDataSource(oldDs, newDs) {
if (oldDs) {
oldDs.disconnect(this);
}
this._needsUpdate = true;
return newDs ? newDs.connect(this) : of();
}
_updateContext() {
const count = this._data.length;
let i = this._viewContainerRef.length;
while (i--) {
const view = this._viewContainerRef.get(i);
view.context.index = this._renderedRange.start + i;
view.context.count = count;
this._updateComputedContextProperties(view.context);
view.detectChanges();
}
}
_applyChanges(changes) {
this._viewRepeater.applyChanges(changes, this._viewContainerRef, (record, _adjustedPreviousIndex, currentIndex) => this._getEmbeddedViewArgs(record, currentIndex), record => record.item);
changes.forEachIdentityChange(record => {
const view = this._viewContainerRef.get(record.currentIndex);
view.context.$implicit = record.item;
});
const count = this._data.length;
let i = this._viewContainerRef.length;
while (i--) {
const view = this._viewContainerRef.get(i);
view.context.index = this._renderedRange.start + i;
view.context.count = count;
this._updateComputedContextProperties(view.context);
}
}
_updateComputedContextProperties(context) {
context.first = context.index === 0;
context.last = context.index === context.count - 1;
context.even = context.index % 2 === 0;
context.odd = !context.even;
}
_getEmbeddedViewArgs(record, index) {
return {
templateRef: this._template,
context: {
$implicit: record.item,
cdkVirtualForOf: this._cdkVirtualForOf,
index: -1,
count: -1,
first: false,
last: false,
odd: false,
even: false
},
index
};
}
static ngTemplateContextGuard(directive, context) {
return true;
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkVirtualForOf,
deps: [],
target: i0.ɵɵFactoryTarget.Directive
});
static ɵdir = i0.ɵɵngDeclareDirective({
minVersion: "14.0.0",
version: "21.0.0",
type: CdkVirtualForOf,
isStandalone: true,
selector: "[cdkVirtualFor][cdkVirtualForOf]",
inputs: {
cdkVirtualForOf: "cdkVirtualForOf",
cdkVirtualForTrackBy: "cdkVirtualForTrackBy",
cdkVirtualForTemplate: "cdkVirtualForTemplate",
cdkVirtualForTemplateCacheSize: "cdkVirtualForTemplateCacheSize"
},
providers: [{
provide: _VIEW_REPEATER_STRATEGY,
useClass: _RecycleViewRepeaterStrategy
}],
ngImport: i0
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkVirtualForOf,
decorators: [{
type: Directive,
args: [{
selector: '[cdkVirtualFor][cdkVirtualForOf]',
providers: [{
provide: _VIEW_REPEATER_STRATEGY,
useClass: _RecycleViewRepeaterStrategy
}]
}]
}],
ctorParameters: () => [],
propDecorators: {
cdkVirtualForOf: [{
type: Input
}],
cdkVirtualForTrackBy: [{
type: Input
}],
cdkVirtualForTemplate: [{
type: Input
}],
cdkVirtualForTemplateCacheSize: [{
type: Input
}]
}
});
class CdkVirtualScrollableElement extends CdkVirtualScrollable {
constructor() {
super();
}
measureBoundingClientRectWithScrollOffset(from) {
return this.getElementRef().nativeElement.getBoundingClientRect()[from] - this.measureScrollOffset(from);
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkVirtualScrollableElement,
deps: [],
target: i0.ɵɵFactoryTarget.Directive
});
static ɵdir = i0.ɵɵngDeclareDirective({
minVersion: "14.0.0",
version: "21.0.0",
type: CdkVirtualScrollableElement,
isStandalone: true,
selector: "[cdkVirtualScrollingElement]",
host: {
classAttribute: "cdk-virtual-scrollable"
},
providers: [{
provide: VIRTUAL_SCROLLABLE,
useExisting: CdkVirtualScrollableElement
}],
usesInheritance: true,
ngImport: i0
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkVirtualScrollableElement,
decorators: [{
type: Directive,
args: [{
selector: '[cdkVirtualScrollingElement]',
providers: [{
provide: VIRTUAL_SCROLLABLE,
useExisting: CdkVirtualScrollableElement
}],
host: {
'class': 'cdk-virtual-scrollable'
}
}]
}],
ctorParameters: () => []
});
class CdkVirtualScrollableWindow extends CdkVirtualScrollable {
constructor() {
super();
const document = inject(DOCUMENT);
this.elementRef = new ElementRef(document.documentElement);
this._scrollElement = document;
}
measureBoundingClientRectWithScrollOffset(from) {
return this.getElementRef().nativeElement.getBoundingClientRect()[from];
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkVirtualScrollableWindow,
deps: [],
target: i0.ɵɵFactoryTarget.Directive
});
static ɵdir = i0.ɵɵngDeclareDirective({
minVersion: "14.0.0",
version: "21.0.0",
type: CdkVirtualScrollableWindow,
isStandalone: true,
selector: "cdk-virtual-scroll-viewport[scrollWindow]",
providers: [{
provide: VIRTUAL_SCROLLABLE,
useExisting: CdkVirtualScrollableWindow
}],
usesInheritance: true,
ngImport: i0
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkVirtualScrollableWindow,
decorators: [{
type: Directive,
args: [{
selector: 'cdk-virtual-scroll-viewport[scrollWindow]',
providers: [{
provide: VIRTUAL_SCROLLABLE,
useExisting: CdkVirtualScrollableWindow
}]
}]
}],
ctorParameters: () => []
});
class CdkScrollableModule {
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkScrollableModule,
deps: [],
target: i0.ɵɵFactoryTarget.NgModule
});
static ɵmod = i0.ɵɵngDeclareNgModule({
minVersion: "14.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkScrollableModule,
imports: [CdkScrollable],
exports: [CdkScrollable]
});
static ɵinj = i0.ɵɵngDeclareInjector({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkScrollableModule
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: CdkScrollableModule,
decorators: [{
type: NgModule,
args: [{
exports: [CdkScrollable],
imports: [CdkScrollable]
}]
}]
});
class ScrollingModule {
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: ScrollingModule,
deps: [],
target: i0.ɵɵFactoryTarget.NgModule
});
static ɵmod = i0.ɵɵngDeclareNgModule({
minVersion: "14.0.0",
version: "21.0.0",
ngImport: i0,
type: ScrollingModule,
imports: [BidiModule, CdkScrollableModule, CdkVirtualScrollViewport, CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollableWindow, CdkVirtualScrollableElement],
exports: [BidiModule, CdkScrollableModule, CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollViewport, CdkVirtualScrollableWindow, CdkVirtualScrollableElement]
});
static ɵinj = i0.ɵɵngDeclareInjector({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: ScrollingModule,
imports: [BidiModule, CdkScrollableModule, BidiModule, CdkScrollableModule]
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.0.0",
ngImport: i0,
type: ScrollingModule,
decorators: [{
type: NgModule,
args: [{
imports: [BidiModule, CdkScrollableModule, CdkVirtualScrollViewport, CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollableWindow, CdkVirtualScrollableElement],
exports: [BidiModule, CdkScrollableModule, CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollViewport, CdkVirtualScrollableWindow, CdkVirtualScrollableElement]
}]
}]
});
export { CdkFixedSizeVirtualScroll, CdkScrollable, CdkScrollableModule, CdkVirtualForOf, CdkVirtualScrollViewport, CdkVirtualScrollable, CdkVirtualScrollableElement, CdkVirtualScrollableWindow, DEFAULT_RESIZE_TIME, DEFAULT_SCROLL_TIME, FixedSizeVirtualScrollStrategy, ScrollDispatcher, ScrollingModule, VIRTUAL_SCROLLABLE, VIRTUAL_SCROLL_STRATEGY, ViewportRuler, _fixedSizeVirtualScrollStrategyFactory };
//# sourceMappingURL=scrolling.mjs.map