@scion/components 21.1.1 → 22.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, DOCUMENT, NgZone, Injectable, input, ElementRef, Renderer2, effect, untracked, Directive, DestroyRef, viewChild, signal, computed, ChangeDetectionStrategy, Component, output, ViewEncapsulation } from '@angular/core';
3
- import { fromEvent, merge, mergeWith, timer, of } from 'rxjs';
4
- import { debounceTime, startWith, map, distinctUntilChanged, first, withLatestFrom, takeWhile, takeUntil, switchMap } from 'rxjs/operators';
2
+ import { inject, DOCUMENT, NgZone, Injectable, input, ElementRef, Renderer2, effect, untracked, Directive, DestroyRef, viewChild, computed, signal, Component, output, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core';
3
+ import { fromEvent, race, tap, merge, finalize, timer, exhaustMap, of, concatWith, mergeWith } from 'rxjs';
4
+ import { debounceTime, startWith, map, distinctUntilChanged, takeUntil, withLatestFrom, switchMap } from 'rxjs/operators';
5
5
  import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
- import { subscribeIn, filterArray } from '@scion/toolkit/operators';
6
+ import { subscribeIn } from '@scion/toolkit/operators';
7
7
  import { coerceElement } from '@angular/cdk/coercion';
8
8
  import { fromResize$, fromMutation$ } from '@scion/toolkit/observable';
9
9
  import { CdkScrollable } from '@angular/cdk/scrolling';
@@ -77,10 +77,10 @@ class SciNativeScrollbarTrackSizeProvider {
77
77
  map(() => this.computeTrackSize()), distinctUntilChanged((t1, t2) => t1?.hScrollbarTrackHeight === t2?.hScrollbarTrackHeight && t1?.vScrollbarTrackWidth === t2?.vScrollbarTrackWidth));
78
78
  return toSignal(trackSize$, { initialValue: null });
79
79
  }
80
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: SciNativeScrollbarTrackSizeProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
81
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: SciNativeScrollbarTrackSizeProvider, providedIn: 'root' });
80
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SciNativeScrollbarTrackSizeProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
81
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SciNativeScrollbarTrackSizeProvider, providedIn: 'root' });
82
82
  }
83
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: SciNativeScrollbarTrackSizeProvider, decorators: [{
83
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SciNativeScrollbarTrackSizeProvider, decorators: [{
84
84
  type: Injectable,
85
85
  args: [{ providedIn: 'root' }]
86
86
  }], ctorParameters: () => [] });
@@ -121,7 +121,7 @@ class SciScrollableDirective {
121
121
  * Controls whether to display native scrollbars.
122
122
  * Has no effect if the native scrollbar sits on top of the content, e.g. in OS X.
123
123
  */
124
- displayNativeScrollbar = input(false, ...(ngDevMode ? [{ debugName: "displayNativeScrollbar", alias: 'sciScrollableDisplayNativeScrollbar' }] : [{ alias: 'sciScrollableDisplayNativeScrollbar' }]));
124
+ displayNativeScrollbar = input(false, { ...(ngDevMode ? { debugName: "displayNativeScrollbar" } : /* istanbul ignore next */ {}), alias: 'sciScrollableDisplayNativeScrollbar' });
125
125
  _host = inject((ElementRef)).nativeElement;
126
126
  _renderer = inject(Renderer2);
127
127
  _nativeScrollbarTrackSizeProvider = inject(SciNativeScrollbarTrackSizeProvider);
@@ -174,10 +174,10 @@ class SciScrollableDirective {
174
174
  setStyle(element, style) {
175
175
  Object.keys(style).forEach(key => this._renderer.setStyle(element, key, style[key]));
176
176
  }
177
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: SciScrollableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
178
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.0", type: SciScrollableDirective, isStandalone: true, selector: "[sciScrollable]", inputs: { displayNativeScrollbar: { classPropertyName: "displayNativeScrollbar", publicName: "sciScrollableDisplayNativeScrollbar", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
177
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SciScrollableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
178
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.1", type: SciScrollableDirective, isStandalone: true, selector: "[sciScrollable]", inputs: { displayNativeScrollbar: { classPropertyName: "displayNativeScrollbar", publicName: "sciScrollableDisplayNativeScrollbar", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
179
179
  }
180
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: SciScrollableDirective, decorators: [{
180
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SciScrollableDirective, decorators: [{
181
181
  type: Directive,
182
182
  args: [{ selector: '[sciScrollable]' }]
183
183
  }], ctorParameters: () => [], propDecorators: { displayNativeScrollbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "sciScrollableDisplayNativeScrollbar", required: false }] }] } });
@@ -195,7 +195,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
195
195
  * Renders a vertical or horizontal scrollbar.
196
196
  *
197
197
  * The scrollbar features the following functionality:
198
- * - allows to move the thumb by mouse or touch
198
+ * - allows to move the thumb by mouse
199
199
  * - enlarges the thumb if the mouse pointer is near the thumb
200
200
  * - allows paging on mousedown on the scroll track
201
201
  *
@@ -204,7 +204,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
204
204
  * To customize the default look of SCION components or support different themes, configure the `@scion/components` SCSS module in `styles.scss`.
205
205
  * To style a specific `sci-scrollbar` component, the following CSS variables can be set directly on the component.
206
206
  *
207
- * - sci-scrollbar-color: Sets the color of the scrollbar.
207
+ * - --sci-scrollbar-color: Sets the color of the scrollbar.
208
208
  *
209
209
  * Example:
210
210
  *
