Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
MurhafSousli committed Mar 4, 2024
1 parent 85e57f8 commit 4992484
Show file tree
Hide file tree
Showing 22 changed files with 548 additions and 235 deletions.
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# These are supported funding model platforms

github: # murhafsousli
github: murhafsousli
patreon: murhaf
open_collective: ngx-scrollbar
ko_fi: # Replace with a single Ko-fi username
Expand Down
1 change: 0 additions & 1 deletion angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@
"zone.js",
"zone.js/testing"
],
"codeCoverage": true,
"karmaConfig": "projects/ngx-scrollbar/karma.conf.js"
}
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"watch": "ng build --watch --configuration development",
"build-lib": "ng build ngx-scrollbar",
"test-lib": "ng test ngx-scrollbar",
"test-lib-headless": "ng test ngx-scrollbar --watch=false --no-progress --browsers=ChromeHeadless",
"test-lib-headless": "ng test ngx-scrollbar --watch=false --no-progress --browsers=ChromeHeadless --code-coverage",
"serve:ssr:ngx-scrollbar-demo": "node dist/ngx-scrollbar-demo/server/server.mjs"
},
"private": true,
Expand Down
3 changes: 2 additions & 1 deletion projects/ngx-scrollbar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
[![Stackblitz](https://img.shields.io/badge/stackblitz-online-orange.svg)](https://stackblitz.com/edit/ngx-scrollbar)
[![Backers on Open Collective](https://opencollective.com/ngx-scrollbar/tiers/backers/badge.svg?label=Backers&color=brightgreen)](#sponsoring-ngx-scrollbar)
[![npm](https://img.shields.io/npm/v/ngx-scrollbar.svg?maxAge=2592000?style=plastic)](https://www.npmjs.com/package/ngx-scrollbar)
[![tests](https://github.com/MurhafSousli/ngx-scrollbar/workflows/tests/badge.svg)](https://github.com/MurhafSousli/ngx-scrollbar/actions?query=workflow%3Atests)
[![CI Build](https://github.com/MurhafSousli/ngx-scrollbar/workflows/tests/badge.svg)](https://github.com/MurhafSousli/ngx-scrollbar/actions?query=workflow%3Aci-build)
[![codecov](https://codecov.io/gh/MurhafSousli/ngx-scrollbar/graph/badge.svg?token=TO2idZEE1i)](https://codecov.io/gh/MurhafSousli/ngx-scrollbar)
[![Downloads](https://img.shields.io/npm/dt/ngx-scrollbar.svg?maxAge=2592000?style=plastic)](https://www.npmjs.com/package/ngx-scrollbar)
[![NPM Downloads](https://img.shields.io/npm/dm/ngx-scrollbar.svg)](https://www.npmjs.com/package/ngx-scrollbar)
[![License](https://img.shields.io/npm/l/express.svg?maxAge=2592000)](/LICENSE)
Expand Down
2 changes: 1 addition & 1 deletion projects/ngx-scrollbar/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-scrollbar",
"version": "14.0.0-beta.4",
"version": "14.0.0-beta.5",
"license": "MIT",
"homepage": "https://ngx-scrollbar.netlify.com/",
"author": {
Expand Down
9 changes: 4 additions & 5 deletions projects/ngx-scrollbar/src/lib/async-detection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,11 @@ export class AsyncDetection implements OnInit, OnDestroy {
}
} else {
const viewportElement: HTMLElement = this.scrollbar.nativeElement.querySelector(this.scrollbar.externalViewport);
if (!viewportElement) {
this.scrollbar.viewport.initialized.set(false);
return;
}
const contentWrapperElement: HTMLElement = this.scrollbar.nativeElement.querySelector(this.scrollbar.externalContentWrapper);
if (!contentWrapperElement) {

if (!viewportElement || !contentWrapperElement) {
this.scrollbar.viewport.nativeElement = null;
this.scrollbar.viewport.contentWrapperElement = null;
this.scrollbar.viewport.initialized.set(false);
}
}
Expand Down
101 changes: 53 additions & 48 deletions projects/ngx-scrollbar/src/lib/ng-scrollbar-ext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,63 +76,68 @@ export class NgScrollbarExt extends NgScrollbarCore implements OnInit {

override ngOnInit(): void {
if (!this.skipInit) {
this.detectExternalSelectors();
}
super.ngOnInit();
}

let viewportElement: HTMLElement;
if (this.customViewport) {
viewportElement = this.customViewport.nativeElement;
} else {
// If viewport selector was defined, query the element
if (this.externalViewport) {
viewportElement = this.nativeElement.querySelector(this.externalViewport);
}
if (!viewportElement) {
console.error(`[NgScrollbar]: Could not find the viewport element for the provided selector "${ this.externalViewport }"`);
}
private detectExternalSelectors(): void {
let viewportElement: HTMLElement;
if (this.customViewport) {
viewportElement = this.customViewport.nativeElement;
} else {
// If viewport selector was defined, query the element
if (this.externalViewport) {
viewportElement = this.nativeElement.querySelector(this.externalViewport);
}

// If an external spacer selector is provided, attempt to query for it
let spacerElement: HTMLElement;
if (this.externalSpacer) {
spacerElement = this.nativeElement.querySelector(this.externalSpacer);
if (!spacerElement) {
console.error(`[NgScrollbar]: Spacer element not found for the provided selector "${ this.externalSpacer }"`);
}
if (!viewportElement) {
console.error(`[NgScrollbar]: Could not find the viewport element for the provided selector "${ this.externalViewport }"`);
return;
}
}

// If an external content wrapper selector is provided, attempt to query for it
let contentWrapperElement: HTMLElement;
if (this.externalContentWrapper && !this.skipInit) {
contentWrapperElement = this.nativeElement.querySelector(this.externalContentWrapper);
if (!contentWrapperElement) {
console.error(`[NgScrollbar]: Content wrapper element not found for the provided selector "${ this.externalContentWrapper }"`);
}
// If an external spacer selector is provided, attempt to query for it
let spacerElement: HTMLElement;
if (this.externalSpacer) {
spacerElement = this.nativeElement.querySelector(this.externalSpacer);
if (!spacerElement) {
console.error(`[NgScrollbar]: Spacer element not found for the provided selector "${ this.externalSpacer }"`);
return;
}
}

// Make sure viewport element is defined to proceed
if (viewportElement) {
// If no external spacer or content wrapper is provided, create a content wrapper element
if (!this.externalSpacer && !this.externalContentWrapper) {
contentWrapperElement = this.renderer.createElement('div');

// Move all content of the viewport into the content wrapper
const childNodes: ChildNode[] = Array.from(viewportElement.childNodes);
childNodes.forEach((node: ChildNode) => this.renderer.appendChild(contentWrapperElement, node));

// Append the content wrapper to the viewport
this.renderer.appendChild(viewportElement, contentWrapperElement);
}

// Make sure content wrapper element is defined to proceed
if (contentWrapperElement) {
// Initialize viewport
this.viewport.init(viewportElement, contentWrapperElement, spacerElement);
// Attach scrollbars
this.attachScrollbars();
}
// If an external content wrapper selector is provided, attempt to query for it
let contentWrapperElement: HTMLElement;
if (this.externalContentWrapper && !this.skipInit) {
contentWrapperElement = this.nativeElement.querySelector(this.externalContentWrapper);
if (!contentWrapperElement) {
console.error(`[NgScrollbar]: Content wrapper element not found for the provided selector "${ this.externalContentWrapper }"`);
return;
}
}

super.ngOnInit();
// Make sure viewport element is defined to proceed
if (viewportElement) {
// If no external spacer or content wrapper is provided, create a content wrapper element
if (!this.externalSpacer && !this.externalContentWrapper) {
contentWrapperElement = this.renderer.createElement('div');

// Move all content of the viewport into the content wrapper
const childNodes: ChildNode[] = Array.from(viewportElement.childNodes);
childNodes.forEach((node: ChildNode) => this.renderer.appendChild(contentWrapperElement, node));

// Append the content wrapper to the viewport
this.renderer.appendChild(viewportElement, contentWrapperElement);
}

// Make sure content wrapper element is defined to proceed
if (contentWrapperElement) {
// Initialize viewport
this.viewport.init(viewportElement, contentWrapperElement, spacerElement);
// Attach scrollbars
this.attachScrollbars();
}
}
}

attachScrollbars(): void {
Expand Down
10 changes: 5 additions & 5 deletions projects/ngx-scrollbar/src/lib/scrollbar/scrollbar-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export abstract class ScrollbarAdapter {
readonly thumb: ThumbAdapter;
// Track directive reference
readonly track: TrackAdapter;
// Pointer events subscription
private pointerEventsSub: Subscription;
// Pointer events subscription (made public for testing purpose)
_pointerEventsSub: Subscription;
// Zone reference
protected readonly zone: NgZone = inject(NgZone);
// Host component reference
Expand All @@ -33,10 +33,10 @@ export abstract class ScrollbarAdapter {
constructor() {
effect((onCleanup: EffectCleanupRegisterFn) => {
if (this.cmp.disableInteraction()) {
this.pointerEventsSub?.unsubscribe();
this._pointerEventsSub?.unsubscribe();
} else {
this.zone.runOutsideAngular(() => {
this.pointerEventsSub = merge(
this._pointerEventsSub = merge(
// Activate scrollbar thumb drag event
this.thumb.dragged,
// Activate scrollbar track click event
Expand All @@ -45,7 +45,7 @@ export abstract class ScrollbarAdapter {
});
}

onCleanup(() => this.pointerEventsSub?.unsubscribe());
onCleanup(() => this._pointerEventsSub?.unsubscribe());
});
}
}
55 changes: 0 additions & 55 deletions projects/ngx-scrollbar/src/lib/tests/clicks.spec.ts

This file was deleted.

77 changes: 77 additions & 0 deletions projects/ngx-scrollbar/src/lib/tests/disable-interactions.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { NgScrollbar } from 'ngx-scrollbar';
import { ComponentFixture, ComponentFixtureAutoDetect, TestBed } from '@angular/core/testing';
import { firstValueFrom } from 'rxjs';
import { setDimensions } from './common-test.';

describe('disableInteraction option', () => {
let component: NgScrollbar;
let fixture: ComponentFixture<NgScrollbar>;

let interactionSubscriptionXSpy: jasmine.Spy;
let interactionSubscriptionYSpy: jasmine.Spy;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [NgScrollbar],
providers: [
{ provide: ComponentFixtureAutoDetect, useValue: true }
]
}).compileComponents();

fixture = TestBed.createComponent(NgScrollbar);
component = fixture.componentInstance;
fixture.detectChanges();
});

function interactionEnabledCases(): void {
expect(component.disableInteraction()).toBeFalse();
expect(component.nativeElement.getAttribute('disableInteraction')).toBe('false');

expect(component._scrollbars.x._pointerEventsSub.closed).toBeFalse();
expect(component._scrollbars.y._pointerEventsSub.closed).toBeFalse();

const componentStyles: CSSStyleDeclaration = getComputedStyle(component.nativeElement);
const trackXStyles: CSSStyleDeclaration = getComputedStyle(component._scrollbars.x.track.nativeElement);
const trackYStyles: CSSStyleDeclaration = getComputedStyle(component._scrollbars.y.track.nativeElement);
expect(componentStyles.getPropertyValue('--_scrollbar-pointer-events')).toBe('auto');
expect(trackXStyles.pointerEvents).toBe('auto');
expect(trackYStyles.pointerEvents).toBe('auto');
}

function interactionDisabledCases(): void {
expect(component.disableInteraction()).toBeTrue();
expect(component.nativeElement.getAttribute('disableInteraction')).toBe('true');

expect(interactionSubscriptionXSpy).toHaveBeenCalled();
expect(interactionSubscriptionYSpy).toHaveBeenCalled();

const componentStyles: CSSStyleDeclaration = getComputedStyle(component.nativeElement);
const trackXStyles: CSSStyleDeclaration = getComputedStyle(component._scrollbars.x.track.nativeElement);
const trackYStyles: CSSStyleDeclaration = getComputedStyle(component._scrollbars.y.track.nativeElement);
expect(componentStyles.getPropertyValue('--_scrollbar-pointer-events')).toBe('none');
expect(trackXStyles.pointerEvents).toBe('none');
expect(trackYStyles.pointerEvents).toBe('none');
}

it('should disable interactions for track and thumb', async () => {
setDimensions(component, { cmpHeight: 100, cmpWidth: 100, contentHeight: 300, contentWidth: 300 });
component.ngOnInit();
component.ngAfterViewInit();
await firstValueFrom(component.afterInit);

interactionSubscriptionXSpy = spyOn(component._scrollbars.x._pointerEventsSub, 'unsubscribe');
interactionSubscriptionYSpy = spyOn(component._scrollbars.y._pointerEventsSub, 'unsubscribe');

interactionEnabledCases();

fixture.componentRef.setInput('disableInteraction', true);
fixture.detectChanges();

interactionDisabledCases();

fixture.componentRef.setInput('disableInteraction', false);
fixture.detectChanges();

interactionEnabledCases();
});
});
Loading

0 comments on commit 4992484

Please sign in to comment.