Skip to content

Commit

Permalink
feat(module:all): Add RTL support to all ng-zorro-antd (#4703)
Browse files Browse the repository at this point in the history
close #4704, close #1762 close #5261

Co-authored-by: Hamed <[email protected]>
Co-authored-by: Hasan Daghash <[email protected]>
Co-authored-by: h.nikoo <[email protected]>
Co-authored-by: hdm91
Co-authored-by: Hsuan Lee <[email protected]>
Co-authored-by: Junhan Yang <[email protected]>
Co-authored-by: Wenqi Chen <[email protected]>
  • Loading branch information
7 people authored Dec 15, 2020
1 parent a481a15 commit 860dfed
Show file tree
Hide file tree
Showing 145 changed files with 4,114 additions and 1,097 deletions.
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node-options=--max-old-space-size=14000
38 changes: 35 additions & 3 deletions components/affix/affix.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { DOCUMENT } from '@angular/common';
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
Expand All @@ -16,6 +17,8 @@ import {
NgZone,
OnChanges,
OnDestroy,
OnInit,
Optional,
Output,
Renderer2,
SimpleChanges,
Expand All @@ -30,6 +33,7 @@ import { getStyleAsText, InputNumber, shallowEqual } from 'ng-zorro-antd/core/ut
import { fromEvent, merge, ReplaySubject, Subject, Subscription } from 'rxjs';
import { auditTime, map, takeUntil } from 'rxjs/operators';

import { Direction, Directionality } from '@angular/cdk/bidi';
import { AffixRespondEvents } from './respond-events';
import { getTargetRect, SimpleRect } from './utils';

Expand All @@ -48,7 +52,7 @@ const NZ_AFFIX_DEFAULT_SCROLL_TIME = 20;
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None
})
export class NzAffixComponent implements AfterViewInit, OnChanges, OnDestroy {
export class NzAffixComponent implements AfterViewInit, OnChanges, OnDestroy, OnInit {
readonly _nzModuleName: NzConfigKey = NZ_CONFIG_MODULE_NAME;
static ngAcceptInputType_nzOffsetTop: NumberInput;
static ngAcceptInputType_nzOffsetBottom: NumberInput;
Expand All @@ -69,6 +73,8 @@ export class NzAffixComponent implements AfterViewInit, OnChanges, OnDestroy {

@Output() readonly nzChange = new EventEmitter<boolean>();

dir: Direction = 'ltr';

private readonly placeholderNode: HTMLElement;

private affixStyle?: NgStyleInterface;
Expand All @@ -91,13 +97,26 @@ export class NzAffixComponent implements AfterViewInit, OnChanges, OnDestroy {
private scrollSrv: NzScrollService,
private ngZone: NgZone,
private platform: Platform,
private renderer: Renderer2
private renderer: Renderer2,
private cdr: ChangeDetectorRef,
@Optional() private directionality: Directionality
) {
// The wrapper would stay at the original position as a placeholder.
this.placeholderNode = el.nativeElement;
this.document = doc;
}

ngOnInit(): void {
this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => {
this.dir = direction;
this.registerListeners();
this.updatePosition({} as Event);
this.cdr.detectChanges();
});

this.dir = this.directionality.value;
}

ngOnChanges(changes: SimpleChanges): void {
const { nzOffsetBottom, nzOffsetTop, nzTarget } = changes;

Expand Down Expand Up @@ -182,7 +201,7 @@ export class NzAffixComponent implements AfterViewInit, OnChanges, OnDestroy {
} else {
wrapEl.classList.remove(NZ_AFFIX_CLS_PREFIX);
}

this.updateRtlClass();
if ((affixStyle && !originalAffixStyle) || (!affixStyle && originalAffixStyle)) {
this.nzChange.emit(fixed);
}
Expand Down Expand Up @@ -289,4 +308,17 @@ export class NzAffixComponent implements AfterViewInit, OnChanges, OnDestroy {
this.syncPlaceholderStyle(e);
}
}

private updateRtlClass(): void {
const wrapEl = this.fixedEl.nativeElement;
if (this.dir === 'rtl') {
if (wrapEl.classList.contains(NZ_AFFIX_CLS_PREFIX)) {
wrapEl.classList.add(`${NZ_AFFIX_CLS_PREFIX}-rtl`);
} else {
wrapEl.classList.remove(`${NZ_AFFIX_CLS_PREFIX}-rtl`);
}
} else {
wrapEl.classList.remove(`${NZ_AFFIX_CLS_PREFIX}-rtl`);
}
}
}
102 changes: 81 additions & 21 deletions components/affix/affix.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BidiModule, Dir } from '@angular/cdk/bidi';
import { Component, DebugElement, ViewChild } from '@angular/core';
import { ComponentFixture, discardPeriodicTasks, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { ComponentFixture, discardPeriodicTasks, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { NzScrollService } from 'ng-zorro-antd/core/services';

Expand Down Expand Up @@ -40,26 +41,28 @@ describe('affix', () => {
const height = 100;
const width = 100;

beforeEach(fakeAsync(() => {
TestBed.configureTestingModule({
imports: [NzAffixModule],
declarations: [TestAffixComponent],
providers: [
{
provide: NzScrollService,
useClass: NzScrollService
}
]
}).compileComponents();

fixture = TestBed.createComponent(TestAffixComponent);
context = fixture.componentInstance;
component = context.nzAffixComponent;
scrollService = TestBed.inject(NzScrollService);
componentObject = new NzAffixPageObject();
debugElement = fixture.debugElement;
componentObject.wrap().id = 'wrap';
}));
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
imports: [NzAffixModule],
declarations: [TestAffixComponent],
providers: [
{
provide: NzScrollService,
useClass: NzScrollService
}
]
}).compileComponents();

fixture = TestBed.createComponent(TestAffixComponent);
context = fixture.componentInstance;
component = context.nzAffixComponent;
scrollService = TestBed.inject(NzScrollService);
componentObject = new NzAffixPageObject();
debugElement = fixture.debugElement;
componentObject.wrap().id = 'wrap';
})
);
afterEach(fakeAsync(() => {
setupInitialState();
}));
Expand Down Expand Up @@ -493,6 +496,43 @@ describe('affix-extra', () => {
}));
});

