import { NgTemplateOutlet } from '@angular/common';
import * as i0 from '@angular/core';
import { Pipe, contentChild, output, input, signal, viewChild, computed, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
import * as i1 from '@angular/forms';
import { FormsModule } from '@angular/forms';
import { ZButtonComponent } from '@shival99/z-ui/components/z-button';
import { ZCalendarComponent } from '@shival99/z-ui/components/z-calendar';
import { ZIconComponent } from '@shival99/z-ui/components/z-icon';
import { ZPopoverDirective } from '@shival99/z-ui/components/z-popover';
import { ZSwitchComponent } from '@shival99/z-ui/components/z-switch';
import { zMergeClasses } from '@shival99/z-ui/utils';
import { cva } from 'class-variance-authority';

function generateFilterId() {
    return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
}
function createFilter(field, operator = 'is', values = []) {
    return {
        id: generateFilterId(),
        field,
        operator,
        values,
    };
}
function isFieldGroup(item) {
    return 'fields' in item && Array.isArray(item.fields);
}
function isGroupLevelField(field) {
    return Boolean(field.group && field.fields);
}
function flattenFields(fields) {
    return fields.reduce((acc, item) => {
        if (isFieldGroup(item)) {
            return [...acc, ...item.fields];
        }
        if (isGroupLevelField(item) && item.fields) {
            return [...acc, ...item.fields];
        }
        return [...acc, item];
    }, []);
}
function getFieldsMap(fields) {
    const flatFields = flattenFields(fields);
    return flatFields.reduce((acc, field) => {
        if (field.key) {
            acc[field.key] = field;
        }
        return acc;
    }, {});
}
function createOperatorsFromI18n(i18n) {
    return {
        select: [
            { value: 'is', label: i18n.operators.is },
            { value: 'is_not', label: i18n.operators.isNot },
            { value: 'empty', label: i18n.operators.empty },
            { value: 'not_empty', label: i18n.operators.notEmpty },
        ],
        multiselect: [
            { value: 'is_any_of', label: i18n.operators.isAnyOf },
            { value: 'is_not_any_of', label: i18n.operators.isNotAnyOf },
            { value: 'includes_all', label: i18n.operators.includesAll },
            { value: 'excludes_all', label: i18n.operators.excludesAll },
            { value: 'empty', label: i18n.operators.empty },
            { value: 'not_empty', label: i18n.operators.notEmpty },
        ],
        date: [
            { value: 'before', label: i18n.operators.before },
            { value: 'after', label: i18n.operators.after },
            { value: 'is', label: i18n.operators.is },
            { value: 'is_not', label: i18n.operators.isNot },
            { value: 'empty', label: i18n.operators.empty },
            { value: 'not_empty', label: i18n.operators.notEmpty },
        ],
        daterange: [
            { value: 'between', label: i18n.operators.between },
            { value: 'not_between', label: i18n.operators.notBetween },
            { value: 'empty', label: i18n.operators.empty },
            { value: 'not_empty', label: i18n.operators.notEmpty },
        ],
        text: [
            { value: 'contains', label: i18n.operators.contains },
            { value: 'not_contains', label: i18n.operators.notContains },
            { value: 'starts_with', label: i18n.operators.startsWith },
            { value: 'ends_with', label: i18n.operators.endsWith },
            { value: 'is', label: i18n.operators.isExactly },
            { value: 'empty', label: i18n.operators.empty },
            { value: 'not_empty', label: i18n.operators.notEmpty },
        ],
        number: [
            { value: 'equals', label: i18n.operators.equals },
            { value: 'not_equals', label: i18n.operators.notEquals },
            { value: 'greater_than', label: i18n.operators.greaterThan },
            { value: 'less_than', label: i18n.operators.lessThan },
            { value: 'between', label: i18n.operators.between },
            { value: 'empty', label: i18n.operators.empty },
            { value: 'not_empty', label: i18n.operators.notEmpty },
        ],
        numberrange: [
            { value: 'between', label: i18n.operators.between },
            { value: 'overlaps', label: i18n.operators.overlaps },
            { value: 'contains', label: i18n.operators.contains },
            { value: 'empty', label: i18n.operators.empty },
            { value: 'not_empty', label: i18n.operators.notEmpty },
        ],
        boolean: [
            { value: 'is', label: i18n.operators.is },
            { value: 'is_not', label: i18n.operators.isNot },
            { value: 'empty', label: i18n.operators.empty },
            { value: 'not_empty', label: i18n.operators.notEmpty },
        ],
        email: [
            { value: 'contains', label: i18n.operators.contains },
            { value: 'not_contains', label: i18n.operators.notContains },
            { value: 'starts_with', label: i18n.operators.startsWith },
            { value: 'ends_with', label: i18n.operators.endsWith },
            { value: 'is', label: i18n.operators.isExactly },
            { value: 'empty', label: i18n.operators.empty },
            { value: 'not_empty', label: i18n.operators.notEmpty },
        ],
        url: [
            { value: 'contains', label: i18n.operators.contains },
            { value: 'not_contains', label: i18n.operators.notContains },
            { value: 'starts_with', label: i18n.operators.startsWith },
            { value: 'ends_with', label: i18n.operators.endsWith },
            { value: 'is', label: i18n.operators.isExactly },
            { value: 'empty', label: i18n.operators.empty },
            { value: 'not_empty', label: i18n.operators.notEmpty },
        ],
        tel: [
            { value: 'contains', label: i18n.operators.contains },
            { value: 'not_contains', label: i18n.operators.notContains },
            { value: 'starts_with', label: i18n.operators.startsWith },
            { value: 'ends_with', label: i18n.operators.endsWith },
            { value: 'is', label: i18n.operators.isExactly },
            { value: 'empty', label: i18n.operators.empty },
            { value: 'not_empty', label: i18n.operators.notEmpty },
        ],
        time: [
            { value: 'before', label: i18n.operators.before },
            { value: 'after', label: i18n.operators.after },
            { value: 'is', label: i18n.operators.is },
            { value: 'between', label: i18n.operators.between },
            { value: 'empty', label: i18n.operators.empty },
            { value: 'not_empty', label: i18n.operators.notEmpty },
        ],
        datetime: [
            { value: 'before', label: i18n.operators.before },
            { value: 'after', label: i18n.operators.after },
            { value: 'is', label: i18n.operators.is },
            { value: 'between', label: i18n.operators.between },
            { value: 'empty', label: i18n.operators.empty },
            { value: 'not_empty', label: i18n.operators.notEmpty },
        ],
    };
}
function getOperatorsForField(field, values, i18n) {
    if (field.operators) {
        return field.operators;
    }
    const operators = createOperatorsFromI18n(i18n);
    let fieldType = field.type || 'select';
    if (fieldType === 'select' && values.length > 1) {
        fieldType = 'multiselect';
    }
    if (fieldType === 'multiselect' || field.type === 'multiselect') {
        return operators['multiselect'];
    }
    return operators[fieldType] || operators['select'];
}
function formatOperator(operator) {
    return operator.replace(/_/g, ' ');
}
function getDefaultOperator(fieldType) {
    switch (fieldType) {
        case 'daterange':
        case 'numberrange':
            return 'between';
        case 'boolean':
            return 'is';
        case 'multiselect':
            return 'is_any_of';
        default:
            return 'is';
    }
}
function getDefaultValues(fieldType, field) {
    switch (fieldType) {
        case 'text':
        case 'number':
        case 'date':
        case 'email':
        case 'url':
        case 'tel':
        case 'time':
        case 'datetime':
            return [''];
        case 'daterange':
            return ['', ''];
        case 'numberrange':
            return [field.min || 0, field.max || 100];
        case 'boolean':
            return [false];
        default:
            return [];
    }
}
function getInputPattern(fieldType) {
    switch (fieldType) {
        case 'email':
            return '^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$';
        case 'url':
            return '^https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)$';
        case 'tel':
            return '^[\\+]?[1-9][\\d]{0,15}$';
        default:
            return undefined;
    }
}

class ZFilterFieldPipe {
    transform(filter, fields) {
        const fieldsMap = getFieldsMap(fields);
        return fieldsMap[filter.field];
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterFieldPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
    static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.9", ngImport: i0, type: ZFilterFieldPipe, isStandalone: true, name: "zFilterField" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterFieldPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'zFilterField',
                    standalone: true,
                    pure: true,
                }]
        }] });

