import { coerceCssPixelValue } from '@angular/cdk/coercion';
import * as i0 from '@angular/core';
import { inject, ANIMATION_MODULE_TYPE, input, booleanAttribute, Directive, NgModule, assertInInjectionContext, computed, signal, ElementRef, effect, Injectable } from '@angular/core';
import { Subject } from 'rxjs';
import { debounceTime, take } from 'rxjs/operators';
import { requestAnimationFrame } from 'ng-zorro-antd/core/polyfill';

/**
 * 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 AnimationDuration {
    static SLOW = '0.3s'; // Modal
    static BASE = '0.2s';
    static FAST = '0.1s'; // Tooltip
}
class AnimationCurves {
    static EASE_BASE_OUT = 'cubic-bezier(0.7, 0.3, 0.1, 1)';
    static EASE_BASE_IN = 'cubic-bezier(0.9, 0, 0.3, 0.7)';
    static EASE_OUT = 'cubic-bezier(0.215, 0.61, 0.355, 1)';
    static EASE_IN = 'cubic-bezier(0.55, 0.055, 0.675, 0.19)';
    static EASE_IN_OUT = 'cubic-bezier(0.645, 0.045, 0.355, 1)';
    static EASE_OUT_BACK = 'cubic-bezier(0.12, 0.4, 0.29, 1.46)';
    static EASE_IN_BACK = 'cubic-bezier(0.71, -0.46, 0.88, 0.6)';
    static EASE_IN_OUT_BACK = 'cubic-bezier(0.71, -0.46, 0.29, 1.46)';
    static EASE_OUT_CIRC = 'cubic-bezier(0.08, 0.82, 0.17, 1)';
    static EASE_IN_CIRC = 'cubic-bezier(0.6, 0.04, 0.98, 0.34)';
    static EASE_IN_OUT_CIRC = 'cubic-bezier(0.78, 0.14, 0.15, 0.86)';
    static EASE_OUT_QUINT = 'cubic-bezier(0.23, 1, 0.32, 1)';
    static EASE_IN_QUINT = 'cubic-bezier(0.755, 0.05, 0.855, 0.06)';
    static EASE_IN_OUT_QUINT = 'cubic-bezier(0.86, 0, 0.07, 1)';
}

/**
 * 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
 */
const NZ_NO_ANIMATION_CLASS = 'nz-animate-disabled';
class NzNoAnimationDirective {
    animationType = inject(ANIMATION_MODULE_TYPE, { optional: true });
    nzNoAnimation = input(false, { ...(ngDevMode ? { debugName: "nzNoAnimation" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NzNoAnimationDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.6", type: NzNoAnimationDirective, isStandalone: true, selector: "[nzNoAnimation]", inputs: { nzNoAnimation: { classPropertyName: "nzNoAnimation", publicName: "nzNoAnimation", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.nz-animate-disabled": "nzNoAnimation() || animationType === 'NoopAnimations'" } }, exportAs: ["nzNoAnimation"], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NzNoAnimationDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[nzNoAnimation]',
                    exportAs: 'nzNoAnimation',
                    host: {
                        [`[class.${NZ_NO_ANIMATION_CLASS}]`]: `nzNoAnimation() || animationType === 'NoopAnimations'`
                    }
                }]
        }], propDecorators: { nzNoAnimation: [{ type: i0.Input, args: [{ isSignal: true, alias: "nzNoAnimation", required: false }] }] } });
/**
 * @deprecated Will be removed in v23, please use {@link NzNoAnimationDirective} instead.
 */
class NzNoAnimationModule {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NzNoAnimationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.6", ngImport: i0, type: NzNoAnimationModule, imports: [NzNoAnimationDirective], exports: [NzNoAnimationDirective] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NzNoAnimationModule });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NzNoAnimationModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [NzNoAnimationDirective],
                    exports: [NzNoAnimationDirective]
                }]
        }] });
/**
 * Returns the set of dependency-injection providers to disable animations in a context.
 */
function provideNzNoAnimation() {
    return [
        {
            provide: ANIMATION_MODULE_TYPE,
            useValue: 'NoopAnimations'
        }
    ];
}
function _internalAnimationEnabled() {
    return inject(ANIMATION_MODULE_TYPE, { optional: true }) !== 'NoopAnimations';
}
/**
 * If the current animation mode is `NoopAnimations`, returns the false as a signal.
 * Otherwise, returns the result of the provided getter as a computed signal.
 * @param getter A function that returns the outer logic for whether animations are enabled.
 */
