-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(module:core): support reset NZ_CONFIG inside component & overflo…
…w component (#6601) * feat(module:config): support reset NZ_CONFIG inside component * refactor: add onDestroy service * feat: add cdk entry * refactor: rebase eslint * feat: support overflow
- Loading branch information
Showing
33 changed files
with
720 additions
and
107 deletions.
There are no files selected for viewing
File renamed without changes.
163 changes: 163 additions & 0 deletions
163
components/cdk/overflow/overflow-container.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
/** | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE | ||
*/ | ||
|
||
import { | ||
Component, | ||
ChangeDetectionStrategy, | ||
ContentChildren, | ||
QueryList, | ||
ElementRef, | ||
OnInit, | ||
AfterContentInit, | ||
OnDestroy, | ||
ContentChild, | ||
ChangeDetectorRef | ||
} from '@angular/core'; | ||
import { BehaviorSubject, combineLatest, Observable, ReplaySubject, Subject } from 'rxjs'; | ||
import { filter, map, pairwise, startWith, switchMap, takeUntil, withLatestFrom } from 'rxjs/operators'; | ||
|
||
import { NzResizeObserver } from 'ng-zorro-antd/cdk/resize-observer'; | ||
|
||
import { NzOverflowItemDirective } from './overflow-item.directive'; | ||
import { NzOverflowRestDirective } from './overflow-rest.directive'; | ||
import { NzOverflowSuffixDirective } from './overflow-suffix.directive'; | ||
|
||
@Component({ | ||
selector: 'nz-overflow-container', | ||
template: ` <ng-content></ng-content> | ||
<ng-content select="[appOverflowRest]"></ng-content> | ||
<ng-content select="[appOverflowSuffix]"></ng-content>`, | ||
providers: [NzResizeObserver], | ||
changeDetection: ChangeDetectionStrategy.OnPush | ||
}) | ||
export class NzOverflowContainerComponent implements OnInit, AfterContentInit, OnDestroy { | ||
contentInit$ = new Subject<void>(); | ||
@ContentChildren(NzOverflowItemDirective) | ||
overflowItems: QueryList<NzOverflowItemDirective> | undefined = undefined; | ||
@ContentChild(NzOverflowSuffixDirective) | ||
overflowSuffix: NzOverflowSuffixDirective | undefined = undefined; | ||
@ContentChild(NzOverflowRestDirective) overflowRest: NzOverflowRestDirective | undefined = undefined; | ||
overflowItems$ = new ReplaySubject<QueryList<NzOverflowItemDirective>>(1); | ||
destroy$ = new Subject<void>(); | ||
containerWidth$ = this.nzResizeObserver | ||
.observe(this.elementRef.nativeElement) | ||
.pipe(map(([item]) => item.target.clientWidth || 0)); | ||
restWidth$ = new BehaviorSubject<number>(0); | ||
suffixWidth$ = new BehaviorSubject<number>(0); | ||
suffixFixedStart$ = new BehaviorSubject<number | null>(null); | ||
displayCount$ = new BehaviorSubject<number>(Number.MAX_SAFE_INTEGER); | ||
restReady$ = new BehaviorSubject<boolean>(false); | ||
maxRestWith$ = this.restWidth$.pipe( | ||
pairwise(), | ||
map(([prevRestWidth, restWidth]) => Math.max(prevRestWidth, restWidth)) | ||
); | ||
omittedItems$ = combineLatest([this.overflowItems$, this.displayCount$]).pipe( | ||
withLatestFrom(this.contentInit$), | ||
map(([[overflowItems, displayCount]]) => overflowItems.toArray().slice(displayCount + 1)) | ||
); | ||
displayRest$ = combineLatest([this.restReady$, this.omittedItems$]).pipe( | ||
map(([restReady, omittedItems]) => restReady && !!omittedItems.length) | ||
); | ||
|
||
updateDisplayCount(count: number, notReady?: boolean): void { | ||
this.displayCount$.next(count); | ||
if (this.overflowItems && !notReady) { | ||
this.restReady$.next(count < this.overflowItems.length - 1); | ||
} | ||
} | ||
|
||
constructor( | ||
private nzResizeObserver: NzResizeObserver, | ||
private elementRef: ElementRef, | ||
private cdr: ChangeDetectorRef | ||
) {} | ||
|
||
ngOnInit(): void { | ||
const overflowItemsWidth$ = this.overflowItems$.pipe( | ||
switchMap(items => combineLatest(items.map(item => item.itemWidth$))) | ||
) as Observable<number[]>; | ||
this.overflowItems$.pipe(takeUntil(this.destroy$)).subscribe(overflowItems => { | ||
if (!overflowItems.length) { | ||
this.displayCount$.next(0); | ||
this.suffixFixedStart$.next(null); | ||
} | ||
}); | ||
combineLatest([overflowItemsWidth$, this.containerWidth$, this.maxRestWith$, this.restWidth$, this.suffixWidth$]) | ||
.pipe( | ||
filter(([, containerWidth, maxRestWith]) => !!(containerWidth && maxRestWith)), | ||
takeUntil(this.destroy$) | ||
) | ||
.subscribe(([overflowItemsWidth, containerWidth, maxRestWith, restWidth, suffixWidth]) => { | ||
let totalWidth = suffixWidth; | ||
const len = overflowItemsWidth.length; | ||
const lastIndex = len - 1; | ||
for (let i = 0; i < len; i += 1) { | ||
const currentItemWidth = overflowItemsWidth[i]; | ||
// Break since data not ready | ||
if (currentItemWidth === undefined) { | ||
this.updateDisplayCount(i - 1, true); | ||
break; | ||
} else { | ||
// Find best match | ||
totalWidth += currentItemWidth; | ||
|
||
if ( | ||
// Only one means `totalWidth` is the final width | ||
(lastIndex === 0 && totalWidth <= containerWidth) || | ||
// Last two width will be the final width | ||
(i === lastIndex - 1 && | ||
overflowItemsWidth[lastIndex] !== undefined && | ||
totalWidth + overflowItemsWidth[lastIndex]! <= containerWidth) | ||
) { | ||
// Additional check if match the end | ||
this.updateDisplayCount(lastIndex); | ||
this.suffixFixedStart$.next(null); | ||
break; | ||
} else if (totalWidth + maxRestWith > containerWidth) { | ||
// Can not hold all the content to show rest | ||
this.updateDisplayCount(i - 1); | ||
this.suffixFixedStart$.next(totalWidth - currentItemWidth - suffixWidth + restWidth); | ||
break; | ||
} | ||
this.cdr.detectChanges(); | ||
} | ||
} | ||
if ( | ||
this.overflowSuffix && | ||
overflowItemsWidth[0] !== undefined && | ||
overflowItemsWidth[0] + suffixWidth > containerWidth | ||
) { | ||
this.suffixFixedStart$.next(null); | ||
} | ||
|
||
this.cdr.detectChanges(); | ||
}); | ||
combineLatest([this.suffixFixedStart$, this.displayCount$]) | ||
.pipe(takeUntil(this.destroy$)) | ||
.subscribe(([suffixFixedStart, displayCount]) => { | ||
this.overflowSuffix?.setSuffixStyle(suffixFixedStart, displayCount); | ||
}); | ||
combineLatest([this.displayCount$, this.overflowItems$]) | ||
.pipe(takeUntil(this.destroy$)) | ||
.subscribe(([displayCount, overflowItems]) => | ||
overflowItems.forEach((item, index) => item.setItemStyle(index <= displayCount, index)) | ||
); | ||
combineLatest([this.displayRest$, this.displayCount$]) | ||
.pipe(takeUntil(this.destroy$)) | ||
.subscribe(([displayRest, displayCount]) => { | ||
this.overflowRest?.setRestStyle(displayRest, displayRest ? displayCount : Number.MAX_SAFE_INTEGER); | ||
}); | ||
} | ||
ngAfterContentInit(): void { | ||
this.overflowItems?.changes.pipe(startWith(this.overflowItems)).subscribe(this.overflowItems$); | ||
this.overflowSuffix?.suffixWidth$.subscribe(this.suffixWidth$); | ||
this.overflowRest?.restWidth$.subscribe(this.restWidth$); | ||
this.contentInit$.next(); | ||
} | ||
ngOnDestroy(): void { | ||
this.destroy$.next(); | ||
this.destroy$.complete(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/** | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE | ||
*/ | ||
|
||
import { ChangeDetectorRef, Directive, ElementRef } from '@angular/core'; | ||
import { distinctUntilChanged, map, startWith, tap } from 'rxjs/operators'; | ||
|
||
import { NzResizeObserver } from 'ng-zorro-antd/cdk/resize-observer'; | ||
|
||
@Directive({ | ||
selector: '[nzOverflowItem]', | ||
host: { | ||
'[style]': 'overflowStyle' | ||
} | ||
}) | ||
export class NzOverflowItemDirective { | ||
overflowStyle: { [key: string]: string | number | undefined } | undefined = undefined; | ||
itemWidth$ = this.nzResizeObserver.observe(this.elementRef.nativeElement).pipe( | ||
map(([item]) => (item.target as HTMLElement).offsetWidth), | ||
distinctUntilChanged(), | ||
startWith(undefined), | ||
tap(width => { | ||
this.itemWidth = width; | ||
}) | ||
); | ||
itemWidth: number | undefined = undefined; | ||
constructor( | ||
private nzResizeObserver: NzResizeObserver, | ||
public elementRef: ElementRef, | ||
private cdr: ChangeDetectorRef | ||
) {} | ||
|
||
setItemStyle(display: boolean, order: number): void { | ||
const mergedHidden = !display; | ||
this.overflowStyle = { | ||
opacity: mergedHidden ? 0 : 1, | ||
height: mergedHidden ? 0 : undefined, | ||
overflowY: mergedHidden ? 'hidden' : undefined, | ||
order: order, | ||
pointerEvents: mergedHidden ? 'none' : undefined, | ||
position: mergedHidden ? 'absolute' : undefined | ||
}; | ||
this.cdr.detectChanges(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/** | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE | ||
*/ | ||
|
||
import { ChangeDetectorRef, Directive, ElementRef } from '@angular/core'; | ||
import { map, startWith, tap } from 'rxjs/operators'; | ||
|
||
import { NzResizeObserver } from 'ng-zorro-antd/cdk/resize-observer'; | ||
|
||
@Directive({ | ||
selector: '[nzOverflowRest]', | ||
host: { | ||
'[style]': 'restStyle' | ||
} | ||
}) | ||
export class NzOverflowRestDirective { | ||
restStyle: { [key: string]: string | number | undefined } | undefined = undefined; | ||
restWidth$ = this.nzResizeObserver.observe(this.elementRef.nativeElement).pipe( | ||
map(([item]) => (item.target as HTMLElement).offsetWidth), | ||
startWith(0), | ||
tap(width => (this.restWidth = width)) | ||
); | ||
restWidth = 0; | ||
constructor( | ||
private nzResizeObserver: NzResizeObserver, | ||
private elementRef: ElementRef, | ||
private cdr: ChangeDetectorRef | ||
) {} | ||
|
||
setRestStyle(display: boolean, order: number): void { | ||
const mergedHidden = !display; | ||
this.restStyle = { | ||
opacity: mergedHidden ? 0 : 1, | ||
height: mergedHidden ? 0 : undefined, | ||
overflowY: mergedHidden ? 'hidden' : undefined, | ||
order: order, | ||
pointerEvents: mergedHidden ? 'none' : undefined, | ||
position: mergedHidden ? 'absolute' : undefined | ||
}; | ||
this.cdr.detectChanges(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/** | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE | ||
*/ | ||
|
||
import { ChangeDetectorRef, Directive, ElementRef } from '@angular/core'; | ||
import { map, tap } from 'rxjs/operators'; | ||
|
||
import { NzResizeObserver } from 'ng-zorro-antd/cdk/resize-observer'; | ||
|
||
@Directive({ | ||
selector: '[nzOverflowSuffix]', | ||
host: { | ||
'[style]': 'suffixStyle' | ||
} | ||
}) | ||
export class NzOverflowSuffixDirective { | ||
suffixStyle = {}; | ||
suffixWidth$ = this.nzResizeObserver.observe(this.elementRef.nativeElement).pipe( | ||
map(([item]) => (item.target as HTMLElement).offsetWidth), | ||
tap(width => (this.suffixWidth = width)) | ||
); | ||
suffixWidth = 0; | ||
constructor( | ||
private nzResizeObserver: NzResizeObserver, | ||
private elementRef: ElementRef, | ||
private cdr: ChangeDetectorRef | ||
) {} | ||
|
||
setSuffixStyle(start: number | null, order: number): void { | ||
if (start !== null) { | ||
this.suffixStyle = { | ||
position: 'absolute', | ||
left: `${start}px`, | ||
top: 0, | ||
opacity: 1, | ||
order: order | ||
}; | ||
} else { | ||
this.suffixStyle = { | ||
opacity: 1, | ||
order: order | ||
}; | ||
} | ||
this.cdr.detectChanges(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE | ||
*/ | ||
|
||
import { NgModule } from '@angular/core'; | ||
|
||
import { NzResizeObserverModule } from 'ng-zorro-antd/cdk/resize-observer'; | ||
|
||
import { NzOverflowContainerComponent } from './overflow-container.component'; | ||
import { NzOverflowItemDirective } from './overflow-item.directive'; | ||
import { NzOverflowRestDirective } from './overflow-rest.directive'; | ||
import { NzOverflowSuffixDirective } from './overflow-suffix.directive'; | ||
|
||
@NgModule({ | ||
imports: [NzResizeObserverModule], | ||
declarations: [ | ||
NzOverflowContainerComponent, | ||
NzOverflowItemDirective, | ||
NzOverflowRestDirective, | ||
NzOverflowSuffixDirective | ||
], | ||
exports: [NzOverflowContainerComponent, NzOverflowItemDirective, NzOverflowRestDirective, NzOverflowSuffixDirective] | ||
}) | ||
export class NzOverflowModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"ngPackage": { | ||
"lib": { | ||
"entryFile": "public-api.ts" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE | ||
*/ | ||
|
||
export { NzOverflowModule } from './overflow.module'; | ||
export { NzOverflowContainerComponent } from './overflow-container.component'; | ||
export { NzOverflowItemDirective } from './overflow-item.directive'; | ||
export { NzOverflowRestDirective } from './overflow-rest.directive'; | ||
export { NzOverflowSuffixDirective } from './overflow-suffix.directive'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/** | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE | ||
*/ | ||
|
||
export * from './public-api'; |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.