class ZFilterInputPatternPipe {
    transform(field) {
        switch (field.type) {
            case 'email':
                return '[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$';
            case 'url':
                return 'https?://.+';
            case 'tel':
                return '[0-9+\\-\\s()]+';
            default:
                return field.pattern || '';
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterInputPatternPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
    static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.9", ngImport: i0, type: ZFilterInputPatternPipe, isStandalone: true, name: "zFilterInputPattern" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterInputPatternPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'zFilterInputPattern',
                    standalone: true,
                    pure: true,
                }]
        }] });

class ZFilterIsBetweenOperatorPipe {
    transform(filter) {
        return filter.operator === 'between' || filter.operator === 'not_between';
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterIsBetweenOperatorPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
    static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.9", ngImport: i0, type: ZFilterIsBetweenOperatorPipe, isStandalone: true, name: "zFilterIsBetweenOperator" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterIsBetweenOperatorPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'zFilterIsBetweenOperator',
                    standalone: true,
                    pure: true,
                }]
        }] });

class ZFilterIsValueHiddenPipe {
    transform(filter) {
        const { operator } = filter;
        return operator === 'is_empty' || operator === 'is_not_empty';
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterIsValueHiddenPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
    static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.9", ngImport: i0, type: ZFilterIsValueHiddenPipe, isStandalone: true, name: "zFilterIsValueHidden" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterIsValueHiddenPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'zFilterIsValueHidden',
                    standalone: true,
                    pure: true,
                }]
        }] });

class ZFilterOperatorLabelPipe {
    transform(filter, fields, i18n) {
        const fieldsMap = getFieldsMap(fields);
        const field = fieldsMap[filter.field];
        if (!field) {
            return '';
        }
        const operators = getOperatorsForField(field, filter.values, i18n);
        const op = operators.find(o => o.value === filter.operator);
        return op?.label || formatOperator(filter.operator);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterOperatorLabelPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
    static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.9", ngImport: i0, type: ZFilterOperatorLabelPipe, isStandalone: true, name: "zFilterOperatorLabel" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterOperatorLabelPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'zFilterOperatorLabel',
                    standalone: true,
                    pure: true,
                }]
        }] });

class ZFilterOperatorsPipe {
    transform(filter, fields, i18n) {
        const fieldsMap = getFieldsMap(fields);
        const field = fieldsMap[filter.field];
        if (!field) {
            return [];
        }
        return getOperatorsForField(field, filter.values, i18n);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterOperatorsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
    static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.9", ngImport: i0, type: ZFilterOperatorsPipe, isStandalone: true, name: "zFilterOperators" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterOperatorsPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'zFilterOperators',
                    standalone: true,
                    pure: true,
                }]
        }] });

class ZFilterSelectedOptionsPipe {
    transform(filter, fields) {
        const fieldsMap = getFieldsMap(fields);
        const field = fieldsMap[filter.field];
        if (!field?.options) {
            return [];
        }
        return field.options.filter(opt => filter.values.includes(opt.value));
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterSelectedOptionsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
    static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.9", ngImport: i0, type: ZFilterSelectedOptionsPipe, isStandalone: true, name: "zFilterSelectedOptions" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterSelectedOptionsPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'zFilterSelectedOptions',
                    standalone: true,
                    pure: true,
                }]
        }] });

class ZFilterUnselectedOptionsPipe {
    transform(filter, fields) {
        const fieldsMap = getFieldsMap(fields);
        const field = fieldsMap[filter.field];
        if (!field?.options) {
            return [];
        }
        return field.options.filter(opt => !filter.values.includes(opt.value));
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterUnselectedOptionsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
    static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.9", ngImport: i0, type: ZFilterUnselectedOptionsPipe, isStandalone: true, name: "zFilterUnselectedOptions" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterUnselectedOptionsPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'zFilterUnselectedOptions',
                    standalone: true,
                    pure: true,
                }]
        }] });

const Z_FILTER_PIPES = [
    ZFilterFieldPipe,
    ZFilterOperatorLabelPipe,
    ZFilterOperatorsPipe,
    ZFilterSelectedOptionsPipe,
    ZFilterUnselectedOptionsPipe,
    ZFilterInputPatternPipe,
    ZFilterIsValueHiddenPipe,
    ZFilterIsBetweenOperatorPipe,
];

const DEFAULT_FILTER_I18N = {
    addFilter: 'Add filter',
    searchFields: 'Search fields...',
    noFieldsFound: 'No fields found.',
    noResultsFound: 'No results found.',
    select: 'Select...',
    true: 'True',
    false: 'False',
    min: 'Min',
    max: 'Max',
    to: 'to',
    selected: 'selected',
    selectedCount: 'selected',
    addFilterTitle: 'Add filter',
    operators: {
        is: 'is',
        isNot: 'is not',
        isAnyOf: 'is any of',
        isNotAnyOf: 'is not any of',
        includesAll: 'includes all',
        excludesAll: 'excludes all',
        before: 'before',
        after: 'after',
        between: 'between',
        notBetween: 'not between',
        contains: 'contains',
        notContains: 'does not contain',
        startsWith: 'starts with',
        endsWith: 'ends with',
        isExactly: 'is exactly',
        equals: 'equals',
        notEquals: 'not equals',
        greaterThan: 'greater than',
        lessThan: 'less than',
        overlaps: 'overlaps',
        includes: 'includes',
        excludes: 'excludes',
        includesAllOf: 'includes all of',
        includesAnyOf: 'includes any of',
        empty: 'is empty',
        notEmpty: 'is not empty',
    },
    placeholders: {
        enterField: 'Enter value...',
        selectField: 'Select...',
        searchField: 'Search...',
        enterKey: 'Enter key...',
        enterValue: 'Enter value...',
    },
    validation: {
        invalidEmail: 'Invalid email format',
        invalidUrl: 'Invalid URL format',
        invalidTel: 'Invalid phone format',
        invalid: 'Invalid input format',
    },
};

const zFilterContainerVariants = cva('flex flex-wrap items-center gap-2', {
    variants: {
        size: {
            sm: 'gap-1.5',
            md: 'gap-2',
            lg: 'gap-2.5',
        },
    },
    defaultVariants: {
        size: 'md',
    },
});
const zFilterItemVariants = cva('inline-flex items-stretch rounded-sm border border-input bg-background shadow-xs overflow-hidden', {
    variants: {
        size: {
            sm: 'h-8',
            md: 'h-9',
            lg: 'h-10',
        },
    },
    defaultVariants: {
        size: 'md',
    },
});
const zFilterFieldLabelVariants = cva('flex items-center gap-1.5 bg-background font-medium text-muted-foreground border-r border-input', {
    variants: {
        size: {
            sm: 'px-2 text-xs',
            md: 'px-2.5 text-sm',
            lg: 'px-3 text-sm',
        },
    },
    defaultVariants: {
        size: 'md',
    },
});
const zFilterInputVariants = cva('flex items-center bg-background px-2 focus-within:bg-muted/50', {
    variants: {
        size: {
            sm: 'text-xs',
            md: 'text-sm',
            lg: 'text-sm',
        },
    },
    defaultVariants: {
        size: 'md',
    },
});
const zFilterRemoveButtonVariants = cva('flex items-center justify-center cursor-pointer bg-background text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive focus:outline-none border-l border-input', {
    variants: {
        size: {
            sm: 'px-1.5',
            md: 'px-2',
            lg: 'px-2.5',
        },
    },
    defaultVariants: {
        size: 'md',
    },
});
const zFilterBetweenVariants = cva('text-muted-foreground flex items-center', {
    variants: {
        size: {
            sm: 'px-1 text-xs',
            md: 'px-1.5 text-xs',
            lg: 'px-2 text-sm',
        },
    },
    defaultVariants: {
        size: 'md',
    },
});