@@ -229,95 +229,111 @@ class SciScrollbarComponent {
229
229
  /**
230
230
  * Specifies the direction of the scrollbar. Defaults to a vertical scrollbar.
231
231
  */
232
- direction = input('vscroll', ...(ngDevMode ? [{ debugName: "direction" }] : []));
232
+ direction = input('vscroll', /* @ts-ignore */
233
+ ...(ngDevMode ? [{ debugName: "direction" }] : /* istanbul ignore next */ []));
233
234
  /**
234
- * The viewport to provide scrollbars for.
235
+ * Specifies the viewport associated with the scrollbar.
235
236
  */
236
- viewport = input.required(...(ngDevMode ? [{ debugName: "viewport" }] : []));
237
+ viewport = input.required(/* @ts-ignore */
238
+ ...(ngDevMode ? [{ debugName: "viewport" }] : /* istanbul ignore next */ []));
237
239
  _host = inject(ElementRef).nativeElement;
238
240
  _document = inject(DOCUMENT);
239
241
  _zone = inject(NgZone);
240
242
  _destroyRef = inject(DestroyRef);
241
243
  _thumbElement = viewChild.required('thumb_handle');
242
- _lastDragPosition = signal(null, ...(ngDevMode ? [{ debugName: "_lastDragPosition" }] : []));
243
- vertical = computed(() => this.direction() === 'vscroll', ...(ngDevMode ? [{ debugName: "vertical" }] : []));
244
- horizontal = computed(() => !this.vertical(), ...(ngDevMode ? [{ debugName: "horizontal" }] : []));
245
- scrolling = computed(() => this._lastDragPosition() !== null, ...(ngDevMode ? [{ debugName: "scrolling" }] : []));
246
- _overflow = false;
247
- _thumbSizeFr = 0;
248
- _thumbPositionFr = 0;
244
+ vertical = computed(() => this.direction() === 'vscroll', /* @ts-ignore */
245
+ ...(ngDevMode ? [{ debugName: "vertical" }] : /* istanbul ignore next */ []));
246
+ horizontal = computed(() => !this.vertical(), /* @ts-ignore */
247
+ ...(ngDevMode ? [{ debugName: "horizontal" }] : /* istanbul ignore next */ []));
248
+ scrolling = signal(false, /* @ts-ignore */
249
+ ...(ngDevMode ? [{ debugName: "scrolling" }] : /* istanbul ignore next */ []));
250
+ overflow = signal(false, /* @ts-ignore */
251
+ ...(ngDevMode ? [{ debugName: "overflow" }] : /* istanbul ignore next */ []));
252
+ thumbSizeFr = signal(0, /* @ts-ignore */
253
+ ...(ngDevMode ? [{ debugName: "thumbSizeFr" }] : /* istanbul ignore next */ []));
254
+ thumbPositionFr = signal(0, /* @ts-ignore */
255
+ ...(ngDevMode ? [{ debugName: "thumbPositionFr" }] : /* istanbul ignore next */ []));
249
256
  constructor() {
250
257
  this.installScrollPositionRenderer();
251
258
  }
252
259
  /**
253
- * Computes the scroll position and updates CSS variables to render the scroll position in the UI.
260
+ * Computes the scroll position and updates CSS variables to render the scroll position.
254
261
  */
255
262
  renderScrollPosition() {
256
263
  NgZone.assertNotInAngularZone();
257
- const viewportSize = this.viewportSize;
258
- const viewportClientSize = this.viewportClientSize;
259
- const thumbPositionFr = this.scrollPosition / viewportClientSize;
260
- const thumbSizeFr = viewportSize / viewportClientSize;
261
- const overflow = viewportClientSize > viewportSize;
262
- if (thumbPositionFr !== this._thumbPositionFr || thumbSizeFr !== this._thumbSizeFr) {
263
- this._thumbPositionFr = thumbPositionFr;
264
- this._thumbSizeFr = thumbSizeFr;
265
- this.setCssVariable('--ɵsci-scrollbar-thumb-position-fr', thumbPositionFr);
266
- this.setCssVariable('--ɵsci-scrollbar-thumb-size-fr', thumbSizeFr);
267
- }
268
- if (overflow !== this._overflow) {
269
- this._overflow = overflow;
270
- overflow ? this._host.classList.add('overflow') : this._host.classList.remove('overflow');
271
- }
272
- }
273
- onTouchStart(event) {
274
- event.preventDefault();
275
- this._lastDragPosition.set(this.vertical() ? event.touches[0].screenY : event.touches[0].screenX);
264
+ const viewportSize = this.viewportSize();
265
+ const viewportClientSize = this.viewportClientSize();
266
+ this.thumbPositionFr.set(this.viewportScrollPosition() / viewportClientSize);
267
+ this.thumbSizeFr.set(viewportSize / viewportClientSize);
268
+ this.overflow.set(viewportClientSize > viewportSize);
276
269
  }
277
- onTouchMove(event) {
278
- event.preventDefault();
279
- const newDragPositionPx = this.vertical() ? event.touches[0].screenY : event.touches[0].screenX;
280
- const scrollbarPanPx = newDragPositionPx - this._lastDragPosition();
281
- const viewportPanPx = this.toViewportPanPx(scrollbarPanPx);
282
- this._lastDragPosition.set(newDragPositionPx);
283
- this.moveViewportClient(viewportPanPx);
284
- }
285
- onTouchEnd(event) {
286
- event.preventDefault();
287
- this._lastDragPosition.set(null);
288
- }
289
- onMouseDown(mousedownEvent) {
270
+ /**
271
+ * Method invoked when clicking on the scrollbar thumb.
272
+ */
273
+ onThumbMouseDown(mousedownEvent) {
290
274
  if (mousedownEvent.button !== 0) {
291
275
  return;
292
276
  }
277
+ this.scrolling.set(true);
278
+ // Prevent text selection during drag.
293
279
  mousedownEvent.preventDefault();
294
- this._lastDragPosition.set(this.vertical() ? mousedownEvent.screenY : mousedownEvent.screenX);
295
- // Listen for 'mousemove' events
296
- const mousemoveListener = merge(fromEvent(this._document, 'mousemove'), fromEvent(this._document, 'sci-mousemove'))
297
- .pipe(subscribeIn(fn => this._zone.runOutsideAngular(fn)), takeUntilDestroyed(this._destroyRef))
280
+ // Memoize offset where thumb was clicked.
281
+ const [thumbStartPosition] = this.thumbPosition();
282
+ const thumbStartOffset = (this.vertical() ? mousedownEvent.pageY : mousedownEvent.pageX) - thumbStartPosition;
283
+ // Stop scrolling when releasing the mouse. Handle the event in the capture phase and stop propagation to not close a potential overlay when releasing the mouse outside the overlay.
284
+ const mouseUp$ = race(fromEvent(this._document, 'mouseup', { capture: true, once: true }), fromEvent(this._document, 'sci-mouseup', { once: true }))
285
+ .pipe(tap(mouseupEvent => mouseupEvent.stopPropagation()));
286
+ // Track pointer until mouse release.
287
+ merge(fromEvent(this._document, 'mousemove'), fromEvent(this._document, 'sci-mousemove'))
288
+ .pipe(subscribeIn(fn => this._zone.runOutsideAngular(fn)), takeUntilDestroyed(this._destroyRef), takeUntil(mouseUp$), finalize(() => this.scrolling.set(false)))
298
289
  .subscribe(mousemoveEvent => {
299
290
  NgZone.assertNotInAngularZone();
291
+ // Prevent user agent scrolling while during drag.
300
292
  mousemoveEvent.preventDefault();
301
- const newDragPositionPx = this.vertical() ? mousemoveEvent.screenY : mousemoveEvent.screenX;
302
- const scrollbarPanPx = newDragPositionPx - this._lastDragPosition();
303
- const viewportPanPx = this.toViewportPanPx(scrollbarPanPx);
304
- this._lastDragPosition.set(newDragPositionPx);
305
- this.moveViewportClient(viewportPanPx);
293
+ // Calculate new thumb position.
294
+ const pointerPosition = this.vertical() ? mousemoveEvent.pageY : mousemoveEvent.pageX;
295
+ this.scrollViewport(pointerPosition - thumbStartOffset);
306
296
  });
307
- // Listen for 'mouseup' events; use 'capture phase' and 'stop propagation' to not close overlays
308
- merge(fromEvent(this._document, 'mouseup', { capture: true }), fromEvent(this._document, 'sci-mouseup'))
309
- .pipe(subscribeIn(fn => this._zone.runOutsideAngular(fn)), first(), takeUntilDestroyed(this._destroyRef))
310
- .subscribe(mouseupEvent => {
297
+ }
298
+ /**
299
+ * Method invoked when clicking on the scrollbar track.
300
+ *
301
+ * Scrolls in discrete steps to the pointer, then switches to regular scrolling until releasing the mouse.
302
+ */
303
+ onScrollTrackMouseDown(event) {
304
+ const mouseMove$ = merge(fromEvent(this._document, 'mousemove'), fromEvent(this._document, 'sci-mousemove'));
305
+ // Stop scrolling when releasing the mouse. Handle the event in the capture phase and stop propagation to not close a potential overlay when releasing the mouse outside the overlay.
306
+ const mouseUp$ = race(fromEvent(this._document, 'mouseup', { capture: true, once: true }), fromEvent(this._document, 'sci-mouseup', { once: true }))
307
+ .pipe(tap(mouseupEvent => mouseupEvent.stopPropagation()));
308
+ // Prevent text selection during drag.
309
+ event.preventDefault();
310
+ this.scrolling.set(true);
311
+ // Scroll in discrete steps to the pointer position, then switch to regular scrolling.
312
+ timer(250, 50)
313
+ .pipe(
314
+ // Track current pointer position.
315
+ withLatestFrom(mouseMove$.pipe(startWith(event)), (_tick, event) => event),
316
+ // Scroll immediately on initial click.
317
+ startWith(event), subscribeIn(fn => this._zone.runOutsideAngular(fn)), exhaustMap(event => {
318
+ const pointerPosition = this.vertical() ? event.pageY : event.pageX;
319
+ const [thumbStartPosition, thumbEndPosition] = this.thumbPosition();
320
+ const thumbSize = thumbEndPosition - thumbStartPosition;
321
+ // Step scroll until the pointer hits the thumb.
322
+ if (!isBetween(pointerPosition, { from: thumbStartPosition - thumbSize, to: thumbEndPosition + thumbSize })) {
323
+ const scrollingDown = pointerPosition > thumbEndPosition;
324
+ return of(scrollingDown ? thumbStartPosition + thumbSize : thumbStartPosition - thumbSize);
325
+ }
326
+ // Switch to "smooth scrolling" following the pointer.
327
+ return of(event)
328
+ .pipe(concatWith(mouseMove$), map(event => (this.vertical() ? event.pageY : event.pageX) - (thumbSize / 2)));
329
+ }),
330
+ // Stop on mouse release.
331
+ takeUntil(mouseUp$), finalize(() => this.scrolling.set(false)))
332
+ .subscribe((thumbPosition) => {
311
333
  NgZone.assertNotInAngularZone();
312
- mouseupEvent.stopPropagation();
313
- mousemoveListener.unsubscribe();
314
- this._lastDragPosition.set(null);
334
+ this.scrollViewport(thumbPosition);
315
335
  });
316
336
  }
317
- onScrollTrackMouseDown(event, direction) {
318
- const signum = (direction === 'up' ? -1 : 1);
319
- this.scrollWhileMouseDown(this.toViewportPanPx(signum * this.thumbSize), event);
320
- }
321
337
  /**
322
338
  * Renders the current scroll position when the viewport is scrolled.
323
339
  */
@@ -333,85 +349,101 @@ class SciScrollbarComponent {
333
349
  });
334
350
  }
335
351
  /**
336
- * Projects the given scrollbar scroll pixels into viewport scroll pixels.
337
- */
338
- toViewportPanPx(scrollbarPanPx) {
339
- const scrollRangePx = this.trackSize - this.thumbSize;
340
- const scrollRatio = scrollbarPanPx / scrollRangePx;
341
- return scrollRatio * (this.viewportClientSize - this.viewportSize);
342
- }
343
- /**
344
- * Moves the viewport client by the specified numbers of pixels.
352
+ * Moves the scrollbar thumb to the specified position, scrolling the viewport accordingly.
353
+ *
354
+ * The thumb position must be given in page coordinates relative to the top-left corner of the document.
345
355
  */
346
- moveViewportClient(viewportPanPx) {
356
+ scrollViewport(thumbPosition) {
357
+ const [scrollbarComponentStartPosition] = this.scrollbarComponentPosition();
358
+ const scrollbarBorderWidth = this.vertical() ? this._host.clientTop : this._host.clientLeft;
359
+ const scrollRatio = clamp((thumbPosition - scrollbarComponentStartPosition - scrollbarBorderWidth) / (this.trackSize() - this.thumbSize()), { min: 0, max: 1 });
360
+ const viewportScrollPosition = scrollRatio * (this.viewportClientSize() - this.viewportSize());
347
361
  if (this.vertical()) {
348
- this.viewport().scrollTop += viewportPanPx;
362
+ this.viewport().scrollTop = viewportScrollPosition;
349
363
  }
350
364
  else {
351
- this.viewport().scrollLeft += viewportPanPx;
365
+ this.viewport().scrollLeft = viewportScrollPosition;
352
366
  }
353
367
  }
354
368
  /**
355
- * Indicates if the content overflows.
369
+ * Returns the position of this component in page coordinates.
370
+ *
371
+ * Returned coordinates are relative to the top-left corner of the document.
372
+ * Depending on the scrollbar orientation, returned coordinates are `[top, bottom]` or `[left, right]`.
356
373
  */
357
- get overflow() {
358
- return this._overflow;
374
+ scrollbarComponentPosition() {
375
+ const boundingBox = this._host.getBoundingClientRect();
376
+ return this.vertical() ? [boundingBox.top + window.scrollY, boundingBox.bottom + window.scrollY] : [boundingBox.left + window.scrollX, boundingBox.right + window.scrollX];
359
377
  }
360
378
  /**
361
- * Scrolls continuously while holding the mouse pressed, or until the mouse leaves the scrolltrack.
379
+ * Returns the size of the viewport in pixels.
380
+ *
381
+ * The viewport is the container for scrollable content (viewport client), displaying scrollbars if it overflows.
382
+ * Depending on the scrollbar orientation, the returned size is `viewport.clientHeight` or `viewport.clientWidth`.
362
383
  */
363
- scrollWhileMouseDown(viewportScrollPx, mousedownEvent) {
364
- // The `EventTarget` type of `Event.target` is not yet compatible with `FromEventTarget` used in `fromEvent`.
365
- // This will be fixed in rxjs version 7.0.0. Refer to https://github.com/ReactiveX/rxjs/commit/5f022d784570684632e6fd5ae247fc259ee34c4b
366
- // for more details.
367
- const scrollTrackElement = mousedownEvent.target;
368
- // scroll continuously every 50ms after an initial delay of 250ms
369
- timer(250, 50)
370
- .pipe(
371
- // continue chain with latest mouse event
372
- withLatestFrom(merge(of(mousedownEvent), fromEvent(scrollTrackElement, 'mousemove')), (tick, event) => event),
373
- // start immediately
374
- startWith(mousedownEvent),
375
- // stop scrolling if the thumb hits the mouse pointer position
376
- takeWhile((event) => scrollTrackElement === this._document.elementFromPoint(event.clientX, event.clientY)), debounceTime(10),
377
- // stop scrolling on mouseout or mouseup
378
- takeUntil(merge(fromEvent(scrollTrackElement, 'mouseout'), fromEvent(scrollTrackElement, 'mouseup'))))
379
- .subscribe(() => {
380
- this.moveViewportClient(viewportScrollPx);
381
- });
382
- }
383
- setCssVariable(key, value) {
384
- this._host.style.setProperty(key, `${value}`);
385
- }
386
- get viewportSize() {
384
+ viewportSize() {
387
385
  return this.vertical() ? this.viewport().clientHeight : this.viewport().clientWidth;
388
386
  }
389
- get viewportClientSize() {
387
+ /**
388
+ * Returns the size of the viewport client in pixels.
389
+ *
390
+ * The viewport client represents scrollable content displayed in the viewport.
391
+ * Depending on the scrollbar orientation, the returned size is `viewport.scrollHeight` or `viewport.scrollWidth`.
392
+ */
393
+ viewportClientSize() {
390
394
  return this.vertical() ? this.viewport().scrollHeight : this.viewport().scrollWidth;
391
395
  }
392
- get scrollPosition() {
396
+ /**
397
+ * Returns the viewport's scroll position in pixels.
398
+ *
399
+ * Depending on the scrollbar orientation, the returned position is `viewport.scrollTop` or `viewport.scrollLeft`.
400
+ */
401
+ viewportScrollPosition() {
393
402
  return this.vertical() ? this.viewport().scrollTop : this.viewport().scrollLeft;
394
403
  }
395
- get thumbSize() {
404
+ /**
405
+ * Returns the size of the scrollbar thumb in pixels.
406
+ *
407
+ * The thumb is the handle used to scroll the scrollbar.
408
+ */
409
+ thumbSize() {
396
410
  const thumbElement = this._thumbElement().nativeElement;
397
- return this.vertical() ? thumbElement.clientHeight : thumbElement.clientWidth;
411
+ return this.vertical() ? thumbElement.offsetHeight : thumbElement.offsetWidth;
398
412
  }
399
- get trackSize() {
413
+ /**
414
+ * Returns the current thumb position in page coordinates.
415
+ *
416
+ * Returned coordinates are relative to the top-left corner of the document.
417
+ * Depending on the scrollbar orientation, returned coordinates are `[top, bottom]` or `[left, right]`.
418
+ */
419
+ thumbPosition() {
420
+ const boundingBox = this._thumbElement().nativeElement.getBoundingClientRect();
421
+ return this.vertical() ? [boundingBox.top + window.scrollY, boundingBox.bottom + window.scrollY] : [boundingBox.left + window.scrollX, boundingBox.right + window.scrollX];
422
+ }
423
+ /**
424
+ * Returns the size of the scrollbar track in pixels.
425
+ *
426
+ * The scrollbar track is the track along which the scrollbar thumb moves.
427
+ */
428
+ trackSize() {
400
429
  return this.vertical() ? this._host.clientHeight : this._host.clientWidth;
401
430
  }
402
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: SciScrollbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
403
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.0.0", type: SciScrollbarComponent, isStandalone: true, selector: "sci-scrollbar", inputs: { direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, viewport: { classPropertyName: "viewport", publicName: "viewport", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "class.vertical": "vertical()", "class.horizontal": "horizontal()", "class.scrolling": "scrolling()" } }, viewQueries: [{ propertyName: "_thumbElement", first: true, predicate: ["thumb_handle"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- scrolltrack to move the viewport client upwards (paging) -->\n<div class=\"scrolltrack-start\" (mousedown)=\"onScrollTrackMouseDown($event, 'up')\"></div>\n\n<!-- scrollthumb -->\n<div #thumb_handle\n class=\"thumb-handle\"\n [class.vertical]=\"vertical()\"\n [class.horizontal]=\"horizontal()\"\n (mousedown)=\"onMouseDown($event)\"\n (touchstart)=\"onTouchStart($event)\"\n (touchmove)=\"onTouchMove($event)\"\n (touchend)=\"onTouchEnd($event)\"\n (touchcancel)=\"onTouchEnd($event)\">\n <div class=\"thumb\"\n [class.vertical]=\"vertical()\"\n [class.horizontal]=\"horizontal()\">\n </div>\n</div>\n\n<!-- scrolltrack to move the viewport client downwards (paging) -->\n<div class=\"scrolltrack-end\" (mousedown)=\"onScrollTrackMouseDown($event, 'down')\"></div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;border:2px solid transparent;box-sizing:border-box;--\\275sci-scrollbar-thumb-position-fr: 0;--\\275sci-scrollbar-thumb-size-fr: 0}:host.vertical{flex-direction:column}:host.horizontal{flex-direction:row}:host>div.scrolltrack-start{flex-grow:var(--\\275sci-scrollbar-thumb-position-fr)}:host>div.thumb-handle{flex-basis:20px;display:flex;flex-grow:var(--\\275sci-scrollbar-thumb-size-fr);align-items:center}:host>div.thumb-handle.vertical{flex-direction:column}:host>div.thumb-handle.horizontal{flex-direction:row}:host>div.thumb-handle>div.thumb{flex:auto;border-radius:4px;background-color:var(--sci-scrollbar-color);opacity:.4;transition-duration:125ms;transition-property:width,height;transition-timing-function:ease-out}:host>div.thumb-handle>div.thumb.vertical{width:60%}:host>div.thumb-handle>div.thumb.horizontal{height:60%}:host>div.scrolltrack-end{flex-grow:calc(1 - (var(--\\275sci-scrollbar-thumb-position-fr) + var(--\\275sci-scrollbar-thumb-size-fr)))}:host-context:not(.overflow){display:none}:host-context:hover>div.thumb-handle>div.thumb,:host-context(.scrolling)>div.thumb-handle>div.thumb{background-color:var(--sci-scrollbar-color);opacity:.75}:host-context:hover>div.thumb-handle>div.thumb.vertical,:host-context(.scrolling)>div.thumb-handle>div.thumb.vertical{width:100%}:host-context:hover>div.thumb-handle>div.thumb.horizontal,:host-context(.scrolling)>div.thumb-handle>div.thumb.horizontal{height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
431
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SciScrollbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
432
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.1", type: SciScrollbarComponent, isStandalone: true, selector: "sci-scrollbar", inputs: { direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, viewport: { classPropertyName: "viewport", publicName: "viewport", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "class.vertical": "vertical()", "class.horizontal": "horizontal()", "class.scrolling": "scrolling()", "class.overflow": "overflow()", "style.--\u0275sci-scrollbar-thumb-position-fr": "thumbPositionFr()", "style.--\u0275sci-scrollbar-thumb-size-fr": "thumbSizeFr()" } }, viewQueries: [{ propertyName: "_thumbElement", first: true, predicate: ["thumb_handle"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- scrolltrack for moving the viewport client upwards (paging) -->\n<div class=\"scrolltrack\" (mousedown)=\"onScrollTrackMouseDown($event)\"></div>\n\n<!-- scrollthumb -->\n<div #thumb_handle\n class=\"thumb-handle\"\n [class.vertical]=\"vertical()\"\n [class.horizontal]=\"horizontal()\"\n (mousedown)=\"onThumbMouseDown($event)\">\n <div class=\"thumb e2e-thumb\"\n [class.vertical]=\"vertical()\"\n [class.horizontal]=\"horizontal()\">\n </div>\n</div>\n\n<!-- scrolltrack for moving the viewport client downwards (paging) -->\n<div class=\"scrolltrack\" (mousedown)=\"onScrollTrackMouseDown($event)\"></div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;box-sizing:border-box;transition-duration:1s;transition-property:opacity;transition-timing-function:ease-out;--\\275sci-scrollbar-thumb-position-fr: 0;--\\275sci-scrollbar-thumb-size-fr: 0}:host.vertical{flex-direction:column;width:8px}:host.horizontal{flex-direction:row;height:8px}:host>div.scrolltrack:first-child{flex-grow:var(--\\275sci-scrollbar-thumb-position-fr)}:host:not(.overflow){display:none}:host:hover>div.thumb-handle>div.thumb,:host.scrolling>div.thumb-handle>div.thumb{background-color:var(--sci-scrollbar-color);opacity:.75}:host:hover>div.thumb-handle>div.thumb.vertical,:host.scrolling>div.thumb-handle>div.thumb.vertical{width:100%}:host:hover>div.thumb-handle>div.thumb.horizontal,:host.scrolling>div.thumb-handle>div.thumb.horizontal{height:100%}:host>div.thumb-handle{display:flex;flex-grow:var(--\\275sci-scrollbar-thumb-size-fr);align-items:center}:host>div.thumb-handle.vertical{flex-direction:column;min-height:20px}:host>div.thumb-handle.horizontal{flex-direction:row;min-width:20px}:host>div.thumb-handle>div.thumb{flex:auto;border-radius:4px;background-color:var(--sci-scrollbar-color);opacity:.4;transition-duration:125ms;transition-property:width,height;transition-timing-function:ease-out}:host>div.thumb-handle>div.thumb.vertical{width:60%}:host>div.thumb-handle>div.thumb.horizontal{height:60%}:host>div.scrolltrack:last-child{flex-grow:calc(1 - (var(--\\275sci-scrollbar-thumb-position-fr) + var(--\\275sci-scrollbar-thumb-size-fr)))}\n"] });
404
433
  }
405
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: SciScrollbarComponent, decorators: [{
434
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SciScrollbarComponent, decorators: [{
406
435
  type: Component,
407
- args: [{ selector: 'sci-scrollbar', changeDetection: ChangeDetectionStrategy.OnPush, host: {
436
+ args: [{ selector: 'sci-scrollbar', host: {
408
437
  '[class.vertical]': 'vertical()',
409
438
  '[class.horizontal]': 'horizontal()',
410
439
  '[class.scrolling]': 'scrolling()',
411
- }, template: "<!-- scrolltrack to move the viewport client upwards (paging) -->\n<div class=\"scrolltrack-start\" (mousedown)=\"onScrollTrackMouseDown($event, 'up')\"></div>\n\n<!-- scrollthumb -->\n<div #thumb_handle\n class=\"thumb-handle\"\n [class.vertical]=\"vertical()\"\n [class.horizontal]=\"horizontal()\"\n (mousedown)=\"onMouseDown($event)\"\n (touchstart)=\"onTouchStart($event)\"\n (touchmove)=\"onTouchMove($event)\"\n (touchend)=\"onTouchEnd($event)\"\n (touchcancel)=\"onTouchEnd($event)\">\n <div class=\"thumb\"\n [class.vertical]=\"vertical()\"\n [class.horizontal]=\"horizontal()\">\n </div>\n</div>\n\n<!-- scrolltrack to move the viewport client downwards (paging) -->\n<div class=\"scrolltrack-end\" (mousedown)=\"onScrollTrackMouseDown($event, 'down')\"></div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;border:2px solid transparent;box-sizing:border-box;--\\275sci-scrollbar-thumb-position-fr: 0;--\\275sci-scrollbar-thumb-size-fr: 0}:host.vertical{flex-direction:column}:host.horizontal{flex-direction:row}:host>div.scrolltrack-start{flex-grow:var(--\\275sci-scrollbar-thumb-position-fr)}:host>div.thumb-handle{flex-basis:20px;display:flex;flex-grow:var(--\\275sci-scrollbar-thumb-size-fr);align-items:center}:host>div.thumb-handle.vertical{flex-direction:column}:host>div.thumb-handle.horizontal{flex-direction:row}:host>div.thumb-handle>div.thumb{flex:auto;border-radius:4px;background-color:var(--sci-scrollbar-color);opacity:.4;transition-duration:125ms;transition-property:width,height;transition-timing-function:ease-out}:host>div.thumb-handle>div.thumb.vertical{width:60%}:host>div.thumb-handle>div.thumb.horizontal{height:60%}:host>div.scrolltrack-end{flex-grow:calc(1 - (var(--\\275sci-scrollbar-thumb-position-fr) + var(--\\275sci-scrollbar-thumb-size-fr)))}:host-context:not(.overflow){display:none}:host-context:hover>div.thumb-handle>div.thumb,:host-context(.scrolling)>div.thumb-handle>div.thumb{background-color:var(--sci-scrollbar-color);opacity:.75}:host-context:hover>div.thumb-handle>div.thumb.vertical,:host-context(.scrolling)>div.thumb-handle>div.thumb.vertical{width:100%}:host-context:hover>div.thumb-handle>div.thumb.horizontal,:host-context(.scrolling)>div.thumb-handle>div.thumb.horizontal{height:100%}\n"] }]
440
+ '[class.overflow]': 'overflow()',
441
+ '[style.--ɵsci-scrollbar-thumb-position-fr]': 'thumbPositionFr()',
442
+ '[style.--ɵsci-scrollbar-thumb-size-fr]': 'thumbSizeFr()',
443
+ }, template: "<!-- scrolltrack for moving the viewport client upwards (paging) -->\n<div class=\"scrolltrack\" (mousedown)=\"onScrollTrackMouseDown($event)\"></div>\n\n<!-- scrollthumb -->\n<div #thumb_handle\n class=\"thumb-handle\"\n [class.vertical]=\"vertical()\"\n [class.horizontal]=\"horizontal()\"\n (mousedown)=\"onThumbMouseDown($event)\">\n <div class=\"thumb e2e-thumb\"\n [class.vertical]=\"vertical()\"\n [class.horizontal]=\"horizontal()\">\n </div>\n</div>\n\n<!-- scrolltrack for moving the viewport client downwards (paging) -->\n<div class=\"scrolltrack\" (mousedown)=\"onScrollTrackMouseDown($event)\"></div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;box-sizing:border-box;transition-duration:1s;transition-property:opacity;transition-timing-function:ease-out;--\\275sci-scrollbar-thumb-position-fr: 0;--\\275sci-scrollbar-thumb-size-fr: 0}:host.vertical{flex-direction:column;width:8px}:host.horizontal{flex-direction:row;height:8px}:host>div.scrolltrack:first-child{flex-grow:var(--\\275sci-scrollbar-thumb-position-fr)}:host:not(.overflow){display:none}:host:hover>div.thumb-handle>div.thumb,:host.scrolling>div.thumb-handle>div.thumb{background-color:var(--sci-scrollbar-color);opacity:.75}:host:hover>div.thumb-handle>div.thumb.vertical,:host.scrolling>div.thumb-handle>div.thumb.vertical{width:100%}:host:hover>div.thumb-handle>div.thumb.horizontal,:host.scrolling>div.thumb-handle>div.thumb.horizontal{height:100%}:host>div.thumb-handle{display:flex;flex-grow:var(--\\275sci-scrollbar-thumb-size-fr);align-items:center}:host>div.thumb-handle.vertical{flex-direction:column;min-height:20px}:host>div.thumb-handle.horizontal{flex-direction:row;min-width:20px}:host>div.thumb-handle>div.thumb{flex:auto;border-radius:4px;background-color:var(--sci-scrollbar-color);opacity:.4;transition-duration:125ms;transition-property:width,height;transition-timing-function:ease-out}:host>div.thumb-handle>div.thumb.vertical{width:60%}:host>div.thumb-handle>div.thumb.horizontal{height:60%}:host>div.scrolltrack:last-child{flex-grow:calc(1 - (var(--\\275sci-scrollbar-thumb-position-fr) + var(--\\275sci-scrollbar-thumb-size-fr)))}\n"] }]
412
444
  }], ctorParameters: () => [], propDecorators: { direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], viewport: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewport", required: true }] }], _thumbElement: [{ type: i0.ViewChild, args: ['thumb_handle', { isSignal: true }] }] } });
413
445
  /**
414
- * Emits whenever the viewport scrolls.
446
+ * Emits whenever the viewport is scrolled.
415
447
  */
416
448
  function viewportScroll$(viewport) {
417
449
  return fromEvent(viewport, 'scroll', { passive: true }).pipe(map(() => undefined));
@@ -446,7 +478,23 @@ function viewportClientSize$(viewport, options) {
446
478
  */
447
479
  function children$(element) {
448
480
  return fromMutation$(element, { subtree: false, childList: true })
449
- .pipe(startWith(undefined), map(() => Array.from(element.children)), filterArray((child) => child instanceof HTMLElement));
481
+ .pipe(startWith(undefined), map(() => Array.from(element.children)
482
+ // Map to slotted content if a slot (Shadow DOM).
483
+ .flatMap(child => child instanceof HTMLSlotElement ? child.assignedElements() : child)
484
+ // Filter HTML elements.
485
+ .filter((child) => child instanceof HTMLElement)));
486
+ }
487
+ /**
488
+ * Returns the value clamped to the inclusive range of min and max.
489
+ */
490
+ function clamp(value, minmax) {
491
+ return Math.max(minmax.min, Math.min(value, minmax.max));
492
+ }
493
+ /**
494
+ * Returns whether the value is between the specified range (inclusive).
495
+ */
496
+ function isBetween(value, range) {
497
+ return value >= range.from && value <= range.to;
450
498
  }
451
499
 
452
500
  /*
@@ -529,7 +577,8 @@ class SciViewportComponent {
529
577
  /**
530
578
  * Controls if to use the native scrollbar or a scrollbar that sits on top of the viewport. Defaults to `on-top`.
531
579
  */
532
- scrollbarStyle = input('on-top', ...(ngDevMode ? [{ debugName: "scrollbarStyle" }] : []));
580
+ scrollbarStyle = input('on-top', /* @ts-ignore */
581
+ ...(ngDevMode ? [{ debugName: "scrollbarStyle" }] : /* istanbul ignore next */ []));
533
582
  /**
534
583
  * Emits when the viewport is scrolled. The event is emitted outside the Angular zone to avoid unnecessary change detection cycles.
535
584
  */
@@ -700,18 +749,18 @@ class SciViewportComponent {
700
749
  });
701
750
  });
702
751
  }
703
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: SciViewportComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
704
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: SciViewportComponent, isStandalone: true, selector: "sci-viewport", inputs: { scrollbarStyle: { classPropertyName: "scrollbarStyle", publicName: "scrollbarStyle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { scroll: "scroll" }, host: { listeners: { "focus": "focus()" } }, viewQueries: [{ propertyName: "_viewport", first: true, predicate: ["viewport"], descendants: true, isSignal: true }, { propertyName: "_viewportClient", first: true, predicate: ["viewport_client"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- viewport and viewport client -->\n<div #viewport\n class=\"viewport\"\n tabindex=\"-1\"\n sciScrollable [sciScrollableDisplayNativeScrollbar]=\"scrollbarStyle() === 'native'\"\n cdkScrollable>\n <div #viewport_client class=\"viewport-client\" part=\"content\">\n <slot></slot>\n </div>\n</div>\n\n<!-- render emulated scrollbars which sit on-top -->\n@if (scrollbarStyle() === 'on-top' && nativeScrollbarTrackSizeProvider.trackSize() !== null) {\n <sci-scrollbar [direction]=\"'vscroll'\" [viewport]=\"viewport\" class=\"e2e-vertical\"/>\n <sci-scrollbar [direction]=\"'hscroll'\" [viewport]=\"viewport\" class=\"e2e-horizontal\"/>\n}\n", styles: [":host{display:grid;grid-template-columns:100%;grid-template-rows:100%;position:relative;overflow:hidden;outline:none}:host:host-context(:not(:hover):not(:active)) sci-scrollbar:not(.scrolling){opacity:0}:host>div.viewport{display:grid;position:relative;outline:none;-webkit-overflow-scrolling:touch}:host>div.viewport>div.viewport-client{display:grid}:host>sci-scrollbar{--sci-scrollbar-color: var(--sci-viewport-scrollbar-color);position:absolute;transition-duration:1s;transition-property:opacity;transition-timing-function:ease-out}:host>sci-scrollbar.vertical{top:0;right:0;bottom:0;left:unset;width:12px}:host>sci-scrollbar.horizontal{top:unset;right:0;bottom:0;left:0;height:12px}\n"], dependencies: [{ kind: "directive", type: SciScrollableDirective, selector: "[sciScrollable]", inputs: ["sciScrollableDisplayNativeScrollbar"] }, { kind: "component", type: SciScrollbarComponent, selector: "sci-scrollbar", inputs: ["direction", "viewport"] }, { kind: "directive", type: CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }], encapsulation: i0.ViewEncapsulation.ShadowDom });
752
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SciViewportComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
753
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: SciViewportComponent, isStandalone: true, selector: "sci-viewport", inputs: { scrollbarStyle: { classPropertyName: "scrollbarStyle", publicName: "scrollbarStyle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { scroll: "scroll" }, host: { listeners: { "focus": "focus()" } }, viewQueries: [{ propertyName: "_viewport", first: true, predicate: ["viewport"], descendants: true, isSignal: true }, { propertyName: "_viewportClient", first: true, predicate: ["viewport_client"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- viewport and viewport client -->\n<div #viewport\n class=\"viewport\"\n tabindex=\"-1\"\n sciScrollable [sciScrollableDisplayNativeScrollbar]=\"scrollbarStyle() === 'native'\"\n cdkScrollable>\n <div #viewport_client class=\"viewport-client\" part=\"content\">\n <slot></slot>\n </div>\n</div>\n\n<!-- render emulated scrollbars which sit on-top -->\n@if (scrollbarStyle() === 'on-top' && nativeScrollbarTrackSizeProvider.trackSize() !== null) {\n <sci-scrollbar [direction]=\"'vscroll'\" [viewport]=\"viewport\" class=\"e2e-vertical\"/>\n <sci-scrollbar [direction]=\"'hscroll'\" [viewport]=\"viewport\" class=\"e2e-horizontal\"/>\n}\n", styles: [":host{display:grid;grid-template-columns:100%;grid-template-rows:100%;position:relative;overflow:hidden;outline:none}:host:is(:not(:hover):not(:active),:host(:not(:hover):not(:active))) sci-scrollbar:not(.scrolling){opacity:0}:host>div.viewport{display:grid;position:relative;outline:none;-webkit-overflow-scrolling:touch}:host>div.viewport>div.viewport-client{display:grid}:host>sci-scrollbar{--sci-scrollbar-color: var(--sci-viewport-scrollbar-color);position:absolute}:host>sci-scrollbar.vertical{top:1px;right:1px;bottom:1px}:host>sci-scrollbar.horizontal{left:1px;bottom:1px;right:1px}\n"], dependencies: [{ kind: "directive", type: SciScrollableDirective, selector: "[sciScrollable]", inputs: ["sciScrollableDisplayNativeScrollbar"] }, { kind: "component", type: SciScrollbarComponent, selector: "sci-scrollbar", inputs: ["direction", "viewport"] }, { kind: "directive", type: CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }], changeDetection: i0.ChangeDetectionStrategy.Eager, encapsulation: i0.ViewEncapsulation.ShadowDom });
705
754
  }
706
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: SciViewportComponent, decorators: [{
755
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SciViewportComponent, decorators: [{
707
756
  type: Component,
708
757
  args: [{ selector: 'sci-viewport', encapsulation: ViewEncapsulation.ShadowDom, imports: [
709
758
  SciScrollableDirective,
710
759
  SciScrollbarComponent,
711
760
  CdkScrollable,
712
- ], host: {
761
+ ], changeDetection: ChangeDetectionStrategy.Eager, host: {
713
762
  '(focus)': 'focus()',
714
- }, template: "<!-- viewport and viewport client -->\n<div #viewport\n class=\"viewport\"\n tabindex=\"-1\"\n sciScrollable [sciScrollableDisplayNativeScrollbar]=\"scrollbarStyle() === 'native'\"\n cdkScrollable>\n <div #viewport_client class=\"viewport-client\" part=\"content\">\n <slot></slot>\n </div>\n</div>\n\n<!-- render emulated scrollbars which sit on-top -->\n@if (scrollbarStyle() === 'on-top' && nativeScrollbarTrackSizeProvider.trackSize() !== null) {\n <sci-scrollbar [direction]=\"'vscroll'\" [viewport]=\"viewport\" class=\"e2e-vertical\"/>\n <sci-scrollbar [direction]=\"'hscroll'\" [viewport]=\"viewport\" class=\"e2e-horizontal\"/>\n}\n", styles: [":host{display:grid;grid-template-columns:100%;grid-template-rows:100%;position:relative;overflow:hidden;outline:none}:host:host-context(:not(:hover):not(:active)) sci-scrollbar:not(.scrolling){opacity:0}:host>div.viewport{display:grid;position:relative;outline:none;-webkit-overflow-scrolling:touch}:host>div.viewport>div.viewport-client{display:grid}:host>sci-scrollbar{--sci-scrollbar-color: var(--sci-viewport-scrollbar-color);position:absolute;transition-duration:1s;transition-property:opacity;transition-timing-function:ease-out}:host>sci-scrollbar.vertical{top:0;right:0;bottom:0;left:unset;width:12px}:host>sci-scrollbar.horizontal{top:unset;right:0;bottom:0;left:0;height:12px}\n"] }]
763
+ }, template: "<!-- viewport and viewport client -->\n<div #viewport\n class=\"viewport\"\n tabindex=\"-1\"\n sciScrollable [sciScrollableDisplayNativeScrollbar]=\"scrollbarStyle() === 'native'\"\n cdkScrollable>\n <div #viewport_client class=\"viewport-client\" part=\"content\">\n <slot></slot>\n </div>\n</div>\n\n<!-- render emulated scrollbars which sit on-top -->\n@if (scrollbarStyle() === 'on-top' && nativeScrollbarTrackSizeProvider.trackSize() !== null) {\n <sci-scrollbar [direction]=\"'vscroll'\" [viewport]=\"viewport\" class=\"e2e-vertical\"/>\n <sci-scrollbar [direction]=\"'hscroll'\" [viewport]=\"viewport\" class=\"e2e-horizontal\"/>\n}\n", styles: [":host{display:grid;grid-template-columns:100%;grid-template-rows:100%;position:relative;overflow:hidden;outline:none}:host:is(:not(:hover):not(:active),:host(:not(:hover):not(:active))) sci-scrollbar:not(.scrolling){opacity:0}:host>div.viewport{display:grid;position:relative;outline:none;-webkit-overflow-scrolling:touch}:host>div.viewport>div.viewport-client{display:grid}:host>sci-scrollbar{--sci-scrollbar-color: var(--sci-viewport-scrollbar-color);position:absolute}:host>sci-scrollbar.vertical{top:1px;right:1px;bottom:1px}:host>sci-scrollbar.horizontal{left:1px;bottom:1px;right:1px}\n"] }]
715
764
  }], ctorParameters: () => [], propDecorators: { scrollbarStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollbarStyle", required: false }] }], scroll: [{ type: i0.Output, args: ["scroll"] }], _viewport: [{ type: i0.ViewChild, args: ['viewport', { isSignal: true }] }], _viewportClient: [{ type: i0.ViewChild, args: ['viewport_client', { isSignal: true }] }] } });
716
765
 
717
766
  /*