import * as i0 from '@angular/core';
import { inject, ElementRef, ChangeDetectorRef, Directive, DestroyRef, ContentChild, ContentChildren, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Subject, ReplaySubject, BehaviorSubject, combineLatest } from 'rxjs';
import { map, distinctUntilChanged, startWith, tap, pairwise, withLatestFrom, switchMap, filter } from 'rxjs/operators';
import { NzResizeObserver } from 'ng-zorro-antd/cdk/resize-observer';

/**
 * 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
 */
class NzOverflowItemDirective {
    nzResizeObserver = inject(NzResizeObserver);
    elementRef = inject(ElementRef);
    cdr = inject(ChangeDetectorRef);
    overflowStyle = undefined;
    itemWidth$ = this.nzResizeObserver.observe(this.elementRef.nativeElement).pipe(map(([item]) => item.target.offsetWidth), distinctUntilChanged(), startWith(undefined), tap(width => {
        this.itemWidth = width;
    }));
    itemWidth = undefined;
    setItemStyle(display, order) {
        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();
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzOverflowItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.0", type: NzOverflowItemDirective, isStandalone: true, selector: "[nzOverflowItem]", host: { properties: { "style": "overflowStyle" } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzOverflowItemDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[nzOverflowItem]',
                    host: {
                        '[style]': 'overflowStyle'
                    }
                }]
        }] });

/**
 * 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
 */
class NzOverflowRestDirective {
    nzResizeObserver = inject(NzResizeObserver);
    elementRef = inject(ElementRef);
    cdr = inject(ChangeDetectorRef);
    restStyle = undefined;
    restWidth$ = this.nzResizeObserver.observe(this.elementRef.nativeElement).pipe(map(([item]) => item.target.offsetWidth), startWith(0), tap(width => (this.restWidth = width)));
    restWidth = 0;
    setRestStyle(display, order) {
        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();
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzOverflowRestDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.0", type: NzOverflowRestDirective, isStandalone: true, selector: "[nzOverflowRest]", host: { properties: { "style": "restStyle" } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzOverflowRestDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[nzOverflowRest]',
                    host: {
                        '[style]': 'restStyle'
                    }
                }]
        }] });

/**
 * 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
 */
class NzOverflowSuffixDirective {
    nzResizeObserver = inject(NzResizeObserver);
    elementRef = inject(ElementRef);
    cdr = inject(ChangeDetectorRef);
    suffixStyle = {};
    suffixWidth$ = this.nzResizeObserver.observe(this.elementRef.nativeElement).pipe(map(([item]) => item.target.offsetWidth), tap(width => (this.suffixWidth = width)));
    suffixWidth = 0;
    setSuffixStyle(start, order) {
        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();
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzOverflowSuffixDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.0", type: NzOverflowSuffixDirective, isStandalone: true, selector: "[nzOverflowSuffix]", host: { properties: { "style": "suffixStyle" } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzOverflowSuffixDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[nzOverflowSuffix]',
                    host: {
                        '[style]': 'suffixStyle'
                    }
                }]
        }] });

/**
 * 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
 */
