1import { 2 ArrayDataSource, 3 BidiModule, 4 Directionality, 5 Platform, 6 RtlScrollAxisType, 7 _RecycleViewRepeaterStrategy, 8 _VIEW_REPEATER_STRATEGY, 9 coerceElement, 10 coerceNumberProperty, 11 getRtlScrollAxisType, 12 isDataSource, 13 supportsScrollBehavior 14} from "./chunk-X25WEEDB.js"; 15import { 16 ChangeDetectionStrategy, 17 ChangeDetectorRef, 18 Component, 19 DOCUMENT, 20 Directive, 21 ElementRef, 22 Inject, 23 Injectable, 24 InjectionToken, 25 Injector, 26 Input, 27 IterableDiffers, 28 NgModule, 29 NgZone, 30 Observable, 31 Optional, 32 Output, 33 Renderer2, 34 RendererFactory2, 35 Subject, 36 Subscription, 37 TemplateRef, 38 ViewChild, 39 ViewContainerRef, 40 ViewEncapsulation, 41 afterNextRender, 42 animationFrameScheduler, 43 asapScheduler, 44 auditTime, 45 booleanAttribute, 46 distinctUntilChanged, 47 filter, 48 forwardRef, 49 inject, 50 isObservable, 51 of, 52 pairwise, 53 setClassMetadata, 54 shareReplay, 55 startWith, 56 switchMap, 57 takeUntil, 58 ɵɵInheritDefinitionFeature, 59 ɵɵNgOnChangesFeature, 60 ɵɵProvidersFeature, 61 ɵɵadvance, 62 ɵɵclassProp, 63 ɵɵdefineComponent, 64 ɵɵdefineDirective, 65 ɵɵdefineInjectable, 66 ɵɵdefineInjector, 67 ɵɵdefineNgModule, 68 ɵɵelement, 69 ɵɵelementEnd, 70 ɵɵelementStart, 71 ɵɵloadQuery, 72 ɵɵprojection, 73 ɵɵprojectionDef, 74 ɵɵqueryRefresh, 75 ɵɵstyleProp, 76 ɵɵviewQuery 77} from "./chunk-6GJQIPT2.js"; 78 79// node_modules/@angular/cdk/fesm2022/scrolling.mjs 80var _c0 = ["contentWrapper"]; 81var _c1 = ["*"]; 82var VIRTUAL_SCROLL_STRATEGY = new InjectionToken("VIRTUAL_SCROLL_STRATEGY"); 83var FixedSizeVirtualScrollStrategy = class { 84 _scrolledIndexChange = new Subject(); 85 /** @docs-private Implemented as part of VirtualScrollStrategy. */ 86 scrolledIndexChange = this._scrolledIndexChange.pipe(distinctUntilChanged()); 87 /** The attached viewport. */ 88 _viewport = null; 89 /** The size of the items in the virtually scrolling list. */ 90 _itemSize; 91 /** The minimum amount of buffer rendered beyond the viewport (in pixels). */ 92 _minBufferPx; 93 /** The number of buffer items to render beyond the edge of the viewport (in pixels). */ 94 _maxBufferPx; 95 /** 96 * @param itemSize The size of the items in the virtually scrolling list. 97 * @param minBufferPx The minimum amount of buffer (in pixels) before needing to render more 98 * @param maxBufferPx The amount of buffer (in pixels) to render when rendering more. 99 */ 100 constructor(itemSize, minBufferPx, maxBufferPx) { 101 this._itemSize = itemSize; 102 this._minBufferPx = minBufferPx; 103 this._maxBufferPx = maxBufferPx; 104 } 105 /** 106 * Attaches this scroll strategy to a viewport. 107 * @param viewport The viewport to attach this strategy to. 108 */ 109 attach(viewport) { 110 this._viewport = viewport; 111 this._updateTotalContentSize(); 112 this._updateRenderedRange(); 113 } 114 /** Detaches this scroll strategy from the currently attached viewport. */ 115 detach() { 116 this._scrolledIndexChange.complete(); 117 this._viewport = null; 118 } 119 /** 120 * Update the item size and buffer size. 121 * @param itemSize The size of the items in the virtually scrolling list. 122 * @param minBufferPx The minimum amount of buffer (in pixels) before needing to render more 123 * @param maxBufferPx The amount of buffer (in pixels) to render when rendering more. 124 */ 125 updateItemAndBufferSize(itemSize, minBufferPx, maxBufferPx) { 126 if (maxBufferPx < minBufferPx && (typeof ngDevMode === "undefined" || ngDevMode)) { 127 throw Error("CDK virtual scroll: maxBufferPx must be greater than or equal to minBufferPx"); 128 } 129 this._itemSize = itemSize; 130 this._minBufferPx = minBufferPx; 131 this._maxBufferPx = maxBufferPx; 132 this._updateTotalContentSize(); 133 this._updateRenderedRange(); 134 } 135 /** @docs-private Implemented as part of VirtualScrollStrategy. */ 136 onContentScrolled() { 137 this._updateRenderedRange(); 138 } 139 /** @docs-private Implemented as part of VirtualScrollStrategy. */ 140 onDataLengthChanged() { 141 this._updateTotalContentSize(); 142 this._updateRenderedRange(); 143 } 144 /** @docs-private Implemented as part of VirtualScrollStrategy. */ 145 onContentRendered() { 146 } 147 /** @docs-private Implemented as part of VirtualScrollStrategy. */ 148 onRenderedOffsetChanged() { 149 } 150 /** 151 * Scroll to the offset for the given index. 152 * @param index The index of the element to scroll to. 153 * @param behavior The ScrollBehavior to use when scrolling. 154 */ 155 scrollToIndex(index, behavior) { 156 if (this._viewport) { 157 this._viewport.scrollToOffset(index * this._itemSize, behavior); 158 } 159 }
160 /** Update the viewport's total content size. */ 161 _updateTotalContentSize() { 162 if (!this._viewport) { 163 return; 164 } 165 this._viewport.setTotalContentSize(this._viewport.getDataLength() * this._itemSize); 166 } 167 /** Update the viewport's rendered range. */ 168 _updateRenderedRange() { 169 if (!this._viewport) { 170 return; 171 } 172 const renderedRange = this._viewport.getRenderedRange(); 173 const newRange = { 174 start: renderedRange.start, 175 end: renderedRange.end 176 }; 177 const viewportSize = this._viewport.getViewportSize(); 178 const dataLength = this._viewport.getDataLength(); 179 let scrollOffset = this._viewport.measureScrollOffset(); 180 let firstVisibleIndex = this._itemSize > 0 ? scrollOffset / this._itemSize : 0; 181 if (newRange.end > dataLength) { 182 const maxVisibleItems = Math.ceil(viewportSize / this._itemSize); 183 const newVisibleIndex = Math.max(0, Math.min(firstVisibleIndex, dataLength - maxVisibleItems)); 184 if (firstVisibleIndex != newVisibleIndex) { 185 firstVisibleIndex = newVisibleIndex; 186 scrollOffset = newVisibleIndex * this._itemSize; 187 newRange.start = Math.floor(firstVisibleIndex); 188 } 189 newRange.end = Math.max(0, Math.min(dataLength, newRange.start + maxVisibleItems)); 190 } 191 const startBuffer = scrollOffset - newRange.start * this._itemSize; 192 if (startBuffer < this._minBufferPx && newRange.start != 0) { 193 const expandStart = Math.ceil((this._maxBufferPx - startBuffer) / this._itemSize); 194 newRange.start = Math.max(0, newRange.start - expandStart); 195 newRange.end = Math.min(dataLength, Math.ceil(firstVisibleIndex + (viewportSize + this._minBufferPx) / this._itemSize)); 196 } else { 197 const endBuffer = newRange.end * this._itemSize - (scrollOffset + viewportSize); 198 if (endBuffer < this._minBufferPx && newRange.end != dataLength) { 199 const expandEnd = Math.ceil((this._maxBufferPx - endBuffer) / this._itemSize); 200 if (expandEnd > 0) { 201 newRange.end = Math.min(dataLength, newRange.end + expandEnd); 202 newRange.start = Math.max(0, Math.floor(firstVisibleIndex - this._minBufferPx / this._itemSize)); 203 } 204 } 205 } 206 this._viewport.setRenderedRange(newRange); 207 this._viewport.setRenderedContentOffset(this._itemSize * newRange.start); 208 this._scrolledIndexChange.next(Math.floor(firstVisibleIndex)); 209 } 210}; 211function _fixedSizeVirtualScrollStrategyFactory(fixedSizeDir) { 212 return fixedSizeDir._scrollStrategy; 213} 214var CdkFixedSizeVirtualScroll = class _CdkFixedSizeVirtualScroll { 215 /** The size of the items in the list (in pixels). */ 216 get itemSize() { 217 return this._itemSize; 218 } 219 set itemSize(value) { 220 this._itemSize = coerceNumberProperty(value); 221 } 222 _itemSize = 20; 223 /** 224 * The minimum amount of buffer rendered beyond the viewport (in pixels). 225 * If the amount of buffer dips below this number, more items will be rendered. Defaults to 100px. 226 */ 227 get minBufferPx() { 228 return this._minBufferPx; 229 } 230 set minBufferPx(value) { 231 this._minBufferPx = coerceNumberProperty(value); 232 } 233 _minBufferPx = 100; 234 /** 235 * The number of pixels worth of buffer to render for when rendering new items. Defaults to 200px. 236 */ 237 get maxBufferPx() { 238 return this._maxBufferPx; 239 } 240 set maxBufferPx(value) { 241 this._maxBufferPx = coerceNumberProperty(value); 242 } 243 _maxBufferPx = 200; 244 /** The scroll strategy used by this directive. */ 245 _scrollStrategy = new FixedSizeVirtualScrollStrategy(this.itemSize, this.minBufferPx, this.maxBufferPx); 246 ngOnChanges() { 247 this._scrollStrategy.updateItemAndBufferSize(this.itemSize, this.minBufferPx, this.maxBufferPx); 248 } 249 static \u0275fac = function CdkFixedSizeVirtualScroll_Factory(__ngFactoryType__) { 250 return new (__ngFactoryType__ || _CdkFixedSizeVirtualScroll)(); 251 }; 252 static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({ 253 type: _CdkFixedSizeVirtualScroll, 254 selectors: [["cdk-virtual-scroll-viewport", "itemSize", ""]], 255 inputs: { 256 itemSize: "itemSize", 257 minBufferPx: "minBufferPx", 258 maxBufferPx: "maxBufferPx" 259 }, 260 features: [\u0275\u0275ProvidersFeature([{ 261 provide: VIRTUAL_SCROLL_STRATEGY, 262 useFactory: _fixedSizeVirtualScrollStrategyFactory, 263 deps: [forwardRef(() => _CdkFixedSizeVirtualScroll)] 264 }]), \u0275\u0275NgOnChangesFeature] 265 }); 266}; 267(() => { 268 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkFixedSizeVirtualScroll, [{ 269 type: Directive, 270 args: [{ 271 selector: "cdk-virtual-scroll-viewport[itemSize]", 272 providers: [{ 273 provide: VIRTUAL_SCROLL_STRATEGY, 274 useFactory: _fixedSizeVirtualScrollStrategyFactory, 275 deps: [forwardRef(() => CdkFixedSizeVirtualScroll)] 276 }] 277 }] 278 }], null, { 279 itemSize: [{ 280 type: Input 281 }], 282 minBufferPx: [{ 283 type: Input 284 }], 285 maxBufferPx: [{ 286 type: Input 287 }] 288 }); 289})(); 290var DEFAULT_SCROLL_TIME = 20; 291var ScrollDispatcher = class _ScrollDispatcher { 292 _ngZone = inject(NgZone); 293 _platform = inject(Platform); 294 _renderer = inject(RendererFactory2).createRenderer(null, null); 295 _cleanupGlobalListener; 296 constructor() { 297 } 298 /** Subject for notifying that a registered scrollable reference element has been scrolled. */ 299 _scrolled = new Subject(); 300 /** Keeps track of the amount of subscriptions to `scrolled`. Used for cleaning up afterwards. */ 301 _scrolledCount = 0; 302 /** 303 * Map of all the scrollable references that are registered with the service and their 304 * scroll event subscriptions. 305 */ 306 scrollContainers = /* @__PURE__ */ new Map(); 307 /** 308 * Registers a scrollable instance with the service and listens for its scrolled events. When the 309 * scrollable is scrolled, the service emits the event to its scrolled observable. 310 * @param scrollable Scrollable instance to be registered. 311 */ 312 register(scrollable) { 313 if (!this.scrollContainers.has(scrollable)) { 314 this.scrollContainers.set(scrollable, scrollable.elementScrolled().subscribe(() => this._scrolled.next(scrollable))); 315 } 316 } 317 /** 318 * De-registers a Scrollable reference and unsubscribes from its scroll event observable. 319 * @param scrollable Scrollable instance to be deregistered. 320 */ 321 deregister(scrollable) { 322 const scrollableReference = this.scrollContainers.get(scrollable); 323 if (scrollableReference) { 324 scrollableReference.unsubscribe(); 325 this.scrollContainers.delete(scrollable); 326 } 327 } 328 /** 329 * Returns an observable that emits an event whenever any of the registered Scrollable 330 * references (or window, document, or body) fire a scrolled event. Can provide a time in ms 331 * to override the default "throttle" time. 332 * 333 * **Note:** in order to avoid hitting change detection for every scroll event, 334 * all of the events emitted from this stream will be run outside the Angular zone. 335 * If you need to update any data bindings as a result of a scroll event, you have 336 * to run the callback using `NgZone.run`. 337 */ 338 scrolled(auditTimeInMs = DEFAULT_SCROLL_TIME) { 339 if (!this._platform.isBrowser) { 340 return of(); 341 } 342 return new Observable((observer) => { 343 if (!this._cleanupGlobalListener) { 344 this._cleanupGlobalListener = this._ngZone.runOutsideAngular(() => this._renderer.listen("document", "scroll", () => this._scrolled.next())); 345 } 346 const subscription = auditTimeInMs > 0 ? this._scrolled.pipe(auditTime(auditTimeInMs)).subscribe(observer) : this._scrolled.subscribe(observer); 347 this._scrolledCount++; 348 return () => { 349 subscription.unsubscribe(); 350 this._scrolledCount--; 351 if (!this._scrolledCount) { 352 this._cleanupGlobalListener?.(); 353 this._cleanupGlobalListener = void 0; 354 } 355 }; 356 }); 357 } 358 ngOnDestroy() { 359 this._cleanupGlobalListener?.(); 360 this._cleanupGlobalListener = void 0;
361 this.scrollContainers.forEach((_, container) => this.deregister(container)); 362 this._scrolled.complete(); 363 } 364 /** 365 * Returns an observable that emits whenever any of the 366 * scrollable ancestors of an element are scrolled. 367 * @param elementOrElementRef Element whose ancestors to listen for. 368 * @param auditTimeInMs Time to throttle the scroll events. 369 */ 370 ancestorScrolled(elementOrElementRef, auditTimeInMs) { 371 const ancestors = this.getAncestorScrollContainers(elementOrElementRef); 372 return this.scrolled(auditTimeInMs).pipe(filter((target) => !target || ancestors.indexOf(target) > -1)); 373 } 374 /** Returns all registered Scrollables that contain the provided element. */ 375 getAncestorScrollContainers(elementOrElementRef) { 376 const scrollingContainers = []; 377 this.scrollContainers.forEach((_subscription, scrollable) => { 378 if (this._scrollableContainsElement(scrollable, elementOrElementRef)) { 379 scrollingContainers.push(scrollable); 380 } 381 }); 382 return scrollingContainers; 383 } 384 /** Returns true if the element is contained within the provided Scrollable. */ 385 _scrollableContainsElement(scrollable, elementOrElementRef) { 386 let element = coerceElement(elementOrElementRef); 387 let scrollableElement = scrollable.getElementRef().nativeElement; 388 do { 389 if (element == scrollableElement) { 390 return true; 391 } 392 } while (element = element.parentElement); 393 return false; 394 } 395 static \u0275fac = function ScrollDispatcher_Factory(__ngFactoryType__) { 396 return new (__ngFactoryType__ || _ScrollDispatcher)(); 397 }; 398 static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({ 399 token: _ScrollDispatcher, 400 factory: _ScrollDispatcher.\u0275fac, 401 providedIn: "root" 402 }); 403}; 404(() => { 405 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ScrollDispatcher, [{ 406 type: Injectable, 407 args: [{ 408 providedIn: "root" 409 }] 410 }], () => [], null); 411})(); 412var CdkScrollable = class _CdkScrollable { 413 elementRef = inject(ElementRef); 414 scrollDispatcher = inject(ScrollDispatcher); 415 ngZone = inject(NgZone); 416 dir = inject(Directionality, { 417 optional: true 418 }); 419 _scrollElement = this.elementRef.nativeElement; 420 _destroyed = new Subject(); 421 _renderer = inject(Renderer2); 422 _cleanupScroll; 423 _elementScrolled = new Subject(); 424 constructor() { 425 } 426 ngOnInit() { 427 this._cleanupScroll = this.ngZone.runOutsideAngular(() => this._renderer.listen(this._scrollElement, "scroll", (event) => this._elementScrolled.next(event))); 428 this.scrollDispatcher.register(this); 429 } 430 ngOnDestroy() { 431 this._cleanupScroll?.(); 432 this._elementScrolled.complete(); 433 this.scrollDispatcher.deregister(this); 434 this._destroyed.next(); 435 this._destroyed.complete(); 436 } 437 /** Returns observable that emits when a scroll event is fired on the host element. */ 438 elementScrolled() { 439 return this._elementScrolled; 440 } 441 /** Gets the ElementRef for the viewport. */ 442 getElementRef() { 443 return this.elementRef; 444 } 445 /** 446 * Scrolls to the specified offsets. This is a normalized version of the browser's native scrollTo 447 * method, since browsers are not consistent about what scrollLeft means in RTL. For this method 448 * left and right always refer to the left and right side of the scrolling container irrespective 449 * of the layout direction. start and end refer to left and right in an LTR context and vice-versa 450 * in an RTL context. 451 * @param options specified the offsets to scroll to. 452 */ 453 scrollTo(options) { 454 const el = this.elementRef.nativeElement; 455 const isRtl = this.dir && this.dir.value == "rtl"; 456 if (options.left == null) { 457 options.left = isRtl ? options.end : options.start; 458 } 459 if (options.right == null) { 460 options.right = isRtl ? options.start : options.end; 461 } 462 if (options.bottom != null) { 463 options.top = el.scrollHeight - el.clientHeight - options.bottom; 464 } 465 if (isRtl && getRtlScrollAxisType() != RtlScrollAxisType.NORMAL) { 466 if (options.left != null) { 467 options.right = el.scrollWidth - el.clientWidth - options.left; 468 } 469 if (getRtlScrollAxisType() == RtlScrollAxisType.INVERTED) { 470 options.left = options.right; 471 } else if (getRtlScrollAxisType() == RtlScrollAxisType.NEGATED) { 472 options.left = options.right ? -options.right : options.right; 473 } 474 } else { 475 if (options.right != null) { 476 options.left = el.scrollWidth - el.clientWidth - options.right; 477 } 478 } 479 this._applyScrollToOptions(options); 480 } 481 _applyScrollToOptions(options) { 482 const el = this.elementRef.nativeElement; 483 if (supportsScrollBehavior()) { 484 el.scrollTo(options); 485 } else { 486 if (options.top != null) { 487 el.scrollTop = options.top; 488 } 489 if (options.left != null) { 490 el.scrollLeft = options.left; 491 } 492 } 493 } 494 /** 495 * Measures the scroll offset relative to the specified edge of the viewport. This method can be 496 * used instead of directly checking scrollLeft or scrollTop, since browsers are not consistent 497 * about what scrollLeft means in RTL. The values returned by this method are normalized such that 498 * left and right always refer to the left and right side of the scrolling container irrespective 499 * of the layout direction. start and end refer to left and right in an LTR context and vice-versa 500 * in an RTL context. 501 * @param from The edge to measure from. 502 */ 503 measureScrollOffset(from) { 504 const LEFT = "left"; 505 const RIGHT = "right"; 506 const el = this.elementRef.nativeElement; 507 if (from == "top") { 508 return el.scrollTop; 509 } 510 if (from == "bottom") { 511 return el.scrollHeight - el.clientHeight - el.scrollTop; 512 } 513 const isRtl = this.dir && this.dir.value == "rtl"; 514 if (from == "start") {
515 from = isRtl ? RIGHT : LEFT; 516 } else if (from == "end") { 517 from = isRtl ? LEFT : RIGHT; 518 } 519 if (isRtl && getRtlScrollAxisType() == RtlScrollAxisType.INVERTED) { 520 if (from == LEFT) { 521 return el.scrollWidth - el.clientWidth - el.scrollLeft; 522 } else { 523 return el.scrollLeft; 524 } 525 } else if (isRtl && getRtlScrollAxisType() == RtlScrollAxisType.NEGATED) { 526 if (from == LEFT) { 527 return el.scrollLeft + el.scrollWidth - el.clientWidth; 528 } else { 529 return -el.scrollLeft; 530 } 531 } else { 532 if (from == LEFT) { 533 return el.scrollLeft; 534 } else { 535 return el.scrollWidth - el.clientWidth - el.scrollLeft; 536 } 537 } 538 } 539 static \u0275fac = function CdkScrollable_Factory(__ngFactoryType__) { 540 return new (__ngFactoryType__ || _CdkScrollable)(); 541 }; 542 static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({ 543 type: _CdkScrollable, 544 selectors: [["", "cdk-scrollable", ""], ["", "cdkScrollable", ""]] 545 }); 546}; 547(() => { 548 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkScrollable, [{ 549 type: Directive, 550 args: [{ 551 selector: "[cdk-scrollable], [cdkScrollable]" 552 }] 553 }], () => [], null); 554})(); 555var DEFAULT_RESIZE_TIME = 20; 556var ViewportRuler = class _ViewportRuler { 557 _platform = inject(Platform); 558 _listeners; 559 /** Cached viewport dimensions. */ 560 _viewportSize; 561 /** Stream of viewport change events. */ 562 _change = new Subject(); 563 /** Used to reference correct document/window */ 564 _document = inject(DOCUMENT, { 565 optional: true 566 }); 567 constructor() { 568 const ngZone = inject(NgZone); 569 const renderer = inject(RendererFactory2).createRenderer(null, null); 570 ngZone.runOutsideAngular(() => { 571 if (this._platform.isBrowser) { 572 const changeListener = (event) => this._change.next(event); 573 this._listeners = [renderer.listen("window", "resize", changeListener), renderer.listen("window", "orientationchange", changeListener)]; 574 } 575 this.change().subscribe(() => this._viewportSize = null); 576 }); 577 } 578 ngOnDestroy() { 579 this._listeners?.forEach((cleanup) => cleanup()); 580 this._change.complete(); 581 } 582 /** Returns the viewport's width and height. */ 583 getViewportSize() { 584 if (!this._viewportSize) { 585 this._updateViewportSize(); 586 } 587 const output = { 588 width: this._viewportSize.width, 589 height: this._viewportSize.height 590 }; 591 if (!this._platform.isBrowser) { 592 this._viewportSize = null; 593 } 594 return output; 595 } 596 /** Gets a DOMRect for the viewport's bounds. */ 597 getViewportRect() { 598 const scrollPosition = this.getViewportScrollPosition(); 599 const { 600 width, 601 height 602 } = this.getViewportSize(); 603 return { 604 top: scrollPosition.top, 605 left: scrollPosition.left, 606 bottom: scrollPosition.top + height, 607 right: scrollPosition.left + width, 608 height, 609 width 610 }; 611 } 612 /** Gets the (top, left) scroll position of the viewport. */ 613 getViewportScrollPosition() { 614 if (!this._platform.isBrowser) { 615 return { 616 top: 0, 617 left: 0 618 }; 619 } 620 const document = this._document; 621 const window2 = this._getWindow(); 622 const documentElement = document.documentElement; 623 const documentRect = documentElement.getBoundingClientRect(); 624 const top = -documentRect.top || document.body.scrollTop || window2.scrollY || documentElement.scrollTop || 0; 625 const left = -documentRect.left || document.body.scrollLeft || window2.scrollX || documentElement.scrollLeft || 0; 626 return { 627 top, 628 left 629 }; 630 } 631 /** 632 * Returns a stream that emits whenever the size of the viewport changes. 633 * This stream emits outside of the Angular zone. 634 * @param throttleTime Time in milliseconds to throttle the stream. 635 */ 636 change(throttleTime = DEFAULT_RESIZE_TIME) { 637 return throttleTime > 0 ? this._change.pipe(auditTime(throttleTime)) : this._change; 638 } 639 /** Use defaultView of injected document if available or fallback to global window reference */ 640 _getWindow() { 641 return this._document.defaultView || window; 642 } 643 /** Updates the cached viewport size. */ 644 _updateViewportSize() { 645 const window2 = this._getWindow(); 646 this._viewportSize = this._platform.isBrowser ? { 647 width: window2.innerWidth,
648 height: window2.innerHeight 649 } : { 650 width: 0, 651 height: 0 652 }; 653 } 654 static \u0275fac = function ViewportRuler_Factory(__ngFactoryType__) { 655 return new (__ngFactoryType__ || _ViewportRuler)(); 656 }; 657 static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({ 658 token: _ViewportRuler, 659 factory: _ViewportRuler.\u0275fac, 660 providedIn: "root" 661 }); 662}; 663(() => { 664 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ViewportRuler, [{ 665 type: Injectable, 666 args: [{ 667 providedIn: "root" 668 }] 669 }], () => [], null); 670})(); 671var VIRTUAL_SCROLLABLE = new InjectionToken("VIRTUAL_SCROLLABLE"); 672var CdkVirtualScrollable = class _CdkVirtualScrollable extends CdkScrollable { 673 constructor() { 674 super(); 675 } 676 /** 677 * Measure the viewport size for the provided orientation. 678 * 679 * @param orientation The orientation to measure the size from. 680 */ 681 measureViewportSize(orientation) { 682 const viewportEl = this.elementRef.nativeElement; 683 return orientation === "horizontal" ? viewportEl.clientWidth : viewportEl.clientHeight; 684 } 685 static \u0275fac = function CdkVirtualScrollable_Factory(__ngFactoryType__) { 686 return new (__ngFactoryType__ || _CdkVirtualScrollable)(); 687 }; 688 static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({ 689 type: _CdkVirtualScrollable, 690 features: [\u0275\u0275InheritDefinitionFeature] 691 }); 692}; 693(() => { 694 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkVirtualScrollable, [{ 695 type: Directive 696 }], () => [], null); 697})(); 698function rangesEqual(r1, r2) { 699 return r1.start == r2.start && r1.end == r2.end; 700} 701var SCROLL_SCHEDULER = typeof requestAnimationFrame !== "undefined" ? animationFrameScheduler : asapScheduler; 702var CdkVirtualScrollViewport = class _CdkVirtualScrollViewport extends CdkVirtualScrollable { 703 elementRef = inject(ElementRef); 704 _changeDetectorRef = inject(ChangeDetectorRef); 705 _scrollStrategy = inject(VIRTUAL_SCROLL_STRATEGY, { 706 optional: true 707 }); 708 scrollable = inject(VIRTUAL_SCROLLABLE, { 709 optional: true 710 }); 711 _platform = inject(Platform); 712 /** Emits when the viewport is detached from a CdkVirtualForOf. */ 713 _detachedSubject = new Subject(); 714 /** Emits when the rendered range changes. */ 715 _renderedRangeSubject = new Subject(); 716 /** The direction the viewport scrolls. */ 717 get orientation() { 718 return this._orientation; 719 } 720 set orientation(orientation) { 721 if (this._orientation !== orientation) { 722 this._orientation = orientation; 723 this._calculateSpacerSize(); 724 } 725 } 726 _orientation = "vertical"; 727 /** 728 * Whether rendered items should persist in the DOM after scrolling out of view. By default, items 729 * will be removed. 730 */ 731 appendOnly = false; 732 // Note: we don't use the typical EventEmitter here because we need to subscribe to the scroll 733 // strategy lazily (i.e. only if the user is actually listening to the events). We do this because 734 // depending on how the strategy calculates the scrolled index, it may come at a cost to 735 // performance. 736 /** Emits when the index of the first element visible in the viewport changes. */ 737 scrolledIndexChange = new Observable((observer) => this._scrollStrategy.scrolledIndexChange.subscribe((index) => Promise.resolve().then(() => this.ngZone.run(() => observer.next(index))))); 738 /** The element that wraps the rendered content. */ 739 _contentWrapper; 740 /** A stream that emits whenever the rendered range changes. */ 741 renderedRangeStream = this._renderedRangeSubject; 742 /** 743 * The total size of all content (in pixels), including content that is not currently rendered. 744 */ 745 _totalContentSize = 0; 746 /** A string representing the `style.width` property value to be used for the spacer element. */ 747 _totalContentWidth = ""; 748 /** A string representing the `style.height` property value to be used for the spacer element. */ 749 _totalContentHeight = ""; 750 /** 751 * The CSS transform applied to the rendered subset of items so that they appear within the bounds 752 * of the visible viewport. 753 */ 754 _renderedContentTransform; 755 /** The currently rendered range of indices. */ 756 _renderedRange = { 757 start: 0, 758 end: 0 759 }; 760 /** The length of the data bound to this viewport (in number of items). */ 761 _dataLength = 0; 762 /** The size of the viewport (in pixels). */ 763 _viewportSize = 0; 764 /** the currently attached CdkVirtualScrollRepeater. */ 765 _forOf; 766 /** The last rendered content offset that was set. */ 767 _renderedContentOffset = 0; 768 /** 769 * Whether the last rendered content offset was to the end of the content (and therefore needs to 770 * be rewritten as an offset to the start of the content). 771 */ 772 _renderedContentOffsetNeedsRewrite = false;
773 /** Whether there is a pending change detection cycle. */ 774 _isChangeDetectionPending = false; 775 /** A list of functions to run after the next change detection cycle. */ 776 _runAfterChangeDetection = []; 777 /** Subscription to changes in the viewport size. */ 778 _viewportChanges = Subscription.EMPTY; 779 _injector = inject(Injector); 780 _isDestroyed = false; 781 constructor() { 782 super(); 783 const viewportRuler = inject(ViewportRuler); 784 if (!this._scrollStrategy && (typeof ngDevMode === "undefined" || ngDevMode)) { 785 throw Error('Error: cdk-virtual-scroll-viewport requires the "itemSize" property to be set.'); 786 } 787 this._viewportChanges = viewportRuler.change().subscribe(() => { 788 this.checkViewportSize(); 789 }); 790 if (!this.scrollable) { 791 this.elementRef.nativeElement.classList.add("cdk-virtual-scrollable"); 792 this.scrollable = this; 793 } 794 } 795 ngOnInit() { 796 if (!this._platform.isBrowser) { 797 return; 798 } 799 if (this.scrollable === this) { 800 super.ngOnInit(); 801 } 802 this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => { 803 this._measureViewportSize(); 804 this._scrollStrategy.attach(this); 805 this.scrollable.elementScrolled().pipe( 806 // Start off with a fake scroll event so we properly detect our initial position. 807 startWith(null), 808 // Collect multiple events into one until the next animation frame. This way if 809 // there are multiple scroll events in the same frame we only need to recheck 810 // our layout once. 811 auditTime(0, SCROLL_SCHEDULER), 812 // Usually `elementScrolled` is completed when the scrollable is destroyed, but 813 // that may not be the case if a `CdkVirtualScrollableElement` is used so we have 814 // to unsubscribe here just in case. 815 takeUntil(this._destroyed) 816 ).subscribe(() => this._scrollStrategy.onContentScrolled()); 817 this._markChangeDetectionNeeded(); 818 })); 819 } 820 ngOnDestroy() { 821 this.detach(); 822 this._scrollStrategy.detach(); 823 this._renderedRangeSubject.complete(); 824 this._detachedSubject.complete(); 825 this._viewportChanges.unsubscribe(); 826 this._isDestroyed = true; 827 super.ngOnDestroy(); 828 } 829 /** Attaches a `CdkVirtualScrollRepeater` to this viewport. */ 830 attach(forOf) { 831 if (this._forOf && (typeof ngDevMode === "undefined" || ngDevMode)) { 832 throw Error("CdkVirtualScrollViewport is already attached."); 833 } 834 this.ngZone.runOutsideAngular(() => { 835 this._forOf = forOf; 836 this._forOf.dataStream.pipe(takeUntil(this._detachedSubject)).subscribe((data) => { 837 const newLength = data.length; 838 if (newLength !== this._dataLength) { 839 this._dataLength = newLength; 840 this._scrollStrategy.onDataLengthChanged(); 841 } 842 this._doChangeDetection(); 843 }); 844 }); 845 } 846 /** Detaches the current `CdkVirtualForOf`. */ 847 detach() { 848 this._forOf = null; 849 this._detachedSubject.next(); 850 } 851 /** Gets the length of the data bound to this viewport (in number of items). */ 852 getDataLength() { 853 return this._dataLength; 854 } 855 /** Gets the size of the viewport (in pixels). */ 856 getViewportSize() { 857 return this._viewportSize; 858 } 859 // TODO(mmalerba): This is technically out of sync with what's really rendered until a render 860 // cycle happens. I'm being careful to only call it after the render cycle is complete and before 861 // setting it to something else, but its error prone and should probably be split into 862 // `pendingRange` and `renderedRange`, the latter reflecting whats actually in the DOM. 863 /** Get the current rendered range of items. */ 864 getRenderedRange() { 865 return this._renderedRange; 866 } 867 measureBoundingClientRectWithScrollOffset(from) { 868 return this.getElementRef().nativeElement.getBoundingClientRect()[from]; 869 } 870 /** 871 * Sets the total size of all content (in pixels), including content that is not currently 872 * rendered. 873 */ 874 setTotalContentSize(size) { 875 if (this._totalContentSize !== size) { 876 this._totalContentSize = size; 877 this._calculateSpacerSize(); 878 this._markChangeDetectionNeeded(); 879 } 880 } 881 /** Sets the currently rendered range of indices. */ 882 setRenderedRange(range) { 883 if (!rangesEqual(this._renderedRange, range)) { 884 if (this.appendOnly) { 885 range = { 886 start: 0, 887 end: Math.max(this._renderedRange.end, range.end) 888 }; 889 } 890 this._renderedRangeSubject.next(this._renderedRange = range); 891 this._markChangeDetectionNeeded(() => this._scrollStrategy.onContentRendered()); 892 } 893 } 894 /** 895 * Gets the offset from the start of the viewport to the start of the rendered data (in pixels). 896 */ 897 getOffsetToRenderedContentStart() { 898 return this._renderedContentOffsetNeedsRewrite ? null : this._renderedContentOffset; 899 } 900 /** 901 * Sets the offset from the start of the viewport to either the start or end of the rendered data 902 * (in pixels). 903 */ 904 setRenderedContentOffset(offset, to = "to-start") { 905 offset = this.appendOnly && to === "to-start" ? 0 : offset; 906 const isRtl = this.dir && this.dir.value == "rtl"; 907 const isHorizontal = this.orientation == "horizontal"; 908 const axis = isHorizontal ? "X" : "Y"; 909 const axisDirection = isHorizontal && isRtl ? -1 : 1; 910 let transform = `translate${axis}(${Number(axisDirection * offset)}px)`; 911 this._renderedContentOffset = offset; 912 if (to === "to-end") { 913 transform += ` translate${axis}(-100%)`; 914 this._renderedContentOffsetNeedsRewrite = true; 915 } 916 if (this._renderedContentTransform != transform) { 917 this._renderedContentTransform = transform; 918 this._markChangeDetectionNeeded(() => { 919 if (this._renderedContentOffsetNeedsRewrite) { 920 this._renderedContentOffset -= this.measureRenderedContentSize(); 921 this._renderedContentOffsetNeedsRewrite = false;
922 this.setRenderedContentOffset(this._renderedContentOffset); 923 } else { 924 this._scrollStrategy.onRenderedOffsetChanged(); 925 } 926 }); 927 } 928 } 929 /** 930 * Scrolls to the given offset from the start of the viewport. Please note that this is not always 931 * the same as setting `scrollTop` or `scrollLeft`. In a horizontal viewport with right-to-left 932 * direction, this would be the equivalent of setting a fictional `scrollRight` property. 933 * @param offset The offset to scroll to. 934 * @param behavior The ScrollBehavior to use when scrolling. Default is behavior is `auto`. 935 */ 936 scrollToOffset(offset, behavior = "auto") { 937 const options = { 938 behavior 939 }; 940 if (this.orientation === "horizontal") { 941 options.start = offset; 942 } else { 943 options.top = offset; 944 } 945 this.scrollable.scrollTo(options); 946 } 947 /** 948 * Scrolls to the offset for the given index. 949 * @param index The index of the element to scroll to. 950 * @param behavior The ScrollBehavior to use when scrolling. Default is behavior is `auto`. 951 */ 952 scrollToIndex(index, behavior = "auto") { 953 this._scrollStrategy.scrollToIndex(index, behavior); 954 } 955 /** 956 * Gets the current scroll offset from the start of the scrollable (in pixels). 957 * @param from The edge to measure the offset from. Defaults to 'top' in vertical mode and 'start' 958 * in horizontal mode. 959 */ 960 measureScrollOffset(from) { 961 let measureScrollOffset; 962 if (this.scrollable == this) { 963 measureScrollOffset = (_from) => super.measureScrollOffset(_from); 964 } else { 965 measureScrollOffset = (_from) => this.scrollable.measureScrollOffset(_from); 966 } 967 return Math.max(0, measureScrollOffset(from ?? (this.orientation === "horizontal" ? "start" : "top")) - this.measureViewportOffset()); 968 } 969 /** 970 * Measures the offset of the viewport from the scrolling container 971 * @param from The edge to measure from. 972 */ 973 measureViewportOffset(from) { 974 let fromRect; 975 const LEFT = "left"; 976 const RIGHT = "right"; 977 const isRtl = this.dir?.value == "rtl"; 978 if (from == "start") { 979 fromRect = isRtl ? RIGHT : LEFT; 980 } else if (from == "end") { 981 fromRect = isRtl ? LEFT : RIGHT; 982 } else if (from) { 983 fromRect = from; 984 } else { 985 fromRect = this.orientation === "horizontal" ? "left" : "top"; 986 } 987 const scrollerClientRect = this.scrollable.measureBoundingClientRectWithScrollOffset(fromRect); 988 const viewportClientRect = this.elementRef.nativeElement.getBoundingClientRect()[fromRect]; 989 return viewportClientRect - scrollerClientRect; 990 } 991 /** Measure the combined size of all of the rendered items. */ 992 measureRenderedContentSize() { 993 const contentEl = this._contentWrapper.nativeElement; 994 return this.orientation === "horizontal" ? contentEl.offsetWidth : contentEl.offsetHeight; 995 } 996 /** 997 * Measure the total combined size of the given range. Throws if the range includes items that are 998 * not rendered. 999 */ 1000 measureRangeSize(range) { 1001 if (!this._forOf) { 1002 return 0; 1003 } 1004 return this._forOf.measureRangeSize(range, this.orientation); 1005 } 1006 /** Update the viewport dimensions and re-render. */ 1007 checkViewportSize() { 1008 this._measureViewportSize(); 1009 this._scrollStrategy.onDataLengthChanged(); 1010 } 1011 /** Measure the viewport size. */ 1012 _measureViewportSize() { 1013 this._viewportSize = this.scrollable.measureViewportSize(this.orientation); 1014 } 1015 /** Queue up change detection to run. */ 1016 _markChangeDetectionNeeded(runAfter) { 1017 if (runAfter) { 1018 this._runAfterChangeDetection.push(runAfter); 1019 } 1020 if (!this._isChangeDetectionPending) { 1021 this._isChangeDetectionPending = true; 1022 this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => { 1023 this._doChangeDetection(); 1024 })); 1025 } 1026 } 1027 /** Run change detection. */ 1028 _doChangeDetection() { 1029 if (this._isDestroyed) { 1030 return; 1031 } 1032 this.ngZone.run(() => { 1033 this._changeDetectorRef.markForCheck(); 1034 this._contentWrapper.nativeElement.style.transform = this._renderedContentTransform; 1035 afterNextRender(() => { 1036 this._isChangeDetectionPending = false;
1037 const runAfterChangeDetection = this._runAfterChangeDetection; 1038 this._runAfterChangeDetection = []; 1039 for (const fn of runAfterChangeDetection) { 1040 fn(); 1041 } 1042 }, { 1043 injector: this._injector 1044 }); 1045 }); 1046 } 1047 /** Calculates the `style.width` and `style.height` for the spacer element. */ 1048 _calculateSpacerSize() { 1049 this._totalContentHeight = this.orientation === "horizontal" ? "" : `${this._totalContentSize}px`; 1050 this._totalContentWidth = this.orientation === "horizontal" ? `${this._totalContentSize}px` : ""; 1051 } 1052 static \u0275fac = function CdkVirtualScrollViewport_Factory(__ngFactoryType__) { 1053 return new (__ngFactoryType__ || _CdkVirtualScrollViewport)(); 1054 }; 1055 static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ 1056 type: _CdkVirtualScrollViewport, 1057 selectors: [["cdk-virtual-scroll-viewport"]], 1058 viewQuery: function CdkVirtualScrollViewport_Query(rf, ctx) { 1059 if (rf & 1) { 1060 \u0275\u0275viewQuery(_c0, 7); 1061 } 1062 if (rf & 2) { 1063 let _t; 1064 \u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._contentWrapper = _t.first); 1065 } 1066 }, 1067 hostAttrs: [1, "cdk-virtual-scroll-viewport"], 1068 hostVars: 4, 1069 hostBindings: function CdkVirtualScrollViewport_HostBindings(rf, ctx) { 1070 if (rf & 2) { 1071 \u0275\u0275classProp("cdk-virtual-scroll-orientation-horizontal", ctx.orientation === "horizontal")("cdk-virtual-scroll-orientation-vertical", ctx.orientation !== "horizontal"); 1072 } 1073 }, 1074 inputs: { 1075 orientation: "orientation", 1076 appendOnly: [2, "appendOnly", "appendOnly", booleanAttribute] 1077 }, 1078 outputs: { 1079 scrolledIndexChange: "scrolledIndexChange" 1080 }, 1081 features: [\u0275\u0275ProvidersFeature([{ 1082 provide: CdkScrollable, 1083 useFactory: (virtualScrollable, viewport) => virtualScrollable || viewport, 1084 deps: [[new Optional(), new Inject(VIRTUAL_SCROLLABLE)], _CdkVirtualScrollViewport] 1085 }]), \u0275\u0275InheritDefinitionFeature], 1086 ngContentSelectors: _c1, 1087 decls: 4, 1088 vars: 4, 1089 consts: [["contentWrapper", ""], [1, "cdk-virtual-scroll-content-wrapper"], [1, "cdk-virtual-scroll-spacer"]], 1090 template: function CdkVirtualScrollViewport_Template(rf, ctx) { 1091 if (rf & 1) { 1092 \u0275\u0275projectionDef(); 1093 \u0275\u0275elementStart(0, "div", 1, 0); 1094 \u0275\u0275projection(2); 1095 \u0275\u0275elementEnd(); 1096 \u0275\u0275element(3, "div", 2); 1097 } 1098 if (rf & 2) { 1099 \u0275\u0275advance(3); 1100 \u0275\u0275styleProp("width", ctx._totalContentWidth)("height", ctx._totalContentHeight); 1101 } 1102 }, 1103 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"], 1104 encapsulation: 2, 1105 changeDetection: 0 1106 }); 1107}; 1108(() => { 1109 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkVirtualScrollViewport, [{ 1110 type: Component, 1111 args: [{ 1112 selector: "cdk-virtual-scroll-viewport", 1113 host: { 1114 "class": "cdk-virtual-scroll-viewport", 1115 "[class.cdk-virtual-scroll-orientation-horizontal]": 'orientation === "horizontal"', 1116 "[class.cdk-virtual-scroll-orientation-vertical]": 'orientation !== "horizontal"' 1117 }, 1118 encapsulation: ViewEncapsulation.None, 1119 changeDetection: ChangeDetectionStrategy.OnPush, 1120 providers: [{ 1121 provide: CdkScrollable, 1122 useFactory: (virtualScrollable, viewport) => virtualScrollable || viewport, 1123 deps: [[new Optional(), new Inject(VIRTUAL_SCROLLABLE)], CdkVirtualScrollViewport] 1124 }], 1125 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', 1126 styles: ["cdk-virtual-scroll-viewport{display:block;position:relative;transform:translateZ(0)}.cdk-virtual-scrollable{overflow:auto;will-change:scroll-position;contain:strict}
1126.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"] 1127 }] 1128 }], () => [], { 1129 orientation: [{ 1130 type: Input 1131 }], 1132 appendOnly: [{ 1133 type: Input, 1134 args: [{ 1135 transform: booleanAttribute 1136 }] 1137 }], 1138 scrolledIndexChange: [{ 1139 type: Output 1140 }], 1141 _contentWrapper: [{ 1142 type: ViewChild, 1143 args: ["contentWrapper", { 1144 static: true 1145 }] 1146 }] 1147 }); 1148})(); 1149function getOffset(orientation, direction, node) { 1150 const el = node; 1151 if (!el.getBoundingClientRect) { 1152 return 0; 1153 } 1154 const rect = el.getBoundingClientRect(); 1155 if (orientation === "horizontal") { 1156 return direction === "start" ? rect.left : rect.right; 1157 } 1158 return direction === "start" ? rect.top : rect.bottom; 1159} 1160var CdkVirtualForOf = class _CdkVirtualForOf { 1161 _viewContainerRef = inject(ViewContainerRef); 1162 _template = inject(TemplateRef); 1163 _differs = inject(IterableDiffers); 1164 _viewRepeater = inject(_VIEW_REPEATER_STRATEGY); 1165 _viewport = inject(CdkVirtualScrollViewport, { 1166 skipSelf: true 1167 }); 1168 /** Emits when the rendered view of the data changes. */ 1169 viewChange = new Subject(); 1170 /** Subject that emits when a new DataSource instance is given. */ 1171 _dataSourceChanges = new Subject(); 1172 /** The DataSource to display. */ 1173 get cdkVirtualForOf() { 1174 return this._cdkVirtualForOf; 1175 } 1176 set cdkVirtualForOf(value) { 1177 this._cdkVirtualForOf = value; 1178 if (isDataSource(value)) { 1179 this._dataSourceChanges.next(value); 1180 } else { 1181 this._dataSourceChanges.next(new ArrayDataSource(isObservable(value) ? value : Array.from(value || []))); 1182 } 1183 } 1184 _cdkVirtualForOf; 1185 /** 1186 * The `TrackByFunction` to use for tracking changes. The `TrackByFunction` takes the index and 1187 * the item and produces a value to be used as the item's identity when tracking changes. 1188 */ 1189 get cdkVirtualForTrackBy() { 1190 return this._cdkVirtualForTrackBy; 1191 } 1192 set cdkVirtualForTrackBy(fn) { 1193 this._needsUpdate = true; 1194 this._cdkVirtualForTrackBy = fn ? (index, item) => fn(index + (this._renderedRange ? this._renderedRange.start : 0), item) : void 0; 1195 } 1196 _cdkVirtualForTrackBy; 1197 /** The template used to stamp out new elements. */ 1198 set cdkVirtualForTemplate(value) { 1199 if (value) { 1200 this._needsUpdate = true; 1201 this._template = value; 1202 } 1203 } 1204 /** 1205 * The size of the cache used to store templates that are not being used for re-use later. 1206 * Setting the cache size to `0` will disable caching. Defaults to 20 templates. 1207 */ 1208 get cdkVirtualForTemplateCacheSize() { 1209 return this._viewRepeater.viewCacheSize; 1210 } 1211 set cdkVirtualForTemplateCacheSize(size) { 1212 this._viewRepeater.viewCacheSize = coerceNumberProperty(size); 1213 } 1214 /** Emits whenever the data in the current DataSource changes. */ 1215 dataStream = this._dataSourceChanges.pipe( 1216 // Start off with null `DataSource`. 1217 startWith(null), 1218 // Bundle up the previous and current data sources so we can work with both. 1219 pairwise(), 1220 // Use `_changeDataSource` to disconnect from the previous data source and connect to the 1221 // new one, passing back a stream of data changes which we run through `switchMap` to give 1222 // us a data stream that emits the latest data from whatever the current `DataSource` is. 1223 switchMap(([prev, cur]) => this._changeDataSource(prev, cur)), 1224 // Replay the last emitted data when someone subscribes. 1225 shareReplay(1) 1226 ); 1227 /** The differ used to calculate changes to the data. */ 1228 _differ = null; 1229 /** The most recent data emitted from the DataSource. */ 1230 _data; 1231 /** The currently rendered items. */ 1232 _renderedItems; 1233 /** The currently rendered range of indices. */ 1234 _renderedRange; 1235 /** Whether the rendered data should be updated during the next ngDoCheck cycle. */ 1236 _needsUpdate = false;
1237 _destroyed = new Subject(); 1238 constructor() { 1239 const ngZone = inject(NgZone); 1240 this.dataStream.subscribe((data) => { 1241 this._data = data; 1242 this._onRenderedDataChange(); 1243 }); 1244 this._viewport.renderedRangeStream.pipe(takeUntil(this._destroyed)).subscribe((range) => { 1245 this._renderedRange = range; 1246 if (this.viewChange.observers.length) { 1247 ngZone.run(() => this.viewChange.next(this._renderedRange)); 1248 } 1249 this._onRenderedDataChange(); 1250 }); 1251 this._viewport.attach(this); 1252 } 1253 /** 1254 * Measures the combined size (width for horizontal orientation, height for vertical) of all items 1255 * in the specified range. Throws an error if the range includes items that are not currently 1256 * rendered. 1257 */ 1258 measureRangeSize(range, orientation) { 1259 if (range.start >= range.end) { 1260 return 0; 1261 } 1262 if ((range.start < this._renderedRange.start || range.end > this._renderedRange.end) && (typeof ngDevMode === "undefined" || ngDevMode)) { 1263 throw Error(`Error: attempted to measure an item that isn't rendered.`); 1264 } 1265 const renderedStartIndex = range.start - this._renderedRange.start; 1266 const rangeLen = range.end - range.start; 1267 let firstNode; 1268 let lastNode; 1269 for (let i = 0; i < rangeLen; i++) { 1270 const view = this._viewContainerRef.get(i + renderedStartIndex); 1271 if (view && view.rootNodes.length) { 1272 firstNode = lastNode = view.rootNodes[0]; 1273 break; 1274 } 1275 } 1276 for (let i = rangeLen - 1; i > -1; i--) { 1277 const view = this._viewContainerRef.get(i + renderedStartIndex); 1278 if (view && view.rootNodes.length) { 1279 lastNode = view.rootNodes[view.rootNodes.length - 1]; 1280 break; 1281 } 1282 } 1283 return firstNode && lastNode ? getOffset(orientation, "end", lastNode) - getOffset(orientation, "start", firstNode) : 0; 1284 } 1285 ngDoCheck() { 1286 if (this._differ && this._needsUpdate) { 1287 const changes = this._differ.diff(this._renderedItems); 1288 if (!changes) { 1289 this._updateContext(); 1290 } else { 1291 this._applyChanges(changes); 1292 } 1293 this._needsUpdate = false; 1294 } 1295 } 1296 ngOnDestroy() { 1297 this._viewport.detach(); 1298 this._dataSourceChanges.next(void 0); 1299 this._dataSourceChanges.complete(); 1300 this.viewChange.complete(); 1301 this._destroyed.next(); 1302 this._destroyed.complete(); 1303 this._viewRepeater.detach(); 1304 } 1305 /** React to scroll state changes in the viewport. */ 1306 _onRenderedDataChange() { 1307 if (!this._renderedRange) { 1308 return; 1309 } 1310 this._renderedItems = this._data.slice(this._renderedRange.start, this._renderedRange.end); 1311 if (!this._differ) { 1312 this._differ = this._differs.find(this._renderedItems).create((index, item) => { 1313 return this.cdkVirtualForTrackBy ? this.cdkVirtualForTrackBy(index, item) : item; 1314 }); 1315 } 1316 this._needsUpdate = true; 1317 } 1318 /** Swap out one `DataSource` for another. */ 1319 _changeDataSource(oldDs, newDs) { 1320 if (oldDs) { 1321 oldDs.disconnect(this); 1322 } 1323 this._needsUpdate = true; 1324 return newDs ? newDs.connect(this) : of(); 1325 } 1326 /** Update the `CdkVirtualForOfContext` for all views. */ 1327 _updateContext() { 1328 const count = this._data.length; 1329 let i = this._viewContainerRef.length; 1330 while (i--) { 1331 const view = this._viewContainerRef.get(i); 1332 view.context.index = this._renderedRange.start + i; 1333 view.context.count = count; 1334 this._updateComputedContextProperties(view.context); 1335 view.detectChanges(); 1336 } 1337 } 1338 /** Apply changes to the DOM. */ 1339 _applyChanges(changes) { 1340 this._viewRepeater.applyChanges(changes, this._viewContainerRef, (record, _adjustedPreviousIndex, currentIndex) => this._getEmbeddedViewArgs(record, currentIndex), (record) => record.item);
1341 changes.forEachIdentityChange((record) => { 1342 const view = this._viewContainerRef.get(record.currentIndex); 1343 view.context.$implicit = record.item; 1344 }); 1345 const count = this._data.length; 1346 let i = this._viewContainerRef.length; 1347 while (i--) { 1348 const view = this._viewContainerRef.get(i); 1349 view.context.index = this._renderedRange.start + i; 1350 view.context.count = count; 1351 this._updateComputedContextProperties(view.context); 1352 } 1353 } 1354 /** Update the computed properties on the `CdkVirtualForOfContext`. */ 1355 _updateComputedContextProperties(context) { 1356 context.first = context.index === 0; 1357 context.last = context.index === context.count - 1; 1358 context.even = context.index % 2 === 0; 1359 context.odd = !context.even; 1360 } 1361 _getEmbeddedViewArgs(record, index) { 1362 return { 1363 templateRef: this._template, 1364 context: { 1365 $implicit: record.item, 1366 // It's guaranteed that the iterable is not "undefined" or "null" because we only 1367 // generate views for elements if the "cdkVirtualForOf" iterable has elements. 1368 cdkVirtualForOf: this._cdkVirtualForOf, 1369 index: -1, 1370 count: -1, 1371 first: false, 1372 last: false, 1373 odd: false, 1374 even: false 1375 }, 1376 index 1377 }; 1378 } 1379 static ngTemplateContextGuard(directive, context) { 1380 return true; 1381 } 1382 static \u0275fac = function CdkVirtualForOf_Factory(__ngFactoryType__) { 1383 return new (__ngFactoryType__ || _CdkVirtualForOf)(); 1384 }; 1385 static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({ 1386 type: _CdkVirtualForOf, 1387 selectors: [["", "cdkVirtualFor", "", "cdkVirtualForOf", ""]], 1388 inputs: { 1389 cdkVirtualForOf: "cdkVirtualForOf", 1390 cdkVirtualForTrackBy: "cdkVirtualForTrackBy", 1391 cdkVirtualForTemplate: "cdkVirtualForTemplate", 1392 cdkVirtualForTemplateCacheSize: "cdkVirtualForTemplateCacheSize" 1393 }, 1394 features: [\u0275\u0275ProvidersFeature([{ 1395 provide: _VIEW_REPEATER_STRATEGY, 1396 useClass: _RecycleViewRepeaterStrategy 1397 }])] 1398 }); 1399}; 1400(() => { 1401 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkVirtualForOf, [{ 1402 type: Directive, 1403 args: [{ 1404 selector: "[cdkVirtualFor][cdkVirtualForOf]", 1405 providers: [{ 1406 provide: _VIEW_REPEATER_STRATEGY, 1407 useClass: _RecycleViewRepeaterStrategy 1408 }] 1409 }] 1410 }], () => [], { 1411 cdkVirtualForOf: [{ 1412 type: Input 1413 }], 1414 cdkVirtualForTrackBy: [{ 1415 type: Input 1416 }], 1417 cdkVirtualForTemplate: [{ 1418 type: Input 1419 }], 1420 cdkVirtualForTemplateCacheSize: [{ 1421 type: Input 1422 }] 1423 }); 1424})(); 1425var CdkVirtualScrollableElement = class _CdkVirtualScrollableElement extends CdkVirtualScrollable { 1426 constructor() { 1427 super(); 1428 } 1429 measureBoundingClientRectWithScrollOffset(from) { 1430 return this.getElementRef().nativeElement.getBoundingClientRect()[from] - this.measureScrollOffset(from); 1431 } 1432 static \u0275fac = function CdkVirtualScrollableElement_Factory(__ngFactoryType__) { 1433 return new (__ngFactoryType__ || _CdkVirtualScrollableElement)(); 1434 }; 1435 static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({ 1436 type: _CdkVirtualScrollableElement, 1437 selectors: [["", "cdkVirtualScrollingElement", ""]], 1438 hostAttrs: [1, "cdk-virtual-scrollable"], 1439 features: [\u0275\u0275ProvidersFeature([{ 1440 provide: VIRTUAL_SCROLLABLE, 1441 useExisting: _CdkVirtualScrollableElement 1442 }]), \u0275\u0275InheritDefinitionFeature] 1443 }); 1444}; 1445(() => { 1446 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkVirtualScrollableElement, [{ 1447 type: Directive, 1448 args: [{ 1449 selector: "[cdkVirtualScrollingElement]", 1450 providers: [{ 1451 provide: VIRTUAL_SCROLLABLE, 1452 useExisting: CdkVirtualScrollableElement 1453 }], 1454 host: { 1455 "class": "cdk-virtual-scrollable" 1456 } 1457 }] 1458 }], () => [], null); 1459})(); 1460var CdkVirtualScrollableWindow = class _CdkVirtualScrollableWindow extends CdkVirtualScrollable { 1461 constructor() { 1462 super(); 1463 const document = inject(DOCUMENT); 1464 this.elementRef = new ElementRef(document.documentElement); 1465 this._scrollElement = document; 1466 } 1467 measureBoundingClientRectWithScrollOffset(from) { 1468 return this.getElementRef().nativeElement.getBoundingClientRect()[from]; 1469 } 1470 static \u0275fac = function CdkVirtualScrollableWindow_Factory(__ngFactoryType__) { 1471 return new (__ngFactoryType__ || _CdkVirtualScrollableWindow)(); 1472 }; 1473 static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({ 1474 type: _CdkVirtualScrollableWindow, 1475 selectors: [["cdk-virtual-scroll-viewport", "scrollWindow", ""]], 1476 features: [\u0275\u0275ProvidersFeature([{ 1477 provide: VIRTUAL_SCROLLABLE, 1478 useExisting: _CdkVirtualScrollableWindow 1479 }]), \u0275\u0275InheritDefinitionFeature] 1480 }); 1481}; 1482(() => { 1483 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkVirtualScrollableWindow, [{ 1484 type: Directive, 1485 args: [{ 1486 selector: "cdk-virtual-scroll-viewport[scrollWindow]", 1487 providers: [{ 1488 provide: VIRTUAL_SCROLLABLE, 1489 useExisting: CdkVirtualScrollableWindow 1490 }] 1491 }] 1492 }], () => [], null); 1493})(); 1494var CdkScrollableModule = class _CdkScrollableModule { 1495 static \u0275fac = function CdkScrollableModule_Factory(__ngFactoryType__) { 1496 return new (__ngFactoryType__ || _CdkScrollableModule)(); 1497 }; 1498 static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({ 1499 type: _CdkScrollableModule, 1500 imports: [CdkScrollable], 1501 exports: [CdkScrollable] 1502 }); 1503 static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({}); 1504}; 1505(() => { 1506 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkScrollableModule, [{ 1507 type: NgModule, 1508 args: [{ 1509 exports: [CdkScrollable], 1510 imports: [CdkScrollable] 1511 }] 1512 }], null, null); 1513})(); 1514var ScrollingModule = class _ScrollingModule { 1515 static \u0275fac = function ScrollingModule_Factory(__ngFactoryType__) { 1516 return new (__ngFactoryType__ || _ScrollingModule)(); 1517 }; 1518 static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({ 1519 type: _ScrollingModule, 1520 imports: [BidiModule, CdkScrollableModule, CdkVirtualScrollViewport, CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollableWindow,
1520CdkVirtualScrollableElement], 1521 exports: [BidiModule, CdkScrollableModule, CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollViewport, CdkVirtualScrollableWindow, CdkVirtualScrollableElement] 1522 }); 1523 static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({ 1524 imports: [BidiModule, CdkScrollableModule, BidiModule, CdkScrollableModule] 1525 }); 1526}; 1527(() => { 1528 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ScrollingModule, [{ 1529 type: NgModule, 1530 args: [{ 1531 imports: [BidiModule, CdkScrollableModule, CdkVirtualScrollViewport, CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollableWindow, CdkVirtualScrollableElement], 1532 exports: [BidiModule, CdkScrollableModule, CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollViewport, CdkVirtualScrollableWindow, CdkVirtualScrollableElement] 1533 }] 1534 }], null, null); 1535})(); 1536 1537export { 1538 ScrollDispatcher, 1539 CdkScrollable, 1540 ViewportRuler, 1541 CdkScrollableModule, 1542 ScrollingModule 1543}; 1544//# sourceMappingURL=chunk-UD5AJOAM.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.