function isAnimationEnabled(getter) {
    if (typeof ngDevMode !== 'undefined' && ngDevMode) {
        assertInInjectionContext(isAnimationEnabled);
    }
    return _internalAnimationEnabled() ? computed(getter) : signal(false);
}
/**
 * If the current animation mode is `NoopAnimations`, returns the no-animation class as a signal.
 * Otherwise, returns the result of the provided class name getter as a computed signal.
 * @param classNameGetter A function that returns the class name string.
 */
function withAnimationCheck(classNameGetter) {
    if (typeof ngDevMode !== 'undefined' && ngDevMode) {
        assertInInjectionContext(withAnimationCheck);
    }
    return _internalAnimationEnabled() ? computed(classNameGetter) : signal(NZ_NO_ANIMATION_CLASS);
}

/**
 * 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
 */
const COLLAPSE_MOTION_CLASS = 'ant-motion-collapse';
class NzAnimationCollapseDirective {
    elementRef = inject(ElementRef);
    noAnimation = inject(NzNoAnimationDirective, { optional: true, host: true });
    animationEnabled = isAnimationEnabled(() => !this.noAnimation?.nzNoAnimation());
    open = input(false, /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
    leavedClassName = input('', /* @ts-ignore */
    ...(ngDevMode ? [{ debugName: "leavedClassName" }] : /* istanbul ignore next */ []));
    firstRender = true;
    constructor() {
        effect(() => {
            const open = this.open();
            // should skip the first rendering
            const animationEnabled = this.animationEnabled() && !this.firstRender;
            const element = this.elementRef.nativeElement;
            const leavedClassName = this.leavedClassName();
            if (open && leavedClassName) {
                element.classList.remove(leavedClassName);
            }
            if (animationEnabled) {
                /**
                 * | open  | animation stage | height | opacity |
                 * | ----  | --------------- | ------ | ------- |
                 * | true  | before          | 0            | 1 |
                 * | true  | active          | scrollHeight | 1 |
                 * | true  | end             | auto         | 1 |
                 * | false | before          | scrollHeight | 0 |
                 * | false | active          | 0            | 0 |
                 * | false | end             | 0            | 0 |
                 */
                element.classList.add(COLLAPSE_MOTION_CLASS);
                if (open) {
                    // Wait for next frame to get correct scrollHeight after removing hidden class
                    requestAnimationFrame(() => {
                        const scrollHeight = this.getActualScrollHeight(element);
                        element.style.height = coerceCssPixelValue(scrollHeight);
                        element.style.opacity = '1';
                    });
                }
                else {
                    // Used for setting height to actual height when transition start
                    const scrollHeight = this.getActualScrollHeight(element);
                    element.style.height = coerceCssPixelValue(scrollHeight);
                    requestAnimationFrame(() => {
                        element.style.height = coerceCssPixelValue(0);
                        element.style.opacity = '0';
                    });
                }
            }
            else {
                if (open) {
                    element.style.height = 'auto';
                    element.style.opacity = '1';
                }
                else {
                    element.style.height = coerceCssPixelValue(0);
                    element.style.opacity = '0';
                    if (leavedClassName) {
                        element.classList.add(leavedClassName);
                    }
                }
            }
            this.firstRender = false;
        });
    }
    // Calculate height by summing up direct children's offsetHeight
    // This naturally excludes collapsed nested submenus since they have height: 0
    getActualScrollHeight(element) {
        return Array.from(element.children).reduce((acc, child) => acc + child.offsetHeight, 0);
    }
    onTransitionEnd(event) {
        if (!this.animationEnabled() || event.target !== this.elementRef.nativeElement) {
            return;
        }
        // set height to auto after transition end, so that it's height can be changed along with content
        if (this.open()) {
            this.elementRef.nativeElement.style.height = 'auto';
        }
        else if (this.leavedClassName()) {
            this.elementRef.nativeElement.classList.add(this.leavedClassName());
        }
        this.elementRef.nativeElement.classList.remove(COLLAPSE_MOTION_CLASS);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NzAnimationCollapseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.6", type: NzAnimationCollapseDirective, isStandalone: true, selector: "[animation-collapse]", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, leavedClassName: { classPropertyName: "leavedClassName", publicName: "leavedClassName", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "transitionend": "onTransitionEnd($event)" } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NzAnimationCollapseDirective, decorators: [{
            type: Directive,
            args: [{
                    // eslint-disable-next-line @angular-eslint/directive-selector
                    selector: '[animation-collapse]',
                    host: {
                        '(transitionend)': 'onTransitionEnd($event)'
                    }
                }]
        }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], leavedClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "leavedClassName", required: false }] }] } });