describe('affix RTL', () => {
let fixture: ComponentFixture<TestAffixRtlComponent>;
let context: TestAffixRtlComponent;
let dl: DebugElement;

beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
imports: [BidiModule, NzAffixModule],
declarations: [TestAffixRtlComponent]
}).compileComponents();
fixture = TestBed.createComponent(TestAffixRtlComponent);
context = fixture.componentInstance;
dl = fixture.debugElement;
})
);
it('should className correct on dir change', fakeAsync(() => {
const value = 10;
context.newOffsetBottom = value;
context.fakeTarget = window;
fixture.detectChanges();
const el = dl.query(By.css('nz-affix')).nativeElement as HTMLElement;
spyOn(el, 'getBoundingClientRect').and.returnValue({
top: 1000,
left: 5,
width: 200,
height: 20
} as DOMRect);
window.dispatchEvent(new Event('scroll'));
tick(30);
fixture.detectChanges();
window.dispatchEvent(new Event('scroll'));
tick(30);
fixture.detectChanges();
expect(el.querySelector('.ant-affix')?.classList).toContain('ant-affix-rtl');
}));
});
@Component({
template: `
<nz-affix id="affix" [nzTarget]="fakeTarget" [nzOffsetTop]="newOffset" [nzOffsetBottom]="newOffsetBottom">
Expand All @@ -507,3 +547,23 @@ class TestAffixComponent {
newOffset!: number;
newOffsetBottom!: number;
}

@Component({
template: `
<div [dir]="direction">
<nz-affix id="affix" [nzTarget]="fakeTarget" [nzOffsetTop]="newOffset" [nzOffsetBottom]="newOffsetBottom">
<button id="content">Affix Button</button>
</nz-affix>
<div id="target"></div>
</div>
`
})
export class TestAffixRtlComponent {
@ViewChild(Dir) dir!: Dir;
direction = 'rtl';

@ViewChild(NzAffixComponent, { static: true }) nzAffixComponent!: NzAffixComponent;
fakeTarget: string | Element | Window | null = null;
newOffset!: number;
newOffsetBottom!: number;
}
18 changes: 16 additions & 2 deletions components/alert/alert.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/

import { Direction, Directionality } from '@angular/cdk/bidi';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Expand All @@ -11,6 +12,8 @@ import {
Input,
OnChanges,
OnDestroy,
OnInit,
Optional,
Output,
SimpleChanges,
TemplateRef,
Expand All @@ -33,6 +36,7 @@ const NZ_CONFIG_MODULE_NAME: NzConfigKey = 'alert';
<div
*ngIf="!closed"
class="ant-alert"
[class.ant-alert-rtl]="dir === 'rtl'"
[class.ant-alert-success]="nzType === 'success'"
[class.ant-alert-info]="nzType === 'info'"
[class.ant-alert-warning]="nzType === 'warning'"
Expand Down Expand Up @@ -72,7 +76,7 @@ const NZ_CONFIG_MODULE_NAME: NzConfigKey = 'alert';
encapsulation: ViewEncapsulation.None,
preserveWhitespaces: false
})
export class NzAlertComponent implements OnChanges, OnDestroy {
export class NzAlertComponent implements OnChanges, OnDestroy, OnInit {
readonly _nzModuleName: NzConfigKey = NZ_CONFIG_MODULE_NAME;
static ngAcceptInputType_nzCloseable: BooleanInput;
static ngAcceptInputType_nzShowIcon: BooleanInput;
Expand All @@ -92,11 +96,12 @@ export class NzAlertComponent implements OnChanges, OnDestroy {
closed = false;
iconTheme: 'outline' | 'fill' = 'fill';
inferredIconType: string = 'info-circle';
dir: Direction = 'ltr';
private isTypeSet = false;
private isShowIconSet = false;
private destroy$ = new Subject();

constructor(public nzConfigService: NzConfigService, private cdr: ChangeDetectorRef) {
constructor(public nzConfigService: NzConfigService, private cdr: ChangeDetectorRef, @Optional() private directionality: Directionality) {
this.nzConfigService
.getConfigChangeEventForComponent(NZ_CONFIG_MODULE_NAME)
.pipe(takeUntil(this.destroy$))
Expand All @@ -105,6 +110,15 @@ export class NzAlertComponent implements OnChanges, OnDestroy {
});
}

ngOnInit(): void {
this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => {
this.dir = direction;
this.cdr.detectChanges();
});

this.dir = this.directionality.value;
}

closeAlert(): void {
this.closed = true;
}
Expand Down
53 changes: 42 additions & 11 deletions components/alert/alert.spec.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import { BidiModule, Dir } from '@angular/cdk/bidi';
import { Component, DebugElement, TemplateRef, ViewChild } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { NzIconTestModule } from 'ng-zorro-antd/icon/testing';
import { NzAlertComponent } from './alert.component';
import { NzAlertModule } from './alert.module';

describe('alert', () => {
beforeEach(fakeAsync(() => {
TestBed.configureTestingModule({
imports: [NzAlertModule, NoopAnimationsModule, NzIconTestModule],
declarations: [NzDemoTestBasicComponent, NzDemoTestBannerComponent]
});
TestBed.compileComponents();
}));
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
imports: [BidiModule, NzAlertModule, NoopAnimationsModule, NzIconTestModule],
declarations: [NzDemoTestBasicComponent, NzDemoTestBannerComponent, NzTestAlertRtlComponent]
});
TestBed.compileComponents();
})
);

describe('basic alert', () => {
let fixture: ComponentFixture<NzDemoTestBasicComponent>;
let testComponent: NzDemoTestBasicComponent;
Expand Down Expand Up @@ -115,9 +119,23 @@ describe('alert', () => {
expect(alert.nativeElement.querySelector('.ant-alert-icon')).toBeDefined();
});
});
describe('RTL', () => {
it('should className correct on dir change', () => {
const fixture = TestBed.createComponent(NzTestAlertRtlComponent);
const alert = fixture.debugElement.query(By.directive(NzAlertComponent));
fixture.detectChanges();
expect(alert.nativeElement.firstElementChild!.classList).toContain('ant-alert-rtl');

fixture.componentInstance.direction = 'ltr';
fixture.detectChanges();
expect(alert.nativeElement.firstElementChild!.classList).not.toContain('ant-alert-rtl');
});
});
});

@Component({
// tslint:disable-next-line:no-selector
selector: 'nz-test-basic-alert',
template: `
<ng-template #template>template</ng-template>
<nz-alert
Expand All @@ -130,8 +148,7 @@ describe('alert', () => {
[nzIconType]="iconType"
[nzType]="type"
(nzOnClose)="onClose($event)"
>
</nz-alert>
></nz-alert>
`
})
export class NzDemoTestBasicComponent {
Expand All @@ -148,6 +165,20 @@ export class NzDemoTestBasicComponent {
}

@Component({
template: ` <nz-alert nzBanner> </nz-alert> `
template: `
<nz-alert nzBanner></nz-alert>
`
})
export class NzDemoTestBannerComponent {}

@Component({
template: `
<div [dir]="direction">
<nz-test-basic-alert></nz-test-basic-alert>
</div>
`
})
export class NzTestAlertRtlComponent {
@ViewChild(Dir) dir!: Dir;
direction = 'rtl';
}
Loading

0 comments on commit 860dfed

Please sign in to comment.