Skip to content

Commit 379e87e

Browse files
committed
update
1 parent 72ac305 commit 379e87e

File tree

11 files changed

+1114
-612
lines changed

11 files changed

+1114
-612
lines changed

CHANGELOG.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
# Changelog
22

3-
## 16.0.0
3+
## 16.1.0
44

5-
- fix: `asyncDetection` scrollbars rendering delay.
5+
- feat: Disable / Suppress the scroll bar during runtime, in [#658](https://github.com/MurhafSousli/ngx-scrollbar/issues/658).
6+
- fix: Wrong track size when used in 3rd party dropdown components, in [#669](https://github.com/MurhafSousli/ngx-scrollbar/issues/669).
7+
- fix: Scrollbar buttons icons not showing in Safari, in [#664](https://github.com/MurhafSousli/ngx-scrollbar/issues/664).
68

7-
## 16.0.0-beta.2
9+
## 16.0.0
810

11+
- fix: `asyncDetection` scrollbars rendering delay.
912
- feat: `scrollViewport` directive can be a descent child, not necessarily a direct child of `<ng-scrollbar externalViewport>`.
1013
- feat: Add `start`, `end`, `right`, `bottom` and `center` options to `scrollToElement` (supports RTL), closes [#637](https://github.com/MurhafSousli/ngx-scrollbar/issues/637).
1114
- feat: Add `syncSpacer` directive that is applied on `<ng-scrollbar externalViewport>` component to sync spacer element with content dimension changes.

package-lock.json

Lines changed: 1001 additions & 570 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,47 +14,47 @@
1414
},
1515
"private": true,
1616
"dependencies": {
17-
"@angular/animations": "^18.2.5",
18-
"@angular/cdk": "^18.2.5",
19-
"@angular/common": "^18.2.5",
20-
"@angular/compiler": "^18.2.5",
21-
"@angular/core": "^18.2.5",
22-
"@angular/forms": "^18.2.5",
23-
"@angular/material": "^18.2.5",
24-
"@angular/platform-browser": "^18.2.5",
25-
"@angular/platform-browser-dynamic": "^18.2.5",
26-
"@angular/platform-server": "^18.2.5",
27-
"@angular/router": "^18.2.5",
28-
"@angular/ssr": "^18.2.5",
17+
"@angular/animations": "^18.2.11",
18+
"@angular/cdk": "^18.2.12",
19+
"@angular/common": "^18.2.11",
20+
"@angular/compiler": "^18.2.11",
21+
"@angular/core": "^18.2.11",
22+
"@angular/forms": "^18.2.11",
23+
"@angular/material": "^18.2.12",
24+
"@angular/platform-browser": "^18.2.11",
25+
"@angular/platform-browser-dynamic": "^18.2.11",
26+
"@angular/platform-server": "^18.2.11",
27+
"@angular/router": "^18.2.11",
28+
"@angular/ssr": "^18.2.11",
2929
"@swimlane/ngx-datatable": "^20.1.0",
30-
"ag-grid-angular": "^32.2.0",
31-
"ag-grid-community": "^32.2.0",
30+
"ag-grid-angular": "^32.3.2",
31+
"ag-grid-community": "^32.3.2",
3232
"chance": "^1.1.12",
33-
"ng-zorro-antd": "^18.1.1",
33+
"ng-zorro-antd": "^18.2.0",
3434
"ngx-color-picker": "^17.0.0",
3535
"ngx-infinite-scroll": "^18.0.0",
36-
"primeng": "^17.18.10",
36+
"primeng": "^17.18.11",
3737
"rxjs": "~7.8.0",
3838
"tslib": "^2.7.0",
3939
"zone.js": "^0.14.10"
4040
},
4141
"devDependencies": {
42-
"@angular-devkit/build-angular": "^18.2.5",
43-
"@angular-eslint/builder": "18.3.1",
44-
"@angular-eslint/eslint-plugin": "18.3.1",
45-
"@angular-eslint/eslint-plugin-template": "18.3.1",
46-
"@angular-eslint/schematics": "18.3.1",
47-
"@angular-eslint/template-parser": "18.3.1",
48-
"@angular/cli": "^18.2.5",
49-
"@angular/compiler-cli": "^18.2.5",
42+
"@angular-devkit/build-angular": "^18.2.11",
43+
"@angular-eslint/builder": "18.4.0",
44+
"@angular-eslint/eslint-plugin": "18.4.0",
45+
"@angular-eslint/eslint-plugin-template": "18.4.0",
46+
"@angular-eslint/schematics": "18.4.0",
47+
"@angular-eslint/template-parser": "18.4.0",
48+
"@angular/cli": "^18.2.11",
49+
"@angular/compiler-cli": "^18.2.11",
5050
"@types/express": "^4.17.17",
5151
"@types/jasmine": "~5.1.0",
5252
"@types/node": "^22.6.1",
5353
"@typescript-eslint/eslint-plugin": "^8.7.0",
5454
"@typescript-eslint/parser": "^8.7.0",
55-
"eslint": "^9.11.1",
56-
"express": "^4.21.0",
57-
"jasmine-core": "^5.3.0",
55+
"eslint": "^9.14.0",
56+
"express": "^5.0.1",
57+
"jasmine-core": "^5.4.0",
5858
"karma": "~6.4.4",
5959
"karma-chrome-launcher": "~3.2.0",
6060
"karma-coverage": "~2.2.0",

projects/ngx-scrollbar/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ngx-scrollbar",
3-
"version": "16.0.0",
3+
"version": "16.1.0",
44
"license": "MIT",
55
"homepage": "https://ngx-scrollbar.netlify.app/",
66
"author": {

projects/ngx-scrollbar/src/lib/button/scrollbar-button.component.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
background-color: var(--INTERNAL-scrollbar-button-color);
1313

1414
svg {
15+
// Must set height and width of SVG so it can render on Safari browsers
16+
width: 100%;
17+
height: 100%;
1518
fill: var(--INTERNAL-scrollbar-button-fill);
1619
}
1720

projects/ngx-scrollbar/src/lib/ng-scrollbar.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494

9595
// The default value for overflow
9696
--_viewport-overflow: auto;
97+
--_viewport-pointer-events: auto;
9798

9899
// Scrollbar thumb color variables used to change when hovered or dragged
99100
--_thumb-x-color: var(--INTERNAL-scrollbar-thumb-color);
@@ -130,6 +131,7 @@
130131
}
131132

132133
&[disableInteraction="true"] {
134+
--_viewport-pointer-events: none;
133135
--_scrollbar-pointer-events: none;
134136
}
135137

projects/ngx-scrollbar/src/lib/styles/viewport.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,8 @@
3434

3535
// In case scroll bounce need to be disabled
3636
overscroll-behavior: var(--_viewport-overscroll-behavior);
37+
38+
// Disables scroll when disableInteraction is set to true
39+
pointer-events: var(--_viewport-pointer-events);
3740
}
3841
}

projects/ngx-scrollbar/src/lib/tests/disable-interactions.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ describe('disableInteraction option', () => {
6767
const trackXWrapperStyles: CSSStyleDeclaration = getComputedStyle(trackX.nativeElement.parentElement);
6868
const trackYWrapperStyles: CSSStyleDeclaration = getComputedStyle(trackY.nativeElement.parentElement);
6969
expect(componentStyles.getPropertyValue('--_scrollbar-pointer-events')).toBe('auto');
70+
expect(componentStyles.getPropertyValue('--_viewport-pointer-events')).toBe('auto');
71+
expect(componentStyles.pointerEvents).toBe('auto');
7072
expect(trackXWrapperStyles.pointerEvents).toBe('auto');
7173
expect(trackYWrapperStyles.pointerEvents).toBe('auto');
7274
}
@@ -89,6 +91,8 @@ describe('disableInteraction option', () => {
8991
const trackXWrapperStyles: CSSStyleDeclaration = getComputedStyle(trackX.nativeElement.parentElement);
9092
const trackYWrapperStyles: CSSStyleDeclaration = getComputedStyle(trackY.nativeElement.parentElement);
9193
expect(componentStyles.getPropertyValue('--_scrollbar-pointer-events')).toBe('none');
94+
expect(componentStyles.getPropertyValue('--_viewport-pointer-events')).toBe('none');
95+
expect(componentStyles.pointerEvents).toBe('none');
9296
expect(trackXWrapperStyles.pointerEvents).toBe('none');
9397
expect(trackYWrapperStyles.pointerEvents).toBe('none');
9498
}

projects/ngx-scrollbar/src/lib/tests/ext-viewport-async.spec.ts

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ import { afterTimeout } from './common-test.';
1414
@if (show) {
1515
<div class="some-wrapper">
1616
<div class="my-custom-viewport">
17-
<div class="my-custom-content-wrapper">
18-
<div #sample class="content-sample">Content Sample</div>
19-
</div>
17+
@if (showWrapper) {
18+
<div class="my-custom-content-wrapper">
19+
<div #sample class="content-sample">Content Sample</div>
20+
</div>
21+
}
2022
<div class="my-custom-spacer"></div>
2123
</div>
2224
</div>
@@ -25,6 +27,7 @@ import { afterTimeout } from './common-test.';
2527
})
2628
class SampleLibComponent {
2729
show: boolean;
30+
showWrapper: boolean = true;
2831
@ViewChild('sample') content: ElementRef<HTMLElement>;
2932
}
3033

@@ -200,4 +203,59 @@ describe('External viewport via classes [AsyncDetection]', () => {
200203
fixture.destroy();
201204
expect(hostViewDestroySpy).toHaveBeenCalled();
202205
});
206+
207+
it('[asyncDetection="auto"] should detect content wrapper removal', async () => {
208+
component.externalViewport = '.my-custom-viewport';
209+
component.externalContentWrapper = '.my-custom-content-wrapper';
210+
component.asyncDetection = 'auto';
211+
fixture.detectChanges();
212+
213+
expect(scrollbar.customViewport()).toBeFalsy();
214+
expect(scrollbar.externalViewport()).toBeTruthy();
215+
expect(scrollbar.externalContentWrapper()).toBeTruthy();
216+
expect(scrollbar.externalSpacer()).toBeFalsy();
217+
expect(scrollbar.skipInit).toBeTruthy();
218+
expect(scrollbar.viewport.initialized()).toBeFalsy();
219+
220+
// Mock library render after the scrollbar has initialized
221+
component.library.show = true;
222+
fixture.detectChanges();
223+
224+
// Verify afterInit is called
225+
await firstValueFrom(outputToObservable(scrollbar.afterInit));
226+
227+
const viewportElement: HTMLElement = fixture.debugElement.query(By.css(scrollbar.externalViewport()))?.nativeElement;
228+
const contentWrapperElement: HTMLElement = fixture.debugElement.query(By.css(scrollbar.externalContentWrapper()))?.nativeElement;
229+
230+
// Verify the viewport
231+
expect(scrollbar.viewport.nativeElement).toBe(viewportElement);
232+
// Verify that the content wrapper here is the content wrapper element
233+
expect(scrollbar.viewport.contentWrapperElement).toBe(contentWrapperElement);
234+
// Verify that the content is a direct child of the content wrapper element
235+
expect(component.library.content.nativeElement.parentElement).toBe(contentWrapperElement);
236+
237+
// Check if the scrollbars component is created
238+
expect(scrollbar._scrollbars()).toBeTruthy();
239+
const scrollbarsDebugElement: DebugElement = fixture.debugElement.query(By.directive(Scrollbars));
240+
// Verify if the created scrollbars component is the same component instance queried
241+
expect(scrollbar._scrollbars()).toBe(scrollbarsDebugElement.componentInstance);
242+
// Check if the created scrollbars component is the direct child of content wrapper element
243+
expect((scrollbarsDebugElement.nativeElement as Element).parentElement).toBe(scrollbar.viewport.contentWrapperElement);
244+
245+
// MutationObserver has a throttleTime 100ms, need to wait before triggering a detection
246+
await afterTimeout(100);
247+
// Mock library removes the content (such as dropdown)
248+
component.library.showWrapper = false;
249+
fixture.detectChanges();
250+
// Wait a bit more than 100ms for change to take effect
251+
await afterTimeout(110);
252+
253+
expect(scrollbar.viewport.initialized()).toBeFalse();
254+
expect(scrollbar.viewport.nativeElement).toBeFalsy();
255+
expect(scrollbar.viewport.contentWrapperElement).toBeFalsy();
256+
257+
const hostViewDestroySpy: jasmine.Spy = spyOn(scrollbar._scrollbarsRef.hostView, 'destroy');
258+
fixture.destroy();
259+
expect(hostViewDestroySpy).toHaveBeenCalled();
260+
});
203261
});

projects/ngx-scrollbar/src/lib/tests/ext-viewport-class.spec.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ describe('External viewport via classes', () => {
8282
const attachScrollbarSpy: jasmine.Spy = spyOn(scrollbarCmp, '_attachScrollbars').and.callThrough();
8383
component.externalViewport = '.my-custom-viewport';
8484

85-
8685
fixture.detectChanges();
8786

8887
expect(scrollbarCmp.customViewport()).toBeFalsy();
@@ -231,7 +230,7 @@ describe('External viewport via classes', () => {
231230
expect(hostViewDestroySpy).toHaveBeenCalled();
232231
});
233232

234-
it(`[Error handling - content wrapper doesn't exist] should NOT initialize viewport or attach scrollbars`, async () => {
233+
it(`[Error handling - viewport doesn't exist] should NOT initialize viewport or attach scrollbars`, async () => {
235234
const fixture: ComponentFixture<WithViewportDirectiveAndInputsComponent> = TestBed.createComponent(WithViewportDirectiveAndInputsComponent);
236235
const component: WithViewportDirectiveAndInputsComponent = fixture.componentInstance;
237236
const scrollbarCmp: NgScrollbarExt = component.scrollbar();
@@ -240,8 +239,7 @@ describe('External viewport via classes', () => {
240239
const attachScrollbarSpy: jasmine.Spy = spyOn(scrollbarCmp, '_attachScrollbars').and.callThrough();
241240
const consoleSpy: jasmine.Spy = spyOn(console, 'error').and.callThrough();
242241

243-
component.externalViewport = '.not-existing-viewport';
244-
242+
component.externalViewport = null;
245243

246244
fixture.detectChanges();
247245

projects/ngx-scrollbar/src/lib/track/track-adapter.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ export abstract class TrackAdapter extends PointerEventsAdapter {
5656

5757
// Scrollbar track length
5858
get size(): number {
59-
return this.clientRect[this.control.rectSizeProperty];
59+
// Noticed that clientHeight is evaluated before getClientRect.height,
60+
// causing a wrong track size when integrated in dropdown integration
61+
return this.nativeElement[this.control.sizeProperty];
6062
}
6163

6264
// Observable for track dragging events
@@ -114,9 +116,7 @@ export abstract class TrackAdapter extends PointerEventsAdapter {
114116
effect(() => {
115117
this.cmp.viewportDimension();
116118
this.cmp.contentDimension();
117-
untracked(() => {
118-
requestAnimationFrame(() => this.control.trackSize.set(this.size));
119-
});
119+
untracked(() => this.control.trackSize.set(this.size));
120120
});
121121
super();
122122
}

0 commit comments

Comments
 (0)