class NzOverflowContainerComponent {
    nzResizeObserver = inject(NzResizeObserver);
    elementRef = inject(ElementRef);
    cdr = inject(ChangeDetectorRef);
    destroyRef = inject(DestroyRef);
    contentInit$ = new Subject();
    overflowItems = undefined;
    overflowSuffix = undefined;
    overflowRest = undefined;
    overflowItems$ = new ReplaySubject(1);
    containerWidth$ = this.nzResizeObserver
        .observe(this.elementRef.nativeElement)
        .pipe(map(([item]) => item.target.clientWidth || 0));
    restWidth$ = new BehaviorSubject(0);
    suffixWidth$ = new BehaviorSubject(0);
    suffixFixedStart$ = new BehaviorSubject(null);
    displayCount$ = new BehaviorSubject(Number.MAX_SAFE_INTEGER);
    restReady$ = new BehaviorSubject(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, notReady) {
        this.displayCount$.next(count);
        if (this.overflowItems && !notReady) {
            this.restReady$.next(count < this.overflowItems.length - 1);
        }
    }
    ngOnInit() {
        const overflowItemsWidth$ = this.overflowItems$.pipe(switchMap(items => combineLatest(items.map(item => item.itemWidth$))));
        this.overflowItems$.pipe(takeUntilDestroyed(this.destroyRef)).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)), takeUntilDestroyed(this.destroyRef))
            .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(takeUntilDestroyed(this.destroyRef))
            .subscribe(([suffixFixedStart, displayCount]) => {
            this.overflowSuffix?.setSuffixStyle(suffixFixedStart, displayCount);
        });
        combineLatest([this.displayCount$, this.overflowItems$])
            .pipe(takeUntilDestroyed(this.destroyRef))
            .subscribe(([displayCount, overflowItems]) => overflowItems.forEach((item, index) => item.setItemStyle(index <= displayCount, index)));
        combineLatest([this.displayRest$, this.displayCount$])
            .pipe(takeUntilDestroyed(this.destroyRef))
            .subscribe(([displayRest, displayCount]) => {
            this.overflowRest?.setRestStyle(displayRest, displayRest ? displayCount : Number.MAX_SAFE_INTEGER);
        });
    }
    ngAfterContentInit() {
        this.overflowItems?.changes.pipe(startWith(this.overflowItems)).subscribe(this.overflowItems$);
        this.overflowSuffix?.suffixWidth$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(this.suffixWidth$);
        this.overflowRest?.restWidth$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(this.restWidth$);
        this.contentInit$.next();
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzOverflowContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.0", type: NzOverflowContainerComponent, isStandalone: true, selector: "nz-overflow-container", providers: [NzResizeObserver], queries: [{ propertyName: "overflowSuffix", first: true, predicate: NzOverflowSuffixDirective, descendants: true }, { propertyName: "overflowRest", first: true, predicate: NzOverflowRestDirective, descendants: true }, { propertyName: "overflowItems", predicate: NzOverflowItemDirective }], ngImport: i0, template: `
    <ng-content></ng-content>
    <ng-content select="[appOverflowRest]"></ng-content>
    <ng-content select="[appOverflowSuffix]"></ng-content>
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzOverflowContainerComponent, decorators: [{
            type: Component,
            args: [{
                    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
                }]
        }], propDecorators: { overflowItems: [{
                type: ContentChildren,
                args: [NzOverflowItemDirective]
            }], overflowSuffix: [{
                type: ContentChild,
                args: [NzOverflowSuffixDirective]
            }], overflowRest: [{
                type: ContentChild,
                args: [NzOverflowRestDirective]
            }] } });

/**
 * 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
 */
class NzOverflowModule {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzOverflowModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.0", ngImport: i0, type: NzOverflowModule, imports: [NzOverflowContainerComponent, NzOverflowItemDirective, NzOverflowRestDirective, NzOverflowSuffixDirective], exports: [NzOverflowContainerComponent, NzOverflowItemDirective, NzOverflowRestDirective, NzOverflowSuffixDirective] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzOverflowModule });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzOverflowModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [NzOverflowContainerComponent, NzOverflowItemDirective, NzOverflowRestDirective, NzOverflowSuffixDirective],
                    exports: [NzOverflowContainerComponent, NzOverflowItemDirective, NzOverflowRestDirective, NzOverflowSuffixDirective]
                }]
        }] });

/**
 * 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
 */

/**
 * Generated bundle index. Do not edit.
 */

export { NzOverflowContainerComponent, NzOverflowItemDirective, NzOverflowModule, NzOverflowRestDirective, NzOverflowSuffixDirective };
//# sourceMappingURL=ng-zorro-antd-cdk-overflow.mjs.map