class NzAnimationTreeCollapseService {
    firstRender = true;
    virtualScroll = false;
    animationDone$ = new Subject();
    constructor() {
        this.animationDone$.pipe(debounceTime(50), take(1)).subscribe(() => {
            this.firstRender = false;
        });
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NzAnimationTreeCollapseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NzAnimationTreeCollapseService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NzAnimationTreeCollapseService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [] });
class NzAnimationTreeCollapseDirective {
    treeCollapseService = inject(NzAnimationTreeCollapseService, { optional: true });
    noAnimation = inject(NzNoAnimationDirective, { optional: true, host: true });
    // should disable animation in virtual scrolling
    animationEnabled = isAnimationEnabled(() => !this.noAnimation?.nzNoAnimation() && !(this.treeCollapseService?.virtualScroll ?? false));
    get firstRender() {
        return this.treeCollapseService?.firstRender ?? false;
    }
    onAnimationEnter(event) {
        if (!this.animationEnabled() || this.firstRender) {
            this.treeCollapseService?.animationDone$.next();
            event.animationComplete();
            return;
        }
        const element = event.target;
        element.style.height = coerceCssPixelValue(0);
        element.style.opacity = '0';
        element.classList.add(COLLAPSE_MOTION_CLASS);
        const onTransitionEnd = (e) => {
            // Only handle height transition to avoid premature cleanup
            if (e.propertyName !== 'height') {
                return;
            }
            element.removeEventListener('transitionend', onTransitionEnd);
            element.style.height = 'auto';
            element.classList.remove(COLLAPSE_MOTION_CLASS);
            event.animationComplete();
        };
        requestAnimationFrame(() => {
            element.style.height = coerceCssPixelValue(element.scrollHeight);
            element.style.opacity = '1';
        });
        element.addEventListener('transitionend', onTransitionEnd);
    }
    onAnimationLeave(event) {
        if (!this.animationEnabled()) {
            event.animationComplete();
            return;
        }
        const element = event.target;
        element.style.height = coerceCssPixelValue(element.scrollHeight);
        element.style.opacity = '1';
        element.classList.add(COLLAPSE_MOTION_CLASS);
        const onTransitionEnd = (e) => {
            // Only handle height transition to avoid premature cleanup
            if (e.propertyName !== 'height') {
                return;
            }
            element.removeEventListener('transitionend', onTransitionEnd);
            event.animationComplete();
        };
        requestAnimationFrame(() => {
            element.style.height = coerceCssPixelValue(0);
            element.style.opacity = '0';
            element.style.marginBottom = '0';
        });
        element.addEventListener('transitionend', onTransitionEnd);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NzAnimationTreeCollapseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.6", type: NzAnimationTreeCollapseDirective, isStandalone: true, selector: "[animation-tree-collapse]", host: { listeners: { "animate.enter": "onAnimationEnter($event)", "animate.leave": "onAnimationLeave($event)" } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NzAnimationTreeCollapseDirective, decorators: [{
            type: Directive,
            args: [{
                    // eslint-disable-next-line @angular-eslint/directive-selector
                    selector: '[animation-tree-collapse]',
                    host: {
                        '(animate.enter)': 'onAnimationEnter($event)',
                        '(animate.leave)': 'onAnimationLeave($event)'
                    }
                }]
        }] });

/**
 * 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
 */
const SLIDE_UP_ANIMATION_CLASS = {
    enter: 'ant-slide-up-enter ant-slide-up-enter-active',
    leave: 'ant-slide-up-leave ant-slide-up-leave-active'
};
const SLIDE_DOWN_ANIMATION_CLASS = {
    enter: 'ant-slide-down-enter ant-slide-down-enter-active',
    leave: 'ant-slide-down-leave ant-slide-down-leave-active'
};
function slideAnimationEnter(directionFn = () => 'up') {
    return withAnimationCheck(() => {
        if (directionFn() === 'up') {
            return SLIDE_UP_ANIMATION_CLASS.enter;
        }
        else {
            return SLIDE_DOWN_ANIMATION_CLASS.enter;
        }
    });
}
function slideAnimationLeave(directionFn = () => 'up') {
    return withAnimationCheck(() => {
        if (directionFn() === 'up') {
            return SLIDE_UP_ANIMATION_CLASS.leave;
        }
        else {
            return SLIDE_DOWN_ANIMATION_CLASS.leave;
        }
    });
}

/**
 * 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 { AnimationCurves, AnimationDuration, NZ_NO_ANIMATION_CLASS, NzAnimationCollapseDirective, NzAnimationTreeCollapseDirective, NzAnimationTreeCollapseService, NzNoAnimationDirective, NzNoAnimationModule, SLIDE_DOWN_ANIMATION_CLASS, SLIDE_UP_ANIMATION_CLASS, isAnimationEnabled, provideNzNoAnimation, slideAnimationEnter, slideAnimationLeave, withAnimationCheck };
//# sourceMappingURL=ng-zorro-antd-core-animation.mjs.map