class ZFilterComponent {
    addButtonTemplate = contentChild('addButton', ...(ngDevMode ? [{ debugName: "addButtonTemplate" }] : []));
    zFiltersChange = output();
    zFilterAdd = output();
    zFilterRemove = output();
    zFilterUpdate = output();
    class = input('', ...(ngDevMode ? [{ debugName: "class" }] : []));
    zFilters = input.required(...(ngDevMode ? [{ debugName: "zFilters" }] : []));
    zFields = input.required(...(ngDevMode ? [{ debugName: "zFields" }] : []));
    zSize = input('md', ...(ngDevMode ? [{ debugName: "zSize" }] : []));
    zI18n = input({}, ...(ngDevMode ? [{ debugName: "zI18n" }] : []));
    zShowAddButton = input(true, ...(ngDevMode ? [{ debugName: "zShowAddButton" }] : []));
    zAllowMultiple = input(true, ...(ngDevMode ? [{ debugName: "zAllowMultiple" }] : []));
    zAddButtonIcon = input('lucidePlus', ...(ngDevMode ? [{ debugName: "zAddButtonIcon" }] : []));
    zAddButtonText = input(...(ngDevMode ? [undefined, { debugName: "zAddButtonText" }] : []));
    addFilterOpen = signal(false, ...(ngDevMode ? [{ debugName: "addFilterOpen" }] : []));
    searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
    operatorPopoverOpen = signal(null, ...(ngDevMode ? [{ debugName: "operatorPopoverOpen" }] : []));
    valuePopoverOpen = signal(null, ...(ngDevMode ? [{ debugName: "valuePopoverOpen" }] : []));
    addFilterSearchInput = viewChild('addFilterSearchInput', ...(ngDevMode ? [{ debugName: "addFilterSearchInput" }] : []));
    focusSearchInput() {
        setTimeout(() => {
            this.addFilterSearchInput()?.nativeElement?.focus();
        }, 50);
    }
    focusSelectSearch(filterId) {
        setTimeout(() => {
            const input = document.getElementById(`select-search-${filterId}`);
            input?.focus();
        }, 50);
    }
    i18n = computed(() => {
        const custom = this.zI18n();
        return {
            ...DEFAULT_FILTER_I18N,
            ...custom,
            operators: { ...DEFAULT_FILTER_I18N.operators, ...custom.operators },
            placeholders: { ...DEFAULT_FILTER_I18N.placeholders, ...custom.placeholders },
            validation: { ...DEFAULT_FILTER_I18N.validation, ...custom.validation },
        };
    }, ...(ngDevMode ? [{ debugName: "i18n" }] : []));
    fieldsMap = computed(() => getFieldsMap(this.zFields()), ...(ngDevMode ? [{ debugName: "fieldsMap" }] : []));
    selectableFields = computed(() => {
        const flatFields = flattenFields(this.zFields());
        const filters = this.zFilters();
        return flatFields.filter(field => {
            if (!field.key || field.type === 'separator') {
                return false;
            }
            if (this.zAllowMultiple()) {
                return true;
            }
            return !filters.some(filter => filter.field === field.key);
        });
    }, ...(ngDevMode ? [{ debugName: "selectableFields" }] : []));
    filteredFields = computed(() => {
        const query = this.searchQuery().toLowerCase().trim();
        if (!query) {
            return this.selectableFields();
        }
        return this.selectableFields().filter(field => field.label?.toLowerCase().includes(query) || field.key?.toLowerCase().includes(query));
    }, ...(ngDevMode ? [{ debugName: "filteredFields" }] : []));
    groupedFields = computed(() => {
        const allFields = this.zFields();
        const query = this.searchQuery().toLowerCase().trim();
        const filters = this.zFilters();
        const allowMultiple = this.zAllowMultiple();
        const filterField = (field) => {
            if (!field.key || field.type === 'separator') {
                return false;
            }
            if (!allowMultiple && filters.some(f => f.field === field.key)) {
                return false;
            }
            if (query && !field.label?.toLowerCase().includes(query) && !field.key?.toLowerCase().includes(query)) {
                return false;
            }
            return true;
        };
        const groups = [];
        for (const item of allFields) {
            if ('fields' in item && Array.isArray(item.fields)) {
                const groupName = item.group || '';
                const filteredGroupFields = item.fields.filter(filterField);
                if (filteredGroupFields.length > 0) {
                    groups.push({ group: groupName, fields: filteredGroupFields });
                }
                continue;
            }
            const field = item;
            if (!filterField(field)) {
                continue;
            }
            const groupName = field.group || '';
            const existingGroup = groups.find(g => g.group === groupName);
            if (existingGroup) {
                existingGroup.fields.push(field);
                continue;
            }
            groups.push({ group: groupName, fields: [field] });
        }
        return groups;
    }, ...(ngDevMode ? [{ debugName: "groupedFields" }] : []));
    buttonSize = computed(() => {
        const size = this.zSize();
        if (size === 'sm') {
            return 'sm';
        }
        if (size === 'lg') {
            return 'lg';
        }
        return 'default';
    }, ...(ngDevMode ? [{ debugName: "buttonSize" }] : []));
    calendarSize = computed(() => {
        const size = this.zSize();
        if (size === 'sm') {
            return 'sm';
        }
        if (size === 'lg') {
            return 'lg';
        }
        return 'default';
    }, ...(ngDevMode ? [{ debugName: "calendarSize" }] : []));
    dateValueMap = computed(() => {
        const map = {};
        for (const filter of this.zFilters()) {
            map[filter.id] = this._parseDateValue(filter.values[0]);
        }
        return map;
    }, ...(ngDevMode ? [{ debugName: "dateValueMap" }] : []));
    dateRangeValueMap = computed(() => {
        const map = {};
        for (const filter of this.zFilters()) {
            const start = this._parseDateValue(filter.values[0]);
            const end = this._parseDateValue(filter.values[1]);
            map[filter.id] = start || end ? { start, end } : null;
        }
        return map;
    }, ...(ngDevMode ? [{ debugName: "dateRangeValueMap" }] : []));
    timeValueMap = computed(() => {
        const map = {};
        for (const filter of this.zFilters()) {
            map[filter.id] = this._parseTimeValue(filter.values[0]);
        }
        return map;
    }, ...(ngDevMode ? [{ debugName: "timeValueMap" }] : []));
    dateTimeValueMap = computed(() => {
        const map = {};
        for (const filter of this.zFilters()) {
            map[filter.id] = this._parseDateTimeValue(filter.values[0]);
        }
        return map;
    }, ...(ngDevMode ? [{ debugName: "dateTimeValueMap" }] : []));
    hostClasses = computed(() => zMergeClasses(zFilterContainerVariants({ size: this.zSize() }), this.class()), ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
    getItemClasses() {
        return zFilterItemVariants({ size: this.zSize() });
    }
    getLabelClasses() {
        return zFilterFieldLabelVariants({ size: this.zSize() });
    }
    getInputClasses() {
        return zFilterInputVariants({ size: this.zSize() });
    }
    getRemoveButtonClasses() {
        return zFilterRemoveButtonVariants({ size: this.zSize() });
    }
    getBetweenClasses() {
        return zFilterBetweenVariants({ size: this.zSize() });
    }
    getFieldForFilter(filter) {
        return this.fieldsMap()[filter.field];
    }
    getOperatorsForFilter(filter) {
        const field = this.getFieldForFilter(filter);
        if (!field) {
            return [];
        }
        return getOperatorsForField(field, filter.values, this.i18n());
    }
    getOperatorLabel(filter) {
        const operators = this.getOperatorsForFilter(filter);
        const op = operators.find(o => o.value === filter.operator);
        return op?.label || formatOperator(filter.operator);
    }
    getSelectedOptions(filter) {
        const field = this.getFieldForFilter(filter);
        if (!field?.options) {
            return [];
        }
        return field.options.filter(opt => filter.values.includes(opt.value));
    }
    getUnselectedOptions(filter) {
        const field = this.getFieldForFilter(filter);
        if (!field?.options) {
            return [];
        }
        return field.options.filter(opt => !filter.values.includes(opt.value));
    }
    isValueHidden(filter) {
        return filter.operator === 'empty' || filter.operator === 'not_empty';
    }
    isBetweenOperator(filter) {
        return filter.operator === 'between';
    }
    getInputPattern(field) {
        return field.pattern || getInputPattern(field.type || '');
    }
    onFieldSelect(field) {
        if (!field.key) {
            return;
        }
        const defaultOperator = field.defaultOperator || getDefaultOperator(field.type || 'select');
        const defaultValues = getDefaultValues(field.type || 'select', field);
        const newFilter = createFilter(field.key, defaultOperator, defaultValues);
        const newFilters = [...this.zFilters(), newFilter];
        this.zFiltersChange.emit(newFilters);
        this.zFilterAdd.emit(newFilter);
        this.addFilterOpen.set(false);
        this.searchQuery.set('');
    }
    updateFilterOperator(filter, operator) {
        const updates = { operator };
        if (operator === 'empty' || operator === 'not_empty') {
            updates.values = [];
        }
        const updatedFilters = this.zFilters().map(f => {
            if (f.id === filter.id) {
                return { ...f, ...updates };
            }
            return f;
        });
        this.zFiltersChange.emit(updatedFilters);
        this.zFilterUpdate.emit({ filter, updates });
        this.operatorPopoverOpen.set(null);
    }
    onSelectValueChange(filter, option) {
        const field = this.getFieldForFilter(filter);
        const isSelected = filter.values.includes(option.value);
        const valueMulti = isSelected ? filter.values.filter(v => v !== option.value) : [...filter.values, option.value];
        const valueSingle = isSelected ? [] : [option.value];
        const newValues = (field?.type === 'multiselect' ? valueMulti : valueSingle);
        const updatedFilters = this.zFilters().map(f => {
            if (f.id === filter.id) {
                return { ...f, values: newValues };
            }
            return f;
        });
        this.zFiltersChange.emit(updatedFilters);
        this.zFilterUpdate.emit({ filter, updates: { values: newValues } });
    }
    onDateValueChange(filter, value) {
        const formattedValue = this._formatDateValue(value);
        const nextValues = [formattedValue];
        this._updateFilterValues(filter, nextValues);
    }
    onDateRangeValueChange(filter, value) {
        const start = this._formatDateValue(value?.start ?? null);
        const end = this._formatDateValue(value?.end ?? null);
        const nextValues = [start, end];
        this._updateFilterValues(filter, nextValues);
    }
    onTimeValueChange(filter, value) {
        const formattedValue = this._formatTimeValue(value);
        const nextValues = [formattedValue];
        this._updateFilterValues(filter, nextValues);
    }
    onDateTimeValueChange(filter, value) {
        const formattedValue = this._formatDateTimeValue(value);
        const nextValues = [formattedValue];
        this._updateFilterValues(filter, nextValues);
    }
    removeFilter(filter) {
        const updatedFilters = this.zFilters().filter(f => f.id !== filter.id);
        this.zFiltersChange.emit(updatedFilters);
        this.zFilterRemove.emit(filter);
    }
    onInputChange(filter, event, index = 0) {
        const input = event.target;
        const newValues = [...filter.values];
        newValues[index] = input.value;
        const updatedFilters = this.zFilters().map(f => {
            if (f.id === filter.id) {
                return { ...f, values: newValues };
            }
            return f;
        });
        this.zFiltersChange.emit(updatedFilters);
        this.zFilterUpdate.emit({ filter, updates: { values: newValues } });
    }
    onBooleanChange(filter, checked) {
        const newValues = [checked];
        const updatedFilters = this.zFilters().map(f => {
            if (f.id === filter.id) {
                return { ...f, values: newValues };
            }
            return f;
        });
        this.zFiltersChange.emit(updatedFilters);
        this.zFilterUpdate.emit({ filter, updates: { values: newValues } });
    }
    onSearchInput(event) {
        const input = event.target;
        this.searchQuery.set(input.value);
    }
    trackByFilterId(index, filter) {
        return filter.id;
    }
    trackByOptionValue(index, option) {
        return option.value;
    }
    trackByFieldKey(index, field) {
        return field.key || `field-${index}`;
    }
    _updateFilterValues(filter, values) {
        const updatedFilters = this.zFilters().map(f => {
            if (f.id === filter.id) {
                return { ...f, values };
            }
            return f;
        });
        this.zFiltersChange.emit(updatedFilters);
        this.zFilterUpdate.emit({ filter, updates: { values } });
    }
    _parseDateValue(value) {
        if (typeof value !== 'string' || !value) {
            return null;
        }
        const [year, month, day] = value.split('-').map(Number);
        if (!year || !month || !day) {
            return null;
        }
        const parsedDate = new Date(year, month - 1, day);
        if (Number.isNaN(parsedDate.getTime())) {
            return null;
        }
        return parsedDate;
    }
    _formatDateValue(value) {
        if (!value) {
            return '';
        }
        const year = value.getFullYear();
        const month = String(value.getMonth() + 1).padStart(2, '0');
        const day = String(value.getDate()).padStart(2, '0');
        return `${year}-${month}-${day}`;
    }
    _parseTimeValue(value) {
        if (typeof value !== 'string' || !value) {
            return null;
        }
        const [hours, minutes] = value.split(':').map(Number);
        if (hours == null || minutes == null || Number.isNaN(hours) || Number.isNaN(minutes)) {
            return null;
        }
        const date = new Date();
        date.setHours(hours, minutes, 0, 0);
        return date;
    }
    _parseDateTimeValue(value) {
        if (typeof value !== 'string' || !value) {
            return null;
        }
        const parsed = new Date(value);
        if (Number.isNaN(parsed.getTime())) {
            return null;
        }
        return parsed;
    }
    _formatTimeValue(value) {
        if (!value) {
            return '';
        }
        const hours = String(value.getHours()).padStart(2, '0');
        const minutes = String(value.getMinutes()).padStart(2, '0');
        return `${hours}:${minutes}`;
    }
    _formatDateTimeValue(value) {
        if (!value) {
            return '';
        }
        const year = value.getFullYear();
        const month = String(value.getMonth() + 1).padStart(2, '0');
        const day = String(value.getDate()).padStart(2, '0');
        const hours = String(value.getHours()).padStart(2, '0');
        const minutes = String(value.getMinutes()).padStart(2, '0');
        return `${year}-${month}-${day}T${hours}:${minutes}`;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: ZFilterComponent, isStandalone: true, selector: "z-filter", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zFilters: { classPropertyName: "zFilters", publicName: "zFilters", isSignal: true, isRequired: true, transformFunction: null }, zFields: { classPropertyName: "zFields", publicName: "zFields", isSignal: true, isRequired: true, transformFunction: null }, zSize: { classPropertyName: "zSize", publicName: "zSize", isSignal: true, isRequired: false, transformFunction: null }, zI18n: { classPropertyName: "zI18n", publicName: "zI18n", isSignal: true, isRequired: false, transformFunction: null }, zShowAddButton: { classPropertyName: "zShowAddButton", publicName: "zShowAddButton", isSignal: true, isRequired: false, transformFunction: null }, zAllowMultiple: { classPropertyName: "zAllowMultiple", publicName: "zAllowMultiple", isSignal: true, isRequired: false, transformFunction: null }, zAddButtonIcon: { classPropertyName: "zAddButtonIcon", publicName: "zAddButtonIcon", isSignal: true, isRequired: false, transformFunction: null }, zAddButtonText: { classPropertyName: "zAddButtonText", publicName: "zAddButtonText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zFiltersChange: "zFiltersChange", zFilterAdd: "zFilterAdd", zFilterRemove: "zFilterRemove", zFilterUpdate: "zFilterUpdate" }, host: { attributes: { "data-slot": "z-filter" }, properties: { "class": "hostClasses()" } }, queries: [{ propertyName: "addButtonTemplate", first: true, predicate: ["addButton"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "addFilterSearchInput", first: true, predicate: ["addFilterSearchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Add Filter Button -->\n@if (zShowAddButton() && selectableFields().length > 0) {\n  @if (addButtonTemplate()) {\n    <ng-container [ngTemplateOutlet]=\"addButtonTemplate()!\" />\n  } @else {\n    <button\n      z-button\n      zType=\"outline\"\n      [zSize]=\"buttonSize()\"\n      z-popover\n      [zPopoverContent]=\"addFilterPopover\"\n      zTrigger=\"click\"\n      zPosition=\"bottom-left\"\n      [zOffset]=\"6\"\n      (zShow)=\"addFilterOpen.set(true); focusSearchInput()\"\n      (zHide)=\"addFilterOpen.set(false); searchQuery.set('')\">\n      <z-icon [zType]=\"zAddButtonIcon()\" zSize=\"14\" />\n      {{ zAddButtonText() || i18n().addFilter }}\n    </button>\n  }\n}\n\n<ng-template #addFilterPopover let-close=\"close\">\n  <div class=\"w-[12.5rem]\">\n    <div class=\"border-border flex items-center border-b px-3\">\n      <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n      <input\n        #addFilterSearchInput\n        type=\"text\"\n        [placeholder]=\"i18n().searchFields\"\n        [value]=\"searchQuery()\"\n        (input)=\"onSearchInput($event)\"\n        class=\"placeholder:text-muted-foreground text-foreground flex h-10 w-full bg-transparent py-3 text-sm outline-none\" />\n    </div>\n    <div class=\"flex max-h-[18.75rem] flex-col gap-0.5 overflow-y-auto p-1\">\n      @for (group of groupedFields(); track group.group; let groupIndex = $index) {\n        @if (group.group) {\n          <div\n            class=\"text-muted-foreground px-2 py-1.5 text-xs font-medium\"\n            [class.border-border]=\"groupIndex > 0\"\n            [class.mt-2]=\"groupIndex > 0\"\n            [class.border-t]=\"groupIndex > 0\"\n            [class.ml-1]=\"groupIndex > 0\">\n            {{ group.group }}\n          </div>\n        }\n        @for (field of group.fields; track trackByFieldKey($index, field)) {\n          <button\n            type=\"button\"\n            class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n            (click)=\"onFieldSelect(field); close()\">\n            @if (field.icon) {\n              <z-icon [zType]=\"field.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n            }\n            <span>{{ field.label }}</span>\n          </button>\n        }\n      } @empty {\n        <div class=\"text-muted-foreground py-6 text-center text-sm\">\n          {{ i18n().noFieldsFound }}\n        </div>\n      }\n    </div>\n  </div>\n</ng-template>\n\n<!-- Filter Items -->\n@for (filter of zFilters(); track trackByFilterId($index, filter)) {\n  @if (filter | zFilterField: $any(zFields()); as field) {\n    <div [class]=\"getItemClasses()\" data-slot=\"filter-item\">\n      <!-- Field Label -->\n      <div [class]=\"getLabelClasses()\">\n        @if (field.icon) {\n          <z-icon [zType]=\"field.icon\" zSize=\"14\" />\n        }\n        {{ field.label }}\n      </div>\n\n      <!-- Operator Dropdown -->\n      <button\n        type=\"button\"\n        z-popover\n        [zPopoverContent]=\"operatorDropdown\"\n        zTrigger=\"click\"\n        zPosition=\"bottom-left\"\n        [zOffset]=\"4\"\n        (zShow)=\"operatorPopoverOpen.set(filter.id)\"\n        (zHide)=\"operatorPopoverOpen.set(null)\"\n        class=\"text-muted-foreground hover:text-foreground hover:bg-muted flex cursor-pointer items-center px-2.5 text-sm transition-colors\"\n        [class.text-foreground]=\"operatorPopoverOpen() === filter.id\"\n        [class.bg-muted]=\"operatorPopoverOpen() === filter.id\">\n        {{ filter | zFilterOperatorLabel: $any(zFields()) : i18n() }}\n        <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"ml-1\" />\n      </button>\n\n      <ng-template #operatorDropdown let-close=\"close\">\n        <div class=\"flex w-fit min-w-32 flex-col gap-0.5 p-1\">\n          @for (op of filter | zFilterOperators: $any(zFields()) : i18n(); track op.value) {\n            <button\n              type=\"button\"\n              class=\"hover:bg-accent flex w-full cursor-pointer items-center justify-between gap-4 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none\"\n              (click)=\"updateFilterOperator(filter, op.value); close()\">\n              <span>{{ op.label }}</span>\n              @if (op.value === filter.operator) {\n                <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary\" />\n              }\n            </button>\n          }\n        </div>\n      </ng-template>\n\n      <!-- Value Selector -->\n      @if (!(filter | zFilterIsValueHidden)) {\n        <!-- Boolean Field -->\n        @if (field.type === 'boolean') {\n          <div class=\"flex items-center gap-2 px-2.5\">\n            <z-switch [zChecked]=\"filter.values[0] === true\" (zChange)=\"onBooleanChange(filter, $event)\" zSize=\"sm\" />\n            @if (field.onLabel && field.offLabel) {\n              <span class=\"text-muted-foreground text-xs\">\n                {{ filter.values[0] === true ? field.onLabel : field.offLabel }}\n              </span>\n            }\n          </div>\n        }\n\n        <!-- Text/Email/URL/Tel Input -->\n        @else if (field.type === 'text' || field.type === 'email' || field.type === 'url' || field.type === 'tel') {\n          <div [class]=\"getInputClasses()\" class=\"w-36\">\n            @if (field.prefix) {\n              <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n            }\n            <input\n              type=\"{{\n                field.type === 'email' ? 'email' : field.type === 'url' ? 'url' : field.type === 'tel' ? 'tel' : 'text'\n              }}\"\n              [value]=\"filter.values[0] || ''\"\n              [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n              [pattern]=\"field | zFilterInputPattern\"\n              class=\"w-full bg-transparent outline-none\"\n              (blur)=\"onInputChange(filter, $event)\" />\n            @if (field.suffix) {\n              <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n            }\n          </div>\n        }\n\n        <!-- Number Input -->\n        @else if (field.type === 'number') {\n          @if (filter | zFilterIsBetweenOperator) {\n            <div class=\"flex items-center\">\n              <div [class]=\"getInputClasses()\" class=\"w-20\">\n                @if (field.prefix) {\n                  <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n                }\n                <input\n                  type=\"number\"\n                  [value]=\"filter.values[0] || ''\"\n                  [placeholder]=\"i18n().min\"\n                  [min]=\"field.min\"\n                  [max]=\"field.max\"\n                  [step]=\"field.step\"\n                  class=\"w-full bg-transparent outline-none\"\n                  (blur)=\"onInputChange(filter, $event, 0)\" />\n              </div>\n              <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n              <div [class]=\"getInputClasses()\" class=\"w-20\">\n                <input\n                  type=\"number\"\n                  [value]=\"filter.values[1] || ''\"\n                  [placeholder]=\"i18n().max\"\n                  [min]=\"field.min\"\n                  [max]=\"field.max\"\n                  [step]=\"field.step\"\n                  class=\"w-full bg-transparent outline-none\"\n                  (blur)=\"onInputChange(filter, $event, 1)\" />\n                @if (field.suffix) {\n                  <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n                }\n              </div>\n            </div>\n          } @else {\n            <div [class]=\"getInputClasses()\" class=\"w-24\">\n              @if (field.prefix) {\n                <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n              }\n              <input\n                type=\"number\"\n                [value]=\"filter.values[0] || ''\"\n                [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n                [min]=\"field.min\"\n                [max]=\"field.max\"\n                [step]=\"field.step\"\n                class=\"w-full bg-transparent outline-none\"\n                (blur)=\"onInputChange(filter, $event)\" />\n              @if (field.suffix) {\n                <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n              }\n            </div>\n          }\n        }\n\n        <!-- Date Input -->\n        @else if (field.type === 'date') {\n          <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-40 min-w-0\">\n            <z-calendar\n              zMode=\"single\"\n              zAllowClear\n              zValueType=\"date\"\n              zFormat=\"YYYY-MM-DD\"\n              [zSize]=\"calendarSize()\"\n              [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n              [ngModel]=\"dateValueMap()[filter.id] ?? null\"\n              (ngModelChange)=\"onDateValueChange(filter, $event)\"\n              class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n          </div>\n        }\n\n        <!-- Date Range Input -->\n        @else if (field.type === 'daterange') {\n          <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-56 min-w-0\">\n            <z-calendar\n              zMode=\"range\"\n              zAllowClear\n              zValueType=\"date\"\n              zFormat=\"YYYY-MM-DD\"\n              [zSize]=\"calendarSize()\"\n              [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n              [ngModel]=\"dateRangeValueMap()[filter.id] ?? null\"\n              (ngModelChange)=\"onDateRangeValueChange(filter, $event)\"\n              class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n          </div>\n        }\n\n        <!-- Time Input -->\n        @else if (field.type === 'time') {\n          <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-28 min-w-0\">\n            <z-calendar\n              zMode=\"time\"\n              zAllowClear\n              zValueType=\"date\"\n              zFormat=\"HH:mm\"\n              [zSize]=\"calendarSize()\"\n              [zShowSecond]=\"false\"\n              [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n              [ngModel]=\"timeValueMap()[filter.id] ?? null\"\n              (ngModelChange)=\"onTimeValueChange(filter, $event)\"\n              class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n          </div>\n        }\n\n        <!-- DateTime Input -->\n        @else if (field.type === 'datetime') {\n          <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-52 min-w-0\">\n            <z-calendar\n              zMode=\"single\"\n              zShowTime\n              zAllowClear\n              zValueType=\"date\"\n              zFormat=\"YYYY-MM-DD HH:mm\"\n              [zSize]=\"calendarSize()\"\n              [zShowSecond]=\"false\"\n              [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n              [ngModel]=\"dateTimeValueMap()[filter.id] ?? null\"\n              (ngModelChange)=\"onDateTimeValueChange(filter, $event)\"\n              class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n          </div>\n        }\n\n        <!-- Select/Multiselect -->\n        @else if (field.type === 'select' || field.type === 'multiselect' || field.options) {\n          <button\n            type=\"button\"\n            z-popover\n            [zPopoverContent]=\"selectPopover\"\n            zTrigger=\"click\"\n            zPosition=\"bottom-left\"\n            [zOffset]=\"4\"\n            (zShow)=\"valuePopoverOpen.set(filter.id); focusSelectSearch(filter.id)\"\n            (zHide)=\"valuePopoverOpen.set(null)\"\n            class=\"hover:bg-muted flex cursor-pointer items-center gap-1.5 px-2.5 text-sm transition-colors\"\n            [class.bg-muted]=\"valuePopoverOpen() === filter.id\">\n            @if (filter | zFilterSelectedOptions: $any(zFields()); as selectedOpts) {\n              @if (selectedOpts.length > 0) {\n                <div class=\"flex items-center -space-x-1.5\">\n                  @for (opt of selectedOpts.slice(0, 3); track $any(opt).value) {\n                    @if (opt.icon) {\n                      <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n                    }\n                  }\n                </div>\n                @if (selectedOpts.length === 1) {\n                  {{ selectedOpts[0].label }}\n                } @else {\n                  {{ selectedOpts.length }} {{ i18n().selectedCount }}\n                }\n              } @else {\n                <span class=\"text-muted-foreground\">{{ i18n().select }}</span>\n              }\n            }\n            <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"text-muted-foreground ml-1\" />\n          </button>\n\n          <ng-template #selectPopover let-close=\"close\">\n            <div class=\"w-[12.5rem]\">\n              @if (field.searchable !== false) {\n                <div class=\"border-border flex items-center border-b px-3\">\n                  <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n                  <input\n                    [id]=\"'select-search-' + filter.id\"\n                    type=\"text\"\n                    [placeholder]=\"i18n().placeholders.searchField\"\n                    class=\"placeholder:text-muted-foreground text-foreground flex h-9 w-full bg-transparent py-2 text-sm outline-none\" />\n                </div>\n              }\n              <div class=\"flex max-h-[12.5rem] flex-col gap-0.5 overflow-y-auto p-1\">\n                <!-- Selected Options -->\n                @for (opt of filter | zFilterSelectedOptions: $any(zFields()); track $any(opt).value) {\n                  <button\n                    type=\"button\"\n                    class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n                    (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n                    @if (opt.icon) {\n                      <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n                    }\n                    <span class=\"truncate\">{{ opt.label }}</span>\n                    <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary ml-auto\" />\n                  </button>\n                }\n\n                <!-- Separator -->\n                @if (\n                  (filter | zFilterSelectedOptions: $any(zFields())).length > 0 &&\n                  (filter | zFilterUnselectedOptions: $any(zFields())).length > 0\n                ) {\n                  <div class=\"bg-border my-1 ml-1 h-px\"></div>\n                }\n\n                <!-- Unselected Options -->\n                @for (opt of filter | zFilterUnselectedOptions: $any(zFields()); track $any(opt).value) {\n                  <button\n                    type=\"button\"\n                    class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n                    (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n                    @if (opt.icon) {\n                      <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n                    }\n                    <span class=\"truncate\">{{ opt.label }}</span>\n                  </button>\n                }\n\n                @if (\n                  (filter | zFilterSelectedOptions: $any(zFields())).length === 0 &&\n                  (filter | zFilterUnselectedOptions: $any(zFields())).length === 0\n                ) {\n                  <div class=\"text-muted-foreground py-6 text-center text-sm\">\n                    {{ i18n().noResultsFound }}\n                  </div>\n                }\n              </div>\n            </div>\n          </ng-template>\n        }\n      }\n\n      <!-- Remove Button -->\n      <button type=\"button\" [class]=\"getRemoveButtonClasses()\" data-slot=\"filter-remove\" (click)=\"removeFilter(filter)\">\n        <z-icon zType=\"lucideX\" zSize=\"14\" />\n      </button>\n    </div>\n  }\n}\n", styles: [":host{display:block}.z-filter-calendar z-calendar{display:contents}.z-filter-calendar z-calendar .z-calendar-wrapper{display:contents}.z-filter-calendar z-calendar .z-calendar-wrapper>.relative{display:contents}.z-filter-calendar z-calendar [z-popover]{display:flex!important;align-items:center!important;height:auto!important;min-height:0!important;width:100%!important;border:0!important;box-shadow:none!important;padding:0!important;background:transparent!important;outline:none!important;gap:.375rem!important;cursor:pointer!important}.z-filter-calendar z-calendar [z-popover]:focus-within{border-color:transparent!important;box-shadow:none!important}.z-filter-calendar z-calendar [z-popover]>z-icon{flex-shrink:0}.z-filter-calendar z-calendar [z-popover]>input{flex:1 1 0!important;min-width:0!important;width:0!important}.z-filter-calendar z-calendar [z-popover]>button[tabindex=\"-1\"]{display:none!important}.z-filter-calendar z-calendar .z-calendar-wrapper>p{display:none!important}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ZSwitchComponent, selector: "z-switch", inputs: ["class", "zSwitchClass", "zThumbClass", "zSize", "zMode", "zLabel", "zText", "zCheckedText", "zUncheckedText", "zCheckedIcon", "zUncheckedIcon", "zDisabled", "zLoading", "zTextPosition", "zWave", "zChecked"], outputs: ["zChange", "zOnBlur", "zOnFocus", "zEvent", "zCheckedChange"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zAnimatedTypeIcon", "zAnimateIcon", "zAnimationTriggerIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zPopoverTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zTriggerRef", "zManualClose", "zOutsideClickClose", "zScrollClose", "zShowArrow"], outputs: ["zShow", "zHide", "zHideStart", "zControl", "zPositionChange", "zOutsideClick"], exportAs: ["zPopover"] }, { kind: "component", type: ZCalendarComponent, selector: "z-calendar", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zShowTime", "zTimeFormat", "zShowHour", "zShowMinute", "zShowSecond", "zQuickSelect", "zAllowEdit", "zShortTime", "zAllowClear", "zFormat", "zMinDate", "zMaxDate", "zValueType", "zValidators", "zShowOk", "zOkText", "zShowCancel", "zCancelText", "zDisabledDate", "zScrollClose", "zDefaultTime", "zRangeDefaultTime"], outputs: ["zControl", "zChange", "zOnBlur", "zOnFocus", "zEvent"], exportAs: ["zCalendar"] }, { kind: "pipe", type: ZFilterFieldPipe, name: "zFilterField" }, { kind: "pipe", type: ZFilterOperatorLabelPipe, name: "zFilterOperatorLabel" }, { kind: "pipe", type: ZFilterOperatorsPipe, name: "zFilterOperators" }, { kind: "pipe", type: ZFilterSelectedOptionsPipe, name: "zFilterSelectedOptions" }, { kind: "pipe", type: ZFilterUnselectedOptionsPipe, name: "zFilterUnselectedOptions" }, { kind: "pipe", type: ZFilterInputPatternPipe, name: "zFilterInputPattern" }, { kind: "pipe", type: ZFilterIsValueHiddenPipe, name: "zFilterIsValueHidden" }, { kind: "pipe", type: ZFilterIsBetweenOperatorPipe, name: "zFilterIsBetweenOperator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZFilterComponent, decorators: [{
            type: Component,
            args: [{ selector: 'z-filter', imports: [
                        FormsModule,
                        ZIconComponent,
                        NgTemplateOutlet,
                        ZSwitchComponent,
                        ZButtonComponent,
                        ZPopoverDirective,
                        ZCalendarComponent,
                        ...Z_FILTER_PIPES,
                    ], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
                        '[class]': 'hostClasses()',
                        'data-slot': 'z-filter',
                    }, template: "<!-- Add Filter Button -->\n@if (zShowAddButton() && selectableFields().length > 0) {\n  @if (addButtonTemplate()) {\n    <ng-container [ngTemplateOutlet]=\"addButtonTemplate()!\" />\n  } @else {\n    <button\n      z-button\n      zType=\"outline\"\n      [zSize]=\"buttonSize()\"\n      z-popover\n      [zPopoverContent]=\"addFilterPopover\"\n      zTrigger=\"click\"\n      zPosition=\"bottom-left\"\n      [zOffset]=\"6\"\n      (zShow)=\"addFilterOpen.set(true); focusSearchInput()\"\n      (zHide)=\"addFilterOpen.set(false); searchQuery.set('')\">\n      <z-icon [zType]=\"zAddButtonIcon()\" zSize=\"14\" />\n      {{ zAddButtonText() || i18n().addFilter }}\n    </button>\n  }\n}\n\n<ng-template #addFilterPopover let-close=\"close\">\n  <div class=\"w-[12.5rem]\">\n    <div class=\"border-border flex items-center border-b px-3\">\n      <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n      <input\n        #addFilterSearchInput\n        type=\"text\"\n        [placeholder]=\"i18n().searchFields\"\n        [value]=\"searchQuery()\"\n        (input)=\"onSearchInput($event)\"\n        class=\"placeholder:text-muted-foreground text-foreground flex h-10 w-full bg-transparent py-3 text-sm outline-none\" />\n    </div>\n    <div class=\"flex max-h-[18.75rem] flex-col gap-0.5 overflow-y-auto p-1\">\n      @for (group of groupedFields(); track group.group; let groupIndex = $index) {\n        @if (group.group) {\n          <div\n            class=\"text-muted-foreground px-2 py-1.5 text-xs font-medium\"\n            [class.border-border]=\"groupIndex > 0\"\n            [class.mt-2]=\"groupIndex > 0\"\n            [class.border-t]=\"groupIndex > 0\"\n            [class.ml-1]=\"groupIndex > 0\">\n            {{ group.group }}\n          </div>\n        }\n        @for (field of group.fields; track trackByFieldKey($index, field)) {\n          <button\n            type=\"button\"\n            class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n            (click)=\"onFieldSelect(field); close()\">\n            @if (field.icon) {\n              <z-icon [zType]=\"field.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n            }\n            <span>{{ field.label }}</span>\n          </button>\n        }\n      } @empty {\n        <div class=\"text-muted-foreground py-6 text-center text-sm\">\n          {{ i18n().noFieldsFound }}\n        </div>\n      }\n    </div>\n  </div>\n</ng-template>\n\n<!-- Filter Items -->\n@for (filter of zFilters(); track trackByFilterId($index, filter)) {\n  @if (filter | zFilterField: $any(zFields()); as field) {\n    <div [class]=\"getItemClasses()\" data-slot=\"filter-item\">\n      <!-- Field Label -->\n      <div [class]=\"getLabelClasses()\">\n        @if (field.icon) {\n          <z-icon [zType]=\"field.icon\" zSize=\"14\" />\n        }\n        {{ field.label }}\n      </div>\n\n      <!-- Operator Dropdown -->\n      <button\n        type=\"button\"\n        z-popover\n        [zPopoverContent]=\"operatorDropdown\"\n        zTrigger=\"click\"\n        zPosition=\"bottom-left\"\n        [zOffset]=\"4\"\n        (zShow)=\"operatorPopoverOpen.set(filter.id)\"\n        (zHide)=\"operatorPopoverOpen.set(null)\"\n        class=\"text-muted-foreground hover:text-foreground hover:bg-muted flex cursor-pointer items-center px-2.5 text-sm transition-colors\"\n        [class.text-foreground]=\"operatorPopoverOpen() === filter.id\"\n        [class.bg-muted]=\"operatorPopoverOpen() === filter.id\">\n        {{ filter | zFilterOperatorLabel: $any(zFields()) : i18n() }}\n        <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"ml-1\" />\n      </button>\n\n      <ng-template #operatorDropdown let-close=\"close\">\n        <div class=\"flex w-fit min-w-32 flex-col gap-0.5 p-1\">\n          @for (op of filter | zFilterOperators: $any(zFields()) : i18n(); track op.value) {\n            <button\n              type=\"button\"\n              class=\"hover:bg-accent flex w-full cursor-pointer items-center justify-between gap-4 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none\"\n              (click)=\"updateFilterOperator(filter, op.value); close()\">\n              <span>{{ op.label }}</span>\n              @if (op.value === filter.operator) {\n                <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary\" />\n              }\n            </button>\n          }\n        </div>\n      </ng-template>\n\n      <!-- Value Selector -->\n      @if (!(filter | zFilterIsValueHidden)) {\n        <!-- Boolean Field -->\n        @if (field.type === 'boolean') {\n          <div class=\"flex items-center gap-2 px-2.5\">\n            <z-switch [zChecked]=\"filter.values[0] === true\" (zChange)=\"onBooleanChange(filter, $event)\" zSize=\"sm\" />\n            @if (field.onLabel && field.offLabel) {\n              <span class=\"text-muted-foreground text-xs\">\n                {{ filter.values[0] === true ? field.onLabel : field.offLabel }}\n              </span>\n            }\n          </div>\n        }\n\n        <!-- Text/Email/URL/Tel Input -->\n        @else if (field.type === 'text' || field.type === 'email' || field.type === 'url' || field.type === 'tel') {\n          <div [class]=\"getInputClasses()\" class=\"w-36\">\n            @if (field.prefix) {\n              <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n            }\n            <input\n              type=\"{{\n                field.type === 'email' ? 'email' : field.type === 'url' ? 'url' : field.type === 'tel' ? 'tel' : 'text'\n              }}\"\n              [value]=\"filter.values[0] || ''\"\n              [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n              [pattern]=\"field | zFilterInputPattern\"\n              class=\"w-full bg-transparent outline-none\"\n              (blur)=\"onInputChange(filter, $event)\" />\n            @if (field.suffix) {\n              <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n            }\n          </div>\n        }\n\n        <!-- Number Input -->\n        @else if (field.type === 'number') {\n          @if (filter | zFilterIsBetweenOperator) {\n            <div class=\"flex items-center\">\n              <div [class]=\"getInputClasses()\" class=\"w-20\">\n                @if (field.prefix) {\n                  <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n                }\n                <input\n                  type=\"number\"\n                  [value]=\"filter.values[0] || ''\"\n                  [placeholder]=\"i18n().min\"\n                  [min]=\"field.min\"\n                  [max]=\"field.max\"\n                  [step]=\"field.step\"\n                  class=\"w-full bg-transparent outline-none\"\n                  (blur)=\"onInputChange(filter, $event, 0)\" />\n              </div>\n              <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n              <div [class]=\"getInputClasses()\" class=\"w-20\">\n                <input\n                  type=\"number\"\n                  [value]=\"filter.values[1] || ''\"\n                  [placeholder]=\"i18n().max\"\n                  [min]=\"field.min\"\n                  [max]=\"field.max\"\n                  [step]=\"field.step\"\n                  class=\"w-full bg-transparent outline-none\"\n                  (blur)=\"onInputChange(filter, $event, 1)\" />\n                @if (field.suffix) {\n                  <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n                }\n              </div>\n            </div>\n          } @else {\n            <div [class]=\"getInputClasses()\" class=\"w-24\">\n              @if (field.prefix) {\n                <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n              }\n              <input\n                type=\"number\"\n                [value]=\"filter.values[0] || ''\"\n                [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n                [min]=\"field.min\"\n                [max]=\"field.max\"\n                [step]=\"field.step\"\n                class=\"w-full bg-transparent outline-none\"\n                (blur)=\"onInputChange(filter, $event)\" />\n              @if (field.suffix) {\n                <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n              }\n            </div>\n          }\n        }\n\n        <!-- Date Input -->\n        @else if (field.type === 'date') {\n          <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-40 min-w-0\">\n            <z-calendar\n              zMode=\"single\"\n              zAllowClear\n              zValueType=\"date\"\n              zFormat=\"YYYY-MM-DD\"\n              [zSize]=\"calendarSize()\"\n              [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n              [ngModel]=\"dateValueMap()[filter.id] ?? null\"\n              (ngModelChange)=\"onDateValueChange(filter, $event)\"\n              class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n          </div>\n        }\n\n        <!-- Date Range Input -->\n        @else if (field.type === 'daterange') {\n          <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-56 min-w-0\">\n            <z-calendar\n              zMode=\"range\"\n              zAllowClear\n              zValueType=\"date\"\n              zFormat=\"YYYY-MM-DD\"\n              [zSize]=\"calendarSize()\"\n              [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n              [ngModel]=\"dateRangeValueMap()[filter.id] ?? null\"\n              (ngModelChange)=\"onDateRangeValueChange(filter, $event)\"\n              class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n          </div>\n        }\n\n        <!-- Time Input -->\n        @else if (field.type === 'time') {\n          <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-28 min-w-0\">\n            <z-calendar\n              zMode=\"time\"\n              zAllowClear\n              zValueType=\"date\"\n              zFormat=\"HH:mm\"\n              [zSize]=\"calendarSize()\"\n              [zShowSecond]=\"false\"\n              [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n              [ngModel]=\"timeValueMap()[filter.id] ?? null\"\n              (ngModelChange)=\"onTimeValueChange(filter, $event)\"\n              class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n          </div>\n        }\n\n        <!-- DateTime Input -->\n        @else if (field.type === 'datetime') {\n          <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-52 min-w-0\">\n            <z-calendar\n              zMode=\"single\"\n              zShowTime\n              zAllowClear\n              zValueType=\"date\"\n              zFormat=\"YYYY-MM-DD HH:mm\"\n              [zSize]=\"calendarSize()\"\n              [zShowSecond]=\"false\"\n              [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n              [ngModel]=\"dateTimeValueMap()[filter.id] ?? null\"\n              (ngModelChange)=\"onDateTimeValueChange(filter, $event)\"\n              class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n          </div>\n        }\n\n        <!-- Select/Multiselect -->\n        @else if (field.type === 'select' || field.type === 'multiselect' || field.options) {\n          <button\n            type=\"button\"\n            z-popover\n            [zPopoverContent]=\"selectPopover\"\n            zTrigger=\"click\"\n            zPosition=\"bottom-left\"\n            [zOffset]=\"4\"\n            (zShow)=\"valuePopoverOpen.set(filter.id); focusSelectSearch(filter.id)\"\n            (zHide)=\"valuePopoverOpen.set(null)\"\n            class=\"hover:bg-muted flex cursor-pointer items-center gap-1.5 px-2.5 text-sm transition-colors\"\n            [class.bg-muted]=\"valuePopoverOpen() === filter.id\">\n            @if (filter | zFilterSelectedOptions: $any(zFields()); as selectedOpts) {\n              @if (selectedOpts.length > 0) {\n                <div class=\"flex items-center -space-x-1.5\">\n                  @for (opt of selectedOpts.slice(0, 3); track $any(opt).value) {\n                    @if (opt.icon) {\n                      <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n                    }\n                  }\n                </div>\n                @if (selectedOpts.length === 1) {\n                  {{ selectedOpts[0].label }}\n                } @else {\n                  {{ selectedOpts.length }} {{ i18n().selectedCount }}\n                }\n              } @else {\n                <span class=\"text-muted-foreground\">{{ i18n().select }}</span>\n              }\n            }\n            <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"text-muted-foreground ml-1\" />\n          </button>\n\n          <ng-template #selectPopover let-close=\"close\">\n            <div class=\"w-[12.5rem]\">\n              @if (field.searchable !== false) {\n                <div class=\"border-border flex items-center border-b px-3\">\n                  <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n                  <input\n                    [id]=\"'select-search-' + filter.id\"\n                    type=\"text\"\n                    [placeholder]=\"i18n().placeholders.searchField\"\n                    class=\"placeholder:text-muted-foreground text-foreground flex h-9 w-full bg-transparent py-2 text-sm outline-none\" />\n                </div>\n              }\n              <div class=\"flex max-h-[12.5rem] flex-col gap-0.5 overflow-y-auto p-1\">\n                <!-- Selected Options -->\n                @for (opt of filter | zFilterSelectedOptions: $any(zFields()); track $any(opt).value) {\n                  <button\n                    type=\"button\"\n                    class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n                    (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n                    @if (opt.icon) {\n                      <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n                    }\n                    <span class=\"truncate\">{{ opt.label }}</span>\n                    <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary ml-auto\" />\n                  </button>\n                }\n\n                <!-- Separator -->\n                @if (\n                  (filter | zFilterSelectedOptions: $any(zFields())).length > 0 &&\n                  (filter | zFilterUnselectedOptions: $any(zFields())).length > 0\n                ) {\n                  <div class=\"bg-border my-1 ml-1 h-px\"></div>\n                }\n\n                <!-- Unselected Options -->\n                @for (opt of filter | zFilterUnselectedOptions: $any(zFields()); track $any(opt).value) {\n                  <button\n                    type=\"button\"\n                    class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n                    (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n                    @if (opt.icon) {\n                      <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n                    }\n                    <span class=\"truncate\">{{ opt.label }}</span>\n                  </button>\n                }\n\n                @if (\n                  (filter | zFilterSelectedOptions: $any(zFields())).length === 0 &&\n                  (filter | zFilterUnselectedOptions: $any(zFields())).length === 0\n                ) {\n                  <div class=\"text-muted-foreground py-6 text-center text-sm\">\n                    {{ i18n().noResultsFound }}\n                  </div>\n                }\n              </div>\n            </div>\n          </ng-template>\n        }\n      }\n\n      <!-- Remove Button -->\n      <button type=\"button\" [class]=\"getRemoveButtonClasses()\" data-slot=\"filter-remove\" (click)=\"removeFilter(filter)\">\n        <z-icon zType=\"lucideX\" zSize=\"14\" />\n      </button>\n    </div>\n  }\n}\n", styles: [":host{display:block}.z-filter-calendar z-calendar{display:contents}.z-filter-calendar z-calendar .z-calendar-wrapper{display:contents}.z-filter-calendar z-calendar .z-calendar-wrapper>.relative{display:contents}.z-filter-calendar z-calendar [z-popover]{display:flex!important;align-items:center!important;height:auto!important;min-height:0!important;width:100%!important;border:0!important;box-shadow:none!important;padding:0!important;background:transparent!important;outline:none!important;gap:.375rem!important;cursor:pointer!important}.z-filter-calendar z-calendar [z-popover]:focus-within{border-color:transparent!important;box-shadow:none!important}.z-filter-calendar z-calendar [z-popover]>z-icon{flex-shrink:0}.z-filter-calendar z-calendar [z-popover]>input{flex:1 1 0!important;min-width:0!important;width:0!important}.z-filter-calendar z-calendar [z-popover]>button[tabindex=\"-1\"]{display:none!important}.z-filter-calendar z-calendar .z-calendar-wrapper>p{display:none!important}\n"] }]
        }], propDecorators: { addButtonTemplate: [{ type: i0.ContentChild, args: ['addButton', { isSignal: true }] }], zFiltersChange: [{ type: i0.Output, args: ["zFiltersChange"] }], zFilterAdd: [{ type: i0.Output, args: ["zFilterAdd"] }], zFilterRemove: [{ type: i0.Output, args: ["zFilterRemove"] }], zFilterUpdate: [{ type: i0.Output, args: ["zFilterUpdate"] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], zFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "zFilters", required: true }] }], zFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "zFields", required: true }] }], zSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSize", required: false }] }], zI18n: [{ type: i0.Input, args: [{ isSignal: true, alias: "zI18n", required: false }] }], zShowAddButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowAddButton", required: false }] }], zAllowMultiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAllowMultiple", required: false }] }], zAddButtonIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAddButtonIcon", required: false }] }], zAddButtonText: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAddButtonText", required: false }] }], addFilterSearchInput: [{ type: i0.ViewChild, args: ['addFilterSearchInput', { isSignal: true }] }] } });

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

export { DEFAULT_FILTER_I18N, ZFilterComponent, ZFilterFieldPipe, ZFilterInputPatternPipe, ZFilterIsBetweenOperatorPipe, ZFilterIsValueHiddenPipe, ZFilterOperatorLabelPipe, ZFilterOperatorsPipe, ZFilterSelectedOptionsPipe, ZFilterUnselectedOptionsPipe, Z_FILTER_PIPES, createFilter, flattenFields, formatOperator, getDefaultOperator, getDefaultValues, getFieldsMap, getInputPattern, getOperatorsForField, zFilterBetweenVariants, zFilterContainerVariants, zFilterFieldLabelVariants, zFilterInputVariants, zFilterItemVariants, zFilterRemoveButtonVariants };
//# sourceMappingURL=shival99-z-ui-components-z-filter.mjs.map
