@scion/components 18.0.1 → 18.1.1
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.
- package/README.md +2 -2
- package/dimension/bounding-client-rect.signal.d.ts +23 -0
- package/dimension/dimension.d.ts +10 -0
- package/dimension/dimension.directive.d.ts +4 -15
- package/dimension/dimension.signal.d.ts +19 -0
- package/dimension/public_api.d.ts +4 -1
- package/esm2022/dimension/bounding-client-rect.signal.mjs +54 -0
- package/esm2022/dimension/dimension.directive.mjs +14 -11
- package/esm2022/dimension/dimension.mjs +11 -0
- package/esm2022/dimension/dimension.signal.mjs +63 -0
- package/esm2022/dimension/public_api.mjs +3 -1
- package/esm2022/viewport/native-scrollbar-track-size-provider.service.mjs +20 -44
- package/esm2022/viewport/scrollable.directive.mjs +29 -31
- package/esm2022/viewport/scrollbar/scrollbar.component.mjs +108 -126
- package/esm2022/viewport/viewport.component.mjs +36 -60
- package/fesm2022/scion-components-dimension.mjs +126 -13
- package/fesm2022/scion-components-dimension.mjs.map +1 -1
- package/fesm2022/scion-components-viewport.mjs +182 -249
- package/fesm2022/scion-components-viewport.mjs.map +1 -1
- package/package.json +2 -2
- package/viewport/native-scrollbar-track-size-provider.service.d.ts +6 -16
- package/viewport/scrollable.directive.d.ts +9 -10
- package/viewport/scrollbar/scrollbar.component.d.ts +17 -32
- package/viewport/viewport.component.d.ts +8 -11
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable,
|
|
2
|
+
import { inject, NgZone, Injectable, ElementRef, Renderer2, input, effect, untracked, Directive, DestroyRef, viewChild, computed, Component, ChangeDetectionStrategy, HostBinding, output, ViewEncapsulation, HostListener, NgModule } from '@angular/core';
|
|
3
|
+
import { DOCUMENT } from '@angular/common';
|
|
4
|
+
import { fromEvent, merge, mergeWith, timer, of } from 'rxjs';
|
|
5
|
+
import { debounceTime, startWith, map, distinctUntilChanged, first, withLatestFrom, takeWhile, takeUntil, switchMap } from 'rxjs/operators';
|
|
6
|
+
import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
7
|
+
import { subscribeIn, filterArray } from '@scion/toolkit/operators';
|
|
3
8
|
import { coerceElement } from '@angular/cdk/coercion';
|
|
4
|
-
import { debounceTime, startWith, map, distinctUntilChanged, takeUntil, switchMap, first, withLatestFrom, takeWhile } from 'rxjs/operators';
|
|
5
|
-
import { BehaviorSubject, Subject, fromEvent, merge, of, timer } from 'rxjs';
|
|
6
|
-
import { DOCUMENT, AsyncPipe } from '@angular/common';
|
|
7
9
|
import { fromResize$, fromMutation$ } from '@scion/toolkit/observable';
|
|
8
|
-
import
|
|
9
|
-
import * as i2 from '@angular/cdk/scrolling';
|
|
10
|
+
import * as i1 from '@angular/cdk/scrolling';
|
|
10
11
|
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
11
12
|
|
|
12
13
|
/*
|
|
13
|
-
* Copyright (c) 2018-
|
|
14
|
+
* Copyright (c) 2018-2024 Swiss Federal Railways
|
|
14
15
|
*
|
|
15
16
|
* This program and the accompanying materials are made
|
|
16
17
|
* available under the terms of the Eclipse Public License 2.0
|
|
@@ -22,26 +23,10 @@ import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
|
22
23
|
* Provides the native scrollbar tracksize.
|
|
23
24
|
*/
|
|
24
25
|
class SciNativeScrollbarTrackSizeProvider {
|
|
25
|
-
constructor(
|
|
26
|
-
this._document =
|
|
27
|
-
this._zone =
|
|
28
|
-
this.
|
|
29
|
-
this._destroy$ = new Subject();
|
|
30
|
-
this.installNativeScrollbarTrackSizeListener();
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Returns an {Observable} which emits the native scrollbar track size, if any, or else `null`.
|
|
34
|
-
*
|
|
35
|
-
* Upon subscription, it emits the track size immediately, and then continuously emits when the track size changes.
|
|
36
|
-
*/
|
|
37
|
-
get trackSize$() {
|
|
38
|
-
return this._trackSize$;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Returns the native scrollbar track size, if any, or else `null`.
|
|
42
|
-
*/
|
|
43
|
-
get trackSize() {
|
|
44
|
-
return this._trackSize$.getValue();
|
|
26
|
+
constructor() {
|
|
27
|
+
this._document = inject(DOCUMENT);
|
|
28
|
+
this._zone = inject(NgZone);
|
|
29
|
+
this.trackSize = this.createNativeScrollbarTrackSizeSignal();
|
|
45
30
|
}
|
|
46
31
|
/**
|
|
47
32
|
* Computes the native scrollbar track size.
|
|
@@ -49,7 +34,7 @@ class SciNativeScrollbarTrackSizeProvider {
|
|
|
49
34
|
* @returns native track size, or `null` if the native scrollbars sit on top of the content.
|
|
50
35
|
*/
|
|
51
36
|
computeTrackSize() {
|
|
52
|
-
//
|
|
37
|
+
// Create temporary viewport and viewport client with native scrollbars to compute the scrolltrack width.
|
|
53
38
|
const viewportDiv = this._document.createElement('div');
|
|
54
39
|
setStyle(viewportDiv, {
|
|
55
40
|
position: 'absolute',
|
|
@@ -74,39 +59,29 @@ class SciNativeScrollbarTrackSizeProvider {
|
|
|
74
59
|
hScrollbarTrackHeight: viewportBounds.height - viewportClientBounds.height,
|
|
75
60
|
vScrollbarTrackWidth: viewportBounds.width - viewportClientBounds.width,
|
|
76
61
|
};
|
|
77
|
-
//
|
|
62
|
+
// Destroy temporary viewport.
|
|
78
63
|
this._document.body.removeChild(viewportDiv);
|
|
79
64
|
if (trackSize.hScrollbarTrackHeight === 0 && trackSize.vScrollbarTrackWidth === 0) {
|
|
80
65
|
return null;
|
|
81
66
|
}
|
|
82
67
|
return trackSize;
|
|
83
68
|
}
|
|
84
|
-
|
|
69
|
+
createNativeScrollbarTrackSizeSignal() {
|
|
85
70
|
// We compute the size of the native scrollbar track when the browser fires the onresize window event.
|
|
86
71
|
// This event is also fired on page zoom or when displaying a hidden document. Hidden documents do not have
|
|
87
72
|
// a scrollbar track size until being displayed, e.g., after showing hidden iframes.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
.subscribe(trackSize => {
|
|
93
|
-
this._zone.run(() => this._trackSize$.next(trackSize));
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
ngOnDestroy() {
|
|
98
|
-
this._destroy$.next();
|
|
73
|
+
const trackSize$ = fromEvent(window, 'resize')
|
|
74
|
+
.pipe(subscribeIn(fn => this._zone.runOutsideAngular(fn)), debounceTime(5), startWith(null), // trigger the initial computation
|
|
75
|
+
map(() => this.computeTrackSize()), distinctUntilChanged((t1, t2) => t1?.hScrollbarTrackHeight === t2?.hScrollbarTrackHeight && t1?.vScrollbarTrackWidth === t2?.vScrollbarTrackWidth));
|
|
76
|
+
return toSignal(trackSize$, { initialValue: null });
|
|
99
77
|
}
|
|
100
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SciNativeScrollbarTrackSizeProvider, deps: [
|
|
78
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SciNativeScrollbarTrackSizeProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
101
79
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SciNativeScrollbarTrackSizeProvider, providedIn: 'root' }); }
|
|
102
80
|
}
|
|
103
81
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SciNativeScrollbarTrackSizeProvider, decorators: [{
|
|
104
82
|
type: Injectable,
|
|
105
83
|
args: [{ providedIn: 'root' }]
|
|
106
|
-
}], ctorParameters: () => [
|
|
107
|
-
type: Inject,
|
|
108
|
-
args: [DOCUMENT]
|
|
109
|
-
}] }, { type: i0.NgZone }] });
|
|
84
|
+
}], ctorParameters: () => [] });
|
|
110
85
|
/**
|
|
111
86
|
* Applies the given style(s) to the given element.
|
|
112
87
|
*
|
|
@@ -140,24 +115,33 @@ function setStyle(element, style) {
|
|
|
140
115
|
* to hide the pushed out native scrollbars.
|
|
141
116
|
*/
|
|
142
117
|
class SciScrollableDirective {
|
|
143
|
-
constructor(
|
|
144
|
-
this._host =
|
|
145
|
-
this._renderer =
|
|
146
|
-
this.
|
|
147
|
-
this._inputChange$ = new Subject();
|
|
118
|
+
constructor() {
|
|
119
|
+
this._host = inject((ElementRef)).nativeElement;
|
|
120
|
+
this._renderer = inject(Renderer2);
|
|
121
|
+
this._nativeScrollbarTrackSizeProvider = inject(SciNativeScrollbarTrackSizeProvider);
|
|
148
122
|
/**
|
|
149
123
|
* Controls whether to display native scrollbars.
|
|
150
124
|
* Has no effect if the native scrollbar sits on top of the content, e.g. in OS X.
|
|
151
125
|
*/
|
|
152
|
-
this.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
126
|
+
this.displayNativeScrollbar = input(false, { alias: 'sciScrollableDisplayNativeScrollbar' });
|
|
127
|
+
this.controlDisplayOfNativeScrollbar();
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Controls the display of the native scrollbar based on this directive's configuration.
|
|
131
|
+
*/
|
|
132
|
+
controlDisplayOfNativeScrollbar() {
|
|
133
|
+
effect(() => {
|
|
134
|
+
const displayNativeScrollbar = this.displayNativeScrollbar();
|
|
135
|
+
if (displayNativeScrollbar) {
|
|
136
|
+
untracked(() => this.useNativeScrollbars());
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const nativeScrollbarTrackSize = this._nativeScrollbarTrackSizeProvider.trackSize();
|
|
140
|
+
if (nativeScrollbarTrackSize) {
|
|
141
|
+
untracked(() => this.shiftNativeScrollbars(nativeScrollbarTrackSize));
|
|
158
142
|
}
|
|
159
143
|
else {
|
|
160
|
-
|
|
144
|
+
untracked(() => this.useNativeScrollbars());
|
|
161
145
|
}
|
|
162
146
|
});
|
|
163
147
|
}
|
|
@@ -165,7 +149,7 @@ class SciScrollableDirective {
|
|
|
165
149
|
* Uses the native scrollbars when content overflows.
|
|
166
150
|
*/
|
|
167
151
|
useNativeScrollbars() {
|
|
168
|
-
this.setStyle(this._host
|
|
152
|
+
this.setStyle(this._host, {
|
|
169
153
|
overflow: 'auto',
|
|
170
154
|
width: '100%',
|
|
171
155
|
height: '100%',
|
|
@@ -177,7 +161,7 @@ class SciScrollableDirective {
|
|
|
177
161
|
* Shifts the native scrollbars out of the visible viewport area.
|
|
178
162
|
*/
|
|
179
163
|
shiftNativeScrollbars(nativeScrollbarTrackSize) {
|
|
180
|
-
this.setStyle(this._host
|
|
164
|
+
this.setStyle(this._host, {
|
|
181
165
|
overflow: 'scroll',
|
|
182
166
|
width: `calc(100% + ${nativeScrollbarTrackSize.vScrollbarTrackWidth}px`,
|
|
183
167
|
height: `calc(100% + ${nativeScrollbarTrackSize.hScrollbarTrackHeight}px`,
|
|
@@ -188,14 +172,8 @@ class SciScrollableDirective {
|
|
|
188
172
|
setStyle(element, style) {
|
|
189
173
|
Object.keys(style).forEach(key => this._renderer.setStyle(element, key, style[key]));
|
|
190
174
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
ngOnDestroy() {
|
|
195
|
-
this._destroy$.next();
|
|
196
|
-
}
|
|
197
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SciScrollableDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: SciNativeScrollbarTrackSizeProvider }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
198
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.1", type: SciScrollableDirective, isStandalone: true, selector: "[sciScrollable]", inputs: { isDisplayNativeScrollbar: ["sciScrollableDisplayNativeScrollbar", "isDisplayNativeScrollbar"] }, usesOnChanges: true, ngImport: i0 }); }
|
|
175
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SciScrollableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
176
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.0.1", type: SciScrollableDirective, isStandalone: true, selector: "[sciScrollable]", inputs: { displayNativeScrollbar: { classPropertyName: "displayNativeScrollbar", publicName: "sciScrollableDisplayNativeScrollbar", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
|
|
199
177
|
}
|
|
200
178
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SciScrollableDirective, decorators: [{
|
|
201
179
|
type: Directive,
|
|
@@ -203,10 +181,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImpor
|
|
|
203
181
|
selector: '[sciScrollable]',
|
|
204
182
|
standalone: true,
|
|
205
183
|
}]
|
|
206
|
-
}], ctorParameters: () => [
|
|
207
|
-
type: Input,
|
|
208
|
-
args: ['sciScrollableDisplayNativeScrollbar']
|
|
209
|
-
}] } });
|
|
184
|
+
}], ctorParameters: () => [] });
|
|
210
185
|
|
|
211
186
|
/*
|
|
212
187
|
* Copyright (c) 2018-2019 Swiss Federal Railways
|
|
@@ -253,52 +228,36 @@ class SciScrollbarComponent {
|
|
|
253
228
|
*/
|
|
254
229
|
static { this.VIEWPORT_RESIZE_DEBOUNCE_TIME = 50; }
|
|
255
230
|
get vertical() {
|
|
256
|
-
return this.
|
|
231
|
+
return this._vertical();
|
|
257
232
|
}
|
|
258
233
|
get horizontal() {
|
|
259
|
-
return this.
|
|
234
|
+
return !this._vertical();
|
|
260
235
|
}
|
|
261
236
|
get scrolling() {
|
|
262
237
|
return this._lastDragPosition !== null;
|
|
263
238
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
this.
|
|
269
|
-
this._viewportChange$.next();
|
|
270
|
-
}
|
|
271
|
-
constructor(_host, _document, _zone) {
|
|
272
|
-
this._host = _host;
|
|
273
|
-
this._document = _document;
|
|
274
|
-
this._zone = _zone;
|
|
275
|
-
this._destroy$ = new Subject();
|
|
276
|
-
this._viewportChange$ = new Subject();
|
|
239
|
+
constructor() {
|
|
240
|
+
this._host = inject((ElementRef)).nativeElement;
|
|
241
|
+
this._document = inject(DOCUMENT);
|
|
242
|
+
this._zone = inject(NgZone);
|
|
243
|
+
this._destroyRef = inject(DestroyRef);
|
|
277
244
|
this._lastDragPosition = null;
|
|
278
245
|
this._overflow = false;
|
|
279
246
|
this._thumbSizeFr = 0;
|
|
280
247
|
this._thumbPositionFr = 0;
|
|
248
|
+
this._thumbElement = viewChild.required('thumb_handle');
|
|
249
|
+
this._vertical = computed(() => this.direction() === 'vscroll');
|
|
281
250
|
/**
|
|
282
251
|
* Specifies the direction of the scrollbar.
|
|
283
252
|
*
|
|
284
253
|
* By default, if not specified, renders a vertical scrollbar.
|
|
285
254
|
*/
|
|
286
|
-
this.direction = 'vscroll';
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
return merge(this.viewportScrollChange$(), this.viewportDimensionChange$({ debounceTime: SciScrollbarComponent.VIEWPORT_RESIZE_DEBOUNCE_TIME }), this.viewportClientDimensionChange$({ debounceTime: SciScrollbarComponent.VIEWPORT_RESIZE_DEBOUNCE_TIME }));
|
|
293
|
-
}), subscribeInside(continueFn => this._zone.runOutsideAngular(continueFn)), takeUntil(this._destroy$))
|
|
294
|
-
.subscribe(() => {
|
|
295
|
-
if (this._viewport) {
|
|
296
|
-
this.renderScrollPosition();
|
|
297
|
-
}
|
|
298
|
-
else {
|
|
299
|
-
this.unsetScrollPosition();
|
|
300
|
-
}
|
|
301
|
-
});
|
|
255
|
+
this.direction = input('vscroll');
|
|
256
|
+
/**
|
|
257
|
+
* The viewport to provide scrollbars for.
|
|
258
|
+
*/
|
|
259
|
+
this.viewport = input.required();
|
|
260
|
+
this.installScrollPositionRenderer();
|
|
302
261
|
}
|
|
303
262
|
/**
|
|
304
263
|
* Computes the scroll position and updates CSS variables to render the scroll position in the UI.
|
|
@@ -318,7 +277,7 @@ class SciScrollbarComponent {
|
|
|
318
277
|
}
|
|
319
278
|
if (overflow !== this._overflow) {
|
|
320
279
|
this._overflow = overflow;
|
|
321
|
-
overflow ? this._host.
|
|
280
|
+
overflow ? this._host.classList.add('overflow') : this._host.classList.remove('overflow');
|
|
322
281
|
}
|
|
323
282
|
}
|
|
324
283
|
/**
|
|
@@ -331,14 +290,12 @@ class SciScrollbarComponent {
|
|
|
331
290
|
this._overflow = false;
|
|
332
291
|
this.setCssVariable('--ɵsci-scrollbar-thumb-position-fr', 0);
|
|
333
292
|
this.setCssVariable('--ɵsci-scrollbar-thumb-size-fr', 0);
|
|
334
|
-
this._host.
|
|
293
|
+
this._host.classList.remove('overflow');
|
|
335
294
|
}
|
|
336
|
-
/* @docs-private */
|
|
337
295
|
onTouchStart(event) {
|
|
338
296
|
event.preventDefault();
|
|
339
297
|
this._lastDragPosition = this.vertical ? event.touches[0].screenY : event.touches[0].screenX;
|
|
340
298
|
}
|
|
341
|
-
/* @docs-private */
|
|
342
299
|
onTouchMove(event) {
|
|
343
300
|
event.preventDefault();
|
|
344
301
|
const newDragPositionPx = this.vertical ? event.touches[0].screenY : event.touches[0].screenX;
|
|
@@ -347,12 +304,10 @@ class SciScrollbarComponent {
|
|
|
347
304
|
this._lastDragPosition = newDragPositionPx;
|
|
348
305
|
this.moveViewportClient(viewportPanPx);
|
|
349
306
|
}
|
|
350
|
-
/* @docs-private */
|
|
351
307
|
onTouchEnd(event) {
|
|
352
308
|
event.preventDefault();
|
|
353
309
|
this._lastDragPosition = null;
|
|
354
310
|
}
|
|
355
|
-
/* @docs-private */
|
|
356
311
|
onMouseDown(mousedownEvent) {
|
|
357
312
|
if (mousedownEvent.button !== 0) {
|
|
358
313
|
return;
|
|
@@ -360,32 +315,49 @@ class SciScrollbarComponent {
|
|
|
360
315
|
mousedownEvent.preventDefault();
|
|
361
316
|
this._lastDragPosition = this.vertical ? mousedownEvent.screenY : mousedownEvent.screenX;
|
|
362
317
|
// Listen for 'mousemove' events
|
|
363
|
-
this.
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
318
|
+
const mousemoveListener = merge(fromEvent(this._document, 'mousemove'), fromEvent(this._document, 'sci-mousemove'))
|
|
319
|
+
.pipe(subscribeIn(fn => this._zone.runOutsideAngular(fn)), takeUntilDestroyed(this._destroyRef))
|
|
320
|
+
.subscribe(mousemoveEvent => {
|
|
321
|
+
NgZone.assertNotInAngularZone();
|
|
322
|
+
mousemoveEvent.preventDefault();
|
|
323
|
+
const newDragPositionPx = this.vertical ? mousemoveEvent.screenY : mousemoveEvent.screenX;
|
|
324
|
+
const scrollbarPanPx = newDragPositionPx - this._lastDragPosition;
|
|
325
|
+
const viewportPanPx = this.toViewportPanPx(scrollbarPanPx);
|
|
326
|
+
this._lastDragPosition = newDragPositionPx;
|
|
327
|
+
this.moveViewportClient(viewportPanPx);
|
|
328
|
+
});
|
|
329
|
+
// Listen for 'mouseup' events; use 'capture phase' and 'stop propagation' to not close overlays
|
|
330
|
+
merge(fromEvent(this._document, 'mouseup', { capture: true }), fromEvent(this._document, 'sci-mouseup'))
|
|
331
|
+
.pipe(subscribeIn(fn => this._zone.runOutsideAngular(fn)), first(), takeUntilDestroyed(this._destroyRef))
|
|
332
|
+
.subscribe(mouseupEvent => {
|
|
333
|
+
NgZone.assertNotInAngularZone();
|
|
334
|
+
mouseupEvent.stopPropagation();
|
|
335
|
+
mousemoveListener.unsubscribe();
|
|
336
|
+
this._lastDragPosition = null;
|
|
382
337
|
});
|
|
383
338
|
}
|
|
384
|
-
/* @docs-private */
|
|
385
339
|
onScrollTrackMouseDown(event, direction) {
|
|
386
340
|
const signum = (direction === 'up' ? -1 : +1);
|
|
387
341
|
this.scrollWhileMouseDown(this.toViewportPanPx(signum * this.thumbSize), event);
|
|
388
342
|
}
|
|
343
|
+
/**
|
|
344
|
+
* Renders the current scroll position when the viewport is scrolled.
|
|
345
|
+
*/
|
|
346
|
+
installScrollPositionRenderer() {
|
|
347
|
+
effect(onCleanup => {
|
|
348
|
+
const viewport = this.viewport();
|
|
349
|
+
untracked(() => {
|
|
350
|
+
if (!viewport) {
|
|
351
|
+
this.unsetScrollPosition();
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
const subscription = viewportScroll$(viewport)
|
|
355
|
+
.pipe(mergeWith(viewportSize$(viewport, { debounceTime: SciScrollbarComponent.VIEWPORT_RESIZE_DEBOUNCE_TIME })), mergeWith(viewportClientSize$(viewport, { debounceTime: SciScrollbarComponent.VIEWPORT_RESIZE_DEBOUNCE_TIME })), subscribeIn(fn => this._zone.runOutsideAngular(fn)))
|
|
356
|
+
.subscribe(() => this.renderScrollPosition());
|
|
357
|
+
onCleanup(() => subscription.unsubscribe());
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
}
|
|
389
361
|
/**
|
|
390
362
|
* Projects the given scrollbar scroll pixels into viewport scroll pixels.
|
|
391
363
|
*/
|
|
@@ -399,10 +371,10 @@ class SciScrollbarComponent {
|
|
|
399
371
|
*/
|
|
400
372
|
moveViewportClient(viewportPanPx) {
|
|
401
373
|
if (this.vertical) {
|
|
402
|
-
this.
|
|
374
|
+
this.viewport().scrollTop += viewportPanPx;
|
|
403
375
|
}
|
|
404
376
|
else {
|
|
405
|
-
this.
|
|
377
|
+
this.viewport().scrollLeft += viewportPanPx;
|
|
406
378
|
}
|
|
407
379
|
}
|
|
408
380
|
/**
|
|
@@ -434,81 +406,32 @@ class SciScrollbarComponent {
|
|
|
434
406
|
this.moveViewportClient(viewportScrollPx);
|
|
435
407
|
});
|
|
436
408
|
}
|
|
437
|
-
/**
|
|
438
|
-
* Emits whenever the viewport scrolls.
|
|
439
|
-
*/
|
|
440
|
-
viewportScrollChange$() {
|
|
441
|
-
return fromEvent(this._viewport, 'scroll', { passive: true }).pipe(map(() => undefined));
|
|
442
|
-
}
|
|
443
|
-
/**
|
|
444
|
-
* Emits on subscription, and then each time the size of the viewport changes.
|
|
445
|
-
*/
|
|
446
|
-
viewportDimensionChange$(options) {
|
|
447
|
-
return fromResize$(this._viewport)
|
|
448
|
-
.pipe(
|
|
449
|
-
// Debouncing is particularly important in the context of Angular animations, since they continuously
|
|
450
|
-
// trigger resize events. Debouncing prevents the scrollbar from flickering, for example, when the user
|
|
451
|
-
// expands a panel that contains a viewport.
|
|
452
|
-
debounceTime(options.debounceTime), map(() => undefined));
|
|
453
|
-
}
|
|
454
|
-
/**
|
|
455
|
-
* Emits on subscription, and then each time the size or style property of the viewport client changes.
|
|
456
|
-
*/
|
|
457
|
-
viewportClientDimensionChange$(options) {
|
|
458
|
-
return this.children$(this._viewport)
|
|
459
|
-
.pipe(switchMap(children => merge(...children.map(child => merge(fromResize$(child),
|
|
460
|
-
// Observe style mutations since some transformations change the scroll position without necessarily triggering a dimension change,
|
|
461
|
-
// e.g., `scale` or `translate` used by some virtual scroll implementations
|
|
462
|
-
fromMutation$(child, { subtree: false, childList: false, attributeFilter: ['style'] }))))),
|
|
463
|
-
// Debouncing is particularly important in the context of Angular animations, since they continuously
|
|
464
|
-
// trigger resize events. Debouncing prevents the scrollbar from flickering, for example, when the user
|
|
465
|
-
// expands a panel that contains a viewport.
|
|
466
|
-
debounceTime(options.debounceTime), map(() => undefined));
|
|
467
|
-
}
|
|
468
|
-
/**
|
|
469
|
-
* Emits the children of the passed element, and then each time child elements are added or removed.
|
|
470
|
-
*/
|
|
471
|
-
children$(element) {
|
|
472
|
-
return fromMutation$(element, { subtree: false, childList: true })
|
|
473
|
-
.pipe(startWith(undefined), map(() => Array.from(element.children)), filterArray((child) => child instanceof HTMLElement));
|
|
474
|
-
}
|
|
475
409
|
setCssVariable(key, value) {
|
|
476
|
-
this._host.
|
|
410
|
+
this._host.style.setProperty(key, value);
|
|
477
411
|
}
|
|
478
412
|
get viewportSize() {
|
|
479
|
-
return this.
|
|
413
|
+
return this.viewport() ? (this.vertical ? this.viewport().clientHeight : this.viewport().clientWidth) : 0;
|
|
480
414
|
}
|
|
481
415
|
get viewportClientSize() {
|
|
482
|
-
return this.
|
|
416
|
+
return this.viewport() ? (this.vertical ? this.viewport().scrollHeight : this.viewport().scrollWidth) : 0;
|
|
483
417
|
}
|
|
484
418
|
get scrollPosition() {
|
|
485
|
-
return this.
|
|
419
|
+
return this.viewport() ? (this.vertical ? this.viewport().scrollTop : this.viewport().scrollLeft) : 0;
|
|
486
420
|
}
|
|
487
421
|
get thumbSize() {
|
|
488
|
-
const thumbElement = this.
|
|
422
|
+
const thumbElement = this._thumbElement().nativeElement;
|
|
489
423
|
return this.vertical ? thumbElement.clientHeight : thumbElement.clientWidth;
|
|
490
424
|
}
|
|
491
425
|
get trackSize() {
|
|
492
|
-
|
|
493
|
-
return this.vertical ? trackElement.clientHeight : trackElement.clientWidth;
|
|
426
|
+
return this.vertical ? this._host.clientHeight : this._host.clientWidth;
|
|
494
427
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
this._destroy$.next();
|
|
498
|
-
}
|
|
499
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SciScrollbarComponent, deps: [{ token: i0.ElementRef }, { token: DOCUMENT }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
500
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.1", type: SciScrollbarComponent, isStandalone: true, selector: "sci-scrollbar", inputs: { direction: "direction", setViewport: ["viewport", "setViewport"] }, host: { properties: { "class.vertical": "this.vertical", "class.horizontal": "this.horizontal", "class.scrolling": "this.scrolling" } }, viewQueries: [{ propertyName: "thumbElement", first: true, predicate: ["thumb_handle"], descendants: true, static: 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 }); }
|
|
428
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SciScrollbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
429
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "18.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": "this.vertical", "class.horizontal": "this.horizontal", "class.scrolling": "this.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 }); }
|
|
501
430
|
}
|
|
502
431
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SciScrollbarComponent, decorators: [{
|
|
503
432
|
type: Component,
|
|
504
433
|
args: [{ selector: 'sci-scrollbar', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, 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"] }]
|
|
505
|
-
}], ctorParameters: () => [
|
|
506
|
-
type: Inject,
|
|
507
|
-
args: [DOCUMENT]
|
|
508
|
-
}] }, { type: i0.NgZone }], propDecorators: { thumbElement: [{
|
|
509
|
-
type: ViewChild,
|
|
510
|
-
args: ['thumb_handle', { static: true }]
|
|
511
|
-
}], vertical: [{
|
|
434
|
+
}], ctorParameters: () => [], propDecorators: { vertical: [{
|
|
512
435
|
type: HostBinding,
|
|
513
436
|
args: ['class.vertical']
|
|
514
437
|
}], horizontal: [{
|
|
@@ -517,12 +440,45 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImpor
|
|
|
517
440
|
}], scrolling: [{
|
|
518
441
|
type: HostBinding,
|
|
519
442
|
args: ['class.scrolling']
|
|
520
|
-
}], direction: [{
|
|
521
|
-
type: Input
|
|
522
|
-
}], setViewport: [{
|
|
523
|
-
type: Input,
|
|
524
|
-
args: [{ alias: 'viewport', required: true }]
|
|
525
443
|
}] } });
|
|
444
|
+
/**
|
|
445
|
+
* Emits whenever the viewport scrolls.
|
|
446
|
+
*/
|
|
447
|
+
function viewportScroll$(viewport) {
|
|
448
|
+
return fromEvent(viewport, 'scroll', { passive: true }).pipe(map(() => undefined));
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Emits on subscription, and then each time the size of the viewport changes.
|
|
452
|
+
*/
|
|
453
|
+
function viewportSize$(viewport, options) {
|
|
454
|
+
return fromResize$(viewport)
|
|
455
|
+
.pipe(
|
|
456
|
+
// Debouncing is particularly important in the context of Angular animations, since they continuously
|
|
457
|
+
// trigger resize events. Debouncing prevents the scrollbar from flickering, for example, when the user
|
|
458
|
+
// expands a panel that contains a viewport.
|
|
459
|
+
debounceTime(options.debounceTime), map(() => undefined));
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Emits on subscription, and then each time the size or style property of the viewport client changes.
|
|
463
|
+
*/
|
|
464
|
+
function viewportClientSize$(viewport, options) {
|
|
465
|
+
return children$(viewport)
|
|
466
|
+
.pipe(switchMap(children => merge(...children.map(child => merge(fromResize$(child),
|
|
467
|
+
// Observe style mutations since some transformations change the scroll position without necessarily triggering a dimension change,
|
|
468
|
+
// e.g., `scale` or `translate` used by some virtual scroll implementations
|
|
469
|
+
fromMutation$(child, { subtree: false, childList: false, attributeFilter: ['style'] }))))),
|
|
470
|
+
// Debouncing is particularly important in the context of Angular animations, since they continuously
|
|
471
|
+
// trigger resize events. Debouncing prevents the scrollbar from flickering, for example, when the user
|
|
472
|
+
// expands a panel that contains a viewport.
|
|
473
|
+
debounceTime(options.debounceTime), map(() => undefined));
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Emits the children of the passed element, and then each time child elements are added or removed.
|
|
477
|
+
*/
|
|
478
|
+
function children$(element) {
|
|
479
|
+
return fromMutation$(element, { subtree: false, childList: true })
|
|
480
|
+
.pipe(startWith(undefined), map(() => Array.from(element.children)), filterArray((child) => child instanceof HTMLElement));
|
|
481
|
+
}
|
|
526
482
|
|
|
527
483
|
/*
|
|
528
484
|
* Copyright (c) 2018-2019 Swiss Federal Railways
|
|
@@ -601,37 +557,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImpor
|
|
|
601
557
|
* ```
|
|
602
558
|
*/
|
|
603
559
|
class SciViewportComponent {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
this.
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
* In the latter, the viewport client remains natively scrollable.
|
|
615
|
-
*/
|
|
616
|
-
set scrollbarStyle(scrollbarStyle) {
|
|
617
|
-
this._scrollbarStyle = scrollbarStyle || 'on-top';
|
|
618
|
-
}
|
|
619
|
-
get scrollbarStyle() {
|
|
620
|
-
return this._scrollbarStyle;
|
|
621
|
-
}
|
|
622
|
-
constructor(host, nativeScrollbarTrackSizeProvider) {
|
|
623
|
-
this.host = host;
|
|
624
|
-
this.nativeScrollbarTrackSizeProvider = nativeScrollbarTrackSizeProvider;
|
|
625
|
-
this._scrollbarStyle = 'on-top';
|
|
560
|
+
constructor() {
|
|
561
|
+
this._viewport = viewChild.required('viewport');
|
|
562
|
+
this._viewportClient = viewChild.required('viewport_client');
|
|
563
|
+
this._host = inject((ElementRef)).nativeElement;
|
|
564
|
+
this.nativeScrollbarTrackSizeProvider = inject(SciNativeScrollbarTrackSizeProvider);
|
|
565
|
+
/**
|
|
566
|
+
* Controls whether to use native scrollbars or, which is by default, emulated scrollbars that sit on top of the viewport client.
|
|
567
|
+
* In the latter, the viewport client remains natively scrollable.
|
|
568
|
+
*/
|
|
569
|
+
this.scrollbarStyle = input('on-top');
|
|
626
570
|
/**
|
|
627
571
|
* Emits upon a scroll event.
|
|
628
572
|
*
|
|
629
573
|
* You can add [sciDimension] directive to the viewport or viewport client to be notified about layout changes.
|
|
630
574
|
*/
|
|
631
|
-
this.scroll =
|
|
575
|
+
this.scroll = output();
|
|
632
576
|
}
|
|
633
577
|
focus() {
|
|
634
|
-
this.
|
|
578
|
+
this.viewportElement.focus();
|
|
635
579
|
}
|
|
636
580
|
onScroll(event) {
|
|
637
581
|
this.scroll.emit(event);
|
|
@@ -642,7 +586,7 @@ class SciViewportComponent {
|
|
|
642
586
|
* @see Element.scrollTop
|
|
643
587
|
*/
|
|
644
588
|
get scrollTop() {
|
|
645
|
-
return this.
|
|
589
|
+
return this.viewportElement.scrollTop;
|
|
646
590
|
}
|
|
647
591
|
/**
|
|
648
592
|
* Sets the number of pixels that the viewport client is scrolled vertically.
|
|
@@ -650,7 +594,7 @@ class SciViewportComponent {
|
|
|
650
594
|
* @see Element.scrollTop
|
|
651
595
|
*/
|
|
652
596
|
set scrollTop(scrollTop) {
|
|
653
|
-
this.
|
|
597
|
+
this.viewportElement.scrollTop = scrollTop;
|
|
654
598
|
}
|
|
655
599
|
/**
|
|
656
600
|
* Returns the number of pixels that the viewport client is scrolled horizontally.
|
|
@@ -658,7 +602,7 @@ class SciViewportComponent {
|
|
|
658
602
|
* @see Element.scrollLeft
|
|
659
603
|
*/
|
|
660
604
|
get scrollLeft() {
|
|
661
|
-
return this.
|
|
605
|
+
return this.viewportElement.scrollLeft;
|
|
662
606
|
}
|
|
663
607
|
/**
|
|
664
608
|
* Sets the number of pixels that the viewport client is scrolled horizontally.
|
|
@@ -666,7 +610,7 @@ class SciViewportComponent {
|
|
|
666
610
|
* @see Element.scrollLeft
|
|
667
611
|
*/
|
|
668
612
|
set scrollLeft(scrollLeft) {
|
|
669
|
-
this.
|
|
613
|
+
this.viewportElement.scrollLeft = scrollLeft;
|
|
670
614
|
}
|
|
671
615
|
/**
|
|
672
616
|
* Returns the height of the viewport client.
|
|
@@ -674,7 +618,7 @@ class SciViewportComponent {
|
|
|
674
618
|
* @see Element.scrollHeight
|
|
675
619
|
*/
|
|
676
620
|
get scrollHeight() {
|
|
677
|
-
return this.
|
|
621
|
+
return this.viewportElement.scrollHeight;
|
|
678
622
|
}
|
|
679
623
|
/**
|
|
680
624
|
* Returns the width of the viewport client.
|
|
@@ -682,19 +626,19 @@ class SciViewportComponent {
|
|
|
682
626
|
* @see Element.scrollWidth
|
|
683
627
|
*/
|
|
684
628
|
get scrollWidth() {
|
|
685
|
-
return this.
|
|
629
|
+
return this.viewportElement.scrollWidth;
|
|
686
630
|
}
|
|
687
631
|
/**
|
|
688
632
|
* Returns the viewport {HTMLElement}.
|
|
689
633
|
*/
|
|
690
634
|
get viewportElement() {
|
|
691
|
-
return this.
|
|
635
|
+
return this._viewport().nativeElement;
|
|
692
636
|
}
|
|
693
637
|
/**
|
|
694
638
|
* Returns the viewport client {HTMLElement}.
|
|
695
639
|
*/
|
|
696
640
|
get viewportClientElement() {
|
|
697
|
-
return this._viewportClient;
|
|
641
|
+
return this._viewportClient().nativeElement;
|
|
698
642
|
}
|
|
699
643
|
/**
|
|
700
644
|
* Checks if the specified element is scrolled into the viewport.
|
|
@@ -716,15 +660,15 @@ class SciViewportComponent {
|
|
|
716
660
|
// The calculation of whether an element is scrolled into view may be wrong by a few pixels if the viewport contains elements with decimal sizes.
|
|
717
661
|
// This can happen because `offsetLeft` and `offsetTop` operate on an integer (not a decimal), losing precision that can accumulate.
|
|
718
662
|
// To avoid incorrect calculation when there is no viewport overflow, we consider all contained elements as scrolled into the view.
|
|
719
|
-
if (this.
|
|
663
|
+
if (this.viewportElement.scrollWidth <= this.viewportElement.clientWidth && this.viewportElement.scrollHeight <= this.viewportElement.clientHeight) {
|
|
720
664
|
return true;
|
|
721
665
|
}
|
|
722
666
|
const elBottom = elTop + coerceElement(element).offsetHeight;
|
|
723
667
|
const elRight = elLeft + coerceElement(element).offsetWidth;
|
|
724
|
-
const vpTop = this.
|
|
725
|
-
const vpLeft = this.
|
|
726
|
-
const vpBottom = vpTop + this.
|
|
727
|
-
const vpRight = vpLeft + this.
|
|
668
|
+
const vpTop = this.viewportElement.scrollTop;
|
|
669
|
+
const vpLeft = this.viewportElement.scrollLeft;
|
|
670
|
+
const vpBottom = vpTop + this.viewportElement.clientHeight;
|
|
671
|
+
const vpRight = vpLeft + this.viewportElement.clientWidth;
|
|
728
672
|
if (fit === 'full') {
|
|
729
673
|
return (elTop >= vpTop && elBottom <= vpBottom) && (elLeft >= vpLeft && elRight <= vpRight);
|
|
730
674
|
}
|
|
@@ -747,8 +691,8 @@ class SciViewportComponent {
|
|
|
747
691
|
if (left === null) {
|
|
748
692
|
return;
|
|
749
693
|
}
|
|
750
|
-
this.
|
|
751
|
-
this.
|
|
694
|
+
this.viewportElement.scrollTop = top - offset;
|
|
695
|
+
this.viewportElement.scrollLeft = left - offset;
|
|
752
696
|
}
|
|
753
697
|
/**
|
|
754
698
|
* Computes the distance of the element to the viewport's left or top border.
|
|
@@ -774,31 +718,20 @@ class SciViewportComponent {
|
|
|
774
718
|
return null;
|
|
775
719
|
}
|
|
776
720
|
el = offsetParent;
|
|
777
|
-
} while (el !== this.
|
|
721
|
+
} while (el !== this._host);
|
|
778
722
|
return offset;
|
|
779
723
|
}
|
|
780
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SciViewportComponent, deps: [
|
|
781
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: SciViewportComponent, isStandalone: true, selector: "sci-viewport", inputs: { scrollbarStyle: "scrollbarStyle" }, outputs: { scroll: "scroll" }, host: { listeners: { "focus": "focus()" } }, viewQueries: [{ propertyName: "
|
|
724
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SciViewportComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
725
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.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 (scroll)=\"onScroll($event)\">\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: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "directive", type: SciScrollableDirective, selector: "[sciScrollable]", inputs: ["sciScrollableDisplayNativeScrollbar"] }, { kind: "component", type: SciScrollbarComponent, selector: "sci-scrollbar", inputs: ["direction", "viewport"] }], encapsulation: i0.ViewEncapsulation.ShadowDom }); }
|
|
782
726
|
}
|
|
783
727
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: SciViewportComponent, decorators: [{
|
|
784
728
|
type: Component,
|
|
785
729
|
args: [{ selector: 'sci-viewport', encapsulation: ViewEncapsulation.ShadowDom, standalone: true, imports: [
|
|
786
|
-
AsyncPipe,
|
|
787
730
|
ScrollingModule,
|
|
788
731
|
SciScrollableDirective,
|
|
789
732
|
SciScrollbarComponent,
|
|
790
|
-
], template: "<!-- viewport and viewport client -->\n<div #viewport\n class=\"viewport\"\n tabindex=\"-1\"\n sciScrollable [sciScrollableDisplayNativeScrollbar]=\"scrollbarStyle === 'native'\"\n cdkScrollable\n (scroll)=\"onScroll($event)\">\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' &&
|
|
791
|
-
}],
|
|
792
|
-
type: ViewChild,
|
|
793
|
-
args: ['viewport', { static: true }]
|
|
794
|
-
}], setViewportClient: [{
|
|
795
|
-
type: ViewChild,
|
|
796
|
-
args: ['viewport_client', { static: true }]
|
|
797
|
-
}], scrollbarStyle: [{
|
|
798
|
-
type: Input
|
|
799
|
-
}], scroll: [{
|
|
800
|
-
type: Output
|
|
801
|
-
}], focus: [{
|
|
733
|
+
], template: "<!-- viewport and viewport client -->\n<div #viewport\n class=\"viewport\"\n tabindex=\"-1\"\n sciScrollable [sciScrollableDisplayNativeScrollbar]=\"scrollbarStyle() === 'native'\"\n cdkScrollable\n (scroll)=\"onScroll($event)\">\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"] }]
|
|
734
|
+
}], propDecorators: { focus: [{
|
|
802
735
|
type: HostListener,
|
|
803
736
|
args: ['focus']
|
|
804
737
|
}] } });
|